miaofuhao 1 月之前
父節點
當前提交
a452517059

+ 2 - 2
apps/web-ele/src/views/oilstation/idphoto/idphoto-data.tsx

@@ -4,7 +4,7 @@ import type { VxeGridProps } from '#/adapter/vxe-table';
4 4
 import { DictEnum } from '@vben/constants';
5 5
 
6 6
 import { stationInfoList } from '#/api/system/infoEntry/stationInfo/stationInfo';
7
-import { getSingleImageUploadConfig } from '#/components/upload';
7
+import { getSingleImageUploadConfig,getFileUploadConfig } from '#/components/upload';
8 8
 // import { uploadFile } from '#/api/upload';
9 9
 import { getDictOptions } from '#/utils/dict';
10 10
 import { renderDict } from '#/utils/render';
@@ -352,7 +352,7 @@ export const drawerFormSchema: FormSchemaGetter = () => [
352 352
     label: '证件扫描件',
353 353
     componentProps: (row: any) => {
354 354
       return {
355
-        ...getSingleImageUploadConfig(),
355
+        ...getFileUploadConfig('.pdf,.docx,.doc,.txt', 'text', 1, '/common/upload'),
356 356
         onSuccess: (res: any) => {
357 357
           if (res.code === 200) {
358 358
             row.certificateScanPath = res.data.fileName;

+ 3 - 3
apps/web-ele/src/views/workflow/components/actions/flow-actions.vue

@@ -111,7 +111,7 @@ const approveDelayFormData = reactive({
111 111
 
112 112
 // 编辑
113 113
 const handleEdit = () => {
114
-  drawerId.value = props.task!.id;
114
+  drawerId.value = props.workOrderDetail!.id;
115 115
   drawerVisible.value = true;
116 116
 };
117 117
 
@@ -208,7 +208,7 @@ function handleRemove() {
208 208
     center: true,
209 209
   })
210 210
     .then(async () => {
211
-      await deleteOrder([props.task!.id]);
211
+      await deleteOrder([props.workOrderDetail!.id]);
212 212
       emit('reload');
213 213
     })
214 214
     .catch(() => {
@@ -226,7 +226,7 @@ async function handleSubmit() {
226 226
       type: 'warning',
227 227
       center: true,
228 228
     });
229
-    await submitOrder(props.task!.id);
229
+    await submitOrder(props.workOrderDetail!.id);
230 230
     emit('reload');
231 231
   } catch {
232 232
     // 用户取消操作,不做任何处理

+ 51 - 45
apps/web-ele/src/views/workflow/components/approval-card.vue

@@ -31,32 +31,40 @@ function handleClick() {
31 31
 }
32 32
 
33 33
 const diffUpdateTimeString = computed(() => {
34
-  return getDiffTimeString(props.info.updateTime);
34
+  return getDiffTimeString(props.info.updateTime || props.info.createTime);
35 35
 });
36 36
 
37
-// 以下函数不再使用,已删除
38
-// // 处理数字类型的状态显示
39
-// function renderStatusNumber(status: number) {
40
-//   const statusMap = {
41
-//     0: { label: '待处理', color: 'warning' },
42
-//     1: { label: '处理中', color: 'info' },
43
-//     2: { label: '已处理', color: 'success' },
44
-//     3: { label: '已退回', color: 'danger' },
45
-//   };
46
-//   
47
-//   const statusInfo = statusMap[status as keyof typeof statusMap] || { label: '未知状态', color: 'default' };
48
-//   return <ElTag color={statusInfo.color}>{statusInfo.label}</ElTag>;
49
-// }
50
-
51
-// // 根据status类型选择渲染方式
52
-// function renderStatus() {
53
-//   const status = props.info.status;
54
-//   if (typeof status === 'number') {
55
-//     return renderStatusNumber(status);
56
-//   } else {
57
-//     return renderDict(status as string, DictEnum.TICKET_STATUS);
58
-//   }
59
-// }
37
+// 处理数字类型的状态显示
38
+function renderStatusNumber(status: number) {
39
+  const statusMap = {
40
+    0: { label: '待处理', type: 'warning' },
41
+    1: { label: '处理中', type: 'info' },
42
+    2: { label: '已处理', type: 'success' },
43
+    3: { label: '已退回', type: 'danger' },
44
+  };
45
+  
46
+  const statusInfo = statusMap[status as keyof typeof statusMap] || { label: '未知状态', type: 'default' };
47
+  return {
48
+    label: statusInfo.label,
49
+    type: statusInfo.type
50
+  };
51
+}
52
+
53
+// 处理数字类型的审批状态显示
54
+function renderApproveStatusNumber(approveStatus: number) {
55
+  const statusMap = {
56
+    0: { label: '未审批', type: 'info' },
57
+    1: { label: '已同意', type: 'success' },
58
+    2: { label: '已拒绝', type: 'danger' },
59
+    3: { label: '已废除', type: 'warning' },
60
+  };
61
+  
62
+  const statusInfo = statusMap[approveStatus as keyof typeof statusMap] || { label: '未知状态', type: 'default' };
63
+  return {
64
+    label: statusInfo.label,
65
+    type: statusInfo.type
66
+  };
67
+}
60 68
 </script>
61 69
 
62 70
 <template>
@@ -73,28 +81,26 @@ const diffUpdateTimeString = computed(() => {
73 81
       size="large"
74 82
     >
75 83
       <template #extra>
76
-        <!-- 根据status的类型选择不同的渲染方式 -->
77
-        <template v-if="typeof info.status === 'number'">
78
-          <ElTag
79
-            :color="{
80
-              0: 'warning',
81
-              1: 'info',
82
-              2: 'success',
83
-              3: 'danger'
84
-            }[info.status] || 'default'"
85
-          >
86
-            {{ {
87
-              0: '待处理',
88
-              1: '处理中',
89
-              2: '已处理',
90
-              3: '已退回'
91
-            }[info.status] || '未知状态' }}
92
-          </ElTag>
93
-        </template>
94
-        <component v-else :is="renderDict(info.status, DictEnum.TICKET_STATUS)" />
84
+        <div class="flex gap-2">
85
+          <!-- 根据status的类型选择不同的渲染方式 -->
86
+          <template v-if="typeof info.status === 'number'">
87
+            <ElTag :type="renderStatusNumber(info.status).type">
88
+              {{ renderStatusNumber(info.status).label }}
89
+            </ElTag>
90
+          </template>
91
+          <component v-else :is="renderDict(info.status, DictEnum.TICKET_STATUS)" />
92
+          
93
+          <!-- 显示审批状态 -->
94
+          <template v-if="typeof info.approveStatus === 'number'">
95
+            <ElTag :type="renderApproveStatusNumber(info.approveStatus).type">
96
+              {{ renderApproveStatusNumber(info.approveStatus).label }}
97
+            </ElTag>
98
+          </template>
99
+          <component v-else-if="info.approveStatus" :is="renderDict(info.approveStatus, DictEnum.TICKET_STATUS)" />
100
+        </div>
95 101
       </template>
96 102
       <ElDescriptionsItem>
97
-        <div class="font-bold">{{ info.content }}</div>
103
+        <div class="font-bold">{{ info.content || info.delayReason }}</div>
98 104
       </ElDescriptionsItem>
99 105
       <ElDescriptionsItem label="提交时间">
100 106
         {{ info.createTime }}
@@ -115,7 +121,7 @@ const diffUpdateTimeString = computed(() => {
115 121
         </span>
116 122
       </div>
117 123
       <div class="text-nowrap opacity-50">
118
-        <ElTooltip placement="top" :content="`更新时间: ${info.updateTime}`">
124
+        <ElTooltip placement="top" :content="`更新时间: ${info.updateTime || info.createTime}`">
119 125
           <div class="flex items-center gap-1">
120 126
             <span class="icon-[mdi--clock-outline] size-[16px]"></span>
121 127
             <span>{{ diffUpdateTimeString }}前更新</span>

+ 130 - 34
apps/web-ele/src/views/workflow/components/approval-timeline-item.vue

@@ -1,15 +1,14 @@
1 1
 <script setup lang="ts">
2 2
 import type { Flow } from '#/api/workflow/instance/model';
3 3
 
4
-import { computed, onMounted, ref } from 'vue';
4
+import { computed, ref } from 'vue';
5 5
 
6 6
 import { VbenAvatar } from '@vben/common-ui';
7 7
 import { DictEnum } from '@vben/constants';
8 8
 import { cn } from '@vben/utils';
9 9
 
10
-import { Message, User } from '@element-plus/icons-vue';
11
-import { ElAvatar, ElTimelineItem } from 'element-plus';
12
-// import { ossInfo } from '#/api/system/oss';
10
+import { Message, User, Timer, Document } from '@element-plus/icons-vue';
11
+import { ElAvatar, ElTimelineItem, ElTag } from 'element-plus';
13 12
 import { renderDict } from '#/utils/render';
14 13
 
15 14
 defineOptions({
@@ -19,7 +18,6 @@ defineOptions({
19 18
 const props = defineProps<{ item: Flow }>();
20 19
 
21 20
 interface AttachmentInfo {
22
-  ossId: string;
23 21
   url: string;
24 22
   name: string;
25 23
 }
@@ -27,22 +25,43 @@ interface AttachmentInfo {
27 25
 /**
28 26
  * 处理附件信息
29 27
  */
30
-const attachmentInfo = ref<AttachmentInfo[]>([]);
31
-onMounted(async () => {
32
-  if (!props.item.ext) {
33
-    return null;
34
-  }
35
-  // const resp = await ossInfo(props.item.ext.split(','));
36
-  // attachmentInfo.value = resp.map((item) => ({
37
-  //   ossId: item.ossId,
38
-  //   url: item.url,
39
-  //   name: item.originalName,
40
-  // }));
28
+const processAttachments = computed(() => {
29
+  const records = props.item.workOrderProcessRecords?.[0];
30
+  if (!records?.attachments) return [];
31
+  const names = records.attachments.split(',');
32
+  const urls = records.attachmentsUrl || [];
33
+  return names.map((name, index) => ({
34
+    name,
35
+    url: urls[index] || ''
36
+  }));
37
+});
38
+
39
+const delayAttachments = computed(() => {
40
+  const delayData = props.item.workOrderDelay?.[0];
41
+  if (!delayData?.applyFile) return [];
42
+  const names = delayData.applyFile.split(',');
43
+  const urls = delayData.applyFileUrl || [];
44
+  return names.map((name, index) => ({
45
+    name,
46
+    url: urls[index] || ''
47
+  }));
41 48
 });
42 49
 
43 50
 const isMultiplePerson = computed(
44 51
   () => props.item.operatorName?.split(',').length > 1,
45 52
 );
53
+
54
+// 处理审批状态显示
55
+function renderApproveStatus(status: number) {
56
+  const statusMap = {
57
+    0: { label: '未审批', type: 'info' },
58
+    1: { label: '已同意', type: 'success' },
59
+    2: { label: '已拒绝', type: 'danger' },
60
+    3: { label: '已废除', type: 'warning' },
61
+  };
62
+  
63
+  return statusMap[status] || { label: '未知状态', type: 'default' };
64
+}
46 65
 </script>
47 66
 
48 67
 <template>
@@ -77,7 +96,7 @@ const isMultiplePerson = computed(
77 96
         <!-- 如果昵称中带, 这里的处理是不准确的 -->
78 97
         <div
79 98
           :class="cn('bg-foreground/5 flex items-center rounded-full', 'p-1')"
80
-          v-for="(name, index) in item.approveName.split(',')"
99
+          v-for="(name, index) in props.item.approveName.split(',')"
81 100
           :key="index">
82 101
           <span class="px-1">{{ name }}</span>
83 102
         </div>
@@ -85,29 +104,106 @@ const isMultiplePerson = computed(
85 104
       <div>{{ props.item.operatorName }}</div>
86 105
 
87 106
       <div>{{ props.item.operationTime }}</div>
107
+      
108
+      <!-- 处理工单内容 -->
109
+      <div v-if="props.item.operationType === 'PROCESS' && (props.item.workOrderProcessRecords?.[0]?.processContent || processAttachments.length > 0)" class="mt-2 rounded-lg border p-3">
110
+        <div v-if="props.item.workOrderProcessRecords?.[0]?.processContent" class="flex flex-wrap gap-2">
111
+          <div class="flex items-center gap-1 font-medium">
112
+            <el-icon :size="16"><Message /></el-icon>
113
+            <span>处理内容:</span>
114
+          </div>
115
+          <div class="text-foreground/75 break-all flex-1">{{ props.item.workOrderProcessRecords[0].processContent }}</div>
116
+        </div>
117
+        <div v-if="processAttachments.length > 0" class="mt-2 flex flex-wrap gap-2">
118
+          <div class="font-medium">附件:</div>
119
+          <div class="flex flex-wrap gap-2">
120
+            <a
121
+              v-for="(attachment, index) in processAttachments"
122
+              :key="index"
123
+              :href="attachment.url"
124
+              class="text-primary"
125
+              target="_blank"
126
+            >
127
+              <div class="flex items-center gap-1">
128
+                <span class="icon-[mingcute--attachment-line] size-[14px]"></span>
129
+                <span>{{ attachment.name }}</span>
130
+              </div>
131
+            </a>
132
+          </div>
133
+        </div>
134
+      </div>
135
+      
136
+      <!-- 申请延时内容 -->
137
+      <div v-else-if="props.item.operationType === 'APPLY_DELAY' && props.item.workOrderDelay?.[0] && (props.item.workOrderDelay[0].delayReason || props.item.workOrderDelay[0].delayDuration || delayAttachments.length > 0)" class="mt-2 rounded-lg border p-3">
138
+        <div v-if="props.item.workOrderDelay[0].delayReason" class="flex flex-wrap gap-2">
139
+          <div class="flex items-center gap-1 font-medium">
140
+            <el-icon :size="16"><Message /></el-icon>
141
+            <span>延时原因:</span>
142
+          </div>
143
+          <div class="text-foreground/75 break-all flex-1">{{ props.item.workOrderDelay[0].delayReason }}</div>
144
+        </div>
145
+        <div v-if="props.item.workOrderDelay[0].delayDuration" class="mt-2 flex flex-wrap gap-2">
146
+          <div class="flex items-center gap-1 font-medium">
147
+            <el-icon :size="16"><Timer /></el-icon>
148
+            <span>延时时长:</span>
149
+          </div>
150
+          <div class="text-foreground/75">{{ props.item.workOrderDelay[0].delayDuration }} 小时</div>
151
+        </div>
152
+        <div v-if="delayAttachments.length > 0" class="mt-2 flex flex-wrap gap-2">
153
+          <div class="font-medium">附件:</div>
154
+          <div class="flex flex-wrap gap-2">
155
+            <a
156
+              v-for="(attachment, index) in delayAttachments"
157
+              :key="index"
158
+              :href="attachment.url"
159
+              class="text-primary"
160
+              target="_blank"
161
+            >
162
+              <div class="flex items-center gap-1">
163
+                <span class="icon-[mingcute--attachment-line] size-[14px]"></span>
164
+                <span>{{ attachment.name }}</span>
165
+              </div>
166
+            </a>
167
+          </div>
168
+        </div>
169
+      </div>
170
+      
171
+      <!-- 审核延时内容 -->
172
+      <div v-else-if="props.item.operationType === 'AUDIT_DELAY' && props.item.workOrderDelay?.[0] && (props.item.workOrderDelay[0].approveRemark || props.item.workOrderDelay[0].approveStatus !== undefined || props.item.workOrderDelay[0].approveTime)" class="mt-2 rounded-lg border p-3">
173
+        <div v-if="props.item.workOrderDelay[0].approveRemark" class="flex flex-wrap gap-2">
174
+          <div class="flex items-center gap-1 font-medium">
175
+            <el-icon :size="16"><Message /></el-icon>
176
+            <span>审批意见:</span>
177
+          </div>
178
+          <div class="text-foreground/75 break-all flex-1">{{ props.item.workOrderDelay[0].approveRemark }}</div>
179
+        </div>
180
+        <div v-if="props.item.workOrderDelay[0].approveStatus !== undefined" class="mt-2 flex flex-wrap gap-2">
181
+          <div class="flex items-center gap-1 font-medium">
182
+            <el-icon :size="16"><User /></el-icon>
183
+            <span>审核状态:</span>
184
+          </div>
185
+          <ElTag :type="renderApproveStatus(props.item.workOrderDelay[0].approveStatus).type">
186
+            {{ renderApproveStatus(props.item.workOrderDelay[0].approveStatus).label }}
187
+          </ElTag>
188
+        </div>
189
+        <div v-if="props.item.workOrderDelay[0].approveTime" class="mt-2 flex flex-wrap gap-2">
190
+          <div class="flex items-center gap-1 font-medium">
191
+            <el-icon :size="16"><Timer /></el-icon>
192
+            <span>新截止时间:</span>
193
+          </div>
194
+          <div class="text-foreground/75">{{ props.item.workOrderDelay[0].approveTime }}</div>
195
+        </div>
196
+      </div>
197
+      
198
+      <!-- 原有消息内容 -->
88 199
       <div
89
-        v-if="props.item.message"
90
-        class="rounded-lg border px-3 py-1"
200
+        v-if="props.item.message && !['PROCESS', 'APPLY_DELAY', 'AUDIT_DELAY'].includes(props.item.operationType)"
201
+        class="mt-2 rounded-lg border px-3 py-1"
91 202
         :class="cn('flex gap-2')"
92 203
       >
93 204
         <Message />
94 205
         <div class="text-foreground/75 break-all">{{ props.item.message }}</div>
95 206
       </div>
96
-      <div v-if="attachmentInfo.length > 0" class="flex flex-wrap gap-2">
97
-        <!-- 这里下载的文件名不是原始文件名 -->
98
-        <a
99
-          v-for="attachment in attachmentInfo"
100
-          :key="attachment.ossId"
101
-          :href="attachment.url"
102
-          class="text-primary"
103
-          target="_blank"
104
-        >
105
-          <div class="flex items-center gap-1">
106
-            <span class="icon-[mingcute--attachment-line] size-[18px]"></span>
107
-            <span>{{ attachment.name }}</span>
108
-          </div>
109
-        </a>
110
-      </div>
111 207
     </div>
112 208
   </ElTimelineItem>
113 209
 </template>

+ 3 - 1
apps/web-ele/src/views/workflow/leave/leave-description.vue

@@ -64,7 +64,7 @@ function closePreview() {
64 64
 
65 65
 <template>
66 66
   <div class="rounded-[6px] border p-2">
67
-    <ElDescriptions v-if="props.workOrderDetail" :column="1">
67
+    <ElDescriptions v-if="props.workOrderDetail" :column="4" class="mb-2">
68 68
       <ElDescriptionsItem label="工单类型:">
69 69
         {{ props.workOrderDetail.ticketTypeName }}
70 70
       </ElDescriptionsItem>
@@ -77,6 +77,8 @@ function closePreview() {
77 77
       <ElDescriptionsItem label="联系电话:">
78 78
         {{ props.workOrderDetail.phone || '无' }}
79 79
       </ElDescriptionsItem>
80
+    </ElDescriptions>
81
+    <ElDescriptions v-if="props.workOrderDetail" :column="1">
80 82
       <ElDescriptionsItem label="提报内容:">
81 83
         {{ props.workOrderDetail.content || '无' }}
82 84
       </ElDescriptionsItem>

+ 3 - 8
apps/web-ele/src/views/workflow/processDefinition/index.vue

@@ -347,6 +347,7 @@ const [ProcessDefinitionDeployDrawerComponent, deployDrawerApi] = useVbenDrawer(
347 347
               <ElPopconfirm title="确认删除" @confirm="confirmEvent(row)">
348 348
                 <template #reference>
349 349
                   <ElButton
350
+                    v-if="!row.isPublish && row.useExpression === 'N'"
350 351
                     size="small"
351 352
                     type="danger"
352 353
                     plain
@@ -411,15 +412,9 @@ const [ProcessDefinitionDeployDrawerComponent, deployDrawerApi] = useVbenDrawer(
411 412
                   </ElButton>
412 413
                 </template>
413 414
               </ElPopconfirm>
414
-              <ElButton
415
-                size="small"
416
-                type="primary"
417
-                plain
418
-                @click="handleExportXml(row)"
419
-                v-access:code="['workflow:definition:export']"
420
-              >
415
+              <!-- <ElButton size="small" type="primary" plain @click="handleExportXml(row)" v-access:code="['workflow:definition:export']" >
421 416
                 导出流程
422
-              </ElButton>
417
+              </ElButton> -->
423 418
             </ElSpace>
424 419
           </template>
425 420
         </BasicTable>

+ 7 - 2
apps/web-ele/src/views/workflow/task/delayedReview.vue

@@ -194,8 +194,13 @@ const currentTaskButtonPermissions = computed(() => {
194 194
   }
195 195
   // 初始化权限对象
196 196
   const permissions: Record<string, boolean> = {};
197
-
198
-  permissions.approveDelay = true;
197
+  const button = currentTaskButtonData.value;
198
+  if (button) {
199
+    const buttonArray = button.split(',');
200
+    // 设置对应按钮的权限
201
+    permissions.approveDelay = buttonArray.includes('approve_delay');
202
+  }
203
+  console.log('currentTaskButtonPermissions', permissions);
199 204
   return permissions;
200 205
 });
201 206
 </script>