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

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