w-web-perm 1.0.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 (101) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.js +55 -0
  4. package/.github/workflows/ci-test.yml +24 -0
  5. package/.jsdoc +25 -0
  6. package/.vscode/launch.json +21 -0
  7. package/LICENSE +21 -0
  8. package/README.md +24 -0
  9. package/SECURITY.md +5 -0
  10. package/babel.config.js +15 -0
  11. package/dist/css/app.79b4b59b.css +1 -0
  12. package/dist/css/chunk-vendors.65775501.css +5 -0
  13. package/dist/index.tmp +1 -0
  14. package/dist/js/app-legacy.954e168c.js +2 -0
  15. package/dist/js/app-legacy.954e168c.js.map +1 -0
  16. package/dist/js/app.954e168c.js +2 -0
  17. package/dist/js/app.954e168c.js.map +1 -0
  18. package/dist/js/chunk-vendors-legacy.f5f1a231.js +13 -0
  19. package/dist/js/chunk-vendors-legacy.f5f1a231.js.map +1 -0
  20. package/dist/js/chunk-vendors.f5f1a231.js +13 -0
  21. package/dist/js/chunk-vendors.f5f1a231.js.map +1 -0
  22. package/dist/w-web-perm.umd.js +7 -0
  23. package/dist/w-web-perm.umd.js.map +1 -0
  24. package/docs/WWebPerm.html +826 -0
  25. package/docs/WWebPerm.mjs.html +558 -0
  26. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  27. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  28. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  29. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  30. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  31. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  32. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  33. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  36. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  37. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  40. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  41. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  42. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  43. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  44. package/docs/index.html +84 -0
  45. package/docs/scripts/collapse.js +39 -0
  46. package/docs/scripts/commonNav.js +28 -0
  47. package/docs/scripts/linenumber.js +25 -0
  48. package/docs/scripts/nav.js +12 -0
  49. package/docs/scripts/polyfill.js +4 -0
  50. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  51. package/docs/scripts/prettify/lang-css.js +2 -0
  52. package/docs/scripts/prettify/prettify.js +28 -0
  53. package/docs/scripts/search.js +99 -0
  54. package/docs/styles/jsdoc.css +776 -0
  55. package/docs/styles/prettify.css +80 -0
  56. package/g.getSettings.mjs +17 -0
  57. package/g.mDb.mjs +10 -0
  58. package/g.mInitialTestData.mjs +20 -0
  59. package/g.mOrm.mjs +24 -0
  60. package/package.json +75 -0
  61. package/public/index.html +23 -0
  62. package/server/WWebPerm.mjs +486 -0
  63. package/src/App.vue +153 -0
  64. package/src/components/Common/CheckYes.vue +85 -0
  65. package/src/components/Common/CheckYesNo.vue +91 -0
  66. package/src/components/Common/LabelItem.vue +106 -0
  67. package/src/components/Common/LoadingWinBar.vue +87 -0
  68. package/src/components/Layout.vue +152 -0
  69. package/src/components/LayoutContent.vue +246 -0
  70. package/src/components/LayoutContentGroups.vue +664 -0
  71. package/src/components/LayoutContentTargets.vue +538 -0
  72. package/src/components/LayoutContentUsers.vue +493 -0
  73. package/src/components/LayoutState.vue +91 -0
  74. package/src/components/VeUser.vue +453 -0
  75. package/src/components/ruleGroup.vue +667 -0
  76. package/src/main.js +103 -0
  77. package/src/perm.mjs +61 -0
  78. package/src/plugins/mDataSelectorSchema.mjs +30 -0
  79. package/src/plugins/mDataSupport.mjs +66 -0
  80. package/src/plugins/mShare.mjs +366 -0
  81. package/src/plugins/mUI.mjs +229 -0
  82. package/src/plugins/mVuetify.mjs +12 -0
  83. package/src/schema/gi.mjs +8 -0
  84. package/src/schema/index.mjs +20 -0
  85. package/src/schema/tables/ruleGroups.mjs +100 -0
  86. package/src/schema/tables/targets.mjs +100 -0
  87. package/src/schema/tables/users.mjs +125 -0
  88. package/src/store/actions.mjs +1 -0
  89. package/src/store/getters.mjs +1 -0
  90. package/src/store/index.mjs +25 -0
  91. package/src/store/mutations.mjs +201 -0
  92. package/src/store/types.mjs +15 -0
  93. package/srv.mjs +52 -0
  94. package/tableTags-web-perm.json +1 -0
  95. package/test/all.test.mjs +10 -0
  96. package/toolg/addVersion.mjs +4 -0
  97. package/toolg/cleanFolder.mjs +4 -0
  98. package/toolg/gDistRollup.mjs +36 -0
  99. package/toolg/genEntry.mjs +23 -0
  100. package/toolg/modifyReadme.mjs +4 -0
  101. package/vue.config.js +15 -0
