@lambo-design/workflow-approve 1.0.0-beta.45 → 1.0.0-beta.47

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.
package/src/portrait.vue CHANGED
@@ -1,1565 +1,1569 @@
1
- <template>
2
- <LamboPageContainer>
3
- <template slot="page-title">
4
- {{ title }}
5
- </template>
6
- <template slot="page-extend">
7
- <slot name="return-button"></slot>
8
- </template>
9
- <div class="portrait-lambo-indicator-card"
10
- :style="{float: 'left', width: isExpanded && showProcessInfo ? `calc(100% - ${portraitWidth+10}px)` : '99%'}">
11
- <slot name="business-content">
12
- </slot>
13
- </div>
14
-
15
- <a v-if="showProcessInfo" @click="isExpanded = !isExpanded" class="arrow-button-container"
16
- :style="{right: isExpanded ? portraitWidth+10 + 'px' : '10px'}">
17
- <Icon class="icon-class" v-if="isExpanded" type="ios-arrow-forward"/>
18
- <Icon class="icon-class" v-if="!isExpanded" type="ios-arrow-back"/>
19
- </a>
20
- <transition v-if="showProcessInfo" name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
21
- @before-leave="beforeFlowInfoLeave" @leave="flowInfoLeave">
22
- <lamboIndicatorCard v-if="isExpanded" class="portrait-lambo-indicator-card"
23
- :style="{width: portraitWidth + 'px', float: 'right'}" :hasExtend="false">
24
- <div slot="content-title">流程信息</div>
25
- <a v-if="!isDetail" @click="auditShow = !auditShow">
26
- <Title
27
- v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
28
- <a style="color: #989898">
29
- <Icon v-if="auditShow" type="ios-arrow-down"/>
30
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
31
- {{ handleName }}信息
32
- </a>
33
- </Title>
34
- </a>
35
- <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave"
36
- @leave="leave">
37
- <div class="box" v-show="auditShow">
38
- <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
39
- v-if="handleButtons && handleButtons.includes('auditOpinion')"
40
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
41
- <FormItem :label="auditOpinionTitle" prop="auditOpinion">
42
- <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
43
- :attachmentdata="fileList" :default-audit-opinion="defaultAuditOpinion"
44
- :smart-flow-server-context="smartFlowServerContext"></AuditOpinion>
45
- </FormItem>
46
- </Form>
47
- <Form ref="auditOpinion" justify="center" :label-width="100"
48
- v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
49
- style="margin: 10px 0 0 10px;">
50
- <FormItem style="min-height: 70px">
51
- <Tooltip placement="bottom" max-width="200">
52
- <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg
53
- .png .gif
54
- </div>
55
- <UploadFile @upload-result="uploadFile" :multiple="true"
56
- :oss-server-context="smartFlowServerContext"
57
- :oss-file-put-url="ossFilePutUrl"></UploadFile>
58
- </Tooltip>
59
- </FormItem>
60
- </Form>
61
- </div>
62
- </transition>
63
- <a v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
64
- <Title
65
- v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
66
- <a style="color: #989898">
67
- <Icon v-if="auditShow" type="ios-arrow-down"/>
68
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
69
- {{ handleName }}信息
70
- </a>
71
- </Title>
72
- </a>
73
- <transition v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" name="draw" @before-enter="beforeEnter"
74
- @enter="enter" @before-leave="beforeLeave" @leave="leave">
75
- <div class="box" v-show="auditShow">
76
- <Form ref="auditOpinion" justify="center" :model="form"
77
- v-if="handleButtons && handleButtons.includes('auditOpinion')"
78
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
79
- <FormItem style="margin-left: -60px">
80
- <Card v-for="(item, index) in hisAuditOpinion" :key="index">
81
- <Row>
82
- <Col span="12" style="word-wrap: break-word">{{ item.auditOpinion }}</Col>
83
- <Col span="2"></Col>
84
- <Col span="10">{{ item.auditTime }}</Col>
85
- </Row>
86
- </Card>
87
- </FormItem>
88
- </Form>
89
- </div>
90
- </transition>
91
- <a @click="historyShow = !historyShow">
92
- <Title v-if="handleButtons && handleButtons.includes('auditHistory')">
93
- <a style="color: #989898">
94
- <Icon v-if="historyShow" type="ios-arrow-down"/>
95
- <Icon v-if="!historyShow" type="ios-arrow-up"/>
96
- {{ handleName }}记录
97
- </a>
98
- </Title>
99
- </a>
100
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
101
- <div class="box" v-show="historyShow">
102
- <Card class="process-history" :style="processHistoryHeight" dis-hover :bordered="false"
103
- v-if="handleButtons && handleButtons.includes('auditHistory')">
104
- <processHistory :portrait-width="portraitWidth" :list="processHistory" :done-page="isDetail" :push-button="pushButton"
105
- :smart-flow-server-context="smartFlowServerContext"></processHistory>
106
- </Card>
107
- </div>
108
- </transition>
109
-
110
- <a @click="attachListShow = !attachListShow">
111
- <Title v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0">
112
- <a style="color: #989898">
113
- <Icon v-if="attachListShow" type="ios-arrow-down"/>
114
- <Icon v-if="!attachListShow" type="ios-arrow-up"/>
115
- 查看附件
116
- </a>
117
- </Title>
118
- </a>
119
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
120
- <div class="box"
121
- v-show="handleButtons && handleButtons.includes('auditHistory') && attachmentList.length > 0 && attachListShow">
122
- <div v-for="(item, index) in attachmentList" :key="index">
123
- <Card dis-hover class="attach-card">
124
- <List item-layout="vertical">
125
- <ListItem style="margin-top: -8px">
126
- <Row style="display: flex; align-items: center;">
127
- <!-- 左边:图片 -->
128
- <Col span="4" style="margin-top: -25px">
129
- <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar"
130
- style="background-color: #005aff"
131
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
132
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
133
- <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar"
134
- style="background-color: #005aff"
135
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
136
- :size="portraitWidth >= 600 ? 'middle' : 'small'">
137
- </avatar>
138
- <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar"
139
- style="background-color: #19be6b"
140
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
141
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
142
- <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar"
143
- style="background-color: #ed4014"
144
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
145
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
146
- <avatar v-else icon="ios-document-outline" class="attach-avatar"
147
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
148
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
149
- </Col>
150
- <!-- 右边:附件信息 -->
151
- <Col span="20">
152
- <Row>
153
- <tooltip>
154
- <span class="attach-name-style"> {{ item.attachName }}</span>
155
- <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
156
- </tooltip>
157
- </Row>
158
- <Row style="margin-top: 3px">
159
- <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
160
- <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
161
- type="vertical"/>
162
- <span style="color: #808695;font-size: 13px"
163
- >{{ showTaskNode(item.taskId) }}</span>
164
- </Row>
165
- <Row style="margin-bottom: -10px; margin-top: 10px">
166
- <template>
167
- <Button @click="getAttach(item)" size="small">下载</Button>
168
- <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
169
- style="margin-left: 10px" size="small">预览
170
- </Button>
171
- </template>
172
- </Row>
173
- </Col>
174
- </Row>
175
-
176
- </ListItem>
177
- </List>
178
- </Card>
179
- </div>
180
- </div>
181
- </transition>
182
- <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
183
- <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
184
- <div slot="footer">
185
- <Button type="primary" @click="modalVisible = false">关闭</Button>
186
- </div>
187
- </Modal>
188
- <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
189
- <div ref="file"></div>
190
- </Modal>
191
- </lamboIndicatorCard>
192
- </transition>
193
-
194
- <Modal v-model="modal1" title="选择节点"
195
- @on-cancel="cancel"
196
- @on-ok="doPass">
197
- <Table border
198
- :data="allNode"
199
- :columns="nodeColumn"
200
- highlight-row
201
- @on-current-change="selectNode">
202
- </Table>
203
- </Modal>
204
- <assigneeBox ref="assigneeHelpBox" :execution-completed="executionCompleted"
205
- @update-selected="handleSelectedUser" @update-next-node-assignee="updateNextNodeAssignee"
206
- :data="assigneeBoxData" :smart-flow-server-context="smartFlowServerContext"
207
- :upms-server-context="upmsServerContext"/>
208
- <Modal v-model="modalBoxShow" width="1000" title="流程跟踪图">
209
- <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId"
210
- :procId="process.procId" :table-columns="diagramTableColumns"
211
- :tableData="process.tableData" :hisAudit="hisAudit" :approve-detail-show-way="approveDetailShowWay"
212
- :smart-flow-server-context="smartFlowServerContext">
213
- </Workflow_Diagram>
214
- </Modal>
215
- <Modal v-model="appointBoxShow" title="下一环节设置"
216
- @on-cancel="appointBoxShow = false" width="600"
217
- @on-ok="appointOk">
218
- <Card v-for="(item,index) of nextNodesFormList" :key="index" style="margin-bottom: 10px"
219
- v-if="handleButtons && (handleButtons.includes('appointHandler') || handleButtons.includes('appointTimeoutTime'))">
220
- <Form ref="appointBox" justify="center" :label-width="100" :model="item"
221
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
222
- <div v-if="handleButtons && handleButtons.includes('appointHandler')">
223
- <FormItem label="下一环节:">
224
- {{ item.name }}
225
- </FormItem>
226
- <FormItem label="人员类型:" v-if="!item.isMultiInstance">
227
- <RadioGroup v-model="item.actionType">
228
- <Radio label="ASSIGNEE">办理人</Radio>
229
- <Radio label="CAND">候选人</Radio>
230
- </RadioGroup>
231
- </FormItem>
232
- <FormItem label="办理人员:" prop="assignee" v-if="!item.isMultiInstance && item.actionType === 'ASSIGNEE'">
233
- <Input v-model="item.assigneeName"
234
- placeholder="请选择办理人"
235
- style="width: 68%"
236
- icon="md-apps"
237
- @on-focus="readingRangeClick(item)"
238
- @on-click="readingRangeClick(item)"/>
239
- </FormItem>
240
- <FormItem label="候选人员:" prop="candidateGroups" v-if="!item.isMultiInstance && item.actionType === 'CAND'">
241
- <Input v-model="item.candidateNames"
242
- placeholder="请选择候选人"
243
- style="width: 68%"
244
- icon="md-apps"
245
- @on-focus="candidateGroupsReadingRangeClick(item)"
246
- @on-click="candidateGroupsReadingRangeClick(item)"/>
247
- </FormItem>
248
- <FormItem label="候选人员:" prop="candidateGroups" v-if="item.isMultiInstance && item.actionType === 'CAND'">
249
- </FormItem>
250
-
251
- <countersingersBox style="margin-bottom: 10px" v-model="item.candidateNames" v-if="item.isMultiInstance && item.actionType === 'CAND'"
252
- :item="item" :permScope="permScope" @update-cand-groups="updateCandGroups" :upms-server-context="upmsServerContext" :smart-flow-server-context="smartFlowServerContext"/>
253
- </div>
254
- <div v-if="handleButtons && handleButtons.includes('appointTimeoutTime')">
255
- <Row>
256
- <Col span="12">
257
- <FormItem label="停留时间:">
258
- <Input v-model="item.remainDay" style="width: 100px" type="number" :min="0"></Input>
259
-
260
- </FormItem>
261
- </Col>
262
- <Col span="12">
263
- <FormItem>
264
- <Input v-model="item.remainTime" style="margin-left: -140px; width: 100px" type="number"
265
- :min="0"></Input>
266
- 小时 自动处理
267
- </FormItem>
268
- </Col>
269
- </Row>
270
- <Row>
271
- <Col span="12">
272
- <FormItem label="任务提前:">
273
- <Input v-model="item.inAdvanceDay" style="width: 100px" type="number" :min="0"></Input>
274
-
275
- </FormItem>
276
- </Col>
277
- <Col span="12">
278
- <FormItem>
279
- <Input v-model="item.inAdvanceTime" style="margin-left: -140px;width: 100px" type="number"
280
- :min="0"></Input>
281
- 小时 标红预警
282
- </FormItem>
283
- </Col>
284
- </Row>
285
- <FormItem label="处理方式:">
286
- <Select v-model="item.processing" style="width:200px" placeholder="自动同意">
287
- <Option v-for="item in handleTypeList" :value="item.value" :key="item.value">
288
- {{ item.label }}
289
- </Option>
290
- </Select>
291
- </FormItem>
292
- </div>
293
- </Form>
294
- </Card>
295
- </Modal>
296
- <candidateGroupsHelpBox ref="candidateGroupsHelpBox" :show="candidateGroupsHelpBoxShow" @update-cand-groups="updateCandGroups"
297
- :upms-server-context="upmsServerContext" :smart-flow-server-context="smartFlowServerContext"/>
298
- <template slot="page-footer">
299
- <div>
300
- <slot name="footer-button"></slot>
301
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo70') && !isDetail"
302
- :disabled="disable" :loading="loading" @click="audit('70')">驳回到原点
303
- </Button>
304
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo40') && !isDetail"
305
- :disabled="disable" :loading="loading" @click="audit('40')">驳回上一节点
306
- </Button>
307
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo90') && !isDetail"
308
- :disabled="disable" :loading="loading" @click="audit('90')">驳回指定节点
309
- </Button>
310
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo80') && !isDetail"
311
- :disabled="disable" :loading="loading" @click="audit('80')">跳转指定节点
312
- </Button>
313
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo82') && !isDetail"
314
- :disabled="disable" :loading="loading" @click="audit('82')">指定他人处理
315
- </Button>
316
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo50') && !isDetail"
317
- :disabled="disable" :loading="loading" @click="audit('50')">直接结束流程
318
- </Button>
319
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('processTrace')"
320
- @click="processPrint">流程跟踪图
321
- </Button>
322
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo30') && !isDetail"
323
- :disabled="disable" :loading="loading" type="primary" @click="audit('30')">通过
324
- </Button>
325
- </div>
326
- </template>
327
- </LamboPageContainer>
328
- </template>
329
-
330
-
331
- <script>
332
- import LamboPageContainer from '@lambo-design/page-container'
333
- import LamboIndicatorCard from '@lambo-design/indicator-card'
334
- import Workflow_Diagram from './workflow-diagram'
335
- import ajax from "@lambo-design/shared/utils/ajax";
336
- import bus from '@lambo-design/shared/utils/bus';
337
- import Title from "./components/title";
338
- import processHistory from "./components/history";
339
- import assigneeBox from "./components/assignee-box";
340
- import CandidateGroupsHelpBox from "./components/candidate-groups-box";
341
- import CountersingersBox from "./components/countersigners-box"
342
- import LamboPagingTable from "@lambo-design/paging-table";
343
- import AuditOpinion from "./components/opinion";
344
- import axios from "axios";
345
- import UploadFile from "@lambo-design/upload-file";
346
- import {timestampToTime} from "@lambo-design/shared/utils/date";
347
-
348
- // 引入docx-preview插件
349
- let docx = require('docx-preview');
350
-
351
-
352
- export default {
353
- props: {
354
- isDetail: {
355
- type: Boolean,
356
- required: false,
357
- default: false
358
- },
359
- width: {
360
- type: Number,
361
- required: false,
362
- default: 400
363
- },
364
- procId: {
365
- type: String,
366
- required: true,
367
- },
368
- taskNode: {
369
- type: String,
370
- required: true,
371
- },
372
- applyId: {
373
- type: String,
374
- required: true,
375
- },
376
- taskId: {
377
- type: String,
378
- required: false,
379
- default: '',
380
- },
381
- auditGroup: {
382
- type: String,
383
- required: false,
384
- default: '',
385
- },
386
- defaultAuditOpinion: {
387
- type: String,
388
- required: false,
389
- default: '',
390
- },
391
- //详情页催办按钮
392
- pushButton: {
393
- type: Boolean,
394
- required: false,
395
- default: true,
396
- },
397
- //流程跟踪图附件列
398
- showAttachmentFile: {
399
- type: Boolean,
400
- required: false,
401
- default: true,
402
- },
403
- //流程跟踪图审批详情触发方式
404
- approveDetailShowWay: {
405
- type: String,
406
- required: false,
407
- default: 'click',
408
- },
409
- //业务表单保存方法
410
- businessFormSave: {
411
- type: Function,
412
- required: false
413
- },
414
- //按钮执行完毕回调方法
415
- executionCompleted: {
416
- type: Function,
417
- required: false,
418
- default: () => {}
419
- },
420
- title: {
421
- type: String,
422
- default: "流程办理"
423
- },
424
- smartFlowServerContext: {
425
- type: String,
426
- default: '/api/smart-flow-server',
427
- },
428
- upmsServerContext: {
429
- type: String,
430
- default: '/api/upms-server',
431
- },
432
- },
433
- components: {
434
- Title,
435
- LamboPageContainer,
436
- Workflow_Diagram,
437
- processHistory,
438
- assigneeBox,
439
- LamboPagingTable,
440
- AuditOpinion,
441
- LamboIndicatorCard,
442
- UploadFile,
443
- CandidateGroupsHelpBox,
444
- CountersingersBox
445
- },
446
- data() {
447
- return {
448
- isExpanded: true,
449
- showProcessInfo: true,
450
- portraitWidth: 0,
451
- requestSuccessCodes: [200, "200"],
452
- auditShow: true,
453
- historyShow: true,
454
- attachListShow: true,
455
- attachmentList: [],
456
- modalVisible: false,
457
- modalDocx: false,
458
- imageUrl: '',
459
- assigneeBoxData: {},
460
- selectedUserId: '',
461
- targetTaskNode: '',
462
- allNode: [],
463
- auditParams: {},
464
- modal1: false,
465
- modalBoxShow: false,
466
- candidateGroupsHelpBoxShow: false,
467
- appointBoxShow: false,
468
- autoOpenNode: '0',
469
- nextNodesOldSettings: [],
470
- nextNodesFormList: [],
471
- hisNode: [],
472
- processHistory: [],
473
- permScope: '',
474
- organTreeType: '00',
475
- defaultOrganTreeType: '00',
476
- ruleValidate: {
477
- auditOpinion: [{required: true, trigger: "blur", message: '意见不能为空'}],
478
- assignee: [{required: true, trigger: "blur", message: "办理人不能为空"}],
479
- candidateGroups: [{required: true, trigger: "blur", message: "候选人不能为空"}],
480
- },
481
- form: {
482
- auditOpinion: '',
483
- },
484
- loading: false,
485
- disable: false,
486
- instanceId: '',
487
- curTaskId: '',
488
- handleButtons: [],
489
- handleName: '',
490
- auditOpinionTitle: '',
491
- auditResult: '',
492
- curAuditGroup: '',
493
- custChange: 'auditInfo',
494
- auditInfo: "auditInfo",
495
- auditProcess: "auditProcess",
496
- fileList: [],
497
- ossFilePutUrl: '/manage/oss/file/put',
498
- hisAudit: [],
499
- hisAuditOpinion: [{
500
- auditOpinion: '',
501
- auditTime: '',
502
- }],
503
- datas: {
504
- orgName: "",
505
- orgId: ""
506
- },
507
- editForm: {
508
- approvalCost: '',
509
- cost: '',
510
- activityDate: []
511
- },
512
- process: {
513
- tableData: [],
514
- instanceId: '',
515
- applyId: '',
516
- procId: ''
517
- },
518
- handleButtonsNames: {
519
- '30': '通过',
520
- '70': '驳回到原点',
521
- '40': '驳回上一节点',
522
- '90': '驳回指定节点',
523
- '80': '跳转指定节点',
524
- '82': '指定他人处理',
525
- '50': '直接结束流程'
526
- },
527
- handleTypeList: [
528
- {
529
- value: '00',
530
- label: '只预警不处理'
531
- },
532
- {
533
- value: '10',
534
- label: '自动同意'
535
- },
536
- {
537
- value: '20',
538
- label: '直接终止流程'
539
- },
540
- {
541
- value: '90',
542
- label: '自动驳回'
543
- }
544
- ],
545
- }
546
-
547
- },
548
-
549
- mounted() {
550
- this.getWidth()
551
- if (this.procId) {
552
- this.initData()
553
- }
554
-
555
- },
556
- computed: {
557
- processHistoryHeight() {
558
- let str = '';
559
- const hasAuditOpinion = this.taskNode && this.handleButtons && this.handleButtons.includes('auditOpinion')
560
- const hasAttachmentFile = this.handleButtons && this.handleButtons.includes('auditHistory') && this.attachmentList.length > 0
561
- const isDetail = this.isDetail && !this.hisAuditOpinion[0].auditOpinion.length > 0
562
- if (hasAuditOpinion && !hasAttachmentFile && !isDetail) {
563
- str += "height: 43vh"
564
- } else if (hasAuditOpinion && hasAttachmentFile && !isDetail) {
565
- str += "height: 40vh"
566
- } else {
567
- str += "height: 67vh"
568
- }
569
- return str;
570
- },
571
- nodeColumn: function () {
572
- let column = []
573
- column.push({title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left'});
574
- column.push({title: '节点名称', key: 'taskName', minWidth: 150, align: 'center', fixed: 'left'})
575
-
576
- column.push({
577
- title: '节点状态', key: 'auditResult', minWidth: 150, align: 'center', fixed: 'left',
578
- render: (h, params) => {
579
- if (params.row.taskNode == this.taskNode) {
580
- return h('div', [
581
- h('tag', {
582
- props: {
583
- color: '#ff9900'
584
- }
585
- }, '当前节点')
586
- ])
587
- } else if (!params.row.auditResult) {
588
- return h('div', [
589
- h('tag', {
590
- props: {
591
- color: '#ff9900'
592
- }
593
- }, `未${params.row.handleName ? params.row.handleName : '审批'}`)
594
- ])
595
- } else {
596
- if (params.row.auditResult == '30' && params.row.taskNode != this.taskNode) {
597
- return h('div', [
598
- h('tag', {
599
- props: {
600
- color: '#19be6b'
601
- }
602
- }, `已${params.row.handleName ? params.row.handleName : '审批'}通过`)
603
- ])
604
- } else if (params.row.auditResult == '40' && params.row.taskNode != this.taskNode) {
605
- return h('div', [
606
- h('tag', {
607
- props: {
608
- color: '#ed4014'
609
- }
610
- }, '已驳回到上一节点')
611
- ])
612
- } else if (params.row.auditResult == '60' && params.row.taskNode != this.taskNode) {
613
- return h('div', [
614
- h('tag', {
615
- props: {
616
- color: '#ed4014'
617
- }
618
- }, '已撤回')
619
- ])
620
- } else if (params.row.auditResult == '80' && params.row.taskNode != this.taskNode) {
621
- return h('div', [
622
- h('tag', {
623
- props: {
624
- color: '#19be6b'
625
- }
626
- }, '已跳转到指定节点')
627
- ])
628
- } else if (params.row.auditResult == '90' && params.row.taskNode != this.taskNode) {
629
- return h('div', [
630
- h('tag', {
631
- props: {
632
- color: '#19be6b'
633
- }
634
- }, '已驳回到指定节点')
635
- ])
636
- }
637
- }
638
- }
639
- })
640
- column.push({
641
- title: "操作", width: 100, align: 'center',
642
- render: (h, params) => {
643
- return h('div', [
644
- h('Button', {
645
- props: {
646
- type: 'primary',
647
- size: 'small'
648
- },
649
- style: {
650
- marginRight: '5px'
651
- },
652
- on: {
653
- click: () => {
654
- this.selectNode(params.row)
655
- }
656
- }
657
- }, '选择')
658
- ])
659
- },
660
- })
661
- return column
662
- },
663
- diagramTableColumns: function () {
664
- let column = []
665
- column.push({title: '序号', type: 'index', width: 60});
666
- column.push({title: `${this.handleName}节点`, key: 'taskName', minWidth: 130})
667
- column.push({title: `${this.handleName}人`, key: 'auditName', minWidth: 150, tooltip: true})
668
- column.push({
669
- title: `${this.handleName}结果`, key: 'auditResult', minWidth: 150, align: 'center',
670
- render: (h, {row, column, index}) => {
671
- let label = "";
672
- let tagColor = "";
673
- if (row.auditResult == '00'){
674
- label = '流程发起';
675
- tagColor = 'green'; // 绿色
676
- }
677
- else if (row.auditResult == '30'){
678
- label = '通过';
679
- tagColor = 'green'; // 绿色
680
- }
681
- else if (row.auditResult == '40'){
682
- label = '驳回到上一级';
683
- tagColor = 'volcano'; // 火红色
684
- }
685
- else if (row.auditResult == '50'){
686
- label = '驳回到原点';
687
- tagColor = 'red'; // 红色
688
- }
689
- else if (row.auditResult == '51'){
690
- label = '流程终止';
691
- tagColor = 'purple'; // 紫色
692
- }
693
- else if (row.auditResult == '60'){
694
- label = '撤回';
695
- tagColor = 'blue'; // 蓝色
696
- }
697
- else if (row.auditResult == '80'){
698
- label = '跳转到指定节点';
699
- tagColor = 'cyan'; // 青色
700
- }
701
- else if (row.auditResult == '90'){
702
- label = '驳回到指定节点';
703
- tagColor = 'magenta'; // 品红色
704
- }
705
- else{
706
- label = '待审核';
707
- tagColor = 'orange'; // 默认橙色
708
- }
709
- return h('Tag', {
710
- props: {
711
- color: tagColor,
712
- value: row.auditResult
713
- }
714
- }, label);
715
- }
716
- })
717
- column.push({
718
- title: `${this.handleName}时间`, key: 'auditTime', minWidth: 150,
719
- render: (h, {row}) => {
720
- const displayDate = row.startDate || row.auditDate;
721
- return h('span', displayDate);
722
- }
723
- })
724
- column.push({
725
- title: `${this.handleName}意见`, key: 'auditComment', minWidth: 180, tooltip: true,
726
- render: (h, {row, column, index}) => {
727
- let label = "";
728
- if (row.auditComment == '' || row.auditComment == null) label = '无';
729
- else label = row.auditComment;
730
- return h('Label', {
731
- props: {
732
- value: row.auditComment
733
- }
734
- }, label)
735
- }
736
- })
737
- if (this.showAttachmentFile){
738
- column.push({
739
- title: `附件`, key: 'fileList', minWidth: 200,
740
- render: (h, { row }) => {
741
- if (!row.fileList || row.fileList.length === 0) {
742
- return h('span', '无'); // 如果没有附件,显示“无”
743
- }
744
-
745
- //显示所有附件
746
- return h('div', row.fileList.map(file => {
747
- return h('a', {
748
- style: {
749
- display: 'block',
750
- marginTop: '5px',
751
- marginRight:'5px',
752
- whiteSpace: 'nowrap',
753
- overflow: 'hidden',
754
- textOverflow: 'ellipsis',
755
- maxWidth: '100px',
756
- },
757
- attrs: {
758
- title: file.attachName // 鼠标悬停时显示完整名称
759
- },
760
- on: {
761
- click: () => {
762
- this.getAttach(file);
763
- }
764
- },
765
- }, file.attachName);
766
- }));
767
- }
768
- })
769
- }
770
-
771
- return column
772
- },
773
- },
774
- provide() {
775
- return {
776
- toBeDoneListDoSearch: this.doSearch
777
- };
778
- },
779
- methods: {
780
- getWidth() {
781
- if (this.width && this.width < 400) {
782
- this.portraitWidth = 400
783
- }
784
- this.portraitWidth = this.width
785
- },
786
- initData() {
787
- if (!this.isDetail) {
788
- this.getTodoTask()
789
- } else {
790
- this.getDoneTask()
791
- }
792
- this.getHandleButtons()
793
- },
794
- getTodoTask() {
795
- const self = this
796
- let param = {
797
- procId: this.procId,
798
- applyId: this.applyId,
799
- taskNode: this.taskNode,
800
- taskId: this.taskId,
801
- auditGroup: this.auditGroup
802
- }
803
- ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (resp) {
804
- if (resp.data.code === '200') {
805
- self.curTaskId = resp.data.data.rows[0].taskId
806
- self.instanceId = resp.data.data.rows[0].procInstanceId
807
- self.curAuditGroup = resp.data.data.rows[0].auditGroup
808
- let procType = resp.data.data.rows[0].procType
809
- ajax.get(self.smartFlowServerContext + "/manage/processType/lists?proType=" + procType)
810
- .then(resp => {
811
- let data = resp.data.data.rows
812
- self.permScope = data[0].permScope
813
- self.defaultOrganTreeType = data[0].organTreeType ? data[0].organTreeType : '00'
814
- self.getNodeOrganTreeType(procType)
815
- }).catch(err => {
816
- console.log(err);
817
- })
818
- self.getAttachList(self.curTaskId)
819
- self.getHisAudit(self.curTaskId);
820
- self.getProcessHistory(self.curTaskId);
821
- } else {
822
- self.$Message.error(resp.data.message)
823
- }
824
- }).catch((err) => {
825
- console.log(err)
826
- })
827
- },
828
- getNodeOrganTreeType(procType){
829
- const self = this
830
- let param = {
831
- procType: procType,
832
- procId: this.procId,
833
- taskNode: this.taskNode
834
- }
835
- ajax.get(self.smartFlowServerContext + "/manage/processTodo/getNodeOrganTreeType", {params: param}).then(function (resp) {
836
- if (resp.data.code === '200') {
837
- self.organTreeType = resp.data.data ? resp.data.data : self.defaultOrganTreeType
838
- } else {
839
- self.$Message.error(resp.data.message)
840
- }
841
- }).catch((err) => {
842
- console.log(err)
843
- })
844
- },
845
- getDoneTask() {
846
- const self = this
847
- let param = {
848
- procId: this.procId,
849
- applyId: this.applyId,
850
- taskNode: this.taskNode,
851
- taskId: this.taskId,
852
- auditGroup: this.auditGroup
853
- }
854
- ajax.get(self.smartFlowServerContext + "/manage/processDone/getDoneDetail", {params: param}).then(function (resp) {
855
- if (resp.data.code === '200') {
856
- let rows = resp.data.data.rows
857
- if (rows.length > 0) {
858
- self.curAuditGroup = rows[0].auditGroup
859
- self.hisAuditOpinion = []
860
- let taskList = resp.data.data.rows
861
- taskList.forEach(item => {
862
- self.hisAuditOpinion.push({
863
- auditOpinion: item.auditComment,
864
- auditTime: timestampToTime(item.auditDate)
865
- })
866
- })
867
- self.curTaskId = taskList[0].taskId
868
- self.instanceId = taskList[0].procInstanceId
869
- } else {
870
- ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (todoResp) {
871
- if (todoResp.data.code === '200') {
872
- self.curTaskId = todoResp.data.data.rows[0].taskId
873
- self.instanceId = todoResp.data.data.rows[0].procInstanceId
874
- self.curAuditGroup = todoResp.data.data.rows[0].auditGroup
875
- } else {
876
- self.$Message.error(todoResp.data.message)
877
- }
878
- }).catch((err) => {
879
- console.log(err)
880
- })
881
- }
882
- self.getAttachList(self.curTaskId)
883
- self.getHisAudit(self.curTaskId);
884
- self.getProcessHistory(self.curTaskId);
885
- } else {
886
- self.$Message.error(resp.data.message)
887
- }
888
- }).catch((err) => {
889
- console.log(err)
890
- })
891
- },
892
- getHandleButtons() {
893
- const self = this
894
- let param = {
895
- procId: this.procId,
896
- taskNode: this.taskNode
897
- }
898
- ajax.post(self.smartFlowServerContext + '/manage/approvalCenter/getNodeData', param).then(function (resp) {
899
- if (resp.data.code === '200') {
900
- self.handleButtons = resp.data.data[0].handleButtons
901
- self.handleName = resp.data.data[0].handleName ? resp.data.data[0].handleName : '审批'
902
- self.auditOpinionTitle = resp.data.data[0].handleName ? resp.data.data[0].handleName + '意见' : '审批意见'
903
- if (!self.handleButtons || (!self.handleButtons.includes('auditOpinion') && !self.handleButtons.includes('attachmentFile') && !self.handleButtons.includes('auditHistory'))){
904
- self.showProcessInfo = false
905
- }
906
- } else {
907
- self.$Message.error(resp.data.message)
908
- }
909
- }).catch((err) => {
910
- console.log(err)
911
- })
912
- },
913
- getNextNodes(){
914
- const self = this
915
- self.nextNodesFormList = []
916
- self.nextNodesOldSettings = []
917
- let param = {
918
- procId: this.procId,
919
- taskNode: this.taskNode
920
- }
921
- ajax.post(self.smartFlowServerContext + '/manage/processTodo/getNextNodes', param).then(function (resp) {
922
- if (resp.data.code === '200') {
923
- let nextNodeForm = {}
924
- let nextNodeOldForm = {}
925
- let data = resp.data.data
926
- for (let i = 0; i < data.length; i++) {
927
- nextNodeOldForm = {
928
- id: data[i].id,
929
- assignee: data[i].assignee ? data[i].assignee.id : '',
930
- timeLimit: data[i].timeLimit,
931
- }
932
- nextNodeForm = {
933
- id: data[i].id,
934
- name: data[i].name,
935
- orgTreeType: data[i].orgTreeType,
936
- assignee: data[i].assignee ? data[i].assignee.id : '',
937
- assigneeName: data[i].assignee ? data[i].assignee.name : '',
938
- candidateGroups: '',
939
- isMultiInstance: data[i].isMultiInstance,
940
- actionType: 'ASSIGNEE',
941
- remainDay : 0,
942
- remainTime : 0,
943
- inAdvanceDay : 0,
944
- inAdvanceTime : 0,
945
- processing : '00'
946
- }
947
- //显示具体候选人信息
948
- if (data[i].candidateGroups){
949
- nextNodeForm.actionType = 'CAND'
950
- let names = [];
951
- let candidates = {};
952
- for (let groupName in data[i].candidateGroups) {
953
- if (data[i].candidateGroups.hasOwnProperty(groupName)) {
954
- let group = data[i].candidateGroups[groupName];
955
- group.forEach(item => {
956
- names.push(item.name);
957
- });
958
- candidates[groupName] = group.map(item => item.id + ':' + item.name).join(',');
959
- }
960
- }
961
- nextNodeForm.candidateNames = names.join(',');
962
- nextNodeForm.candidates = candidates;
963
- nextNodeOldForm.candidates = candidates;
964
- }
965
- if (data[i].timeLimit) {
966
- let expireTime = data[i].timeLimit.split(";")[0].split(":")[1]
967
- let warningTime = data[i].timeLimit.split(";")[1].split(":")[1]
968
- let handleType = data[i].timeLimit.split(";")[2].split(":")[1]
969
- let days = expireTime.slice(0, expireTime.indexOf("D")) //过期天
970
- let hourOfDay = expireTime.slice(expireTime.indexOf("D") + 1, expireTime.indexOf("H")) //过期小时
971
- let daysWarn = warningTime.slice(0, warningTime.indexOf("D")) //警告天
972
- let hourOfDayWarn = warningTime.slice(warningTime.indexOf("D") + 1, warningTime.indexOf("H")) //警告小时
973
- nextNodeForm.remainDay = parseInt(days)
974
- nextNodeForm.remainTime = parseInt(hourOfDay)
975
- nextNodeForm.inAdvanceDay = parseInt(daysWarn)
976
- nextNodeForm.inAdvanceTime = parseInt(hourOfDayWarn)
977
- nextNodeForm.processing = handleType
978
- }
979
- self.nextNodesFormList.push(nextNodeForm)
980
- self.nextNodesOldSettings.push(nextNodeOldForm)
981
- }
982
- } else {
983
- self.$Message.error(resp.data.message)
984
- }
985
- }).catch((err) => {
986
- console.log(err)
987
- })
988
- },
989
- getAttachList(taskId) {
990
- const self = this
991
- const param = {
992
- taskId: taskId,
993
- procId: this.procId,
994
- applyId: this.applyId
995
- }
996
- ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', {params: param}).then(function (resp) {
997
- self.attachmentList = resp.data.data.rows
998
- self.attachmentList.forEach(item => {
999
- const index = item.fileName.lastIndexOf(".")
1000
- const fileType = item.fileName.substr(index + 1).toLowerCase()
1001
- const imageList = ['jpg', 'gif', 'png', 'svg']
1002
- const docList = ['doc', 'docx']
1003
- const zipList = ['rar', 'zip']
1004
- const typeList = ['jpg', 'gif', 'png', 'docx']
1005
- item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
1006
- item.showPreview = typeList.indexOf(fileType) !== -1
1007
- })
1008
- }).catch(err => {
1009
- console.log(err);
1010
- })
1011
- },
1012
- getHisAudit(taskId) {
1013
- let self = this
1014
- let params = {
1015
- applyId: self.applyId,
1016
- instanceId: self.instanceId,
1017
- procId: self.procId,
1018
- taskId: taskId
1019
- }
1020
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getHisAudit', {params: params}).then(function (resp) {
1021
- if (resp.data.code === '200') {
1022
- self.hisAudit = resp.data.data
1023
- let uniqueDataMap = {};
1024
- self.hisAudit.forEach((item) => {
1025
- uniqueDataMap[item["taskNode"]] = item;
1026
- })
1027
- self.hisNode = Object.values(uniqueDataMap);
1028
-
1029
- }
1030
- })
1031
- },
1032
- getProcessHistory(taskId) {
1033
- let self = this
1034
- let params = {
1035
- applyId: self.applyId,
1036
- instanceId: self.instanceId,
1037
- procId: self.procId,
1038
- taskId: taskId
1039
- }
1040
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getProcessHis', {params: params}).then(function (resp) {
1041
- if (resp.data.code === '200') {
1042
- self.processHistory = resp.data.data
1043
- }
1044
- })
1045
- },
1046
-
1047
- audit: function (auditResult) {
1048
- let self = this
1049
- self.auditResult = auditResult
1050
- self.submit()
1051
- },
1052
- submit() {
1053
- let self = this;
1054
- self.auditParams = {
1055
- procId: self.procId,
1056
- applyId: self.applyId,
1057
- taskId: self.curTaskId,
1058
- auditOpinion: self.form.auditOpinion,
1059
- fileListStr: JSON.stringify(self.fileList),
1060
- auditResult: self.auditResult,
1061
- params: JSON.stringify(self.datas),
1062
- targetTaskNode: self.targetTaskNode,
1063
- selectedUserId: self.selectedUserId,
1064
- }
1065
- if (self.auditResult == '' || self.auditResult == null) {
1066
- self.$Message.error(`请选择${self.handleName}结果!`);
1067
- return;
1068
- }
1069
- if (self.form.auditOpinion == '' || self.form.auditOpinion == null) {
1070
- if (!self.handleButtons || self.handleButtons.includes('auditOpinion')) {
1071
- self.$Message.error(`请输入${self.handleName}意见!`)
1072
- return;
1073
- } else {
1074
- self.auditParams.auditOpinion = self.handleButtonsNames[self.auditResult];
1075
- }
1076
- }
1077
- self.businessFormSave ? self.businessFormSave(self.handleSaveResult) : self.handleSaveResult(true)
1078
- },
1079
- handleSaveResult(saveResult, businessParams) {
1080
- if (saveResult) {
1081
- this.executeButtonAction(businessParams);
1082
- } else {
1083
- console.error('保存失败');
1084
- }
1085
- },
1086
- executeButtonAction(businessParams) {
1087
- const self = this;
1088
- if (businessParams) {
1089
- Object.assign(self.datas, businessParams)
1090
- self.auditParams.params = JSON.stringify(self.datas)
1091
- }
1092
- let auditResult = {
1093
- code: self.auditResult,
1094
- name: self.handleButtonsNames[self.auditResult]
1095
- }
1096
- if (self.auditResult === '82') {
1097
- self.assigneeBoxData = self.auditParams
1098
- self.assigneeBoxData.auditResultName = self.handleButtonsNames[self.auditResult]
1099
- self.assigneeBoxData.instanceId = self.instanceId
1100
- self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'transferCurTask')
1101
- } else if (self.auditResult === '80') {
1102
- self.getNodesBehind()
1103
- } else if (self.auditResult === '90') {
1104
- self.getAllPreNodes()
1105
- } else if (self.auditResult === '40') {
1106
- self.loading = true
1107
- self.disable = true
1108
- let url = self.smartFlowServerContext + '/manage/processTodo/getPreNode'
1109
- ajax.post(url, self.auditParams).then(function (resp) {
1110
- let result = resp.data
1111
- if (result.code == '30013' || result.code == '30014') {
1112
- //前序节点为子流程或当前节点为子流程第一个节点不可驳回上一级节点
1113
- self.$Message.warning(result.message)
1114
- //避免未提示消息直接回调
1115
- setTimeout(() => {
1116
- self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1117
- }, 1000)
1118
- } else if (result.code == '30010') {
1119
- self.$Modal.confirm({
1120
- title: "提示",
1121
- content: result.message,
1122
- onOk: () => {
1123
- self.auditParams.auditResult = '70'
1124
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1125
- ajax.post(url, self.auditParams).then(function (resp) {
1126
- let result = resp.data
1127
- if (result.code == '200') {
1128
- self.loading = false
1129
- self.disable = false
1130
- self.$Message.success(result.message);
1131
- //后端没有返回数据
1132
- setTimeout(() => {
1133
- self.executionCompleted(true, null, null, auditResult, self.curTaskId);
1134
- }, 1000)
1135
- bus.$emit('triggerTimer')
1136
- } else {
1137
- self.loading = false
1138
- self.disable = false
1139
- self.$Message.error(result.message)
1140
- setTimeout(() => {
1141
- self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1142
- }, 1000)
1143
- }
1144
- bus.$emit('triggerTimer')
1145
- })
1146
- },
1147
- onCancel: () => {
1148
- self.loading = false
1149
- self.disable = false
1150
- }
1151
- })
1152
- } else if (result.code == '10012') {
1153
- // 数据同步
1154
- self.loading = false
1155
- self.disable = false
1156
- self.$Message.warning(result.message)
1157
- setTimeout(() => {
1158
- self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1159
- }, 1000)
1160
- } else {
1161
- self.loading = true
1162
- self.disable = true
1163
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1164
- ajax.post(url, self.auditParams).then(function (resp) {
1165
- let result = resp.data
1166
- if (result.code == '200') {
1167
- self.loading = false
1168
- self.disable = false
1169
- self.$Message.success(result.message);
1170
- setTimeout(() => {
1171
- if (result.data) {
1172
- let taskIds = result.data.map(item => item.id).join(',');
1173
- self.executionCompleted(true, result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1174
- } else {
1175
- self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1176
- }
1177
- }, 1000)
1178
- } else {
1179
- self.loading = false
1180
- self.disable = false
1181
- self.$Message.error(result.message)
1182
- setTimeout(() => {
1183
- self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1184
- }, 1000)
1185
- }
1186
- bus.$emit('triggerTimer')
1187
- })
1188
- }
1189
- })
1190
- } else {
1191
- if (self.auditResult === '30' && (!self.handleButtons || self.handleButtons.includes('appointHandler') || self.handleButtons.includes('appointTimeoutTime'))){
1192
- self.getNextNodes()
1193
- self.appointBoxShow = true
1194
- } else {
1195
- self.doPass()
1196
- }
1197
- }
1198
- },
1199
- doPass(){
1200
- let self = this;
1201
- this.modal = false
1202
- let auditResult = {
1203
- code: self.auditResult,
1204
- name: self.handleButtonsNames[self.auditResult]
1205
- }
1206
- if (self.auditResult === '82' && (self.targetTaskNode == '' || self.targetTaskNode == null)) {
1207
- self.auditResult = '';
1208
- self.$Message.error(`请选择${self.handleName}节点!`);
1209
- } else {
1210
- self.loading = true
1211
- self.disable = true
1212
- self.auditParams.targetTaskNode = self.targetTaskNode
1213
- let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1214
- ajax.post(url, self.auditParams).then(function (resp) {
1215
- let result = resp.data
1216
- if (result.code == '200') {
1217
- self.loading = false
1218
- self.disable = false
1219
- self.$Message.success(result.message ? result.message : `${self.handleName}成功`);
1220
- if (result.data){
1221
- let taskIds = result.data.id ? result.data.id : result.data.map(item => item.id).join(',');
1222
- setTimeout(() => {
1223
- self.executionCompleted(true, result.data.id ? result.data.processInstanceId : result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1224
- }, 1000)
1225
- } else {
1226
- setTimeout(() => {
1227
- self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1228
- }, 1000)
1229
- }
1230
- } else if (result.code == '10012') {
1231
- // 数据同步
1232
- self.loading = false
1233
- self.disable = false
1234
- self.$Message.warning(result.message)
1235
- setTimeout(() => {
1236
- self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1237
- }, 1000)
1238
- } else if (result.code == '20002') {
1239
- // 流程结束
1240
- self.loading = false
1241
- self.disable = false
1242
- self.$Message.success(result.message)
1243
- setTimeout(() => {
1244
- self.executionCompleted(true, '流程已结束', '流程已结束', auditResult, self.curTaskId)
1245
- }, 1000)
1246
- } else {
1247
- self.loading = false
1248
- self.disable = false
1249
- self.$Message.error(result.message ? result.message : `${self.handleName}失败`)
1250
- setTimeout(() => {
1251
- self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1252
- }, 1000)
1253
- }
1254
- bus.$emit('triggerTimer')
1255
- })
1256
- }
1257
- },
1258
-
1259
- doSearch() {
1260
- //不需要实现,是子组件assigneeBox要求使用父组件的这个方法
1261
- },
1262
- tabsChange(tab) {
1263
- console.log(tab)
1264
- },
1265
- getAttach(row) {
1266
- window.open(this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId, "_blank");
1267
- },
1268
- preViewAttach(row) {
1269
- let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
1270
- let regs = /\.(pdf)$/
1271
- if (reg.test(row.fileName)) {
1272
- let url = this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId;
1273
- this.imgPreview(url);
1274
- } else if (regs.test(row.fileName)) {
1275
- window.open(this.smartFlowServerContext + "/manage/oss/file/getFileStream?fileId=" + row.fileId, "_blank");
1276
- } else {
1277
- this.modalDocx = true
1278
- axios({
1279
- method: 'get',
1280
- responseType: 'blob', // 因为是流文件,所以要指定blob类型
1281
- url: this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId// 一个word下载文件的接口
1282
- }).then(({data}) => {
1283
- docx.renderAsync(data, this.$refs.file, null, {
1284
- className: "docx", //默认和文档样式类的类名/前缀
1285
- inWrapper: true, //启用围绕文档内容呈现包装器
1286
- ignoreWidth: false, //禁用页面的渲染宽度
1287
- ignoreHeight: false, //禁用页面的渲染高度
1288
- ignoreFonts: false, //禁用字体渲染
1289
- breakPages: true, //在分页符上启用分页
1290
- ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
1291
- experimental: false, //启用实验功能(制表符停止计算)
1292
- trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
1293
- useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
1294
- useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
1295
- showChanges: false, //启用文档更改的实验渲染(插入/删除)
1296
- debug: false, //启用额外的日志记录
1297
- })
1298
- }
1299
- )
1300
- }
1301
- },
1302
- imgPreview(url) {
1303
- this.imageUrl = url;
1304
- this.modalVisible = true;
1305
- },
1306
-
1307
- //打印流程图信息
1308
- processPrint() {
1309
- let self = this
1310
- let params = {
1311
- applyId: self.applyId,
1312
- instanceId: self.instanceId,
1313
- procId: self.procId,
1314
- taskId: self.curTaskId,
1315
- }
1316
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getPrintData', {params: params}).then(function (resp) {
1317
- let result = resp.data.data
1318
- if (resp.data.code === '200') {
1319
- let tableData = result
1320
- self.process.tableData = tableData
1321
- self.process.applyId = self.applyId
1322
- self.process.instanceId = self.instanceId
1323
- self.process.procId = self.procId
1324
- self.datas.orgId = tableData[0].orgId
1325
- self.datas.orgName = tableData[0].orgName
1326
- self.modalBoxShow = true
1327
- }
1328
- })
1329
- },
1330
-
1331
- showTaskNode(taskId) {
1332
- if (this.processHistory.length > 0) {
1333
- let task = null
1334
- this.processHistory.some(itemList => {
1335
- task = itemList.find(item => item.taskId === taskId);
1336
- return task !== undefined;
1337
- });
1338
- return task ? task.taskName : ''
1339
- }
1340
- return ''
1341
- },
1342
- cancel() {
1343
- this.modal = false
1344
- this.auditResult = '';
1345
- },
1346
- selectNode(currentRow, oldCurrentRow) {
1347
- let self = this
1348
- self.targetTaskNode = currentRow.taskNode
1349
- },
1350
- getAllPreNodes() {
1351
- let self = this
1352
- let params = {
1353
- processDefId: self.procId,
1354
- taskId: self.curTaskId,
1355
- }
1356
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getAllPreNodes', {params: params}).then(function (resp) {
1357
- if (resp.data.code === '200') {
1358
- if (resp.data.data.length > 0) {
1359
- self.allNode = resp.data.data
1360
- self.modal1 = true
1361
- } else {
1362
- self.$Message.warning('当前流程无前序节点')
1363
- }
1364
- } else {
1365
- self.$Message.error(resp.data.message)
1366
- }
1367
- })
1368
- },
1369
- getNodesBehind() {
1370
- let self = this
1371
- let params = {
1372
- processDefId: self.procId,
1373
- taskId: self.curTaskId,
1374
- }
1375
- ajax.get(self.smartFlowServerContext + '/manage/processTodo/getNodesBehind', {params: params}).then(function (resp) {
1376
- if (resp.data.code === '200') {
1377
- if (resp.data.data.length > 0) {
1378
- self.allNode = resp.data.data
1379
- self.modal1 = true
1380
- } else {
1381
- self.$Message.warning('当前流程无后续节点')
1382
- }
1383
- } else {
1384
- self.$Message.error(resp.data.message)
1385
- }
1386
- })
1387
- },
1388
- handleSelectedUser(userId) {
1389
- this.selectedUserId = userId;
1390
- },
1391
-
1392
- //折叠动画效果
1393
- beforeEnter(el) {
1394
- el.style.height = '0';
1395
- },
1396
- enter(el, done) {
1397
- setTimeout(() => {
1398
- el.style.height = el.scrollHeight + 'px';
1399
- }, 0);
1400
-
1401
- el.addEventListener('transitionend', done);
1402
- },
1403
- beforeLeave(el) {
1404
- el.style.height = el.scrollHeight + 'px';
1405
- },
1406
- leave(el, done) {
1407
- setTimeout(() => {
1408
- el.style.height = '0';
1409
- }, 0);
1410
-
1411
- el.addEventListener('transitionend', done);
1412
- },
1413
-
1414
- beforeFlowInfoEnter(el) {
1415
- el.style.transform = 'translateX(100%)';
1416
- },
1417
- flowInfoEnter(el, done) {
1418
- const transitionDuration = 0.5;
1419
- el.style.transition = `transform ${transitionDuration}s`;
1420
- el.style.transform = 'translateX(0)';
1421
- el.addEventListener('transitionend', done);
1422
- },
1423
- beforeFlowInfoLeave(el) {
1424
- el.style.transform = 'translateX(0)';
1425
- },
1426
- flowInfoLeave(el, done) {
1427
- const transitionDuration = 0.5;
1428
- el.style.transition = `transform ${transitionDuration}s`;
1429
- el.style.transform = 'translateX(100%)';
1430
- el.addEventListener('transitionend', done);
1431
- },
1432
- uploadFile(file) {
1433
- const self = this;
1434
- self.fileList = []
1435
- file.forEach(item => {
1436
- self.fileList.push({
1437
- fileName: item.fileName,
1438
- fileId: item.fileCode,
1439
- });
1440
- })
1441
- },
1442
-
1443
- appointOk() {
1444
- const self = this
1445
- let oldSettings
1446
- let params = this.nextNodesFormList.reduce((acc, item) => {
1447
- acc[item.id] = {
1448
- needUpdate: 'false',
1449
- }
1450
- item.assignee ? acc[item.id].assignee = item.assignee : ''
1451
- item.candidateGroups ? acc[item.id].candidateGroup = item.candidateGroups : ''
1452
- let timeLimit = 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1453
- if(!(item.remainDay === 0 && item.remainTime === 0 && item.inAdvanceDay === 0 && item.inAdvanceTime === 0)) {
1454
- timeLimit = 'expireTime:' + parseInt(item.remainDay) + "D" + parseInt(item.remainTime) + "H" + ";warningTime:" + parseInt(item.inAdvanceDay) + "D" + parseInt(item.inAdvanceTime) + "H;" + "handleType:" + item.processing;
1455
- acc[item.id].timeLimit = timeLimit
1456
- } else {
1457
- acc[item.id].timeLimit = ''
1458
- }
1459
- oldSettings = self.nextNodesOldSettings.filter(oldSetting => oldSetting.id === item.id)[0]
1460
- if (oldSettings.assignee !== item.assignee || self.checkGroupsUpdate(oldSettings.candidates, item.candidateGroups) || self.checkTimeLimitUpdate(oldSettings.timeLimit, timeLimit)) {
1461
- acc[item.id].needUpdate = 'true'
1462
- }
1463
- return acc;
1464
- }, {});
1465
- self.auditParams.nodeConfigMaps = JSON.stringify(params)
1466
- self.doPass((execResult, instanceId, taskIds, auditResult, curTaskId) => {
1467
- if (this.executionCompleted) {
1468
- this.executionCompleted(execResult, instanceId, taskIds, auditResult, curTaskId);
1469
- }
1470
- })
1471
- },
1472
- checkGroupsUpdate(oldSetting, newSetting) {
1473
- if (oldSetting && newSetting) {
1474
- let oldIdList = []
1475
- for (let [key, value] of Object.entries(oldSetting)) {
1476
- if (value) {
1477
- value.split(',').forEach(part => {
1478
- const [id] = part.split(':');
1479
- if (id) {
1480
- oldIdList.push(id);
1481
- }
1482
- })
1483
- }
1484
- }
1485
- const regex = /(?:O:|U:|P:|R:|T:)([^,]+)/g;
1486
- let match;
1487
- const newIds = [];
1488
- while ((match = regex.exec(newSetting)) !== null) {
1489
- newIds.push(...match[1].split(';'))
1490
- }
1491
- const allInString = oldIdList.every(item => newIds.includes(item));
1492
- const hasExtra = newIds.some(item => !oldIdList.includes(item));
1493
- return !allInString || hasExtra
1494
- }
1495
- return false
1496
- },
1497
- checkTimeLimitUpdate(oldSetting, newSetting){
1498
- if (oldSetting && newSetting){
1499
- return oldSetting !== newSetting
1500
- }
1501
- if (!oldSetting){
1502
- return newSetting !== 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1503
- }
1504
- return false
1505
- },
1506
- readingRangeClick(item) {
1507
- let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1508
- let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1509
- this.$refs.assigneeHelpBox.toggleShowHelpBox(orgTreeType, permScope, 'transferNextTask', item.id)
1510
- },
1511
- candidateGroupsReadingRangeClick(item) {
1512
- let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1513
- let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1514
- this.$refs.candidateGroupsHelpBox.toggleShowHelpBox(permScope, item.candidates, orgTreeType, item.id);
1515
- },
1516
- updateCandGroups(newCandGroups, nameStr, detail, nodeId){
1517
- let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1518
- if (JSON.stringify(oldSettings.candidates) != JSON.stringify(detail)) {
1519
- let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1520
- node.candidateGroups = newCandGroups
1521
- node.candidateNames = nameStr
1522
- node.candidates = detail
1523
- node.needUpdate = true
1524
- this.$forceUpdate();
1525
- }
1526
- },
1527
- updateNextNodeAssignee(selectedAssigneeId, selectedAssigneeName, nodeId){
1528
- let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1529
- if (oldSettings.assignee != selectedAssigneeId) {
1530
- let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1531
- node.assignee = selectedAssigneeId
1532
- node.assigneeName = selectedAssigneeName
1533
- node.needUpdate = true
1534
- this.$forceUpdate();
1535
- }
1536
- }
1537
- },
1538
- watch: {
1539
- auditOpinionText(label) {
1540
- this.form.auditOpinion = label;
1541
- },
1542
- procId(val) {
1543
- this.procId = val;
1544
- this.initData()
1545
- },
1546
- }
1547
- }
1548
- </script>
1549
-
1550
- <style lang="less" scoped>
1551
- @import "./styles/css/index.less";
1552
-
1553
- /deep/ .ivu-table-row-highlight td {
1554
- background-color: #50c1ff !important;
1555
- color: #fff !important;
1556
- }
1557
-
1558
- /deep/ .ivu-card-body {
1559
- padding: 10px;
1560
- }
1561
-
1562
- .page-info /deep/ .page-body {
1563
- overflow-y: hidden;
1564
- }
1565
- </style>
1
+ <template>
2
+ <LamboPageContainer>
3
+ <template slot="page-title">
4
+ {{ title }}
5
+ </template>
6
+ <template slot="page-extend">
7
+ <slot name="return-button"></slot>
8
+ </template>
9
+ <div class="portrait-lambo-indicator-card"
10
+ :style="{float: 'left', width: isExpanded && showProcessInfo ? `calc(100% - ${portraitWidth+10}px)` : '99%'}">
11
+ <slot name="business-content">
12
+ </slot>
13
+ </div>
14
+
15
+ <a v-if="showProcessInfo" @click="isExpanded = !isExpanded" class="arrow-button-container"
16
+ :style="{right: isExpanded ? portraitWidth+10 + 'px' : '10px'}">
17
+ <Icon class="icon-class" v-if="isExpanded" type="ios-arrow-forward"/>
18
+ <Icon class="icon-class" v-if="!isExpanded" type="ios-arrow-back"/>
19
+ </a>
20
+ <transition v-if="showProcessInfo" name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
21
+ @before-leave="beforeFlowInfoLeave" @leave="flowInfoLeave">
22
+ <lamboIndicatorCard v-if="isExpanded" class="portrait-lambo-indicator-card"
23
+ :style="{width: portraitWidth + 'px', float: 'right'}" :hasExtend="false">
24
+ <div slot="content-title">流程信息</div>
25
+ <a v-if="!isDetail" @click="auditShow = !auditShow">
26
+ <Title
27
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
28
+ <a style="color: #989898">
29
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
30
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
31
+ {{ handleName }}信息
32
+ </a>
33
+ </Title>
34
+ </a>
35
+ <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave"
36
+ @leave="leave">
37
+ <div class="box" v-show="auditShow">
38
+ <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
39
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
40
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
41
+ <FormItem :label="auditOpinionTitle" prop="auditOpinion">
42
+ <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
43
+ :attachmentdata="fileList" :default-audit-opinion="defaultAuditOpinion"
44
+ :smart-flow-server-context="smartFlowServerContext"></AuditOpinion>
45
+ </FormItem>
46
+ </Form>
47
+ <Form ref="auditOpinion" justify="center" :label-width="100"
48
+ v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
49
+ style="margin: 10px 0 0 10px;">
50
+ <FormItem style="min-height: 70px">
51
+ <Tooltip placement="bottom" max-width="200">
52
+ <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg
53
+ .png .gif
54
+ </div>
55
+ <UploadFile @upload-result="uploadFile" :multiple="true"
56
+ :oss-server-context="smartFlowServerContext"
57
+ :oss-file-put-url="ossFilePutUrl"></UploadFile>
58
+ </Tooltip>
59
+ </FormItem>
60
+ </Form>
61
+ </div>
62
+ </transition>
63
+ <a v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
64
+ <Title
65
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
66
+ <a style="color: #989898">
67
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
68
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
69
+ {{ handleName }}信息
70
+ </a>
71
+ </Title>
72
+ </a>
73
+ <transition v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" name="draw" @before-enter="beforeEnter"
74
+ @enter="enter" @before-leave="beforeLeave" @leave="leave">
75
+ <div class="box" v-show="auditShow">
76
+ <Form ref="auditOpinion" justify="center" :model="form"
77
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
78
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
79
+ <FormItem style="margin-left: -60px">
80
+ <Card v-for="(item, index) in hisAuditOpinion" :key="index">
81
+ <Row>
82
+ <Col span="12" style="word-wrap: break-word">{{ item.auditOpinion }}</Col>
83
+ <Col span="2"></Col>
84
+ <Col span="10">{{ item.auditTime }}</Col>
85
+ </Row>
86
+ </Card>
87
+ </FormItem>
88
+ </Form>
89
+ </div>
90
+ </transition>
91
+ <a @click="historyShow = !historyShow">
92
+ <Title v-if="handleButtons && handleButtons.includes('auditHistory')">
93
+ <a style="color: #989898">
94
+ <Icon v-if="historyShow" type="ios-arrow-down"/>
95
+ <Icon v-if="!historyShow" type="ios-arrow-up"/>
96
+ {{ handleName }}记录
97
+ </a>
98
+ </Title>
99
+ </a>
100
+ <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
101
+ <div class="box" v-show="historyShow">
102
+ <Card class="process-history" :style="processHistoryHeight" dis-hover :bordered="false"
103
+ v-if="handleButtons && handleButtons.includes('auditHistory')">
104
+ <processHistory :portrait-width="portraitWidth" :list="processHistory" :done-page="isDetail" :push-button="pushButton"
105
+ :smart-flow-server-context="smartFlowServerContext"></processHistory>
106
+ </Card>
107
+ </div>
108
+ </transition>
109
+
110
+ <a @click="attachListShow = !attachListShow">
111
+ <Title v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0">
112
+ <a style="color: #989898">
113
+ <Icon v-if="attachListShow" type="ios-arrow-down"/>
114
+ <Icon v-if="!attachListShow" type="ios-arrow-up"/>
115
+ 查看附件
116
+ </a>
117
+ </Title>
118
+ </a>
119
+ <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
120
+ <div class="box"
121
+ v-show="handleButtons && handleButtons.includes('auditHistory') && attachmentList.length > 0 && attachListShow">
122
+ <div v-for="(item, index) in attachmentList" :key="index">
123
+ <Card dis-hover class="attach-card">
124
+ <List item-layout="vertical">
125
+ <ListItem style="margin-top: -8px">
126
+ <Row style="display: flex; align-items: center;">
127
+ <!-- 左边:图片 -->
128
+ <Col span="4" style="margin-top: -25px">
129
+ <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar"
130
+ style="background-color: #005aff"
131
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
132
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
133
+ <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar"
134
+ style="background-color: #005aff"
135
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
136
+ :size="portraitWidth >= 600 ? 'middle' : 'small'">
137
+ </avatar>
138
+ <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar"
139
+ style="background-color: #19be6b"
140
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
141
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
142
+ <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar"
143
+ style="background-color: #ed4014"
144
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
145
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
146
+ <avatar v-else icon="ios-document-outline" class="attach-avatar"
147
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
148
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
149
+ </Col>
150
+ <!-- 右边:附件信息 -->
151
+ <Col span="20">
152
+ <Row>
153
+ <tooltip>
154
+ <span class="attach-name-style"> {{ item.attachName }}</span>
155
+ <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
156
+ </tooltip>
157
+ </Row>
158
+ <Row style="margin-top: 3px">
159
+ <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
160
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
161
+ type="vertical"/>
162
+ <span style="color: #808695;font-size: 13px"
163
+ >{{ showTaskNode(item.taskId) }}</span>
164
+ </Row>
165
+ <Row style="margin-bottom: -10px; margin-top: 10px">
166
+ <template>
167
+ <Button @click="getAttach(item)" size="small">下载</Button>
168
+ <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
169
+ style="margin-left: 10px" size="small">预览
170
+ </Button>
171
+ </template>
172
+ </Row>
173
+ </Col>
174
+ </Row>
175
+
176
+ </ListItem>
177
+ </List>
178
+ </Card>
179
+ </div>
180
+ </div>
181
+ </transition>
182
+ <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
183
+ <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
184
+ <div slot="footer">
185
+ <Button type="primary" @click="modalVisible = false">关闭</Button>
186
+ </div>
187
+ </Modal>
188
+ <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
189
+ <div ref="file"></div>
190
+ </Modal>
191
+ </lamboIndicatorCard>
192
+ </transition>
193
+
194
+ <Modal v-model="modal1" title="选择节点"
195
+ @on-cancel="cancel"
196
+ @on-ok="doPass">
197
+ <Table border
198
+ :data="allNode"
199
+ :columns="nodeColumn"
200
+ highlight-row
201
+ @on-current-change="selectNode">
202
+ </Table>
203
+ </Modal>
204
+ <assigneeBox ref="assigneeHelpBox" :execution-completed="executionCompleted"
205
+ @update-selected="handleSelectedUser" @update-next-node-assignee="updateNextNodeAssignee"
206
+ :data="assigneeBoxData" :smart-flow-server-context="smartFlowServerContext"
207
+ :upms-server-context="upmsServerContext"/>
208
+ <Modal v-model="modalBoxShow" width="1000" title="流程跟踪图">
209
+ <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId"
210
+ :procId="process.procId" :table-columns="diagramTableColumns"
211
+ :tableData="process.tableData" :hisAudit="hisAudit" :approve-detail-show-way="approveDetailShowWay"
212
+ :smart-flow-server-context="smartFlowServerContext">
213
+ </Workflow_Diagram>
214
+ </Modal>
215
+ <Modal v-model="appointBoxShow" title="下一环节设置"
216
+ @on-cancel="appointBoxShow = false" width="600"
217
+ @on-ok="appointOk">
218
+ <Card v-for="(item,index) of nextNodesFormList" :key="index" style="margin-bottom: 10px"
219
+ v-if="handleButtons && (handleButtons.includes('appointHandler') || handleButtons.includes('appointTimeoutTime'))">
220
+ <Form ref="appointBox" justify="center" :label-width="100" :model="item"
221
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
222
+ <div v-if="handleButtons && handleButtons.includes('appointHandler')">
223
+ <FormItem label="下一环节:">
224
+ {{ item.name }}
225
+ </FormItem>
226
+ <FormItem label="人员类型:" v-if="!item.isMultiInstance">
227
+ <RadioGroup v-model="item.actionType">
228
+ <Radio label="ASSIGNEE">办理人</Radio>
229
+ <Radio label="CAND">候选人</Radio>
230
+ </RadioGroup>
231
+ </FormItem>
232
+ <FormItem label="办理人员:" prop="assignee" v-if="!item.isMultiInstance && item.actionType === 'ASSIGNEE'">
233
+ <Input v-model="item.assigneeName"
234
+ placeholder="请选择办理人"
235
+ style="width: 68%"
236
+ icon="md-apps"
237
+ @on-focus="readingRangeClick(item)"
238
+ @on-click="readingRangeClick(item)"/>
239
+ </FormItem>
240
+ <FormItem label="候选人员:" prop="candidateGroups" v-if="!item.isMultiInstance && item.actionType === 'CAND'">
241
+ <Input v-model="item.candidateNames"
242
+ placeholder="请选择候选人"
243
+ style="width: 68%"
244
+ icon="md-apps"
245
+ @on-focus="candidateGroupsReadingRangeClick(item)"
246
+ @on-click="candidateGroupsReadingRangeClick(item)"/>
247
+ </FormItem>
248
+ <FormItem label="候选人员:" prop="candidateGroups" v-if="item.isMultiInstance && item.actionType === 'CAND'">
249
+ </FormItem>
250
+
251
+ <countersingersBox style="margin-bottom: 10px" v-model="item.candidateNames" v-if="item.isMultiInstance && item.actionType === 'CAND'"
252
+ :item="item" :permScope="permScope" @update-cand-groups="updateCandGroups" :upms-server-context="upmsServerContext" :smart-flow-server-context="smartFlowServerContext"/>
253
+ </div>
254
+ <div v-if="handleButtons && handleButtons.includes('appointTimeoutTime')">
255
+ <Row>
256
+ <Col span="12">
257
+ <FormItem label="停留时间:">
258
+ <Input v-model="item.remainDay" style="width: 100px" type="number" :min="0"></Input>
259
+
260
+ </FormItem>
261
+ </Col>
262
+ <Col span="12">
263
+ <FormItem>
264
+ <Input v-model="item.remainTime" style="margin-left: -140px; width: 100px" type="number"
265
+ :min="0"></Input>
266
+ 小时 自动处理
267
+ </FormItem>
268
+ </Col>
269
+ </Row>
270
+ <Row>
271
+ <Col span="12">
272
+ <FormItem label="任务提前:">
273
+ <Input v-model="item.inAdvanceDay" style="width: 100px" type="number" :min="0"></Input>
274
+
275
+ </FormItem>
276
+ </Col>
277
+ <Col span="12">
278
+ <FormItem>
279
+ <Input v-model="item.inAdvanceTime" style="margin-left: -140px;width: 100px" type="number"
280
+ :min="0"></Input>
281
+ 小时 标红预警
282
+ </FormItem>
283
+ </Col>
284
+ </Row>
285
+ <FormItem label="处理方式:">
286
+ <Select v-model="item.processing" style="width:200px" placeholder="自动同意">
287
+ <Option v-for="item in handleTypeList" :value="item.value" :key="item.value">
288
+ {{ item.label }}
289
+ </Option>
290
+ </Select>
291
+ </FormItem>
292
+ </div>
293
+ </Form>
294
+ </Card>
295
+ </Modal>
296
+ <candidateGroupsHelpBox ref="candidateGroupsHelpBox" :show="candidateGroupsHelpBoxShow" @update-cand-groups="updateCandGroups"
297
+ :upms-server-context="upmsServerContext" :smart-flow-server-context="smartFlowServerContext"/>
298
+ <template slot="page-footer">
299
+ <div>
300
+ <slot name="footer-button"></slot>
301
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo70') && !isDetail"
302
+ :disabled="disable" :loading="loading" @click="audit('70')">驳回到原点
303
+ </Button>
304
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo40') && !isDetail"
305
+ :disabled="disable" :loading="loading" @click="audit('40')">驳回上一节点
306
+ </Button>
307
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo90') && !isDetail"
308
+ :disabled="disable" :loading="loading" @click="audit('90')">驳回指定节点
309
+ </Button>
310
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo80') && !isDetail"
311
+ :disabled="disable" :loading="loading" @click="audit('80')">跳转指定节点
312
+ </Button>
313
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo82') && !isDetail"
314
+ :disabled="disable" :loading="loading" @click="audit('82')">指定他人处理
315
+ </Button>
316
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo50') && !isDetail"
317
+ :disabled="disable" :loading="loading" @click="audit('50')">直接结束流程
318
+ </Button>
319
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('processTrace')"
320
+ @click="processPrint">流程跟踪图
321
+ </Button>
322
+ <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo30') && !isDetail"
323
+ :disabled="disable" :loading="loading" type="primary" @click="audit('30')">通过
324
+ </Button>
325
+ </div>
326
+ </template>
327
+ </LamboPageContainer>
328
+ </template>
329
+
330
+
331
+ <script>
332
+ import LamboPageContainer from '@lambo-design/page-container'
333
+ import LamboIndicatorCard from '@lambo-design/indicator-card'
334
+ import Workflow_Diagram from './workflow-diagram'
335
+ import ajax from "@lambo-design/shared/utils/ajax";
336
+ import bus from '@lambo-design/shared/utils/bus';
337
+ import Title from "./components/title";
338
+ import processHistory from "./components/history";
339
+ import assigneeBox from "./components/assignee-box";
340
+ import CandidateGroupsHelpBox from "./components/candidate-groups-box";
341
+ import CountersingersBox from "./components/countersigners-box"
342
+ import LamboPagingTable from "@lambo-design/paging-table";
343
+ import AuditOpinion from "./components/opinion";
344
+ import axios from "axios";
345
+ import UploadFile from "@lambo-design/upload-file";
346
+ import {timestampToTime} from "@lambo-design/shared/utils/date";
347
+
348
+ // 引入docx-preview插件
349
+ let docx = require('docx-preview');
350
+
351
+
352
+ export default {
353
+ props: {
354
+ isDetail: {
355
+ type: Boolean,
356
+ required: false,
357
+ default: false
358
+ },
359
+ width: {
360
+ type: Number,
361
+ required: false,
362
+ default: 400
363
+ },
364
+ procId: {
365
+ type: String,
366
+ required: true,
367
+ },
368
+ taskNode: {
369
+ type: String,
370
+ required: true,
371
+ },
372
+ applyId: {
373
+ type: String,
374
+ required: true,
375
+ },
376
+ taskId: {
377
+ type: String,
378
+ required: false,
379
+ default: '',
380
+ },
381
+ auditGroup: {
382
+ type: String,
383
+ required: false,
384
+ default: '',
385
+ },
386
+ defaultAuditOpinion: {
387
+ type: String,
388
+ required: false,
389
+ default: '',
390
+ },
391
+ //详情页催办按钮
392
+ pushButton: {
393
+ type: Boolean,
394
+ required: false,
395
+ default: true,
396
+ },
397
+ //流程跟踪图附件列
398
+ showAttachmentFile: {
399
+ type: Boolean,
400
+ required: false,
401
+ default: true,
402
+ },
403
+ //流程跟踪图审批详情触发方式
404
+ approveDetailShowWay: {
405
+ type: String,
406
+ required: false,
407
+ default: 'click',
408
+ },
409
+ //业务表单保存方法
410
+ businessFormSave: {
411
+ type: Function,
412
+ required: false
413
+ },
414
+ //按钮执行完毕回调方法
415
+ executionCompleted: {
416
+ type: Function,
417
+ required: false,
418
+ default: () => {}
419
+ },
420
+ title: {
421
+ type: String,
422
+ default: "流程办理"
423
+ },
424
+ smartFlowServerContext: {
425
+ type: String,
426
+ default: '/api/smart-flow-server',
427
+ },
428
+ upmsServerContext: {
429
+ type: String,
430
+ default: '/api/upms-server',
431
+ },
432
+ },
433
+ components: {
434
+ Title,
435
+ LamboPageContainer,
436
+ Workflow_Diagram,
437
+ processHistory,
438
+ assigneeBox,
439
+ LamboPagingTable,
440
+ AuditOpinion,
441
+ LamboIndicatorCard,
442
+ UploadFile,
443
+ CandidateGroupsHelpBox,
444
+ CountersingersBox
445
+ },
446
+ data() {
447
+ return {
448
+ isExpanded: true,
449
+ showProcessInfo: true,
450
+ portraitWidth: 0,
451
+ requestSuccessCodes: [200, "200"],
452
+ auditShow: true,
453
+ historyShow: true,
454
+ attachListShow: true,
455
+ attachmentList: [],
456
+ modalVisible: false,
457
+ modalDocx: false,
458
+ imageUrl: '',
459
+ assigneeBoxData: {},
460
+ selectedUserId: '',
461
+ targetTaskNode: '',
462
+ allNode: [],
463
+ auditParams: {},
464
+ modal1: false,
465
+ modalBoxShow: false,
466
+ candidateGroupsHelpBoxShow: false,
467
+ appointBoxShow: false,
468
+ autoOpenNode: '0',
469
+ nextNodesOldSettings: [],
470
+ nextNodesFormList: [],
471
+ hisNode: [],
472
+ processHistory: [],
473
+ permScope: '',
474
+ organTreeType: '00',
475
+ defaultOrganTreeType: '00',
476
+ ruleValidate: {
477
+ auditOpinion: [{required: true, trigger: "blur", message: '意见不能为空'}],
478
+ assignee: [{required: true, trigger: "blur", message: "办理人不能为空"}],
479
+ candidateGroups: [{required: true, trigger: "blur", message: "候选人不能为空"}],
480
+ },
481
+ form: {
482
+ auditOpinion: '',
483
+ },
484
+ loading: false,
485
+ disable: false,
486
+ instanceId: '',
487
+ curTaskId: '',
488
+ handleButtons: [],
489
+ handleName: '',
490
+ auditOpinionTitle: '',
491
+ auditResult: '',
492
+ curAuditGroup: '',
493
+ custChange: 'auditInfo',
494
+ auditInfo: "auditInfo",
495
+ auditProcess: "auditProcess",
496
+ fileList: [],
497
+ ossFilePutUrl: '/manage/oss/file/put',
498
+ hisAudit: [],
499
+ hisAuditOpinion: [{
500
+ auditOpinion: '',
501
+ auditTime: '',
502
+ }],
503
+ datas: {
504
+ orgName: "",
505
+ orgId: ""
506
+ },
507
+ editForm: {
508
+ approvalCost: '',
509
+ cost: '',
510
+ activityDate: []
511
+ },
512
+ process: {
513
+ tableData: [],
514
+ instanceId: '',
515
+ applyId: '',
516
+ procId: ''
517
+ },
518
+ handleButtonsNames: {
519
+ '30': '通过',
520
+ '70': '驳回到原点',
521
+ '40': '驳回上一节点',
522
+ '90': '驳回指定节点',
523
+ '80': '跳转指定节点',
524
+ '82': '指定他人处理',
525
+ '50': '直接结束流程'
526
+ },
527
+ handleTypeList: [
528
+ {
529
+ value: '00',
530
+ label: '只预警不处理'
531
+ },
532
+ {
533
+ value: '10',
534
+ label: '自动同意'
535
+ },
536
+ {
537
+ value: '20',
538
+ label: '直接终止流程'
539
+ },
540
+ {
541
+ value: '90',
542
+ label: '自动驳回'
543
+ }
544
+ ],
545
+ }
546
+
547
+ },
548
+
549
+ mounted() {
550
+ this.getWidth()
551
+ if (this.procId) {
552
+ this.initData()
553
+ }
554
+
555
+ },
556
+ computed: {
557
+ processHistoryHeight() {
558
+ let str = '';
559
+ const hasAuditOpinion = this.taskNode && this.handleButtons && this.handleButtons.includes('auditOpinion')
560
+ const hasAttachmentFile = this.handleButtons && this.handleButtons.includes('auditHistory') && this.attachmentList.length > 0
561
+ const isDetail = this.isDetail && !this.hisAuditOpinion[0].auditOpinion.length > 0
562
+ if (hasAuditOpinion && !hasAttachmentFile && !isDetail) {
563
+ str += "height: 43vh"
564
+ } else if (hasAuditOpinion && hasAttachmentFile && !isDetail) {
565
+ str += "height: 40vh"
566
+ } else {
567
+ str += "height: 67vh"
568
+ }
569
+ return str;
570
+ },
571
+ nodeColumn: function () {
572
+ let column = []
573
+ column.push({title: '序号', type: 'index', width: 70, align: 'center', fixed: 'left'});
574
+ column.push({title: '节点名称', key: 'taskName', minWidth: 150, align: 'center', fixed: 'left'})
575
+
576
+ column.push({
577
+ title: '节点状态', key: 'auditResult', minWidth: 150, align: 'center', fixed: 'left',
578
+ render: (h, params) => {
579
+ if (params.row.taskNode == this.taskNode) {
580
+ return h('div', [
581
+ h('tag', {
582
+ props: {
583
+ color: '#ff9900'
584
+ }
585
+ }, '当前节点')
586
+ ])
587
+ } else if (!params.row.auditResult) {
588
+ return h('div', [
589
+ h('tag', {
590
+ props: {
591
+ color: '#ff9900'
592
+ }
593
+ }, `未${params.row.handleName ? params.row.handleName : '审批'}`)
594
+ ])
595
+ } else {
596
+ if (params.row.auditResult == '30' && params.row.taskNode != this.taskNode) {
597
+ return h('div', [
598
+ h('tag', {
599
+ props: {
600
+ color: '#19be6b'
601
+ }
602
+ }, `已${params.row.handleName ? params.row.handleName : '审批'}通过`)
603
+ ])
604
+ } else if (params.row.auditResult == '40' && params.row.taskNode != this.taskNode) {
605
+ return h('div', [
606
+ h('tag', {
607
+ props: {
608
+ color: '#ed4014'
609
+ }
610
+ }, '已驳回到上一节点')
611
+ ])
612
+ } else if (params.row.auditResult == '60' && params.row.taskNode != this.taskNode) {
613
+ return h('div', [
614
+ h('tag', {
615
+ props: {
616
+ color: '#ed4014'
617
+ }
618
+ }, '已撤回')
619
+ ])
620
+ } else if (params.row.auditResult == '80' && params.row.taskNode != this.taskNode) {
621
+ return h('div', [
622
+ h('tag', {
623
+ props: {
624
+ color: '#19be6b'
625
+ }
626
+ }, '已跳转到指定节点')
627
+ ])
628
+ } else if (params.row.auditResult == '90' && params.row.taskNode != this.taskNode) {
629
+ return h('div', [
630
+ h('tag', {
631
+ props: {
632
+ color: '#19be6b'
633
+ }
634
+ }, '已驳回到指定节点')
635
+ ])
636
+ }
637
+ }
638
+ }
639
+ })
640
+ column.push({
641
+ title: "操作", width: 100, align: 'center',
642
+ render: (h, params) => {
643
+ return h('div', [
644
+ h('Button', {
645
+ props: {
646
+ type: 'primary',
647
+ size: 'small'
648
+ },
649
+ style: {
650
+ marginRight: '5px'
651
+ },
652
+ on: {
653
+ click: () => {
654
+ this.selectNode(params.row)
655
+ }
656
+ }
657
+ }, '选择')
658
+ ])
659
+ },
660
+ })
661
+ return column
662
+ },
663
+ diagramTableColumns: function () {
664
+ let column = []
665
+ column.push({title: '序号', type: 'index', width: 60});
666
+ column.push({title: `${this.handleName}节点`, key: 'taskName', minWidth: 130})
667
+ column.push({title: `${this.handleName}人`, key: 'auditName', minWidth: 150, tooltip: true})
668
+ column.push({
669
+ title: `${this.handleName}结果`, key: 'auditResult', minWidth: 150, align: 'center',
670
+ render: (h, {row, column, index}) => {
671
+ let label = "";
672
+ let tagColor = "";
673
+ if (row.auditResult == '00'){
674
+ label = '流程发起';
675
+ tagColor = 'green'; // 绿色
676
+ }
677
+ else if (row.auditResult == '10'){
678
+ label = '自动跳过';
679
+ tagColor = 'green'; // 绿色
680
+ }
681
+ else if (row.auditResult == '30'){
682
+ label = '通过';
683
+ tagColor = 'green'; // 绿色
684
+ }
685
+ else if (row.auditResult == '40'){
686
+ label = '驳回到上一级';
687
+ tagColor = 'volcano'; // 火红色
688
+ }
689
+ else if (row.auditResult == '50'){
690
+ label = '驳回到原点';
691
+ tagColor = 'red'; // 红色
692
+ }
693
+ else if (row.auditResult == '51'){
694
+ label = '流程终止';
695
+ tagColor = 'purple'; // 紫色
696
+ }
697
+ else if (row.auditResult == '60'){
698
+ label = '撤回';
699
+ tagColor = 'blue'; // 蓝色
700
+ }
701
+ else if (row.auditResult == '80'){
702
+ label = '跳转到指定节点';
703
+ tagColor = 'cyan'; // 青色
704
+ }
705
+ else if (row.auditResult == '90'){
706
+ label = '驳回到指定节点';
707
+ tagColor = 'magenta'; // 品红色
708
+ }
709
+ else{
710
+ label = '待审核';
711
+ tagColor = 'orange'; // 默认橙色
712
+ }
713
+ return h('Tag', {
714
+ props: {
715
+ color: tagColor,
716
+ value: row.auditResult
717
+ }
718
+ }, label);
719
+ }
720
+ })
721
+ column.push({
722
+ title: `${this.handleName}时间`, key: 'auditTime', minWidth: 150,
723
+ render: (h, {row}) => {
724
+ const displayDate = row.startDate || row.auditDate;
725
+ return h('span', displayDate);
726
+ }
727
+ })
728
+ column.push({
729
+ title: `${this.handleName}意见`, key: 'auditComment', minWidth: 180, tooltip: true,
730
+ render: (h, {row, column, index}) => {
731
+ let label = "";
732
+ if (row.auditComment == '' || row.auditComment == null) label = '无';
733
+ else label = row.auditComment;
734
+ return h('Label', {
735
+ props: {
736
+ value: row.auditComment
737
+ }
738
+ }, label)
739
+ }
740
+ })
741
+ if (this.showAttachmentFile){
742
+ column.push({
743
+ title: `附件`, key: 'fileList', minWidth: 200,
744
+ render: (h, { row }) => {
745
+ if (!row.fileList || row.fileList.length === 0) {
746
+ return h('span', '无'); // 如果没有附件,显示“无”
747
+ }
748
+
749
+ //显示所有附件
750
+ return h('div', row.fileList.map(file => {
751
+ return h('a', {
752
+ style: {
753
+ display: 'block',
754
+ marginTop: '5px',
755
+ marginRight:'5px',
756
+ whiteSpace: 'nowrap',
757
+ overflow: 'hidden',
758
+ textOverflow: 'ellipsis',
759
+ maxWidth: '100px',
760
+ },
761
+ attrs: {
762
+ title: file.attachName // 鼠标悬停时显示完整名称
763
+ },
764
+ on: {
765
+ click: () => {
766
+ this.getAttach(file);
767
+ }
768
+ },
769
+ }, file.attachName);
770
+ }));
771
+ }
772
+ })
773
+ }
774
+
775
+ return column
776
+ },
777
+ },
778
+ provide() {
779
+ return {
780
+ toBeDoneListDoSearch: this.doSearch
781
+ };
782
+ },
783
+ methods: {
784
+ getWidth() {
785
+ if (this.width && this.width < 400) {
786
+ this.portraitWidth = 400
787
+ }
788
+ this.portraitWidth = this.width
789
+ },
790
+ initData() {
791
+ if (!this.isDetail) {
792
+ this.getTodoTask()
793
+ } else {
794
+ this.getDoneTask()
795
+ }
796
+ this.getHandleButtons()
797
+ },
798
+ getTodoTask() {
799
+ const self = this
800
+ let param = {
801
+ procId: this.procId,
802
+ applyId: this.applyId,
803
+ taskNode: this.taskNode,
804
+ taskId: this.taskId,
805
+ auditGroup: this.auditGroup
806
+ }
807
+ ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (resp) {
808
+ if (resp.data.code === '200') {
809
+ self.curTaskId = resp.data.data.rows[0].taskId
810
+ self.instanceId = resp.data.data.rows[0].procInstanceId
811
+ self.curAuditGroup = resp.data.data.rows[0].auditGroup
812
+ let procType = resp.data.data.rows[0].procType
813
+ ajax.get(self.smartFlowServerContext + "/manage/processType/lists?proType=" + procType)
814
+ .then(resp => {
815
+ let data = resp.data.data.rows
816
+ self.permScope = data[0].permScope
817
+ self.defaultOrganTreeType = data[0].organTreeType ? data[0].organTreeType : '00'
818
+ self.getNodeOrganTreeType(procType)
819
+ }).catch(err => {
820
+ console.log(err);
821
+ })
822
+ self.getAttachList(self.curTaskId)
823
+ self.getHisAudit(self.curTaskId);
824
+ self.getProcessHistory(self.curTaskId);
825
+ } else {
826
+ self.$Message.error(resp.data.message)
827
+ }
828
+ }).catch((err) => {
829
+ console.log(err)
830
+ })
831
+ },
832
+ getNodeOrganTreeType(procType){
833
+ const self = this
834
+ let param = {
835
+ procType: procType,
836
+ procId: this.procId,
837
+ taskNode: this.taskNode
838
+ }
839
+ ajax.get(self.smartFlowServerContext + "/manage/processTodo/getNodeOrganTreeType", {params: param}).then(function (resp) {
840
+ if (resp.data.code === '200') {
841
+ self.organTreeType = resp.data.data ? resp.data.data : self.defaultOrganTreeType
842
+ } else {
843
+ self.$Message.error(resp.data.message)
844
+ }
845
+ }).catch((err) => {
846
+ console.log(err)
847
+ })
848
+ },
849
+ getDoneTask() {
850
+ const self = this
851
+ let param = {
852
+ procId: this.procId,
853
+ applyId: this.applyId,
854
+ taskNode: this.taskNode,
855
+ taskId: this.taskId,
856
+ auditGroup: this.auditGroup
857
+ }
858
+ ajax.get(self.smartFlowServerContext + "/manage/processDone/getDoneDetail", {params: param}).then(function (resp) {
859
+ if (resp.data.code === '200') {
860
+ let rows = resp.data.data.rows
861
+ if (rows.length > 0) {
862
+ self.curAuditGroup = rows[0].auditGroup
863
+ self.hisAuditOpinion = []
864
+ let taskList = resp.data.data.rows
865
+ taskList.forEach(item => {
866
+ self.hisAuditOpinion.push({
867
+ auditOpinion: item.auditComment,
868
+ auditTime: timestampToTime(item.auditDate)
869
+ })
870
+ })
871
+ self.curTaskId = taskList[0].taskId
872
+ self.instanceId = taskList[0].procInstanceId
873
+ } else {
874
+ ajax.get(self.smartFlowServerContext + "/manage/processTodo/list", {params: param}).then(function (todoResp) {
875
+ if (todoResp.data.code === '200') {
876
+ self.curTaskId = todoResp.data.data.rows[0].taskId
877
+ self.instanceId = todoResp.data.data.rows[0].procInstanceId
878
+ self.curAuditGroup = todoResp.data.data.rows[0].auditGroup
879
+ } else {
880
+ self.$Message.error(todoResp.data.message)
881
+ }
882
+ }).catch((err) => {
883
+ console.log(err)
884
+ })
885
+ }
886
+ self.getAttachList(self.curTaskId)
887
+ self.getHisAudit(self.curTaskId);
888
+ self.getProcessHistory(self.curTaskId);
889
+ } else {
890
+ self.$Message.error(resp.data.message)
891
+ }
892
+ }).catch((err) => {
893
+ console.log(err)
894
+ })
895
+ },
896
+ getHandleButtons() {
897
+ const self = this
898
+ let param = {
899
+ procId: this.procId,
900
+ taskNode: this.taskNode
901
+ }
902
+ ajax.post(self.smartFlowServerContext + '/manage/approvalCenter/getNodeData', param).then(function (resp) {
903
+ if (resp.data.code === '200') {
904
+ self.handleButtons = resp.data.data[0].handleButtons
905
+ self.handleName = resp.data.data[0].handleName ? resp.data.data[0].handleName : '审批'
906
+ self.auditOpinionTitle = resp.data.data[0].handleName ? resp.data.data[0].handleName + '意见' : '审批意见'
907
+ if (!self.handleButtons || (!self.handleButtons.includes('auditOpinion') && !self.handleButtons.includes('attachmentFile') && !self.handleButtons.includes('auditHistory'))){
908
+ self.showProcessInfo = false
909
+ }
910
+ } else {
911
+ self.$Message.error(resp.data.message)
912
+ }
913
+ }).catch((err) => {
914
+ console.log(err)
915
+ })
916
+ },
917
+ getNextNodes(){
918
+ const self = this
919
+ self.nextNodesFormList = []
920
+ self.nextNodesOldSettings = []
921
+ let param = {
922
+ procId: this.procId,
923
+ taskNode: this.taskNode
924
+ }
925
+ ajax.post(self.smartFlowServerContext + '/manage/processTodo/getNextNodes', param).then(function (resp) {
926
+ if (resp.data.code === '200') {
927
+ let nextNodeForm = {}
928
+ let nextNodeOldForm = {}
929
+ let data = resp.data.data
930
+ for (let i = 0; i < data.length; i++) {
931
+ nextNodeOldForm = {
932
+ id: data[i].id,
933
+ assignee: data[i].assignee ? data[i].assignee.id : '',
934
+ timeLimit: data[i].timeLimit,
935
+ }
936
+ nextNodeForm = {
937
+ id: data[i].id,
938
+ name: data[i].name,
939
+ orgTreeType: data[i].orgTreeType,
940
+ assignee: data[i].assignee ? data[i].assignee.id : '',
941
+ assigneeName: data[i].assignee ? data[i].assignee.name : '',
942
+ candidateGroups: '',
943
+ isMultiInstance: data[i].isMultiInstance,
944
+ actionType: 'ASSIGNEE',
945
+ remainDay : 0,
946
+ remainTime : 0,
947
+ inAdvanceDay : 0,
948
+ inAdvanceTime : 0,
949
+ processing : '00'
950
+ }
951
+ //显示具体候选人信息
952
+ if (data[i].candidateGroups){
953
+ nextNodeForm.actionType = 'CAND'
954
+ let names = [];
955
+ let candidates = {};
956
+ for (let groupName in data[i].candidateGroups) {
957
+ if (data[i].candidateGroups.hasOwnProperty(groupName)) {
958
+ let group = data[i].candidateGroups[groupName];
959
+ group.forEach(item => {
960
+ names.push(item.name);
961
+ });
962
+ candidates[groupName] = group.map(item => item.id + ':' + item.name).join(',');
963
+ }
964
+ }
965
+ nextNodeForm.candidateNames = names.join(',');
966
+ nextNodeForm.candidates = candidates;
967
+ nextNodeOldForm.candidates = candidates;
968
+ }
969
+ if (data[i].timeLimit) {
970
+ let expireTime = data[i].timeLimit.split(";")[0].split(":")[1]
971
+ let warningTime = data[i].timeLimit.split(";")[1].split(":")[1]
972
+ let handleType = data[i].timeLimit.split(";")[2].split(":")[1]
973
+ let days = expireTime.slice(0, expireTime.indexOf("D")) //过期天
974
+ let hourOfDay = expireTime.slice(expireTime.indexOf("D") + 1, expireTime.indexOf("H")) //过期小时
975
+ let daysWarn = warningTime.slice(0, warningTime.indexOf("D")) //警告天
976
+ let hourOfDayWarn = warningTime.slice(warningTime.indexOf("D") + 1, warningTime.indexOf("H")) //警告小时
977
+ nextNodeForm.remainDay = parseInt(days)
978
+ nextNodeForm.remainTime = parseInt(hourOfDay)
979
+ nextNodeForm.inAdvanceDay = parseInt(daysWarn)
980
+ nextNodeForm.inAdvanceTime = parseInt(hourOfDayWarn)
981
+ nextNodeForm.processing = handleType
982
+ }
983
+ self.nextNodesFormList.push(nextNodeForm)
984
+ self.nextNodesOldSettings.push(nextNodeOldForm)
985
+ }
986
+ } else {
987
+ self.$Message.error(resp.data.message)
988
+ }
989
+ }).catch((err) => {
990
+ console.log(err)
991
+ })
992
+ },
993
+ getAttachList(taskId) {
994
+ const self = this
995
+ const param = {
996
+ taskId: taskId,
997
+ procId: this.procId,
998
+ applyId: this.applyId
999
+ }
1000
+ ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', {params: param}).then(function (resp) {
1001
+ self.attachmentList = resp.data.data.rows
1002
+ self.attachmentList.forEach(item => {
1003
+ const index = item.fileName.lastIndexOf(".")
1004
+ const fileType = item.fileName.substr(index + 1).toLowerCase()
1005
+ const imageList = ['jpg', 'gif', 'png', 'svg']
1006
+ const docList = ['doc', 'docx']
1007
+ const zipList = ['rar', 'zip']
1008
+ const typeList = ['jpg', 'gif', 'png', 'docx']
1009
+ item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
1010
+ item.showPreview = typeList.indexOf(fileType) !== -1
1011
+ })
1012
+ }).catch(err => {
1013
+ console.log(err);
1014
+ })
1015
+ },
1016
+ getHisAudit(taskId) {
1017
+ let self = this
1018
+ let params = {
1019
+ applyId: self.applyId,
1020
+ instanceId: self.instanceId,
1021
+ procId: self.procId,
1022
+ taskId: taskId
1023
+ }
1024
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getHisAudit', {params: params}).then(function (resp) {
1025
+ if (resp.data.code === '200') {
1026
+ self.hisAudit = resp.data.data
1027
+ let uniqueDataMap = {};
1028
+ self.hisAudit.forEach((item) => {
1029
+ uniqueDataMap[item["taskNode"]] = item;
1030
+ })
1031
+ self.hisNode = Object.values(uniqueDataMap);
1032
+
1033
+ }
1034
+ })
1035
+ },
1036
+ getProcessHistory(taskId) {
1037
+ let self = this
1038
+ let params = {
1039
+ applyId: self.applyId,
1040
+ instanceId: self.instanceId,
1041
+ procId: self.procId,
1042
+ taskId: taskId
1043
+ }
1044
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getProcessHis', {params: params}).then(function (resp) {
1045
+ if (resp.data.code === '200') {
1046
+ self.processHistory = resp.data.data
1047
+ }
1048
+ })
1049
+ },
1050
+
1051
+ audit: function (auditResult) {
1052
+ let self = this
1053
+ self.auditResult = auditResult
1054
+ self.submit()
1055
+ },
1056
+ submit() {
1057
+ let self = this;
1058
+ self.auditParams = {
1059
+ procId: self.procId,
1060
+ applyId: self.applyId,
1061
+ taskId: self.curTaskId,
1062
+ auditOpinion: self.form.auditOpinion,
1063
+ fileListStr: JSON.stringify(self.fileList),
1064
+ auditResult: self.auditResult,
1065
+ params: JSON.stringify(self.datas),
1066
+ targetTaskNode: self.targetTaskNode,
1067
+ selectedUserId: self.selectedUserId,
1068
+ }
1069
+ if (self.auditResult == '' || self.auditResult == null) {
1070
+ self.$Message.error(`请选择${self.handleName}结果!`);
1071
+ return;
1072
+ }
1073
+ if (self.form.auditOpinion == '' || self.form.auditOpinion == null) {
1074
+ if (!self.handleButtons || self.handleButtons.includes('auditOpinion')) {
1075
+ self.$Message.error(`请输入${self.handleName}意见!`)
1076
+ return;
1077
+ } else {
1078
+ self.auditParams.auditOpinion = self.handleButtonsNames[self.auditResult];
1079
+ }
1080
+ }
1081
+ self.businessFormSave ? self.businessFormSave(self.handleSaveResult) : self.handleSaveResult(true)
1082
+ },
1083
+ handleSaveResult(saveResult, businessParams) {
1084
+ if (saveResult) {
1085
+ this.executeButtonAction(businessParams);
1086
+ } else {
1087
+ console.error('保存失败');
1088
+ }
1089
+ },
1090
+ executeButtonAction(businessParams) {
1091
+ const self = this;
1092
+ if (businessParams) {
1093
+ Object.assign(self.datas, businessParams)
1094
+ self.auditParams.params = JSON.stringify(self.datas)
1095
+ }
1096
+ let auditResult = {
1097
+ code: self.auditResult,
1098
+ name: self.handleButtonsNames[self.auditResult]
1099
+ }
1100
+ if (self.auditResult === '82') {
1101
+ self.assigneeBoxData = self.auditParams
1102
+ self.assigneeBoxData.auditResultName = self.handleButtonsNames[self.auditResult]
1103
+ self.assigneeBoxData.instanceId = self.instanceId
1104
+ self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'transferCurTask')
1105
+ } else if (self.auditResult === '80') {
1106
+ self.getNodesBehind()
1107
+ } else if (self.auditResult === '90') {
1108
+ self.getAllPreNodes()
1109
+ } else if (self.auditResult === '40') {
1110
+ self.loading = true
1111
+ self.disable = true
1112
+ let url = self.smartFlowServerContext + '/manage/processTodo/getPreNode'
1113
+ ajax.post(url, self.auditParams).then(function (resp) {
1114
+ let result = resp.data
1115
+ if (result.code == '30013' || result.code == '30014') {
1116
+ //前序节点为子流程或当前节点为子流程第一个节点不可驳回上一级节点
1117
+ self.$Message.warning(result.message)
1118
+ //避免未提示消息直接回调
1119
+ setTimeout(() => {
1120
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1121
+ }, 1000)
1122
+ } else if (result.code == '30010') {
1123
+ self.$Modal.confirm({
1124
+ title: "提示",
1125
+ content: result.message,
1126
+ onOk: () => {
1127
+ self.auditParams.auditResult = '70'
1128
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1129
+ ajax.post(url, self.auditParams).then(function (resp) {
1130
+ let result = resp.data
1131
+ if (result.code == '200') {
1132
+ self.loading = false
1133
+ self.disable = false
1134
+ self.$Message.success(result.message);
1135
+ //后端没有返回数据
1136
+ setTimeout(() => {
1137
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId);
1138
+ }, 1000)
1139
+ bus.$emit('triggerTimer')
1140
+ } else {
1141
+ self.loading = false
1142
+ self.disable = false
1143
+ self.$Message.error(result.message)
1144
+ setTimeout(() => {
1145
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1146
+ }, 1000)
1147
+ }
1148
+ bus.$emit('triggerTimer')
1149
+ })
1150
+ },
1151
+ onCancel: () => {
1152
+ self.loading = false
1153
+ self.disable = false
1154
+ }
1155
+ })
1156
+ } else if (result.code == '10012') {
1157
+ // 数据同步
1158
+ self.loading = false
1159
+ self.disable = false
1160
+ self.$Message.warning(result.message)
1161
+ setTimeout(() => {
1162
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1163
+ }, 1000)
1164
+ } else {
1165
+ self.loading = true
1166
+ self.disable = true
1167
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1168
+ ajax.post(url, self.auditParams).then(function (resp) {
1169
+ let result = resp.data
1170
+ if (result.code == '200') {
1171
+ self.loading = false
1172
+ self.disable = false
1173
+ self.$Message.success(result.message);
1174
+ setTimeout(() => {
1175
+ if (result.data) {
1176
+ let taskIds = result.data.map(item => item.id).join(',');
1177
+ self.executionCompleted(true, result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1178
+ } else {
1179
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1180
+ }
1181
+ }, 1000)
1182
+ } else {
1183
+ self.loading = false
1184
+ self.disable = false
1185
+ self.$Message.error(result.message)
1186
+ setTimeout(() => {
1187
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId);
1188
+ }, 1000)
1189
+ }
1190
+ bus.$emit('triggerTimer')
1191
+ })
1192
+ }
1193
+ })
1194
+ } else {
1195
+ if (self.auditResult === '30' && (!self.handleButtons || self.handleButtons.includes('appointHandler') || self.handleButtons.includes('appointTimeoutTime'))){
1196
+ self.getNextNodes()
1197
+ self.appointBoxShow = true
1198
+ } else {
1199
+ self.doPass()
1200
+ }
1201
+ }
1202
+ },
1203
+ doPass(){
1204
+ let self = this;
1205
+ this.modal = false
1206
+ let auditResult = {
1207
+ code: self.auditResult,
1208
+ name: self.handleButtonsNames[self.auditResult]
1209
+ }
1210
+ if (self.auditResult === '82' && (self.targetTaskNode == '' || self.targetTaskNode == null)) {
1211
+ self.auditResult = '';
1212
+ self.$Message.error(`请选择${self.handleName}节点!`);
1213
+ } else {
1214
+ self.loading = true
1215
+ self.disable = true
1216
+ self.auditParams.targetTaskNode = self.targetTaskNode
1217
+ let url = self.smartFlowServerContext + '/manage/processTodo/audit'
1218
+ ajax.post(url, self.auditParams).then(function (resp) {
1219
+ let result = resp.data
1220
+ if (result.code == '200') {
1221
+ self.loading = false
1222
+ self.disable = false
1223
+ self.$Message.success(result.message ? result.message : `${self.handleName}成功`);
1224
+ if (result.data){
1225
+ let taskIds = result.data.id ? result.data.id : result.data.map(item => item.id).join(',');
1226
+ setTimeout(() => {
1227
+ self.executionCompleted(true, result.data.id ? result.data.processInstanceId : result.data[0].processInstanceId, taskIds, auditResult, self.curTaskId)
1228
+ }, 1000)
1229
+ } else {
1230
+ setTimeout(() => {
1231
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1232
+ }, 1000)
1233
+ }
1234
+ } else if (result.code == '10012') {
1235
+ // 数据同步
1236
+ self.loading = false
1237
+ self.disable = false
1238
+ self.$Message.warning(result.message)
1239
+ setTimeout(() => {
1240
+ self.executionCompleted(true, null, null, auditResult, self.curTaskId)
1241
+ }, 1000)
1242
+ } else if (result.code == '20002') {
1243
+ // 流程结束
1244
+ self.loading = false
1245
+ self.disable = false
1246
+ self.$Message.success(result.message)
1247
+ setTimeout(() => {
1248
+ self.executionCompleted(true, '流程已结束', '流程已结束', auditResult, self.curTaskId)
1249
+ }, 1000)
1250
+ } else {
1251
+ self.loading = false
1252
+ self.disable = false
1253
+ self.$Message.error(result.message ? result.message : `${self.handleName}失败`)
1254
+ setTimeout(() => {
1255
+ self.executionCompleted(false, null, null, auditResult, self.curTaskId)
1256
+ }, 1000)
1257
+ }
1258
+ bus.$emit('triggerTimer')
1259
+ })
1260
+ }
1261
+ },
1262
+
1263
+ doSearch() {
1264
+ //不需要实现,是子组件assigneeBox要求使用父组件的这个方法
1265
+ },
1266
+ tabsChange(tab) {
1267
+ console.log(tab)
1268
+ },
1269
+ getAttach(row) {
1270
+ window.open(this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId, "_blank");
1271
+ },
1272
+ preViewAttach(row) {
1273
+ let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
1274
+ let regs = /\.(pdf)$/
1275
+ if (reg.test(row.fileName)) {
1276
+ let url = this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId;
1277
+ this.imgPreview(url);
1278
+ } else if (regs.test(row.fileName)) {
1279
+ window.open(this.smartFlowServerContext + "/manage/oss/file/getFileStream?fileId=" + row.fileId, "_blank");
1280
+ } else {
1281
+ this.modalDocx = true
1282
+ axios({
1283
+ method: 'get',
1284
+ responseType: 'blob', // 因为是流文件,所以要指定blob类型
1285
+ url: this.smartFlowServerContext + "/manage/oss/file/get/" + row.fileId// 一个word下载文件的接口
1286
+ }).then(({data}) => {
1287
+ docx.renderAsync(data, this.$refs.file, null, {
1288
+ className: "docx", //默认和文档样式类的类名/前缀
1289
+ inWrapper: true, //启用围绕文档内容呈现包装器
1290
+ ignoreWidth: false, //禁用页面的渲染宽度
1291
+ ignoreHeight: false, //禁用页面的渲染高度
1292
+ ignoreFonts: false, //禁用字体渲染
1293
+ breakPages: true, //在分页符上启用分页
1294
+ ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
1295
+ experimental: false, //启用实验功能(制表符停止计算)
1296
+ trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
1297
+ useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
1298
+ useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
1299
+ showChanges: false, //启用文档更改的实验渲染(插入/删除)
1300
+ debug: false, //启用额外的日志记录
1301
+ })
1302
+ }
1303
+ )
1304
+ }
1305
+ },
1306
+ imgPreview(url) {
1307
+ this.imageUrl = url;
1308
+ this.modalVisible = true;
1309
+ },
1310
+
1311
+ //打印流程图信息
1312
+ processPrint() {
1313
+ let self = this
1314
+ let params = {
1315
+ applyId: self.applyId,
1316
+ instanceId: self.instanceId,
1317
+ procId: self.procId,
1318
+ taskId: self.curTaskId,
1319
+ }
1320
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getPrintData', {params: params}).then(function (resp) {
1321
+ let result = resp.data.data
1322
+ if (resp.data.code === '200') {
1323
+ let tableData = result
1324
+ self.process.tableData = tableData
1325
+ self.process.applyId = self.applyId
1326
+ self.process.instanceId = self.instanceId
1327
+ self.process.procId = self.procId
1328
+ self.datas.orgId = tableData[0].orgId
1329
+ self.datas.orgName = tableData[0].orgName
1330
+ self.modalBoxShow = true
1331
+ }
1332
+ })
1333
+ },
1334
+
1335
+ showTaskNode(taskId) {
1336
+ if (this.processHistory.length > 0) {
1337
+ let task = null
1338
+ this.processHistory.some(itemList => {
1339
+ task = itemList.find(item => item.taskId === taskId);
1340
+ return task !== undefined;
1341
+ });
1342
+ return task ? task.taskName : ''
1343
+ }
1344
+ return ''
1345
+ },
1346
+ cancel() {
1347
+ this.modal = false
1348
+ this.auditResult = '';
1349
+ },
1350
+ selectNode(currentRow, oldCurrentRow) {
1351
+ let self = this
1352
+ self.targetTaskNode = currentRow.taskNode
1353
+ },
1354
+ getAllPreNodes() {
1355
+ let self = this
1356
+ let params = {
1357
+ processDefId: self.procId,
1358
+ taskId: self.curTaskId,
1359
+ }
1360
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getAllPreNodes', {params: params}).then(function (resp) {
1361
+ if (resp.data.code === '200') {
1362
+ if (resp.data.data.length > 0) {
1363
+ self.allNode = resp.data.data
1364
+ self.modal1 = true
1365
+ } else {
1366
+ self.$Message.warning('当前流程无前序节点')
1367
+ }
1368
+ } else {
1369
+ self.$Message.error(resp.data.message)
1370
+ }
1371
+ })
1372
+ },
1373
+ getNodesBehind() {
1374
+ let self = this
1375
+ let params = {
1376
+ processDefId: self.procId,
1377
+ taskId: self.curTaskId,
1378
+ }
1379
+ ajax.get(self.smartFlowServerContext + '/manage/processTodo/getNodesBehind', {params: params}).then(function (resp) {
1380
+ if (resp.data.code === '200') {
1381
+ if (resp.data.data.length > 0) {
1382
+ self.allNode = resp.data.data
1383
+ self.modal1 = true
1384
+ } else {
1385
+ self.$Message.warning('当前流程无后续节点')
1386
+ }
1387
+ } else {
1388
+ self.$Message.error(resp.data.message)
1389
+ }
1390
+ })
1391
+ },
1392
+ handleSelectedUser(userId) {
1393
+ this.selectedUserId = userId;
1394
+ },
1395
+
1396
+ //折叠动画效果
1397
+ beforeEnter(el) {
1398
+ el.style.height = '0';
1399
+ },
1400
+ enter(el, done) {
1401
+ setTimeout(() => {
1402
+ el.style.height = el.scrollHeight + 'px';
1403
+ }, 0);
1404
+
1405
+ el.addEventListener('transitionend', done);
1406
+ },
1407
+ beforeLeave(el) {
1408
+ el.style.height = el.scrollHeight + 'px';
1409
+ },
1410
+ leave(el, done) {
1411
+ setTimeout(() => {
1412
+ el.style.height = '0';
1413
+ }, 0);
1414
+
1415
+ el.addEventListener('transitionend', done);
1416
+ },
1417
+
1418
+ beforeFlowInfoEnter(el) {
1419
+ el.style.transform = 'translateX(100%)';
1420
+ },
1421
+ flowInfoEnter(el, done) {
1422
+ const transitionDuration = 0.5;
1423
+ el.style.transition = `transform ${transitionDuration}s`;
1424
+ el.style.transform = 'translateX(0)';
1425
+ el.addEventListener('transitionend', done);
1426
+ },
1427
+ beforeFlowInfoLeave(el) {
1428
+ el.style.transform = 'translateX(0)';
1429
+ },
1430
+ flowInfoLeave(el, done) {
1431
+ const transitionDuration = 0.5;
1432
+ el.style.transition = `transform ${transitionDuration}s`;
1433
+ el.style.transform = 'translateX(100%)';
1434
+ el.addEventListener('transitionend', done);
1435
+ },
1436
+ uploadFile(file) {
1437
+ const self = this;
1438
+ self.fileList = []
1439
+ file.forEach(item => {
1440
+ self.fileList.push({
1441
+ fileName: item.fileName,
1442
+ fileId: item.fileCode,
1443
+ });
1444
+ })
1445
+ },
1446
+
1447
+ appointOk() {
1448
+ const self = this
1449
+ let oldSettings
1450
+ let params = this.nextNodesFormList.reduce((acc, item) => {
1451
+ acc[item.id] = {
1452
+ needUpdate: 'false',
1453
+ }
1454
+ item.assignee ? acc[item.id].assignee = item.assignee : ''
1455
+ item.candidateGroups ? acc[item.id].candidateGroup = item.candidateGroups : ''
1456
+ let timeLimit = 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1457
+ if(!(item.remainDay === 0 && item.remainTime === 0 && item.inAdvanceDay === 0 && item.inAdvanceTime === 0)) {
1458
+ timeLimit = 'expireTime:' + parseInt(item.remainDay) + "D" + parseInt(item.remainTime) + "H" + ";warningTime:" + parseInt(item.inAdvanceDay) + "D" + parseInt(item.inAdvanceTime) + "H;" + "handleType:" + item.processing;
1459
+ acc[item.id].timeLimit = timeLimit
1460
+ } else {
1461
+ acc[item.id].timeLimit = ''
1462
+ }
1463
+ oldSettings = self.nextNodesOldSettings.filter(oldSetting => oldSetting.id === item.id)[0]
1464
+ if (oldSettings.assignee !== item.assignee || self.checkGroupsUpdate(oldSettings.candidates, item.candidateGroups) || self.checkTimeLimitUpdate(oldSettings.timeLimit, timeLimit)) {
1465
+ acc[item.id].needUpdate = 'true'
1466
+ }
1467
+ return acc;
1468
+ }, {});
1469
+ self.auditParams.nodeConfigMaps = JSON.stringify(params)
1470
+ self.doPass((execResult, instanceId, taskIds, auditResult, curTaskId) => {
1471
+ if (this.executionCompleted) {
1472
+ this.executionCompleted(execResult, instanceId, taskIds, auditResult, curTaskId);
1473
+ }
1474
+ })
1475
+ },
1476
+ checkGroupsUpdate(oldSetting, newSetting) {
1477
+ if (oldSetting && newSetting) {
1478
+ let oldIdList = []
1479
+ for (let [key, value] of Object.entries(oldSetting)) {
1480
+ if (value) {
1481
+ value.split(',').forEach(part => {
1482
+ const [id] = part.split(':');
1483
+ if (id) {
1484
+ oldIdList.push(id);
1485
+ }
1486
+ })
1487
+ }
1488
+ }
1489
+ const regex = /(?:O:|U:|P:|R:|T:)([^,]+)/g;
1490
+ let match;
1491
+ const newIds = [];
1492
+ while ((match = regex.exec(newSetting)) !== null) {
1493
+ newIds.push(...match[1].split(';'))
1494
+ }
1495
+ const allInString = oldIdList.every(item => newIds.includes(item));
1496
+ const hasExtra = newIds.some(item => !oldIdList.includes(item));
1497
+ return !allInString || hasExtra
1498
+ }
1499
+ return false
1500
+ },
1501
+ checkTimeLimitUpdate(oldSetting, newSetting){
1502
+ if (oldSetting && newSetting){
1503
+ return oldSetting !== newSetting
1504
+ }
1505
+ if (!oldSetting){
1506
+ return newSetting !== 'expireTime:0D0H;warningTime:0D0H;handleType:00'
1507
+ }
1508
+ return false
1509
+ },
1510
+ readingRangeClick(item) {
1511
+ let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1512
+ let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1513
+ this.$refs.assigneeHelpBox.toggleShowHelpBox(orgTreeType, permScope, 'transferNextTask', item.id)
1514
+ },
1515
+ candidateGroupsReadingRangeClick(item) {
1516
+ let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1517
+ let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1518
+ this.$refs.candidateGroupsHelpBox.toggleShowHelpBox(permScope, item.candidates, orgTreeType, item.id);
1519
+ },
1520
+ updateCandGroups(newCandGroups, nameStr, detail, nodeId){
1521
+ let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1522
+ if (JSON.stringify(oldSettings.candidates) != JSON.stringify(detail)) {
1523
+ let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1524
+ node.candidateGroups = newCandGroups
1525
+ node.candidateNames = nameStr
1526
+ node.candidates = detail
1527
+ node.needUpdate = true
1528
+ this.$forceUpdate();
1529
+ }
1530
+ },
1531
+ updateNextNodeAssignee(selectedAssigneeId, selectedAssigneeName, nodeId){
1532
+ let oldSettings = this.nextNodesOldSettings.filter(item => item.id === nodeId)[0]
1533
+ if (oldSettings.assignee != selectedAssigneeId) {
1534
+ let node = this.nextNodesFormList.filter(item => item.id === nodeId)[0]
1535
+ node.assignee = selectedAssigneeId
1536
+ node.assigneeName = selectedAssigneeName
1537
+ node.needUpdate = true
1538
+ this.$forceUpdate();
1539
+ }
1540
+ }
1541
+ },
1542
+ watch: {
1543
+ auditOpinionText(label) {
1544
+ this.form.auditOpinion = label;
1545
+ },
1546
+ procId(val) {
1547
+ this.procId = val;
1548
+ this.initData()
1549
+ },
1550
+ }
1551
+ }
1552
+ </script>
1553
+
1554
+ <style lang="less" scoped>
1555
+ @import "./styles/css/index.less";
1556
+
1557
+ /deep/ .ivu-table-row-highlight td {
1558
+ background-color: #50c1ff !important;
1559
+ color: #fff !important;
1560
+ }
1561
+
1562
+ /deep/ .ivu-card-body {
1563
+ padding: 10px;
1564
+ }
1565
+
1566
+ .page-info /deep/ .page-body {
1567
+ overflow-y: hidden;
1568
+ }
1569
+ </style>