| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import {
- adaptBpmTask,
- adaptCcProcess,
- approveTask,
- getCcProcessPage,
- getDoneTaskPage,
- getProcessInstance,
- getTodoTaskPage,
- rejectTask,
- } from "@/api/hr/bpm";
- import { loadResignationDetail } from "@/api/hr/resign";
- export const APPROVAL_TAB_TODO = "待我审批";
- export const APPROVAL_TAB_DONE = "我已审批";
- export const APPROVAL_TAB_CC = "抄送我的";
- export const APPROVAL_TABS = [APPROVAL_TAB_TODO, APPROVAL_TAB_DONE, APPROVAL_TAB_CC];
- export const RESIGN_BUSINESS_TYPE = "离职申请";
- // 缓存最近一次列表结果,详情页按 id 查找时优先命中,避免重复请求
- const listCache = new Map();
- function isResignType(text) {
- return String(text || "").includes("离职");
- }
- // 服务端任务不一定回填 businessType,这里把流程名 / 移动端路由一起作为兜底判断
- function isResignItem(item = {}) {
- return [item.type, item.businessName, item.processName, item.viewRouter].some(
- (text) => isResignType(text) || String(text || "").toLowerCase().includes("resign")
- );
- }
- function withStatus(item) {
- const status = (item.result || {}).status || "待审批";
- return {
- ...item,
- statusLabel: status,
- statusClass:
- status === "已同意"
- ? "status-approved"
- : status === "待审批" || status === "已抄送"
- ? "status-pending"
- : "status-rejected",
- };
- }
- // 任务上没带业务主键时,回流程实例里找(PC 端发起流程时写入 businessId / 流程变量)
- async function resolveBusiness(item) {
- if (item.businessId && item.applicant !== "—") return item;
- if (!item.processInstanceId) return item;
- try {
- const instance = (await getProcessInstance(item.processInstanceId, false)) || {};
- const variables = instance.variables || {};
- const businessId = item.businessId || instance.businessId || variables.businessId || "";
- const applicant =
- item.applicant && item.applicant !== "—"
- ? item.applicant
- : instance.startUserNickname || variables.businessName || "—";
- return {
- ...item,
- businessId,
- processName:
- item.processName || instance.name || variables.businessName || "",
- businessCode: item.businessCode || instance.businessCode || variables.businessCode || "",
- applicant,
- avatar: String(applicant || "审").charAt(0),
- dept: item.dept || variables.departmentName || "",
- position: item.position || variables.positionName || "",
- type: isResignType(item.type) || !variables.businessType ? item.type : variables.businessType,
- };
- } catch (error) {
- return item;
- }
- }
- // 离职类审批:补全离职单信息,便于审批人在手机上直接看单据
- async function withResignation(item) {
- if (!isResignItem(item) || !item.businessId) return item;
- try {
- const resignation = await loadResignationDetail(item.businessId);
- if (!resignation) return item;
- const applicant =
- item.applicant && item.applicant !== "—" ? item.applicant : resignation.name || "—";
- return {
- ...item,
- resignation,
- applicant,
- avatar: String(applicant || "离").charAt(0),
- dept: item.dept || resignation.department || "",
- position: item.position || resignation.position || "",
- businessCode: resignation.resignationNo || item.businessCode || "",
- processName: item.processName || resignation.type || RESIGN_BUSINESS_TYPE,
- summary: `${resignation.type || RESIGN_BUSINESS_TYPE} · 预计离职 ${
- resignation.expectedLeaveDate || "—"
- }`,
- reason: resignation.reason || item.reason,
- days: item.days || `${(resignation.handover && resignation.handover.items ? resignation.handover.items.length : 0)} 项交接`,
- };
- } catch (error) {
- return item;
- }
- }
- async function toServerItem(vo, done) {
- const task = adaptBpmTask(vo);
- const base = {
- id: task.taskId,
- source: "server",
- taskId: task.taskId,
- processInstanceId: task.processInstanceId,
- processName: task.processName,
- businessId: task.businessId,
- businessCode: task.businessCode,
- businessName: task.businessName,
- type: task.businessType || task.processName,
- applicant: task.applicant || "—",
- avatar: String(task.applicant || "审").charAt(0),
- dept: task.department,
- position: task.position,
- taskName: task.name,
- viewRouter: task.viewRouter,
- handleRouter: task.handleRouter,
- summary: [task.businessType, task.businessCode || task.businessName].filter(Boolean).join(" · "),
- reason: "",
- days: "",
- color: "#157a2c",
- time: task.createTime,
- result: done
- ? {
- status: task.resultLabel || "已同意",
- comment: task.reason || "",
- handledAt: task.handledAt,
- }
- : null,
- raw: vo,
- };
- return withStatus(await withResignation(await resolveBusiness(base)));
- }
- // 抄送我的是只读列表,不带审批动作
- function toCcItem(vo) {
- const cc = adaptCcProcess(vo);
- return withStatus({
- id: `cc-${cc.id}`,
- source: "server",
- ccId: cc.id,
- processInstanceId: cc.processInstanceId,
- processName: cc.processName,
- businessId: "",
- businessCode: "",
- type: cc.processName || "流程抄送",
- applicant: cc.applicant || cc.creatorName || "—",
- avatar: String(cc.applicant || cc.creatorName || "抄").charAt(0),
- dept: "",
- position: "",
- taskName: cc.taskName,
- summary: [cc.processName, cc.taskName].filter(Boolean).join(" · "),
- reason: cc.reason,
- days: "",
- color: "#157a2c",
- time: cc.createTime,
- readonly: true,
- result: { status: "已抄送", comment: cc.reason || "", handledAt: cc.createTime },
- raw: vo,
- });
- }
- async function serverApprovalItems(tab) {
- if (tab === APPROVAL_TAB_CC) {
- const page = await getCcProcessPage();
- return (page.list || []).map((vo) => toCcItem(vo));
- }
- const page = tab === APPROVAL_TAB_TODO ? await getTodoTaskPage() : await getDoneTaskPage();
- const done = tab !== APPROVAL_TAB_TODO;
- return Promise.all((page.list || []).map((vo) => toServerItem(vo, done)));
- }
- /**
- * 审批列表统一入口
- */
- export async function loadApprovalList(tab = APPROVAL_TAB_TODO) {
- const list = await serverApprovalItems(tab);
- listCache.set(tab, list);
- return { list, source: "api" };
- }
- /**
- * 审批详情:优先命中缓存,未命中则待办 / 已办各拉一次再匹配
- */
- export async function loadApprovalDetail(id) {
- if (!id) return null;
- const cachedList = Array.from(listCache.values());
- for (let i = 0; i < cachedList.length; i++) {
- const hit = (cachedList[i] || []).find((x) => String(x.id) === String(id));
- if (hit) return hit;
- }
- const results = await Promise.all([
- serverApprovalItems(APPROVAL_TAB_TODO),
- serverApprovalItems(APPROVAL_TAB_DONE),
- ]);
- const all = results[0].concat(results[1]);
- return all.find((x) => String(x.id) === String(id)) || null;
- }
- /**
- * 审批通过
- */
- export async function actApproveApproval(item, comment = "") {
- if (!item || !item.id) throw new Error("缺少审批主键");
- const reason = String(comment || "").trim() || "同意";
- await approveTask({ id: item.taskId || item.id, reason });
- return true;
- }
- /**
- * 审批驳回
- */
- export async function actRejectApproval(item, comment = "") {
- if (!item || !item.id) throw new Error("缺少审批主键");
- const reason = String(comment || "").trim() || "申请信息不完整";
- await rejectTask({ id: item.taskId || item.id, reason });
- return true;
- }
- /** 待办数量(首页 / 工作台 / TabBar 角标) */
- export async function fetchPendingApprovalCount() {
- try {
- const page = await getTodoTaskPage({ pageSize: 1 }, false);
- return page.total || 0;
- } catch (error) {
- return 0;
- }
- }
|