feat(flow): 应用内「抄送给我的」——notice_cc 列表页(路由 /cc)、API 封装、跳通知详情(type=0 不标读)
数据源 /api/notice/cc/My(flw_cc 落表经 flow.cc.sent 回调);未发布通知的详情可见由后端 NoticeFlowGuard 第 4 条(被抄送人)放行
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { Method } from "alova";
|
||||
import { alovaInstance } from "@/utils/alova/alova-iview";
|
||||
|
||||
/**
|
||||
* 应用内「抄送给我的」接口封装(2026-09-24)。
|
||||
* 走本应用后端 /api/notice/cc/My(身份=CAS 登录态,前端不传身份);
|
||||
* 数据源是 flow.cc.sent 回调落的 notice_cc 表,点击行跳通知详情。
|
||||
*/
|
||||
|
||||
function get<T = any>(url: string, params?: Record<string, any>): Method<T> {
|
||||
return new Method<T>("GET", alovaInstance, url, { params });
|
||||
}
|
||||
|
||||
export interface CcItem {
|
||||
id: number;
|
||||
noticeId: number;
|
||||
flowInstanceId: number | null;
|
||||
nodeId: string | null;
|
||||
nodeName: string | null;
|
||||
sentTime: string;
|
||||
title: string | null;
|
||||
deptName: string | null;
|
||||
publisherName: string | null;
|
||||
noticeStatus: number | null;
|
||||
auditStatus: number | null;
|
||||
auditStatusDesc: string | null;
|
||||
}
|
||||
|
||||
export interface CcPage {
|
||||
total: number;
|
||||
content: CcItem[];
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
hasNext: boolean;
|
||||
}
|
||||
|
||||
export const ccApi = {
|
||||
/** 抄送给我的(分页,sent_time 倒序) */
|
||||
my(page = 1, size = 10): Method<CcPage> {
|
||||
return get(`/api/notice/cc/My`, { page, size });
|
||||
},
|
||||
};
|
||||
|
||||
export default ccApi;
|
||||
@@ -82,6 +82,15 @@ const routes: RouteRecordRaw[] = [
|
||||
meta: { title: "我的待审核", modId: 2100 },
|
||||
},
|
||||
|
||||
// 抄送给我的(流程 NOTIFY 知会;modId 25 深层页不在菜单树,菜单挂载待后端 GetUserMod 配置;
|
||||
// 勿复用 23——/list/detail 已占,modId 撞车会让菜单解析兜底到错误页面)
|
||||
{
|
||||
path: "/cc",
|
||||
name: "notice_cc",
|
||||
component: () => import("@/views/notice/NoticeCc.vue"),
|
||||
meta: { title: "抄送给我的", modId: 25, parentId: 1 },
|
||||
},
|
||||
|
||||
/* ---- 旧版路径兼容重定向(书签、残留的平台模块配置) ---- */
|
||||
{ path: "/accept", redirect: "/" },
|
||||
{ path: "/details", redirect: "/list/detail" },
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="page-wrapper yh-fill">
|
||||
<div class="main-container">
|
||||
<div class="table-region" ref="regionRef">
|
||||
<Table :columns="cols" :data="rows" :height="tableH || undefined" :loading="loading"
|
||||
no-data-text="暂无抄送通知">
|
||||
<template #title="{ row }">
|
||||
<a v-if="row.title" class="notice-link" @click="openDetail(row)">{{ row.title }}</a>
|
||||
<span v-else class="notice-gone">通知已删除</span>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<Tag v-if="row.auditStatusDesc && row.auditStatusDesc !== '通知已删除'"
|
||||
:color="statusColor(row.auditStatus)">{{ row.auditStatusDesc }}</Tag>
|
||||
<Tag v-else-if="row.noticeStatus === 1" color="green">已发布</Tag>
|
||||
<Tag v-else>—</Tag>
|
||||
</template>
|
||||
</Table>
|
||||
</div>
|
||||
<div class="page-panel" v-if="page.total > page.pageSize">
|
||||
<Page class="page-box fr" :current="page.pageIndex" :page-size="page.pageSize" :total="page.total"
|
||||
show-total @on-change="load" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Message } from "view-ui-plus";
|
||||
import { useElementHeight } from "@/utils/hook/useElementHeight";
|
||||
import ccApi, { type CcItem } from "@/api/module/cc";
|
||||
|
||||
/**
|
||||
* 抄送给我的(2026-09-24):流程 NOTIFY 节点激活即抄送(审批过程中就出现在列表里,
|
||||
* 此时通知未发布——被抄送人可见由 NoticeFlowGuard 第 4 条放行)。点击标题跳通知详情;
|
||||
* 编辑视角(type=0)不标读:未发布通知的阅读统计无意义。
|
||||
*/
|
||||
const router = useRouter();
|
||||
const loading = ref(false);
|
||||
const rows = ref<CcItem[]>([]);
|
||||
const page = ref({ total: 0, pageIndex: 1, pageSize: 10 });
|
||||
|
||||
const regionRef = ref<HTMLElement | null>(null);
|
||||
const tableH = useElementHeight(regionRef);
|
||||
|
||||
const cols = [
|
||||
{ title: "通知标题", slot: "title", minWidth: 260, ellipsis: true, tooltip: true },
|
||||
{ title: "来源部门", key: "deptName", width: 140 },
|
||||
{ title: "抄送环节", key: "nodeName", width: 140 },
|
||||
{ title: "抄送时间", key: "sentTime", width: 170, render: fmtTime },
|
||||
{ title: "状态", slot: "status", width: 100 },
|
||||
];
|
||||
|
||||
function fmtTime(h: any, p: any) {
|
||||
return h(
|
||||
"span",
|
||||
{},
|
||||
String(p.row[p.column.key] || "").replace("T", " ").slice(0, 19) || "—"
|
||||
);
|
||||
}
|
||||
|
||||
function statusColor(auditStatus: number | null) {
|
||||
return ({ 0: "default", 10: "blue", 20: "green", 30: "red", 40: "orange" } as Record<number, string>)[
|
||||
auditStatus ?? -1
|
||||
] || "default";
|
||||
}
|
||||
|
||||
function openDetail(row: CcItem) {
|
||||
router.push({ path: "/list/detail", query: { serid: row.noticeId, type: 0 } });
|
||||
}
|
||||
|
||||
async function load(p = 1) {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await ccApi.my(p, page.value.pageSize).send();
|
||||
page.value = res;
|
||||
rows.value = res.content || [];
|
||||
} catch (e: any) {
|
||||
Message.error(e?.message || "抄送列表加载失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => load(1));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.notice-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.notice-gone {
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user