w-web-perm 1.0.47 → 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 +48 -24
- package/src/components/LayoutContentPemis.vue +48 -24
- package/src/components/LayoutContentStaInfor.vue +536 -0
- package/src/components/LayoutContentTargets.vue +48 -24
- package/src/components/LayoutContentUsers.vue +48 -24
- package/src/components/LayoutState.vue +5 -0
- package/src/components/VeCgrups.vue +62 -20
- package/src/components/VeCpemis.vue +62 -20
- package/src/components/VeCrules.vue +58 -16
- package/src/components/VeGrupBlngUsers.vue +77 -32
- package/src/components/VePemiBlngGrups.vue +77 -32
- 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 +15 -7
- package/src/store/mutations.mjs +1 -1
- 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.f1277a07.js +0 -1
- package/dist/js/app.f1277a07.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
|
|
|
@@ -369,12 +371,22 @@ export default {
|
|
|
369
371
|
vo.widthGrupsName = get(vo, 'webInfor.widthGrupsName', '')
|
|
370
372
|
vo.widthGrupsDescription = get(vo, 'webInfor.widthGrupsDescription', '')
|
|
371
373
|
|
|
372
|
-
|
|
374
|
+
//會觸發數據變更再導致opt變更導致觸發rowsChange等事件, 故得要延遲, 供組件偵測初始設定數據初始化之用
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
vo.firstSetting = false
|
|
377
|
+
// console.log('firstSetting', vo.firstSetting)
|
|
378
|
+
}, 1)
|
|
379
|
+
|
|
373
380
|
}
|
|
374
381
|
|
|
375
382
|
},
|
|
376
383
|
computed: {
|
|
377
384
|
|
|
385
|
+
syncState: function() {
|
|
386
|
+
let vo = this
|
|
387
|
+
return get(vo, '$store.state.syncState')
|
|
388
|
+
},
|
|
389
|
+
|
|
378
390
|
webInfor: function() {
|
|
379
391
|
let wi = get(this, `$store.state.webInfor`)
|
|
380
392
|
return wi
|
|
@@ -739,6 +751,11 @@ export default {
|
|
|
739
751
|
// console.log('rowsChange', rs)
|
|
740
752
|
// console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
|
|
741
753
|
|
|
754
|
+
//check
|
|
755
|
+
if (!vo.syncState || vo.firstLoading || vo.firstSetting) {
|
|
756
|
+
return
|
|
757
|
+
}
|
|
758
|
+
|
|
742
759
|
//isModified
|
|
743
760
|
vo.isModified = true
|
|
744
761
|
|
|
@@ -1162,20 +1179,28 @@ export default {
|
|
|
1162
1179
|
|
|
1163
1180
|
},
|
|
1164
1181
|
|
|
1165
|
-
saveGrups: function() {
|
|
1166
|
-
// console.log('method saveGrups')
|
|
1182
|
+
saveGrups: function(msg) {
|
|
1167
1183
|
|
|
1168
1184
|
let vo = this
|
|
1169
1185
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1186
|
+
//第一行立刻釋放按鈕視覺鎖
|
|
1187
|
+
msg.pm.resolve()
|
|
1172
1188
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1189
|
+
//fire-and-forget, 不 await
|
|
1190
|
+
vo.doSaveGrups()
|
|
1175
1191
|
|
|
1176
|
-
|
|
1192
|
+
},
|
|
1193
|
+
|
|
1194
|
+
doSaveGrups: function() {
|
|
1195
|
+
// console.log('method doSaveGrups')
|
|
1196
|
+
|
|
1197
|
+
let vo = this
|
|
1198
|
+
|
|
1199
|
+
async function core() {
|
|
1200
|
+
|
|
1201
|
+
//1) 同步檢測 (在開 loading 之前)
|
|
1177
1202
|
if (isestr(vo.isError)) {
|
|
1178
|
-
vo.$
|
|
1203
|
+
await vo.$dg.showCheckYes(`${vo.isError}`)
|
|
1179
1204
|
return
|
|
1180
1205
|
}
|
|
1181
1206
|
|
|
@@ -1184,35 +1209,34 @@ export default {
|
|
|
1184
1209
|
|
|
1185
1210
|
//check
|
|
1186
1211
|
if (size(rows) === 0) {
|
|
1187
|
-
vo.$
|
|
1212
|
+
await vo.$dg.showCheckYes(`${vo.$t('grupAddEmpty')}`)
|
|
1188
1213
|
return
|
|
1189
1214
|
}
|
|
1190
1215
|
|
|
1191
|
-
//
|
|
1216
|
+
//2) 確定打 API 才開 loading
|
|
1217
|
+
vo.$ui.updateLoading(true)
|
|
1218
|
+
|
|
1219
|
+
//3) updateGrups, 各自 catch + 旗標短路
|
|
1220
|
+
let okSave = false
|
|
1192
1221
|
await vo.$fapi.updateGrups(rows)
|
|
1193
|
-
.
|
|
1194
|
-
|
|
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)}`)
|
|
1195
1226
|
})
|
|
1196
|
-
|
|
1197
|
-
//check
|
|
1198
|
-
if (errTemp !== null) {
|
|
1199
|
-
vo.$alert(`${vo.$t('grupSaveGrupsFail')}: ${errTemp}`, { type: 'error' })
|
|
1200
|
-
return
|
|
1201
|
-
}
|
|
1227
|
+
if (!okSave) return
|
|
1202
1228
|
|
|
1203
1229
|
//isModified
|
|
1204
1230
|
vo.isModified = false
|
|
1205
1231
|
|
|
1206
|
-
//alert
|
|
1207
|
-
vo.$
|
|
1232
|
+
//alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
|
|
1233
|
+
vo.$ui.updateLoading(false)
|
|
1234
|
+
await vo.$dg.showCheckYes(vo.$t('grupSaveGrupsSuccess'), { type: 'success' })
|
|
1208
1235
|
|
|
1209
1236
|
}
|
|
1210
1237
|
|
|
1211
1238
|
//core
|
|
1212
1239
|
core()
|
|
1213
|
-
// .then((res) => {
|
|
1214
|
-
// console.log('then', res)
|
|
1215
|
-
// })
|
|
1216
1240
|
.catch((err) => {
|
|
1217
1241
|
console.log('catch', err)
|
|
1218
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
|
|
|
@@ -369,12 +371,22 @@ export default {
|
|
|
369
371
|
vo.widthPemisName = get(vo, 'webInfor.widthPemisName', '')
|
|
370
372
|
vo.widthPemisDescription = get(vo, 'webInfor.widthPemisDescription', '')
|
|
371
373
|
|
|
372
|
-
|
|
374
|
+
//會觸發數據變更再導致opt變更導致觸發rowsChange等事件, 故得要延遲, 供組件偵測初始設定數據初始化之用
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
vo.firstSetting = false
|
|
377
|
+
// console.log('firstSetting', vo.firstSetting)
|
|
378
|
+
}, 1)
|
|
379
|
+
|
|
373
380
|
}
|
|
374
381
|
|
|
375
382
|
},
|
|
376
383
|
computed: {
|
|
377
384
|
|
|
385
|
+
syncState: function() {
|
|
386
|
+
let vo = this
|
|
387
|
+
return get(vo, '$store.state.syncState')
|
|
388
|
+
},
|
|
389
|
+
|
|
378
390
|
webInfor: function() {
|
|
379
391
|
let wi = get(this, `$store.state.webInfor`)
|
|
380
392
|
return wi
|
|
@@ -739,6 +751,11 @@ export default {
|
|
|
739
751
|
// console.log('rowsChange', rs)
|
|
740
752
|
// console.log('rowsChange cloneDeep(vo.opt.rows)', cloneDeep(vo.opt.rows))
|
|
741
753
|
|
|
754
|
+
//check
|
|
755
|
+
if (!vo.syncState || vo.firstLoading || vo.firstSetting) {
|
|
756
|
+
return
|
|
757
|
+
}
|
|
758
|
+
|
|
742
759
|
//isModified
|
|
743
760
|
vo.isModified = true
|
|
744
761
|
|
|
@@ -1164,20 +1181,28 @@ export default {
|
|
|
1164
1181
|
|
|
1165
1182
|
},
|
|
1166
1183
|
|
|
1167
|
-
savePemis: function() {
|
|
1168
|
-
// console.log('method savePemis')
|
|
1184
|
+
savePemis: function(msg) {
|
|
1169
1185
|
|
|
1170
1186
|
let vo = this
|
|
1171
1187
|
|
|
1172
|
-
|
|
1173
|
-
|
|
1188
|
+
//第一行立刻釋放按鈕視覺鎖
|
|
1189
|
+
msg.pm.resolve()
|
|
1174
1190
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1191
|
+
//fire-and-forget, 不 await
|
|
1192
|
+
vo.doSavePemis()
|
|
1177
1193
|
|
|
1178
|
-
|
|
1194
|
+
},
|
|
1195
|
+
|
|
1196
|
+
doSavePemis: function() {
|
|
1197
|
+
// console.log('method doSavePemis')
|
|
1198
|
+
|
|
1199
|
+
let vo = this
|
|
1200
|
+
|
|
1201
|
+
async function core() {
|
|
1202
|
+
|
|
1203
|
+
//1) 同步檢測 (在開 loading 之前)
|
|
1179
1204
|
if (isestr(vo.isError)) {
|
|
1180
|
-
vo.$
|
|
1205
|
+
await vo.$dg.showCheckYes(`${vo.isError}`)
|
|
1181
1206
|
return
|
|
1182
1207
|
}
|
|
1183
1208
|
|
|
@@ -1186,35 +1211,34 @@ export default {
|
|
|
1186
1211
|
|
|
1187
1212
|
//check
|
|
1188
1213
|
if (size(rows) === 0) {
|
|
1189
|
-
vo.$
|
|
1214
|
+
await vo.$dg.showCheckYes(`${vo.$t('pemiAddEmpty')}`)
|
|
1190
1215
|
return
|
|
1191
1216
|
}
|
|
1192
1217
|
|
|
1193
|
-
//
|
|
1218
|
+
//2) 確定打 API 才開 loading
|
|
1219
|
+
vo.$ui.updateLoading(true)
|
|
1220
|
+
|
|
1221
|
+
//3) updatePemis, 各自 catch + 旗標短路
|
|
1222
|
+
let okSave = false
|
|
1194
1223
|
await vo.$fapi.updatePemis(rows)
|
|
1195
|
-
.
|
|
1196
|
-
|
|
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)}`)
|
|
1197
1228
|
})
|
|
1198
|
-
|
|
1199
|
-
//check
|
|
1200
|
-
if (errTemp !== null) {
|
|
1201
|
-
vo.$alert(`${vo.$t('pemiSavePemisFail')}: ${errTemp}`, { type: 'error' })
|
|
1202
|
-
return
|
|
1203
|
-
}
|
|
1229
|
+
if (!okSave) return
|
|
1204
1230
|
|
|
1205
1231
|
//isModified
|
|
1206
1232
|
vo.isModified = false
|
|
1207
1233
|
|
|
1208
|
-
//alert
|
|
1209
|
-
vo.$
|
|
1234
|
+
//alert(showCheckYes 前關 loading,避免 modal 等待期間 loading 疊在底下)
|
|
1235
|
+
vo.$ui.updateLoading(false)
|
|
1236
|
+
await vo.$dg.showCheckYes(vo.$t('pemiSavePemisSuccess'), { type: 'success' })
|
|
1210
1237
|
|
|
1211
1238
|
}
|
|
1212
1239
|
|
|
1213
1240
|
//core
|
|
1214
1241
|
core()
|
|
1215
|
-
// .then((res) => {
|
|
1216
|
-
// console.log('then', res)
|
|
1217
|
-
// })
|
|
1218
1242
|
.catch((err) => {
|
|
1219
1243
|
console.log('catch', err)
|
|
1220
1244
|
vo.$alert(vo.$t('anUnexpectedErrorOccurred'), { type: 'error' })
|