fl-web-component 0.1.0

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.
Files changed (52) hide show
  1. package/README.md +24 -0
  2. package/dist/demo.html +10 -0
  3. package/dist/fl-web-component.common.js +316 -0
  4. package/dist/fl-web-component.common.js.map +1 -0
  5. package/dist/fl-web-component.css +1 -0
  6. package/dist/fl-web-component.umd.js +326 -0
  7. package/dist/fl-web-component.umd.js.map +1 -0
  8. package/dist/fl-web-component.umd.min.js +2 -0
  9. package/dist/fl-web-component.umd.min.js.map +1 -0
  10. package/package.json +47 -0
  11. package/packages/components/button/index.vue +22 -0
  12. package/packages/components/model/api/index.js +429 -0
  13. package/packages/components/model/api/mock/detecttree.js +58 -0
  14. package/packages/components/model/api/mock/getmodel-line.js +79336 -0
  15. package/packages/components/model/api/mock/init.js +1 -0
  16. package/packages/components/model/api/mock/pbstree.js +835 -0
  17. package/packages/components/model/api/mock/topology.json +3238 -0
  18. package/packages/components/model/components/TextOverTooltip/index.vue +84 -0
  19. package/packages/components/model/components/annotation-toolbar.vue +425 -0
  20. package/packages/components/model/components/check-proofing-model.vue +42 -0
  21. package/packages/components/model/components/clipping-type.vue +51 -0
  22. package/packages/components/model/components/com-dialogWrapper/Readme.md +53 -0
  23. package/packages/components/model/components/com-dialogWrapper/index.vue +117 -0
  24. package/packages/components/model/components/detect-panel.vue +327 -0
  25. package/packages/components/model/components/detect-tree.vue +460 -0
  26. package/packages/components/model/components/firstPer-panel.vue +111 -0
  27. package/packages/components/model/components/header-button.vue +546 -0
  28. package/packages/components/model/components/imageViewer/index.vue +127 -0
  29. package/packages/components/model/components/import-model.vue +127 -0
  30. package/packages/components/model/components/location-panel.vue +95 -0
  31. package/packages/components/model/components/measure-type.vue +59 -0
  32. package/packages/components/model/components/pbs-tree.vue +502 -0
  33. package/packages/components/model/components/proof-config.vue +80 -0
  34. package/packages/components/model/components/proof-for-pc.vue +123 -0
  35. package/packages/components/model/components/proof-history.vue +318 -0
  36. package/packages/components/model/components/proof-panel-detail.vue +567 -0
  37. package/packages/components/model/components/proof-panel.vue +770 -0
  38. package/packages/components/model/components/proof-project-user.vue +482 -0
  39. package/packages/components/model/components/proof-publish.vue +130 -0
  40. package/packages/components/model/components/proof-role.vue +535 -0
  41. package/packages/components/model/components/props-panel.vue +249 -0
  42. package/packages/components/model/index.vue +3413 -0
  43. package/packages/components/model/readme.md +31 -0
  44. package/packages/components/model/utils/annotation-tool.js +340 -0
  45. package/packages/components/model/utils/cursor.js +18 -0
  46. package/packages/components/model/utils/detect-v1.js +341 -0
  47. package/packages/components/model/utils/index.js +48 -0
  48. package/packages/components/model/utils/threejs/measure-angle.js +258 -0
  49. package/packages/components/model/utils/threejs/measure-area.js +269 -0
  50. package/packages/components/model/utils/threejs/measure-distance.js +207 -0
  51. package/packages/components/model/utils/threejs/measure-volume.js +94 -0
  52. package/packages/index.js +24 -0
