功能修订
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# 启动:npm run dev:mock
|
# 启动:npm run dev:mock
|
||||||
VITE_BASE_HOST=
|
VITE_BASE_HOST=
|
||||||
VITE_SSO_HOST=
|
VITE_SSO_HOST=
|
||||||
VITE_SERVICE_HOST=http://localhost:8070
|
VITE_SERVICE_HOST=http://localhost:8101
|
||||||
VITE_ZIYUANKU_HOST=
|
VITE_ZIYUANKU_HOST=
|
||||||
VITE_ZHUANXIANG_HOST=
|
VITE_ZHUANXIANG_HOST=
|
||||||
VITE_IS_MOCK=true
|
VITE_IS_MOCK=true
|
||||||
|
|||||||
+7
-1
@@ -62,7 +62,7 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("加载用户信息失败", error);
|
console.error("加载用户信息失败", error);
|
||||||
if (error !== "redirect") {
|
if (error?.message !== "redirect") {
|
||||||
Message.error("载入用户信息失败,请检查后端服务是否正常!");
|
Message.error("载入用户信息失败,请检查后端服务是否正常!");
|
||||||
}
|
}
|
||||||
// 降级:使用默认值("/" 即已收到页,无需跳转)
|
// 降级:使用默认值("/" 即已收到页,无需跳转)
|
||||||
@@ -101,4 +101,10 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
/* 表格操作列(operatingHandle 渲染的 Tooltip 包裹层)横排且随单元格居中 */
|
||||||
|
.ivu-table-cell > .ivu-tooltip {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -214,11 +214,6 @@ class SettingApi {
|
|||||||
sortDeptDic(ids: string) {
|
sortDeptDic(ids: string) {
|
||||||
return postForm<void>(`${DICT}/Sort`, { ids });
|
return postForm<void>(`${DICT}/Sort`, { ids });
|
||||||
}
|
}
|
||||||
/** 同步基础平台部门 */
|
|
||||||
getDeptSync() {
|
|
||||||
return get<void>(`${DICT}/Sync`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== 自定义组管理 ==========
|
// ========== 自定义组管理 ==========
|
||||||
/** 获取联系组列表 */
|
/** 获取联系组列表 */
|
||||||
getGroup(page: number, count: number) {
|
getGroup(page: number, count: number) {
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="notice-upload">
|
<div class="notice-upload">
|
||||||
<!-- 自定义上传附件(自旧前端 oldfront/src/components/uploadFile.vue 适配) -->
|
<!-- 自定义上传附件(自旧前端 oldfront/src/components/uploadFile.vue 适配) -->
|
||||||
<Upload
|
<div class="upload-row">
|
||||||
:on-success="encloSuccess"
|
<Upload
|
||||||
:on-remove="encloRemove"
|
:on-success="encloSuccess"
|
||||||
:default-file-list="defaultList"
|
:on-remove="encloRemove"
|
||||||
:action="uploadFileUrl"
|
:default-file-list="defaultList"
|
||||||
:accept="fileType"
|
:action="uploadFileUrl"
|
||||||
:multiple="isMultiple"
|
:accept="fileType"
|
||||||
:before-upload="handleUpload"
|
:multiple="isMultiple"
|
||||||
:format="formatArr"
|
:before-upload="handleUpload"
|
||||||
:max-size="maxSize"
|
:format="formatArr"
|
||||||
:on-format-error="handleFormatError"
|
:max-size="maxSize"
|
||||||
:on-exceeded-size="handleExceeded"
|
:on-format-error="handleFormatError"
|
||||||
>
|
:on-exceeded-size="handleExceeded"
|
||||||
<Button><Icon type="ios-cloud-upload-outline"></Icon>选择文件</Button>
|
>
|
||||||
</Upload>
|
<Button><Icon type="ios-cloud-upload-outline"></Icon>选择文件</Button>
|
||||||
<span class="upload-tip">提示:附件大小不超过{{ maxFileSize }}</span>
|
</Upload>
|
||||||
|
<span class="upload-tip">提示:附件大小不超过{{ maxFileSize }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -87,12 +89,23 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.notice-upload {
|
.notice-upload {
|
||||||
display: flex;
|
display: block;
|
||||||
align-items: center;
|
.upload-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
:deep(.ivu-upload) {
|
:deep(.ivu-upload) {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
/* 文件列表整体另起一行,每项独占一行,不再与按钮挤在一起 */
|
||||||
|
:deep(.ivu-upload-list) {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
:deep(.ivu-upload-list-file) {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
.upload-tip {
|
.upload-tip {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
color: #f90;
|
color: #f90;
|
||||||
|
|||||||
+15
-6
@@ -6,7 +6,8 @@ import type { RouteRecordRaw } from "vue-router";
|
|||||||
* - /list/new?serid= (编辑)
|
* - /list/new?serid= (编辑)
|
||||||
* - /list/new?fid= (转发)
|
* - /list/new?fid= (转发)
|
||||||
* - /list/new?tempid=(模板引用)
|
* - /list/new?tempid=(模板引用)
|
||||||
* - /details?serid=&type= type: 0=编辑视角(不标读) 1=普通查看(标读)
|
* - /list/detail?serid=&type=、/noticelist/detail?serid=&type=
|
||||||
|
* type: 0=编辑视角(不标读) 1=普通查看(标读)
|
||||||
*
|
*
|
||||||
* modId 是菜单 ↔ 路由的稳定契约(对照后端 GetUserMod 现行数据):
|
* modId 是菜单 ↔ 路由的稳定契约(对照后端 GetUserMod 现行数据):
|
||||||
* 1=已收到 2=已发送 3=全部通知 4=通知统计 21=应用设置
|
* 1=已收到 2=已发送 3=全部通知 4=通知统计 21=应用设置
|
||||||
@@ -43,12 +44,19 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import("@/views/notice/NoticeList.vue"),
|
component: () => import("@/views/notice/NoticeList.vue"),
|
||||||
meta: { title: "全部通知", modId: 3 },
|
meta: { title: "全部通知", modId: 3 },
|
||||||
},
|
},
|
||||||
// 通知详情(已发/已收共用,type 区分是否标读)
|
// 通知详情(同一组件挂两个路由,面包屑/菜单高亮由 meta.parentId 确定父节点:
|
||||||
|
// 已发送下 /list/detail,全部通知下 /noticelist/detail;type 区分是否标读)
|
||||||
{
|
{
|
||||||
path: "/details",
|
path: "/list/detail",
|
||||||
name: "notice_details",
|
name: "notice_list_detail",
|
||||||
component: () => import("@/views/notice/NoticeDetails.vue"),
|
component: () => import("@/views/notice/NoticeDetails.vue"),
|
||||||
meta: { title: "通知详情", modId: 5 },
|
meta: { title: "通知详情", modId: 23, parentId: 2 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/noticelist/detail",
|
||||||
|
name: "notice_manage_detail",
|
||||||
|
component: () => import("@/views/notice/NoticeDetails.vue"),
|
||||||
|
meta: { title: "通知详情", modId: 24, parentId: 3 },
|
||||||
},
|
},
|
||||||
// 通知统计(旧版行为:整页跳转外部统计系统)
|
// 通知统计(旧版行为:整页跳转外部统计系统)
|
||||||
{
|
{
|
||||||
@@ -67,6 +75,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
|
|
||||||
/* ---- 旧版路径兼容重定向(书签、残留的平台模块配置) ---- */
|
/* ---- 旧版路径兼容重定向(书签、残留的平台模块配置) ---- */
|
||||||
{ path: "/accept", redirect: "/" },
|
{ path: "/accept", redirect: "/" },
|
||||||
|
{ path: "/details", redirect: "/list/detail" },
|
||||||
{ path: "/newnotice", redirect: "/list/new" },
|
{ path: "/newnotice", redirect: "/list/new" },
|
||||||
{ path: "/edit", redirect: "/list/new" },
|
{ path: "/edit", redirect: "/list/new" },
|
||||||
{ path: "/manage", redirect: "/noticelist" },
|
{ path: "/manage", redirect: "/noticelist" },
|
||||||
@@ -76,7 +85,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{ path: "/notice/notice_accept", redirect: "/accept" },
|
{ path: "/notice/notice_accept", redirect: "/accept" },
|
||||||
{ path: "/notice/notice_list", redirect: "/list" },
|
{ path: "/notice/notice_list", redirect: "/list" },
|
||||||
{ path: "/notice/manage", redirect: "/noticelist" },
|
{ path: "/notice/manage", redirect: "/noticelist" },
|
||||||
{ path: "/notice/notice_details", redirect: "/details" },
|
{ path: "/notice/notice_details", redirect: "/list/detail" },
|
||||||
{ path: "/notice/statistics", redirect: "/stats" },
|
{ path: "/notice/statistics", redirect: "/stats" },
|
||||||
{ path: "/notice/setting", redirect: "/setting" },
|
{ path: "/notice/setting", redirect: "/setting" },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -58,9 +58,11 @@ function errorHandle<T>(res: BschResponse<T>, status: number): T {
|
|||||||
case 302:
|
case 302:
|
||||||
console.log(res);
|
console.log(res);
|
||||||
// 后端 CasSsoApiRedirectFilter 已在 service 中拼好 ;redirectToReferer=<hex>,
|
// 后端 CasSsoApiRedirectFilter 已在 service 中拼好 ;redirectToReferer=<hex>,
|
||||||
// 直接跳转即可;登录后由 CasSsoRefererRedirectFilter 解码 302 回前端页
|
// 直接跳转即可;登录后由 CasSsoRefererRedirectFilter 解码 302 回前端页。
|
||||||
|
// 跳转后返回永不 resolve 的挂起 Promise:调用方 await 悬停,
|
||||||
|
// 全局 onBizError 与各页面的 catch 均不再触发(不弹 redirect 报错)
|
||||||
window.location.href = res.urlToRedirectTo!;
|
window.location.href = res.urlToRedirectTo!;
|
||||||
throw new Error("redirect");
|
return new Promise(() => {}) as T;
|
||||||
case 4:
|
case 4:
|
||||||
throw new Error(res.msg || "参数错误!");
|
throw new Error(res.msg || "参数错误!");
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ async function doAdd(_type?: string) {
|
|||||||
Message.info("请选择大于当前的时间!");
|
Message.info("请选择大于当前的时间!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data.timingSendTime = dateFormat(new Date(timeForm.date1), "yyyy/MM/dd HH:mm:ss");
|
data.timingSendTime = dateFormat(new Date(timeForm.date1), "yyyy-MM-dd HH:mm:ss");
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ const viewType = computed(() => {
|
|||||||
const t = Number(route.query.type);
|
const t = Number(route.query.type);
|
||||||
return t === 0 ? 0 : 1;
|
return t === 0 ? 0 : 1;
|
||||||
});
|
});
|
||||||
const fromPath = computed(() => (route.query.from as string) || "/accept");
|
|
||||||
/* 上一/下一篇的序列类型:管理视角走已发(type=0),查看走已收(type=1) */
|
/* 上一/下一篇的序列类型:管理视角走已发(type=0),查看走已收(type=1) */
|
||||||
const navType = computed(() => (viewType.value === 0 ? "0" : "1"));
|
const navType = computed(() => (viewType.value === 0 ? "0" : "1"));
|
||||||
|
|
||||||
@@ -140,16 +139,12 @@ function openPreview(item: { name?: string; filename?: string; fileid?: number;
|
|||||||
fileName: displayName(item),
|
fileName: displayName(item),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function back() {
|
|
||||||
router.push(fromPath.value);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="page-wrapper">
|
<div class="page-wrapper">
|
||||||
<div class="main-container" v-if="detail">
|
<div class="main-container" v-if="detail">
|
||||||
<div class="ops-top">
|
<div class="ops-top">
|
||||||
<Button icon="ios-arrow-back" @click="back">返回</Button>
|
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<Button size="small" :disabled="!prevId" @click="goNav(prevId)">上一篇</Button>
|
<Button size="small" :disabled="!prevId" @click="goNav(prevId)">上一篇</Button>
|
||||||
<Button size="small" :disabled="!nextId" @click="goNav(nextId)">下一篇</Button>
|
<Button size="small" :disabled="!nextId" @click="goNav(nextId)">下一篇</Button>
|
||||||
@@ -288,9 +283,6 @@ function back() {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.stat-nums:hover .item {
|
|
||||||
color: #2d8cf0;
|
|
||||||
}
|
|
||||||
.stat-nums .item {
|
.stat-nums .item {
|
||||||
color: #8a94a6;
|
color: #8a94a6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ watch(
|
|||||||
|
|
||||||
/* ============ 操作(规范 §2:operating-btn iconfont;§6:删除 myConfirm) ============ */
|
/* ============ 操作(规范 §2:operating-btn iconfont;§6:删除 myConfirm) ============ */
|
||||||
function openDetail(row: NoticeVo) {
|
function openDetail(row: NoticeVo) {
|
||||||
router.push({ path: "/details", query: { serid: row.id, type: 0, from: route.path } });
|
// 详情路由随入口:已发送 → /list/detail(高亮已发送),全部通知 → /noticelist/detail(高亮全部通知)
|
||||||
|
const detailPath = route.path.startsWith("/noticelist") ? "/noticelist/detail" : "/list/detail";
|
||||||
|
router.push({ path: detailPath, query: { serid: row.id, type: 0 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
function del(row: NoticeVo) {
|
function del(row: NoticeVo) {
|
||||||
@@ -139,7 +141,7 @@ function downloadFiles(row: NoticeVo & { UpFile?: string }) {
|
|||||||
|
|
||||||
/* 表格列(对照旧版 notice_list.vue;操作列图标式 width 180 fixed right) */
|
/* 表格列(对照旧版 notice_list.vue;操作列图标式 width 180 fixed right) */
|
||||||
const columns = [
|
const columns = [
|
||||||
{ title: "序号", type: "index", width: 60, align: "center" },
|
{ title: "序号", type: "index", width: 90, align: "center" },
|
||||||
{ title: "标题", key: "title", align: "left", tooltip: true },
|
{ title: "标题", key: "title", align: "left", tooltip: true },
|
||||||
{ title: "来源部门", key: "deptName", width: 130, align: "left" },
|
{ title: "来源部门", key: "deptName", width: 130, align: "left" },
|
||||||
{ title: "发布人", key: "publisherName", width: 110, align: "left", tooltip: true },
|
{ title: "发布人", key: "publisherName", width: 110, align: "left", tooltip: true },
|
||||||
@@ -149,10 +151,10 @@ const columns = [
|
|||||||
align: "left",
|
align: "left",
|
||||||
render: (h: any, p: any) => h("span", {}, String(p.row.createTime || "").slice(0, 16)),
|
render: (h: any, p: any) => h("span", {}, String(p.row.createTime || "").slice(0, 16)),
|
||||||
},
|
},
|
||||||
{ title: "已读人数", key: "readCount", width: 90, align: "left" },
|
{ title: "已读人数", key: "readCount", width: 110, align: "left" },
|
||||||
{
|
{
|
||||||
title: "未读人数",
|
title: "未读人数",
|
||||||
width: 90,
|
width: 110,
|
||||||
align: "left",
|
align: "left",
|
||||||
render: (h: any, p: any) => h("span", {}, (p.row.allowCount || 0) - (p.row.readCount || 0)),
|
render: (h: any, p: any) => h("span", {}, (p.row.allowCount || 0) - (p.row.readCount || 0)),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -144,16 +144,6 @@ async function deptSortSave() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncDept() {
|
|
||||||
try {
|
|
||||||
await settingApi.getDeptSync().send();
|
|
||||||
Message.success("同步成功");
|
|
||||||
await getDeptList();
|
|
||||||
} catch (e: any) {
|
|
||||||
Message.error(e.message || "同步失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============ 自定义组(规范 §5 联系组管理页形态) ============ */
|
/* ============ 自定义组(规范 §5 联系组管理页形态) ============ */
|
||||||
interface GroupItem {
|
interface GroupItem {
|
||||||
serid: number;
|
serid: number;
|
||||||
@@ -306,6 +296,8 @@ async function settingUserSubmit(users: SchoolTreeNode[]) {
|
|||||||
try {
|
try {
|
||||||
await settingApi.setContactsTea(setUserGid.value, ids).send();
|
await settingApi.setContactsTea(setUserGid.value, ids).send();
|
||||||
Message.success("设置成功");
|
Message.success("设置成功");
|
||||||
|
// 刷新组列表,组员数即时更新
|
||||||
|
await getGroupList();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
Message.error(e.message || "设置失败");
|
Message.error(e.message || "设置失败");
|
||||||
}
|
}
|
||||||
@@ -324,7 +316,6 @@ const groupColumns = [
|
|||||||
title: "操作",
|
title: "操作",
|
||||||
width: 250,
|
width: 250,
|
||||||
align: "center",
|
align: "center",
|
||||||
fixed: "right",
|
|
||||||
render: (h: any, params: any) => {
|
render: (h: any, params: any) => {
|
||||||
const row: GroupItem = params.row;
|
const row: GroupItem = params.row;
|
||||||
return [
|
return [
|
||||||
@@ -352,7 +343,6 @@ const groupTableHeight = computed(() => Utils.useTableHeight({ isTabs: true, isS
|
|||||||
<Alert show-icon>设置说明:拖动卡片调整部门排序;停用的部门不出现在「通知发送」的部门下拉中</Alert>
|
<Alert show-icon>设置说明:拖动卡片调整部门排序;停用的部门不出现在「通知发送」的部门下拉中</Alert>
|
||||||
<div class="search-wrap fix">
|
<div class="search-wrap fix">
|
||||||
<Button class="fl" type="primary" @click="addDeptShow">新增部门</Button>
|
<Button class="fl" type="primary" @click="addDeptShow">新增部门</Button>
|
||||||
<Button class="fr" @click="syncDept">同步基础平台部门</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<draggable
|
<draggable
|
||||||
class="type_set-wrap fix"
|
class="type_set-wrap fix"
|
||||||
|
|||||||
+1
-1
@@ -101,7 +101,7 @@ export default defineConfig(({ command, mode }: ConfigEnv): UserConfig => {
|
|||||||
// dev 正式模式:serviceHost 为空(同源相对路径 /api/...),经此代理转发到本地后端
|
// dev 正式模式:serviceHost 为空(同源相对路径 /api/...),经此代理转发到本地后端
|
||||||
// (后端 CAS 过滤器对 /api/* 不回 CORS 头,浏览器直连 8070 会被拦,必须同源代理)
|
// (后端 CAS 过滤器对 /api/* 不回 CORS 头,浏览器直连 8070 会被拦,必须同源代理)
|
||||||
"/api": {
|
"/api": {
|
||||||
target: "http://localhost:8070",
|
target: "http://localhost:8101",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user