|
|
@@ -1,13 +1,16 @@
|
|
1
|
1
|
<script setup lang="ts">
|
|
2
|
2
|
import { ref, onMounted, computed } from 'vue';
|
|
3
|
|
-import { useRoute, useRouter } from 'vue-router';
|
|
4
|
|
-import { ElCard, ElButton, ElDescriptions, ElDescriptionsItem, ElDivider, ElUpload, ElImage, ElInput, ElPageHeader } from 'element-plus';
|
|
|
3
|
+import { useRoute } from 'vue-router';
|
|
|
4
|
+import { ElButton, ElDescriptions, ElDescriptionsItem, ElUpload, ElInput, ElIcon, ElImageViewer } from 'element-plus';
|
|
5
|
5
|
import { ElMessage } from 'element-plus';
|
|
|
6
|
+import { Plus } from '@element-plus/icons-vue';
|
|
6
|
7
|
|
|
|
8
|
+import { downloadByUrl } from '#/utils/file/download';
|
|
|
9
|
+
|
|
|
10
|
+import { uploadApi } from '#/api/core/upload';
|
|
7
|
11
|
import { requestClient } from '#/api/request';
|
|
8
|
12
|
|
|
9
|
13
|
const route = useRoute();
|
|
10
|
|
-const router = useRouter();
|
|
11
|
14
|
const id = computed(() => route.params.id as string);
|
|
12
|
15
|
|
|
13
|
16
|
// 交接详情数据
|
|
|
@@ -16,6 +19,11 @@ const handoverDetail = ref<any>(null);
|
|
16
|
19
|
const loading = ref(true);
|
|
17
|
20
|
// 保存状态
|
|
18
|
21
|
const saving = ref(false);
|
|
|
22
|
+// 确认交接状态
|
|
|
23
|
+const confirming = ref(false);
|
|
|
24
|
+// 图片预览相关
|
|
|
25
|
+const previewVisible = ref(false);
|
|
|
26
|
+const previewUrl = ref('');
|
|
19
|
27
|
|
|
20
|
28
|
// 获取交接详情
|
|
21
|
29
|
const getHandoverDetail = async () => {
|
|
|
@@ -35,7 +43,7 @@ const getHandoverDetail = async () => {
|
|
35
|
43
|
const saveItem = async (item: any) => {
|
|
36
|
44
|
try {
|
|
37
|
45
|
saving.value = true;
|
|
38
|
|
- const response = await requestClient.put('/gasHandoverItems/items', {
|
|
|
46
|
+ await requestClient.put('/gasHandoverItems/items', {
|
|
39
|
47
|
id: item.id,
|
|
40
|
48
|
attachments: item.attachments,
|
|
41
|
49
|
photos: item.photos,
|
|
|
@@ -50,9 +58,135 @@ const saveItem = async (item: any) => {
|
|
50
|
58
|
}
|
|
51
|
59
|
};
|
|
52
|
60
|
|
|
53
|
|
-// 返回列表页
|
|
54
|
|
-const goBack = () => {
|
|
55
|
|
- router.push('/oilstation/connect');
|
|
|
61
|
+// 自定义上传方法
|
|
|
62
|
+const handleUpload = async (options: any, item: any, fieldName: string) => {
|
|
|
63
|
+ try {
|
|
|
64
|
+ const res = await uploadApi(options.file);
|
|
|
65
|
+ const fileName = res.originalFilename || res.newFileName || res.fileName;
|
|
|
66
|
+ const responseData = {
|
|
|
67
|
+ url: res.url,
|
|
|
68
|
+ name: fileName // 使用原始文件名作为显示名称
|
|
|
69
|
+ };
|
|
|
70
|
+
|
|
|
71
|
+ // 根据字段名设置对应的fileName
|
|
|
72
|
+ if (fieldName === 'photos') {
|
|
|
73
|
+ item.photos = item.photos ? `${item.photos},${res.fileName}` : res.fileName;
|
|
|
74
|
+ item.photosUrl = item.photosUrl ? `${item.photosUrl},${res.url}` : res.url;
|
|
|
75
|
+ } else if (fieldName === 'attachments') {
|
|
|
76
|
+ item.attachments = item.attachments ? `${item.attachments},${res.fileName}` : res.fileName;
|
|
|
77
|
+ item.attachmentsUrl = item.attachmentsUrl ? `${item.attachmentsUrl},${res.url}` : res.url;
|
|
|
78
|
+ }
|
|
|
79
|
+
|
|
|
80
|
+ options.onSuccess(responseData);
|
|
|
81
|
+ } catch (error) {
|
|
|
82
|
+ console.error('上传失败:', error);
|
|
|
83
|
+ options.onError(error);
|
|
|
84
|
+ }
|
|
|
85
|
+};
|
|
|
86
|
+
|
|
|
87
|
+// 删除文件处理
|
|
|
88
|
+const handleRemove = (file: any, fileList: any[], item: any, fieldName: string) => {
|
|
|
89
|
+ // 从字段值中移除对应的fileName
|
|
|
90
|
+ if (fieldName === 'photos' && item.photos) {
|
|
|
91
|
+ item.photos = item.photos.split(',').filter(fileName => fileName !== file.name).join(',');
|
|
|
92
|
+ item.photosUrl = item.photosUrl.split(',').filter(url => url !== file.url).join(',');
|
|
|
93
|
+ } else if (fieldName === 'attachments' && item.attachments) {
|
|
|
94
|
+ item.attachments = item.attachments.split(',').filter(fileName => fileName !== file.name).join(',');
|
|
|
95
|
+ item.attachmentsUrl = item.attachmentsUrl.split(',').filter(url => url !== file.url).join(',');
|
|
|
96
|
+ }
|
|
|
97
|
+ return true;
|
|
|
98
|
+};
|
|
|
99
|
+
|
|
|
100
|
+// 预览文件处理
|
|
|
101
|
+const handlePreview = (file: any) => {
|
|
|
102
|
+ // 判断是否是图片文件
|
|
|
103
|
+ const isImage = /\.(jpg|jpeg|png|gif|bmp)$/i.test(file.name);
|
|
|
104
|
+
|
|
|
105
|
+ if (isImage) {
|
|
|
106
|
+ // 图片预览
|
|
|
107
|
+ previewUrl.value = file.url;
|
|
|
108
|
+ previewVisible.value = true;
|
|
|
109
|
+ } else {
|
|
|
110
|
+ // 附件下载
|
|
|
111
|
+ downloadByUrl({
|
|
|
112
|
+ url: file.url,
|
|
|
113
|
+ fileName: file.name
|
|
|
114
|
+ });
|
|
|
115
|
+ }
|
|
|
116
|
+};
|
|
|
117
|
+
|
|
|
118
|
+// 生成文件列表
|
|
|
119
|
+const generateFileList = (item: any, fieldName: string) => {
|
|
|
120
|
+ const newData = [];
|
|
|
121
|
+ let urls, fileNames;
|
|
|
122
|
+
|
|
|
123
|
+ // 根据字段名获取对应的URL和文件名
|
|
|
124
|
+ if (fieldName === 'photos') {
|
|
|
125
|
+ urls = item.photosUrl;
|
|
|
126
|
+ fileNames = item.photos;
|
|
|
127
|
+ } else if (fieldName === 'attachments') {
|
|
|
128
|
+ urls = item.attachmentsUrl;
|
|
|
129
|
+ fileNames = item.attachments;
|
|
|
130
|
+ } else {
|
|
|
131
|
+ return newData;
|
|
|
132
|
+ }
|
|
|
133
|
+
|
|
|
134
|
+ // 处理URL
|
|
|
135
|
+ if (urls) {
|
|
|
136
|
+ if (Array.isArray(urls)) {
|
|
|
137
|
+ urls.forEach((url: string, index: number) => {
|
|
|
138
|
+ // 从 fileNames 中获取对应的文件名
|
|
|
139
|
+ const fileNameArray = fileNames ? fileNames.split(',') : [];
|
|
|
140
|
+ let fileName = fileNameArray[index] || '';
|
|
|
141
|
+
|
|
|
142
|
+ // 如果没有获取到文件名,从URL中提取
|
|
|
143
|
+ if (!fileName) {
|
|
|
144
|
+ fileName = url.split('/').pop()?.split('?')[0] || '';
|
|
|
145
|
+ }
|
|
|
146
|
+
|
|
|
147
|
+ newData.push({
|
|
|
148
|
+ url: url.includes('http') ? url : `/common/upload/${url}`,
|
|
|
149
|
+ name: fileName
|
|
|
150
|
+ });
|
|
|
151
|
+ });
|
|
|
152
|
+ } else if (typeof urls === 'string') {
|
|
|
153
|
+ // 处理字符串形式的URL
|
|
|
154
|
+ const urlArray = urls.split(',');
|
|
|
155
|
+ const fileNameArray = fileNames ? fileNames.split(',') : [];
|
|
|
156
|
+
|
|
|
157
|
+ urlArray.forEach((url: string, index: number) => {
|
|
|
158
|
+ let fileName = fileNameArray[index] || '';
|
|
|
159
|
+
|
|
|
160
|
+ // 如果没有获取到文件名,从URL中提取
|
|
|
161
|
+ if (!fileName) {
|
|
|
162
|
+ fileName = url.split('/').pop()?.split('?')[0] || '';
|
|
|
163
|
+ }
|
|
|
164
|
+
|
|
|
165
|
+ newData.push({
|
|
|
166
|
+ url: url.includes('http') ? url : `/common/upload/${url}`,
|
|
|
167
|
+ name: fileName
|
|
|
168
|
+ });
|
|
|
169
|
+ });
|
|
|
170
|
+ }
|
|
|
171
|
+ }
|
|
|
172
|
+
|
|
|
173
|
+ return newData;
|
|
|
174
|
+};
|
|
|
175
|
+
|
|
|
176
|
+// 确认交接
|
|
|
177
|
+const handleConfirmHandover = async () => {
|
|
|
178
|
+ try {
|
|
|
179
|
+ confirming.value = true;
|
|
|
180
|
+ await requestClient.put(`/gasHandoverMain/main/process/${handoverDetail.value.id}`);
|
|
|
181
|
+ ElMessage.success('确认交接成功');
|
|
|
182
|
+ // 重新获取交接详情,更新状态
|
|
|
183
|
+ await getHandoverDetail();
|
|
|
184
|
+ } catch (error) {
|
|
|
185
|
+ ElMessage.error('确认交接失败');
|
|
|
186
|
+ console.error('确认交接失败:', error);
|
|
|
187
|
+ } finally {
|
|
|
188
|
+ confirming.value = false;
|
|
|
189
|
+ }
|
|
56
|
190
|
};
|
|
57
|
191
|
|
|
58
|
192
|
// 初始化
|
|
|
@@ -63,135 +197,179 @@ onMounted(() => {
|
|
63
|
197
|
|
|
64
|
198
|
<template>
|
|
65
|
199
|
<div class="handover-process-container">
|
|
66
|
|
- <ElPageHeader @back="goBack" content="站长交接详情" />
|
|
|
200
|
+ <div class="flex items-center gap-4 jiayi_header">
|
|
|
201
|
+ <div style="width: 4px; height: 12px; background-color: #215acd"></div>
|
|
|
202
|
+ <span class="text-lg font-bold text-gray-800" style="font-size: 14px; font-weight: 600">
|
|
|
203
|
+ 站长交接详情
|
|
|
204
|
+ </span>
|
|
|
205
|
+ </div>
|
|
67
|
206
|
|
|
68
|
|
- <ElCard :loading="loading" class="mt-4">
|
|
69
|
|
- <!-- 基本信息 -->
|
|
70
|
|
- <ElDescriptions :column="2" border>
|
|
71
|
|
- <ElDescriptionsItem label="片区">{{ handoverDetail?.areaId }}</ElDescriptionsItem>
|
|
72
|
|
- <ElDescriptionsItem label="油站">{{ handoverDetail?.stationId }}</ElDescriptionsItem>
|
|
73
|
|
- <ElDescriptionsItem label="移交人">{{ handoverDetail?.transferPersonName }}</ElDescriptionsItem>
|
|
74
|
|
- <ElDescriptionsItem label="接收人">{{ handoverDetail?.receiver ? handoverDetail.receiver : '未指定' }}</ElDescriptionsItem>
|
|
75
|
|
- <ElDescriptionsItem label="监交人">{{ handoverDetail?.supervisorName }}</ElDescriptionsItem>
|
|
76
|
|
- <ElDescriptionsItem label="交接开始时间">{{ handoverDetail?.handoverStartTime }}</ElDescriptionsItem>
|
|
77
|
|
- <ElDescriptionsItem label="交接完成时间" :span="2">
|
|
78
|
|
- {{ handoverDetail?.handoverEndTime ? handoverDetail.handoverEndTime : '未完成' }}
|
|
79
|
|
- </ElDescriptionsItem>
|
|
80
|
|
- </ElDescriptions>
|
|
81
|
|
-
|
|
82
|
|
- <ElDivider />
|
|
83
|
|
-
|
|
84
|
|
- <!-- 交接项列表 -->
|
|
85
|
|
- <div v-if="handoverDetail?.gasHandoverItemsList && handoverDetail.gasHandoverItemsList.length > 0">
|
|
86
|
|
- <h3>交接事项</h3>
|
|
87
|
|
- <div v-for="item in handoverDetail.gasHandoverItemsList" :key="item.id" class="item-card mt-4">
|
|
88
|
|
- <ElCard :header="`${item.linkName} (${item.isMandatory === 1 ? '必做' : '可选'})`">
|
|
89
|
|
- <ElDescriptions :column="1" border>
|
|
90
|
|
- <ElDescriptionsItem label="交接事项">{{ item.handoverItem }}</ElDescriptionsItem>
|
|
91
|
|
- <ElDescriptionsItem label="建议时长">{{ item.suggestDuration }} 天</ElDescriptionsItem>
|
|
92
|
|
- <ElDescriptionsItem label="要求/指引">{{ item.requirementGuide }}</ElDescriptionsItem>
|
|
93
|
|
- <ElDescriptionsItem label="负责人">{{ item.principal ? item.principal : '未指定' }}</ElDescriptionsItem>
|
|
94
|
|
- </ElDescriptions>
|
|
95
|
|
-
|
|
96
|
|
- <!-- 文本内容 -->
|
|
97
|
|
- <div v-if="item.hasTextBox === 1" class="form-item mt-4">
|
|
98
|
|
- <label>文本内容:</label>
|
|
99
|
|
- <ElInput
|
|
100
|
|
- type="textarea"
|
|
101
|
|
- v-model="item.textContent"
|
|
102
|
|
- placeholder="请输入文本内容"
|
|
103
|
|
- :rows="4"
|
|
104
|
|
- class="w-full"
|
|
105
|
|
- />
|
|
106
|
|
- </div>
|
|
|
207
|
+ <!-- 基本信息 -->
|
|
|
208
|
+ <ElDescriptions :column="4" class="task-info">
|
|
|
209
|
+ <ElDescriptionsItem label="片区">{{ handoverDetail?.areaIdName }}</ElDescriptionsItem>
|
|
|
210
|
+ <ElDescriptionsItem label="油站">{{ handoverDetail?.stationName }}</ElDescriptionsItem>
|
|
|
211
|
+ <ElDescriptionsItem label="移交人">{{ handoverDetail?.transferPersonName }}</ElDescriptionsItem>
|
|
|
212
|
+ <ElDescriptionsItem label="接收人">{{ handoverDetail?.receiver || '未指定' }}</ElDescriptionsItem>
|
|
|
213
|
+ <ElDescriptionsItem label="监交人">{{ handoverDetail?.supervisorName }}</ElDescriptionsItem>
|
|
|
214
|
+ <ElDescriptionsItem label="交接开始时间">{{ handoverDetail?.handoverStartTime }}</ElDescriptionsItem>
|
|
|
215
|
+ <ElDescriptionsItem label="交接完成时间">
|
|
|
216
|
+ {{ handoverDetail?.handoverEndTime || '未完成' }}
|
|
|
217
|
+ </ElDescriptionsItem>
|
|
|
218
|
+ </ElDescriptions>
|
|
107
|
219
|
|
|
108
|
|
- <!-- 照片 -->
|
|
109
|
|
- <div v-if="item.hasPhoto === 1" class="form-item mt-4">
|
|
110
|
|
- <label>照片:</label>
|
|
111
|
|
- <div class="photo-upload">
|
|
112
|
|
- <ElUpload
|
|
113
|
|
- action=""
|
|
114
|
|
- :auto-upload="false"
|
|
115
|
|
- :show-file-list="false"
|
|
116
|
|
- @change="(file) => {
|
|
117
|
|
- // 这里需要实现照片上传逻辑
|
|
118
|
|
- console.log('照片上传:', file);
|
|
119
|
|
- }"
|
|
120
|
|
- >
|
|
121
|
|
- <ElButton type="primary">上传照片</ElButton>
|
|
122
|
|
- </ElUpload>
|
|
123
|
|
- <div v-if="item.photos" class="photo-list mt-2">
|
|
124
|
|
- <ElImage
|
|
125
|
|
- v-for="(photo, index) in item.photos.split(',')"
|
|
126
|
|
- :key="index"
|
|
127
|
|
- :src="photo"
|
|
128
|
|
- :preview-src-list="[photo]"
|
|
129
|
|
- fit="cover"
|
|
130
|
|
- class="photo-item"
|
|
131
|
|
- />
|
|
132
|
|
- </div>
|
|
133
|
|
- </div>
|
|
134
|
|
- </div>
|
|
|
220
|
+ <!-- 交接项列表 -->
|
|
|
221
|
+ <div v-if="handoverDetail?.gasHandoverItemsList && handoverDetail.gasHandoverItemsList.length > 0">
|
|
|
222
|
+ <div v-for="item in handoverDetail.gasHandoverItemsList" :key="item.id">
|
|
|
223
|
+ <div class="flex items-center gap-4">
|
|
|
224
|
+ <div style="width: 4px; height: 12px; background-color: #215acd"></div>
|
|
|
225
|
+ <span class="text-lg font-bold text-gray-800" style="font-size: 14px; font-weight: 600">
|
|
|
226
|
+ {{ item.linkName }}({{ item.isMandatory === 1 ? '必做' : '可选' }})
|
|
|
227
|
+ </span>
|
|
|
228
|
+ </div>
|
|
|
229
|
+
|
|
|
230
|
+ <ElDescriptions :column="4" class="task-info">
|
|
|
231
|
+ <ElDescriptionsItem label="交接事项">{{ item.handoverItem }}</ElDescriptionsItem>
|
|
|
232
|
+ <ElDescriptionsItem label="建议时长">{{ item.suggestDuration }} 天</ElDescriptionsItem>
|
|
|
233
|
+ <ElDescriptionsItem label="负责人">{{ item.principal || '未指定' }}</ElDescriptionsItem>
|
|
|
234
|
+ <ElDescriptionsItem label="要求/指引" :span="4">{{ item.requirementGuide }}</ElDescriptionsItem>
|
|
|
235
|
+ </ElDescriptions>
|
|
|
236
|
+
|
|
|
237
|
+ <div class="task-info">
|
|
|
238
|
+ <!-- 文本内容 -->
|
|
|
239
|
+ <div v-if="item.hasTextBox === 1" class="form-item">
|
|
|
240
|
+ <label>文本内容:</label>
|
|
|
241
|
+ <ElInput
|
|
|
242
|
+ type="textarea"
|
|
|
243
|
+ v-model="item.textContent"
|
|
|
244
|
+ placeholder="请输入文本内容"
|
|
|
245
|
+ :rows="4"
|
|
|
246
|
+ class="w-full"
|
|
|
247
|
+ />
|
|
|
248
|
+ </div>
|
|
135
|
249
|
|
|
136
|
|
- <!-- 附件 -->
|
|
137
|
|
- <div v-if="item.hasAttachment === 1" class="form-item mt-4">
|
|
138
|
|
- <label>附件:</label>
|
|
139
|
|
- <div class="attachment-upload">
|
|
140
|
|
- <ElUpload
|
|
141
|
|
- action=""
|
|
142
|
|
- :auto-upload="false"
|
|
143
|
|
- :show-file-list="false"
|
|
144
|
|
- @change="(file) => {
|
|
145
|
|
- // 这里需要实现附件上传逻辑
|
|
146
|
|
- console.log('附件上传:', file);
|
|
147
|
|
- }"
|
|
148
|
|
- >
|
|
149
|
|
- <ElButton type="primary">上传附件</ElButton>
|
|
150
|
|
- </ElUpload>
|
|
151
|
|
- <div v-if="item.attachments" class="attachment-list mt-2">
|
|
152
|
|
- <a
|
|
153
|
|
- v-for="(attachment, index) in item.attachments.split(',')"
|
|
154
|
|
- :key="index"
|
|
155
|
|
- :href="attachment"
|
|
156
|
|
- target="_blank"
|
|
157
|
|
- class="attachment-item"
|
|
158
|
|
- >
|
|
159
|
|
- {{ attachment.split('/').pop() }}
|
|
160
|
|
- </a>
|
|
|
250
|
+ <!-- 照片 -->
|
|
|
251
|
+ <div v-if="item.hasPhoto === 1" class="form-item">
|
|
|
252
|
+ <label>照片:</label>
|
|
|
253
|
+ <div class="photo-upload">
|
|
|
254
|
+ <ElUpload
|
|
|
255
|
+ action="#"
|
|
|
256
|
+ accept=".jpg,.jpeg,.png"
|
|
|
257
|
+ list-type="picture-card"
|
|
|
258
|
+ :auto-upload="true"
|
|
|
259
|
+ :http-request="(options) => handleUpload(options, item, 'photos')"
|
|
|
260
|
+ :on-remove="(file, fileList) => handleRemove(file, fileList, item, 'photos')"
|
|
|
261
|
+ :on-preview="handlePreview"
|
|
|
262
|
+ :file-list="generateFileList(item,'photos')"
|
|
|
263
|
+ >
|
|
|
264
|
+ <div v-if="handoverDetail && !handoverDetail.handoverEndTime">
|
|
|
265
|
+ <ElIcon class="el-upload__icon">
|
|
|
266
|
+ <Plus size="30" />
|
|
|
267
|
+ </ElIcon>
|
|
161
|
268
|
</div>
|
|
162
|
|
- </div>
|
|
|
269
|
+ </ElUpload>
|
|
163
|
270
|
</div>
|
|
|
271
|
+ </div>
|
|
164
|
272
|
|
|
165
|
|
- <!-- 保存按钮 -->
|
|
166
|
|
- <div class="item-actions mt-4">
|
|
167
|
|
- <ElButton type="primary" @click="saveItem(item)" :loading="saving">
|
|
168
|
|
- 保存
|
|
169
|
|
- </ElButton>
|
|
|
273
|
+ <!-- 附件 -->
|
|
|
274
|
+ <div v-if="item.hasAttachment === 1" class="form-item">
|
|
|
275
|
+ <label>附件:</label>
|
|
|
276
|
+ <div class="attachment-upload">
|
|
|
277
|
+ <ElUpload
|
|
|
278
|
+ action="#"
|
|
|
279
|
+ list-type="text"
|
|
|
280
|
+ :auto-upload="true"
|
|
|
281
|
+ :http-request="(options) => handleUpload(options, item, 'attachments')"
|
|
|
282
|
+ :on-remove="(file, fileList) => handleRemove(file, fileList, item, 'attachments')"
|
|
|
283
|
+ :on-preview="handlePreview"
|
|
|
284
|
+ :file-list="generateFileList(item ,'attachments')"
|
|
|
285
|
+ >
|
|
|
286
|
+ <ElButton type="primary" v-if="handoverDetail && !handoverDetail.handoverEndTime">
|
|
|
287
|
+ <ElIcon>
|
|
|
288
|
+ <Plus />
|
|
|
289
|
+ </ElIcon>
|
|
|
290
|
+ 上传附件
|
|
|
291
|
+ </ElButton>
|
|
|
292
|
+ </ElUpload>
|
|
170
|
293
|
</div>
|
|
171
|
|
- </ElCard>
|
|
|
294
|
+ </div>
|
|
|
295
|
+ </div>
|
|
|
296
|
+
|
|
|
297
|
+ <!-- 保存按钮 -->
|
|
|
298
|
+ <div class="item-actions" style="margin-right: 20px;" v-if="handoverDetail && !handoverDetail.handoverEndTime">
|
|
|
299
|
+ <ElButton type="primary" @click="saveItem(item)" :loading="saving">
|
|
|
300
|
+ 保存
|
|
|
301
|
+ </ElButton>
|
|
172
|
302
|
</div>
|
|
173
|
303
|
</div>
|
|
|
304
|
+ </div>
|
|
174
|
305
|
|
|
175
|
|
- <div v-else-if="!loading" class="no-data mt-4">
|
|
176
|
|
- 暂无交接事项
|
|
177
|
|
- </div>
|
|
178
|
|
- </ElCard>
|
|
|
306
|
+ <div v-else-if="!loading" class="no-data">
|
|
|
307
|
+ 暂无交接事项
|
|
|
308
|
+ </div>
|
|
|
309
|
+
|
|
|
310
|
+ <!-- 确认交接按钮 -->
|
|
|
311
|
+ <div v-if="handoverDetail && !handoverDetail.handoverEndTime" class="confirm-handover-btn">
|
|
|
312
|
+ <ElButton type="primary" size="large" @click="handleConfirmHandover" :loading="confirming">
|
|
|
313
|
+ 确认交接
|
|
|
314
|
+ </ElButton>
|
|
|
315
|
+ </div>
|
|
|
316
|
+
|
|
|
317
|
+ <!-- 图片预览组件 -->
|
|
|
318
|
+ <ElImageViewer
|
|
|
319
|
+ v-if="previewVisible"
|
|
|
320
|
+ :url-list="[previewUrl]"
|
|
|
321
|
+ @close="() => previewVisible = false"
|
|
|
322
|
+ />
|
|
179
|
323
|
</div>
|
|
180
|
324
|
</template>
|
|
181
|
325
|
|
|
182
|
326
|
<style scoped lang="scss">
|
|
183
|
|
-.handover-process-container {
|
|
184
|
|
- padding: 20px;
|
|
|
327
|
+.jiayi_header {
|
|
|
328
|
+ padding-top: 18px !important;
|
|
|
329
|
+ padding-bottom: 4px !important;
|
|
|
330
|
+ padding-left: 0px !important;
|
|
|
331
|
+ border-bottom: none !important;
|
|
185
|
332
|
}
|
|
186
|
333
|
|
|
187
|
|
-.item-card {
|
|
188
|
|
- margin-bottom: 20px;
|
|
|
334
|
+// 去掉描述列表的边框
|
|
|
335
|
+:deep(.el-descriptions) {
|
|
|
336
|
+ border: none !important;
|
|
|
337
|
+}
|
|
|
338
|
+
|
|
|
339
|
+// 去掉描述列表项的边框
|
|
|
340
|
+:deep(.el-descriptions__cell) {
|
|
|
341
|
+ border: none !important;
|
|
|
342
|
+}
|
|
|
343
|
+
|
|
|
344
|
+.task-info {
|
|
|
345
|
+ padding: 0px 15px 15px 15px;
|
|
|
346
|
+
|
|
|
347
|
+ :deep(.el-descriptions__label) {
|
|
|
348
|
+ font-size: 14px;
|
|
|
349
|
+ font-weight: 400;
|
|
|
350
|
+ color: var(--text-color-secondary);
|
|
|
351
|
+ }
|
|
|
352
|
+
|
|
|
353
|
+ :deep(.el-descriptions__content) {
|
|
|
354
|
+ font-size: 14px;
|
|
|
355
|
+ font-weight: 500;
|
|
|
356
|
+ color: var(--text-color-primary);
|
|
|
357
|
+ }
|
|
|
358
|
+
|
|
|
359
|
+ :deep(.el-descriptions__table) {
|
|
|
360
|
+ background: transparent !important;
|
|
|
361
|
+ }
|
|
|
362
|
+}
|
|
|
363
|
+
|
|
|
364
|
+.handover-process-container {
|
|
|
365
|
+ background: #ffffff;
|
|
|
366
|
+ margin: 15px;
|
|
189
|
367
|
}
|
|
190
|
368
|
|
|
191
|
369
|
.form-item {
|
|
192
|
370
|
margin-top: 20px;
|
|
193
|
371
|
margin-bottom: 20px;
|
|
194
|
|
-
|
|
|
372
|
+
|
|
195
|
373
|
label {
|
|
196
|
374
|
display: block;
|
|
197
|
375
|
margin-bottom: 8px;
|
|
|
@@ -204,35 +382,9 @@ onMounted(() => {
|
|
204
|
382
|
margin-top: 8px;
|
|
205
|
383
|
}
|
|
206
|
384
|
|
|
207
|
|
-.photo-list {
|
|
208
|
|
- display: flex;
|
|
209
|
|
- flex-wrap: wrap;
|
|
210
|
|
- gap: 10px;
|
|
211
|
|
-}
|
|
212
|
|
-
|
|
213
|
|
-.photo-item {
|
|
214
|
|
- width: 120px;
|
|
215
|
|
- height: 120px;
|
|
216
|
|
- border: 1px solid #e8e8e8;
|
|
217
|
|
- border-radius: 4px;
|
|
218
|
|
-}
|
|
219
|
|
-
|
|
220
|
|
-.attachment-list {
|
|
221
|
|
- margin-top: 10px;
|
|
222
|
|
-}
|
|
223
|
|
-
|
|
224
|
|
-.attachment-item {
|
|
225
|
|
- display: inline-block;
|
|
226
|
|
- margin-right: 10px;
|
|
227
|
|
- padding: 4px 8px;
|
|
228
|
|
- background-color: #f5f5f5;
|
|
229
|
|
- border-radius: 4px;
|
|
230
|
|
- text-decoration: none;
|
|
231
|
|
- color: #1890ff;
|
|
232
|
|
-}
|
|
233
|
|
-
|
|
234
|
385
|
.item-actions {
|
|
235
|
386
|
margin-top: 20px;
|
|
|
387
|
+ margin-bottom: 20px;
|
|
236
|
388
|
text-align: right;
|
|
237
|
389
|
}
|
|
238
|
390
|
|
|
|
@@ -242,11 +394,10 @@ onMounted(() => {
|
|
242
|
394
|
color: #999;
|
|
243
|
395
|
}
|
|
244
|
396
|
|
|
245
|
|
-.mt-2 {
|
|
246
|
|
- margin-top: 8px;
|
|
247
|
|
-}
|
|
248
|
|
-
|
|
249
|
|
-.mt-4 {
|
|
250
|
|
- margin-top: 16px;
|
|
|
397
|
+.confirm-handover-btn {
|
|
|
398
|
+ margin-top: 40px;
|
|
|
399
|
+ margin-bottom: 20px;
|
|
|
400
|
+ padding-bottom: 20px;
|
|
|
401
|
+ text-align: center;
|
|
251
|
402
|
}
|
|
252
|
403
|
</style>
|