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
@@ -0,0 +1,187 @@
1
+ import get from 'lodash-es/get.js'
2
+ import each from 'lodash-es/each.js'
3
+ import map from 'lodash-es/map.js'
4
+ import size from 'lodash-es/size.js'
5
+ import isestr from 'wsemi/src/isestr.mjs'
6
+ import haskey from 'wsemi/src/haskey.mjs'
7
+ import arrHas from 'wsemi/src/arrHas.mjs'
8
+ import ltdtDiffByKey from 'wsemi/src/ltdtDiffByKey.mjs'
9
+ import ltdtmapping from 'wsemi/src/ltdtmapping.mjs'
10
+ import ds from '../src/schema/index.mjs'
11
+
12
+
13
+ function proc(woItems, procOrm, { srLog, kmx }) {
14
+
15
+
16
+ //updateTabItems
17
+ let updateTabItems = async (keyTable, userId, rows, keyDetect) => {
18
+ // console.log('updateTabItems', keyTable, userId, rows.length, keyDetect)
19
+
20
+ //序列化同表之並行整表批次寫入: 防 lost update (同 keyTable 序列化, 不同表並行)
21
+ return await kmx('updateTabItems:' + keyTable, async () => {
22
+
23
+ //ltdtmapping
24
+ rows = ltdtmapping(rows, ds[keyTable].keys)
25
+ // console.log('ltdtmapping rows', rows)
26
+
27
+ //重給order
28
+ rows = map(rows, (r, k) => {
29
+ r.order = k + 1
30
+ return r
31
+ })
32
+
33
+ //ckKey, 回傳 err key (saveRowFieldInvalid / saveRowFieldDuplicate) 或 null; 動態細節 (row index/field/value) 改記 srLog, 不進使用者訊息
34
+ let ckKey = (rows, key) => {
35
+ let err = null
36
+
37
+ //check
38
+ let kp = {}
39
+ each(rows, (v, k) => {
40
+
41
+ //value
42
+ let value = get(v, key, '')
43
+
44
+ //check
45
+ if (!isestr(value)) {
46
+ srLog.error({ event: 'updateTabItems-ckKey-error', keyTable, key, msg: 'saveRowFieldInvalid', row: k })
47
+ err = `saveRowFieldInvalid`
48
+ return false //跳出
49
+ }
50
+
51
+ //check
52
+ if (haskey(kp, value)) {
53
+ srLog.error({ event: 'updateTabItems-ckKey-error', keyTable, key, msg: 'saveRowFieldDuplicate', row: k, value })
54
+ err = `saveRowFieldDuplicate`
55
+ return false //跳出
56
+ }
57
+
58
+ //kp
59
+ kp[value] = true
60
+
61
+ })
62
+
63
+ return err
64
+ }
65
+
66
+ //偵測未給予或重複
67
+ let err = null
68
+ if (true) {
69
+ if (arrHas(keyTable, ['targets'])) {
70
+ err = ckKey(rows, 'id')
71
+ if (err !== null) {
72
+ return Promise.reject(err)
73
+ }
74
+ }
75
+ if (arrHas(keyTable, ['pemis', 'grups'])) { //users可重複name故不列入
76
+ err = ckKey(rows, 'name')
77
+ if (err !== null) {
78
+ return Promise.reject(err)
79
+ }
80
+ }
81
+ if (arrHas(keyTable, ['users'])) {
82
+ err = ckKey(rows, 'email')
83
+ if (err !== null) {
84
+ return Promise.reject(err)
85
+ }
86
+ }
87
+ }
88
+
89
+ //ltdtDiffByKey
90
+ let ltdtOld = await woItems[keyTable].select()
91
+ let ltdtNew = rows
92
+ let r = ltdtDiffByKey(ltdtOld, ltdtNew, keyDetect)
93
+ // console.log('ltdtDiffByKey r', r)
94
+
95
+ //del
96
+ if (size(r.del) > 0) {
97
+ await procOrm(userId, keyTable, 'del', r.del) //須使用procOrm才有辦法自動給予相關欄位
98
+ // .catch((err) => {
99
+ // console.log('woItems[keyTable].del err', err)
100
+ // })
101
+ }
102
+
103
+ //add
104
+ if (size(r.add) > 0) {
105
+ await procOrm(userId, keyTable, 'insert', r.add) //須使用procOrm才有辦法自動給予相關欄位
106
+ // .catch((err) => {
107
+ // console.log('woItems[keyTable].insert err', err)
108
+ // })
109
+ }
110
+
111
+ //diff
112
+ if (size(r.diff) > 0) {
113
+ await procOrm(userId, keyTable, 'save', r.diff) //須使用procOrm才有辦法自動給予相關欄位
114
+ // .catch((err) => {
115
+ // console.log('woItems[keyTable].save err', err)
116
+ // })
117
+ }
118
+
119
+ return ltdtNew
120
+
121
+ })
122
+ }
123
+
124
+
125
+ //errLog: 失敗統一記 err key (updateTabItems reject 為 key 字串如 saveRowFieldInvalid; procOrm 失敗為 Error)
126
+ let errLog = (event, userId, err) => {
127
+ srLog.error({ event, userId, msg: (typeof err === 'string') ? err : ((err && err.message) || event) })
128
+ }
129
+
130
+
131
+ //updateTargets
132
+ let updateTargets = async (userId, rows) => {
133
+ try {
134
+ await updateTabItems('targets', userId, rows, 'id')
135
+ }
136
+ catch (err) { errLog('updateTargets-error', userId, err); throw err }
137
+ srLog.info({ event: 'updateTargets-success', userId })
138
+ return 'saveTabItemsSuccess' //成功 msg key
139
+ }
140
+
141
+
142
+ //updatePemis
143
+ let updatePemis = async (userId, rows) => {
144
+ try {
145
+ await updateTabItems('pemis', userId, rows, 'name')
146
+ }
147
+ catch (err) { errLog('updatePemis-error', userId, err); throw err }
148
+ srLog.info({ event: 'updatePemis-success', userId })
149
+ return 'saveTabItemsSuccess' //成功 msg key
150
+ }
151
+
152
+
153
+ //updateGrups
154
+ let updateGrups = async (userId, rows) => {
155
+ try {
156
+ await updateTabItems('grups', userId, rows, 'name')
157
+ }
158
+ catch (err) { errLog('updateGrups-error', userId, err); throw err }
159
+ srLog.info({ event: 'updateGrups-success', userId })
160
+ return 'saveTabItemsSuccess' //成功 msg key
161
+ }
162
+
163
+
164
+ //updateUsers
165
+ let updateUsers = async (userId, rows) => {
166
+ try {
167
+ await updateTabItems('users', userId, rows, 'id')
168
+ }
169
+ catch (err) { errLog('updateUsers-error', userId, err); throw err }
170
+ srLog.info({ event: 'updateUsers-success', userId })
171
+ return 'saveTabItemsSuccess' //成功 msg key
172
+ }
173
+
174
+
175
+ let p = {
176
+ updateTargets,
177
+ updatePemis,
178
+ updateGrups,
179
+ updateUsers,
180
+ }
181
+
182
+
183
+ return p
184
+ }
185
+
186
+
187
+ export default proc
@@ -57,10 +57,11 @@ let kpLang = {
57
57
  cht: '等待數據中...',
58
58
  },
