|
@@ -36,49 +36,7 @@
|
|
|
>{{ button.name }}</el-button
|
|
>{{ button.name }}</el-button
|
|
|
>
|
|
>
|
|
|
<!-- 用户名显示 -->
|
|
<!-- 用户名显示 -->
|
|
|
- <el-dropdown>
|
|
|
|
|
- <div class="user-name-box">
|
|
|
|
|
- {{ userName }}
|
|
|
|
|
- </div>
|
|
|
|
|
- <template #dropdown>
|
|
|
|
|
- <el-dropdown-menu class="dropdown-menu user-popover-content">
|
|
|
|
|
- <!-- 退出登录按钮 -->
|
|
|
|
|
- <div class="user-logout-btn" @click="LogoutClick()">
|
|
|
|
|
- 退出登录
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 用户信息 -->
|
|
|
|
|
- <div class="top-box">
|
|
|
|
|
- <div class="top-inner-box">
|
|
|
|
|
- <p>已激活课程</p>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="bottom-inner-box">
|
|
|
|
|
- <div v-for="(course, index) in courses" :key="index" class="course-item">
|
|
|
|
|
- <div class="check-circle">✓</div>
|
|
|
|
|
- <span>{{ course.name }}</span>
|
|
|
|
|
- <span>{{ course.expireDate }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 激活码 -->
|
|
|
|
|
- <div class="bottom-box">
|
|
|
|
|
- <el-input
|
|
|
|
|
- v-model="activationCode"
|
|
|
|
|
- placeholder="请输入课程激活码"
|
|
|
|
|
- class="activation-input"
|
|
|
|
|
- size="small"
|
|
|
|
|
- />
|
|
|
|
|
- <el-button
|
|
|
|
|
- type="primary"
|
|
|
|
|
- size="small"
|
|
|
|
|
- class="activation-btn"
|
|
|
|
|
- @click="handleActivation"
|
|
|
|
|
- >
|
|
|
|
|
- 激活
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-dropdown-menu>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-dropdown>
|
|
|
|
|
|
|
+ <UserInfoPopover />
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -123,6 +81,8 @@ import { useRouter } from 'vue-router'
|
|
|
import { ClassList } from '@/api/class.js'
|
|
import { ClassList } from '@/api/class.js'
|
|
|
import {ArrowDown} from '@element-plus/icons-vue'
|
|
import {ArrowDown} from '@element-plus/icons-vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
import { ElMessage } from 'element-plus'
|
|
|
|
|
+import UserInfoPopover from '@/components/user/UserInfoPopover.vue'
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// 导入图片
|
|
// 导入图片
|
|
|
import intelligenceImg from '@/assets/images/intelligence.png'
|
|
import intelligenceImg from '@/assets/images/intelligence.png'
|
|
@@ -136,34 +96,18 @@ import logoutIcon from '@/assets/icon/logout.png'
|
|
|
import {logoutLogic, removeLocalStorageKey} from '@/utils/loginUtils.js'
|
|
import {logoutLogic, removeLocalStorageKey} from '@/utils/loginUtils.js'
|
|
|
import {aiCourseRoutes, blocklyRoutes, homeRoutes} from "@/router/index.js";
|
|
import {aiCourseRoutes, blocklyRoutes, homeRoutes} from "@/router/index.js";
|
|
|
|
|
|
|
|
-// 激活码响应式变量
|
|
|
|
|
-const activationCode = ref('')
|
|
|
|
|
|
|
|
|
|
-// 课程列表响应式变量
|
|
|
|
|
-const courses = ref([
|
|
|
|
|
- { name: 'AI编程课', expireDate: '2026.02.21到期' },
|
|
|
|
|
- { name: 'AI实验课', expireDate: '2026.05.12到期' }
|
|
|
|
|
-])
|
|
|
|
|
|
|
|
|
|
// 平台标题响应式变量
|
|
// 平台标题响应式变量
|
|
|
const platformTitle = ref(import.meta.env.VITE_APP_TITLE)
|
|
const platformTitle = ref(import.meta.env.VITE_APP_TITLE)
|
|
|
-// 用户名响应式变量
|
|
|
|
|
-const userName = ref(import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME)
|
|
|
|
|
// 更新平台标题
|
|
// 更新平台标题
|
|
|
const updatePlatformTitle = () => {
|
|
const updatePlatformTitle = () => {
|
|
|
platformTitle.value = localStorage.getItem('tenantName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_TENANT
|
|
platformTitle.value = localStorage.getItem('tenantName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_TENANT
|
|
|
}
|
|
}
|
|
|
-// 更新用户名
|
|
|
|
|
-const updateUserName = () => {
|
|
|
|
|
- userName.value = localStorage.getItem('userName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
// 获取当前路由对象
|
|
// 获取当前路由对象
|
|
|
const router = useRouter()
|
|
const router = useRouter()
|
|
|
-// 退出登录
|
|
|
|
|
-const LogoutClick = async () => {
|
|
|
|
|
- await logoutLogic(router, homeRoutes.login)
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// 处理按钮点击事件
|
|
// 处理按钮点击事件
|
|
|
const handleButtonClick = (button) => {
|
|
const handleButtonClick = (button) => {
|
|
@@ -260,31 +204,17 @@ const handleGradeSelect = (command) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 处理激活按钮点击
|
|
|
|
|
-const handleActivation = () => {
|
|
|
|
|
- if (!activationCode.value) {
|
|
|
|
|
- ElMessage.warning('请输入激活码')
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- // 这里可以添加激活码验证逻辑
|
|
|
|
|
- ElMessage.success('激活码:' + activationCode.value + ' 提交成功')
|
|
|
|
|
- activationCode.value = ''
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
fetchCtTypes()
|
|
fetchCtTypes()
|
|
|
// 初始化平台标题
|
|
// 初始化平台标题
|
|
|
updatePlatformTitle()
|
|
updatePlatformTitle()
|
|
|
- // 初始化用户名
|
|
|
|
|
- updateUserName()
|
|
|
|
|
// storage事件监听器,监听其他标签页对localStorage的修改
|
|
// storage事件监听器,监听其他标签页对localStorage的修改
|
|
|
window.addEventListener('storage', (e) => {
|
|
window.addEventListener('storage', (e) => {
|
|
|
if (e.key === 'tenantName') {
|
|
if (e.key === 'tenantName') {
|
|
|
updatePlatformTitle()
|
|
updatePlatformTitle()
|
|
|
}
|
|
}
|
|
|
- if (e.key === 'userName') {
|
|
|
|
|
- updateUserName()
|
|
|
|
|
- }
|
|
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
//删除所有以token开头的键值对
|
|
//删除所有以token开头的键值对
|
|
@@ -307,21 +237,7 @@ window.updateTenantName = (newName) => {
|
|
|
@return math.div($px, 750) * 100vw;
|
|
@return math.div($px, 750) * 100vw;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 用户名显示
|
|
|
|
|
-.user-name-box {
|
|
|
|
|
- width: auto;
|
|
|
|
|
- height: rpx(15);
|
|
|
|
|
- margin: rpx(10) rpx(-10) 0 0;
|
|
|
|
|
- color: white;
|
|
|
|
|
- font-size: rpx(8);
|
|
|
|
|
- display: flex;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- background-color: rgba(255, 255, 255, 0.2);
|
|
|
|
|
- border-radius: rpx(15);
|
|
|
|
|
- padding: rpx(0) rpx(10);
|
|
|
|
|
- min-width: rpx(20);
|
|
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
.home-container {
|
|
.home-container {
|
|
|
position: fixed;
|
|
position: fixed;
|
|
|
top: 0;
|
|
top: 0;
|
|
@@ -533,147 +449,7 @@ window.updateTenantName = (newName) => {
|
|
|
box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
|
|
box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 用户信息弹框样式
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
-.user-popover-content {
|
|
|
|
|
- width: auto;
|
|
|
|
|
- min-width: rpx(100);
|
|
|
|
|
- max-width: rpx(200);
|
|
|
|
|
- border-radius: rpx(5);
|
|
|
|
|
- background-color: white;
|
|
|
|
|
- backdrop-filter: blur(rpx(5));
|
|
|
|
|
- box-shadow: 0 rpx(2) rpx(4) rgba(202, 52, 52, 0.1);
|
|
|
|
|
- padding-bottom: rpx(0);
|
|
|
|
|
- position: relative;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.user-logout-btn {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- padding: rpx(2) rpx(6);
|
|
|
|
|
- background: linear-gradient(
|
|
|
|
|
- to bottom,
|
|
|
|
|
- #fee78a,
|
|
|
|
|
- #ffce1b
|
|
|
|
|
- );
|
|
|
|
|
- border-bottom-left-radius: rpx(5);
|
|
|
|
|
- border-top-right-radius: rpx(5);
|
|
|
|
|
- color: black;
|
|
|
|
|
- font-size: rpx(6);
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
-}
|
|
|
|
|
-.user-popover-content p {
|
|
|
|
|
- font-size: rpx(8);
|
|
|
|
|
- color: black;
|
|
|
|
|
- margin: rpx(5) 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.user-popover-content p:first-child {
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.top-box {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
-}
|
|
|
|
|
-.top-inner-box{
|
|
|
|
|
- padding-top: rpx(5);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.top-inner-box,
|
|
|
|
|
-.bottom-inner-box {
|
|
|
|
|
- padding-left: rpx(6);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.top-inner-box p{
|
|
|
|
|
- font-size: rpx(8);
|
|
|
|
|
- margin: rpx(2) 0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.top-inner-box p:first-child {
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.bottom-inner-box {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.course-item {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: row;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- gap: rpx(4);
|
|
|
|
|
- padding: rpx(2);
|
|
|
|
|
- border-radius: rpx(3);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.course-item span {
|
|
|
|
|
- font-size: rpx(7);
|
|
|
|
|
- color: #525050;
|
|
|
|
|
- white-space: nowrap;
|
|
|
|
|
-}
|
|
|
|
|
-.course-item span:nth-child(3) {
|
|
|
|
|
- font-size: rpx(6);
|
|
|
|
|
- color: #a6a4a4;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.check-circle {
|
|
|
|
|
- width: rpx(7);
|
|
|
|
|
- height: rpx(7);
|
|
|
|
|
- border-radius: 50%;
|
|
|
|
|
- background: linear-gradient(
|
|
|
|
|
- to bottom,
|
|
|
|
|
- #fee78a,
|
|
|
|
|
- #ffce1b
|
|
|
|
|
- );
|
|
|
|
|
- color: white;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- font-size: rpx(5);
|
|
|
|
|
- font-weight: bold;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.bottom-box {
|
|
|
|
|
- border-bottom-right-radius: rpx(5);
|
|
|
|
|
- border-bottom-left-radius: rpx(5);
|
|
|
|
|
- background-color: rgba(240, 240, 240, 0.9);
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- gap: rpx(10);
|
|
|
|
|
- padding: rpx(8);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.activation-input {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.activation-input :deep(.el-input__wrapper) {
|
|
|
|
|
- border-radius: rpx(3);
|
|
|
|
|
- width: rpx(60);
|
|
|
|
|
- height: rpx(15);
|
|
|
|
|
- font-size: rpx(7);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.activation-btn {
|
|
|
|
|
- width: rpx(40);
|
|
|
|
|
- height: rpx(15);
|
|
|
|
|
- font-size: rpx(7);
|
|
|
|
|
- border: none;
|
|
|
|
|
- color: black;
|
|
|
|
|
- border-radius: rpx(10);
|
|
|
|
|
- background: linear-gradient(
|
|
|
|
|
- to bottom,
|
|
|
|
|
- #fee78a,
|
|
|
|
|
- #ffce1b
|
|
|
|
|
- );
|
|
|
|
|
-}
|
|
|
|
|
</style>
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|