@@ -0,0 +1,664 @@
1
+ <template>
2
+ <div
3
+ style="height:100%;"
4
+ v-domresize
5
+ @domresize="resizePanel"
6
+ :changeGroups="changeGroups"
7
+ >
8
+
9
+ <div
10
+ style="border-bottom:1px solid #ddd;"
11
+ v-domresize
12
+ @domresize="resizeHead"
13
+ >
14
+
15
+ <!-- 標題區 -->
16
+ <div style="padding:30px 25px 0px 20px; background:#fff;">
17
+ <div style="padding:5px 15px 5px 5px; display:inline-block; border-bottom:3px solid #FF9100;">
18
+ <div style="display:flex; align-items:center;">
19
+
20
+ <WIcon
21
+ :icon="mdiStackOverflow"
22
+ :color="'#FF9800'"
23
+ ></WIcon>
24
+
25
+ <div style="padding-left:10px; font-size:1.3rem; color:#d3912c;">
26
+ 管理權限群組
27
+ </div>
28
+
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <!-- 編輯設定區 -->
34
+ <div style="background:#fff;">
35
+
36
+ <div style="padding:20px 20px 15px 20px; background:#fff;">
37
+
38
+ <div style="display:flex;">
39
+ <WSwitch
40
+ :text="'是否編輯'"
41
+ :checkedSwitchCircleColor="'#D81B60'"
42
+ :checkedSwitchCircleColorHover="'#f26'"
43
+ :checkedSwitchBarColor="'#F8BBD0'"
44
+ :checkedSwitchBarColorHover="'#F8BBD0'"
45
+ v-model="isOperatable"
46
+ ></WSwitch>
47
+ </div>
48
+
49
+ <div style="padding-top:5px; font-size:0.8rem; _color:#f26;" v-if="isOperatable">
50
+ <div style="padding:3px 0px;">
51
+ 1. 請依照系統管理需求創建適合各類使用者適合的權限群組。
52
+ </div>
53
+ <div style="padding:3px 0px;">
54
+ 2. 開啟編輯時可拖曳權限群組變更其相對順序。
55
+ </div>
56
+ <div style="padding:3px 0px;">
57
+ 3. 此區域變更時將自動儲存。
58
+ </div>
59
+ </div>
60
+
61
+ </div>
62
+
63
+ <div
64
+ style="padding:10px 10px 12px 10px; border-top:1px solid #F48FB1; border-bottom:1px solid #F48FB1; background:#FCE4EC; display:flex; align-items:center; justify-content:flex-end;"
65
+ v-if="isModified"
66
+ >
67
+
68
+ <WButtonChip
69
+ :paddingStyle="{v:0,h:11}"
70
+ :text="'儲存變更'"
71
+ :icon="mdiCloudUploadOutline"
72
+ :backgroundColor="'rgba(255,0,50,0.7)'"
73
+ :backgroundColorHover="'rgba(255,0,50,0.8)'"
74
+ :textColor="'#eee'"
75
+ :textColorHover="'#fff'"
76
+ :iconColor="'#eee'"
77
+ :iconColorHover="'#fff'"
78
+ @click="saveGroups"
79
+ ></WButtonChip>
80
+
81
+ </div>
82
+
83
+ </div>
84
+
85
+ </div>
86
+
87
+ <div :style="`padding:${spacePading}px;`" v-if="!firstLoading">
88
+
89
+ <div style="background:#fff; box-shadow:0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);">
90
+
91
+ <div
92
+ v-domresize
93
+ @domresize="resizeGroupInfor"
94
+ >
95
+
96
+ <!-- 權限群組區(含新增) -->
97
+ <div style="padding:10px 20px; border-bottom:3px solid #ddd;">
98
+
99
+ <WGroupTags
100
+ :keyText="'name'"
101
+ :draggable="isOperatable"
102
+ :editableClose="isOperatable"
103
+ :editableInput="isOperatable"
104
+ :addButtonText="'新增群組'"
105
+ :addButtonTooltip="'新增權限群組'"
106
+ :addButtonTextColor="'#eee'"
107
+ :addButtonTextColorHover="'#fff'"
108
+ :addButtonIconColor="'#eee'"
109
+ :addButtonIconColorHover="'#fff'"
110
+ :addButtonBackgroundColor="'rgba(255,0,50,0.7)'"
111
+ :addButtonBackgroundColorHover="'rgba(255,0,50,0.8)'"
112
+ :value="groupsTrans"
113
+ @input="dragGroupsOrder"
114
+ @click="clickGroup"
115
+ @click-add="clickAddGroup"
116
+ @click-close="clickRemoveGroup"
117
+ ></WGroupTags>
118
+
119
+ </div>
120
+
121
+ </div>
122
+
123
+ <ruleGroup
124
+ :height="ruleGroupHeight"
125
+ :group="pickGroup"
126
+ :editable="isOperatable"
127
+ @update="modifyGroup"
128
+ v-if="pickGroup"
129
+ ></ruleGroup>
130
+
131
+ <div
132
+ style="padding:20px; _color:#666; font-size:0.85rem;"
133
+ v-else
134
+ >
135
+ 未選擇權限群組,請點擇上方任一權限群組以顯示管理範圍。
136
+ </div>
137
+
138
+ </div>
139
+
140
+ </div>
141
+
142
+ <div style="padding:10px 15px; font-size:0.8rem;" v-else>
143
+ 載入中...
144
+ </div>
145
+
146
+ </div>
147
+ </template>
148
+
149
+ <script>
150
+ import { mdiStackOverflow, mdiVectorPolylinePlus, mdiCheckboxMarkedCircle, mdiCloudUploadOutline } from '@mdi/js/mdi.js'
151
+ import get from 'lodash/get'
152
+ import each from 'lodash/each'
153
+ import map from 'lodash/map'
154
+ import find from 'lodash/find'
155
+ import size from 'lodash/size'
156
+ import max from 'lodash/max'
157
+ import sortBy from 'lodash/sortBy'
158
+ import isEqual from 'lodash/isEqual'
159
+ import cloneDeep from 'lodash/cloneDeep'
160
+ import genID from 'wsemi/src/genID.mjs'
161
+ import isestr from 'wsemi/src/isestr.mjs'
162
+ import iseobj from 'wsemi/src/iseobj.mjs'
163
+ import waitFun from 'wsemi/src/waitFun.mjs'
164
+ import WIcon from 'w-component-vue/src/components/WIcon.vue'
165
+ import WButtonChip from 'w-component-vue/src/components/WButtonChip.vue'
166
+ import WSwitch from 'w-component-vue/src/components/WSwitch.vue'
167
+ import WGroupTags from 'w-component-vue/src/components/WGroupTags.vue'
168
+ import ruleGroup from './ruleGroup.vue'
169
+
170
+
171
+ export default {
172
+ components: {
173
+ WIcon,
174
+ WButtonChip,
175
+ WSwitch,
176
+ WGroupTags,
177
+ ruleGroup,
178
+ },
179
+ props: {
180
+ },
181
+ data: function() {
182
+ return {
183
+ mdiStackOverflow,
184
+ mdiVectorPolylinePlus,
185
+ mdiCheckboxMarkedCircle,
186
+ mdiCloudUploadOutline,
187
+
188
+ panelWidth: 100,
189
+ panelHeight: 100,
190
+ headHeight: 100,
191
+ groupInforHeight: 100,
192
+
193
+ firstLoading: true,
194
+ isOperatable: false,
195
+ isModified: false,
196
+
197
+ groupsTrans: [],
198
+
199
+ pickGroupId: '',
200
+
201
+ }
202
+ },
203
+ computed: {
204
+
205
+ ruleGroups: function() {
206
+ return get(this, `$store.state.ruleGroups`)
207
+ },
208
+
209
+ groups: function() {
210
+ // console.log('computed groups')
211
+
212
+ let vo = this
213
+
214
+ //rs, 此區程式碼等同於ruleGroups, 若確認後續無需求再移除
215
+ let rs = map(vo.ruleGroups, (v) => {
216
+ // let rules = JSON.parse(v.crules)
217
+ return {
218
+ ...v,
219
+ // rules,
220
+ }
221
+ })
222
+
223
+ //sortBy
224
+ rs = sortBy(rs, 'order')
225
+
226
+ return rs
227
+ },
228
+
229
+ changeGroups: function() {
230
+ // console.log('computed changeGroups')
231
+
232
+ let vo = this
233
+
234
+ //default
235
+ vo.groupsTrans = []
236
+
237
+ //check
238
+ if (size(vo.groups) === 0) { //不能用被修改的groupsTrans, 否則會反覆觸發
239
+ return ''
240
+ }
241
+
242
+ //save
243
+ vo.groupsTrans = cloneDeep(vo.groups)
244
+
245
+ //firstLoading
246
+ vo.firstLoading = false
247
+
248
+ return ''
249
+ },
250
+
251
+ spacePading: function() {
252
+ let vo = this
253
+ if (vo.panelWidth < 400) {
254
+ return 0
255
+ }
256
+ else if (vo.panelWidth < 800) {
257
+ return 10
258
+ }
259
+ return 20
260
+ },
261
+
262
+ ruleGroupHeight: function() {
263
+ let vo = this
264
+
265
+ //h
266
+ let h = vo.panelHeight - vo.headHeight - 2 * vo.spacePading - vo.groupInforHeight
267
+ h = Math.max(h, 0)
268
+
269
+ return h
270
+ },
271
+
272
+ pickGroup: function() {
273
+ // console.log('computed pickGroup')
274
+
275
+ let vo = this
276
+
277
+ //find, 點擊權限按鈕提供權限物件, 刪除後找不到亦可自動清空
278
+ let r = find(vo.groupsTrans, { id: vo.pickGroupId })
279
+
280
+ return r
281
+ },
282
+
283
+ },
284
+ methods: {
285
+
286
+ resizePanel: function(msg) {
287
+ // console.log('methods resizePanel', msg)
288
+
289
+ let vo = this
290
+
291
+ //panelWidth, panelHeight
292
+ vo.panelWidth = msg.snew.offsetWidth
293
+ vo.panelHeight = msg.snew.offsetHeight
294
+
295
+ },
296
+
297
+ resizeHead: function(msg) {
298
+ // console.log('methods resizeHead', msg)
299
+
300
+ let vo = this
301
+
302
+ //headHeight
303
+ vo.headHeight = msg.snew.offsetHeight
304
+
305
+ },
306
+
307
+ resizeGroupInfor: function(msg) {
308
+ // console.log('methods resizeGroupInfor', msg)
309
+
310
+ let vo = this
311
+
312
+ //groupInforHeight
313
+ vo.groupInforHeight = msg.snew.offsetHeight
314
+
315
+ },
316
+
317
+ getDescription: function(g) {
318
+ // console.log('methods getDescription', g)
319
+
320
+ //r
321
+ let r = get(g, 'description', '')
322
+
323
+ //check
324
+ if (!isestr(r)) {
325
+ r = '無說明'
326
+ }
327
+
328
+ return r
329
+ },
330
+
331
+ clickGroup: function(msg) {
332
+ // console.log('methods clickGroup', msg)
333
+
334
+ let vo = this
335
+
336
+ //g
337
+ let g = get(msg, 'item', {})
338
+ // console.log('g', g)
339
+
340
+ //id
341
+ let id = get(g, 'id', '')
342
+
343
+ //save
344
+ vo.pickGroupId = id
345
+
346
+ },
347
+
348
+ clickAddGroup: function() {
349
+ // console.log('methods clickAddGroup')
350
+
351
+ let vo = this
352
+
353
+ async function core() {
354
+ let errTemp = null
355
+
356
+ //show loading
357
+ vo.$ui.updateLoading(true)
358
+
359
+ //orderMax
360
+ let orderMax = null
361
+ orderMax = map(vo.groupsTrans, 'order')
362
+ orderMax = max(orderMax) + 1
363
+
364
+ //g
365
+ let g = {
366
+ id: genID(),
367
+ name: '新權限群組',
368
+ crules: `{ "___all___": { "show": "n", "active": "n" } }`,
369
+ order: orderMax,
370
+ }
371
+
372
+ //save
373
+ await vo.$fapi.ruleGroups.insert(g)
374
+ .catch((err) => {
375
+ errTemp = err
376
+ })
377
+
378
+ //check
379
+ if (errTemp !== null) {
380
+ vo.$alert(`新增權限群組失敗: ${errTemp}`, { type: 'error' })
381
+ }
382
+
383
+ //gn
384
+ let gn = null
385
+ await waitFun(() => {
386
+ gn = find(vo.groupsTrans, { id: g.id })
387
+ let b = iseobj(gn) //確認g.id已存在
388
+ // console.log('waitFun', gn, b)
389
+ return b
390
+ })
391
+ // console.log('gn', gn)
392
+
393
+ //alert
394
+ vo.$alert(`新增權限群組成功`)
395
+
396
+ }
397
+
398
+ //core
399
+ core()
400
+ // .then((res) => {
401
+ // console.log('then', res)
402
+ // })
403
+ .catch((err) => {
404
+ console.log('catch', err)
405
+ vo.$alert(`發生非預期錯誤,請洽管理員`, { type: 'error' })
406
+ })
407
+ .finally(() => {
408
+
409
+ //hide loading
410
+ vo.$ui.updateLoading(false)
411
+
412
+ })
413
+
414
+ },
415
+
416
+ clickRemoveGroup: function(msg) {
417
+ // console.log('methods clickRemoveGroup', msg)
418
+
419
+ let vo = this
420
+
421
+ async function core() {
422
+ let errTemp = null
423
+
424
+ //g
425
+ let g = get(msg, 'item', {})
426
+
427
+ //name
428
+ let name = get(g, 'name', '未知')
429
+
430
+ //showCheckYesNo
431
+ let bExit = false
432
+ await vo.$dg.showCheckYesNo(`確認是否刪除權限群組「${name}」?`)
433
+ .catch(() => {
434
+ bExit = true
435
+ })
436
+ if (bExit) {
437
+ return
438
+ }
439
+
440
+ //show loading
441
+ vo.$ui.updateLoading(true)
442
+
443
+ //save
444
+ await vo.$fapi.ruleGroups.del(g)
445
+ .catch((err) => {
446
+ errTemp = err
447
+ })
448
+
449
+ //check
450
+ if (errTemp !== null) {
451
+ vo.$alert(`刪除權限群組失敗: ${errTemp}`, { type: 'error' })
452
+ return
453
+ }
454
+
455
+ //gn
456
+ let gn = null
457
+ await waitFun(() => {
458
+ gn = find(vo.groupsTrans, { id: g.id })
459
+ let b = !iseobj(gn) //確認g.id已不存在
460
+ // console.log('waitFun', gn, b)
461
+ return b
462
+ })
463
+ // console.log('gn', gn)
464
+
465
+ //alert
466
+ vo.$alert(`刪除權限群組成功`)
467
+
468
+ }
469
+
470
+ //core
471
+ core()
472
+ // .then((res) => {
473
+ // console.log('then', res)
474
+ // })
475
+ .catch((err) => {
476
+ console.log('catch', err)
477
+ vo.$alert(`發生非預期錯誤,請洽管理員`, { type: 'error' })
478
+ })
479
+ .finally(() => {
480
+
481
+ //hide loading
482
+ vo.$ui.updateLoading(false)
483
+
484
+ })
485
+
486
+ },
487
+
488
+ dragGroupsOrder: function(groupsNew) {
489
+ // console.log('dragGroupsOrder', groupsNew)
490
+
491
+ let vo = this
492
+
493
+ async function core() {
494
+ let errTemp = null
495
+
496
+ //check, 新增或刪除皆跳出, 僅處理排序之操作
497
+ if (size(vo.groupsTrans) !== size(groupsNew)) {
498
+ return
499
+ }
500
+ // console.log(`size(vo.groupsTrans)`, size(vo.groupsTrans))
501
+ // console.log(`size(groupsNew)`, size(groupsNew))
502
+
503
+ //show loading
504
+ vo.$ui.updateLoading(true)
505
+
506
+ //gs
507
+ let gs = []
508
+ each(groupsNew, (v, k) => {
509
+ gs.push({
510
+ id: v.id,
511
+ order: k,
512
+ })
513
+ })
514
+ // console.log('gs', gs)
515
+
516
+ //save
517
+ await vo.$fapi.ruleGroups.save(gs)
518
+ .catch((err) => {
519
+ errTemp = err
520
+ })
521
+
522
+ //check
523
+ if (errTemp !== null) {
524
+ vo.$alert(`變更權限群組順序失敗: ${errTemp}`, { type: 'error' })
525
+ return
526
+ }
527
+
528
+ //gsn
529
+ let gsn = null
530
+ await waitFun(() => {
531
+ gsn = map(vo.groupsTrans, (v, k) => {
532
+ return {
533
+ id: v.id,
534
+ order: k,
535
+ }
536
+ })
537
+ return isEqual(gsn, gs)
538
+ })
539
+ // console.log('gsn', gsn)
540
+
541
+ //alert
542
+ vo.$alert(`變更權限群組順序成功`)
543
+
544
+ }
545
+
546
+ //core
547
+ core()
548
+ // .then((res) => {
549
+ // console.log('then', res)
550
+ // })
551
+ .catch((err) => {
552
+ console.log('catch', err)
553
+ vo.$alert(`發生非預期錯誤,請洽管理員`, { type: 'error' })
554
+ })
555
+ .finally(() => {
556
+
557
+ //hide loading
558
+ vo.$ui.updateLoading(false)
559
+
560
+ })
561
+
562
+ },
563
+
564
+ modifyGroup: function(group) {
565
+ // console.log('methods modifyGroup', group)
566
+
567
+ let vo = this
568
+
569
+ //check
570
+ if (!isestr(group.name)) {
571
+ vo.$alert(`權限群組名稱請記得給予`, { type: 'warning' })
572
+ }
573
+
574
+ //modify
575
+ each(vo.groupsTrans, (v, k) => {
576
+ if (v.id === group.id) {
577
+ vo.groupsTrans[k] = group
578
+ }
579
+ })
580
+ // console.log('vo.groupsTrans', cloneDeep(vo.groupsTrans))
581
+
582
+ //isModified
583
+ vo.isModified = true
584
+
585
+ },
586
+
587
+ saveGroups: function() {
588
+ // console.log('methods saveGroups')
589
+
590
+ let vo = this
591
+
592
+ async function core() {
593
+ let errTemp = null
594
+
595
+ //check
596
+ let b = false
597
+ each(vo.groupsTrans, (v, k) => {
598
+ if (!isestr(v.name)) {
599
+ vo.$alert(`第 ${k + 1} 個權限群組名稱為空`, { type: 'error' })
600
+ b = true
601
+ }
602
+ })
603
+ if (b) {
604
+ return
605
+ }
606
+
607
+ //show loading
608
+ vo.$ui.updateLoading(true)
609
+
610
+ //groups
611
+ let groups = map(vo.groupsTrans, (group) => {
612
+ let g = {
613
+ id: group.id,
614
+ name: group.name,
615
+ description: group.description,
616
+ crules: group.crules,
617
+ }
618
+ return g
619
+ })
620
+
621
+ //save
622
+ await vo.$fapi.ruleGroups.save(groups)
623
+ .catch((err) => {
624
+ errTemp = err
625
+ })
626
+
627
+ //check
628
+ if (errTemp !== null) {
629
+ vo.$alert(`儲存權限群組失敗: ${errTemp}`, { type: 'error' })
630
+ return
631
+ }
632
+
633
+ //isModified
634
+ vo.isModified = false
635
+
636
+ //alert
637
+ vo.$alert(`儲存權限群組成功`)
638
+
639
+ }
640
+
641
+ //core
642
+ core()
643
+ // .then((res) => {
644
+ // console.log('then', res)
645
+ // })
646
+ .catch((err) => {
647
+ console.log('catch', err)
648
+ vo.$alert(`發生非預期錯誤,請洽管理員`, { type: 'error' })
649
+ })
650
+ .finally(() => {
651
+
652
+ //hide loading
653
+ vo.$ui.updateLoading(false)
654
+
655
+ })
656
+
657
+ },
658
+
659
+ }
660
+ }
661
+ </script>
662
+
663
+ <style scoped>
664
+ </style>