@lambo-design/workflow-approve 1.0.0-beta.85 → 1.0.0-beta.87

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,201 +1,128 @@
1
1
  <template>
2
- <LamboPageContainer>
2
+ <LamboPageContainer style="padding: 0">
3
3
  <template slot="page-title">
4
- {{ title }}
4
+ <Tabs v-if="processTraceInTab" value="business" @on-click="changeTab">
5
+ <TabPane :label="title" name="business"></TabPane>
6
+ <TabPane label="流程跟踪" name="processTrace"></TabPane>
7
+ </Tabs>
8
+ <span v-else>{{ title }}</span>
5
9
  </template>
6
10
  <template slot="page-extend">
7
11
  <slot name="return-button"></slot>
8
12
  </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
+
14
+ <!-- 横版 -->
15
+ <div v-if="inHorizontal && currentTab === 'business'" style="display: flex; flex-direction: column; height: 100%">
16
+ <!-- 业务内容区插槽 -->
17
+ <div class="portrait-lambo-indicator-card" :style="{height: `${soltHeight}px`}">
18
+ <slot name="business-content"></slot>
19
+ </div>
20
+
21
+ <!-- 流程信息区 -->
22
+ <div
23
+ v-if="openProcessInfo"
24
+ class="resizable-container"
25
+ :style="{
26
+ height: `${currentHeight}px`,
27
+ maxHeight: `${maxHeight}px`,
28
+ minHeight: `${minHeight}px`,
29
+ }">
30
+ <div
31
+ class="resizer"
32
+ @mousedown="startDrag"
33
+ :class="{ 'resizing': isResizing }">
34
+ <div class="resizer-handle"></div>
35
+ </div>
36
+
37
+ <div class="resizable-content portrait-lambo-indicator-card">
38
+ <div class="process-info-header">
39
+ <span style="flex: 1">流程信息</span>
40
+ <Icon type="md-remove" @click="changeShowHeight('reduce')" class="process-info-header-icon"/>
41
+ <Icon type="md-expand" @click="changeShowHeight('amplify')" class="process-info-header-icon"/>
42
+ <Icon type="md-refresh" @click="changeShowHeight('refresh')" class="process-info-header-icon"/>
43
+ </div>
44
+ <ProcessInfo ref="processInfo" v-show="openProcessInfo"
45
+ v-model="form.auditOpinion"
46
+ :apply-id="applyId"
47
+ :task-node="taskNode"
48
+ :proc-id="procId"
49
+ :task-id="curTaskId"
50
+ :is-detail="isDetail"
51
+ :default-audit-opinion="defaultAuditOpinion"
52
+ :push-button="pushButton"
53
+ :in-horizontal="inHorizontal"
54
+ :handle-name="handleName"
55
+ :handle-buttons="handleButtons"
56
+ :process-history="processHistory"
57
+ :portrait-width="portraitWidth"
58
+ :smart-flow-server-context="smartFlowServerContext"
59
+ @upload-file="uploadFile"/>
60
+ </div>
61
+ </div>
62
+ <div v-else>
63
+ <div class="process-info-hidden-header">
64
+ <span style="flex: 1">流程信息</span>
65
+ <Icon type="md-remove" @click="changeShowHeight('reduce')" class="process-info-header-icon"/>
66
+ <Icon type="md-expand" @click="changeShowHeight('amplify')" class="process-info-header-icon"/>
67
+ <Icon type="md-refresh" @click="changeShowHeight('refresh')" class="process-info-header-icon"/>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <div ref="processTraceTab" v-if="inHorizontal && currentTab === 'processTrace'">
73
+ <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId" :key="currentTab"
74
+ :procId="process.procId" :table-columns="diagramTableColumns" :scroll-element="scrollElement"
75
+ :tableData="process.tableData" :hisAudit="hisAudit"
76
+ :approve-detail-show-way="approveDetailShowWay"
77
+ :smart-flow-server-context="smartFlowServerContext">
78
+ </Workflow_Diagram>
13
79
  </div>
14
80
 
15
- <a v-if="showProcessInfo" @click="isExpanded = !isExpanded" class="arrow-button-container"
81
+ <!-- 竖版 -->
82
+ <div v-if="!inHorizontal" class="portrait-lambo-indicator-card"
83
+ :style="{float: 'left', width: isExpanded && showProcessInfo ? `calc(100% - ${portraitWidth+10}px)` : '99%'}">
84
+ <!-- 业务内容区插槽 -->
85
+ <slot v-if="currentTab === 'business'" name="business-content"></slot>
86
+ <div ref="processTraceTab" v-if="currentTab === 'processTrace'">
87
+ <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId" :key="currentTab"
88
+ :procId="process.procId" :table-columns="diagramTableColumns" :scroll-element="scrollElement"
89
+ :tableData="process.tableData" :hisAudit="hisAudit"
90
+ :approve-detail-show-way="approveDetailShowWay"
91
+ :smart-flow-server-context="smartFlowServerContext">
92
+ </Workflow_Diagram>
93
+ </div>
94
+ </div>
95
+ <!-- 流程信息区 -->
96
+ <a v-if="showProcessInfo && !inHorizontal" @click="isExpanded = !isExpanded" class="arrow-button-container"
16
97
  :style="{right: isExpanded ? portraitWidth+10 + 'px' : '10px'}">
17
98
  <Icon class="icon-class" v-if="isExpanded" type="ios-arrow-forward"/>
18
99
  <Icon class="icon-class" v-if="!isExpanded" type="ios-arrow-back"/>
19
100
  </a>
