feat(msgcenter): /msg 换真实数据——服务端筛选+滚动分页、铃铛直跳、unreadCount 上提 store、WS 通知带应用名
- views/msg/index.vue:数据层整体替换(msgType 0/1/2 映射、isRead 1=已读、fmtTime 重写绝对时间);列表走 msgCenter/list 服务端筛选(msgType/appKey/isRead/keyword 防抖 300ms),滚动到底追加下一页,切视图/搜索重置第 1 页;左栏分类计数走 summary(旧版 UserMsg 缺字段降级显示 —),应用清单取 store 应用列表、计数同源 todos;点击卡片标已读、全部已读、去处理(showJump/jumpUrl)、审批直批(共享弹窗);失败态有重试;WS 新消息经 mittBus 自刷新 - components/Header.vue:铃铛直跳 /msg(移除 Poptip 浮层与 900 宽 Modal 及 columns/tableApi 死代码);unreadCount 上提 pinia store(角标与 /msg、LeftMenu 同源);WS Notice.info 标题带应用名(appKey 匹配 store 应用列表,缺失回退类型标签);壁纸/LOGO Modal 不动 - components/MsgApprovalModal.vue(新增):审批直批弹窗抽共享组件,逻辑照抄原 Header 内联实现(同意可选意见/拒绝必填校验/三种失败反馈) - components/LeftMenu.vue:「消息」入口(url=/msg)未读角标(读 store,红底白字胶囊) - store/index.ts:unreadCount + setUnreadCount/incUnread/decUnread - api/BaseApi.ts:getMsgCenterList 参数类型放宽(服务端筛选项);getMsgCenterSummary 返回类型补分类计数字段(可缺省) - assets/styles/header.scss:删除消息浮层死样式 .message-wrap 段
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<!-- 消息卡片直批弹窗(B3 §2,消息对接 2026-09-30 抽共享):同意可选意见 / 拒绝意见必填;
|
||||
身份(operatorId/schId/operatorName)服务端取会话。Header 铃铛域已无直批入口,
|
||||
本组件供 /msg 消息中心页使用,逻辑照抄原 Header 内联实现。 -->
|
||||
<Modal :model-value="visible" width="460" :mask-closable="false"
|
||||
:title="action === 'approve' ? '同意办理' : '拒绝办理'" @on-cancel="close">
|
||||
<div class="approval-body">
|
||||
<p class="approval-title text-ellipsis">{{ title || "确认办理该待办?" }}</p>
|
||||
<Input v-model="opinion" type="textarea" :rows="3" maxlength="200" show-word-limit
|
||||
:placeholder="action === 'approve' ? '审批意见(可选)' : '请输入拒绝意见(必填)'" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button type="primary" :loading="submitting" @click="submit">
|
||||
{{ action === "approve" ? "确认同意" : "确认拒绝" }}
|
||||
</Button>
|
||||
<Button @click="close">取消</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { Notice } from "view-ui-plus";
|
||||
import BaseApi from "@/api/BaseApi";
|
||||
|
||||
/**
|
||||
* 审批直批弹窗(msgCenter/handle 代理)。
|
||||
* 父组件 open({msgId, title, action}) 打开;成功(后端 ok)后 emit("handled", msgId),
|
||||
* 失败/已被处理等场景只弹后端文案,不关弹窗(成功/失败/已被处理三种场景都有反馈)。
|
||||
*/
|
||||
const emit = defineEmits<{ (e: "handled", msgId: number): void }>();
|
||||
|
||||
const visible = ref(false);
|
||||
const msgId = ref(0);
|
||||
const title = ref("");
|
||||
const action = ref<"approve" | "reject">("approve");
|
||||
const opinion = ref("");
|
||||
const submitting = ref(false);
|
||||
|
||||
function open(row: { msgId: number; title?: string }, act: "approve" | "reject") {
|
||||
msgId.value = row.msgId;
|
||||
action.value = act;
|
||||
title.value = row.title ? String(row.title) : "";
|
||||
opinion.value = "";
|
||||
submitting.value = false;
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
function close() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (submitting.value) return;
|
||||
if (action.value === "reject" && !opinion.value.trim()) {
|
||||
Notice.warning({ title: "拒绝必须填写意见", duration: 3 });
|
||||
return;
|
||||
}
|
||||
submitting.value = true;
|
||||
try {
|
||||
const res: any = await BaseApi.handleMsg(msgId.value, action.value, opinion.value.trim());
|
||||
if (res && res.ok) {
|
||||
Notice.success({ title: "办理成功", duration: 3 });
|
||||
visible.value = false;
|
||||
emit("handled", msgId.value);
|
||||
} else {
|
||||
Notice.warning({ title: (res && res.message) || "办理失败", duration: 5 });
|
||||
}
|
||||
} catch (e) {
|
||||
// flow-center 不可达等:降级为提示,不阻塞消息卡片其余功能
|
||||
Notice.error({ title: "流程中心暂不可用,请稍后重试", duration: 5 });
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.approval-body {
|
||||
.approval-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #2c3138;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user