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

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