20
- <transition v-if="showProcessInfo" name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
101
+ <transition v-if="showProcessInfo && !inHorizontal" name="draw" @before-enter="beforeFlowInfoEnter" @enter="flowInfoEnter"
21
102
  @before-leave="beforeFlowInfoLeave" @leave="flowInfoLeave">
22
103
  <lamboIndicatorCard v-show="isExpanded" class="portrait-lambo-indicator-card"
23
104
  :style="{width: portraitWidth + 'px', float: 'right'}" :hasExtend="false">
24
105
  <div slot="content-title">流程信息</div>
25
- <a v-if="!isDetail" @click="auditShow = !auditShow">
26
- <Title
27
- v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
28
- <a style="color: #989898">
29
- <Icon v-if="auditShow" type="ios-arrow-down"/>
30
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
31
- {{ handleName }}信息
32
- </a>
33
- </Title>
34
- </a>
35
- <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave"
36
- @leave="leave">
37
- <div class="box" v-show="auditShow">
38
- <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
39
- v-if="handleButtons && handleButtons.includes('auditOpinion')"
40
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
41
- <FormItem :label="auditOpinionTitle" prop="auditOpinion">
42
- <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
43
- :attachmentdata="fileList" :default-audit-opinion="defaultAuditOpinion"
44
- :smart-flow-server-context="smartFlowServerContext"></AuditOpinion>
45
- </FormItem>
46
- </Form>
47
- <Form ref="auditOpinion" justify="center" :label-width="100"
48
- v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
49
- style="margin: 10px 0 0 10px;">
50
- <FormItem style="min-height: 70px">
51
- <Tooltip placement="bottom" max-width="200">
52
- <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg
53
- .png .gif
54
- </div>
55
- <UploadFile @upload-result="uploadFile" :multiple="true"
56
- :oss-server-context="smartFlowServerContext"
57
- :oss-file-put-url="ossFilePutUrl"></UploadFile>
58
- </Tooltip>
59
- </FormItem>
60
- </Form>
61
- </div>
62
- </transition>
63
- <a v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
64
- <Title
65
- v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
66
- <a style="color: #989898">
67
- <Icon v-if="auditShow" type="ios-arrow-down"/>
68
- <Icon v-if="!auditShow" type="ios-arrow-up"/>
69
- {{ handleName }}信息
70
- </a>
71
- </Title>
72
- </a>
73
- <transition v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" name="draw"
74
- @before-enter="beforeEnter"
75
- @enter="enter" @before-leave="beforeLeave" @leave="leave">
76
- <div class="box" v-show="auditShow">
77
- <Form ref="auditOpinion" justify="center" :model="form"
78
- v-if="handleButtons && handleButtons.includes('auditOpinion')"
79
- style="margin: 10px 0 0 10px;" :rules="ruleValidate">
80
- <FormItem style="margin-left: -60px">
81
- <Card v-for="(item, index) in hisAuditOpinion" :key="index">
82
- <Row style="display: flex">
83
- <Col span="24">
84
- <div style="word-wrap: break-word;">
85
- <span>{{ item.auditOpinion }}</span>
86
- <div style="position: absolute; right: 0;bottom: -18px;color: grey">{{ item.auditTime }}</div>
87
- </div>
88
- </Col>
89
- </Row>
90
- </Card>
91
- </FormItem>
92
- </Form>
93
- </div>
94
- </transition>
95
- <a @click="historyShow = !historyShow">
96
- <Title v-if="handleButtons && handleButtons.includes('auditHistory')">
97
- <a style="color: #989898">
98
- <Icon v-if="historyShow" type="ios-arrow-down"/>
99
- <Icon v-if="!historyShow" type="ios-arrow-up"/>
100
- {{ handleName }}记录
101
- </a>
102
- </Title>
103
- </a>
104
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
105
- <div class="box" v-show="historyShow">
106
- <Card class="process-history" :style="processHistoryHeight" dis-hover :bordered="false"
107
- v-if="handleButtons && handleButtons.includes('auditHistory')">
108
- <processHistory :portrait-width="portraitWidth" :list="processHistory" :done-page="isDetail"
109
- :push-button="pushButton"
110
- :smart-flow-server-context="smartFlowServerContext"></processHistory>
111
- </Card>
112
- </div>
113
- </transition>
114
-
115
- <a @click="attachListShow = !attachListShow">
116
- <Title v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0">
117
- <a style="color: #989898">
118
- <Icon v-if="attachListShow" type="ios-arrow-down"/>
119
- <Icon v-if="!attachListShow" type="ios-arrow-up"/>
120
- 查看附件
121
- </a>
122
- </Title>
123
- </a>
124
- <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
125
- <div class="box"
126
- v-show="handleButtons && handleButtons.includes('auditHistory') && attachmentList.length > 0 && attachListShow">
127
- <div v-for="(item, index) in attachmentList" :key="index">
128
- <Card dis-hover class="attach-card">
129
- <List item-layout="vertical">
130
- <ListItem style="margin-top: -8px">
131
- <Row style="display: flex; align-items: center;">
132
- <!-- 左边:图片 -->
133
- <Col span="4" style="margin-top: -25px">
134
- <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar"
135
- style="background-color: #005aff"
136
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
137
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
138
- <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar"
139
- style="background-color: #005aff"
140
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
141
- :size="portraitWidth >= 600 ? 'middle' : 'small'">
142
- </avatar>
143
- <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar"
144
- style="background-color: #19be6b"
145
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
146
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
147
- <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar"
148
- style="background-color: #ed4014"
149
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
150
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
151
- <avatar v-else icon="ios-document-outline" class="attach-avatar"
152
- :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
153
- :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
154
- </Col>
155
- <!-- 右边:附件信息 -->
156
- <Col span="20">
157
- <Row>
158
- <tooltip>
159
- <span class="attach-name-style"> {{ item.attachName }}</span>
160
- <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
161
- </tooltip>
162
- </Row>
163
- <Row style="margin-top: 3px">
164
- <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
165
- <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
166
- type="vertical"/>
167
- <span style="color: #808695;font-size: 13px"
168
- >{{ showTaskNode(item.taskId) }}</span>
169
- </Row>
170
- <Row style="margin-bottom: -10px; margin-top: 10px">
171
- <template>
172
- <Button @click="getAttach(item)" size="small">下载</Button>
173
- <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
174
- style="margin-left: 10px" size="small">预览
175
- </Button>
176
- </template>
177
- </Row>
178
- </Col>
179
- </Row>
180
-
181
- </ListItem>
182
- </List>
183
- </Card>
184
- </div>
185
- </div>
186
- </transition>
187
- <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
188
- <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
189
- <div slot="footer">
190
- <Button type="primary" @click="modalVisible = false">关闭</Button>
191
- </div>
192
- </Modal>
193
- <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
194
- <div ref="file"></div>
195
- </Modal>
106
+ <ProcessInfo ref="processInfo"
107
+ v-model="form.auditOpinion"
108
+ :apply-id="applyId"
109
+ :task-node="taskNode"
110
+ :proc-id="procId"
111
+ :task-id="curTaskId"
112
+ :is-detail="isDetail"
113
+ :default-audit-opinion="defaultAuditOpinion"
114
+ :push-button="pushButton"
115
+ :in-horizontal="inHorizontal"
116
+ :handle-name="handleName"
117
+ :handle-buttons="handleButtons"
118
+ :process-history="processHistory"
119
+ :portrait-width="portraitWidth"
120
+ :smart-flow-server-context="smartFlowServerContext"
121
+ @upload-file="uploadFile"/>
196
122
  </lamboIndicatorCard>
