feat(flow): 应用内「抄送给我的」——notice_cc 列表页(路由 /cc)、API 封装、跳通知详情(type=0 不标读)

数据源 /api/notice/cc/My(flw_cc 落表经 flow.cc.sent 回调);未发布通知的详情可见由后端 NoticeFlowGuard 第 4 条(被抄送人)放行
This commit is contained in:
chenxing
2026-09-24 09:29:21 +08:00
parent 7c885c0b4b
commit edd91b53b7
3 changed files with 151 additions and 0 deletions
+45
View File
@@ -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;
+9
View File
@@ -82,6 +82,15 @@ const routes: RouteRecordRaw[] = [
meta: { title: "我的待审核", modId: 2100 }, 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: "/accept", redirect: "/" },
{ path: "/details", redirect: "/list/detail" }, { path: "/details", redirect: "/list/detail" },
+97
View File
@@ -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>