59
59
 
60
- isEditabled: {
61
- eng: 'Editable',
62
- cht: '是否編輯',
63
- },
60
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
61
+ // isEditabled: {
62
+ // eng: 'Editable',
63
+ // cht: '是否編輯',
64
+ // },
64
65
  saveChanges: {
65
66
  eng: `Save changes`,
66
67
  cht: `儲存變更`,
@@ -85,10 +86,11 @@ let kpLang = {
85
86
  eng: `Delete`,
86
87
  cht: `刪除`,
87
88
  },
88
- cancel: {
89
- eng: `Cancel`,
90
- cht: `取消`,
91
- },
89
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
90
+ // cancel: {
91
+ // eng: `Cancel`,
92
+ // cht: `取消`,
93
+ // },
92
94
  screenFull: {
93
95
  eng: `Max size`,
94
96
  cht: `最大化尺寸`,
@@ -130,11 +132,103 @@ let kpLang = {
130
132
  eng: `An unexpected error occurred, please contact the administrator`,
131
133
  cht: `發生非預期錯誤,請洽管理員`,
132
134
  },
133
- unknow: {
134
- eng: `Unknow`,
135
- cht: `未知`,
135
+
136
+ //後端 reject 之 err key (eng + cht), 前端 .catch 依 lang 用 $tErr 反查顯示
137
+ cannotConnectServer: {
138
+ eng: `Cannot connect to server`,
139
+ cht: `無法連線至伺服器`,
140
+ },
141
+ saveRowFieldInvalid: {
142
+ eng: `Invalid field value in saved data`,
143
+ cht: `儲存資料的欄位值無效`,
144
+ },
145
+ saveRowFieldDuplicate: {
146
+ eng: `Duplicate field value in saved data`,
147
+ cht: `儲存資料的欄位值重複`,
148
+ },
149
+ saveTabItemsSuccess: {
150
+ eng: `Saved successfully`,
151
+ cht: `儲存成功`,
152
+ },
153
+ cannotGetUserId: {
154
+ eng: `Cannot get the user id`,
155
+ cht: `無法取得使用者 Id`,
156
+ },
157
+ cannotGetUserEmail: {
158
+ eng: `Cannot get the email of user`,
159
+ cht: `無法取得使用者 Email`,
160
+ },
161
+ cannotGetUserName: {
162
+ eng: `Cannot get the name of user`,
163
+ cht: `無法取得使用者名稱`,
164
+ },
165
+ cannotGetUserRole: {
166
+ eng: `Cannot get the role of user`,
167
+ cht: `無法取得使用者角色`,
168
+ },
169
+ cannotFindUserFromToken: {
170
+ eng: `Cannot identify the user from token`,
171
+ cht: `無法由 token 識別使用者`,
172
+ },
173
+ cannotGetUserProp: {
174
+ eng: `Cannot get the property of user`,
175
+ cht: `無法取得使用者對應屬性`,
176
+ },
177
+ cannotGetUserFromPerm: {
178
+ eng: `Cannot find the user in permission system`,
179
+ cht: `無法於權限系統取得使用者`,
180
+ },
181
+ userNoPermission: {
182
+ eng: `User does not have permission`,
183
+ cht: `使用者權限不足`,
184
+ },
185
+ invalidPayload: {
186
+ eng: `Invalid payload in request`,
187
+ cht: `請求內容無效`,
188
+ },
189
+ invalidFromInPayload: {
190
+ eng: `Invalid from in payload`,
191
+ cht: `請求來源欄位無效`,
192
+ },
193
+ invalidRowsInPayload: {
194
+ eng: `Invalid rows in payload`,
195
+ cht: `請求資料列無效`,
196
+ },
197
+ invalidFrom: {
198
+ eng: `Invalid from`,
199
+ cht: `來源欄位無效`,
200
+ },
201
+ invalidRows: {
202
+ eng: `Invalid rows`,
203
+ cht: `資料列無效`,
204
+ },
205
+ cannotGetUserRules: {
206
+ eng: `Cannot get rules of user`,
207
+ cht: `無法取得使用者權限規則`,
208
+ },
209
+ tokenNoPermission: {
210
+ eng: `Token does not have permission`,
211
+ cht: `權限不足`,
212
+ },
213
+ userIdNoPermrules: {
214
+ eng: `The user id does not have permission rules`,
215
+ cht: `此使用者沒有權限規則`,
216
+ },
217
+ invalidKeyTable: {
218
+ eng: `Invalid key table`,
219
+ cht: `資料表名稱無效`,
220
+ },
221
+ cannotFindUserId: {
222
+ eng: `Cannot find the user id`,
223
+ cht: `無法找到使用者 Id`,
136
224
  },
137
225
 
226
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
227
+ // unknow: {
228
+ // eng: `Unknow`,
229
+ // cht: `未知`,
230
+ // },
231
+
138
232
  username: {
139
233
  eng: `Username`,
140
234
  cht: `使用者姓名`,
@@ -172,10 +266,11 @@ let kpLang = {
172
266
  eng: `Use groups`,
173
267
  cht: `所屬權限群組`,
174
268
  },
175
- belongPemis: {
176
- eng: `Use permissions`,
177
- cht: `所屬權限`,
178
- },
269
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
270
+ // belongPemis: {
271
+ // eng: `Use permissions`,
272
+ // cht: `所屬權限`,
273
+ // },
179
274
  belongGrupsNames: {
180
275
  eng: `Use permission groups`,
181
276
  cht: `所屬權限群組名稱`,
@@ -198,6 +293,10 @@ let kpLang = {
198
293
  eng: `Name errors`,
199
294
  cht: `名稱出現錯誤待修復`,
200
295
  },
296
+ errInIds: {
297
+ eng: `ID errors`,
298
+ cht: `ID 出現錯誤待修復`,
299
+ },
201
300
  errInEmails: {
202
301
  eng: `Email errors`,
203
302
  cht: `Email出現錯誤待修復`,
@@ -292,10 +391,11 @@ let kpLang = {
292
391
  eng: `Enable`,
293
392
  cht: `是否使用`,
294
393
  },
295
- targetClearTargetsFail: {
296
- eng: `Failed to clear existing targets`,
297
- cht: `清除既有對象數據失敗`,
298
- },
394
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
395
+ // targetClearTargetsFail: {
396
+ // eng: `Failed to clear existing targets`,
397
+ // cht: `清除既有對象數據失敗`,
398
+ // },
299
399
  targetSaveTargetsFail: {
300
400
  eng: `Failed to save targets`,
301
401
  cht: `儲存對象數據失敗`,
@@ -385,10 +485,11 @@ let kpLang = {
385
485
  eng: `Has {n} rule(s){nms}`,
386
486
  cht: `使用共 {n} 項對象{nms}`,
387
487
  },
388
- pemiClearPemisFail: {
389
- eng: `Failed to clear existing permissions`,
390
- cht: `清除既有權限數據失敗`,
391
- },
488
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
489
+ // pemiClearPemisFail: {
490
+ // eng: `Failed to clear existing permissions`,
491
+ // cht: `清除既有權限數據失敗`,
492
+ // },
392
493
  pemiSavePemisFail: {
393
494
  eng: `Failed to save permissions`,
394
495
  cht: `儲存權限數據失敗`,
@@ -512,10 +613,11 @@ let kpLang = {
512
613
  eng: `Has {n} permission(s){nms}`,
513
614
  cht: `使用 {n} 項權限{nms}`,
514
615
  },
515
- grupClearGrupsFail: {
516
- eng: `Failed to clear existing permission groups`,
517
- cht: `清除既有權限群組數據失敗`,
518
- },
616
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
617
+ // grupClearGrupsFail: {
618
+ // eng: `Failed to clear existing permission groups`,
619
+ // cht: `清除既有權限群組數據失敗`,
620
+ // },
519
621
  grupSaveGrupsEmpty: {
520
622
  eng: `No user`,
521
623
  cht: `未有變更權限群組資料`,
@@ -636,7 +738,7 @@ let kpLang = {
636
738
  cht: `編輯使用權限群組`,
637
739
  },
638
740
  userEditCgrupsForDisplay: {
639
- eng: `Edit list of user`,
741
+ eng: `Permission groups of user`, //展示版不帶 Edit 動詞(2026-07-10 訂正: 原誤與編輯版同值, 唯讀對話框標題顯示「Edit...」且 e2e 無法以標題區分模式)
640
742
  cht: `展示使用權限群組`,
641
743
  },
642
744
  userEditCgrupsNoUserId: {
@@ -693,10 +795,11 @@ let kpLang = {
693
795
  cht: `刪除勾選權限`,
694
796
  },
695
797
 
696
- allDefaults: {
697
- eng: `All defaults`,
698
- cht: `全部項目預設值`,
699
- },
798
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
799
+ // allDefaults: {
800
+ // eng: `All defaults`,
801
+ // cht: `全部項目預設值`,
802
+ // },
700
803
  show: {
701
804
  eng: `Show`,
702
805
  cht: `顯示`,
@@ -705,34 +808,36 @@ let kpLang = {
705
808
  eng: `Active`,
706
809
  cht: `啟用`,
707
810
  },
708
- showChildren: {
709
- eng: `Show children`,
710
- cht: `所屬顯示`,
711
- },
712
- hideChildren: {
713
- eng: `Hide children`,
714
- cht: `所屬不顯示`,
715
- },
716
- activateChildren: {
717
- eng: `Activate children`,
718
- cht: `所屬啟用`,
719
- },
720
- deactivateChildren: {
721
- eng: `Deactivate children`,
722
- cht: `所屬不啟用`,
723
- },
724
- isUsernameEmpty: {
725
- eng: `Username is empty`,
726
- cht: `使用者名稱不得為空`,
727
- },
728
- failedToSaveUser: {
729
- eng: `Failed to save the user`,
730
- cht: `變更使用者失敗`,
731
- },
732
- successfulToSaveUser: {
733
- eng: `Save the user successfully`,
734
- cht: `變更使用者成功`,
735
- },
811
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
812
+ // showChildren: {
813
+ // eng: `Show children`,
814
+ // cht: `所屬顯示`,
815
+ // },
816
+ // hideChildren: {
817
+ // eng: `Hide children`,
818
+ // cht: `所屬不顯示`,
819
+ // },
820
+ // activateChildren: {
821
+ // eng: `Activate children`,
822
+ // cht: `所屬啟用`,
823
+ // },
824
+ // deactivateChildren: {
825
+ // eng: `Deactivate children`,
826
+ // cht: `所屬不啟用`,
827
+ // },
828
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
829
+ // isUsernameEmpty: {
830
+ // eng: `Username is empty`,
831
+ // cht: `使用者名稱不得為空`,
832
+ // },
833
+ // failedToSaveUser: {
834
+ // eng: `Failed to save the user`,
835
+ // cht: `變更使用者失敗`,
836
+ // },
837
+ // successfulToSaveUser: {
838
+ // eng: `Save the user successfully`,
839
+ // cht: `變更使用者成功`,
840
+ // },
736
841
 
737
842
  userId: {
738
843
  eng: `ID of the created user`,
@@ -751,6 +856,117 @@ let kpLang = {
751
856
  cht: '更新時間',
752
857
  },
753
858
 
859
+ invalidUrl: {
860
+ eng: `Invalid url`,
861
+ cht: `網址無效`,
862
+ },
863
+ invalidTokenTar: {
864
+ eng: `Invalid target token`,
865
+ cht: `目標 token 無效`,
866
+ },
867
+ invalidTokenSelf: {
868
+ eng: `Invalid self token`,
869
+ cht: `自身 token 無效`,
870
+ },
871
+ invalidUserIdTar: {
872
+ eng: `Invalid target user id`,
873
+ cht: `目標使用者 Id 無效`,
874
+ },
875
+ noTokenInUrl: {
876
+ eng: `Missing token in url`,
877
+ cht: `網址缺少 token`,
878
+ },
879
+ noTokenUserIdInUrl: {
880
+ eng: `Missing token or userId in url`,
881
+ cht: `網址缺少 token 或 userId`,
882
+ },
883
+ cannotGetUserByUrl: {
884
+ eng: `Cannot get user by url`,
885
+ cht: `無法由網址取得使用者`,
886
+ },
887
+ cannotGetUserDataByUrl: {
888
+ eng: `Cannot get user data by url`,
889
+ cht: `無法由網址取得使用者資料`,
890
+ },
891
+ noUserDataByUrl: {
892
+ eng: `No user data by url`,
893
+ cht: `該網址無使用者資料`,
894
+ },
895
+ noUserDataAfterConvert: {
896
+ eng: `No user data after permission conversion`,
897
+ cht: `權限轉換後無使用者資料`,
898
+ },
899
+
900
+ mmStaInfor: {
901
+ eng: `Statistics`,
902
+ cht: `統計資訊`,
903
+ },
904
+ staEventTitle: {
905
+ eng: `Event Frequency`,
906
+ cht: `事件發生頻率`,
907
+ },
908
+ //目前無引用,保留供日後使用(見 spec/設計要點與取捨.md ADR-014)
909
+ // staTimeGroup: {
910
+ // eng: `Time grouping`,
911
+ // cht: `時間分組`,
912
+ // },
913
+ staTimeHr: {
914
+ eng: `Hourly`,
915
+ cht: `每小時`,
916
+ },
917
+ staTimeDay: {
918
+ eng: `Daily`,
919
+ cht: `每日`,
920
+ },
921
+ staSelectEvents: {
922
+ eng: `Events`,
923
+ cht: `事件`,
924
+ },
925
+ staSelectAll: {
926
+ eng: `Select all`,
927
+ cht: `全選`,
928
+ },
929
+ staClear: {
930
+ eng: `Clear`,
931
+ cht: `清除`,
932
+ },
933
+ staTotal: {
934
+ eng: `Total`,
935
+ cht: `全部加總`,
936
+ },
937
+ staNoData: {
938
+ eng: `No event data`,
939
+ cht: `尚無事件資料`,
940
+ },
941
+ getDataError: {
942
+ eng: `Failed to load data`,
943
+ cht: `資料載入失敗`,
944
+ },
945
+ staTableTitle: {
946
+ eng: `Event Statistics`,
947
+ cht: `事件統計表`,
948
+ },
949
+ staColEvent: {
950
+ eng: `Event`,
951
+ cht: `事件`,
952
+ },
953
+ staColLast1Day: {
954
+ eng: `Last 1 Day`,
955
+ cht: `最近1日`,
956
+ },
957
+ staColLast8Hour: {
958
+ eng: `Last 8 Hours`,
959
+ cht: `最近8小時`,
960
+ },
961
+ staColLast4Hour: {
962
+ eng: `Last 4 Hours`,
963
+ cht: `最近4小時`,
964
+ },
965
+ staColLast1Hour: {
966
+ eng: `Last 1 Hour`,
967
+ cht: `最近1小時`,
968
+ },
969
+
754
970
  }
755
971
 
756
972