197
123
  </transition>
198
124
 
125
+ <!-- 节点跳转选择弹框 -->
199
126
  <Modal v-model="modal1" title="选择节点"
200
127
  @on-cancel="cancel"
201
128
  @on-ok="doJump">
@@ -212,12 +139,14 @@
212
139
  </RadioGroup>
213
140
  </Card>
214
141
  </Modal>
142
+ <!-- 指定他人处理弹框 -->
215
143
  <assigneeBox ref="assigneeHelpBox" :execution-completed="executionCompleted"
216
144
  @update-selected="handleSelectedUser" @update-next-node-assignee="updateNextNodeAssignee"
217
145
  @add-multitask-instance="addMultitaskInstance" @delegate-task-assignee="delegateTask"
218
146
  :data="assigneeBoxData" :smart-flow-server-context="smartFlowServerContext"
219
147
  :upms-server-context="upmsServerContext"/>
220
- <Modal ref="processTraceModal" v-model="modalBoxShow" width="1000" title="流程跟踪图">
148
+ <!-- 流程跟踪图弹框 -->
149
+ <Modal v-if="!processTraceInTab" ref="processTraceModal" v-model="modalBoxShow" width="1000" title="流程跟踪图">
221
150
  <Workflow_Diagram ref="processTrace" :instanceId="process.instanceId" :applyId="process.applyId"
222
151
  :procId="process.procId" :table-columns="diagramTableColumns" :scroll-element="scrollElement"
223
152
  :tableData="process.tableData" :hisAudit="hisAudit"
@@ -225,6 +154,7 @@
225
154
  :smart-flow-server-context="smartFlowServerContext">
226
155
  </Workflow_Diagram>
227
156
  </Modal>
157
+ <!-- 减签弹框 -->
228
158
  <Modal v-model="reductionMultitaskInstanceModal" title="选择减签人员"
229
159
  @on-cancel="reductionModalCancel"
230
160
  @on-ok="reductionMultitaskInstance">
@@ -234,6 +164,7 @@
234
164
  @on-selection-change="selectAssignee">
235
165
  </Table>
236
166
  </Modal>
167
+ <!-- 下一环节设置弹框 -->
237
168
  <Modal v-model="appointBoxShow" title="下一环节设置"
238
169
  @on-cancel="appointBoxShow = false" width="600"
239
170
  @on-ok="appointOk">
@@ -331,49 +262,23 @@
331
262
  @update-cand-groups="updateCandGroups"
332
263
  :upms-server-context="upmsServerContext"
333
264
  :smart-flow-server-context="smartFlowServerContext"/>
265
+
266
+ <!-- 底部操作按钮区 -->
334
267
  <template slot="page-footer">
335
268
  <div>
336
269
  <slot name="footer-button"></slot>
337
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo70') && !isDetail && !appointTask && !rejectedTask"
338
- :disabled="disable" :loading="loading" @click="audit('70')">{{rejectName}}到原点
339
- </Button>
340
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo40') && !isDetail && !appointTask && !rejectedTask"
341
- :disabled="disable" :loading="loading" @click="audit('40')">{{rejectName}}上一节点
342
- </Button>
343
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo90') && !isDetail && !appointTask && !rejectedTask"
344
- :disabled="disable" :loading="loading" @click="audit('90')">{{rejectName}}指定节点
345
- </Button>
346
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo80') && !isDetail && !appointTask && !rejectedTask"
347
- :disabled="disable" :loading="loading" @click="audit('80')">跳转指定节点
348
- </Button>
349
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo82') && !isDetail && !appointTask && !rejectedTask"
350
- :disabled="disable" :loading="loading" @click="audit('82')">指定他人处理
270
+ <Button
271
+ v-for="button in buttons"
272
+ :key="button.id"
273
+ style="margin-left: 10px;"
274
+ v-if="button.condition"
275
+ :disabled="button.disabled || disable"
276
+ :loading="loading"
277
+ :type="button.type || 'default'"
278
+ @click="button.action"
279
+ >
280
+ {{ button.label }}
351
281
  </Button>
