w-web-perm 1.0.48 → 1.0.50

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 (111) hide show
  1. package/.github/workflows/ci-test.yml +2 -2
  2. package/README.md +5 -5
  3. package/dist/css/app.8781355a.css +1 -0
  4. package/dist/css/{chunk-vendors.f149e124.css → chunk-vendors.58917286.css} +1 -1
  5. package/dist/index.tmp +2 -2
  6. package/dist/js/app-legacy.b2754bb1.js +1 -0
  7. package/dist/js/app.b2754bb1.js +1 -0
  8. package/dist/js/chunk-vendors-legacy.c14a1ed1.js +21 -0
  9. package/dist/js/chunk-vendors.c14a1ed1.js +21 -0
  10. package/dist/w-web-perm.umd.js +2 -2
  11. package/dist/w-web-perm.umd.js.map +1 -1
  12. package/docs/WWebPerm.html +3 -3
  13. package/docs/WWebPerm.mjs.html +162 -210
  14. package/docs/index.html +1 -1
  15. package/logs/2026-06-19T16.log +191 -0
  16. package/logs/2026-06-19T23.log +0 -0
  17. package/logs/2026-06-20T00.log +207 -0
  18. package/logs/2026-06-20T11.log +221 -0
  19. package/logs/2026-06-20T12.log +146 -0
  20. package/logs/2026-06-20T13.log +134 -0
  21. package/logs/2026-06-20T14.log +296 -0
  22. package/logs/2026-06-20T15.log +225 -0
  23. package/logs/2026-06-20T16.log +174 -0
  24. package/logs/2026-06-21T16.log +110 -0
  25. package/logs/2026-06-21T17.log +301 -0
  26. package/logs/2026-06-21T18.log +238 -0
  27. package/logs/2026-06-21T19.log +141 -0
  28. package/logs/2026-06-21T20.log +99 -0
  29. package/logs/2026-06-21T21.log +143 -0
  30. package/logs/2026-06-21T23.log +26 -0
  31. package/logs/2026-06-22T00.log +33 -0
  32. package/logs/2026-06-22T08.log +235 -0
  33. package/logs/2026-06-22T09.log +246 -0
  34. package/logs/2026-06-22T10.log +301 -0
  35. package/logs/2026-06-22T11.log +140 -0
  36. package/logs/2026-06-22T12.log +22 -0
  37. package/logs/2026-06-22T14.log +44 -0
  38. package/logs/2026-06-22T23.log +951 -0
  39. package/logs/2026-06-23T00.log +263 -0
  40. package/logs/2026-06-23T08.log +611 -0
  41. package/logs/2026-06-30T21.log +3609 -0
  42. package/logs/2026-06-30T22.log +3682 -0
  43. package/logs/2026-06-30T23.log +592 -0
  44. package/logs/2026-07-01T12.log +0 -0
  45. package/logs/2026-07-09T22.log +2220 -0
  46. package/logs/2026-07-09T23.log +1140 -0
  47. package/logs/2026-07-10T12.log +6 -0
  48. package/logs/2026-07-10T13.log +351 -0
  49. package/logs/2026-07-10T16.log +1272 -0
  50. package/logs/2026-07-10T19.log +6 -0
  51. package/logs/2026-07-10T20.log +1883 -0
  52. package/logs/2026-07-10T21.log +3505 -0
  53. package/logs/2026-07-10T22.log +3395 -0
  54. package/logs/2026-07-11T00.log +1338 -0
  55. package/logs/2026-07-11T01.log +2492 -0
  56. package/logs/2026-07-11T17.log +19 -0
  57. package/package.json +23 -16
  58. package/public/index.html +2 -2
  59. package/server/WWebPerm.mjs +161 -209
  60. package/server/procCore.mjs +187 -0
  61. package/server/procLang.mjs +276 -60
  62. package/server/procStaInfor.mjs +128 -0
  63. package/server/provideTabs.mjs +1 -1
  64. package/server/srLog.mjs +30 -0
  65. package/server/staLogs/filterVpfsByWindow.mjs +27 -0
  66. package/server/staLogs/staEvent.callWorker.mjs +46 -0
  67. package/server/staLogs/staEvent.mjs +118 -0
  68. package/server/staLogs/staEvent.shellWorker.mjs +19 -0
  69. package/server/staLogs/staEventTable.mjs +102 -0
  70. package/settings.json +43 -0
  71. package/src/components/Common/CheckYes.vue +18 -1
  72. package/src/components/Layout.vue +1 -1
  73. package/src/components/LayoutContent.vue +13 -3
  74. package/src/components/LayoutContentGrups.vue +32 -25
  75. package/src/components/LayoutContentPemis.vue +32 -25
  76. package/src/components/LayoutContentStaInfor.vue +534 -0
  77. package/src/components/LayoutContentTargets.vue +35 -28
  78. package/src/components/LayoutContentUsers.vue +32 -25
  79. package/src/components/LayoutState.vue +5 -0
  80. package/src/components/VeCgrups.vue +19 -9
  81. package/src/components/VeCpemis.vue +19 -9
  82. package/src/components/VeCrules.vue +19 -9
  83. package/src/components/VeGrupBlngUsers.vue +35 -29
  84. package/src/components/VePemiBlngGrups.vue +35 -29
  85. package/src/getPerm.mjs +7 -17
  86. package/src/getPermUserInfor.mjs +8 -18
  87. package/src/main.js +4 -9
  88. package/src/perm.mjs +3 -4
  89. package/src/plugins/mShare.mjs +8 -13
  90. package/src/plugins/mUI.mjs +7 -44
  91. package/src/store/mutations.mjs +0 -10
  92. package/src/store/types.mjs +0 -2
  93. package/srv.mjs +76 -101
  94. package/tableTags.json +1 -1
  95. package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +450 -0
  96. package/db/wperm/grups/data.mdb +0 -0
  97. package/db/wperm/grups/lock.mdb +0 -0
  98. package/db/wperm/pemis/data.mdb +0 -0
  99. package/db/wperm/pemis/lock.mdb +0 -0
  100. package/db/wperm/targets/data.mdb +0 -0
  101. package/db/wperm/targets/lock.mdb +0 -0
  102. package/db/wperm/users/data.mdb +0 -0
  103. package/db/wperm/users/lock.mdb +0 -0
  104. package/dist/css/app.30e81bfe.css +0 -1
  105. package/dist/js/app-legacy.3324392e.js +0 -1
  106. package/dist/js/app.3324392e.js +0 -1
  107. package/dist/js/chunk-vendors-legacy.e8703728.js +0 -21
  108. package/dist/js/chunk-vendors.e8703728.js +0 -21
  109. package/src/plugins/mDataSelectorSchema.mjs +0 -30
  110. package/tableTags-web-perm.json +0 -1
  111. package/test/getUserRules.test.mjs +0 -899
