|
|
@@ -160,7 +160,7 @@
|
|
|
<!-- 审批信息流程展示 -->
|
|
|
<div v-if="isView" style="margin-top: 24px; padding: 0 12px">
|
|
|
<div style="font-weight: bold; margin-bottom: 12px">审批流程进度</div>
|
|
|
- <el-steps :active="steps.length" align-center>
|
|
|
+ <el-steps :active="stepActiveIndex" align-center finish-status="success">
|
|
|
<el-step
|
|
|
v-for="(step, index) in steps"
|
|
|
:key="index"
|
|
|
@@ -453,102 +453,285 @@ const timeline = ref({
|
|
|
approvemsg:''
|
|
|
});
|
|
|
|
|
|
+//审批(与 SpecialBorrowApp 同构;通用借用保留仓库等详情)
|
|
|
+// 课堂借用(borrow_type=1)、特殊借用(=2):仅「创建申请 → 审批通过 → 流程完成」,不展示领取仓库
|
|
|
+function formatApprovalRecordTime(t: any): string {
|
|
|
+ if (t == null || t === '') return '';
|
|
|
+ const d = dayjs(t);
|
|
|
+ return d.isValid() ? d.format('YYYY-MM-DD HH:mm:ss') : String(t);
|
|
|
+}
|
|
|
+
|
|
|
+function getApproversTextForNode(step: any): string {
|
|
|
+ if (!step?.approvers?.length) return '';
|
|
|
+ let approvers = step.approvers;
|
|
|
+ const sn = String(step.step_name || '');
|
|
|
+ if (sn.includes('老师')) {
|
|
|
+ approvers = approvers.filter((a: any) => a.type === 'app_user');
|
|
|
+ } else if (sn.includes('管理员')) {
|
|
|
+ approvers = approvers.filter((a: any) => a.type === 'admin');
|
|
|
+ }
|
|
|
+ return approvers
|
|
|
+ .map((a: any) => a.name)
|
|
|
+ .filter((n: string) => n && String(n).trim())
|
|
|
+ .join('、');
|
|
|
+}
|
|
|
+
|
|
|
+/** 领取仓库与选仓操作挂在「管理员」环节;学院领导/老师等节点不展示(与 step_name 约定一致) */
|
|
|
+function isPickupWarehouseStep(workflowStep: any, record: any): boolean {
|
|
|
+ const a = String(workflowStep?.step_name ?? '');
|
|
|
+ const b = String((record as any)?.step_name ?? '');
|
|
|
+ return a.includes('管理员') || b.includes('管理员');
|
|
|
+}
|
|
|
+
|
|
|
+function isAllStepsStatusApprovedStep(step: any): boolean {
|
|
|
+ return (
|
|
|
+ step?.status === 'approved' ||
|
|
|
+ step?.status === 'finished' ||
|
|
|
+ step?.status_label === '已通过' ||
|
|
|
+ step?.status === 'pass'
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function findApprovedRecordForWorkflowStep(
|
|
|
+ step: any,
|
|
|
+ approvedOnly: any[],
|
|
|
+ sortedConfigSteps: any[]
|
|
|
+): any | null {
|
|
|
+ if (!step || !approvedOnly.length) return null;
|
|
|
+ const o = step.step_order;
|
|
|
+ let hit = approvedOnly.find(
|
|
|
+ (r: any) =>
|
|
|
+ r?.step_order != null &&
|
|
|
+ o != null &&
|
|
|
+ Number(r.step_order) === Number(o)
|
|
|
+ );
|
|
|
+ if (hit) return hit;
|
|
|
+ if (step.step_name) {
|
|
|
+ hit = approvedOnly.find(
|
|
|
+ (r: any) =>
|
|
|
+ r?.step_name &&
|
|
|
+ String(r.step_name) === String(step.step_name)
|
|
|
+ );
|
|
|
+ if (hit) return hit;
|
|
|
+ }
|
|
|
+ const stepIdx = sortedConfigSteps.findIndex((s) => s === step);
|
|
|
+ if (stepIdx >= 0 && stepIdx < approvedOnly.length) {
|
|
|
+ const r = approvedOnly[stepIdx];
|
|
|
+ if (r?.status === 1) return r;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+}
|
|
|
+
|
|
|
+const stepActiveIndex = computed(() => {
|
|
|
+ const s = steps.value;
|
|
|
+ if (!s.length) return 0;
|
|
|
+ const i = s.findIndex((x) => x.status === 'process' || x.status === 'error' || x.status === 'wait');
|
|
|
+ if (i >= 0) return i;
|
|
|
+ return Math.max(0, s.length - 1);
|
|
|
+});
|
|
|
|
|
|
function buildSteps(data: any) {
|
|
|
- steps.value = [
|
|
|
+ const list: any[] = [
|
|
|
{
|
|
|
title: '创建申请',
|
|
|
- description: `创建时间:${data.create_datetime ? dayjs(data.create_datetime).format('YYYY-MM-DD HH:mm:ss') : ''}`,
|
|
|
- status: 'finish'
|
|
|
+ description: `创建时间:${
|
|
|
+ data.create_datetime
|
|
|
+ ? dayjs(data.create_datetime).format('YYYY-MM-DD HH:mm:ss')
|
|
|
+ : ''
|
|
|
+ }`,
|
|
|
+ status: 'finish',
|
|
|
},
|
|
|
- {
|
|
|
- title: '待审批',
|
|
|
- description: `待审批人:${getPendingApproverDisplay(data)} 审批`,
|
|
|
- status: data.status >= 2 ? 'finish' : 'process'
|
|
|
- }
|
|
|
];
|
|
|
|
|
|
- const approverinfo = data.approver_info ?? data.admin_approver_info
|
|
|
+ if (data.status === 3) {
|
|
|
+ const rejectNames = data.approval_records
|
|
|
+ ?.filter((item: any) => item.status === 2)
|
|
|
+ .map(
|
|
|
+ (item: any) =>
|
|
|
+ item.approver_name || item.app_user_approver_name || item.name
|
|
|
+ )
|
|
|
+ .filter((name: any) => name && name.trim());
|
|
|
+ const rejectReason = data.approval_records
|
|
|
+ ?.filter((item: any) => item.status === 2)
|
|
|
+ .map((item: any) => item.approve_remark)
|
|
|
+ .filter((reason: any) => reason && reason.trim());
|
|
|
+ const rejectTime = data.approval_records
|
|
|
+ ?.filter((item: any) => item.status === 2)
|
|
|
+ .map((item: any) => item.approve_time)
|
|
|
+ .filter((time: any) => time && time.trim());
|
|
|
+ list.push({
|
|
|
+ title: '审批拒绝',
|
|
|
+ description: `审批人:${(rejectNames || []).join('、')},拒绝原因: ${(rejectReason || []).join('、')},时间:${(rejectTime || []).join('、')}`,
|
|
|
+ status: 'error',
|
|
|
+ });
|
|
|
+ steps.value = list;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
+ const isClassroomOrSpecial =
|
|
|
+ data.borrow_type === 1 || data.borrow_type === 2;
|
|
|
+ if (isClassroomOrSpecial) {
|
|
|
+ if (data.status === 1) {
|
|
|
+ list.push({
|
|
|
+ title: '审批通过',
|
|
|
+ description: `待审批人:${getPendingApproverDisplay(data)} 审批`,
|
|
|
+ status: 'process',
|
|
|
+ });
|
|
|
+ } else if (data.status >= 2) {
|
|
|
+ const approved = (data.approval_records || [])
|
|
|
+ .filter((r: any) => r.status === 1)
|
|
|
+ .sort(
|
|
|
+ (a: any, b: any) => (a.step_order ?? 0) - (b.step_order ?? 0)
|
|
|
+ );
|
|
|
+ const last = approved[approved.length - 1];
|
|
|
+ const nameStr = approved.length
|
|
|
+ ? approved
|
|
|
+ .map(
|
|
|
+ (r: any) => r.approver_name || r.app_user_approver_name
|
|
|
+ )
|
|
|
+ .filter((n: string) => n && String(n).trim())
|
|
|
+ .join('、') || '-'
|
|
|
+ : '-';
|
|
|
+ const tRaw = last
|
|
|
+ ? last.approve_time != null
|
|
|
+ ? last.approve_time
|
|
|
+ : last.create_datetime
|
|
|
+ : null;
|
|
|
+ list.push({
|
|
|
+ title: '审批通过',
|
|
|
+ description: `审批人: ${nameStr}, 时间: ${formatApprovalRecordTime(tRaw) || ''}`,
|
|
|
+ status: 'finish',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (data.status >= 2 && data.status !== 3) {
|
|
|
+ list.push({
|
|
|
+ title: '流程完成',
|
|
|
+ description: '流程已结束',
|
|
|
+ status: 'finish',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ steps.value = list;
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- if (data.status >= 2&&data.status!=3 && data.borrow_type!=1) {
|
|
|
- /* // 将审批记录倒序排列
|
|
|
- const reversedApprovalRecords = [...data.approval_records]
|
|
|
- reversedApprovalRecords.forEach((item:any,index:number) => {
|
|
|
- if(item.status === 1){
|
|
|
- if(index == 1){
|
|
|
- steps.value.push({
|
|
|
+ const admin = data.admin_approver_info;
|
|
|
+ const allCfg =
|
|
|
+ admin?.all_steps_status && admin.all_steps_status.length
|
|
|
+ ? [...admin.all_steps_status].sort(
|
|
|
+ (a: any, b: any) => (a.step_order ?? 0) - (b.step_order ?? 0)
|
|
|
+ )
|
|
|
+ : null;
|
|
|
+
|
|
|
+ if (allCfg) {
|
|
|
+ const approvedOnly = (data.approval_records || [])
|
|
|
+ .filter((r: any) => r.status === 1)
|
|
|
+ .sort(
|
|
|
+ (a: any, b: any) => (a.step_order ?? 0) - (b.step_order ?? 0)
|
|
|
+ );
|
|
|
+ const maxPassedOrder = approvedOnly.length
|
|
|
+ ? Math.max(
|
|
|
+ ...approvedOnly.map(
|
|
|
+ (r: any) => (r.step_order != null ? Number(r.step_order) : 0)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ : -1;
|
|
|
+
|
|
|
+ let hasPendingInWorkflow = false;
|
|
|
+ for (const step of allCfg) {
|
|
|
+ const rec = findApprovedRecordForWorkflowStep(
|
|
|
+ step,
|
|
|
+ approvedOnly,
|
|
|
+ allCfg
|
|
|
+ );
|
|
|
+ const done = !!rec || isAllStepsStatusApprovedStep(step);
|
|
|
+ if (done) {
|
|
|
+ const name =
|
|
|
+ (rec as any)?.approver_name ||
|
|
|
+ (rec as any)?.app_user_approver_name ||
|
|
|
+ '';
|
|
|
+ const tRaw =
|
|
|
+ (rec as any)?.approve_time != null
|
|
|
+ ? (rec as any).approve_time
|
|
|
+ : (rec as any)?.create_datetime;
|
|
|
+ const isLastInChain =
|
|
|
+ rec &&
|
|
|
+ (rec as any).step_order != null &&
|
|
|
+ Number((rec as any).step_order) === maxPassedOrder;
|
|
|
+ const warehouseInfo =
|
|
|
+ data.status >= 2 &&
|
|
|
+ data.status !== 3 &&
|
|
|
+ isLastInChain &&
|
|
|
+ isPickupWarehouseStep(step, rec)
|
|
|
+ ? `, 领取仓库:${getWarehouseName(data.warehouse) || '暂无仓库'}`
|
|
|
+ : '';
|
|
|
+ // 与课堂/特殊借用、查看效果图一致:已通过节点统一展示「审批通过」
|
|
|
+ list.push({
|
|
|
title: '审批通过',
|
|
|
- description: `审批人:${item.app_user_approver_name},时 间:${item.approve_time}`,
|
|
|
- status: 'finish'
|
|
|
- });
|
|
|
- }else{
|
|
|
- steps.value.push({
|
|
|
- title: '审批通过',
|
|
|
- description: `审批人:${item.approver_name},时 间:${item.create_datetime},领取仓库:${getWarehouseName(data.warehouse)||'暂无仓库'}`,
|
|
|
- status: 'finish'
|
|
|
- });
|
|
|
- }
|
|
|
+ description: `审批人: ${name || '-'}, 时间: ${formatApprovalRecordTime(tRaw) || ''}${warehouseInfo}`,
|
|
|
+ status: 'finish',
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ hasPendingInWorkflow = true;
|
|
|
+ const names = getApproversTextForNode(step) || getPendingApproverDisplay(data);
|
|
|
+ list.push({
|
|
|
+ title: '待审批',
|
|
|
+ description: `待审批人:${names} 审批`,
|
|
|
+ status: 'process',
|
|
|
+ });
|
|
|
+ break;
|
|
|
}
|
|
|
- }); */
|
|
|
- // 将审批记录倒序排列
|
|
|
- const reversedApprovalRecords = [...data.approval_records]
|
|
|
- // 先找出所有审批通过的记录
|
|
|
- const approvedRecords = reversedApprovalRecords.filter((item:any) => item.status === 1)
|
|
|
- const lastApprovedIndex = approvedRecords.length - 1
|
|
|
-
|
|
|
- reversedApprovalRecords.forEach((item:any,index:number) => {
|
|
|
- if(item.status === 1){
|
|
|
- // 找到当前记录在审批通过记录中的索引
|
|
|
- const currentApprovedIndex = approvedRecords.findIndex((record:any) => record === item)
|
|
|
- // 判断是否是最后一个审批通过的记录
|
|
|
- const isLastApproved = currentApprovedIndex === lastApprovedIndex
|
|
|
-
|
|
|
- /* if(index == 1){1
|
|
|
- steps.value.push({
|
|
|
- title: '审批通过',
|
|
|
- description: `审批人:${item.approver_name||item.app_user_approver_name},时 间:${item.approve_time}`,
|
|
|
- status: 'finish'
|
|
|
- });
|
|
|
- }else{ */
|
|
|
- // 只在最后一个审批通过的记录中显示领取仓库
|
|
|
- const warehouseInfo = isLastApproved ? `,领取仓库:${getWarehouseName(data.warehouse)||'暂无仓库'}` : ''
|
|
|
- steps.value.push({
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ !hasPendingInWorkflow &&
|
|
|
+ data.status >= 2 &&
|
|
|
+ data.status !== 3
|
|
|
+ ) {
|
|
|
+ list.push({
|
|
|
+ title: '流程完成',
|
|
|
+ description: '流程已结束',
|
|
|
+ status: 'finish',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (data.status === 1) {
|
|
|
+ list.push({
|
|
|
+ title: '待审批',
|
|
|
+ description: `待审批人:${getPendingApproverDisplay(data)} 审批`,
|
|
|
+ status: 'process',
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (data.status >= 2 && data.status !== 3) {
|
|
|
+ const approvedRecords = (data.approval_records || [])
|
|
|
+ .filter((item: any) => item.status === 1)
|
|
|
+ .sort(
|
|
|
+ (a: any, b: any) => (a.step_order ?? 0) - (b.step_order ?? 0)
|
|
|
+ );
|
|
|
+ if (approvedRecords.length > 0) {
|
|
|
+ const lastI = approvedRecords.length - 1;
|
|
|
+ approvedRecords.forEach((item: any, idx: number) => {
|
|
|
+ const isLast = idx === lastI;
|
|
|
+ const wh =
|
|
|
+ isLast && isPickupWarehouseStep(null, item)
|
|
|
+ ? `, 领取仓库:${getWarehouseName(data.warehouse) || '暂无仓库'}`
|
|
|
+ : '';
|
|
|
+ list.push({
|
|
|
title: '审批通过',
|
|
|
- description: `审批人:${item.approver_name||item.app_user_approver_name},时 间:${item.create_datetime ? dayjs(item.create_datetime).format('YYYY-MM-DD HH:mm:ss') : ''}${warehouseInfo}`,
|
|
|
- status: 'finish'
|
|
|
+ description: `审批人: ${item.approver_name || item.app_user_approver_name || '-'}, 时间: ${formatApprovalRecordTime(
|
|
|
+ item.approve_time != null ? item.approve_time : item.create_datetime
|
|
|
+ )}${wh}`,
|
|
|
+ status: 'finish',
|
|
|
});
|
|
|
- /* } */
|
|
|
+ });
|
|
|
+ list.push({
|
|
|
+ title: '流程完成',
|
|
|
+ description: '流程已结束',
|
|
|
+ status: 'finish',
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
- } else if (data.status === 3) {
|
|
|
- // console.log("data.approver_name:::",data.approver_info.name)
|
|
|
- const rejectNames = data.approval_records
|
|
|
- .filter((item:any) => item.status === 2)
|
|
|
- .map((item:any) => item.approver_name || item.app_user_approver_name || item.name)
|
|
|
- .filter((name:any) => name && name.trim());
|
|
|
- const rejectReason = data.approval_records
|
|
|
- .filter((item:any) => item.status === 2)
|
|
|
- .map((item:any) => item.approve_remark)
|
|
|
- .filter((reason:any) => reason && reason.trim());
|
|
|
- const rejectTime = data.approval_records
|
|
|
- .filter((item:any) => item.status === 2)
|
|
|
- .map((item:any) => item.approve_time)
|
|
|
- .filter((time:any) => time && time.trim());
|
|
|
- steps.value.push({
|
|
|
- title: '审批拒绝',
|
|
|
- description: `审批人:${rejectNames.join('、')},拒绝原因: ${rejectReason.join('、')},时间:${rejectTime.join('、')}`,
|
|
|
- status: 'error'
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (data.status >= 4) {
|
|
|
- steps.value.push({
|
|
|
- title: '流程完成',
|
|
|
- description: '流程已结束',
|
|
|
- status: 'finish'
|
|
|
- });
|
|
|
- }
|
|
|
+ steps.value = list;
|
|
|
}
|
|
|
|
|
|
// const activeStep = ref(1);
|