@lambo-design/workflow-approve 1.0.0-beta.9 → 1.0.0-beta.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,378 +1,839 @@
1
- <template>
2
- <div>
3
-
4
- <Timeline class="portrait-timeline">
5
- <TimelineItem v-for="(items,index) in itemList" :key="index" class="portrait-timeline-item">
6
- <template #dot>
7
- <div v-if="items[0].auditResult === '30' || items[0].auditResult === '80'" class="cicle" style="background-color: #005aff"></div>
8
- <div v-else-if="items[0].auditResult === '40' || items[0].auditResult === '50'" class="cicle" style="background-color: #ffcc66"></div>
9
- <div v-else-if="items[0].auditResult === '60'" class="cicle" style="background-color: #ed4014"></div>
10
- <div v-else class="cicle" style="background-color: #ff9900"></div>
11
- </template>
12
- <Collapse v-model="activeName" simple style="margin: -10px 0 0 -2px;border: none">
13
- <Panel :name="'panel' + index" hide-arrow>
14
- <span class="history-title"> {{ items[0].taskName }}</span>
15
- <template #content>
16
- <div v-for="(item, index) in items" :key="index">
17
- <div v-for="(itemListItem, itemListIndex) in item.auditName" :key="itemListIndex">
18
- <Card dis-hover
19
- class="portrait-card"
20
- :bordered="false">
21
- <List item-layout="vertical">
22
- <ListItem>
23
- <Row style="display: flex; align-items: center;">
24
- <!-- 左边:Avatar -->
25
- <Col>
26
- <avatar
27
- :class="portraitWidth >= 600 ? 'portrait-avatar-large' : 'portrait-avatar-small'"
28
- size="small">
29
- {{ getFirstName(itemListItem) }}</avatar>
30
- </Col>
31
- <!-- 右边:审批信息 -->
32
- <Col span="17">
33
- <Row>
34
- <tooltip>
35
- <span class="audit-name-style"> {{ itemListItem }}</span>
36
- <div slot="content" style="white-space: normal"> {{ itemListItem }}</div>
37
- </tooltip>
38
- <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
39
- type="vertical"/>
40
- <span v-if="item.auditOrganName"
41
- class="audit-name-style"> {{ item.auditOrganName[itemListIndex] }}</span>
42
- <span v-if="portraitWidth === 0 || portraitWidth >= 600" class="audit-date-style">
43
- {{ item.startDate }}{{ item.auditDate }}
44
- </span>
45
- </Row>
46
- <Row v-if="item.auditComment">
47
- <span class="audit-name-style">{{ item.auditComment }}</span>
48
- </Row>
49
- <Row v-if="portraitWidth < 600" class="portrait-audit-date-style">{{showDate(item)}}{{ item.startDate }}{{ item.auditDate }}</Row>
50
- <Row style="margin-top: 10px">
51
- <Col span="12">
52
- <span style="color: #005aff;; font-size: 13px;"
53
- v-if="item.auditResult === '30'">通过</span>
54
- <span style="color: #ed4014; font-size: 13px;"
55
- v-else-if="item.auditResult === '40'">驳回到上一节点</span>
56
- <span style="color: #ed4014; font-size: 13px;"
57
- v-else-if="item.auditResult === '50'">驳回到原点</span>
58
- <span style="color: #ed4014; font-size: 13px;"
59
- v-else-if="item.auditResult === '60'">撤回</span>
60
- <span style="color: #19be6b; font-size: 13px;"
61
- v-else-if="item.auditResult === '80'">跳转到指定节点</span>
62
- <span style="color: #19be6b; font-size: 13px;"
63
- v-else-if="item.auditResult === '90'">驳回到指定节点</span>
64
- <span style="color: #ff9900; font-size: 13px;" v-else>待审批</span>
65
- </Col>
66
- <Col span="12" style="text-align: right">
67
- <Button v-if="item.fileList && item.fileList.length > 0" size="small" type="primary" ghost class="urging" @click="openModal(item)">查看附件</Button>
68
- <Button v-if="displayPushButton && item.auditResult !== '30'&&item.auditResult !== '40'&&item.auditResult !== '50'&&item.auditResult !== '60'&&item.auditResult!=='80'&&item.auditResult!=='90'"
69
- size="small" type="primary" ghost class="urging"
70
- @click="pushHim(item,itemListItem,itemListIndex)">催一下
71
- </Button>
72
- </Col>
73
- </Row>
74
- </Col>
75
- </Row>
76
-
77
- </ListItem>
78
- </List>
79
- </Card>
80
- </div>
81
- </div>
82
- </template>
83
- </Panel>
84
- </Collapse>
85
- </TimelineItem>
86
- </Timeline>
87
-
88
- <Modal
89
- v-model="showModal"
90
- title="查看附件"
91
- >
92
- <Table border
93
- :columns="attachmentColumn"
94
- :data="fileList"
95
- >
96
- </Table>
97
- </Modal>
98
- <div v-if="0 < allGroupKeys.length">
99
- <div v-show="arrowShow" class="arrow">
100
- <a @click="arrowClick">
101
- <Icon type="ios-arrow-down"/>
102
- 展开显示更多
103
- </a>
104
- </div>
105
- <div v-show="!arrowShow" class="arrow">
106
- <a @click="arrowClick">
107
- <Icon type="ios-arrow-up"/>
108
- 收缩
109
- </a>
110
- </div>
111
- </div>
112
- <Modal title="查看附件" v-model="modalImg" fullscreen scrollable :mask="false">
113
- <img :src="image" v-if="modalImg" alt="" style="width: 100%">
114
- <div slot="footer">
115
- <Button type="primary" @click="modalImg = false">关闭</Button>
116
- </div>
117
- </Modal>
118
- <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
119
- <div ref="file"></div>
120
- </Modal>
121
- </div>
122
- </template>
123
-
124
- <script>
125
- import ajax from "@lambo-design/shared/utils/ajax";
126
- import { operateHref } from '@lambo-design/shared/utils/assist'
127
- import axios from 'axios';
128
- // 引入docx-preview插件
129
- let docx = require('docx-preview');
130
- export default {
131
- components: {},
132
- props: {
133
- list: {
134
- type: Array,
135
- default: () => []
136
- },
137
- applyId: {
138
- type: String,
139
- default: ""
140
- },
141
- donePage: {
142
- type: Boolean,
143
- default: false
144
- },
145
- //横竖版样式不同
146
- portraitWidth: {
147
- type: Number,
148
- default: 0
149
- },
150
- smartFlowServerContext: {
151
- type: String,
152
- default: '/api/smart-flow-server',
153
- },
154
- },
155
- data() {
156
- return {
157
- allGroupKeys: [],
158
- displayedList: [],
159
- arrowShow: true, // 控制加载更多按钮的显示
160
- activeName: 'panel0',
161
- modalDocx: false,
162
- setModals: {
163
- modals: []
164
- },
165
- showModal: false,
166
- fileList: [],
167
- modalImg: false,
168
- image: "",
169
- itemList: {},
170
- auditNameList: [],
171
- displayPushButton: false,
172
- }
173
- },
174
- computed: {
175
- attachmentColumn: function () {
176
- let column = [];
177
- column.push({title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left'});
178
- column.push({
179
- title: '附件名称', key: 'fileName', minWidth: 150, align: 'center', fixed: 'left',
180
- render(h, {row}) {
181
- const index = row.fileName.lastIndexOf(".");
182
- const fileName = row.fileName.substr(0, index)
183
- return h("span", fileName)
184
-
185
- }
186
- });
187
- column.push({
188
- title: '附件类型', width: 100, align: 'center', fixed: 'left',
189
- render: (h, {row}) => {
190
- const index = row.fileName.lastIndexOf(".");
191
- const fileType = row.fileName.substr(index + 1)
192
- return h("span", fileType)
193
- }
194
- });
195
-
196
- column.push({
197
- title: "操作", width: 160, align: 'center', tooltip: true,
198
- render: (h, {row}) => {
199
- const index = row.fileName.lastIndexOf(".");
200
- const fileType = row.fileName.substr(index + 1).toLowerCase()
201
- const typeList=['jpg','gif','png','docx']
202
- if (typeList.indexOf(fileType) !== -1) {
203
- return h("div", [
204
- operateHref(this, h, row, "下载", () => {
205
- this.getAttach(row);
206
- }, "primary"),
207
- operateHref(this, h, row, "预览", () => {
208
- this.preViewAttach(row);
209
- }, "primary")
210
- ]);
211
- } else {
212
- return h("div", [
213
- operateHref(this, h, row, "下载", () => {
214
- this.getAttach(row);
215
- }, "primary")
216
- ]);
217
- }
218
-
219
- }
220
-
221
- });
222
- return column;
223
- }
224
- },
225
- methods: {
226
- pushHim(item, auditName, index) {
227
- if (this.isDebouncing) {
228
- return;
229
- }
230
-
231
- this.isDebouncing = true;
232
- // 设置一个延时,例如 1 秒,之后重置防抖状态
233
- setTimeout(() => {
234
- this.isDebouncing = false;
235
- }, 2000);
236
-
237
- let self = this;
238
- let applyUserName = item.applyUser.split(":")[1];
239
- let params = {
240
- applyUserName: applyUserName,
241
- auditName: auditName,
242
- auditId: item.auditId[index],
243
- procName: item.procName,
244
- effectTime: item.startDate,
245
- expireTime: item.warningDate,
246
- };
247
- let url = self.smartFlowServerContext + "/manage/processTodo/sendMessage";
248
- ajax.post(url, params).then(function (resp) {
249
- console.log("message ", resp);
250
- if (resp.data.code == 200) {
251
- self.$Message.success("催办成功");
252
- } else {
253
- self.$Message.error("催办失败");
254
- }
255
- });
256
- },
257
- getAttach(row) {
258
- window.open(this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId, "_blank");
259
- },
260
- preViewAttach(row) {
261
- let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
262
- let regs = /\.(pdf)$/
263
- if (reg.test(row.fileName)) {
264
- let url = this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId;
265
- this.imgPreview(url);
266
- } else if (regs.test(row.fileName)) {
267
- window.open(this.smartFlowServerContext + "/manage/oss/file/getFileStream?fileId=" + row.fileId, "_blank");
268
- } else {
269
- this.modalDocx = true
270
- axios({
271
- method: 'get',
272
- responseType: 'blob', // 因为是流文件,所以要指定blob类型
273
- url: this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId// 一个word下载文件的接口
274
- }).then(({data}) => {
275
- docx.renderAsync(data, this.$refs.file, null, {
276
- className: "docx", //默认和文档样式类的类名/前缀
277
- inWrapper: true, //启用围绕文档内容呈现包装器
278
- ignoreWidth: false, //禁用页面的渲染宽度
279
- ignoreHeight: false, //禁用页面的渲染高度
280
- ignoreFonts: false, //禁用字体渲染
281
- breakPages: true, //在分页符上启用分页
282
- ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
283
- experimental: false, //启用实验功能(制表符停止计算)
284
- trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
285
- useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
286
- useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
287
- showChanges: false, //启用文档更改的实验渲染(插入/删除)
288
- debug: false, //启用额外的日志记录
289
- })
290
- }
291
- )
292
- }
293
- },
294
- //查看附件
295
- imgPreview: function (img) {
296
- this.modalImg = true
297
- this.image = img;
298
- },
299
- arrowClick() {
300
- if (this.itemList.length > 0) {
301
- if (this.arrowShow) {
302
- // 显示全部
303
- this.displayedList = this.itemList;
304
- this.arrowShow = false;
305
- } else {
306
- // 只显示两个
307
- this.displayedList = this.itemList.slice(0, 2);
308
- this.arrowShow = true;
309
- }
310
- }
311
- },
312
- openModal(item) {
313
- this.fileList = item.fileList
314
- this.showModal = true
315
- },
316
- getFirstName(item) {
317
- return item ? item[0] : ''
318
- },
319
- showDate(item) {
320
- if (item.auditResult){
321
- return '处理时间:'
322
- }
323
- return '接收时间:'
324
- }
325
- },
326
- mounted() {
327
- this.displayPushButton = this.donePage;
328
- this.itemList = this.list;
329
- if (this.itemList.length > 0) {
330
- this.displayedList = this.itemList.slice(0, 2);
331
- // 初始化modals
332
- this.setModals.modals = this.itemList.map(() => ({value: false}));
333
- this.activeName = 'panel0';
334
- }
335
- },
336
- watch: {
337
- list: function (newValue) {
338
- this.$nextTick(() => {
339
- this.itemList = newValue;
340
- if (this.itemList.length > 0) {
341
- this.displayedList = this.itemList.slice(0, 2);
342
- this.setModals.modals = this.itemList.map(() => ({value: false}));
343
- }
344
-
345
- });
346
- }
347
- }
348
-
349
-
350
- }
351
- </script>
352
-
353
- <style scoped>
354
- @import "../styles/css/index.less";
355
- /deep/ .docx {
356
- width: 100% !important;
357
- }
358
-
359
- /deep/ .ivu-timeline-item-tail {
360
- border-style: solid;
361
- border-left: none;
362
- border-color: #005aff;
363
- border-width: thin;
364
- }
365
-
366
- /deep/ .ivu-list-item {
367
- padding-bottom: 0 !important;
368
- }
369
-
370
- /deep/ .ivu-collapse-content-box {
371
- padding: 0 !important;
372
- }
373
-
374
- /deep/ .ivu-card-body {
375
- padding: 5px !important;
376
- }
377
-
378
- </style>
1
+ <template>
2
+ <div>
3
+ <!-- 添加排序和分组切换按钮 -->
4
+ <div class="history-controls" style="margin-bottom: 16px;">
5
+ <ButtonGroup>
6
+ <Button
7
+ :type="sortBy === 'time' ? 'primary' : 'default'"
8
+ size="small"
9
+ @click="toggleSortBy('time')">
10
+ <Icon type="md-time" />
11
+ 按时间排序
12
+ </Button>
13
+ <Button
14
+ :type="sortBy === 'node' ? 'primary' : 'default'"
15
+ size="small"
16
+ @click="toggleSortBy('node')">
17
+ <Icon type="md-git-network" />
18
+ 按节点分组
19
+ </Button>
20
+ </ButtonGroup>
21
+ </div>
22
+
23
+ <Timeline class="portrait-timeline">
24
+ <TimelineItem v-for="(items,index) in processedItemList" :key="index" class="portrait-timeline-item">
25
+ <template #dot>
26
+ <div class="cicle" :style="{backgroundColor: getTimelineDotColor(items[0].auditResult)}"></div>
27
+ </template>
28
+ <!-- 按时间排序时:不显示标题,自动展开 -->
29
+ <template v-if="sortBy === 'time'">
30
+ <!-- 检查是否有待审批记录 -->
31
+ <template v-if="items.some(item => isPendingAudit(item))">
32
+ <!-- 待审批的记录:使用折叠面板 -->
33
+ <Collapse v-model="pendingActiveName" simple style="margin: -10px 0 0 20px;border: none">
34
+ <Panel :name="'pending-panel' + index" hide-arrow>
35
+ <span class="pending-audit-title">
36
+ <Icon type="md-time" style="color: #ff9900; margin-right: 5px;" />
37
+ 待{{ handleName }}
38
+ </span>
39
+ <template #content>
40
+ <!-- 遍历所有待审批的记录 -->
41
+ <div v-for="(item, itemIndex) in items.filter(item => isPendingAudit(item))" :key="itemIndex">
42
+ <div v-for="(itemListItem, itemListIndex) in item.auditName" :key="itemListIndex">
43
+ <Card dis-hover
44
+ class="portrait-card portrait-card-time"
45
+ :bordered="false">
46
+ <List item-layout="vertical">
47
+ <ListItem>
48
+ <Row style="display: flex; align-items: center;">
49
+ <!-- 左边:Avatar -->
50
+ <Col>
51
+ <avatar
52
+ :class="portraitWidth >= 600 ? 'portrait-avatar-large' : 'portrait-avatar-small'"
53
+ size="small">
54
+ {{ getFirstName(itemListItem) }}</avatar>
55
+ </Col>
56
+ <!-- 右边:审批信息 -->
57
+ <Col span="17">
58
+ <Row>
59
+ <tooltip>
60
+ <span class="audit-name-style"> {{ itemListItem }}</span>
61
+ <div slot="content" style="white-space: normal"> {{ itemListItem }}</div>
62
+ </tooltip>
63
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
64
+ type="vertical"/>
65
+ <tooltip v-if="item.auditOrganName">
66
+ <span class="audit-name-style"> {{ item.auditOrganName[itemListIndex] }}</span>
67
+ <div slot="content" style="white-space: normal"> {{ item.auditOrganName[itemListIndex] }}</div>
68
+ </tooltip>
69
+ <span v-if="portraitWidth === 0 || portraitWidth >= 600" class="audit-date-style">
70
+ {{showDate(item)}}
71
+ </span>
72
+ </Row>
73
+ <Row v-if="item.auditComment">
74
+ <tooltip max-width="200px" placement="bottom-start">
75
+ <span class="audit-comment-style">{{ item.auditComment }}</span>
76
+ <div slot="content" style="white-space: normal"> {{ item.auditComment }}</div>
77
+ </tooltip>
78
+ </Row>
79
+ <Row v-if="portraitWidth < 600" class="portrait-audit-date-style">{{showDate(item)}}</Row>
80
+ <Row style="margin-top: 10px">
81
+ <Col span="12">
82
+ <span style="color: #ff9900; font-size: 13px;">{{ '待' + handleName }}</span>
83
+ </Col>
84
+ <Col span="12" style="text-align: right">
85
+ <Button v-if="item.fileList && item.fileList.length > 0" size="small" type="primary" ghost class="urging" @click="openModal(item)">查看附件</Button>
86
+ <Button v-if="displayPushButton"
87
+ size="small" type="primary" ghost class="urging" v-permission="'swf-work-hurry'"
88
+ @click="pushHim(item,itemListItem,itemListIndex)">催一下
89
+ </Button>
90
+ </Col>
91
+ </Row>
92
+ </Col>
93
+ </Row>
94
+ </ListItem>
95
+ </List>
96
+ </Card>
97
+ </div>
98
+ </div>
99
+ </template>
100
+ </Panel>
101
+ </Collapse>
102
+ </template>
103
+
104
+ <!-- 已审批的记录:直接显示 -->
105
+ <div v-for="(item, itemIndex) in items.filter(item => !isPendingAudit(item))" :key="'approved-' + itemIndex">
106
+ <div v-for="(itemListItem, itemListIndex) in item.auditName" :key="itemListIndex">
107
+ <Card dis-hover
108
+ class="portrait-card portrait-card-time"
109
+ :bordered="false">
110
+ <List item-layout="vertical">
111
+ <ListItem>
112
+ <Row style="display: flex; align-items: center;">
113
+ <!-- 左边:Avatar -->
114
+ <Col>
115
+ <avatar
116
+ :class="portraitWidth >= 600 ? 'portrait-avatar-large' : 'portrait-avatar-small'"
117
+ size="small">
118
+ {{ getFirstName(itemListItem) }}</avatar>
119
+ </Col>
120
+ <!-- 右边:审批信息 -->
121
+ <Col span="17">
122
+ <Row>
123
+ <tooltip>
124
+ <span class="audit-name-style"> {{ itemListItem }}</span>
125
+ <div slot="content" style="white-space: normal"> {{ itemListItem }}</div>
126
+ </tooltip>
127
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
128
+ type="vertical"/>
129
+ <tooltip v-if="item.auditOrganName">
130
+ <span class="audit-name-style"> {{ item.auditOrganName[itemListIndex] }}</span>
131
+ <div slot="content" style="white-space: normal"> {{ item.auditOrganName[itemListIndex] }}</div>
132
+ </tooltip>
133
+ <span v-if="portraitWidth === 0 || portraitWidth >= 600" class="audit-date-style">
134
+ {{showDate(item)}}
135
+ </span>
136
+ </Row>
137
+ <Row v-if="item.auditComment">
138
+ <tooltip max-width="200px" placement="bottom-start">
139
+ <span class="audit-comment-style">{{ item.auditComment }}</span>
140
+ <div slot="content" style="white-space: normal"> {{ item.auditComment }}</div>
141
+ </tooltip>
142
+ </Row>
143
+ <Row v-if="portraitWidth < 600" class="portrait-audit-date-style">{{showDate(item)}}</Row>
144
+ <Row style="margin-top: 10px">
145
+ <Col span="12">
146
+ <span style="color: #005aff;; font-size: 13px;"
147
+ v-if="item.auditResult === '00'">流程发起</span>
148
+ <span style="color: #005aff;; font-size: 13px;"
149
+ v-else-if="item.auditResult === '10'">自动跳过</span>
150
+ <span style="color: #005aff;; font-size: 13px;"
151
+ v-else-if="item.auditResult === '11'">与上一环节办理人相同自动跳过</span>
152
+ <span style="color: #005aff;; font-size: 13px;"
153
+ v-else-if="item.auditResult === '12'">与发起人相同自动跳过</span>
154
+ <span style="color: #005aff;; font-size: 13px;"
155
+ v-else-if="item.auditResult === '13'">办理人为空自动跳过</span>
156
+ <span style="color: #005aff;; font-size: 13px;"
157
+ v-else-if="item.auditResult === '14'">符合流程变量条件自动跳过</span>
158
+ <span style="color: #005aff;; font-size: 13px;"
159
+ v-else-if="item.auditResult === '30'">通过</span>
160
+ <span style="color: #ed4014; font-size: 13px;"
161
+ v-else-if="item.auditResult === '40'">{{item.rejectName ? item.rejectName : '驳回'}}上一节点</span>
162
+ <span style="color: #ed4014; font-size: 13px;"
163
+ v-else-if="item.auditResult === '50'">{{item.rejectName ? item.rejectName : '驳回'}}到原点</span>
164
+ <span style="color: #ed4014; font-size: 13px;"
165
+ v-else-if="item.auditResult === '51'">流程终止</span>
166
+ <span style="color: #ed4014; font-size: 13px;"
167
+ v-else-if="item.auditResult === '60'">撤回</span>
168
+ <span style="color: #005aff; font-size: 13px;"
169
+ v-else-if="item.auditResult === '61'">交回委派任务</span>
170
+ <span style="color: #ed4014; font-size: 13px;"
171
+ v-else-if="item.auditResult === '62'">委派任务被撤回</span>
172
+ <span style="color: #19be6b; font-size: 13px;"
173
+ v-else-if="item.auditResult === '80'">跳转指定节点</span>
174
+ <span style="color: #005aff; font-size: 13px;"
175
+ v-else-if="item.auditResult === '82'">指定他人处理</span>
176
+ <span style="color: #ed4014; font-size: 13px;"
177
+ v-else-if="item.auditResult === '83'">会签减签</span>
178
+ <span style="color: #ed4014; font-size: 13px;"
179
+ v-else-if="item.auditResult === '90'">{{item.rejectName ? item.rejectName : '驳回'}}指定节点</span>
180
+ </Col>
181
+ <Col span="12" style="text-align: right">
182
+ <Button v-if="item.fileList && item.fileList.length > 0" size="small" type="primary" ghost class="urging" @click="openModal(item)">查看附件</Button>
183
+ </Col>
184
+ </Row>
185
+ </Col>
186
+ </Row>
187
+ </ListItem>
188
+ </List>
189
+ </Card>
190
+ </div>
191
+ </div>
192
+ </template>
193
+
194
+ <!-- 按节点分组时:显示折叠面板 -->
195
+ <template v-else>
196
+ <Collapse v-model="activeName" simple style="margin: -10px 0 0 -2px;border: none">
197
+ <Panel :name="'panel' + index" hide-arrow>
198
+ <span class="history-title">{{ items[0].taskName }}</span>
199
+ <template #content>
200
+ <div v-for="(item, index) in items" :key="index">
201
+ <div v-for="(itemListItem, itemListIndex) in item.auditName" :key="itemListIndex">
202
+ <Card dis-hover
203
+ class="portrait-card"
204
+ :bordered="false">
205
+ <List item-layout="vertical">
206
+ <ListItem>
207
+ <Row style="display: flex; align-items: center;">
208
+ <!-- 左边:Avatar -->
209
+ <Col>
210
+ <avatar
211
+ :class="portraitWidth >= 600 ? 'portrait-avatar-large' : 'portrait-avatar-small'"
212
+ size="small">
213
+ {{ getFirstName(itemListItem) }}</avatar>
214
+ </Col>
215
+ <!-- 右边:审批信息 -->
216
+ <Col span="17">
217
+ <Row>
218
+ <tooltip>
219
+ <span class="audit-name-style"> {{ itemListItem }}</span>
220
+ <div slot="content" style="white-space: normal"> {{ itemListItem }}</div>
221
+ </tooltip>
222
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
223
+ type="vertical"/>
224
+ <tooltip v-if="item.auditOrganName">
225
+ <span class="audit-name-style"> {{ item.auditOrganName[itemListIndex] }}</span>
226
+ <div slot="content" style="white-space: normal"> {{ item.auditOrganName[itemListIndex] }}</div>
227
+ </tooltip>
228
+ <span v-if="portraitWidth === 0 || portraitWidth >= 600" class="audit-date-style">
229
+ {{showDate(item)}}
230
+ </span>
231
+ </Row>
232
+ <Row v-if="item.auditComment">
233
+ <tooltip max-width="200px" placement="bottom-start">
234
+ <span class="audit-comment-style">{{ item.auditComment }}</span>
235
+ <div slot="content" style="white-space: normal"> {{ item.auditComment }}</div>
236
+ </tooltip>
237
+ </Row>
238
+ <Row v-if="portraitWidth < 600" class="portrait-audit-date-style">{{showDate(item)}}</Row>
239
+ <Row style="margin-top: 10px">
240
+ <Col span="12">
241
+ <span style="color: #005aff;; font-size: 13px;"
242
+ v-if="item.auditResult === '00'">流程发起</span>
243
+ <span style="color: #005aff;; font-size: 13px;"
244
+ v-else-if="item.auditResult === '10'">自动跳过</span>
245
+ <span style="color: #005aff;; font-size: 13px;"
246
+ v-else-if="item.auditResult === '11'">与上一环节办理人相同自动跳过</span>
247
+ <span style="color: #005aff;; font-size: 13px;"
248
+ v-else-if="item.auditResult === '12'">与发起人相同自动跳过</span>
249
+ <span style="color: #005aff;; font-size: 13px;"
250
+ v-else-if="item.auditResult === '13'">办理人为空自动跳过</span>
251
+ <span style="color: #005aff;; font-size: 13px;"
252
+ v-else-if="item.auditResult === '14'">符合流程变量条件自动跳过</span>
253
+ <span style="color: #005aff;; font-size: 13px;"
254
+ v-else-if="item.auditResult === '30'">通过</span>
255
+ <span style="color: #ed4014; font-size: 13px;"
256
+ v-else-if="item.auditResult === '40'">{{item.rejectName ? item.rejectName : '驳回'}}上一节点</span>
257
+ <span style="color: #ed4014; font-size: 13px;"
258
+ v-else-if="item.auditResult === '50'">{{item.rejectName ? item.rejectName : '驳回'}}到原点</span>
259
+ <span style="color: #ed4014; font-size: 13px;"
260
+ v-else-if="item.auditResult === '51'">流程终止</span>
261
+ <span style="color: #ed4014; font-size: 13px;"
262
+ v-else-if="item.auditResult === '60'">撤回</span>
263
+ <span style="color: #005aff; font-size: 13px;"
264
+ v-else-if="item.auditResult === '61'">交回委派任务</span>
265
+ <span style="color: #ed4014; font-size: 13px;"
266
+ v-else-if="item.auditResult === '62'">委派任务被撤回</span>
267
+ <span style="color: #19be6b; font-size: 13px;"
268
+ v-else-if="item.auditResult === '80'">跳转指定节点</span>
269
+ <span style="color: #005aff; font-size: 13px;"
270
+ v-else-if="item.auditResult === '82'">指定他人处理</span>
271
+ <span style="color: #ed4014; font-size: 13px;"
272
+ v-else-if="item.auditResult === '83'">会签减签</span>
273
+ <span style="color: #ed4014; font-size: 13px;"
274
+ v-else-if="item.auditResult === '90'">{{item.rejectName ? item.rejectName : '驳回'}}指定节点</span>
275
+ <span style="color: #ff9900; font-size: 13px;" v-else>{{ '待' + handleName }}</span>
276
+ </Col>
277
+ <Col span="12" style="text-align: right">
278
+ <Button v-if="item.fileList && item.fileList.length > 0" size="small" type="primary" ghost class="urging" @click="openModal(item)">查看附件</Button>
279
+ <Button v-if="displayPushButton && !auditPassStatus.includes(item.auditResult) && item.auditResult !== '40'&&item.auditResult !== '50'&&item.auditResult !== '60'&&item.auditResult !== '62'&&item.auditResult!=='83'&&item.auditResult!=='90'"
280
+ size="small" type="primary" ghost class="urging" v-permission="'swf-work-hurry'"
281
+ @click="pushHim(item,itemListItem,itemListIndex)">催一下
282
+ </Button>
283
+ </Col>
284
+ </Row>
285
+ </Col>
286
+ </Row>
287
+
288
+ </ListItem>
289
+ </List>
290
+ </Card>
291
+ </div>
292
+ </div>
293
+ </template>
294
+ </Panel>
295
+ </Collapse>
296
+ </template>
297
+ </TimelineItem>
298
+ </Timeline>
299
+
300
+ <Modal
301
+ v-model="showModal"
302
+ title="查看附件"
303
+ >
304
+ <Table border
305
+ :columns="attachmentColumn"
306
+ :data="fileList"
307
+ >
308
+ </Table>
309
+ </Modal>
310
+ <div v-if="0 < allGroupKeys.length">
311
+ <div v-show="arrowShow" class="arrow">
312
+ <a @click="arrowClick">
313
+ <Icon type="ios-arrow-down"/>
314
+ 展开显示更多
315
+ </a>
316
+ </div>
317
+ <div v-show="!arrowShow" class="arrow">
318
+ <a @click="arrowClick">
319
+ <Icon type="ios-arrow-up"/>
320
+ 收缩
321
+ </a>
322
+ </div>
323
+ </div>
324
+ <Modal title="查看附件" v-model="modalImg" fullscreen scrollable :mask="false">
325
+ <img :src="image" v-if="modalImg" alt="" style="width: 100%">
326
+ <div slot="footer">
327
+ <Button type="primary" @click="modalImg = false">关闭</Button>
328
+ </div>
329
+ </Modal>
330
+ <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
331
+ <div ref="file"></div>
332
+ </Modal>
333
+ </div>
334
+ </template>
335
+
336
+ <script>
337
+ import ajax from "@lambo-design/shared/utils/ajax";
338
+ import { operateHref } from '@lambo-design/shared/utils/assist'
339
+ import axios from 'axios';
340
+ // 引入docx-preview插件
341
+ let docx = require('docx-preview');
342
+ export default {
343
+ components: {},
344
+ props: {
345
+ list: {
346
+ type: Array,
347
+ default: () => []
348
+ },
349
+ applyId: {
350
+ type: String,
351
+ default: ""
352
+ },
353
+ donePage: {
354
+ type: Boolean,
355
+ default: false
356
+ },
357
+ pushButton: {
358
+ type: Boolean,
359
+ default: true
360
+ },
361
+ handleName: {
362
+ type: String,
363
+ default: "审批"
364
+ },
365
+ //横竖版样式不同
366
+ portraitWidth: {
367
+ type: Number,
368
+ default: 400
369
+ },
370
+ smartFlowServerContext: {
371
+ type: String,
372
+ default: '/api/smart-flow-server',
373
+ },
374
+ },
375
+ data() {
376
+ return {
377
+ allGroupKeys: [],
378
+ displayedList: [],
379
+ arrowShow: true, // 控制加载更多按钮的显示
380
+ activeName: 'panel0',
381
+ modalDocx: false,
382
+ setModals: {
383
+ modals: []
384
+ },
385
+ auditPassStatus:['00', '10', '11', '12', '13', '14', '30', '40', '50', '51', '60', '61', '62', '80', '82', '83', '90'],
386
+ showModal: false,
387
+ fileList: [],
388
+ modalImg: false,
389
+ image: "",
390
+ itemList: [],
391
+ auditNameList: [],
392
+ displayPushButton: false,
393
+ sortBy: 'time',
394
+ pendingActiveName: [], // 控制待审批折叠面板的展开状态
395
+ }
396
+ },
397
+ computed: {
398
+ processedItemList() {
399
+ // 确保 itemList 存在且是数组
400
+ if (!this.itemList || !Array.isArray(this.itemList) || this.itemList.length === 0) {
401
+ return [];
402
+ }
403
+
404
+ if (this.sortBy === 'time') {
405
+ // 按时间排序:将所有审批记录平铺,按时间排序,然后重新分组
406
+ let allRecords = [];
407
+
408
+ // 平铺所有审批记录
409
+ this.itemList.forEach(nodeGroup => {
410
+ // 确保 nodeGroup 是数组
411
+ if (Array.isArray(nodeGroup)) {
412
+ nodeGroup.forEach(record => {
413
+ if (record && typeof record === 'object') {
414
+ // 获取准确的时间用于排序
415
+ let sortTime = this.getRecordTime(record);
416
+ let timestamp = new Date(sortTime).getTime();
417
+
418
+ // 验证时间戳是否有效
419
+ if (isNaN(timestamp)) {
420
+ console.warn('时间戳解析失败:', {
421
+ record: record,
422
+ sortTime: sortTime,
423
+ auditDate: record.auditDate,
424
+ createTime: record.createTime
425
+ });
426
+ // 使用当前时间作为后备
427
+ timestamp = new Date().getTime();
428
+ sortTime = new Date().toISOString();
429
+ }
430
+
431
+ allRecords.push({
432
+ record: record,
433
+ sortTime: sortTime,
434
+ timestamp: timestamp
435
+ });
436
+ }
437
+ });
438
+ }
439
+ });
440
+
441
+ // 调试信息:打印排序前的数据
442
+ console.log('排序前的记录:', allRecords.map(item => ({
443
+ auditResult: item.record.auditResult,
444
+ auditDate: item.record.auditDate,
445
+ createTime: item.record.createTime,
446
+ sortTime: item.sortTime,
447
+ timestamp: item.timestamp,
448
+ date: new Date(item.timestamp)
449
+ })));
450
+
451
+ // 按时间戳排序(倒序,最新在前)
452
+ allRecords.sort((a, b) => {
453
+ // 使用时间戳进行排序,避免字符串比较问题
454
+ return b.timestamp - a.timestamp;
455
+ });
456
+
457
+ // 调试信息:打印排序后的数据
458
+ console.log('排序后的记录:', allRecords.map(item => ({
459
+ auditResult: item.record.auditResult,
460
+ auditDate: item.record.auditDate,
461
+ createTime: item.record.createTime,
462
+ sortTime: item.sortTime,
463
+ timestamp: item.timestamp,
464
+ date: new Date(item.timestamp)
465
+ })));
466
+
467
+ // 重新分组:相同状态且时间相近的记录分为一组
468
+ let groupedRecords = [];
469
+ let currentGroup = [];
470
+
471
+ allRecords.forEach((item, index) => {
472
+ if (currentGroup.length === 0) {
473
+ // 第一个记录,直接加入
474
+ currentGroup.push(item.record);
475
+ } else {
476
+ // 检查是否应该与当前组合并
477
+ let shouldGroup = false;
478
+
479
+ // 如果都是待审批状态且是同一个节点,则分为一组
480
+ if (this.isPendingAudit(item.record) &&
481
+ currentGroup.some(r => this.isPendingAudit(r) && r.taskName === item.record.taskName)) {
482
+ shouldGroup = true;
483
+ }
484
+ // 如果都是已审批状态且时间非常接近(同一天或几分钟内),可以考虑分组,但通常按个人分组
485
+ else if (!this.isPendingAudit(item.record) &&
486
+ currentGroup.length === 1 &&
487
+ !this.isPendingAudit(currentGroup[0]) &&
488
+ currentGroup[0].taskName === item.record.taskName) {
489
+ // 暂时不分组已审批记录,每个人一组
490
+ shouldGroup = false;
491
+ }
492
+
493
+ if (shouldGroup) {
494
+ currentGroup.push(item.record);
495
+ } else {
496
+ // 开始新的分组
497
+ if (currentGroup.length > 0) {
498
+ groupedRecords.push([...currentGroup]);
499
+ }
500
+ currentGroup = [item.record];
501
+ }
502
+ }
503
+ });
504
+
505
+ // 添加最后一组
506
+ if (currentGroup.length > 0) {
507
+ groupedRecords.push(currentGroup);
508
+ }
509
+
510
+ return groupedRecords;
511
+ } else {
512
+ // 按节点分组:保持原有的节点分组结构
513
+ return this.itemList;
514
+ }
515
+ },
516
+
517
+ attachmentColumn: function () {
518
+ let column = [];
519
+ column.push({title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left'});
520
+ column.push({
521
+ title: '附件名称', key: 'fileName', minWidth: 150, align: 'center', fixed: 'left',
522
+ render(h, {row}) {
523
+ const index = row.fileName.lastIndexOf(".");
524
+ const fileName = row.fileName.substr(0, index)
525
+ return h("span", fileName)
526
+
527
+ }
528
+ });
529
+ column.push({
530
+ title: '附件类型', width: 100, align: 'center', fixed: 'left',
531
+ render: (h, {row}) => {
532
+ const index = row.fileName.lastIndexOf(".");
533
+ const fileType = row.fileName.substr(index + 1)
534
+ return h("span", fileType)
535
+ }
536
+ });
537
+
538
+ column.push({
539
+ title: "操作", width: 160, align: 'center', tooltip: true,
540
+ render: (h, {row}) => {
541
+ const index = row.fileName.lastIndexOf(".");
542
+ const fileType = row.fileName.substr(index + 1).toLowerCase()
543
+ const typeList=['jpg','gif','png','docx']
544
+ if (typeList.indexOf(fileType) !== -1) {
545
+ return h("div", [
546
+ operateHref(this, h, row, "下载", () => {
547
+ this.getAttach(row);
548
+ }, "primary"),
549
+ operateHref(this, h, row, "预览", () => {
550
+ this.preViewAttach(row);
551
+ }, "primary")
552
+ ]);
553
+ } else {
554
+ return h("div", [
555
+ operateHref(this, h, row, "下载", () => {
556
+ this.getAttach(row);
557
+ }, "primary")
558
+ ]);
559
+ }
560
+
561
+ }
562
+
563
+ });
564
+ return column;
565
+ }
566
+ },
567
+ methods: {
568
+ pushHim(item, auditName, index) {
569
+ if (this.isDebouncing) {
570
+ return;
571
+ }
572
+
573
+ this.isDebouncing = true;
574
+ // 设置一个延时,例如 1 秒,之后重置防抖状态
575
+ setTimeout(() => {
576
+ this.isDebouncing = false;
577
+ }, 2000);
578
+
579
+ let self = this;
580
+ let applyUserName = item.applyUser.split(":")[1];
581
+ let params = {
582
+ applyUserName: applyUserName,
583
+ auditName: auditName,
584
+ auditId: item.auditId[index],
585
+ procName: item.procName,
586
+ effectTime: item.startDate,
587
+ expireTime: item.warningDate,
588
+ applyId: item.applyId,
589
+ taskNode: item.taskNode
590
+ };
591
+ let url = self.smartFlowServerContext + "/manage/processTodo/sendMessage";
592
+ ajax.post(url, params).then(function (resp) {
593
+ console.log("message ", resp);
594
+ if (resp.data.code == 200) {
595
+ self.$Message.success("催办成功");
596
+ } else {
597
+ self.$Message.error("催办失败");
598
+ }
599
+ });
600
+ },
601
+ getAttach(row) {
602
+ window.open(this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId, "_blank");
603
+ },
604
+ preViewAttach(row) {
605
+ let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
606
+ let regs = /\.(pdf)$/
607
+ if (reg.test(row.fileName)) {
608
+ let url = this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId;
609
+ this.imgPreview(url);
610
+ } else if (regs.test(row.fileName)) {
611
+ window.open(this.smartFlowServerContext + "/manage/oss/file/getFileStream?fileId=" + row.fileId, "_blank");
612
+ } else {
613
+ this.modalDocx = true
614
+ axios({
615
+ method: 'get',
616
+ responseType: 'blob', // 因为是流文件,所以要指定blob类型
617
+ url: this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId// 一个word下载文件的接口
618
+ }).then(({data}) => {
619
+ docx.renderAsync(data, this.$refs.file, null, {
620
+ className: "docx", //默认和文档样式类的类名/前缀
621
+ inWrapper: true, //启用围绕文档内容呈现包装器
622
+ ignoreWidth: false, //禁用页面的渲染宽度
623
+ ignoreHeight: false, //禁用页面的渲染高度
624
+ ignoreFonts: false, //禁用字体渲染
625
+ breakPages: true, //在分页符上启用分页
626
+ ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
627
+ experimental: false, //启用实验功能(制表符停止计算)
628
+ trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
629
+ useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
630
+ useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
631
+ showChanges: false, //启用文档更改的实验渲染(插入/删除)
632
+ debug: false, //启用额外的日志记录
633
+ })
634
+ }
635
+ )
636
+ }
637
+ },
638
+ //查看附件
639
+ imgPreview: function (img) {
640
+ this.modalImg = true
641
+ this.image = img;
642
+ },
643
+ arrowClick() {
644
+ if (this.itemList.length > 0) {
645
+ if (this.arrowShow) {
646
+ // 显示全部
647
+ this.displayedList = this.itemList;
648
+ this.arrowShow = false;
649
+ } else {
650
+ // 只显示两个
651
+ this.displayedList = this.itemList.slice(0, 2);
652
+ this.arrowShow = true;
653
+ }
654
+ }
655
+ },
656
+ openModal(item) {
657
+ this.fileList = item.fileList
658
+ this.showModal = true
659
+ },
660
+ getFirstName(item) {
661
+ return item ? item[0] : ''
662
+ },
663
+ showDate(item) {
664
+ if (item.auditResult){
665
+ if (item.auditResult === '00'){
666
+ return `发起时间:${item.auditDate}`
667
+ }
668
+ return `处理时间:${item.auditDate}`
669
+ }
670
+ return `接收时间:${item.createTime}`
671
+ },
672
+ getRecordTime(item) {
673
+ // 获取记录的时间用于排序
674
+ let timeStr = '';
675
+
676
+ if (item.auditResult && item.auditResult !== '') {
677
+ // 已审批记录:优先使用审批时间
678
+ timeStr = item.auditDate || item.createTime;
679
+ } else {
680
+ // 待审批记录:使用创建时间
681
+ timeStr = item.createTime || item.auditDate;
682
+ }
683
+
684
+ // 如果没有时间,使用当前时间
685
+ if (!timeStr) {
686
+ return new Date().toISOString();
687
+ }
688
+
689
+ // 标准化时间格式
690
+ try {
691
+ // 处理中国标准时间格式 "YYYY-MM-DD HH:mm:ss"
692
+ if (typeof timeStr === 'string') {
693
+ // 移除可能的多余空格
694
+ timeStr = timeStr.trim();
695
+
696
+ // 检查是否是标准格式 "YYYY-MM-DD HH:mm:ss"
697
+ if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(timeStr)) {
698
+ // 直接使用 new Date() 解析,这样会按本地时区处理
699
+ let date = new Date(timeStr);
700
+ if (!isNaN(date.getTime())) {
701
+ return date.toISOString();
702
+ }
703
+ }
704
+
705
+ // 如果包含 T 但没有时区信息,添加本地时区
706
+ if (timeStr.includes('T') && !timeStr.includes('Z') && !timeStr.includes('+')) {
707
+ timeStr += 'Z';
708
+ }
709
+ }
710
+
711
+ // 验证时间是否有效
712
+ let date = new Date(timeStr);
713
+ if (isNaN(date.getTime())) {
714
+ console.warn('Invalid date format:', timeStr);
715
+ return new Date().toISOString();
716
+ }
717
+
718
+ return date.toISOString();
719
+ } catch (error) {
720
+ console.warn('Error parsing date:', timeStr, error);
721
+ return new Date().toISOString();
722
+ }
723
+ },
724
+ getTimelineDotColor(auditResult) {
725
+ if (this.auditPassStatus.includes(auditResult)) {
726
+ return '#005aff'; // 蓝色:通过状态
727
+ } else if (auditResult === '40' || auditResult === '50' ) {
728
+ return '#ffcc66'; // 黄色:驳回状态
729
+ } else if (auditResult === '60' || auditResult === '62' || auditResult === '83') {
730
+ return '#ed4014'; // 红色:撤回/委派状态
731
+ } else {
732
+ return '#ff9900'; // 橙色:其他状态
733
+ }
734
+ },
735
+ toggleSortBy(by) {
736
+ this.sortBy = by;
737
+ },
738
+ isPendingAudit(item) {
739
+ // 判断是否为待审批状态
740
+ // auditResult为空、null、undefined或者不在已审批状态列表中时,认为是待审批
741
+ return !item.auditResult || !this.auditPassStatus.includes(item.auditResult);
742
+ }
743
+ },
744
+ mounted() {
745
+ this.displayPushButton = this.donePage && this.pushButton;
746
+ this.itemList = this.list;
747
+ if (this.itemList.length > 0) {
748
+ // 初始化modals
749
+ this.setModals.modals = this.itemList.map(() => ({value: false}));
750
+ this.activeName = 'panel0';
751
+ }
752
+ },
753
+ watch: {
754
+ list: function (newValue) {
755
+ this.$nextTick(() => {
756
+ this.itemList = newValue;
757
+ if (this.itemList.length > 0) {
758
+ this.setModals.modals = this.itemList.map(() => ({value: false}));
759
+ }
760
+ });
761
+ }
762
+ }
763
+
764
+
765
+ }
766
+ </script>
767
+
768
+ <style scoped>
769
+ @import "../styles/css/index.less";
770
+
771
+ .history-controls {
772
+ padding: 12px;
773
+ background-color: #f8f9fa;
774
+ border-radius: 6px;
775
+ border: 1px solid #e8eaec;
776
+ text-align: center;
777
+ }
778
+
779
+ .history-controls .ivu-btn-group .ivu-btn {
780
+ margin-right: 0;
781
+ }
782
+
783
+ .history-controls .ivu-btn-group .ivu-btn + .ivu-btn {
784
+ margin-left: -1px;
785
+ }
786
+
787
+ .history-title {
788
+ font-weight: 600;
789
+ color: #2c3e50;
790
+ }
791
+
792
+ .pending-audit-title {
793
+ font-weight: 600;
794
+ color: #ff9900;
795
+ font-size: 14px;
796
+ display: flex;
797
+ align-items: center;
798
+ }
799
+
800
+ /* 按时间排序的卡片样式 - 更小,不遮挡时间轴圆点 */
801
+ .portrait-card-time {
802
+ margin-left: 20px !important;
803
+ margin-right: 10px !important;
804
+ margin-bottom: 8px !important;
805
+ background-color: #fafafa !important;
806
+ }
807
+
808
+ :deep(.portrait-card-time .ivu-card-body) {
809
+ padding: 8px 12px !important;
810
+ }
811
+
812
+ :deep(.portrait-card-time .ivu-list-item) {
813
+ padding: 6px 0 !important;
814
+ }
815
+
816
+ :deep(.docx) {
817
+ width: 100% !important;
818
+ }
819
+
820
+ :deep(.ivu-timeline-item-tail) {
821
+ border-style: solid;
822
+ border-left: none;
823
+ border-color: #005aff;
824
+ border-width: thin;
825
+ }
826
+
827
+ :deep(.ivu-list-item) {
828
+ padding-bottom: 0 !important;
829
+ }
830
+
831
+ :deep(.ivu-collapse-content-box) {
832
+ padding: 0 !important;
833
+ }
834
+
835
+ :deep(.ivu-card-body) {
836
+ padding: 5px !important;
837
+ }
838
+
839
+ </style>