@lambo-design/workflow-approve 1.0.0-beta.20 → 1.0.0-beta.22

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