@@ -39,6 +39,7 @@
39
39
 
40
40
  <!-- 功能區 -->
41
41
  <div
42
+ data-fmid="users-toolbar"
42
43
  style="padding:5px; border-top:1px solid #ddd; display:flex; align-items:center;"
43
44
  _v-if="showIsEditable || isEditable"
44
45
  >
@@ -185,6 +186,7 @@
185
186
  :iconColor="'#eee'"
186
187
  :iconColorHover="'#fff'"
187
188
  :shadow="false"
189
+ :promiseUnlock="true"
188
190
  @click="saveUsers"
189
191
  ></WButtonCircle>
190
192
 
@@ -298,7 +300,6 @@ export default {
298
300
  mdiPencilOutline,
299
301
  mdiContentCopy,
300
302
 
301
- panelWidth: 100,
302
303
  panelHeight: 100,
303
304
  headHeight: 100,
304
305
 
@@ -616,7 +617,6 @@ export default {
616
617
  let vo = this
617
618
 
618
619
  //panelWidth, panelHeight
619
- vo.panelWidth = msg.snew.offsetWidth
620
620
  vo.panelHeight = msg.snew.offsetHeight
621
621
 
622
622
  },
@@ -1148,20 +1148,28 @@ export default {
1148
1148
 
1149
1149
  },
1150
1150
 
1151
- saveUsers: function() {
1152
- // console.log('method saveUsers')
1151
+ saveUsers: function(msg) {
1153
1152
 
1154
1153
  let vo = this
1155
1154
 
1156
- async function core() {
1157
- let errTemp = null
1155
+ //第一行立刻釋放按鈕視覺鎖
1156
+ msg.pm.resolve()
1158
1157
 
1159
- //show loading
1160
- vo.$ui.updateLoading(true)
1158
+ //fire-and-forget, 不 await
1159
+ vo.doSaveUsers()
1161
1160
 
1162
- //check
1161
+ },
1162
+
1163
+ doSaveUsers: function() {
1164
+ // console.log('method doSaveUsers')
1165
+
1166
+ let vo = this
1167
+
1168
+ async function core() {
1169
+
1170
+ //1) 同步檢測 (在開 loading 之前)
1163
1171
  if (isestr(vo.isError)) {
1164
- vo.$alert(`${vo.isError}`, { type: 'error' })
1172
+ await vo.$dg.showCheckYes(`${vo.isError}`)
1165
1173
  return
1166
1174
  }
1167
1175
 
@@ -1170,35 +1178,34 @@ export default {
1170
1178
 
1171
1179
  //check
1172
1180
  if (size(rows) === 0) {
1173
- vo.$alert(`${vo.$t('userAddEmpty')}`, { type: 'error' })
1181
+ await vo.$dg.showCheckYes(`${vo.$t('userAddEmpty')}`)
1174
1182
  return
1175
1183
  }
1176
1184
 
1177
- //updateUsers
1185
+ //2) 確定打 API 才開 loading
1186
+ vo.$ui.updateLoading(true)
1187
+
1188
+ //3) updateUsers, 各自 catch + 旗標短路
1189
+ let okSave = false
1178
1190
  await vo.$fapi.updateUsers(rows)
1179
- .catch((err) => {
1180
- errTemp = err
1191
+ .then(() => { okSave = true })
1192
+ .catch(async (err) => {
1193
+ vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
1194
+ await vo.$dg.showCheckYes(`${vo.$t('userSaveUsersFail')}: ${vo.$tErr(err)}`)
1181
1195
  })
1182
-
1183
- //check
1184
- if (errTemp !== null) {
1185
- vo.$alert(`${vo.$t('userSaveUsersFail')}: ${errTemp}`, { type: 'error' })
1186
- return
1187
- }
1196
+ if (!okSave) return
1188
1197
 
1189
1198
  //isModified
1190
1199
  vo.isModified = false
1191
1200
 
1192
- //alert
1193
- vo.$alert(vo.$t('userSaveUsersSuccess'))
1201
+ //alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
1202
+ vo.$ui.updateLoading(false)
1203
+ await vo.$dg.showCheckYes(vo.$t('userSaveUsersSuccess'), { type: 'success' })
1194
1204
 
1195
1205
  }
1196
1206
 
1197
1207
  //core
1198
1208
  core()
1199
- // .then((res) => {
1200
- // console.log('then', res)
1201
- // })
1202
1209
  .catch((err) => {
1203
1210
  console.log('catch', err)
1204
1211
  vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' })
@@ -3,6 +3,9 @@
3
3
  :style="`position:absolute; top:0px; left:0px; width:100%; height:100%; transition:all 0.5s linear; display:flex; align-items:center; justify-content:center;`"
4
4
  >
5
5
 
6
+ <!-- conn-state 觀看區包覆層(e2e 紅框標注用;display:flex 與原置中內容布局一致,不改視覺) -->
7
+ <div data-fmid="conn-state" style="display:flex; align-items:center;">
8
+
6
9
  <template v-if="connState==='csIng'">
7
10
 
8
11
  <img style="width:100px; height:100px;" :src="img_connection">
@@ -63,6 +66,8 @@
63
66
 
64
67
  </template>
65
68
 
69
+ </div>
70
+
66
71
  </div>
67
72
  </template>
68
73
 
@@ -198,7 +198,6 @@ export default {
198
198
 
199
199
  fullscreen: false,
200
200
 
201
- panelWidth: 100,
202
201
  panelHeight: 100,
203
202
  headHeight: 100,
204
203
 
@@ -339,7 +338,6 @@ export default {
339
338
  let vo = this
340
339
 
341
340
  //panelWidth, panelHeight
342
- vo.panelWidth = msg.panelWidth
343
341
  vo.panelHeight = msg.contentHeightMax
344
342
 
345
343
  },
@@ -411,9 +409,9 @@ export default {
411
409
  'mode': 'text',
412
410
  'enable': 'text',
413
411
  },
414
- // kpHeadCheckBox: {
415
- // 'name': true,
416
- // },
412
+ kpHeadCheckBox: {
413
+ 'name': true,
414
+ },
417
415
  rowsChange: (rs) => {
418
416
  // console.log('rowsChange', rs)
419
417
  // console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
@@ -747,6 +745,18 @@ export default {
747
745
 
748
746
  let vo = this
749
747
 
748
+ //save按鈕第一行立刻釋放視覺鎖
749
+ msg.pm.resolve()
750
+
751
+ //fire-and-forget, 不 await
752
+ vo.doSave()
753
+
754
+ },
755
+
756
+ doSave: function() {
757
+
758
+ let vo = this
759
+
750
760
  async function core() {
751
761
 
752
762
  //show loading
@@ -802,12 +812,12 @@ export default {
802
812
  vo.bShow = false
803
813
 
804
814
  })
805
- .catch(() => { })
815
+ .catch((err) => {
816
+ console.log('doSave', err)
817
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' }) //§5.1: 非預期例外須告知, 不靜默吞 (失敗時 .then 不執行→視窗不關)
818
+ })
806
819
  .finally(() => {
807
820
 
808
- //save按鈕解除loading
809
- msg.pm.resolve()
810
-
811
821
  //hide loading
812
822
  vo.$ui.updateLoading(false)
813
823
 
@@ -198,7 +198,6 @@ export default {
198
198
 
199
199
  fullscreen: false,
200
200
 
201
- panelWidth: 100,
202
201
  panelHeight: 100,
203
202
  headHeight: 100,
204
203
 
@@ -339,7 +338,6 @@ export default {
339
338
  let vo = this
340
339
 
341
340
  //panelWidth, panelHeight
342
- vo.panelWidth = msg.panelWidth
343
341
  vo.panelHeight = msg.contentHeightMax
344
342
 
345
343
  },
@@ -411,9 +409,9 @@ export default {
411
409
  'mode': 'text',
412
410
  'enable': 'text',
413
411
  },
414
- // kpHeadCheckBox: {
415
- // 'name': true,
416
- // },
412
+ kpHeadCheckBox: {
413
+ 'name': true,
414
+ },
417
415
  rowsChange: (rs) => {
418
416
  // console.log('rowsChange', rs)
419
417
  // console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
@@ -747,6 +745,18 @@ export default {
747
745
 
748
746
  let vo = this
749
747
 
748
+ //save按鈕第一行立刻釋放視覺鎖
749
+ msg.pm.resolve()
750
+
751
+ //fire-and-forget, 不 await
752
+ vo.doSave()
753
+
754
+ },
755
+
756
+ doSave: function() {
757
+
758
+ let vo = this
759
+
750
760
  async function core() {
751
761
 
752
762
  //show loading
@@ -802,12 +812,12 @@ export default {
802
812
  vo.bShow = false
803
813
 
804
814
  })
805
- .catch(() => { })
815
+ .catch((err) => {
816
+ console.log('doSave', err)
817
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' }) //§5.1: 非預期例外須告知, 不靜默吞 (失敗時 .then 不執行→視窗不關)
818
+ })
806
819
  .finally(() => {
807
820
 
808
- //save按鈕解除loading
809
- msg.pm.resolve()
810
-
811
821
  //hide loading
812
822
  vo.$ui.updateLoading(false)
813
823
 
@@ -194,7 +194,6 @@ export default {
194
194
 
195
195
  fullscreen: false,
196
196
 
197
- panelWidth: 100,
198
197
  panelHeight: 100,
199
198
  headHeight: 100,
200
199
 
@@ -334,7 +333,6 @@ export default {
334
333
  let vo = this
335
334
 
336
335
  //panelWidth, panelHeight
337
- vo.panelWidth = msg.panelWidth
338
336
  vo.panelHeight = msg.contentHeightMax
339
337
 
340
338
  },
@@ -401,9 +399,9 @@ export default {
401
399
  'id': 'text',
402
400
  'enable': 'text',
403
401
  },
404
- // kpHeadCheckBox: {
405
- // 'id': true,
406
- // },
402
+ kpHeadCheckBox: {
403
+ 'id': true,
404
+ },
407
405
  rowsChange: (rs) => {
408
406
  // console.log('rowsChange', rs)
409
407
  // console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
@@ -690,6 +688,18 @@ export default {
690
688
 
691
689
  let vo = this
692
690
 
691
+ //save按鈕第一行立刻釋放視覺鎖
692
+ msg.pm.resolve()
693
+
694
+ //fire-and-forget, 不 await
695
+ vo.doSave()
696
+
697
+ },
698
+
699
+ doSave: function() {
700
+
701
+ let vo = this
702
+
693
703
  async function core() {
694
704
 
695
705
  //show loading
@@ -737,12 +747,12 @@ export default {
737
747
  vo.bShow = false
738
748
 
739
749
  })
740
- .catch(() => { })
750
+ .catch((err) => {
751
+ console.log('doSave', err)
752
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' }) //§5.1: 非預期例外須告知, 不靜默吞 (失敗時 .then 不執行→視窗不關)
753
+ })
741
754
  .finally(() => {
742
755
 
743
- //save按鈕解除loading
744
- msg.pm.resolve()
745
-
746
756
  //hide loading
747
757
  vo.$ui.updateLoading(false)
748
758
 
@@ -225,7 +225,6 @@ export default {
225
225
 
226
226
  fullscreen: false,
227
227
 
228
- panelWidth: 100,
229
228
  panelHeight: 100,
230
229
  headHeight: 100,
231
230
 
@@ -374,7 +373,6 @@ export default {
374
373
  let vo = this
375
374
 
376
375
  //panelWidth, panelHeight
377
- vo.panelWidth = msg.panelWidth
378
376
  vo.panelHeight = msg.contentHeightMax
379
377
 
380
378
  },
@@ -960,29 +958,21 @@ export default {
960
958
 
961
959
  let vo = this
962
960
 
963
- //errTemp
964
- let errTemp = null
965
-
966
- //check
967
- if (size(rows) === 0) {
968
- vo.$alert(`${vo.$t('userSaveUsersEmpty')}`, { type: 'error' })
969
- return
970
- }
971
-
972
- //updateUsers
961
+ //3) updateUsers, 各自 catch + okX 旗標短路 (canonical 五段結構; 空清單檢查已上移至 doSave core())
962
+ let okSave = false
973
963
  await vo.$fapi.updateUsers(rows)
974
- .catch((err) => {
975
- errTemp = err
964
+ .then(() => { okSave = true })
965
+ .catch(async (err) => {
966
+ vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
967
+ await vo.$dg.showCheckYes(`${vo.$t('userSaveUsersFail')}: ${vo.$tErr(err)}`)
976
968
  })
977
-
978
- //check
979
- if (errTemp !== null) {
980
- vo.$alert(`${vo.$t('userSaveUsersFail')}: ${errTemp}`, { type: 'error' })
969
+ if (!okSave) {
981
970
  return
982
971
  }
983
972
 
984
- //alert
985
- vo.$alert(vo.$t('userSaveUsersSuccess'))
973
+ //alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
974
+ vo.$ui.updateLoading(false)
975
+ await vo.$dg.showCheckYes(vo.$t('userSaveUsersSuccess'), { type: 'success' })
986
976
 
987
977
  },
988
978
 
@@ -1006,18 +996,34 @@ export default {
1006
996
 
1007
997
  let vo = this
1008
998
 
999
+ //save按鈕第一行立刻釋放視覺鎖
1000
+ msg.pm.resolve()
1001
+
1002
+ //fire-and-forget, 不 await
1003
+ vo.doSave()
1004
+
1005
+ },
1006
+
1007
+ doSave: function() {
1008
+
1009
+ let vo = this
1010
+
1009
1011
  async function core() {
1010
1012
 
1011
- //show loading
1013
+ //1) 事先檢測 (所有同步檢查在開 loading 之前, 空清單不應先閃 loading)
1014
+ let rows = get(vo, 'opt.rows', [])
1015
+ // console.log('rows', rows)
1016
+ if (size(rows) === 0) {
1017
+ await vo.$dg.showCheckYes(`${vo.$t('userSaveUsersEmpty')}`)
1018
+ return
1019
+ }
1020
+
1021
+ //2) 確定打 API 才開 loading
1012
1022
  vo.$ui.updateLoading(true)
1013
1023
 
1014
1024
  //delay
1015
1025
  await delay(300)
1016
1026
 
1017
- //rows
1018
- let rows = get(vo, 'opt.rows', [])
1019
- // console.log('rows', rows)
1020
-
1021
1027
  //users
1022
1028
  let users = cloneDeep(vo.users)
1023
1029
  // console.log('users', users)
@@ -1084,12 +1090,12 @@ export default {
1084
1090
  vo.bShow = false
1085
1091
 
1086
1092
  })
1087
- .catch(() => { })
1093
+ .catch((err) => {
1094
+ console.log('doSave', err)
1095
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' }) //§5.1: 非預期例外須告知, 不靜默吞 (失敗時 .then 不執行→視窗不關)
1096
+ })
1088
1097
  .finally(() => {
1089
1098
 
1090
- //save按鈕解除loading
1091
- msg.pm.resolve()
1092
-
1093
1099
  //hide loading
1094
1100
  vo.$ui.updateLoading(false)
1095
1101
 
@@ -225,7 +225,6 @@ export default {
225
225
 
226
226
  fullscreen: false,
227
227
 
228
- panelWidth: 100,
229
228
  panelHeight: 100,
230
229
  headHeight: 100,
231
230
 
@@ -374,7 +373,6 @@ export default {
374
373
  let vo = this
375
374
 
376
375
  //panelWidth, panelHeight
377
- vo.panelWidth = msg.panelWidth
378
376
  vo.panelHeight = msg.contentHeightMax
379
377
 
380
378
  },
@@ -960,29 +958,21 @@ export default {
960
958
 
961
959
  let vo = this
962
960
 
963
- //errTemp
964
- let errTemp = null
965
-
966
- //check
967
- if (size(rows) === 0) {
968
- vo.$alert(`${vo.$t('grupSaveGrupsEmpty')}`, { type: 'error' })
969
- return
970
- }
971
-
972
- //updateGrups
961
+ //3) updateGrups, 各自 catch + okX 旗標短路 (canonical 五段結構; 空清單檢查已上移至 doSave core())
962
+ let okSave = false
973
963
  await vo.$fapi.updateGrups(rows)
974
- .catch((err) => {
975
- errTemp = err
964
+ .then(() => { okSave = true })
965
+ .catch(async (err) => {
966
+ vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
967
+ await vo.$dg.showCheckYes(`${vo.$t('grupSaveGrupsFail')}: ${vo.$tErr(err)}`)
976
968
  })
977
-
978
- //check
979
- if (errTemp !== null) {
980
- vo.$alert(`${vo.$t('grupSaveGrupsFail')}: ${errTemp}`, { type: 'error' })
969
+ if (!okSave) {
981
970
  return
982
971
  }
983
972
 
984
- //alert
985
- vo.$alert(vo.$t('grupSaveGrupsSuccess'))
973
+ //alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
974
+ vo.$ui.updateLoading(false)
975
+ await vo.$dg.showCheckYes(vo.$t('grupSaveGrupsSuccess'), { type: 'success' })
986
976
 
987
977
  },
988
978
 
@@ -1006,18 +996,34 @@ export default {
1006
996
 
1007
997
  let vo = this
1008
998
 
999
+ //save按鈕第一行立刻釋放視覺鎖
1000
+ msg.pm.resolve()
1001
+
1002
+ //fire-and-forget, 不 await
1003
+ vo.doSave()
1004
+
1005
+ },
1006
+
1007
+ doSave: function() {
1008
+
1009
+ let vo = this
1010
+
1009
1011
  async function core() {
1010
1012
 
1011
- //show loading
1013
+ //1) 事先檢測 (所有同步檢查在開 loading 之前, 空清單不應先閃 loading)
1014
+ let rows = get(vo, 'opt.rows', [])
1015
+ // console.log('rows', rows)
1016
+ if (size(rows) === 0) {
1017
+ await vo.$dg.showCheckYes(`${vo.$t('grupSaveGrupsEmpty')}`)
1018
+ return
1019
+ }
1020
+
1021
+ //2) 確定打 API 才開 loading
1012
1022
  vo.$ui.updateLoading(true)
1013
1023
 
1014
1024
  //delay
1015
1025
  await delay(300)
1016
1026
 
1017
- //rows
1018
- let rows = get(vo, 'opt.rows', [])
1019
- // console.log('rows', rows)
1020
-
1021
1027
  //grups
1022
1028
  let grups = cloneDeep(vo.grups)
1023
1029
  // console.log('grups', grups)
@@ -1084,12 +1090,12 @@ export default {
1084
1090
  vo.bShow = false
1085
1091
 
1086
1092
  })
1087
- .catch(() => { })
1093
+ .catch((err) => {
1094
+ console.log('doSave', err)
1095
+ vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' }) //§5.1: 非預期例外須告知, 不靜默吞 (失敗時 .then 不執行→視窗不關)
1096
+ })
1088
1097
  .finally(() => {
1089
1098
 
1090
- //save按鈕解除loading
1091
- msg.pm.resolve()
1092
-
1093
1099
  //hide loading
1094
1100
  vo.$ui.updateLoading(false)
1095
1101
 
package/src/getPerm.mjs CHANGED
@@ -12,10 +12,10 @@ async function getPerm(url, tokenTar, opt = {}) {
12
12
 
13
13
  //check
14
14
  if (!isestr(url)) {
15
- return Promise.reject('invalid url')
15
+ return Promise.reject('invalidUrl')
16
16
  }
17
17
  if (!isestr(tokenTar)) {
18
- return Promise.reject('invalid tokenTar')
18
+ return Promise.reject('invalidTokenTar')
19
19
  }
20
20
 
21
21
  //funConvertPerm
@@ -23,7 +23,7 @@ async function getPerm(url, tokenTar, opt = {}) {
23
23
 
24
24
  //url
25
25
  if (url.indexOf('token={token}') < 0) {
26
- return Promise.reject(`no 'token={token}' in url`)
26
+ return Promise.reject('noTokenInUrl')
27
27
  }
28
28
  url = url.replaceAll('{token}', tokenTar)
29
29
  // console.log('getPerm: url', url)
@@ -36,10 +36,7 @@ async function getPerm(url, tokenTar, opt = {}) {
36
36
 
37
37
  //check
38
38
  if (errTemp !== null) {
39
- console.log('res', res)
40
- console.log('errTemp', errTemp)
41
- console.log(`can not get user by url[${url}]`)
42
- return Promise.reject(`can not get user by url[${url}]`) //由SSO取得使用者資訊錯誤
39
+ return Promise.reject('cannotGetUserByUrl') //由SSO取得使用者資訊錯誤
43
40
  }
44
41
 
45
42
  //data
@@ -53,12 +50,7 @@ async function getPerm(url, tokenTar, opt = {}) {
53
50
 
54
51
  //check
55
52
  if (state !== 'success') {
56
- console.log('res', res)
57
- console.log('data', data)
58
- console.log('state', state)
59
- console.log('errTemp', msg)
60
- console.log(`can not get user data by url[${url}]`)
61
- return Promise.reject(`can not get user data by url[${url}]`) //取得使用者資訊失敗
53
+ return Promise.reject('cannotGetUserDataByUrl') //取得使用者資訊失敗
62
54
  }
63
55
 
64
56
  //ur
@@ -67,8 +59,7 @@ async function getPerm(url, tokenTar, opt = {}) {
67
59
 
68
60
  //check
69
61
  if (!iseobj(ur)) {
70
- console.log(`no user data by url[${url}]`)
71
- return Promise.reject(`no user data by url[${url}]`)
62
+ return Promise.reject('noUserDataByUrl')
72
63
  }
73
64
 
74
65
  //check
@@ -83,8 +74,7 @@ async function getPerm(url, tokenTar, opt = {}) {
83
74
 
84
75
  //check
85
76
  if (!iseobj(ur)) {
86
- console.log(`no user data after funConvertPerm`)
87
- return Promise.reject(`no user data after funConvertPerm`)
77
+ return Promise.reject('noUserDataAfterConvert')
88
78
  }
89
79
 
90
80
  }