w-web-perm 1.0.48 → 1.0.49
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.
- package/.github/workflows/ci-test.yml +2 -2
- package/_gh-pages-deploy/.nojekyll +0 -0
- package/_gh-pages-deploy/WWebPerm.html +938 -0
- package/_gh-pages-deploy/WWebPerm.mjs.html +1228 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/_gh-pages-deploy/index.html +84 -0
- package/_gh-pages-deploy/scripts/collapse.js +39 -0
- package/_gh-pages-deploy/scripts/commonNav.js +28 -0
- package/_gh-pages-deploy/scripts/linenumber.js +25 -0
- package/_gh-pages-deploy/scripts/nav.js +12 -0
- package/_gh-pages-deploy/scripts/polyfill.js +4 -0
- package/_gh-pages-deploy/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/_gh-pages-deploy/scripts/prettify/lang-css.js +2 -0
- package/_gh-pages-deploy/scripts/prettify/prettify.js +28 -0
- package/_gh-pages-deploy/scripts/search.js +99 -0
- package/_gh-pages-deploy/styles/jsdoc.css +776 -0
- package/_gh-pages-deploy/styles/prettify.css +80 -0
- package/dist/css/app.d8b16216.css +1 -0
- package/dist/css/{chunk-vendors.f149e124.css → chunk-vendors.2d3ef2ba.css} +1 -1
- package/dist/index.tmp +2 -2
- package/dist/js/app-legacy.fb48310a.js +1 -0
- package/dist/js/app.fb48310a.js +1 -0
- package/dist/js/chunk-vendors-legacy.8fdd4435.js +21 -0
- package/dist/js/chunk-vendors.8fdd4435.js +21 -0
- package/dist/w-web-perm.umd.js +2 -2
- package/dist/w-web-perm.umd.js.map +1 -1
- package/docs/WWebPerm.html +2 -2
- package/docs/WWebPerm.mjs.html +138 -199
- package/docs/index.html +1 -1
- package/package.json +15 -11
- package/public/index.html +2 -2
- package/server/WWebPerm.mjs +137 -198
- package/server/procCore.mjs +169 -0
- package/server/procLang.mjs +197 -0
- package/server/procStaInfor.mjs +118 -0
- package/server/provideTabs.mjs +1 -1
- package/server/srLog.mjs +30 -0
- package/server/staLogs/staEvent.callWorker.mjs +46 -0
- package/server/staLogs/staEvent.mjs +116 -0
- package/server/staLogs/staEvent.shellWorker.mjs +19 -0
- package/server/staLogs/staEventTable.mjs +100 -0
- package/server/staLogs/test_staEvent.mjs +22 -0
- package/settings.json +40 -0
- package/src/components/Common/CheckYes.vue +18 -1
- package/src/components/Layout.vue +1 -1
- package/src/components/LayoutContent.vue +13 -1
- package/src/components/LayoutContentGrups.vue +32 -23
- package/src/components/LayoutContentPemis.vue +32 -23
- package/src/components/LayoutContentStaInfor.vue +536 -0
- package/src/components/LayoutContentTargets.vue +32 -23
- package/src/components/LayoutContentUsers.vue +32 -23
- package/src/components/LayoutState.vue +5 -0
- package/src/components/VeCgrups.vue +12 -3
- package/src/components/VeCpemis.vue +12 -3
- package/src/components/VeCrules.vue +12 -3
- package/src/components/VeGrupBlngUsers.vue +18 -6
- package/src/components/VePemiBlngGrups.vue +18 -6
- package/src/getPerm.mjs +7 -17
- package/src/getPermUserInfor.mjs +8 -18
- package/src/main.js +1 -0
- package/src/plugins/mShare.mjs +8 -13
- package/src/plugins/mUI.mjs +11 -0
- package/srv.mjs +76 -101
- package/tableTags.json +1 -1
- package/db/wperm/grups/data.mdb +0 -0
- package/db/wperm/grups/lock.mdb +0 -0
- package/db/wperm/pemis/data.mdb +0 -0
- package/db/wperm/pemis/lock.mdb +0 -0
- package/db/wperm/targets/data.mdb +0 -0
- package/db/wperm/targets/lock.mdb +0 -0
- package/db/wperm/users/data.mdb +0 -0
- package/db/wperm/users/lock.mdb +0 -0
- package/dist/css/app.30e81bfe.css +0 -1
- package/dist/js/app-legacy.3324392e.js +0 -1
- package/dist/js/app.3324392e.js +0 -1
- package/dist/js/chunk-vendors-legacy.e8703728.js +0 -21
- package/dist/js/chunk-vendors.e8703728.js +0 -21
- package/test/getUserRules.test.mjs +0 -899
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { parentPort } from 'worker_threads'
|
|
2
|
+
import staEvent from './staEvent.mjs'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
parentPort.on('message', async (param) => {
|
|
6
|
+
try {
|
|
7
|
+
let r = await staEvent(param.timeLength, param.timeInterval, param.opt)
|
|
8
|
+
parentPort.postMessage({
|
|
9
|
+
mode: 'done',
|
|
10
|
+
payload: r,
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
parentPort.postMessage({
|
|
15
|
+
mode: 'error',
|
|
16
|
+
payload: err,
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import ot from 'dayjs'
|
|
2
|
+
import get from 'lodash-es/get.js'
|
|
3
|
+
import each from 'lodash-es/each.js'
|
|
4
|
+
import genPm from 'wsemi/src/genPm.mjs'
|
|
5
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
6
|
+
import fsTreeFolder from 'wsemi/src/fsTreeFolder.mjs'
|
|
7
|
+
import fsBuildReadStreamText from 'wsemi/src/fsBuildReadStreamText.mjs'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
//統計各 event 事件於近 1日/8hr/4hr/1hr 各窗內之發生數量(鏡像 staEvent.mjs 的 NDJSON 讀取方式)。
|
|
11
|
+
//巢狀窗:1hr⊂4hr⊂8hr⊂24hr, 各窗各自累計該窗內出現總數。
|
|
12
|
+
//回傳: [{ event, last1Day, last8Hour, last4Hour, last1Hour }, ...], 依 last1Day 由大到小排序。
|
|
13
|
+
async function staEventTable(opt = {}) {
|
|
14
|
+
|
|
15
|
+
//fdLog
|
|
16
|
+
let fdLog = get(opt, 'fdLog')
|
|
17
|
+
if (!isestr(fdLog)) {
|
|
18
|
+
fdLog = './_logs'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//now
|
|
22
|
+
let now = ot()
|
|
23
|
+
|
|
24
|
+
//kp, 各 event 名累計各窗計數
|
|
25
|
+
let kp = {}
|
|
26
|
+
|
|
27
|
+
//vpfs
|
|
28
|
+
let vpfs = fsTreeFolder(fdLog)
|
|
29
|
+
|
|
30
|
+
//逐檔逐行讀取
|
|
31
|
+
for (let vpf of vpfs) {
|
|
32
|
+
|
|
33
|
+
//fp
|
|
34
|
+
let fp = vpf.path
|
|
35
|
+
|
|
36
|
+
//ev
|
|
37
|
+
let ev = fsBuildReadStreamText(fp)
|
|
38
|
+
|
|
39
|
+
//line
|
|
40
|
+
ev.on('line', (line) => {
|
|
41
|
+
try {
|
|
42
|
+
let v = JSON.parse(line)
|
|
43
|
+
let event = v.event
|
|
44
|
+
if (!isestr(event)) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//dh, 距今幾小時(用 dayjs 比較)
|
|
49
|
+
let dh = now.diff(ot(v.time), 'hour')
|
|
50
|
+
if (dh < 0 || dh > 24) {
|
|
51
|
+
return //超過 1日窗或未來時間略過
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//初始化
|
|
55
|
+
if (!kp[event]) {
|
|
56
|
+
kp[event] = { last1Day: 0, last8Hour: 0, last4Hour: 0, last1Hour: 0 }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//巢狀窗各自累計(1hr⊂4hr⊂8hr⊂24hr)
|
|
60
|
+
if (dh <= 24) {
|
|
61
|
+
kp[event].last1Day += 1
|
|
62
|
+
}
|
|
63
|
+
if (dh <= 8) {
|
|
64
|
+
kp[event].last8Hour += 1
|
|
65
|
+
}
|
|
66
|
+
if (dh <= 4) {
|
|
67
|
+
kp[event].last4Hour += 1
|
|
68
|
+
}
|
|
69
|
+
if (dh <= 1) {
|
|
70
|
+
kp[event].last1Hour += 1
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
//await close
|
|
77
|
+
let pm = genPm()
|
|
78
|
+
ev.on('close', () => {
|
|
79
|
+
pm.resolve()
|
|
80
|
+
})
|
|
81
|
+
await pm
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//rs
|
|
86
|
+
let rs = []
|
|
87
|
+
each(kp, (vv, event) => {
|
|
88
|
+
rs.push({
|
|
89
|
+
event,
|
|
90
|
+
...vv,
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
//依 last1Day 由大到小排序
|
|
95
|
+
rs.sort((a, b) => b.last1Day - a.last1Day)
|
|
96
|
+
|
|
97
|
+
return rs
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default staEventTable
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// import staEvent from './staEvent.mjs' //一般版
|
|
2
|
+
import staEvent from './staEvent.callWorker.mjs' //worker 版
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
let rs = await staEvent(7, 'hr')
|
|
6
|
+
console.log(JSON.stringify(rs, null, 2))
|
|
7
|
+
}
|
|
8
|
+
main()
|
|
9
|
+
// [
|
|
10
|
+
// {
|
|
11
|
+
// "time": "2026-06-21T12",
|
|
12
|
+
// "data": {
|
|
13
|
+
// "count": 50,
|
|
14
|
+
// "verifyConn-success": 42,
|
|
15
|
+
// "updatePemis-success": 5,
|
|
16
|
+
// "api/getPerm-success": 3
|
|
17
|
+
// }
|
|
18
|
+
// },
|
|
19
|
+
// ...
|
|
20
|
+
// ]
|
|
21
|
+
|
|
22
|
+
//node server/staLogs/test_staEvent.mjs
|
package/settings.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
|
|
3
|
+
serverPort: 11006,
|
|
4
|
+
subfolder: '', //mperm
|
|
5
|
+
urlRedirect: 'https://www.google.com/', //本機測試時得先編譯, 再瀏覽: http://localhost:11006/
|
|
6
|
+
|
|
7
|
+
showLanguage: 'y', //'n',
|
|
8
|
+
language: 'eng', //'eng', 'cht'
|
|
9
|
+
|
|
10
|
+
showModeEditTargets: 'y', //'n',
|
|
11
|
+
showModeEditPemis: 'y',
|
|
12
|
+
showModeEditGrups: 'y',
|
|
13
|
+
showModeEditUsers: 'y',
|
|
14
|
+
modeEditTargets: 'y', //'n',
|
|
15
|
+
modeEditPemis: 'y',
|
|
16
|
+
modeEditGrups: 'y',
|
|
17
|
+
modeEditUsers: 'y',
|
|
18
|
+
|
|
19
|
+
webName: {
|
|
20
|
+
eng: 'Permission Service',
|
|
21
|
+
cht: '權限管理系統',
|
|
22
|
+
},
|
|
23
|
+
webDescription: {
|
|
24
|
+
eng: 'A web service package for user permissions and management targets.',
|
|
25
|
+
cht: '基於簡易分層架構來給予與設定使用者所需之權限及群組管理功能',
|
|
26
|
+
},
|
|
27
|
+
webLogo: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjQ4IiB3aWR0aD0iNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTQ4IDBIMHY0OGg0OFYwWiIgZmlsbD0iI2ZmZiIgZmlsbC1vcGFjaXR5PSIuMDEiLz48cGF0aCBkPSJNMzcuODU2IDIwdjhNMjcuNDY0IDM4bDMuNDY0LTIgMy40NjQtMk0yMC41MzYgMzhsLTMuNDY1LTItMy40NjQtMk0xMC4xNDQgMjB2OE0xMy42MDcgMTRsMy40NjUtMiAzLjQ2NC0yTTI3LjQ2NCAxMGwzLjQ2NCAyIDMuNDY0IDIiIHN0cm9rZT0iI0ZGOTgwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiLz48cGF0aCBkPSJNMjQgNDRhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4Wk0yNCAxMmE0IDQgMCAxIDAgMC04IDQgNCAwIDAgMCAwIDhaTTI0IDI4YTQgNCAwIDEgMCAwLTggNCA0IDAgMCAwIDAgOFpNMzggMjBhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4Wk0zOCAzNmE0IDQgMCAxIDAgMC04IDQgNCAwIDAgMCAwIDhaTTEwIDIwYTQgNCAwIDEgMCAwLTggNCA0IDAgMCAwIDAgOFpNMTAgMzZhNCA0IDAgMSAwIDAtOCA0IDQgMCAwIDAgMCA4WiIgZmlsbD0iI0ZGRTBCMiIgc3Ryb2tlPSIjRkY5ODAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPg==',
|
|
28
|
+
|
|
29
|
+
// kpLangExt: {
|
|
30
|
+
// mmTargets: {
|
|
31
|
+
// eng: `Current features list`,
|
|
32
|
+
// cht: `現有功能清單`,
|
|
33
|
+
// },
|
|
34
|
+
// mmTargetsMsg: {
|
|
35
|
+
// eng: `Features generally refer to entities such as pages, data, etc., and can also include features or services.`,
|
|
36
|
+
// cht: `現有功能泛指實體的頁面、數據等,亦可為的功能或服務。`,
|
|
37
|
+
// },
|
|
38
|
+
// },
|
|
39
|
+
|
|
40
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
:show.sync="bShow"
|
|
4
4
|
:title="$t('systemMessage')"
|
|
5
5
|
:content="content"
|
|
6
|
+
:contentIcon="contentIcon"
|
|
7
|
+
:contentIconColor="contentIconColor"
|
|
6
8
|
:_contentColor="'white'"
|
|
7
9
|
:_contentIconColor="'white'"
|
|
8
10
|
:_contentBackgroundColor="'orange lighten-5'"
|
|
@@ -15,6 +17,7 @@
|
|
|
15
17
|
|
|
16
18
|
<script>
|
|
17
19
|
import Vue from 'vue'
|
|
20
|
+
import { mdiAlert, mdiCheckCircle } from '@mdi/js'
|
|
18
21
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
19
22
|
import WConfirm from 'w-component-vue/src/components/WConfirm.vue'
|
|
20
23
|
|
|
@@ -32,6 +35,10 @@ export default {
|
|
|
32
35
|
|
|
33
36
|
content: '',
|
|
34
37
|
|
|
38
|
+
//content icon(依 type 切換:success=綠勾,其餘=驚嘆號)
|
|
39
|
+
contentIcon: mdiAlert,
|
|
40
|
+
contentIconColor: '#D81B60',
|
|
41
|
+
|
|
35
42
|
}
|
|
36
43
|
},
|
|
37
44
|
mounted: function() {
|
|
@@ -47,7 +54,7 @@ export default {
|
|
|
47
54
|
},
|
|
48
55
|
methods: {
|
|
49
56
|
|
|
50
|
-
show: function (content) {
|
|
57
|
+
show: function (content, opt = {}) {
|
|
51
58
|
//console.log('methods show', content)
|
|
52
59
|
|
|
53
60
|
let vo = this
|
|
@@ -58,6 +65,16 @@ export default {
|
|
|
58
65
|
//save
|
|
59
66
|
vo.content = content
|
|
60
67
|
|
|
68
|
+
//content icon:type='success' 顯示綠勾,其餘維持驚嘆號
|
|
69
|
+
if (opt && opt.type === 'success') {
|
|
70
|
+
vo.contentIcon = mdiCheckCircle
|
|
71
|
+
vo.contentIconColor = '#2E7D32'
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
vo.contentIcon = mdiAlert
|
|
75
|
+
vo.contentIconColor = '#D81B60'
|
|
76
|
+
}
|
|
77
|
+
|
|
61
78
|
//show
|
|
62
79
|
vo.bShow = true
|
|
63
80
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div style="height:100svh; background:#f5f5f5;">
|
|
3
3
|
|
|
4
4
|
<!-- menu top, 因窄版導致名稱換行故須使用overflow-y:hidden -->
|
|
5
|
-
<div :style="`height:${heightToolbar}px; overflow-y:hidden; padding:0px 10px; background:#fff; border-bottom:1px solid #ccc; display:flex; align-items:center;`">
|
|
5
|
+
<div data-fmid="app-topbar" :style="`height:${heightToolbar}px; box-sizing:border-box; overflow-y:hidden; padding:0px 10px; background:#fff; border-bottom:1px solid #ccc; display:flex; align-items:center;`">
|
|
6
6
|
|
|
7
7
|
<div style="padding-left:5px; white-space:nowrap">
|
|
8
8
|
<div style="display:flex; align-items:center;">
|
|
@@ -89,6 +89,11 @@
|
|
|
89
89
|
v-if="menuKey==='mmUsers'"
|
|
90
90
|
></LayoutContentUsers>
|
|
91
91
|
|
|
92
|
+
<LayoutContentStaInfor
|
|
93
|
+
:drawer="drawer"
|
|
94
|
+
v-if="menuKey==='mmStaInfor'"
|
|
95
|
+
></LayoutContentStaInfor>
|
|
96
|
+
|
|
92
97
|
</template>
|
|
93
98
|
|
|
94
99
|
<div
|
|
@@ -129,7 +134,7 @@
|
|
|
129
134
|
</template>
|
|
130
135
|
|
|
131
136
|
<script>
|
|
132
|
-
import { mdiArrowLeftBoldHexagonOutline, mdiArrowRightBoldHexagonOutline, mdiGamepadCircle, mdiStackOverflow, mdiSelectGroup, mdiAccountGroupOutline } from '@mdi/js/mdi.js'
|
|
137
|
+
import { mdiArrowLeftBoldHexagonOutline, mdiArrowRightBoldHexagonOutline, mdiGamepadCircle, mdiStackOverflow, mdiSelectGroup, mdiAccountGroupOutline, mdiChartBoxOutline } from '@mdi/js/mdi.js'
|
|
133
138
|
import get from 'lodash-es/get.js'
|
|
134
139
|
import find from 'lodash-es/find.js'
|
|
135
140
|
import WDrawer from 'w-component-vue/src/components/WDrawer.vue'
|
|
@@ -139,6 +144,7 @@ import LayoutContentTargets from './LayoutContentTargets.vue'
|
|
|
139
144
|
import LayoutContentPemis from './LayoutContentPemis.vue'
|
|
140
145
|
import LayoutContentGrups from './LayoutContentGrups.vue'
|
|
141
146
|
import LayoutContentUsers from './LayoutContentUsers.vue'
|
|
147
|
+
import LayoutContentStaInfor from './LayoutContentStaInfor.vue'
|
|
142
148
|
|
|
143
149
|
|
|
144
150
|
export default {
|
|
@@ -150,6 +156,7 @@ export default {
|
|
|
150
156
|
LayoutContentPemis,
|
|
151
157
|
LayoutContentGrups,
|
|
152
158
|
LayoutContentUsers,
|
|
159
|
+
LayoutContentStaInfor,
|
|
153
160
|
},
|
|
154
161
|
props: {
|
|
155
162
|
},
|
|
@@ -200,6 +207,11 @@ export default {
|
|
|
200
207
|
text: vo.$t('mmUsers'),
|
|
201
208
|
icon: mdiAccountGroupOutline,
|
|
202
209
|
},
|
|
210
|
+
{
|
|
211
|
+
key: 'mmStaInfor',
|
|
212
|
+
text: vo.$t('mmStaInfor'),
|
|
213
|
+
icon: mdiChartBoxOutline,
|
|
214
|
+
},
|
|
203
215
|
]
|
|
204
216
|
return ms
|
|
205
217
|
},
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
|
|
40
40
|
<!-- 功能區 -->
|
|
41
41
|
<div
|
|
42
|
+
data-fmid="grups-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="saveGrups"
|
|
189
191
|
></WButtonCircle>
|
|
190
192
|
|
|
@@ -1177,20 +1179,28 @@ export default {
|
|
|
1177
1179
|
|
|
1178
1180
|
},
|
|
1179
1181
|
|
|
1180
|
-
saveGrups: function() {
|
|
1181
|
-
// console.log('method saveGrups')
|
|
1182
|
+
saveGrups: function(msg) {
|
|
1182
1183
|
|
|
1183
1184
|
let vo = this
|
|
1184
1185
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1186
|
+
//第一行立刻釋放按鈕視覺鎖
|
|
1187
|
+
msg.pm.resolve()
|
|
1187
1188
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1189
|
+
//fire-and-forget, 不 await
|
|
1190
|
+
vo.doSaveGrups()
|
|
1190
1191
|
|
|
1191
|
-
|
|
1192
|
+
},
|
|
1193
|
+
|
|
1194
|
+
doSaveGrups: function() {
|
|
1195
|
+
// console.log('method doSaveGrups')
|
|
1196
|
+
|
|
1197
|
+
let vo = this
|
|
1198
|
+
|
|
1199
|
+
async function core() {
|
|
1200
|
+
|
|
1201
|
+
//1) 同步檢測 (在開 loading 之前)
|
|
1192
1202
|
if (isestr(vo.isError)) {
|
|
1193
|
-
vo.$
|
|
1203
|
+
await vo.$dg.showCheckYes(`${vo.isError}`)
|
|
1194
1204
|
return
|
|
1195
1205
|
}
|
|
1196
1206
|
|
|
@@ -1199,35 +1209,34 @@ export default {
|
|
|
1199
1209
|
|
|
1200
1210
|
//check
|
|
1201
1211
|
if (size(rows) === 0) {
|
|
1202
|
-
vo.$
|
|
1212
|
+
await vo.$dg.showCheckYes(`${vo.$t('grupAddEmpty')}`)
|
|
1203
1213
|
return
|
|
1204
1214
|
}
|
|
1205
1215
|
|
|
1206
|
-
//
|
|
1216
|
+
//2) 確定打 API 才開 loading
|
|
1217
|
+
vo.$ui.updateLoading(true)
|
|
1218
|
+
|
|
1219
|
+
//3) updateGrups, 各自 catch + 旗標短路
|
|
1220
|
+
let okSave = false
|
|
1207
1221
|
await vo.$fapi.updateGrups(rows)
|
|
1208
|
-
.
|
|
1209
|
-
|
|
1222
|
+
.then(() => { okSave = true })
|
|
1223
|
+
.catch(async (err) => {
|
|
1224
|
+
vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
|
|
1225
|
+
await vo.$dg.showCheckYes(`${vo.$t('grupSaveGrupsFail')}: ${vo.$tErr(err)}`)
|
|
1210
1226
|
})
|
|
1211
|
-
|
|
1212
|
-
//check
|
|
1213
|
-
if (errTemp !== null) {
|
|
1214
|
-
vo.$alert(`${vo.$t('grupSaveGrupsFail')}: ${errTemp}`, { type: 'error' })
|
|
1215
|
-
return
|
|
1216
|
-
}
|
|
1227
|
+
if (!okSave) return
|
|
1217
1228
|
|
|
1218
1229
|
//isModified
|
|
1219
1230
|
vo.isModified = false
|
|
1220
1231
|
|
|
1221
|
-
//alert
|
|
1222
|
-
vo.$
|
|
1232
|
+
//alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
|
|
1233
|
+
vo.$ui.updateLoading(false)
|
|
1234
|
+
await vo.$dg.showCheckYes(vo.$t('grupSaveGrupsSuccess'), { type: 'success' })
|
|
1223
1235
|
|
|
1224
1236
|
}
|
|
1225
1237
|
|
|
1226
1238
|
//core
|
|
1227
1239
|
core()
|
|
1228
|
-
// .then((res) => {
|
|
1229
|
-
// console.log('then', res)
|
|
1230
|
-
// })
|
|
1231
1240
|
.catch((err) => {
|
|
1232
1241
|
console.log('catch', err)
|
|
1233
1242
|
vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' })
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
|
|
40
40
|
<!-- 功能區 -->
|
|
41
41
|
<div
|
|
42
|
+
data-fmid="pemis-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="savePemis"
|
|
189
191
|
></WButtonCircle>
|
|
190
192
|
|
|
@@ -1179,20 +1181,28 @@ export default {
|
|
|
1179
1181
|
|
|
1180
1182
|
},
|
|
1181
1183
|
|
|
1182
|
-
savePemis: function() {
|
|
1183
|
-
// console.log('method savePemis')
|
|
1184
|
+
savePemis: function(msg) {
|
|
1184
1185
|
|
|
1185
1186
|
let vo = this
|
|
1186
1187
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1188
|
+
//第一行立刻釋放按鈕視覺鎖
|
|
1189
|
+
msg.pm.resolve()
|
|
1189
1190
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1191
|
+
//fire-and-forget, 不 await
|
|
1192
|
+
vo.doSavePemis()
|
|
1192
1193
|
|
|
1193
|
-
|
|
1194
|
+
},
|
|
1195
|
+
|
|
1196
|
+
doSavePemis: function() {
|
|
1197
|
+
// console.log('method doSavePemis')
|
|
1198
|
+
|
|
1199
|
+
let vo = this
|
|
1200
|
+
|
|
1201
|
+
async function core() {
|
|
1202
|
+
|
|
1203
|
+
//1) 同步檢測 (在開 loading 之前)
|
|
1194
1204
|
if (isestr(vo.isError)) {
|
|
1195
|
-
vo.$
|
|
1205
|
+
await vo.$dg.showCheckYes(`${vo.isError}`)
|
|
1196
1206
|
return
|
|
1197
1207
|
}
|
|
1198
1208
|
|
|
@@ -1201,35 +1211,34 @@ export default {
|
|
|
1201
1211
|
|
|
1202
1212
|
//check
|
|
1203
1213
|
if (size(rows) === 0) {
|
|
1204
|
-
vo.$
|
|
1214
|
+
await vo.$dg.showCheckYes(`${vo.$t('pemiAddEmpty')}`)
|
|
1205
1215
|
return
|
|
1206
1216
|
}
|
|
1207
1217
|
|
|
1208
|
-
//
|
|
1218
|
+
//2) 確定打 API 才開 loading
|
|
1219
|
+
vo.$ui.updateLoading(true)
|
|
1220
|
+
|
|
1221
|
+
//3) updatePemis, 各自 catch + 旗標短路
|
|
1222
|
+
let okSave = false
|
|
1209
1223
|
await vo.$fapi.updatePemis(rows)
|
|
1210
|
-
.
|
|
1211
|
-
|
|
1224
|
+
.then(() => { okSave = true })
|
|
1225
|
+
.catch(async (err) => {
|
|
1226
|
+
vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
|
|
1227
|
+
await vo.$dg.showCheckYes(`${vo.$t('pemiSavePemisFail')}: ${vo.$tErr(err)}`)
|
|
1212
1228
|
})
|
|
1213
|
-
|
|
1214
|
-
//check
|
|
1215
|
-
if (errTemp !== null) {
|
|
1216
|
-
vo.$alert(`${vo.$t('pemiSavePemisFail')}: ${errTemp}`, { type: 'error' })
|
|
1217
|
-
return
|
|
1218
|
-
}
|
|
1229
|
+
if (!okSave) return
|
|
1219
1230
|
|
|
1220
1231
|
//isModified
|
|
1221
1232
|
vo.isModified = false
|
|
1222
1233
|
|
|
1223
|
-
//alert
|
|
1224
|
-
vo.$
|
|
1234
|
+
//alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
|
|
1235
|
+
vo.$ui.updateLoading(false)
|
|
1236
|
+
await vo.$dg.showCheckYes(vo.$t('pemiSavePemisSuccess'), { type: 'success' })
|
|
1225
1237
|
|
|
1226
1238
|
}
|
|
1227
1239
|
|
|
1228
1240
|
//core
|
|
1229
1241
|
core()
|
|
1230
|
-
// .then((res) => {
|
|
1231
|
-
// console.log('then', res)
|
|
1232
|
-
// })
|
|
1233
1242
|
.catch((err) => {
|
|
1234
1243
|
console.log('catch', err)
|
|
1235
1244
|
vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' })
|