@lambo-design/workflow-approve 1.0.0-beta.9 → 1.0.0-beta.90

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.
@@ -0,0 +1,542 @@
1
+ <template>
2
+ <div class="process-info-content">
3
+ <a v-if="!isDetail" @click="auditShow = !auditShow">
4
+ <Title
5
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
6
+ <a style="color: #989898">
7
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
8
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
9
+ {{ handleName }}信息
10
+ </a>
11
+ </Title>
12
+ </a>
13
+ <transition v-if="!isDetail" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave"
14
+ @leave="leave">
15
+ <div class="box" v-show="auditShow">
16
+ <Form ref="auditOpinion" justify="center" :label-width="100" :model="form"
17
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
18
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
19
+ <FormItem :label="auditOpinionTitle" prop="auditOpinion">
20
+ <AuditOpinion v-model="form.auditOpinion" :attachment-file="handleButtons.includes('attachmentFile')"
21
+ :attachmentdata="fileList" :default-audit-opinion="defaultAuditOpinion"
22
+ :smart-flow-server-context="smartFlowServerContext" @handle-file="handleFile"></AuditOpinion>
23
+ </FormItem>
24
+ </Form>
25
+ <Form ref="auditOpinion" justify="center" :label-width="100"
26
+ v-if="handleButtons && !handleButtons.includes('auditOpinion') && handleButtons.includes('attachmentFile')"
27
+ style="margin: 10px 0 0 10px;">
28
+ <FormItem style="min-height: 70px">
29
+ <Tooltip placement="bottom" max-width="200">
30
+ <div style="font-size: smaller" slot="content">支持扩展名:.pdf .doc .docx .txt .xls .xlsx .jpg .jpeg
31
+ .png .gif
32
+ </div>
33
+ <UploadFile @upload-result="uploadFile" :multiple="true"
34
+ :oss-server-context="smartFlowServerContext"
35
+ :oss-file-put-url="ossFilePutUrl"></UploadFile>
36
+ </Tooltip>
37
+ </FormItem>
38
+ </Form>
39
+ </div>
40
+ </transition>
41
+ <a v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" @click="auditShow = !auditShow">
42
+ <Title
43
+ v-if="handleButtons && (handleButtons.includes('auditOpinion') || handleButtons.includes('attachmentFile'))">
44
+ <a style="color: #989898">
45
+ <Icon v-if="auditShow" type="ios-arrow-down"/>
46
+ <Icon v-if="!auditShow" type="ios-arrow-up"/>
47
+ {{ handleName }}信息
48
+ </a>
49
+ </Title>
50
+ </a>
51
+ <transition v-if="taskNode && isDetail && hisAuditOpinion[0].auditOpinion" name="draw"
52
+ @before-enter="beforeEnter"
53
+ @enter="enter" @before-leave="beforeLeave" @leave="leave">
54
+ <div class="box" v-show="auditShow">
55
+ <Form ref="auditOpinion" justify="center" :model="form"
56
+ v-if="handleButtons && handleButtons.includes('auditOpinion')"
57
+ style="margin: 10px 0 0 10px;" :rules="ruleValidate">
58
+ <FormItem style="margin-left: -60px">
59
+ <Card v-for="(item, index) in hisAuditOpinion" :key="index">
60
+ <Row style="display: flex">
61
+ <Col span="24">
62
+ <div style="word-wrap: break-word;">
63
+ <span>{{ item.auditOpinion }}</span>
64
+ <div style="position: absolute; right: 0;bottom: -18px;color: grey">{{ item.auditTime }}</div>
65
+ </div>
66
+ </Col>
67
+ </Row>
68
+ </Card>
69
+ </FormItem>
70
+ </Form>
71
+ </div>
72
+ </transition>
73
+ <a @click="historyShow = !historyShow">
74
+ <Title v-if="handleButtons && handleButtons.includes('auditHistory')">
75
+ <a style="color: #989898">
76
+ <Icon v-if="historyShow" type="ios-arrow-down"/>
77
+ <Icon v-if="!historyShow" type="ios-arrow-up"/>
78
+ {{ handleName }}记录
79
+ </a>
80
+ </Title>
81
+ </a>
82
+ <transition name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
83
+ <div class="box" v-show="historyShow">
84
+ <Card class="process-history" :style="processHistoryHeight" dis-hover :bordered="false"
85
+ v-if="handleButtons && handleButtons.includes('auditHistory')">
86
+ <processHistory :portrait-width="processInfoWidth" :list="processHistory" :done-page="isDetail"
87
+ :push-button="pushButton"
88
+ :smart-flow-server-context="smartFlowServerContext"></processHistory>
89
+ </Card>
90
+ </div>
91
+ </transition>
92
+ <a @click="attachListShow = !attachListShow">
93
+ <Title v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0 && attachListShow">
94
+ <a style="color: #989898">
95
+ <Icon v-if="attachListShow" type="ios-arrow-down"/>
96
+ <Icon v-if="!attachListShow" type="ios-arrow-up"/>
97
+ 查看附件
98
+ </a>
99
+ </Title>
100
+ </a>
101
+ <transition v-if="handleButtons && handleButtons.includes('attachmentFile') && attachmentList.length > 0 && attachListShow" name="draw" @before-enter="beforeEnter" @enter="enter" @before-leave="beforeLeave" @leave="leave">
102
+ <div class="box" v-if="!inHorizontal">
103
+ <div v-for="(item, index) in attachmentList" :key="index">
104
+ <Card dis-hover class="attach-card">
105
+ <List item-layout="vertical">
106
+ <ListItem style="margin-top: -8px">
107
+ <Row style="display: flex; align-items: center;">
108
+ <!-- 左边:图片 -->
109
+ <Col span="4" style="margin-top: -25px">
110
+ <avatar v-if="item.fileType === 'image'" icon="ios-image-outline" class="attach-avatar"
111
+ style="background-color: #005aff"
112
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
113
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
114
+ <avatar v-else-if="item.fileType === 'doc'" icon="ios-document-outline" class="attach-avatar"
115
+ style="background-color: #005aff"
116
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
117
+ :size="portraitWidth >= 600 ? 'middle' : 'small'">
118
+ </avatar>
119
+ <avatar v-else-if="item.fileType === 'xlsx'" icon="ios-document-outline" class="attach-avatar"
120
+ style="background-color: #19be6b"
121
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
122
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
123
+ <avatar v-else-if="item.fileType === 'pdf'" icon="ios-document-outline" class="attach-avatar"
124
+ style="background-color: #ed4014"
125
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
126
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
127
+ <avatar v-else icon="ios-document-outline" class="attach-avatar"
128
+ :style="portraitWidth >= 600 ? 'margin-left: 10px' : ''"
129
+ :size="portraitWidth >= 600 ? 'middle' : 'small'"></avatar>
130
+ </Col>
131
+ <!-- 右边:附件信息 -->
132
+ <Col span="20">
133
+ <Row>
134
+ <tooltip>
135
+ <span class="attach-name-style"> {{ item.attachName }}</span>
136
+ <div slot="content" style="white-space: normal"> {{ item.attachName }}</div>
137
+ </tooltip>
138
+ </Row>
139
+ <Row style="margin-top: 3px">
140
+ <span style="color: #005aff; font-size: 13px;">{{ item.uploadUserName }}</span>
141
+ <Divider style="background-color:#808695;height: 1em;margin: 4px 9px 0 6px;"
142
+ type="vertical"/>
143
+ <span style="color: #808695;font-size: 13px"
144
+ >{{ showTaskNode(item.taskId) }}</span>
145
+ </Row>
146
+ <Row style="margin-bottom: -10px; margin-top: 10px">
147
+ <template>
148
+ <Button @click="getAttach(item)" size="small">下载</Button>
149
+ <Button v-if="item.showPreview" ghost type="primary" @click="preViewAttach(item)"
150
+ style="margin-left: 10px" size="small">预览
151
+ </Button>
152
+ </template>
153
+ </Row>
154
+ </Col>
155
+ </Row>
156
+
157
+ </ListItem>
158
+ </List>
159
+ </Card>
160
+ </div>
161
+ </div>
162
+ <div class="box" v-else style="margin: 20px">
163
+ <LamboPagingTable :requestSuccessCodes="requestSuccessCodes" :pageDisable="true" ref="table" :dataUrl="dataUrl" :columns="tableColumn"></LamboPagingTable>
164
+ </div>
165
+ </transition>
166
+ <Modal title="查看附件" v-model="modalVisible" fullscreen scrollable :mask="false">
167
+ <img :src="imageUrl" v-if="modalVisible" alt="" style="width: 100%">
168
+ <div slot="footer">
169
+ <Button type="primary" @click="modalVisible = false">关闭</Button>
170
+ </div>
171
+ </Modal>
172
+ <Modal title="查看附件" v-model="modalDocx" fullscreen scrollable :mask="false">
173
+ <div ref="file"></div>
174
+ </Modal>
175
+ </div>
176
+ </template>
177
+
178
+ <script>
179
+ import ajax from "@lambo-design/shared/utils/ajax";
180
+ import axios from "axios";
181
+ import Title from './title'
182
+ import processHistory from './history'
183
+ import AuditOpinion from './opinion'
184
+ import UploadFile from '@lambo-design/upload-file'
185
+ import {operateBtn} from "@lambo-design/shared/utils/assist";
186
+ import LamboPagingTable from '@lambo-design/paging-table'
187
+
188
+ // 引入docx-preview插件
189
+ let docx = require('docx-preview')
190
+
191
+ export default {
192
+ name: "process-info",
193
+ components: {
194
+ Title,
195
+ processHistory,
196
+ AuditOpinion,
197
+ UploadFile,
198
+ LamboPagingTable,
199
+ },
200
+ props: {
201
+ value: {
202
+ type: String,
203
+ required: false,
204
+ default: ''
205
+ },
206
+ isDetail: {
207
+ type: Boolean,
208
+ required: false,
209
+ default: false
210
+ },
211
+ procId: {
212
+ type: String,
213
+ required: true,
214
+ },
215
+ taskNode: {
216
+ type: String,
217
+ required: true,
218
+ },
219
+ applyId: {
220
+ type: String,
221
+ required: true,
222
+ },
223
+ taskId: {
224
+ type: String,
225
+ required: false,
226
+ default: '',
227
+ },
228
+ defaultAuditOpinion: {
229
+ type: String,
230
+ required: false,
231
+ default: '',
232
+ },
233
+ //详情页催办按钮
234
+ pushButton: {
235
+ type: Boolean,
236
+ required: false,
237
+ default: true,
238
+ },
239
+ //组件宽度
240
+ portraitWidth: {
241
+ type: Number,
242
+ default: 0
243
+ },
244
+ //是否显示竖向布局
245
+ inHorizontal: {
246
+ type: Boolean,
247
+ default: false
248
+ },
249
+ //审批名称
250
+ handleName: {
251
+ type: String,
252
+ default: '审批',
253
+ },
254
+ //操作按钮
255
+ handleButtons: {
256
+ type: [Array, String],
257
+ default: () => ([])
258
+ },
259
+ //审批历史
260
+ processHistory: {
261
+ type: Array,
262
+ default: () => ([])
263
+ },
264
+ smartFlowServerContext: {
265
+ type: String,
266
+ default: '/api/smart-flow-server',
267
+ },
268
+ },
269
+ data(){
270
+ return{
271
+ auditShow: true,
272
+ historyShow: true,
273
+ attachListShow: true,
274
+ modalVisible: false,
275
+ modalDocx: false,
276
+ imageUrl: '',
277
+ processInfoWidth: 400,
278
+ auditOpinionTitle: this.handleName + '意见',
279
+ fileList: [],
280
+ attachmentList: [],
281
+ requestSuccessCodes: [200, "200"],
282
+ dataUrl: this.smartFlowServerContext + '/manage/processDone/getAttachmentList?procId='+this.procId + '&applyId=' + this.applyId,
283
+ form: {
284
+ auditOpinion: '',
285
+ },
286
+ hisAuditOpinion: [{
287
+ auditOpinion: '',
288
+ auditTime: '',
289
+ }],
290
+ ossFilePutUrl: '/manage/oss/file/put',
291
+ ruleValidate: {
292
+ auditOpinion: [{ required: true, trigger: 'blur', message: '意见不能为空' }],
293
+ assignee: [{ required: true, trigger: 'blur', message: '办理人不能为空' }],
294
+ candidateGroups: [{ required: true, trigger: 'blur', message: '候选人不能为空' }],
295
+ },
296
+ }
297
+ },
298
+ computed: {
299
+ processHistoryHeight() {
300
+ if (this.inHorizontal) return ''
301
+ let str = ''
302
+ const hasAuditOpinion = this.taskNode && this.handleButtons && this.handleButtons.includes('auditOpinion')
303
+ const hasAttachmentFile = this.handleButtons && this.handleButtons.includes('auditHistory') && this.attachmentList.length > 0
304
+ const isDetail = this.isDetail && !this.hisAuditOpinion[0].auditOpinion.length > 0
305
+ if (hasAuditOpinion && !hasAttachmentFile && !isDetail) {
306
+ str += 'height: 43vh'
307
+ } else if (hasAuditOpinion && hasAttachmentFile && !isDetail) {
308
+ str += 'height: 40vh'
309
+ } else {
310
+ str += 'height: 67vh'
311
+ }
312
+ return str
313
+ },
314
+ tableColumn() {
315
+ let column = [];
316
+ let self = this;
317
+ column.push({
318
+ title: '序号',
319
+ type: 'index',
320
+ width: 70,
321
+ align: 'center',
322
+ });
323
+ column.push({
324
+ title: '附件名称', key: 'fileName', minWidth: 150, align: 'center',
325
+ render(h, {row}) {
326
+ const index= row.fileName.lastIndexOf(".");
327
+ const fileName=row.fileName.substr(0,index)
328
+ return h("span",fileName)
329
+
330
+ }
331
+ });
332
+ column.push({
333
+ title: '附件类型', width: 100, align: 'center',
334
+ render:(h,{row})=>{
335
+ const index= row.fileName.lastIndexOf(".");
336
+ const fileType=row.fileName.substr(index+1)
337
+ return h("span",fileType)
338
+ }
339
+ });
340
+
341
+ column.push({
342
+ title: "上传人姓名",
343
+ key: "uploadUserName",
344
+ width: 170,
345
+ align: "center",
346
+ });
347
+
348
+ column.push({
349
+ title: "节点名称",
350
+ key: "taskName",
351
+ width: 170,
352
+ align: "center",
353
+ });
354
+
355
+ column.push({
356
+ title: "操作", width: 160, align: 'center', tooltip: true,
357
+ render: (h, {row}) => {
358
+ const index= row.fileName.lastIndexOf(".");
359
+ const fileType=row.fileName.substr(index+1).toLowerCase()
360
+ // const typeList=['jpg','pdf','gif','png','docx']
361
+ //由于pdf预览显示乱码 暂时不提供pdf预览功能
362
+ const typeList=['jpg','gif','png','docx']
363
+ if (typeList.indexOf(fileType)!==-1){
364
+ return h("div", [
365
+ operateBtn(this, h, row, "下载", () => {
366
+ this.getAttach(row);
367
+ }, "primary"),
368
+ operateBtn(this, h, row, "预览", () => {
369
+ this.preViewAttach(row);
370
+ }, "primary")
371
+ ]);
372
+ }else {
373
+ return h("div", [
374
+ operateBtn(this, h, row, "下载", () => {
375
+ this.getAttach(row);
376
+ }, "primary")
377
+ ]);
378
+ }
379
+
380
+ }
381
+
382
+ });
383
+
384
+ return column;
385
+ },
386
+ },
387
+ methods: {
388
+
389
+ imgPreview(url) {
390
+ this.imageUrl = url
391
+ this.modalVisible = true
392
+ },
393
+ preViewAttach(row) {
394
+ let reg = /\.(gif|jpg|jpeg|bmp|png|PNG)$/
395
+ let regs = /\.(pdf)$/
396
+ if (reg.test(row.fileName)) {
397
+ let url = this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId
398
+ this.imgPreview(url)
399
+ } else if (regs.test(row.fileName)) {
400
+ window.open(this.smartFlowServerContext + '/manage/oss/file/getFileStream?fileId=' + row.fileId, '_blank')
401
+ } else {
402
+ this.modalDocx = true
403
+ axios({
404
+ method: 'get',
405
+ responseType: 'blob', // 因为是流文件,所以要指定blob类型
406
+ url: this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId// 一个word下载文件的接口
407
+ }).then(({ data }) => {
408
+ docx.renderAsync(data, this.$refs.file, null, {
409
+ className: 'docx', //默认和文档样式类的类名/前缀
410
+ inWrapper: true, //启用围绕文档内容呈现包装器
411
+ ignoreWidth: false, //禁用页面的渲染宽度
412
+ ignoreHeight: false, //禁用页面的渲染高度
413
+ ignoreFonts: false, //禁用字体渲染
414
+ breakPages: true, //在分页符上启用分页
415
+ ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
416
+ experimental: false, //启用实验功能(制表符停止计算)
417
+ trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
418
+ useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
419
+ useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
420
+ showChanges: false, //启用文档更改的实验渲染(插入/删除)
421
+ debug: false, //启用额外的日志记录
422
+ })
423
+ }
424
+ )
425
+ }
426
+ },
427
+ getAttach(row) {
428
+ window.open(this.smartFlowServerContext + '/manage/oss/file/get/' + row.fileId, '_blank')
429
+ },
430
+ showTaskNode(taskId) {
431
+ if (this.processHistory.length > 0) {
432
+ let task = null
433
+ this.processHistory.some(itemList => {
434
+ task = itemList.find(item => item.taskId === taskId)
435
+ return task !== undefined
436
+ })
437
+ return task ? task.taskName : ''
438
+ }
439
+ return ''
440
+ },
441
+ getAttachList(taskId) {
442
+ const self = this
443
+ const param = {
444
+ taskId: taskId,
445
+ procId: this.procId,
446
+ applyId: this.applyId
447
+ }
448
+ ajax.get(self.smartFlowServerContext + '/manage/processDone/getAttachmentList', { params: param }).then(function (resp) {
449
+ self.attachmentList = resp.data.data.rows
450
+ self.attachmentList.forEach(item => {
451
+ const index = item.fileName.lastIndexOf('.')
452
+ const fileType = item.fileName.substr(index + 1).toLowerCase()
453
+ const imageList = ['jpg', 'gif', 'png', 'svg']
454
+ const docList = ['doc', 'docx']
455
+ const zipList = ['rar', 'zip']
456
+ const typeList = ['jpg', 'gif', 'png', 'docx']
457
+ item.fileType = imageList.indexOf(fileType) !== -1 ? 'image' : docList.indexOf(fileType) !== -1 ? 'doc' : zipList.indexOf(fileType) !== -1 ? 'zip' : fileType
458
+ item.showPreview = typeList.indexOf(fileType) !== -1
459
+ })
460
+ }).catch(err => {
461
+ console.log(err)
462
+ })
463
+ },
464
+ uploadFile(file) {
465
+ const self = this
466
+ self.fileList = []
467
+ file.forEach(item => {
468
+ self.fileList.push({
469
+ fileName: item.fileName,
470
+ fileId: item.fileCode,
471
+ })
472
+ })
473
+ this.$emit('upload-file', self.fileList)
474
+ },
475
+ handleFile(file){
476
+ this.$emit('upload-file', file)
477
+ },
478
+
479
+ //折叠动画效果
480
+ beforeEnter(el) {
481
+ el.style.height = '0'
482
+ },
483
+ enter(el, done) {
484
+ setTimeout(() => {
485
+ el.style.height = el.scrollHeight + 'px'
486
+ }, 0)
487
+
488
+ el.addEventListener('transitionend', done)
489
+ },
490
+ beforeLeave(el) {
491
+ el.style.height = el.scrollHeight + 'px'
492
+ },
493
+ leave(el, done) {
494
+ setTimeout(() => {
495
+ el.style.height = '0'
496
+ }, 0)
497
+
498
+ el.addEventListener('transitionend', done)
499
+ },
500
+
501
+ beforeFlowInfoEnter(el) {
502
+ el.style.transform = 'translateX(100%)'
503
+ },
504
+ flowInfoEnter(el, done) {
505
+ const transitionDuration = 0.5
506
+ el.style.transition = `transform ${transitionDuration}s`
507
+ el.style.transform = 'translateX(0)'
508
+ el.addEventListener('transitionend', done)
509
+ },
510
+ beforeFlowInfoLeave(el) {
511
+ el.style.transform = 'translateX(0)'
512
+ },
513
+ flowInfoLeave(el, done) {
514
+ const transitionDuration = 0.5
515
+ el.style.transition = `transform ${transitionDuration}s`
516
+ el.style.transform = 'translateX(100%)'
517
+ el.addEventListener('transitionend', done)
518
+ },
519
+ },
520
+ mounted() {
521
+ this.getAttachList(this.taskId)
522
+ this.processInfoWidth = this.inHorizontal ? 1000 : this.portraitWidth
523
+ this.form.auditOpinion = this.value;
524
+ },
525
+ watch: {
526
+ 'form.auditOpinion'(val) {
527
+ this.$emit('input', val)
528
+ },
529
+ value(newVal) {
530
+ this.form.auditOpinion = newVal;
531
+ },
532
+ defaultAuditOpinion(val) {
533
+ this.auditOpinion = this.defaultAuditOpinion
534
+ this.$emit('input', val)
535
+ }
536
+ }
537
+ }
538
+ </script>
539
+
540
+ <style scoped>
541
+
542
+ </style>