铃铛与齿轮两枚图标下线,人像图标成为唯一入口,点击展开一张卡片: 切换身份列表(9条实测溢出滚动)+ 个人信息 + 后台管理(仅管理员)+ 退出登录。 删除无功能损失的冗余入口:原齿轮菜单的 sys/logo/sidebar/statset/backend 五项 已于 2026-09-30 迁入 /settings(Settings.vue:620 ALL_PANES),齿轮成为纯冗余。 消息中心仍走左侧菜单 /msg,LeftMenu 未读角标不受影响。 改动要点: - isUserInfoShow + isRoleInfoShow 合并为 isUserCardShow,9 处函数体同步改名; 删除 onUserinfoClickRoles、storeToRefs import 与 unreadCount 解构(模板已无 Badge) - showUserInfo 改跳 /settings?pane=profile,不再 emit showUserInfoModal (该事件仍有 AppHeader/BschIframe/harness-main 三处消费方,不可删) - :key 用 roleId-schId-childId 复合键,避免同校多身份时 roleId 重复 - header.scss 删 .roleinfo-wrap 与随之失效的 @use "sass:color",新增 .user-card (身份列表 max-height:310px + overflow-y:scroll + 6px 自绘滚动条) - settingsWallpaper 等 6 个入口函数保留:对应 Modal 仍挂模板尾部且 logoList 是 header 徽标数据源,只改内部变量名并加注释 验证:未声明标识符全量扫 47 个 .vue 零问题;vite build 通过;mock 取证实测 scrollHeight 683 > clientHeight 310 出滚动条、1 条时 75=75 不滚动、 menu-rows 管理员 2/普通用户 1、bell-count 与 gear-count 均为 0。 另:.gitignore 忽略卡片取证三件套(本地临时用,与 harness-* 同类不进 git)。
This commit is contained in:
+70
-120
@@ -20,110 +20,64 @@
|
||||
</div>
|
||||
</Transition>
|
||||
</li>
|
||||
<!-- 铃铛直跳 /msg(消息对接 2026-09-30:移除 Poptip 浮层与 900 宽列表 Modal,
|
||||
未读数上提 store 与 /msg 页左栏同源;审批直批弹窗抽至 MsgApprovalModal) -->
|
||||
<!-- 人像图标 =唯一入口(2026-10-08整合):铃铛与齿轮两枚图标下线,
|
||||
消息中心仍走左侧菜单 /msg(LeftMenu 保留未读角标);
|
||||
原齿轮菜单的 个人信息/后台管理/退出登陆 合并进本卡片,
|
||||
其余 sys/logo/sidebar/statset 五项 2026-09-30 已迁/settings,不再重复入口 -->
|
||||
<li>
|
||||
<div class="icon-box" v-wave title="消息中心" @click="router.push('/msg')">
|
||||
<Badge :count="unreadCount" :offset="[2, 0]" overflow-count="99">
|
||||
<SvgIcon name="header-2" color="#333333" />
|
||||
</Badge>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<Poptip class="fl" popper-class="roleinfo-wrap reset-panel" :width="240" trigger="click"
|
||||
placement="bottom-end" v-model="isRoleInfoShow" :transfer="true">
|
||||
<div class="icon-box" v-wave>
|
||||
<Poptip class="fl" popper-class="user-card-wrap reset-panel" :width="260" trigger="click"
|
||||
placement="bottom-end" v-model="isUserCardShow" :transfer="true">
|
||||
<div class="icon-box" v-wave title="切换身份">
|
||||
<SvgIcon name="header-3" color="#333333" />
|
||||
</div>
|
||||
<template #content>
|
||||
<h3 class="title">
|
||||
<SvgIcon name="switch-role" color="#272829" />
|
||||
<span class="ml-8">切换身份</span>
|
||||
</h3>
|
||||
<vuescroll>
|
||||
<ul class="roles-ul">
|
||||
<template v-for="(item, index) in userRole">
|
||||
<li :class="{ acitve: getIsCheckRoles(item) }" @click="changeRole(item)">
|
||||
<SvgIcon v-if="getIsCheckRoles(item)" color="#45B972" name="role-checked" />
|
||||
<SvgIcon v-else name="role-check" color="#dcdee0" />
|
||||
<div class="user-wrap">
|
||||
<div class="user-box fix">
|
||||
<span v-if="item.roleId != 3" class="fl f16 mr-10">
|
||||
{{ store.userInfo.name }}
|
||||
</span>
|
||||
<span v-else class="fl f16 mr-10">
|
||||
{{ item.childName }}
|
||||
</span>
|
||||
<span v-if="!!item.roleName" class="role-info">
|
||||
{{ item.roleName }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="schname-box">
|
||||
{{ item.schName }}
|
||||
</div>
|
||||
<div class="user-card">
|
||||
<div class="user-card-hd">
|
||||
<SvgIcon name="switch-role" color="#272829" />
|
||||
<span class="ttl">切换身份</span>
|
||||
<span class="close" @click="isUserCardShow = false">✕</span>
|
||||
</div>
|
||||
<!-- 身份列表有最大高度,超出显示滚动条。
|
||||
key 用 roleId+schId+childId 复合:同校多身份时 roleId 会重复 -->
|
||||
<div class="user-card-roles">
|
||||
<div v-for="item in userRole"
|
||||
:key="`${item.roleId}-${item.schId}-${item.childId}`"
|
||||
:class="['u-role', { active: getIsCheckRoles(item) }]" @click="changeRole(item)">
|
||||
<SvgIcon v-if="getIsCheckRoles(item)" color="#45B972" name="role-checked" />
|
||||
<SvgIcon v-else name="role-check" color="#dcdee0" />
|
||||
<div class="who">
|
||||
<div class="nm">
|
||||
<span class="t">{{ item.roleId != 3 ? store.userInfo.name : item.childName }}</span>
|
||||
<span v-if="!!item.roleName" class="role-info">{{ item.roleName }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
<div class="sch">{{ item.schName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="userinfo-ul user-card-menu">
|
||||
<li @click="showUserInfo">
|
||||
<img :src="requireImg('userinfo/icon1.png')" alt="" />
|
||||
<span>个人信息</span>
|
||||
<svg class="arw" viewBox="0 0 16 16" fill="none">
|
||||
<path
|
||||
d="M6 3.5L10.5 8L6 12.5" stroke="#b6bbc3" stroke-width="1.5"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</li>
|
||||
<li v-if="!!store.getIsAdmin" @click="linkBackendManage">
|
||||
<SvgIcon name="admin-backend" size="20" color="#323233" class="backend-manage-icon" />
|
||||
<span>后台管理</span>
|
||||
<svg class="arw" viewBox="0 0 16 16" fill="none">
|
||||
<path
|
||||
d="M6 3.5L10.5 8L6 12.5" stroke="#b6bbc3" stroke-width="1.5"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</li>
|
||||
</ul>
|
||||
</vuescroll>
|
||||
</template>
|
||||
</Poptip>
|
||||
</li>
|
||||
<li>
|
||||
<Poptip class="fl" popper-class="reset-panel" :width="220" trigger="click" placement="bottom-end"
|
||||
v-model="isUserInfoShow" :transfer="true">
|
||||
<div class="icon-box" v-wave>
|
||||
<SvgIcon name="header-5" color="#333333" />
|
||||
</div>
|
||||
<template #content>
|
||||
<ul class="userinfo-ul">
|
||||
<!-- <li class="header border" @click="onUserinfoClickRoles">
|
||||
<span class="name">{{ store.userInfo?.name }}</span>
|
||||
<span v-if="!!store.curRoleInfo?.roleName" class="role-info mr-10">
|
||||
{{ store.curRoleInfo?.roleName }}
|
||||
</span>
|
||||
<Icon :size="18" color="#333" type="ios-arrow-forward" />
|
||||
</li> -->
|
||||
<li class="border" @click="showUserInfo">
|
||||
<img :src="requireImg('userinfo/icon1.png')" alt="" />
|
||||
<span>个人信息</span>
|
||||
</li>
|
||||
<li v-if="!!store.getIsAdmin" @click="linkSysSetting">
|
||||
<img :src="requireImg('userinfo/icon5.png')" alt="" />
|
||||
<span>系统设置</span>
|
||||
</li>
|
||||
<li v-if="!!store.getIsAdmin" @click="linkBackendManage">
|
||||
<SvgIcon name="admin-backend" size="20" color="#323233" class="backend-manage-icon" />
|
||||
<span>后台管理</span>
|
||||
</li>
|
||||
<li v-if="!!store.getIsAdmin" @click="linkLogoSetting">
|
||||
<img :src="requireImg('userinfo/icon3.png')" alt="" />
|
||||
<span>设置LOGO</span>
|
||||
</li>
|
||||
<!-- 边栏设置已迁设置中心(/settings?pane=sidebar,2026-09-30 二轮迁入真实管理),
|
||||
此处仅跳转不再开旧 MenuBarModal(组件保留未挂载) -->
|
||||
<li @click="linkSidebarSetting" v-if="!!store.getIsAdmin">
|
||||
<img :src="requireImg('userinfo/icon6.png')" alt="" />
|
||||
<span>边栏设置</span>
|
||||
</li>
|
||||
<li @click="settingsStats" v-if="!!store.getIsAdmin">
|
||||
<img :src="requireImg('userinfo/icon7.png')" alt="" />
|
||||
<span>统计设置</span>
|
||||
</li>
|
||||
<!--<li @click="settingsTeacherCopilot" v-if="!!store.getIsAdmin">
|
||||
<img :src="requireImg('userinfo/icon8.png')" alt="" />
|
||||
<span>教师助手设置</span>
|
||||
</li>-->
|
||||
|
||||
<li @click="settingsWallpaper" class="border">
|
||||
<img :src="requireImg('userinfo/icon2.png')" alt="" />
|
||||
<span>设置壁纸</span>
|
||||
</li>
|
||||
<li @click="logout">
|
||||
<img :src="requireImg('userinfo/icon4.png')" alt="" />
|
||||
<span>退出登陆</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="user-card-logout">
|
||||
<button class="logout-btn" @click="logout">退出登录</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Poptip>
|
||||
</li>
|
||||
@@ -234,7 +188,6 @@ import SvgIcon from "@/components/SvgIcon.vue";
|
||||
import vuescroll from "vuescroll";
|
||||
import { ref, reactive, computed, onMounted, onUnmounted, inject, watch } from "vue";
|
||||
import { useDefaultStore } from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { requireImg } from "@/utils/hook/useImg";
|
||||
import ContextMenu from "@/components/ContextMenu.vue";
|
||||
@@ -257,8 +210,8 @@ const refMsgApproval = ref<any>();
|
||||
const { $conf } = useCurrentInstance();
|
||||
const baseUrl = computed(() => $conf.fileHost);
|
||||
|
||||
/** 未读消息数上提 pinia store(消息对接 2026-09-30):Header 角标与 /msg 页左栏、LeftMenu 同源 */
|
||||
const { unreadCount } = storeToRefs(store);
|
||||
/** 未读消息数上提 pinia store(消息对接 2026-09-30):Header 铃铛角标已于 2026-10-08 下线,
|
||||
* 但摘要拉取与 WS 推送仍需保留 —— /msg 页左栏与 LeftMenu 角标与本store 同源 */
|
||||
|
||||
const refSearchInput = ref<any>();
|
||||
const refStatsBarModal = ref<any>();
|
||||
@@ -272,8 +225,7 @@ const logoUrl = computed(() => {
|
||||
const sysLogo = logoList.value.find(x => x.type == 0);
|
||||
return sysLogo ? sysLogo.url : "";
|
||||
});
|
||||
const isUserInfoShow = ref(false),
|
||||
isRoleInfoShow = ref(false),
|
||||
const isUserCardShow = ref(false),
|
||||
isWallpaperShow = ref(false),
|
||||
isLogoShow = ref(false),
|
||||
isSearching = ref(false),
|
||||
@@ -431,7 +383,7 @@ function getIsCheckRoles(item: RoleInfo) {
|
||||
async function changeRole(role: RoleInfo) {
|
||||
if (!!getIsCheckRoles(role)) return;
|
||||
setTimeout(() => {
|
||||
isRoleInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
}, 150);
|
||||
store.setCurRoleInfo(role);
|
||||
await BaseApi.savUserRole(role);
|
||||
@@ -440,13 +392,6 @@ async function changeRole(role: RoleInfo) {
|
||||
await loadLogoList();
|
||||
}
|
||||
|
||||
function onUserinfoClickRoles() {
|
||||
isUserInfoShow.value = false;
|
||||
setTimeout(() => {
|
||||
isRoleInfoShow.value = true;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/** 消息类型名(UserMsg msgType:0系统通知/1业务提醒/2审批待办);WS 帧缺 appName 时的降级标签 */
|
||||
function msgTypeLabel(msgType: number | null) {
|
||||
return { 0: "系统通知", 1: "业务提醒", 2: "审批待办" }[msgType as 0 | 1 | 2] || "系统通知";
|
||||
@@ -463,25 +408,28 @@ async function getUserWallpaperList() {
|
||||
// });
|
||||
wallpaperList.value = orderBy(list, ["type", "id"], ["asc", "asc"]);
|
||||
}
|
||||
/** 以下入口函数自2026-10-08 齿轮菜单下线后已无 UI 调用方,但对应 Modal 组件仍挂在模板尾部、
|
||||
* 且 logoList 是header 徽标的数据源,故保留函数体不删,仅把已并轨的 isUserInfoShow 换成 isUserCardShow。
|
||||
* 恢复入口时直接绑到卡片菜单即可。 */
|
||||
async function settingsWallpaper() {
|
||||
await getUserWallpaperList();
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
isWallpaperShow.value = true;
|
||||
}
|
||||
|
||||
/** 边栏设置入口改跳设置中心 pane(原 settingsMenu 开旧 MenuBarModal 的能力已于 2026-09-30 迁入 Settings.vue sidebar pane) */
|
||||
function linkSidebarSetting() {
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
router.push("/settings?pane=sidebar");
|
||||
}
|
||||
|
||||
async function settingsStats() {
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
refStatsBarModal.value.show();
|
||||
}
|
||||
|
||||
async function settingsTeacherCopilot() {
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
refTeacherCopilotModal.value.show();
|
||||
}
|
||||
|
||||
@@ -523,27 +471,29 @@ async function toggleWidgetShow() {
|
||||
}
|
||||
|
||||
function linkSysSetting() {
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
router.push("/syssetting");
|
||||
}
|
||||
|
||||
function linkBackendManage() {
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
const url = `${$conf.baseHost}/userbase/front/index.html`;
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
|
||||
async function linkLogoSetting() {
|
||||
await loadLogoList();
|
||||
isUserInfoShow.value = false;
|
||||
isUserCardShow.value = false;
|
||||
isLogoShow.value = true;
|
||||
}
|
||||
|
||||
function showSeachBox() { }
|
||||
|
||||
/** 卡片菜单:个人信息 → 设置中心 profile pane(与通知端/用户中心同一地址)。
|
||||
* 注意:mittBus 的 showUserInfoModal 事件仍由 AppHeader/BschIframe 使用,此处不再触发 */
|
||||
function showUserInfo() {
|
||||
isUserInfoShow.value = false;
|
||||
mittBus.emit("showUserInfoModal");
|
||||
isUserCardShow.value = false;
|
||||
router.push("/settings?pane=profile");
|
||||
}
|
||||
|
||||
function logout() {
|
||||
|
||||
Reference in New Issue
Block a user