603 lines
23 KiB
Vue
603 lines
23 KiB
Vue
<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>
|
|
<SvgIcon name="header-2" color="#333333" />
|
|
</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.read,
|
|
}">
|
|
<span class="app-name-box">{{ item.name }}</span>
|
|
<span class="content" :title="item.msg"
|
|
@click="linkMessage(item.id, item.appPath, item.read)">
|
|
{{ item.msg }}
|
|
</span>
|
|
</h4>
|
|
<a href="javascript:;" @click="linkMessage(item.id, item.appPath, item.read)"
|
|
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="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>
|
|
|
|
<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 { 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[]>([]);
|
|
|
|
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.getMessagePageList(params);
|
|
const columns = ref<any[]>([
|
|
{
|
|
type: "index",
|
|
title: "序号",
|
|
width: 70,
|
|
align: "center",
|
|
},
|
|
{
|
|
title: "应用",
|
|
width: 150,
|
|
tooltip: true,
|
|
align: "center",
|
|
key: "name",
|
|
},
|
|
{
|
|
title: "消息内容",
|
|
tooltip: true,
|
|
key: "msg",
|
|
},
|
|
{
|
|
title: "状态",
|
|
width: 100,
|
|
render(h: any, params: any) {
|
|
return h("span", params.row.read ? "已读" : "未读");
|
|
},
|
|
},
|
|
{
|
|
title: "日期",
|
|
align: "center",
|
|
width: 200,
|
|
key: "date",
|
|
},
|
|
]);
|
|
onMounted(async () => {
|
|
setTimeout(() => {
|
|
reloadMsg();
|
|
// isWallpaperShow.value = true;
|
|
}, 200);
|
|
loadLogoList();
|
|
mittBus.on("searchReset", () => {
|
|
isSearching.value = false;
|
|
searchAppText.value = null;
|
|
});
|
|
});
|
|
onUnmounted(() => {
|
|
mittBus.off("searchReset");
|
|
});
|
|
watch(isSearching, val => {
|
|
if (val) {
|
|
setTimeout(() => refSearchInput.value?.focus(), 300);
|
|
} else {
|
|
// searchAppText.value = null;
|
|
}
|
|
});
|
|
|
|
watch(searchAppText, val => {
|
|
mittBus.emit("searchChange", val);
|
|
});
|
|
function linkMessage(msgId: number, path: string, isread: boolean) {
|
|
if (!isread) BaseApi.readMessage(msgId);
|
|
var index = userMsgList.value.findIndex(x => x.id == msgId);
|
|
if (index !== -1) userMsgList.value[index].read = true;
|
|
window.open(path);
|
|
}
|
|
|
|
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.readMessageAll();
|
|
await reloadMsg();
|
|
if (type == 2) resetMsgPage();
|
|
}
|
|
|
|
async function reloadMsg() {
|
|
const result = await BaseApi.getMessageList();
|
|
userMsgList.value = result.list;
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
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 = "/cas/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;
|
|
}
|
|
</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>
|