Files
UserhomeFront/src/components/Header.vue
T

880 lines
33 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<header :class="headerClass">
<img v-if="!!logoUrl" :src="baseUrl + '/image/default-logo.png'" v-real-img="logoUrl" class="logo-box" alt="" />
<ul class="operate-container fix">
<!-- <li>
<Button @click="settingsMenu">test</Button>
</li> -->
<li v-if="isWidgetIconShow" :class="{ active: isWidgetShow }">
<div class="icon-box" v-wave @click="toggleWidgetShow">
<SvgIcon name="header-4" color="#333333" />
</div>
</li>
<li v-if="isSearchIconShow">
<Transition name="fade1" :duration="{ enter: 1000, leave: 0 }">
<div v-show="!isSearching" @click="isSearching = true" class="icon-box" v-wave>
<SvgIcon name="header-1" color="#333333" />
</div>
</Transition>
<Transition name="search" :duration="{ enter: 300, leave: 300 }">
<div v-show="isSearching" class="search-box">
<input ref="refSearchInput" v-model="searchAppText" type="text" placeholder="请输入应用名称搜索" />
<SvgIcon @click="isSearching = false" class="icon" name="header-1" size="20" color="#c4c4c4" />
</div>
</Transition>
</li>
<li>
<Poptip class="fl" popper-class="message-wrap reset-panel" :width="360" trigger="click"
placement="bottom-end" v-model="isMsgShow" :transfer="true">
<div class="icon-box" v-wave>
<Badge :count="unreadCount" :offset="[2, 0]" overflow-count="99">
<SvgIcon name="header-2" color="#333333" />
</Badge>
</div>
<template #content>
<h3 class="title">查看消息</h3>
<vuescroll>
<ul class="msg-ul">
<li class="no-msg-box" v-if="userMsgList.length == 0">暂无消息</li>
<template v-else v-for="(item, index) in userMsgList">
<li class="fix">
<h4 :class="{
'text-ellipsis': true,
read: item.isRead === 1,
}">
<span class="app-name-box">{{ item.appName || msgTypeLabel(item.msgType) }}</span>
<span class="content" :title="item.content"
@click="onClickMsg(item)">
{{ item.title }}:{{ item.content }}
</span>
</h4>
<span v-if="item.msgType === 2" class="approval-box">
<a href="javascript:;" class="approval-link approve"
@click="openApproval(item, 'approve')">同意</a>
<a href="javascript:;" class="approval-link reject"
@click="openApproval(item, 'reject')">拒绝</a>
</span>
<a v-if="item.showJump" href="javascript:;" @click="onClickMsg(item)"
title="查看详情">
<SvgIcon name="arrow-right" color="#bbbbbb" />
</a>
</li>
</template>
</ul>
</vuescroll>
<div class="footer fix">
<a href="javascript:;" class="fl link-all" @click="showMsgList">查看全部</a>
<a href="javascript:;" class="fr read-all" v-if="userMsgList.length > 0"
@click="readMsgAll(1)">
全部已读
</a>
<!-- <a class="tzql_r" @click="clearMsg" href="javascript:;" title="清空消息"
><img src="image/msg-clear.png"
/></a> -->
</div>
</template>
</Poptip>
</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>
<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>
</li>
</template>
</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>
<li @click="settingsMenu" 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>
</template>
</Poptip>
</li>
</ul>
</header>
<Modal v-model="isMsgListShow" width="900" :mask="true" title="消息" class-name="msg-modal" :transfer="false">
<div class="fix mb-10">
<Button type="primary" @click="resetMsgPage" size="small" class="fl ml-10 width-10" ghost>刷新</Button>
<Button type="primary" @click="readMsgAll(2)" size="small" class="fl ml-10 width-10" ghost>全部已读</Button>
</div>
<TablePage :table-height="360" ref="refTablePage" page-type="small" :dataApi="tableApi" :pageParams="pageParams"
:columns="columns" :auto-load="false" />
<template #footer>
<Button type="primary" ghost @click="isMsgListShow = false">关闭</Button>
</template>
</Modal>
<Modal v-model="isWallpaperShow" class-name="wallpaper-modal" width="960" :mask="false" title="设置壁纸"
:transfer="false">
<vuescroll>
<div class="wallpaper-wrap">
<ul class="wallpaper-ul">
<template v-for="(item, index) in wallpaperList">
<li :class="(index + 1) % 6 == 0 ? '' : 'mr-16'" @click="onClickWallpaper(item.url)">
<div class="check-box">
<SvgIcon size="16" v-if="getIsWallpaper(item.url)" color="#45B972"
name="role-checked" />
<SvgIcon size="16" v-else name="role-check" color="#dcdee0" />
</div>
<label v-if="item.type == 0">系统</label>
<label v-if="item.type == 1">校</label>
<ContextMenu v-if="item.isEdit" @select="onWallpaperSelect" :menu="[
{
label: '删除',
id: item.id,
},
]">
<img :src="item.url" alt="" />
</ContextMenu>
<template v-else>
<img :src="item.url" alt="" />
</template>
<div class="mask-box">{{ index + 1 }}</div>
</li>
</template>
<li>
<Upload class="add-wrap tc" :on-success="wallpaperSuccess" :show-upload-list="false"
:action="$conf.serviceHost + '/api/wallpaperUpload'"
accept="image/jpeg, image/jpg, image/png" :with-credentials="true"
:headers="uploadHeaders">
<div class="add-box">
<SvgIcon name="upload-add" color="#939393" style="width: 24px; height: 24px" />
<p>点击上传图片</p>
</div>
</Upload>
</li>
</ul>
</div>
</vuescroll>
<template #footer>
<Button type="primary" ghost @click="isWallpaperShow = false">关闭</Button>
</template>
</Modal>
<Modal v-model="isLogoShow" class-name="logo-modal" width="720" :mask="false" title="设置LOGO" :transfer="false">
<vuescroll>
<div class="wallpaper-wrap">
<ul class="wallpaper-ul">
<template v-for="(item, index) in logoList">
<li :class="(index + 1) % 4 == 0 ? '' : 'mr-16'">
<label v-if="item.type == 0">系统</label>
<label v-else>校</label>
<ContextMenu v-if="item.isEdit" @select="onLogoSelect" :menu="[
{
label: '删除',
id: item.id,
},
]">
<img :src="item.url" alt="" />
</ContextMenu>
<template v-else>
<img :src="item.url" alt="" />
</template>
</li>
</template>
<li>
<Upload class="add-wrap tc" :on-success="logoSuccess" :show-upload-list="false"
:action="$conf.serviceHost + '/api/logoUpload'"
accept="image/jpeg, image/jpg, image/png, image/gif, image/webp"
:with-credentials="true" :headers="uploadHeaders">
<div class="add-box">
<SvgIcon name="upload-add" color="#939393" style="width: 24px; height: 24px" />
<p>点击上传图片</p>
</div>
</Upload>
</li>
</ul>
</div>
</vuescroll>
<template #footer>
<Button type="primary" ghost @click="isLogoShow = false">关闭</Button>
</template>
</Modal>
<!-- 卡片直批弹窗(B3 §2):同意可选意见 / 拒绝意见必填;身份服务端取会话 -->
<Modal v-model="approval.visible" width="460" :mask-closable="false"
:title="approval.action === 'approve' ? '同意办理' : '拒绝办理'">
<div class="approval-body">
<p class="approval-title text-ellipsis">{{ approval.title || "确认办理该待办?" }}</p>
<Input v-model="approval.opinion" type="textarea" :rows="3" maxlength="200" show-word-limit
:placeholder="approval.action === 'approve' ? '审批意见(可选)' : '请输入拒绝意见(必填)'" />
</div>
<template #footer>
<Button type="primary" :loading="approval.submitting" @click="submitApproval">
{{ approval.action === "approve" ? "确认同意" : "确认拒绝" }}
</Button>
<Button @click="approval.visible = false">取消</Button>
</template>
</Modal>
<MenuBarModal ref="refMenuBarModal" />
<StatsBarModal ref="refStatsBarModal" />
<TeacherCopilotModal ref="refTeacherCopilotModal" />
</template>
<script lang="ts" setup>
import useCurrentInstance from "@/utils/hook/useCurrentInstance";
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 { useRoute, useRouter } from "vue-router";
import { requireImg } from "@/utils/hook/useImg";
import ContextMenu from "@/components/ContextMenu.vue";
import MenuBarModal from "@/components/MenuBarModal.vue";
import StatsBarModal from "@/components/StatsBarModal.vue";
import TeacherCopilotModal from "@/components/TeacherCopilotModal.vue";
import BaseApi from "@/api/BaseApi";
import TablePage from "@/components/TablePage.vue";
import { Notice } from "view-ui-plus";
import { IframePageParmas, RoleInfo } from "@/types";
import { isEqual, orderBy } from "lodash";
import { PageParams } from "@/types/Basics";
import UserSettingApi from "@/api/UserSettingApi";
import mittBus from "@/utils/mitt";
import MenuBarApi from "@/api/MenuBarApi";
import Utils from "@/utils";
const route = useRoute();
const router = useRouter();
const store = useDefaultStore();
const refTablePage: any = ref(null);
const { $conf } = useCurrentInstance();
const baseUrl = computed(() => $conf.fileHost);
const refSearchInput = ref<any>();
const refMenuBarModal = ref<any>();
const refStatsBarModal = ref<any>();
const refTeacherCopilotModal = ref<any>();
const uploadHeaders = { yschapirequest: 1, yschreferer: Utils.strToHexCharCode(window.location.href) };
const logoUrl = computed(() => {
const schLogo = logoList.value.find(x => x.type == 1);
if (schLogo) return schLogo.url;
const sysLogo = logoList.value.find(x => x.type == 0);
return sysLogo ? sysLogo.url : "";
});
const isMsgShow = ref(false),
isMsgListShow = ref(false),
isUserInfoShow = ref(false),
isRoleInfoShow = ref(false),
isWallpaperShow = ref(false),
isLogoShow = ref(false),
isSearching = ref(false),
searchAppText = ref<string | null>(null),
wallpaperList = ref<any[]>([]),
logoList = ref<any[]>([]),
userMsgList = ref<any[]>([]),
/** 未读消息数(msgCenter/summary 拉取 + WS newMessage 实时累加) */
unreadCount = ref(0);
// ===== 消息中心 WS 实时推送(UserMsg /ws/msg,一次性票据握手;断线 5s 重连换新票) =====
let msgWs: WebSocket | null = null;
let msgWsPingTimer: any = null;
let msgWsReconnectTimer: any = null;
let msgWsClosed = false;
async function loadSummary() {
try {
const summary = await BaseApi.getMsgCenterSummary();
unreadCount.value = (summary && summary.unreadCount) || 0;
} catch (e) {
/* 摘要失败不打扰页面 */
}
}
async function connectMsgWs() {
if (msgWsClosed) return;
let wsUrl: string | null = null;
try {
const res: any = await BaseApi.getMsgCenterWsTicket();
wsUrl = res && res.url;
} catch (e) {
/* 未登录/不可达:走兜底重连 */
}
// 票据不可得(UserMsg 重启中/未配置)也要保持重连节奏:服务恢复后自动续上
if (!wsUrl) {
if (!msgWsClosed) {
clearTimeout(msgWsReconnectTimer);
msgWsReconnectTimer = setTimeout(connectMsgWs, 5000);
}
return;
}
const ws = new WebSocket(wsUrl);
msgWs = ws;
ws.onopen = () => {
// 25s 心跳保活(服务端 90s 空闲回收)
msgWsPingTimer = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) ws.send('{"type":"ping"}');
}, 25000);
};
ws.onmessage = ev => {
try {
const frame = JSON.parse(ev.data);
if (frame.type === "newMessage") onNewMessage(frame);
} catch (e) {
/* 非 JSON 帧忽略 */
}
};
ws.onclose = () => {
clearInterval(msgWsPingTimer);
msgWsPingTimer = null;
if (msgWs === ws) msgWs = null;
// 票据一次性:重连必换新票;退避上限 30s 防服务端长时间不可用时空转
if (!msgWsClosed) {
clearTimeout(msgWsReconnectTimer);
msgWsReconnectTimer = setTimeout(connectMsgWs, 5000);
}
};
}
function onNewMessage(frame: any) {
unreadCount.value += 1;
reloadMsg();
if (isMsgListShow.value) resetMsgPage();
Notice.info({
title: frame.title || "新消息",
desc: frame.content || "",
duration: 5,
});
}
function closeMsgWs() {
msgWsClosed = true;
clearTimeout(msgWsReconnectTimer);
msgWsReconnectTimer = null;
clearInterval(msgWsPingTimer);
msgWsPingTimer = null;
if (msgWs) {
try {
msgWs.close();
} catch (e) {
/* 已断开 */
}
msgWs = null;
}
}
const headerClass = computed(() => {
return { "default-header": true, "base-mask": route.name !== "index" };
});
const isWidgetIconShow = computed(() => {
return route.name === "index";
});
const isSearchIconShow = computed(() => {
return route.name === "apps";
});
const isWidgetShow = computed(() => {
return store.getWidgetDragObj.isWidgetShow;
});
const userRole = computed(() => store.userRoleList);
const toggleSearch: any = inject("toggleSearch");
const pageParams: PageParams = reactive({ page: 1, count: 10 });
const tableApi = (params: PageParams) => BaseApi.getMsgCenterList(params);
const columns = ref<any[]>([
{
type: "index",
title: "序号",
width: 70,
align: "center",
},
{
title: "应用",
width: 110,
align: "center",
render(h: any, params: any) {
return h("span", params.row.appName || msgTypeLabel(params.row.msgType));
},
},
{
title: "消息内容",
render(h: any, params: any) {
const row = params.row;
return h("span", { attrs: { title: row.content } }, `${row.title || ""}:${row.content || ""}`);
},
},
{
title: "状态",
width: 100,
render(h: any, params: any) {
return h("span", params.row.isRead === 1 ? "已读" : "未读");
},
},
{
title: "日期",
align: "center",
width: 200,
key: "sendTime",
},
{
title: "操作",
width: 210,
align: "center",
render(h: any, params: any) {
const row = params.row;
const nodes: any[] = [];
// 审批待办(msgType=2)直批入口:taskId 由服务端按 bizId 匹配定位;
// 无权限/已处理由后端返回文案,直批按钮不受跳转权限影响
if (row.msgType === 2 && row.msgId) {
nodes.push(
h(
"a",
{
attrs: { href: "javascript:;" },
on: {
click: () => openApproval(row, "approve"),
},
},
"同意"
),
h("span", " "),
h(
"a",
{
attrs: { href: "javascript:;" },
on: {
click: () => openApproval(row, "reject"),
},
},
"拒绝"
)
);
}
if (row.showJump) {
if (nodes.length) nodes.push(h("span", " "));
nodes.push(
h(
"a",
{
attrs: { href: "javascript:;" },
on: {
click: () => {
if (row.isRead !== 1 && row.msgId) {
BaseApi.readMsgCenter(row.msgId);
row.isRead = 1;
unreadCount.value = Math.max(0, unreadCount.value - 1);
}
window.open(row.jumpUrl, "_blank");
},
},
},
"去处理"
)
);
}
if (!nodes.length) return h("span", "—");
return h("span", nodes);
},
},
]);
onMounted(async () => {
setTimeout(() => {
reloadMsg();
loadSummary();
connectMsgWs();
// isWallpaperShow.value = true;
}, 200);
loadLogoList();
mittBus.on("searchReset", () => {
isSearching.value = false;
searchAppText.value = null;
});
});
onUnmounted(() => {
mittBus.off("searchReset");
closeMsgWs();
});
watch(isSearching, val => {
if (val) {
setTimeout(() => refSearchInput.value?.focus(), 300);
} else {
// searchAppText.value = null;
}
});
watch(searchAppText, val => {
mittBus.emit("searchChange", val);
});
function getIsCheckRoles(item: RoleInfo) {
return isEqual(item, store.curRoleInfo);
}
async function changeRole(role: RoleInfo) {
if (!!getIsCheckRoles(role)) return;
setTimeout(() => {
isRoleInfoShow.value = false;
}, 150);
store.setCurRoleInfo(role);
await BaseApi.savUserRole(role);
mittBus.emit("switchRole", role);
await getUserWallpaperList();
await loadLogoList();
}
function onUserinfoClickRoles() {
isUserInfoShow.value = false;
setTimeout(() => {
isRoleInfoShow.value = true;
}, 0);
}
async function readMsgAll(type: 1 | 2) {
await BaseApi.readMsgCenterAll();
await reloadMsg();
unreadCount.value = 0;
if (type == 2) resetMsgPage();
}
async function reloadMsg() {
const result: any = await BaseApi.getMsgCenterList({ page: 1, count: 10 });
userMsgList.value = result.list || [];
}
/** 消息类型名(UserMsg msgType:0系统通知/1业务提醒/2审批待办) */
function msgTypeLabel(msgType: number) {
return { 0: "系统通知", 1: "业务提醒", 2: "审批待办" }[msgType as 0 | 1 | 2] || "系统通知";
}
/** 点击消息:未读先标读;配了 jumpUrl(如 flow.task 待办)新窗口打开落地页 */
async function onClickMsg(item: any) {
if (item.isRead !== 1 && item.msgId) {
await BaseApi.readMsgCenter(item.msgId);
item.isRead = 1;
unreadCount.value = Math.max(0, unreadCount.value - 1);
}
if (item.jumpUrl) window.open(item.jumpUrl, "_blank");
}
// ===== 卡片直批(B3 §2):同意/拒绝待办;operatorId/schId/operatorName 服务端取会话 =====
const approval = reactive({
visible: false,
msgId: 0,
action: "approve" as "approve" | "reject",
title: "",
opinion: "",
submitting: false,
});
function openApproval(item: any, action: "approve" | "reject") {
approval.msgId = item.msgId;
approval.action = action;
approval.title = item.title ? String(item.title) : "";
approval.opinion = "";
approval.visible = true;
}
async function submitApproval() {
if (approval.submitting) return;
if (approval.action === "reject" && !approval.opinion.trim()) {
Notice.warning({ title: "拒绝必须填写意见", duration: 3 });
return;
}
approval.submitting = true;
try {
const res: any = await BaseApi.handleMsg(approval.msgId, approval.action, approval.opinion.trim());
if (res && res.ok) {
Notice.success({ title: "办理成功", duration: 3 });
approval.visible = false;
markRowRead(approval.msgId);
} else {
Notice.warning({ title: (res && res.message) || "办理失败", duration: 5 });
}
// 成功/失效/被他人处理等场景都同步刷新,让卡片状态跟上服务端
reloadMsg();
} catch (e) {
// flow-center 不可达等:降级为提示,不阻塞消息卡片其余功能
Notice.error({ title: "流程中心暂不可用,请稍后重试", duration: 5 });
} finally {
approval.submitting = false;
}
}
function markRowRead(msgId: number) {
const row = userMsgList.value.find((m: any) => m.msgId === msgId);
if (row && row.isRead !== 1) {
row.isRead = 1;
unreadCount.value = Math.max(0, unreadCount.value - 1);
}
}
function resetMsgPage() {
refTablePage.value.reloadData();
}
function showMsgList() {
isMsgShow.value = false;
isMsgListShow.value = true;
refTablePage.value.reloadData();
}
async function wallpaperSuccess(response: any, file: any, fileListt: any) {
await getUserWallpaperList();
}
async function getUserWallpaperList() {
const list = await UserSettingApi.getUserWallpaperList(store.getCurSchId);
// list.forEach(element => {
// if (element.type == 1) element.url = $conf.serviceHost + element.url;
// });
wallpaperList.value = orderBy(list, ["type", "id"], ["asc", "asc"]);
}
async function settingsWallpaper() {
await getUserWallpaperList();
isUserInfoShow.value = false;
isWallpaperShow.value = true;
}
async function settingsMenu() {
isUserInfoShow.value = false;
refMenuBarModal.value.show();
}
async function settingsStats() {
isUserInfoShow.value = false;
refStatsBarModal.value.show();
}
async function settingsTeacherCopilot() {
isUserInfoShow.value = false;
refTeacherCopilotModal.value.show();
}
async function onClickWallpaper(url: string) {
await UserSettingApi.checkWallpaper(store.getCurSchId, url);
const userSetting = store.curUserSettingInfo;
if (!!userSetting) {
userSetting.wallpaperUrl = url;
store.setCurUserSettingsInfo(userSetting);
}
isWallpaperShow.value = false;
}
async function onWallpaperSelect(item: any) {
await UserSettingApi.deleteWallById(item.id);
await getUserWallpaperList();
}
async function loadLogoList() {
const list = await UserSettingApi.getLogoList();
logoList.value = list || [];
}
async function logoSuccess(response: any, file: any, fileListt: any) {
await loadLogoList();
}
async function onLogoSelect(item: any) {
await UserSettingApi.deleteLogoById(item.id);
await loadLogoList();
}
function getIsWallpaper(url: string) {
return url === store.getCurWallPaperUrl;
}
async function toggleWidgetShow() {
const id = store.curUserSettingInfo?.id;
if (!!store.curUserSettingInfo) store.curUserSettingInfo.isWidgetShow = !store.getWidgetDragObj.isWidgetShow;
await UserSettingApi.toggleWidgetShow(id);
}
function linkSysSetting() {
isUserInfoShow.value = false;
router.push("/syssetting");
}
function linkBackendManage() {
isUserInfoShow.value = false;
const url = `${$conf.baseHost}/userbase/front/index.html`;
window.open(url, "_blank");
}
async function linkLogoSetting() {
await loadLogoList();
isUserInfoShow.value = false;
isLogoShow.value = true;
}
function showSeachBox() { }
function showUserInfo() {
isUserInfoShow.value = false;
mittBus.emit("showUserInfoModal");
}
function logout() {
let url = window.location.href;
url = "/logout?service=" + url;
url = $conf.ssoHost + url;
if (!!window.top) window.top.location.href = url;
else window.location.href = url;
}
</script>
<style lang="scss" scoped>
@import url("@/assets/styles/header.scss");
::v-deep .ivu-table td {
height: 32px;
}
/* 卡片直批(B3):待办消息行内「同意/拒绝」入口 */
.approval-box {
margin-right: 6px;
white-space: nowrap;
}
.approval-link {
margin-left: 8px;
font-size: 12px;
color: #577afb;
}
.approval-link.reject {
color: #ed4014;
}
.approval-body {
padding: 4px 2px;
}
.approval-title {
margin-bottom: 10px;
color: #515a6e;
font-weight: 600;
}
</style>
<style lang="scss">
.reset-panel .ivu-poptip-body {
padding: 0;
}
.reset-panel .ivu-poptip-inner {
border-radius: 10px;
overflow: hidden;
box-shadow: 0 10px 20px 0 rgba(0, 0, 0, 0.06);
}
.wallpaper-modal {
z-index: 11 !important;
}
.wallpaper-modal .ivu-modal-body {
padding: 0;
}
.logo-modal {
z-index: 11 !important;
}
.logo-modal .ivu-modal-body {
padding: 0;
}
.ivu-table-cell .operating-link {
display: inline-block;
color: #2d8cf0;
cursor: pointer;
padding-right: 10px;
&.disabled {
color: #aaa !important;
cursor: not-allowed;
}
}
.ivu-table:before {
content: none !important;
}
</style>