@@ -0,0 +1,567 @@
1
+ <template>
2
+ <!-- 添加批注 -->
3
+ <div>
4
+ <el-dialog
5
+ v-if="showDialog"
6
+ title="视点"
7
+ confirm-text="确定"
8
+ width="60%"
9
+ custom-class="test-dialog"
10
+ :append-to-body="true"
11
+ :visible.sync="showDialog"
12
+ :fullscreen="isClient"
13
+ :show-close="!this.isClient"
14
+ :before-close="beforeClose"
15
+ >
16
+ <el-row v-loading="loading" :gutter="20" type="flex" justify="center">
17
+ <el-col
18
+ :span="16"
19
+ style="
20
+ border-radius: 6px;
21
+ position: relative;
22
+ height: 530px;
23
+ background: #f6f6f6;
24
+ "
25
+ >
26
+ <div
27
+ class="image-edit-container"
28
+ v-show="!readOnlyMode"
29
+ v-if="!isClient"
30
+ v-hasPermi="btnPermission"
31
+ >
32
+ <i
33
+ class="el-icon-edit-outline image-edit"
34
+ @click="clickEdit"
35
+ ></i>
36
+ </div>
37
+ <ImageViewer ref="ImageViewrRef" :image-url="screenshotUrl" :isErrorImage="isErrorImage"/>
38
+ </el-col>
39
+ <!-- 新增批注内容 -->
40
+ <!-- :disabled="disabledDetailForm" -->
41
+ <el-col :span="8">
42
+ <el-descriptions :column="1" v-if="readOnlyMode || isClient">
43
+ <el-descriptions-item label="所属专业">{{ postName }}</el-descriptions-item>
44
+ <el-descriptions-item label="问题描述">
45
+ <el-input
46
+ type="textarea"
47
+ :rows="3"
48
+ size="medium"
49
+ placeholder="请输入"
50
+ v-model="detailModel.description"
51
+ disabled
52
+ >
53
+ </el-input>
54
+ </el-descriptions-item>
55
+ </el-descriptions >
56
+ <el-form
57
+ v-else
58
+ @submit.native.prevent
59
+ :model="detailModel"
60
+ ref="detailForm"
61
+ :inline="true"
62
+ label-width="68px"
63
+ class="detail-form"
64
+ >
65
+ <el-form-item label="所属专业" prop="postId">
66
+ <el-select v-model="detailModel.postId" placeholder="请选择">
67
+ <el-option
68
+ v-for="item in postList"
69
+ :key="item.postId"
70
+ :label="item.postName"
71
+ :value="item.postId"
72
+ :disabled="item.disabled"
73
+ >
74
+ </el-option>
75
+ </el-select>
76
+ </el-form-item>
77
+ <el-form-item label="问题描述" prop="description">
78
+ <el-input
79
+ type="textarea"
80
+ :rows="3"
81
+ size="medium"
82
+ placeholder="请输入"
83
+ v-model="detailModel.description"
84
+ >
85
+ </el-input>
86
+ <!-- <el-input
87
+
88
+ v-model="detailModel.desc"
89
+ prefix-icon="el-icon-search"
90
+ placeholder="请输入"
91
+ clearable
92
+ size="small"
93
+ @keyup.enter.native="handleQuery"
94
+ /> -->
95
+ </el-form-item>
96
+ </el-form>
97
+ <el-divider content-position="left">回复</el-divider>
98
+ <el-form
99
+ v-if="isClient"
100
+ ref="form"
101
+ :model="detailModel"
102
+ label-width="68px"
103
+ class="reply-form"
104
+ :rules="rules"
105
+ >
106
+ <el-form-item label="解决人" prop="solveBy">
107
+ <el-select v-model="detailModel.solveBy" placeholder="请选择">
108
+ <el-option
109
+ v-for="item in userList"
110
+ :key="item.userId"
111
+ :label="item.userName"
112
+ :value="item.userName"
113
+ >
114
+ </el-option>
115
+ </el-select>
116
+ </el-form-item>
117
+
118
+ <el-form-item label="解决意见" prop="status">
119
+ <el-select v-model="detailModel.status" placeholder="请选择">
120
+ <el-option
121
+ v-for="item in filterStatusOpt"
122
+ :key="item.value"
123
+ :label="item.label"
124
+ :value="item.value"
125
+ >
126
+ </el-option>
127
+ </el-select>
128
+ </el-form-item>
129
+
130
+ <!-- <el-form-item label="视点截图">
131
+ <el-image
132
+ v-if="detailModel.replyPrintscreen"
133
+ :src="`//${detailModel.replyPrintscreen}`"
134
+ :preview-src-list="[`//${detailModel.replyPrintscreen}`]"
135
+ >
136
+ </el-image>
137
+ <span v-else>暂无</span>
138
+ </el-form-item> -->
139
+ <el-form-item label="备注" prop="remark">
140
+ <el-input
141
+ type="textarea"
142
+ :rows="2"
143
+ size="small"
144
+ placeholder="请输入"
145
+ v-model="detailModel.remark"
146
+ />
147
+ </el-form-item>
148
+ <el-form-item label="创建时间" prop="createTime">
149
+ {{ detailModel.createTime }}
150
+ </el-form-item>
151
+ <el-form-item label="回复时间" prop="replyTime"
152
+ >{{ detailModel.replyTime }}
153
+ </el-form-item>
154
+ </el-form>
155
+ <el-descriptions :column="1" v-else>
156
+ <el-descriptions-item label="解决人">{{ detailModel.solveBy }}</el-descriptions-item>
157
+ <el-descriptions-item label="解决意见">{{ proofStatus }}</el-descriptions-item>
158
+ <el-descriptions-item label="备注">{{ detailModel.remark }}</el-descriptions-item>
159
+ <el-descriptions-item label="创建时间">{{ detailModel.createTime }}</el-descriptions-item>
160
+ <el-descriptions-item label="回复时间">{{ detailModel.replyTime }}</el-descriptions-item>
161
+ </el-descriptions >
162
+ </el-col>
163
+ </el-row>
164
+ <span v-show="!readOnlyMode" slot="footer" class="dialog-footer">
165
+ <el-button @click="close(true, true)">取消</el-button>
166
+ <el-button
167
+ v-if="isClient"
168
+ type="primary"
169
+ @click="clickSave"
170
+ :loading="updatingOpinion"
171
+ >保存</el-button>
172
+ <el-button
173
+ v-else
174
+ type="primary"
175
+ @click="clickSave"
176
+ :loading="updatingOpinion"
177
+ v-hasPermi="btnPermission"
178
+ >保存</el-button>
179
+ </span>
180
+ </el-dialog>
181
+ </div>
182
+ </template>
183
+ <script>
184
+ import ImageViewer from './imageViewer'
185
+ export default {
186
+ components: {
187
+ ImageViewer
188
+ },
189
+ props: {
190
+ dialogVisible: {
191
+ type: Boolean,
192
+ default: false
193
+ },
194
+ // 批注前初始的文档文件数据
195
+ fileData: {
196
+ type: Object,
197
+ default: () => {}
198
+ },
199
+ // 批注后文件的数据
200
+ annotationFileData: {
201
+ type: Object,
202
+ default: () => {}
203
+ },
204
+ // // 列表id 用于查看详情
205
+ // dataId: {
206
+ // type: Number,
207
+ // default: 0
208
+ // },
209
+ // 操作类型
210
+ moduleType: {
211
+ type: String,
212
+ default: 'add'
213
+ },
214
+ detailProps: {
215
+ type: Object,
216
+ default: () => {}
217
+ },
218
+ postList: {
219
+ type: Array,
220
+ default: () => []
221
+ },
222
+ userList: {
223
+ type: Array,
224
+ default: () => []
225
+ },
226
+ isClient:{
227
+ type: Boolean,
228
+ default: false
229
+ },
230
+ readOnlyMode:{
231
+ type: Boolean,
232
+ default: false,
233
+ },
234
+ updatingOpinion: {
235
+ type: Boolean,
236
+ default: false,
237
+ },
238
+ defaultParams: {
239
+ type: Object,
240
+ default() {
241
+ return {};
242
+ },
243
+ },
244
+ },
245
+ computed: {
246
+ screenshotUrl: {
247
+ get(){
248
+ // console.log(this.detailModel.previewScreenshotData)
249
+ const screenshotUrl = this.detailModel.previewScreenshotData || `//${this.detailModel.problemPrintscreen}`;
250
+ return screenshotUrl;
251
+ },
252
+ set(val){
253
+ this.detailModel.problemPrintscreen = val;
254
+ }
255
+ },
256
+ detailModel: {
257
+ get(){
258
+ const detailData = Object.keys(this.detailProps).length ? this.detailProps
259
+ : Object.keys(this.detailData).length ? this.detailData : {};
260
+
261
+ return detailData
262
+ }
263
+ },
264
+ isErrorImage(){
265
+ return !(this.detailModel.previewScreenshotData || this.detailModel.problemPrintscreen);
266
+ },
267
+ solveBy(){
268
+ const item = this.userList.find(item => item.value === this.detailModel.solveBy)
269
+ return item && item.value;
270
+ },
271
+ proofStatus(){
272
+ const item = this.filterStatusOpt.find(item => item.value === this.detailModel.status)
273
+ return item && item.label
274
+ },
275
+ postName(){
276
+ const item = this.postList.find(item => item.postId === this.detailModel.postId)
277
+ return item && item.postName
278
+ },
279
+ isEditing() {
280
+ return this.detailProps.id != undefined
281
+ },
282
+ btnPermission() {
283
+ const btnPermission = this.isEditing ? [`project:opinion:edit:proj:${this.defaultParams.projectId}`] : [`project:opinion:add:proj:${this.defaultParams.projectId}`];
284
+ return btnPermission
285
+ }
286
+ },
287
+ data() {
288
+ return {
289
+ loading: false,
290
+ dialogLoading: false,
291
+ form: {},
292
+ imageUrl: '', // 图片路径
293
+ // nickName: this.filterUser(store.getters.userId), // 用户名
294
+ // userName: store.getters.name, // 用户登录名
295
+ // departName: JSON.parse(sessionStorage.getItem('dept')).deptName, // 部门
296
+ chooseUserDialog: false,
297
+ // fileId: '',
298
+ confirmText: '提交',
299
+ detailData: {},
300
+ filterStatusOpt: [
301
+ {
302
+ value: "0",
303
+ label: "未处理",
304
+ },
305
+ {
306
+ value: "1",
307
+ label: "已处理",
308
+ },
309
+ {
310
+ value: "2",
311
+ label: "待确认",
312
+ }
313
+ ],
314
+ showDialog: false,
315
+ rules: {
316
+ solveBy: [
317
+ { required: true, message: "请选择解决人", trigger: "blur" },
318
+ ],
319
+ }
320
+ }
321
+ },
322
+ watch: {
323
+ dialogVisible(val) {
324
+ if (val) {
325
+ this.showDialog = true
326
+ } else {
327
+ this.showDialog = false
328
+ }
329
+ },
330
+ showDialog(val){
331
+ val === false && this.close(true)
332
+ }
333
+ },
334
+ created() {
335
+ if (this.moduleType === 'add') {
336
+ // this.fileId = this.annotationFileData.fileId
337
+ // this.getUserList() // 获取用户列表
338
+ // this.perview() // 预览
339
+ } else {
340
+ // this.moduleType === 'operation' && this.getUserList() // 获取用户列表
341
+ this.handleDetail()
342
+ }
343
+ },
344
+ methods: {
345
+ perview() {
346
+ let _this = this
347
+ perview({ id: this.fileId })
348
+ .then((res) => {
349
+ let reader = new FileReader()
350
+ reader.readAsDataURL(res) // 转换为base64
351
+ reader.onload = function () {
352
+ _this.imageUrl = reader.result
353
+ _this.$refs.ImageViewrRef.resetImage()
354
+ }
355
+ })
356
+ .finally(() => {
357
+ this.loading = false
358
+ })
359
+ },
360
+ // 详情
361
+ handleDetail() {
362
+ this.loading = true
363
+ detail({ id: this.dataId }).then((res) => {
364
+ if (res.code === 200) {
365
+ this.detailData = res.data
366
+ // 撤回状态
367
+ if (res.data.status === '2' && this.moduleType === 'view')
368
+ this.detailData.recordList = [res.data]
369
+ // 流程字段 操作模式并当前登陆人 = 创建人
370
+ if (
371
+ this.moduleType === 'operation' &&
372
+ this.detailData.createBy === this.userName &&
373
+ this.detailData.recordList.length === 0
374
+ ) {
375
+ this.form.operateState = '0'
376
+ this.$nextTick(() => {
377
+ this.$refs.form.clearValidate('operateState') // 移除校验
378
+ })
379
+ }
380
+ this.fileId = res.data.fileId
381
+ this.perview()
382
+ }
383
+ })
384
+ },
385
+ // 下一处理人 输入建议
386
+ querySearch(queryString, cb) {
387
+ var restaurants = this.userList
388
+ var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
389
+ // 调用 callback 返回建议列表的数据
390
+ if (results.length === 0) {
391
+ this.form.nextUser = ''
392
+ this.form.nextUserName = ''
393
+ this.$set(this.form, 'nextUserName', '')
394
+ }
395
+ cb(results)
396
+ },
397
+ createFilter(queryString) {
398
+ return (restaurant) => {
399
+ return restaurant.nickName.toLowerCase().indexOf(queryString.toLowerCase()) === 0
400
+ }
401
+ },
402
+ // 选择处理人
403
+ handleSelect(item) {
404
+ this.form.nextUser = item.userName
405
+ this.form.nextUserName = item.nickName
406
+ this.$set(this.form, 'nextUserName', item.nickName)
407
+ this.$nextTick(() => {
408
+ this.$refs.form.clearValidate('nextUserName') // 移除校验
409
+ })
410
+ },
411
+ // 提交/撤回/操作处理
412
+ dialogConfirm() {
413
+ let that = this
414
+ let timer = null
415
+ switch (this.moduleType) {
416
+ case 'view':
417
+ this.revokeAnnotations() // 撤销
418
+ break
419
+
420
+ default:
421
+ timer = setTimeout(() => {
422
+ that.$refs.form.validate((valid) => {
423
+ if (valid) {
424
+ that.moduleType === 'add' && that.addAnnotations()
425
+ that.moduleType === 'operation' && that.operateAnnotations()
426
+ clearTimeout(timer)
427
+ }
428
+ })
429
+ }, 300)
430
+ break
431
+ }
432
+ },
433
+ // 新增批注
434
+ addAnnotations() {
435
+ this.dialogLoading = true
436
+ let params = {
437
+ // projectId: store.getters.projectId,
438
+ name: this.fileData.fileName,
439
+ origFileId: this.fileData.fileId, // 原始的文件id
440
+ fileId: this.annotationFileData.fileId,
441
+ // deptName: store.getters.deptName,
442
+ type: 'doc' // model:模型。doc:文档
443
+ }
444
+ // 添加批注
445
+ add(Object.assign(params, this.form))
446
+ .then((res) => {
447
+ this.$message({
448
+ type: res.code === 200 ? 'success' : 'error',
449
+ message: res.msg
450
+ })
451
+ if (res.code === 200) this.$emit('handleAdd')
452
+ })
453
+ .finally(() => {
454
+ this.dialogLoading = false
455
+ })
456
+ },
457
+ // 撤销
458
+ revokeAnnotations() {
459
+ this.dialogLoading = true
460
+ revoke({ id: this.detailData.id })
461
+ .then((res) => {
462
+ this.$message({
463
+ type: res.code === 200 ? 'success' : 'error',
464
+ message: res.msg
465
+ })
466
+ if (res.code === 200) this.close(true)
467
+ })
468
+ .finally(() => {
469
+ this.dialogLoading = false
470
+ })
471
+ },
472
+ // 操作 处理
473
+ operateAnnotations() {
474
+ this.dialogLoading = true
475
+ let params = {
476
+ id: this.detailData.id,
477
+ // fileId: this.detailData.fileId,
478
+ // deptName: store.getters.deptName
479
+ }
480
+ operate(Object.assign(params, this.form))
481
+ .then((res) => {
482
+ this.$message({
483
+ type: res.code === 200 ? 'success' : 'error',
484
+ message: res.msg
485
+ })
486
+ if (res.code === 200) this.close(true)
487
+ })
488
+ .finally(() => {
489
+ this.dialogLoading = false
490
+ })
491
+ },
492
+ // 关闭弹窗 refresh 判断是否需要刷新列表数据
493
+ close(refresh, resetForm) {
494
+ if(this.isClient && resetForm){
495
+ this.$refs.form.resetFields();
496
+ }
497
+ this.$emit('close', refresh)
498
+ },
499
+ dialogConfirmChooseUser(list) {
500
+ this.form.nextUser = list[0].label
501
+ this.$set(this.form, 'nextUserName', list[0].nickName)
502
+ this.$nextTick(() => {
503
+ this.$refs.form.clearValidate('nextUserName') // 移除校验
504
+ })
505
+ this.chooseUserDialog = false
506
+ },
507
+ clickEdit(){
508
+ this.$emit('clickEditPic', this.detailModel);
509
+ },
510
+ clickSave(){
511
+ if(this.isClient){
512
+ this.$refs["form"].validate(async (valid) => {
513
+ if (valid) {
514
+ this.handleSave();
515
+ }
516
+ });
517
+ }else{
518
+ this.handleSave();
519
+ }
520
+ },
521
+ handleSave(reset){
522
+ this.close(true, reset)
523
+ this.$emit("clickSaveBtn", this.detailModel);
524
+ },
525
+ beforeClose(){
526
+ // this.detailData = {};
527
+ this.close(true)
528
+ }
529
+ }
530
+ }
531
+ </script>
532
+ <style lang="scss" scoped>
533
+ .nextUser {
534
+ position: relative;
535
+ i {
536
+ position: absolute;
537
+ bottom: 4px;
538
+ right: 10px;
539
+ z-index: 1;
540
+ color: #c2d8e6;
541
+ font-size: 20px;
542
+ }
543
+ }
544
+ .list-item {
545
+ padding: 12px;
546
+ border-bottom: 1px solid rgba(0, 0, 0, 0.09);
547
+ }
548
+ .operation {
549
+ padding: 12px;
550
+ border-top: 1px solid rgba(0, 0, 0, 0.09);
551
+ }
552
+ .image-edit-container{
553
+ cursor: pointer;
554
+ float: right;
555
+ width: 36px;
556
+ height: 36px;
557
+ background: #fff;
558
+ border-radius: 5px;
559
+ display: flex;
560
+ justify-content: center;
561
+ align-items: center;
562
+ .image-edit{
563
+ font-size: 32px;
564
+ }
565
+ }
566
+
567
+ </style>