352
- <Button style="margin-left: 10px;"
353
- v-if="curNodeType === 'userTask' && handleButtons && handleButtons.includes('delegateTask') && !isDetail && !appointTask && !rejectedTask"
354
- :disabled="disable" :loading="loading" @click="audit('84')">委派
355
- </Button>
356
- <Button style="margin-left: 10px;"
357
- v-if="curNodeType === 'multiNode' && handleButtons && handleButtons.includes('addMultitaskInstance') && !isDetail && !appointTask && !rejectedTask"
358
- :disabled="disable" :loading="loading" @click="showUpdateMultitaskInstanceModal('81')">加签
359
- </Button>
360
- <Button style="margin-left: 10px;"
361
- v-if="curNodeType === 'multiNode' && handleButtons && handleButtons.includes('reductionMultitaskInstance') && !isDetail && !appointTask && !rejectedTask"
362
- :disabled="disable" :loading="loading" @click="showUpdateMultitaskInstanceModal('83')">减签
363
- </Button>
364
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo50') && !isDetail && !appointTask && !rejectedTask"
365
- :disabled="disable" :loading="loading" @click="audit('50')">直接结束流程
366
- </Button>
367
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('processTrace')"
368
- @click="processPrint">流程跟踪图
369
- </Button>
370
- <Button style="margin-left: 10px;" v-if="handleButtons && handleButtons.includes('auditTo30') && !isDetail && !appointTask"
371
- :disabled="disable" :loading="loading" type="primary" @click="audit('30')">{{passName}}
372
- </Button>
373
- <Button style="margin-left: 10px;" v-if="revokeDelegateTask"
374
- :disabled="!revokeDelegateTask && disable" :loading="loading" @click="audit('62')">撤回委派
375
- </Button>
376
- <Button style="margin-left: 10px;" v-if="appointTask" :disabled="disable" :loading="loading" type="primary" @click="audit('61')">交回</Button>
377
282
  </div>
378
283
  </template>
379
284
  </LamboPageContainer>
@@ -391,14 +296,9 @@ import processHistory from './components/history'
391
296
  import assigneeBox from './components/assignee-box'
392
297
  import CandidateGroupsHelpBox from './components/candidate-groups-box'
393
298
  import CountersingersBox from './components/countersigners-box'
394
- import LamboPagingTable from '@lambo-design/paging-table'
395
- import AuditOpinion from './components/opinion'
396
- import axios from 'axios'
397
- import UploadFile from '@lambo-design/upload-file'
398
299
  import { timestampToTime } from '@lambo-design/shared/utils/date'
399
-
400
- // 引入docx-preview插件
401
- let docx = require('docx-preview')
300
+ import ProcessInfo from './components/process-info'
301
+ import { nodeType } from './utils/const'
402
302
 
