w-web-perm 1.0.12 → 1.0.13

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 (68) hide show
  1. package/.vscode/launch.json +0 -1
  2. package/README.md +0 -1
  3. package/dist/css/app.f22995d1.css +1 -0
  4. package/dist/index.tmp +1 -1
  5. package/dist/js/app-legacy.82274c39.js +2 -0
  6. package/dist/js/app-legacy.82274c39.js.map +1 -0
  7. package/dist/js/app.82274c39.js +2 -0
  8. package/dist/js/app.82274c39.js.map +1 -0
  9. package/dist/js/chunk-vendors-legacy.d89048a8.js +13 -0
  10. package/dist/js/chunk-vendors-legacy.d89048a8.js.map +1 -0
  11. package/dist/js/chunk-vendors.d89048a8.js +13 -0
  12. package/dist/js/chunk-vendors.d89048a8.js.map +1 -0
  13. package/dist/w-web-perm.umd.js +2 -2
  14. package/dist/w-web-perm.umd.js.map +1 -1
  15. package/docs/WWebPerm.html +2 -2
  16. package/docs/WWebPerm.mjs.html +212 -64
  17. package/docs/index.html +1 -1
  18. package/g.backupDb.mjs +1 -1
  19. package/g.initialData.mjs +211 -111
  20. package/g.initialTestData.mjs +2 -1
  21. package/g.mjs +0 -0
  22. package/g.provideGrups.mjs +87 -0
  23. package/g.providePemis.mjs +43 -0
  24. package/g.provideTargets.mjs +20 -13
  25. package/g.provideUsers.mjs +45 -13
  26. package/package.json +8 -8
  27. package/script.txt +5 -5
  28. package/server/WWebPerm.mjs +211 -63
  29. package/server/provideGrups.mjs +64 -0
  30. package/server/{provideRuleGroups.mjs → providePemis.mjs} +14 -15
  31. package/server/provideTargets.mjs +8 -5
  32. package/server/provideUsers.mjs +9 -9
  33. package/src/App.vue +16 -3
  34. package/src/components/Layout.vue +13 -5
  35. package/src/components/LayoutContent.vue +31 -16
  36. package/src/components/LayoutContentGrups.vue +793 -0
  37. package/src/components/LayoutContentPemis.vue +793 -0
  38. package/src/components/LayoutContentTargets.vue +481 -307
  39. package/src/components/LayoutContentUsers.vue +796 -291
  40. package/src/components/VeCgrups.vue +926 -0
  41. package/src/components/VeCpemis.vue +926 -0
  42. package/src/components/VeCrules.vue +820 -0
  43. package/src/main.js +2 -2
  44. package/src/perm.mjs +5 -5
  45. package/src/plugins/mShare.mjs +444 -153
  46. package/src/plugins/mUI.mjs +37 -19
  47. package/src/schema/gi.mjs +1 -1
  48. package/src/schema/index.mjs +4 -2
  49. package/src/schema/tables/grups.mjs +154 -0
  50. package/src/schema/tables/{ruleGroups.mjs → pemis.mjs} +27 -16
  51. package/src/schema/tables/targets.mjs +49 -16
  52. package/src/schema/tables/users.mjs +55 -27
  53. package/src/store/mutations.mjs +375 -150
  54. package/srv.mjs +2 -2
  55. package/tableTags-web-perm.json +1 -1
  56. package/dist/css/app.f6c50bec.css +0 -1
  57. package/dist/js/app-legacy.767522f1.js +0 -2
  58. package/dist/js/app-legacy.767522f1.js.map +0 -1
  59. package/dist/js/app.767522f1.js +0 -2
  60. package/dist/js/app.767522f1.js.map +0 -1
  61. package/dist/js/chunk-vendors-legacy.b0d63e17.js +0 -13
  62. package/dist/js/chunk-vendors-legacy.b0d63e17.js.map +0 -1
  63. package/dist/js/chunk-vendors.b0d63e17.js +0 -13
  64. package/dist/js/chunk-vendors.b0d63e17.js.map +0 -1
  65. package/g.provideRuleGroups.mjs +0 -56
  66. package/src/components/LayoutContentGroups.vue +0 -671
  67. package/src/components/VeUser.vue +0 -446
  68. package/src/components/ruleGroup.vue +0 -645
