应用页规范(bsch)重构: - 6 个列表页迁规范骨架: page-wrapper/tabs-wrapper + search-wrap 搜索区(关键字 200px 即输即搜, 去查询按钮) + link-table table-bottom-box 定高表格 + page-panel 分页栏 - 分页列表统一接 TablePageAlovaNew(页长 [10,20,30,40]/customPageCount 记忆/增删智能翻页); dataApi 须返回 Method, 调 .send() 会导致表格静默空数据 - 操作列统一图标式 operatingHandle(Tooltip+fixed right 居中); 各列表补序号列; 危险操作统一 MyConfirm 二次确认 - 弹窗表单必填红星 + 统一提示「请填写红色星号内容!」 - TablePageAlovaNew 补页长记忆与重载后清空勾选; 新增 src/types OperatorEnum 工作台与流程轨迹优化: - 已办列表去重: 每办件一行, doneCount>1 显示「共办理 N 次」标签 - 新增 TraceTimeline 轨迹时间流(时间升序/kind/轮次, 按人员/科室切换写回 URL), 接入详情/办理页 - 新增流程源码只读抽屉 SourceDrawer, 接入定义列表与图示页 - 办理人映射/流程定义新增「启用」回路(/admin/map/enable, /admin/def/enable) - 图示视图口径统一 dept/user 两档, 缺省人员视图; 状态列 Tag 色映射统一导出
This commit is contained in:
+119
-81
@@ -2,6 +2,7 @@
|
||||
// 办理人映射管理(概览 §4.7/§六):DEPT_KEY → 办理人;办理人改为弹窗选人(参照 Notice 选人范式)
|
||||
import { ref, onMounted } from "vue";
|
||||
import { Message } from "view-ui-plus";
|
||||
import MyConfirm from "@/components/MyConfirm";
|
||||
import UserSelectInput from "@/components/UserSelectInput.vue";
|
||||
import { flowApi } from "@/api/module/flow";
|
||||
import Utils from "@/utils";
|
||||
@@ -9,10 +10,8 @@ import Utils from "@/utils";
|
||||
const loading = ref(false);
|
||||
const deptKeyFilter = ref("");
|
||||
const rows = ref<any[]>([]);
|
||||
|
||||
const saveVisible = ref(false);
|
||||
const saving = ref(false);
|
||||
const form = ref<any>({ deptKey: "", deptName: "", userId: null, userName: "" });
|
||||
// 操作按钮区 + 搜索区、无分页
|
||||
const tableHeight = ref(Utils.useTableHeight({ isSearch: true, isOperat: true }));
|
||||
|
||||
// 一键拉取教师组(预览确认后批量导入)
|
||||
const groupVisible = ref(false);
|
||||
@@ -22,7 +21,7 @@ const groupRows = ref<any[]>([]);
|
||||
const groupColumns = [
|
||||
{ title: "科室编码", key: "deptKey", width: 100 },
|
||||
{ title: "科室名称", key: "deptName", width: 160 },
|
||||
{ title: "成员数", key: "memberCount", width: 90, render: (h: any, p: any) => h("span", String(p.row.users?.length || 0)) },
|
||||
{ title: "成员数", key: "memberCount", width: 90, align: "center", render: (h: any, p: any) => h("span", String(p.row.users?.length || 0)) },
|
||||
{ title: "成员", key: "members", render: (h: any, p: any) => h("span", (p.row.users || []).map((u: any) => `${u.userName}(${u.userId})`).join("、") || "(空,导入后可手工补)") },
|
||||
];
|
||||
|
||||
@@ -54,26 +53,41 @@ async function onGroupImport() {
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ title: "序号", type: "index", width: 70, align: "center" },
|
||||
{ title: "科室编码", key: "deptKey", width: 140 },
|
||||
{ title: "科室名称", key: "deptName", width: 160, render: (h: any, p: any) => h("span", p.row.deptName || "-") },
|
||||
{ title: "科室名称", width: 160, render: (h: any, p: any) => h("span", p.row.deptName || "-") },
|
||||
{ title: "办理人", key: "userName", width: 120 },
|
||||
{ title: "用户ID", key: "userId", width: 90 },
|
||||
{ title: "状态", width: 90, render: (h: any, p: any) => h("Tag", { color: p.row.status === 0 ? "green" : "gray" }, () => (p.row.status === 0 ? "启用" : "停用")) },
|
||||
{ title: "操作", width: 100, render: (h: any, p: any) =>
|
||||
{ title: "状态", width: 90, align: "center", render: (h: any, p: any) => h("Tag", { color: p.row.status === 0 ? "green" : "gray" }, () => (p.row.status === 0 ? "启用" : "停用")) },
|
||||
{ title: "操作", width: 100, align: "center", fixed: "right", render: (h: any, p: any) =>
|
||||
p.row.status === 0
|
||||
? Utils.operatingTextHandle(h, "停用", "text-error", () => onDisable(p.row))
|
||||
: h("span", "-") },
|
||||
? Utils.operatingHandle(h, "停用", "icon-stop", () => onDisable(p.row))
|
||||
: Utils.operatingHandle(h, "启用", "icon-play", () => onEnable(p.row)) },
|
||||
];
|
||||
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
try {
|
||||
rows.value = (await flowApi.mapList(deptKeyFilter.value || undefined).send()) || [];
|
||||
rows.value = (await flowApi.mapList(deptKeyFilter.value.trim() || undefined).send()) || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onSearch() {
|
||||
load();
|
||||
}
|
||||
|
||||
// ---- 新增/更新映射弹窗(规范:必填红星标注,校验失败提示统一文案) ----
|
||||
const saveVisible = ref(false);
|
||||
const saving = ref(false);
|
||||
const formRef = ref<any>(null);
|
||||
const form = ref<any>({ deptKey: "", deptName: "", userId: null, userName: "" });
|
||||
const saveRules = {
|
||||
deptKey: [{ required: true, message: "请填写红色星号内容!", trigger: "blur" }],
|
||||
userId: [{ required: true, message: "请填写红色星号内容!", trigger: "change" }],
|
||||
};
|
||||
|
||||
function onAdd() {
|
||||
form.value = { deptKey: "", deptName: "", userId: null, userName: "" };
|
||||
saveVisible.value = true;
|
||||
@@ -84,84 +98,108 @@ function onUserPick(u: any) {
|
||||
form.value.userName = u?.name || "";
|
||||
}
|
||||
|
||||
async function onSave() {
|
||||
if (!form.value.deptKey.trim() || !form.value.userId) {
|
||||
Message.warning("科室编码与办理人必填");
|
||||
return;
|
||||
}
|
||||
saving.value = true;
|
||||
try {
|
||||
await flowApi.mapSave({
|
||||
deptKey: form.value.deptKey.trim(),
|
||||
deptName: form.value.deptName,
|
||||
userId: Number(form.value.userId),
|
||||
userName: form.value.userName,
|
||||
}).send();
|
||||
Message.success("已保存");
|
||||
saveVisible.value = false;
|
||||
load();
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
function onSave() {
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (!valid) return;
|
||||
saving.value = true;
|
||||
try {
|
||||
await flowApi.mapSave({
|
||||
deptKey: form.value.deptKey.trim(),
|
||||
deptName: form.value.deptName,
|
||||
userId: Number(form.value.userId),
|
||||
userName: form.value.userName,
|
||||
}).send();
|
||||
Message.success("已保存");
|
||||
saveVisible.value = false;
|
||||
load();
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function onDisable(row: any) {
|
||||
await flowApi.mapDisable(row.id).send();
|
||||
Message.success("已停用");
|
||||
load();
|
||||
function onDisable(row: any) {
|
||||
MyConfirm({
|
||||
title: "停用",
|
||||
msg: `确定停用科室「${row.deptName || row.deptKey}」的办理人映射吗?`,
|
||||
info: "停用后该科室流程节点需重新配置办理人",
|
||||
async onOk() {
|
||||
await flowApi.mapDisable(row.id).send();
|
||||
Message.success("已停用");
|
||||
load();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 启用(2026-09-18 补齐:原来停用后只能重新"新增映射"恢复) */
|
||||
function onEnable(row: any) {
|
||||
MyConfirm({
|
||||
title: "启用",
|
||||
msg: `确定启用科室「${row.deptName || row.deptKey}」的办理人「${row.userName || row.userId}」吗?`,
|
||||
info: "启用后该科室的流程节点会重新解析到这名办理人",
|
||||
async onOk() {
|
||||
await flowApi.mapEnable(row.id).send();
|
||||
Message.success("已启用");
|
||||
load();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="filter">
|
||||
<Input v-model="deptKeyFilter" placeholder="按科室编码筛选" style="width: 200px" clearable @on-enter="load" />
|
||||
<Button @click="load">查询</Button>
|
||||
<Button type="primary" @click="onAdd">新增映射</Button>
|
||||
<Button type="info" :loading="groupLoading" @click="onGroupPreview">一键拉取教师组</Button>
|
||||
<div class="page-wrapper">
|
||||
<div class="main-container">
|
||||
<!-- 操作按钮区:主操作靠左、其余靠右(bsch应用页规范 §1) -->
|
||||
<div class="fix mb-12">
|
||||
<Button class="fl" type="primary" size="large" @click="onAdd">新增映射</Button>
|
||||
<Button class="fr" size="large" :loading="groupLoading" @click="onGroupPreview">一键拉取教师组</Button>
|
||||
</div>
|
||||
|
||||
<!-- 搜索区:关键字即输即搜,不设查询按钮 -->
|
||||
<div class="search-wrap fix">
|
||||
<Input class="fr" v-model="deptKeyFilter" placeholder="按科室编码筛选" search suffix="ios-search"
|
||||
style="width: 200px" @on-search="onSearch" @on-clear="onSearch" />
|
||||
</div>
|
||||
|
||||
<Table :columns="columns" :data="rows" :loading="loading" class="link-table table-bottom-box"
|
||||
:height="tableHeight" no-data-text="暂无数据" />
|
||||
|
||||
<Modal v-model="saveVisible" title="新增/更新映射" :mask-closable="false">
|
||||
<Form ref="formRef" :model="form" :rules="saveRules" :label-width="90">
|
||||
<FormItem label="科室编码" prop="deptKey">
|
||||
<Input v-model="form.deptKey" placeholder="流程 JSON 中 DEPT_KEY 引用的编码,如 ybb" />
|
||||
</FormItem>
|
||||
<FormItem label="科室名称">
|
||||
<Input v-model="form.deptName" placeholder="如 医保办(可空)" />
|
||||
</FormItem>
|
||||
<FormItem label="办理人" prop="userId">
|
||||
<UserSelectInput
|
||||
:model-value="form.userId"
|
||||
:display-name="form.userName"
|
||||
@update:model-value="form.userId = $event"
|
||||
@update:display-name="form.userName = $event"
|
||||
@on-change="onUserPick"
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<Button @click="saveVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="saving" @click="onSave">提交</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
|
||||
<Modal v-model="groupVisible" title="一键拉取教师组(UserBase 学校组树)" width="720" :mask-closable="false">
|
||||
<p style="margin-bottom: 8px; color: #808695">
|
||||
按学校组树中类型=教师组(type 7)的容器组取其子组作为科室(无子组时容器自身即科室),科室编码=UserBase 组 id,成员=组内用户。已存在且启用中的映射自动跳过。
|
||||
</p>
|
||||
<Table :columns="groupColumns" :data="groupRows" :loading="groupLoading" max-height="360" no-data-text="暂无数据" />
|
||||
<template #footer>
|
||||
<Button @click="groupVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="groupImporting" :disabled="!groupRows.length" @click="onGroupImport">确认导入</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
<Table :columns="columns" :data="rows" :loading="loading" stripe />
|
||||
|
||||
<Modal v-model="saveVisible" title="新增/更新映射" :mask-closable="false">
|
||||
<Form :label-width="90">
|
||||
<FormItem label="科室编码">
|
||||
<Input v-model="form.deptKey" placeholder="流程 JSON 中 DEPT_KEY 引用的编码,如 ybb" />
|
||||
</FormItem>
|
||||
<FormItem label="科室名称">
|
||||
<Input v-model="form.deptName" placeholder="如 医保办(可空)" />
|
||||
</FormItem>
|
||||
<FormItem label="办理人">
|
||||
<UserSelectInput
|
||||
:model-value="form.userId"
|
||||
:display-name="form.userName"
|
||||
@update:model-value="form.userId = $event"
|
||||
@update:display-name="form.userName = $event"
|
||||
@on-change="onUserPick"
|
||||
/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<Button @click="saveVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="saving" @click="onSave">保存</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
|
||||
<Modal v-model="groupVisible" title="一键拉取教师组(UserBase 学校组树)" width="720" :mask-closable="false">
|
||||
<p style="margin-bottom: 8px; color: #808695">
|
||||
按学校组树中类型=教师组(type 7)的容器组取其子组作为科室(无子组时容器自身即科室),科室编码=UserBase 组 id,成员=组内用户。已存在且启用中的映射自动跳过。
|
||||
</p>
|
||||
<Table :columns="groupColumns" :data="groupRows" :loading="groupLoading" max-height="360" stripe />
|
||||
<template #footer>
|
||||
<Button @click="groupVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="groupImporting" :disabled="!groupRows.length" @click="onGroupImport">确认导入</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.page { padding: 12px 16px; }
|
||||
.filter { margin-bottom: 10px; display: flex; gap: 8px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user