@lambo-design/workflow-approve 1.0.0-beta.24 → 1.0.0-beta.26

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