diff --git a/src/api/module/flow.ts b/src/api/module/flow.ts index 18decd6..b75b7bc 100644 --- a/src/api/module/flow.ts +++ b/src/api/module/flow.ts @@ -252,6 +252,10 @@ class FlowApi { callbackRepush(ids: number[]) { return post(`${ROOT}/admin/callback/repush`, ids); } + /** 对接健康度体检(2026-10-15 P2):每应用一行六项检查 + 综合评分,零新增表 */ + callbackHealth() { + return get(`${ROOT}/admin/callback/health`); + } // ==================== 管理面:条件路由注册 / 重跑 ==================== diff --git a/src/views/flow/admin/AppSetting.vue b/src/views/flow/admin/AppSetting.vue index c997688..1ad0e36 100644 --- a/src/views/flow/admin/AppSetting.vue +++ b/src/views/flow/admin/AppSetting.vue @@ -2,8 +2,9 @@ // 应用设置(2026-10-10 四议题):tab1 应用管理(flw_app 白名单 + 学校池同步 + 开关); // tab2 科室管理(flw_dept 组+成员模型,取代旧「办理人映射」页——deptKey=本地自增 id, // 切源后旧流程定义引用的 UserBase 组 id 需重建科室后重新配置)。 -import { ref, onMounted } from "vue"; -import { Message, Tag } from "view-ui-plus"; +import { ref, onMounted, watch } from "vue"; +import { useRouter } from "vue-router"; +import { Message, Tag, Button } from "view-ui-plus"; import MyConfirm from "@/components/MyConfirm"; import UserCheckModal from "@/components/UserCheckModal.vue"; import { flowApi } from "@/api/module/flow"; @@ -11,6 +12,7 @@ import { actionColumn } from "@/utils/tableActions"; import { useElementHeight } from "@/utils/hook/useElementHeight"; const tab = ref("apps"); +const router = useRouter(); // ==================== tab1 应用管理 ==================== const loading = ref(false); @@ -343,6 +345,101 @@ onMounted(() => { load(); loadDepts(); }); + +// ==================== tab3 对接健康度(2026-10-15 议题二 P2) ==================== +// 每应用一行六项检查 + 综合评分;数据全部来自已有接口(/callback/health 聚合),零新增表。 +// 应用无注册行 = 未接入(由接入向导负责),不参与体检。 +const healthLoading = ref(false); +const healthRows = ref([]); + +const healthColumns = [ + { + title: "应用", + key: "appName", + minWidth: 180, + render: (h: any, p: any) => + h("div", { class: "hc-app" }, [ + h("span", { class: "hc-app-n" }, p.row.appName), + h("span", { class: "hc-app-k" }, p.row.appKey), + ]), + }, + { + title: "评分", + width: 96, + align: "center", + render: (h: any, p: any) => + h("span", { class: ["hc-score", "is-" + p.row.level] }, String(p.row.score)), + }, + { + title: "结论", + width: 90, + align: "center", + render: (h: any, p: any) => { + const map: Record = { + ok: ["正常", "green"], + warn: ["关注", "orange"], + bad: ["异常", "red"], + }; + const [txt, color] = map[p.row.level] || ["未知", "default"]; + return h(Tag, { color }, () => txt); + }, + }, + { + title: "检查项", + minWidth: 460, + render: (h: any, p: any) => + h("div", { class: "hc-checks" }, (p.row.checks || []).map((c: any) => + h("span", { + class: ["hc-chip", "is-" + c.level], + attrs: { title: (c.advice ? c.advice + "\n" : "") + "实测:" + (c.value || "-") }, + }, [ + h("i", { class: ["hc-dot", "is-" + c.level] }), + h("span", { class: "hc-chip-n" }, c.name), + c.value ? h("em", { class: "hc-chip-v" }, c.value) : null, + ]))), + }, + { + title: "结论说明", + key: "summary", + minWidth: 220, + render: (h: any, p: any) => h("span", { class: "hc-sum" }, p.row.summary || "-"), + }, + { + title: "操作", + width: 110, + align: "center", + render: (h: any, p: any) => + h(Button, { + props: { type: "text", size: "small" }, + on: { click: () => onViewLogs(p.row) }, + }, () => "查推送日志"), + }, +]; + +function onViewLogs(row: any) { + router.push({ path: "/admin/callbacks", query: { appKey: row.appKey } }); +} + +async function loadHealth() { + healthLoading.value = true; + try { + healthRows.value = ((await (flowApi as any).callbackHealth().send()) as any[]) || []; + } catch (e: any) { + Message.error(e?.message || "健康度加载失败"); + healthRows.value = []; + } finally { + healthLoading.value = false; + } +} + +// 首次切到「对接健康度」时按需加载(避免进页面就多打一次聚合查询) +let healthLoaded = false; +watch(tab, (t) => { + if (t === "health" && !healthLoaded) { + healthLoaded = true; + loadHealth(); + } +});