403
303
  export default {
404
304
  props: {
@@ -469,10 +369,20 @@ export default {
469
369
  default: () => {
470
370
  }
471
371
  },
372
+ //是否显示竖向布局
373
+ inHorizontal: {
374
+ type: Boolean,
375
+ default: false
376
+ },
472
377
  title: {
473
378
  type: String,
474
379
  default: '流程办理'
475
380
  },
381
+ //流程跟踪图以tab形式展示
382
+ processTraceInTab: {
383
+ type: Boolean,
384
+ default: false
385
+ },
476
386
  smartFlowServerContext: {
477
387
  type: String,
478
388
  default: '/api/smart-flow-server',
@@ -488,24 +398,30 @@ export default {
488
398
  Workflow_Diagram,
489
399
  processHistory,
490
400
  assigneeBox,
491
- LamboPagingTable,
492
- AuditOpinion,
493
401
  LamboIndicatorCard,
494
- UploadFile,
495
402
  CandidateGroupsHelpBox,
496
- CountersingersBox
403
+ CountersingersBox,
404
+ ProcessInfo,
497
405
  },
498
406
  data() {
499
407
  return {
500
408
  isExpanded: true,
501
409
  showProcessInfo: true,
502
410
  portraitWidth: 0,
411
+ openProcessInfo: true,
412
+ currentHeight: 0,
413
+ soltHeight: 0,
414
+ maxHeight: 0,
415
+ isResizing: false,
416
+ startY: 0,
417
+ minHeight: 0,
418
+ maxHeightPercent: 85,
419
+ initialHeightPercent: 30,
503
420
  procType: '',
504
421
  requestSuccessCodes: [200, '200'],
505
422
  auditShow: true,
506
423
  historyShow: true,
507
424
  attachListShow: true,
508
- attachmentList: [],
509
425
  modalVisible: false,
510
426
  modalDocx: false,
511
427
  imageUrl: '',
@@ -551,7 +467,7 @@ export default {
551
467
  appointTask: false,
552
468
  instanceId: '',
553
469
  curTaskId: '',
554
- curNodeType: 'userTask',
470
+ curNodeType: nodeType.userTask,
555
471
  handleButtons: [],
556
472
  handleName: '审批',
557
473
  passName: '通过',
@@ -564,6 +480,7 @@ export default {
564
480
  auditProcess: 'auditProcess',
565
481
  fileList: [],
566
482
  ossFilePutUrl: '/manage/oss/file/put',
483
+ currentTab: 'business',
567
484
  hisAudit: [],
568
485
  hisAuditOpinion: [{
569
486
  auditOpinion: '',
@@ -619,34 +536,122 @@ export default {
619
536
  },
620
537
 
621
538
  mounted() {
539
+ this.calculateDimensions();
540
+ // 监听窗口大小变化
541
+ window.addEventListener('resize', this.handleWindowResize);
542
+
622
543
  this.getWidth()
623
544
  if (this.procId) {
624
545
  this.initData()
625
546
  }
626
- let modalElement = this.$refs.processTraceModal.$el
627
- for (let i = 0; i < modalElement.children.length; i++) {
628
- //找到滚动的目标element
629
- let targetElement = modalElement.children[i]
630
- if (targetElement.classList.toString().includes('-wrap')){
631
- this.scrollElement = targetElement
632
- break
547
+ if (!this.processTraceInTab){
548
+ let modalElement = this.$refs.processTraceModal.$el
549
+ for (let i = 0; i < modalElement.children.length; i++) {
550
+ //找到滚动的目标element
551
+ let targetElement = modalElement.children[i]
552
+ if (targetElement.classList.toString().includes('-wrap')){
553
+ this.scrollElement = targetElement
554
+ break
555
+ }
633
556
  }
634
557
  }
635
558
  },
559
+ beforeDestroy() {
560
+ // 移除事件监听
561
+ window.removeEventListener('resize', this.handleWindowResize);
562
+ },
636
563
  computed: {
637
- processHistoryHeight() {
638
- let str = ''
639
- const hasAuditOpinion = this.taskNode && this.handleButtons && this.handleButtons.includes('auditOpinion')
640
- const hasAttachmentFile = this.handleButtons && this.handleButtons.includes('auditHistory') && this.attachmentList.length > 0
641
- const isDetail = this.isDetail && !this.hisAuditOpinion[0].auditOpinion.length > 0
642
- if (hasAuditOpinion && !hasAttachmentFile && !isDetail) {
643
- str += 'height: 43vh'
644
- } else if (hasAuditOpinion && hasAttachmentFile && !isDetail) {
645
- str += 'height: 40vh'
646
- } else {
647
- str += 'height: 67vh'
648
- }
649
- return str
564
+ buttons() {
565
+ const showButtons = !this.isDetail && !this.appointTask && !this.rejectedTask
566
+ return [
567
+ {
568
+ id: 'auditTo70',
569
+ label: `${this.rejectName}到原点`,
570
+ condition: this.handleButtons?.includes('auditTo70') && showButtons,
571
+ action: () => this.audit('70')
572
+ },
573
+ {
574
+ id: 'auditTo40',
575
+ label: `${this.rejectName}上一节点`,
576
+ condition: this.handleButtons?.includes('auditTo40') && showButtons,
577
+ action: () => this.audit('40')
578
+ },
579
+ {
580
+ id: 'auditTo90',
581
+ label: `${this.rejectName}指定节点`,
582
+ condition: this.handleButtons?.includes('auditTo90') && showButtons,
583
+ action: () => this.audit('90')
584
+ },
585
+ {
586
+ id: 'auditTo80',
587
+ label: '跳转指定节点',
588
+ condition: this.handleButtons?.includes('auditTo80') && showButtons,
589
+ action: () => this.audit('80')
590
+ },
591
+ {
592
+ id: 'auditTo82',
593
+ label: '指定他人处理',
594
+ condition: this.handleButtons?.includes('auditTo82') && showButtons,
595
+ action: () => this.audit('82')
596
+ },
597
+ {
598
+ id: 'delegateTask',
599
+ label: '委派',
600
+ condition: this.curNodeType === nodeType.userTask &&
601
+ this.handleButtons?.includes('delegateTask') &&
602
+ showButtons,
603
+ action: () => this.audit('84')
604
+ },
605
+ {
606
+ id: 'addMultitaskInstance',
607
+ label: '加签',
608
+ condition: this.curNodeType === nodeType.multiNode &&
609
+ this.handleButtons?.includes('addMultitaskInstance') &&
610
+ showButtons,
611
+ action: () => this.showUpdateMultitaskInstanceModal('81')
612
+ },
613
+ {
614
+ id: 'reductionMultitaskInstance',
615
+ label: '减签',
616
+ condition: this.curNodeType === nodeType.multiNode &&
617
+ this.handleButtons?.includes('reductionMultitaskInstance') &&
618
+ showButtons,
619
+ action: () => this.showUpdateMultitaskInstanceModal('83')
620
+ },
621
+ {
622
+ id: 'auditTo50',
623
+ label: '直接结束流程',
624
+ condition: this.handleButtons?.includes('auditTo50') && showButtons,
625
+ action: () => this.audit('50')
626
+ },
627
+ {
628
+ id: 'processTrace',
629
+ label: '流程跟踪图',
630
+ condition: this.handleButtons?.includes('processTrace') && !this.processTraceInTab,
631
+ action: () => this.processPrint()
632
+ },
633
+ {
634
+ id: 'auditTo30',
635
+ label: this.passName,
636
+ condition: this.handleButtons?.includes('auditTo30') && !this.isDetail && !this.appointTask,
637
+ action: () => this.audit('30'),
638
+ type: 'primary'
639
+ },
640
+ {
641
+ id: 'revokeDelegateTask',
642
+ label: '撤回委派',
643
+ condition: this.revokeDelegateTask,
644
+ action: () => this.audit('62'),
645
+ disabled: !this.revokeDelegateTask
646
+ },
647
+ {
648
+ id: 'appointTask',
649
+ label: '交回',
650
+ condition: this.appointTask,
651
+ action: () => this.audit('61'),
652
+ type: 'primary'
653
+ }
654
+ ];
650
655
  },
651
656
  nodeColumn: function () {
652
657
  let column = []
@@ -942,6 +947,75 @@ export default {
942
947
  }
943
948
  },
944
949
  methods: {
950
+ changeShowHeight(option){
951
+ const windowHeight = window.innerHeight - 50;
952
+ switch (option){
953
+ case 'reduce':
954
+ this.openProcessInfo = false
955
+ this.soltHeight = windowHeight - 80;
956
+ break;
957
+ case 'amplify':
958
+ this.openProcessInfo = true
959
+ this.currentHeight = 0.8 * windowHeight;
960
+ this.soltHeight = windowHeight - this.currentHeight - 40;
961
+ break;
962
+ case 'refresh':
963
+ this.openProcessInfo = true
964
+ this.calculateDimensions()
965
+ break;
966
+ }
967
+ },
968
+ calculateDimensions() {
969
+ const windowHeight = window.innerHeight - 50;
970
+ this.maxHeight = (this.maxHeightPercent / 100) * windowHeight;
971
+ this.minHeight = 0.15 * windowHeight;
972
+
973
+ let initialHeight = (this.initialHeightPercent / 100) * windowHeight;
974
+ initialHeight = Math.max(this.minHeight, Math.min(initialHeight, this.maxHeight));
975
+ this.currentHeight = initialHeight;
976
+ this.soltHeight = windowHeight - initialHeight - 40;
977
+ },
978
+
979
+ startDrag(e) {
980
+ e.preventDefault();
981
+ this.isResizing = true;
982
+ this.startY = e.clientY;
983
+
984
+ document.addEventListener('mousemove', this.handleDrag);
985
+ document.addEventListener('mouseup', this.stopDrag);
986
+
987
+ document.body.style.userSelect = 'none';
988
+ },
989
+
990
+ handleDrag(e) {
991
+ if (!this.isResizing) return;
992
+
993
+ const windowHeight = window.innerHeight - 50;
994
+ const deltaY = e.clientY - this.startY;
995
+ let newHeight = this.currentHeight - deltaY;
996
+
997
+ newHeight = Math.max(this.minHeight, Math.min(newHeight, this.maxHeight));
998
+
999
+ this.currentHeight = newHeight;
1000
+ this.soltHeight = windowHeight - newHeight - 40;
1001
+ this.startY = e.clientY;
1002
+ this.$emit('height-change', this.currentHeight);
1003
+ },
1004
+
1005
+ stopDrag() {
1006
+ this.isResizing = false;
1007
+
1008
+ document.removeEventListener('mousemove', this.handleDrag);
1009
+ document.removeEventListener('mouseup', this.stopDrag);
1010
+ document.body.style.userSelect = '';
1011
+
1012
+ this.$emit('resize-end', this.currentHeight);
1013
+ },
1014
+
1015
+ handleWindowResize() {
1016
+ this.calculateDimensions();
1017
+ },
1018
+
945
1019
  getWidth() {
946
1020
  if (this.width && this.width < 400) {
947
1021
  this.portraitWidth = 400
@@ -982,15 +1056,14 @@ export default {
982
1056
  let procType = todoData.procType
983
1057
  self.procType = todoData.procType
984
1058
  ajax.get(self.smartFlowServerContext + '/manage/processType/lists?proType=' + procType)
985
- .then(resp => {
986
- let data = resp.data.data.rows
987
- self.permScope = data[0].permScope
988
- self.defaultOrganTreeType = data[0].organTreeType ? data[0].organTreeType : '00'
989
- self.getNodeOrganTreeType(procType)
990
- }).catch(err => {
1059
+ .then(resp => {
1060
+ let data = resp.data.data.rows
1061
+ self.permScope = data[0].permScope
1062
+ self.defaultOrganTreeType = data[0].organTreeType ? data[0].organTreeType : '00'
1063
+ self.getNodeOrganTreeType(procType)
1064
+ }).catch(err => {
991
1065
  console.log(err)
992
1066
  })
993
- self.getAttachList(self.curTaskId)
994
1067
  self.getHisAudit(self.curTaskId)
995
1068
  self.getProcessHistory(self.curTaskId)
996
1069
  } else {
@@ -1054,7 +1127,6 @@ export default {
1054
1127
  console.log(err)
1055
1128
  })
1056
1129
  }
1057
- self.getAttachList(self.curTaskId)
1058
1130
  self.getHisAudit(self.curTaskId)
1059
1131
  self.getProcessHistory(self.curTaskId)
1060
1132
  } else {
@@ -1074,7 +1146,7 @@ export default {
1074
1146
  if (resp.data.code === '200') {
1075
1147
  self.handleButtons = resp.data.data[0].handleButtons ? resp.data.data[0].handleButtons : ["processTrace","auditHistory","auditOpinion","attachmentFile","auditTo30","auditTo70","auditTo40","auditTo90","auditTo80","auditTo82","auditTo50"];
1076
1148
  if (resp.data.data[0].hasOwnProperty('isSequential')) {
1077
- self.curNodeType = resp.data.data[0].isSequential ? 'sequentialMultiNode' : 'multiNode';
1149
+ self.curNodeType = resp.data.data[0].isSequential ? nodeType.sequentialMultiNode : nodeType.multiNode;
1078
1150
  }
1079
1151
  self.handleName = resp.data.data[0].handleName ? resp.data.data[0].handleName : '审批';
1080
1152
  self.rejectName = resp.data.data[0].rejectName ? resp.data.data[0].rejectName : '驳回';
@@ -1166,29 +1238,6 @@ export default {
1166
1238
  console.log(err)
1167
1239
  })
1168
1240
  },
1169
- getAttachList(taskId) {
1170
- const self = this
1171
- const param = {
1172
- taskId: taskId,
1173
- procId: this.procId,
1174
- applyId: this.applyId
1175
- }
1176
- ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', { params: param }).then(function (resp) {
1177
- self.attachmentList = resp.data.data.rows
1178
- self.attachmentList.forEach(item => {
1179
- const index = item.fileName.lastIndexOf('.')
1180
- const fileType = item.fileName.substr(index + 1).toLowerCase()
1181
- const imageList = ['jpg', 'gif', 'png', 'svg']
1182
- const docList = ['doc', 'docx']
1183
- const zipList = ['rar', 'zip']
1184
- const typeList = ['jpg', 'gif', 'png', 'docx']
1185
- item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
1186
- item.showPreview = typeList.indexOf(fileType) !== -1
1187
- })
1188
- }).catch(err => {
1189
- console.log(err)
1190
- })
1191
- },
1192
1241
  getHisAudit(taskId) {
1193
1242
  let self = this
1194
1243
  let params = {
@@ -1287,24 +1336,10 @@ export default {
1287
1336
  self.assigneeBoxData = self.auditParams
1288
1337
  self.assigneeBoxData.auditResultName = self.handleButtonsNames[self.auditResult]
1289
1338
  self.assigneeBoxData.instanceId = self.instanceId
1290
- const params = {
1291
- procType: self.procType,
1292
- procId: self.procId,
1293
- taskNode: self.taskNode
1294
- }
1295
- const url = self.smartFlowServerContext + '/manage/nodeConfig/getTransferRange';
1296
- ajax.post(url, params).then(resp => {
1297
- if (resp.data.code === '200'){
1298
- const data = resp.data.data
1299
- self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'transferCurTask', '', data)
1300
- }
1301
- }).catch(error => {
1302
- self.$Message.error('获取交接人员范围失败');
1303
- console.log(error)
1304
- })
1339
+ self.getTransferRangeAndOpenModal(self.organTreeType, '', 'auditTo82')
1305
1340
  } else if (self.auditResult === '84') {
1306
1341
  //委派任务
1307
- self.$refs.assigneeHelpBox.toggleShowHelpBox(self.organTreeType, '', 'delegateTask')
1342
+ this.getTransferRangeAndOpenModal(self.organTreeType, '', 'delegateTask', '')
1308
1343
  } else if (self.auditResult === '62') {
1309
1344
  //撤回委派任务
1310
1345
  ajax.post(self.smartFlowServerContext + '/manage/processTodo/audit', self.auditParams).then(resp => {
@@ -1496,7 +1531,7 @@ export default {
1496
1531
  showUpdateMultitaskInstanceModal(updateType) {
1497
1532
  const self = this
1498
1533
  if (updateType === '81') {
1499
- this.$refs.assigneeHelpBox.toggleShowHelpBox(this.organTreeType, '', 'addMultitaskInstance')
1534
+ this.getTransferRangeAndOpenModal(this.organTreeType, '', 'addMultitaskInstance', '')
1500
1535
  } else if (updateType === '83') {
1501
1536
  ajax.get(self.smartFlowServerContext + '/manage/processTodo/getUnapprovedListOfMultiNode?taskId=' + self.curTaskId).then(function (resp) {
1502
1537
  if (resp.data.code === '200') {
@@ -1590,51 +1625,9 @@ export default {
1590
1625
  doSearch() {
1591
1626
  //不需要实现,是子组件assigneeBox要求使用父组件的这个方法
1592
1627
  },
1593
- tabsChange(tab) {
1594
- console.log(tab)
1595
- },
1596
1628
  getAttach(row) {
1597
1629
  window.open(this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId, '_blank')
1598
1630
  },
1599
- preViewAttach(row) {
1600
- let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
1601
- let regs = /\.(pdf)$/
1602
- if (reg.test(row.fileName)) {
1603
- let url = this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId
1604
- this.imgPreview(url)
1605
- } else if (regs.test(row.fileName)) {
1606
- window.open(this.smartFlowServerContext + '/manage/oss/file/getFileStream?fileId=' + row.fileId, '_blank')
1607
- } else {
1608
- this.modalDocx = true
1609
- axios({
1610
- method: 'get',
1611
- responseType: 'blob', // 因为是流文件,所以要指定blob类型
1612
- url: this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId// 一个word下载文件的接口
1613
- }).then(({ data }) => {
1614
- docx.renderAsync(data, this.$refs.file, null, {
1615
- className: 'docx', //默认和文档样式类的类名/前缀
1616
- inWrapper: true, //启用围绕文档内容呈现包装器
1617
- ignoreWidth: false, //禁用页面的渲染宽度
1618
- ignoreHeight: false, //禁用页面的渲染高度
1619
- ignoreFonts: false, //禁用字体渲染
1620
- breakPages: true, //在分页符上启用分页
1621
- ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
1622
- experimental: false, //启用实验功能(制表符停止计算)
1623
- trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
1624
- useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
1625
- useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
1626
- showChanges: false, //启用文档更改的实验渲染(插入/删除)
1627
- debug: false, //启用额外的日志记录
1628
- })
1629
- }
1630
- )
1631
- }
1632
- },
1633
- imgPreview(url) {
1634
- this.imageUrl = url
1635
- this.modalVisible = true
1636
- },
1637
-
1638
1631
  //打印流程图信息
1639
1632
  processPrint() {
1640
1633
  let self = this
@@ -1659,17 +1652,6 @@ export default {
1659
1652
  })
1660
1653
  },
1661
1654
 
1662
- showTaskNode(taskId) {
1663
- if (this.processHistory.length > 0) {
1664
- let task = null
1665
- this.processHistory.some(itemList => {
1666
- task = itemList.find(item => item.taskId === taskId)
1667
- return task !== undefined
1668
- })
1669
- return task ? task.taskName : ''
1670
- }
1671
- return ''
1672
- },
1673
1655
  cancel() {
1674
1656
  this.modal = false
1675
1657
  this.auditResult = ''
@@ -1776,15 +1758,8 @@ export default {
1776
1758
  el.style.transform = 'translateX(100%)'
1777
1759
  el.addEventListener('transitionend', done)
1778
1760
  },
1779
- uploadFile(file) {
1780
- const self = this
1781
- self.fileList = []
1782
- file.forEach(item => {
1783
- self.fileList.push({
1784
- fileName: item.fileName,
1785
- fileId: item.fileCode,
1786
- })
1787
- })
1761
+ uploadFile(fileList) {
1762
+ this.fileList = fileList
1788
1763
  },
1789
1764
 
1790
1765
  appointOk() {
@@ -1862,7 +1837,7 @@ export default {
1862
1837
  readingRangeClick(item) {
1863
1838
  let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
1864
1839
  let orgTreeType = item.orgTreeType ? item.orgTreeType : this.defaultOrganTreeType
1865
- this.$refs.assigneeHelpBox.toggleShowHelpBox(orgTreeType, permScope, 'transferNextTask', item.id)
1840
+ this.getTransferRangeAndOpenModal(orgTreeType, permScope, 'appointHandler', item.id)
1866
1841
  },
1867
1842
  candidateGroupsReadingRangeClick(item) {
1868
1843
  let permScope = item.orgTreeType === this.defaultOrganTreeType ? this.permScope : 'all'
@@ -1912,24 +1887,24 @@ export default {
1912
1887
  } else {
1913
1888
  if (self.auditParams.auditResult == '40'){
1914
1889
  self.rejectAttributeList.push(
1915
- {
1916
- type: 'returnToCurrentAuditUser',
1917
- name: '返回我'
1918
- }
1890
+ {
1891
+ type: 'returnToCurrentAuditUser',
1892
+ name: '返回我'
1893
+ }
1919
1894
  )
1920
1895
  } else {
1921
1896
  self.rejectAttributeList.push(
1922
- {
1923
- type: 'returnToCurrentNode',
1924
- name: '返回本节点'
1925
- }
1897
+ {
1898
+ type: 'returnToCurrentNode',
1899
+ name: '返回本节点'
1900
+ }
1926
1901
  )
1927
1902
  if (!resp.data.data.multiNode){
1928
1903
  self.rejectAttributeList.push(
1929
- {
1930
- type: 'returnToCurrentAuditUser',
1931
- name: '返回我'
1932
- }
1904
+ {
1905
+ type: 'returnToCurrentAuditUser',
1906
+ name: '返回我'
1907
+ }
1933
1908
  )
1934
1909
  }
1935
1910
  }
@@ -1954,7 +1929,51 @@ export default {
1954
1929
  return originalString.replace(regex, replaceString)
1955
1930
  }
1956
1931
  return originalString
1957
- }
1932
+ },
1933
+ changeTab(name){
1934
+ if (name === 'processTrace'){
1935
+ this.processPrint()
1936
+ this.$nextTick(() => {
1937
+ setTimeout(() => {
1938
+ if (this.$refs.processTraceTab.$el) {
1939
+ let modalElement = this.$refs.processTraceTab.$el
1940
+ for (let i = 0; i < modalElement.children.length; i++) {
1941
+ //找到滚动的目标element
1942
+ let targetElement = modalElement.children[i]
1943
+ if (targetElement.classList.toString().includes('-wrap')){
1944
+ this.scrollElement = targetElement
1945
+ break
1946
+ }
1947
+ }
1948
+ }
1949
+ }, 1000);
1950
+ })
1951
+ }
1952
+ this.currentTab = name
1953
+ },
1954
+ getTransferRangeAndOpenModal(organTreeType, permScope, actionType, id){
1955
+ const self = this
1956
+ const params = {
1957
+ procType: self.procType,
1958
+ procId: self.procId,
1959
+ taskNode: self.taskNode,
1960
+ applyId: self.applyId,
1961
+ taskId: self.curTaskId,
1962
+ processInstanceId: self.instanceId,
1963
+ auditGroup: self.auditGroup,
1964
+ actionType: actionType,
1965
+ }
1966
+ const url = self.smartFlowServerContext + '/manage/nodeConfig/getTransferRange';
1967
+ ajax.post(url, params).then(resp => {
1968
+ if (resp.data.code === '200'){
1969
+ const data = resp.data.data
1970
+ self.$refs.assigneeHelpBox.toggleShowHelpBox(organTreeType, permScope, actionType, id, data)
1971
+ }
1972
+ }).catch(error => {
1973
+ self.$Message.error('获取交接人员范围失败');
1974
+ console.log(error)
1975
+ })
1976
+ },
1958
1977
  },
1959
1978
  watch: {
1960
1979
  auditOpinionText(label) {
@@ -1990,7 +2009,17 @@ export default {
1990
2009
  padding: 10px;
1991
2010
  }
1992
2011
 
1993
- .page-info /deep/ .page-body {
2012
+ /deep/ .page-body {
1994
2013
  overflow-y: hidden;
2014
+ padding: 0 0 50px 0 !important;
1995
2015
  }
2016
+
2017
+ /deep/ .ivu-tabs-bar {
2018
+ margin-bottom: 0;
2019
+ }
2020
+
2021
+ /deep/ .ivu-tabs-nav .ivu-tabs-tab {
2022
+ padding: 4px 16px;
2023
+ }
2024
+
1996
2025
  </style>