@@ -0,0 +1,793 @@
1
+ <template>
2
+ <div
3
+ style="height:100%;"
4
+ v-domresize
5
+ @domresize="resizePanel"
6
+ :changePemis="changePemis"
7
+ >
8
+
9
+ <div
10
+ style="border-bottom:1px solid #ddd; background:#fff;"
11
+ v-domresize
12
+ @domresize="resizeHead"
13
+ >
14
+
15
+ <!-- 標題區 -->
16
+ <div style="padding:10px 10px 10px 20px;">
17
+ <div :style="`display:flex; align-items:center; padding:${drawer?'5px':'5px 5px 5px 20px'};`">
18
+
19
+ <WIcon
20
+ :icon="mdiStackOverflow"
21
+ :color="'#000'"
22
+ :size="26"
23
+ ></WIcon>
24
+
25
+ <div style="padding-left:10px; font-size:1.4rem; color:#000;">
26
+ {{$t('managementPemis')}}
27
+ </div>
28
+
29
+ </div>
30
+ </div>
31
+
32
+ <!-- 功能區 -->
33
+ <div style="padding:5px; border-top:1px solid #ddd; display:flex; align-items:center;">
34
+
35
+ <template>
36
+
37
+ <WButtonCircle
38
+ :paddingStyle="{v:6,h:6}"
39
+ :tooltip="$t('pemiAdd')"
40
+ :icon="mdiPlus"
41
+ :backgroundColor="'#fff'"
42
+ :backgroundColorHover="'#f2f2f2'"
43
+ _textColor="'#eee'"
44
+ _textColorHover="'#fff'"
45
+ :iconColor="'#444'"
46
+ :iconColorHover="'#222'"
47
+ :shadow="false"
48
+ @click="addItem"
49
+ ></WButtonCircle>
50
+
51
+ <div style="padding-left:6px;"></div>
52
+
53
+ </template>
54
+
55
+ <template v-if="hasItemCheckOne">
56
+
57
+ <WButtonCircle
58
+ :paddingStyle="{v:6,h:6}"
59
+ :tooltip="$t('pemiCopy')"
60
+ :icon="mdiContentCopy"
61
+ :backgroundColor="'#fff'"
62
+ :backgroundColorHover="'#f2f2f2'"
63
+ _textColor="'#eee'"
64
+ _textColorHover="'#fff'"
65
+ :iconColor="'#444'"
66
+ :iconColorHover="'#222'"
67
+ :shadow="false"
68
+ @click="copyItem"
69
+ ></WButtonCircle>
70
+
71
+ <div style="padding-left:6px;"></div>
72
+
73
+ </template>
74
+
75
+ <template v-if="hasItemsCheck">
76
+
77
+ <WButtonCircle
78
+ :paddingStyle="{v:6,h:6}"
79
+ :tooltip="$t('pemiDeleteChecks')"
80
+ :icon="mdiTrashCanOutline"
81
+ :backgroundColor="'#fff'"
82
+ :backgroundColorHover="'#f2f2f2'"
83
+ _textColor="'#eee'"
84
+ _textColorHover="'#fff'"
85
+ :iconColor="'#444'"
86
+ :iconColorHover="'#222'"
87
+ :shadow="false"
88
+ @click="deleteItemsCheck"
89
+ ></WButtonCircle>
90
+
91
+ <div style="padding-left:6px;"></div>
92
+
93
+ </template>
94
+
95
+ <template v-if="isModified">
96
+
97
+ <WButtonCircle
98
+ :paddingStyle="{v:6,h:6}"
99
+ :tooltip="$t('saveChanges')"
100
+ :icon="mdiCloudUploadOutline"
101
+ :backgroundColor="'rgba(255,0,50,0.7)'"
102
+ :backgroundColorHover="'rgba(255,0,50,0.8)'"
103
+ :textColor="'#eee'"
104
+ :textColorHover="'#fff'"
105
+ :iconColor="'#eee'"
106
+ :iconColorHover="'#fff'"
107
+ :shadow="false"
108
+ @click="savePemis"
109
+ ></WButtonCircle>
110
+
111
+ <div style="padding-left:6px;"></div>
112
+
113
+ </template>
114
+
115
+ </div>
116
+
117
+ </div>
118
+
119
+ <template
120
+ v-if="!firstLoading"
121
+ >
122
+
123
+ <template v-if="items">
124
+ <WAggridVueDyn
125
+ ref="rftable"
126
+ :style="`width:100%;`"
127
+ :height="contentHeight"
128
+ :opt="opt"
129
+ >
130
+ </WAggridVueDyn>
131
+ </template>
132
+
133
+ </template>
134
+
135
+ <div style="padding:10px 15px; font-size:0.8rem;" v-else>
136
+ {{$t('waitingData')}}
137
+ </div>
138
+
139
+ </div>
140
+ </template>
141
+
142
+ <script>
143
+ import { mdiStackOverflow, mdiVectorPolylinePlus, mdiCheckboxMarkedCircle, mdiCloudUploadOutline, mdiTrashCanOutline, mdiPlus, mdiPencilOutline, mdiContentCopy } from '@mdi/js/mdi.js'
144
+ import get from 'lodash-es/get.js'
145
+ import set from 'lodash-es/set.js'
146
+ import each from 'lodash-es/each.js'
147
+ import size from 'lodash-es/size.js'
148
+ import filter from 'lodash-es/filter.js'
149
+ import sortBy from 'lodash-es/sortBy.js'
150
+ import cloneDeep from 'lodash-es/cloneDeep.js'
151
+ import haskey from 'wsemi/src/haskey.mjs'
152
+ import isestr from 'wsemi/src/isestr.mjs'
153
+ import iseobj from 'wsemi/src/iseobj.mjs'
154
+ import cstr from 'wsemi/src/cstr.mjs'
155
+ import WIcon from 'w-component-vue/src/components/WIcon.vue'
156
+ import WButtonCircle from 'w-component-vue/src/components/WButtonCircle.vue'
157
+ import WAggridVueDyn from 'w-component-vue/src/components/WAggridVueDyn.vue'
158
+
159
+
160
+ export default {
161
+ components: {
162
+ WIcon,
163
+ WButtonCircle,
164
+ WAggridVueDyn,
165
+ },
166
+ props: {
167
+ drawer: {
168
+ type: Boolean,
169
+ default: false,
170
+ },
171
+ },
172
+ data: function() {
173
+ return {
174
+ mdiStackOverflow,
175
+ mdiVectorPolylinePlus,
176
+ mdiCheckboxMarkedCircle,
177
+ mdiCloudUploadOutline,
178
+ mdiTrashCanOutline,
179
+ mdiPlus,
180
+ mdiPencilOutline,
181
+ mdiContentCopy,
182
+
183
+ panelWidth: 100,
184
+ panelHeight: 100,
185
+ headHeight: 100,
186
+
187
+ firstLoading: true,
188
+ isModified: false,
189
+
190
+ items: [],
191
+ itemsCheck: [],
192
+ opt: null,
193
+
194
+ }
195
+ },
196
+ mounted: function() {
197
+ // console.log('mounted')
198
+
199
+ let vo = this
200
+
201
+ //註冊至$dg供使用
202
+ vo.$dg.showVeCrulesById = vo.showVeCrulesById
203
+
204
+ },
205
+ computed: {
206
+
207
+ targets: function() {
208
+ let rs = get(this, `$store.state.targets`)
209
+ rs = sortBy(rs, 'order')
210
+ return rs
211
+ },
212
+
213
+ pemis: function() {
214
+ let rs = get(this, `$store.state.pemis`)
215
+ rs = sortBy(rs, 'order')
216
+ return rs
217
+ },
218
+
219
+ grups: function() {
220
+ let rs = get(this, `$store.state.grups`)
221
+ rs = sortBy(rs, 'order')
222
+ return rs
223
+ },
224
+
225
+ users: function() {
226
+ let rs = get(this, `$store.state.users`)
227
+ rs = sortBy(rs, 'order')
228
+ return rs
229
+ },
230
+
231
+ changePemis: function() {
232
+ // console.log('computed changePemis')
233
+
234
+ let vo = this
235
+
236
+ //check
237
+ if (size(vo.pemis) === 0) {
238
+ return ''
239
+ }
240
+
241
+ //cloneDeep
242
+ let items = cloneDeep(vo.pemis)
243
+
244
+ //save
245
+ vo.items = items
246
+
247
+ //genOpt
248
+ vo.genOpt()
249
+
250
+ //firstLoading
251
+ vo.firstLoading = false
252
+
253
+ return ''
254
+ },
255
+
256
+ contentHeight: function() {
257
+ let vo = this
258
+
259
+ //h
260
+ let h = vo.panelHeight - vo.headHeight
261
+ h = Math.max(h, 0)
262
+
263
+ return h
264
+ },
265
+
266
+ hasItemsCheck: function() {
267
+ let vo = this
268
+
269
+ //h
270
+ let b = size(vo.itemsCheck) > 0
271
+
272
+ return b
273
+ },
274
+
275
+ hasItemCheckOne: function() {
276
+ let vo = this
277
+
278
+ //h
279
+ let b = size(vo.itemsCheck) === 1
280
+
281
+ return b
282
+ },
283
+
284
+ errItemsByName: function() {
285
+ let vo = this
286
+
287
+ //rows
288
+ let rows = get(vo, 'opt.rows', [])
289
+
290
+ //kpErr
291
+ let kpErr = {}
292
+ let kpName = {}
293
+ each(rows, (v, k) => {
294
+
295
+ //name
296
+ let name = get(v, 'name', '')
297
+
298
+ //check
299
+ if (!isestr(name)) {
300
+
301
+ //kpErr
302
+ kpErr[name] = vo.$t(`pemiNameEmpty`)
303
+
304
+ return true //跳出換下一個
305
+ }
306
+
307
+ //check
308
+ if (haskey(kpName, name)) {
309
+
310
+ //kpErr
311
+ kpErr[name] = vo.$t(`pemiNameDuplicate`)
312
+
313
+ return true //跳出換下一個
314
+ }
315
+
316
+ //kpName
317
+ kpName[name] = true
318
+
319
+ })
320
+
321
+ return kpErr
322
+ },
323
+
324
+ isError: function() {
325
+ let vo = this
326
+
327
+ let c = ''
328
+ let b = false
329
+ b = iseobj(vo.errItemsByName)
330
+ if (b) {
331
+ c = vo.$t('errInNames')
332
+ }
333
+
334
+ return c
335
+ },
336
+
337
+ },
338
+ methods: {
339
+
340
+ resizePanel: function(msg) {
341
+ // console.log('methods resizePanel', msg)
342
+
343
+ let vo = this
344
+
345
+ //panelWidth, panelHeight
346
+ vo.panelWidth = msg.snew.offsetWidth
347
+ vo.panelHeight = msg.snew.offsetHeight
348
+
349
+ },
350
+
351
+ resizeHead: function(msg) {
352
+ // console.log('methods resizeHead', msg)
353
+
354
+ let vo = this
355
+
356
+ //headHeight
357
+ vo.headHeight = msg.snew.offsetHeight
358
+
359
+ },
360
+
361
+ genOpt: function() {
362
+ // console.log('methods genOpt')
363
+
364
+ let vo = this
365
+
366
+ //default
367
+ vo.itemsCheck = []
368
+
369
+ //opt
370
+ let opt = null
371
+ if (size(vo.items) > 0) {
372
+
373
+ //ks
374
+ let ks = [
375
+ 'id',
376
+ 'name',
377
+ 'description',
378
+ 'from',
379
+ 'crules',
380
+ 'userId',
381
+ 'timeCreate',
382
+ 'userIdUpdate',
383
+ 'timeUpdate',
384
+ ]
385
+ // console.log('ks', ks)
386
+
387
+ //kpHead
388
+ let kpHead = {
389
+ 'id': vo.$t('id'),
390
+ 'name': vo.$t('name'),
391
+ 'description': vo.$t('description'),
392
+ 'from': vo.$t('from'),
393
+ 'crules': vo.$t('pemiCrules'),
394
+ 'userId': vo.$t('userId'),
395
+ 'timeCreate': vo.$t('timeCreate'),
396
+ 'userIdUpdate': vo.$t('userIdUpdate'),
397
+ 'timeUpdate': vo.$t('timeUpdate'),
398
+ }
399
+
400
+ //opt
401
+ opt = {
402
+ language: vo.$t('aggridLanguage'),
403
+ rows: vo.items,
404
+ keys: ks,
405
+ kpHead,
406
+ // autoFitColumn: true,
407
+ defHeadFilter: true,
408
+ defCellAlignH: 'left',
409
+ kpHeadHide: {
410
+ 'id': true,
411
+ },
412
+ kpHeadFixLeft: {
413
+ 'name': true,
414
+ },
415
+ defHeadMinWidth: 150,
416
+ kpHeadWidth: {
417
+ 'name': 300,
418
+ 'crules': 100,
419
+ 'timeCreate': 220,
420
+ 'timeUpdate': 220,
421
+ },
422
+ kpHeadFilterType: {
423
+ 'id': 'text',
424
+ 'name': 'text',
425
+ 'description': 'text',
426
+ 'from': 'text',
427
+ 'crules': 'text',
428
+ 'userId': 'text',
429
+ 'timeCreate': 'text',
430
+ 'userIdUpdate': 'text',
431
+ 'timeUpdate': 'text',
432
+ },
433
+ kpCellEditable: {
434
+ 'name': true,
435
+ 'description': true,
436
+ 'from': true,
437
+ },
438
+ kpRowDrag: {
439
+ 'name': true,
440
+ },
441
+ kpHeadCheckBox: {
442
+ 'name': true,
443
+ },
444
+ kpHeadFilter: {
445
+ 'crules': false,
446
+ },
447
+ kpHeadSort: {
448
+ 'crules': false,
449
+ },
450
+ kpHeadFocusHighlight: { //雖然效果不完全, 但因按鈕與cell有padding可被點擊, 故還是需要開啟
451
+ 'crules': false,
452
+ },
453
+ kpCellRender: {
454
+ 'name': (v) => {
455
+ // console.log('kpCellRender name', v)
456
+
457
+ //err
458
+ let err = get(vo.errItemsByName, v, '')
459
+ // console.log(v, err)
460
+
461
+ //check
462
+ if (isestr(err)) {
463
+ v = `
464
+ <span title="${err}">
465
+ <span style="color:#F57C00;">${cstr(v)}</span>
466
+ <img style="vertical-align:sub; width:16px; height:16px;" src="${vo.$ui.getIcon('warning')}" />
467
+ </span>
468
+ `
469
+ }
470
+
471
+ return v
472
+ },
473
+ 'crules': (v, k, r) => {
474
+ // console.log('kpCellRender crules', v, k, r)
475
+
476
+ //id
477
+ let id = get(r, 'id', '')
478
+ // console.log('id', id, k, r)
479
+
480
+ //因kpHeadFocusHighlight設定false時, 仍會於點擊其他可focus的cell, 再點回時依然出現highlight的focus邊框, 故改使用stopPropagation強制吃掉點擊訊息
481
+ //因stopPropagation只吃掉訊息, 原本focus會處於原本可focus的cell, 再重複點時會於前個focus的cell出現highlight邊框, 故再多使用preventDefault阻止瀏覽器預設行為, 此等同於return false
482
+ let t = `
483
+ <div onclick="event.stopPropagation();event.preventDefault();" onmousedown="event.stopPropagation();event.preventDefault();">
484
+ <button style="width:100%;" onclick="$vo.$dg.showVeCrulesById('${id}')">${vo.$t('pemiEditCrulesSimple')}</button>
485
+ </div>
486
+ `
487
+
488
+ return t
489
+ },
490
+ },
491
+ rowsChange: (rs) => {
492
+ // console.log('rowsChange', rs)
493
+ // console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
494
+
495
+ //isModified
496
+ vo.isModified = true
497
+
498
+ },
499
+ rowChecked: (rs) => {
500
+ // console.log('rowChecked', rs)
501
+ // console.log('rowChecked cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
502
+
503
+ //save itemsCheck
504
+ vo.itemsCheck = cloneDeep(rs)
505
+
506
+ },
507
+ }
508
+ // console.log('opt', opt)
509
+
510
+ }
511
+
512
+ //save
513
+ vo.opt = opt
514
+
515
+ },
516
+
517
+ refresh: function() {
518
+ let vo = this
519
+
520
+ //cmp
521
+ let cmp = get(vo, '$refs.rftable.$refs.$self')
522
+ // console.log('cmp', cmp)
523
+
524
+ //refresh, 因set不會觸發kpCellRender, 故須另外調用組件函數refresh, 進而觸發kpCellRender, 使能更新數據
525
+ cmp.refresh()
526
+
527
+ },
528
+
529
+ addItem: function() {
530
+ // console.log('method addItem')
531
+
532
+ let vo = this
533
+
534
+ //cloneDeep
535
+ let rows = get(vo, 'opt.rows', [])
536
+
537
+ //cloneDeep
538
+ rows = cloneDeep(rows)
539
+
540
+ //r
541
+ let r = vo.$ds.pemis.funNew()
542
+ r.name = vo.$s.getNameNew(rows, 'name', '', vo.$t('pemiAddNameNew'))
543
+ r.userId = `{${vo.$t('pemiAddIdNew')}}`
544
+ r.timeCreate = `{${vo.$t('pemiAddIdNew')}}`
545
+ r.userIdUpdate = `{${vo.$t('pemiAddIdNew')}}`
546
+ r.timeUpdate = `{${vo.$t('pemiAddIdNew')}}`
547
+ // console.log('r', r)
548
+
549
+ //添加至最首
550
+ rows = [
551
+ r,
552
+ ...rows,
553
+ ]
554
+
555
+ //save
556
+ vo.opt.rows = rows
557
+ // console.log('cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
558
+
559
+ //isModified
560
+ vo.isModified = true
561
+
562
+ },
563
+
564
+ copyItem: function() {
565
+ // console.log('method copyItem')
566
+
567
+ let vo = this
568
+
569
+ //check
570
+ if (size(vo.itemsCheck) !== 1) {
571
+ console.log(`size(vo.itemsCheck) !== 1`, vo.itemsCheck)
572
+ vo.$alert(`${vo.$t('anUnexpectedErrorOccurred')}`, { type: 'error' })
573
+ return
574
+ }
575
+
576
+ //cloneDeep
577
+ let rows = get(vo, 'opt.rows', [])
578
+
579
+ //cloneDeep
580
+ rows = cloneDeep(rows)
581
+
582
+ //find
583
+ let tar = vo.itemsCheck[0]
584
+ let tarId = get(tar, 'data.id', '')
585
+ let row = null
586
+ each(rows, (v) => {
587
+ let id = get(v, 'id', '')
588
+ if (id === tarId) {
589
+ row = v
590
+ return false //跳出
591
+ }
592
+ })
593
+ // console.log('tar', tar)
594
+ // console.log('row', row)
595
+
596
+ //check
597
+ if (!iseobj(row)) {
598
+ console.log(`!iseobj(row)`, row)
599
+ vo.$alert(`${vo.$t('anUnexpectedErrorOccurred')}`, { type: 'error' })
600
+ return
601
+ }
602
+
603
+ //r
604
+ let r = cloneDeep(row)
605
+ let nameOld = r.name
606
+ let _r = vo.$ds.pemis.funNew()
607
+ r.id = _r.id //使用新建方式預先產生id避免重複
608
+ r.name = vo.$s.getNameNew(rows, 'name', nameOld, vo.$t('pemiCopyNameNew'))
609
+ r.userId = `{${vo.$t('pemiAddIdNew')}}`
610
+ r.timeCreate = `{${vo.$t('pemiAddIdNew')}}`
611
+ r.userIdUpdate = `{${vo.$t('pemiAddIdNew')}}`
612
+ r.timeUpdate = `{${vo.$t('pemiAddIdNew')}}`
613
+ // console.log('r', r)
614
+
615
+ //添加至最首
616
+ rows = [
617
+ r,
618
+ ...rows,
619
+ ]
620
+
621
+ //save
622
+ vo.opt.rows = rows
623
+ // console.log('cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
624
+
625
+ //isModified
626
+ vo.isModified = true
627
+
628
+ },
629
+
630
+ deleteItemsCheck: function() {
631
+ // console.log('method deleteItemsCheck')
632
+
633
+ let vo = this
634
+
635
+ //check
636
+ if (size(vo.itemsCheck) === 0) {
637
+ console.log(`size(vo.itemsCheck) === 0`, vo.itemsCheck)
638
+ vo.$alert(`${vo.$t('anUnexpectedErrorOccurred')}`, { type: 'error' })
639
+ return
640
+ }
641
+
642
+ //cloneDeep
643
+ let rows = get(vo, 'opt.rows', [])
644
+
645
+ //cloneDeep
646
+ rows = cloneDeep(rows)
647
+
648
+ //filter
649
+ each(vo.itemsCheck, (v) => {
650
+ // console.log('v', v)
651
+ let id = get(v, 'data.id', '')
652
+ if (!isestr(id)) {
653
+ console.log(`invalid id`)
654
+ return true //跳出換下一個
655
+ }
656
+ rows = filter(rows, (vv) => {
657
+ return vv.id !== id
658
+ })
659
+ })
660
+
661
+ //clear
662
+ vo.itemsCheck = []
663
+
664
+ //save
665
+ vo.opt.rows = rows
666
+ // console.log('deleteItemsCheck cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
667
+
668
+ //isModified
669
+ vo.isModified = true
670
+
671
+ },
672
+
673
+ showVeCrulesById: function(id) {
674
+ // console.log('method showVeCrulesById', id)
675
+
676
+ let vo = this
677
+
678
+ //check
679
+ if (!isestr(id)) {
680
+ vo.$alert(`${vo.$t('pemiEditCrulesNoId')}`, { type: 'error' })
681
+ return
682
+ }
683
+
684
+ //rows
685
+ let rows = get(vo, 'opt.rows', [])
686
+
687
+ //find
688
+ let r = null
689
+ let kr = null
690
+ each(rows, (v, k) => {
691
+ if (get(v, 'id', '') === id) {
692
+ r = v
693
+ kr = k
694
+ return false //跳出
695
+ }
696
+ })
697
+
698
+ //check
699
+ if (!iseobj(r)) {
700
+ vo.$alert(`${vo.$t('pemiEditCrulesNoPemi')}`, { type: 'error' })
701
+ return
702
+ }
703
+
704
+ //showVeCrules
705
+ vo.$dg.showVeCrules(r)
706
+ .then((crules) => {
707
+ // console.log('crules', crules)
708
+
709
+ //set
710
+ set(vo, `opt.rows[${kr}].crules`, crules)
711
+ // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
712
+
713
+ //refresh
714
+ vo.refresh()
715
+
716
+ //isModified
717
+ vo.isModified = true
718
+
719
+ })
720
+ .catch(() => {})
721
+
722
+ },
723
+
724
+ savePemis: function() {
725
+ // console.log('method savePemis')
726
+
727
+ let vo = this
728
+
729
+ async function core() {
730
+ let errTemp = null
731
+
732
+ //show loading
733
+ vo.$ui.updateLoading(true)
734
+
735
+ //check
736
+ if (isestr(vo.isError)) {
737
+ vo.$alert(`${vo.isError}`, { type: 'error' })
738
+ return
739
+ }
740
+
741
+ //rows
742
+ let rows = get(vo, 'opt.rows', [])
743
+
744
+ //check
745
+ if (size(rows) === 0) {
746
+ vo.$alert(`${vo.$t('pemiAddEmpty')}`, { type: 'error' })
747
+ return
748
+ }
749
+
750
+ //updatePemis
751
+ await vo.$fapi.updatePemis(rows)
752
+ .catch((err) => {
753
+ errTemp = err
754
+ })
755
+
756
+ //check
757
+ if (errTemp !== null) {
758
+ vo.$alert(`${vo.$t('pemiSavePemisFail')}: ${errTemp}`, { type: 'error' })
759
+ return
760
+ }
761
+
762
+ //isModified
763
+ vo.isModified = false
764
+
765
+ //alert
766
+ vo.$alert(vo.$t('pemiSavePemisSuccess'))
767
+
768
+ }
769
+
770
+ //core
771
+ core()
772
+ // .then((res) => {
773
+ // console.log('then', res)
774
+ // })
775
+ .catch((err) => {
776
+ console.log('catch', err)
777
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' })
778
+ })
779
+ .finally(() => {
780
+
781
+ //hide loading
782
+ vo.$ui.updateLoading(false)
783
+
784
+ })
785
+
786
+ },
787
+
788
+ }
789
+ }
790
+ </script>
791
+
792
+ <style scoped>
793
+ </style>