w-web-api 1.0.52 → 1.0.55
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/README.md +1 -1
- package/dist/css/app.cad4a1ca.css +1 -0
- package/dist/index.tmp +4 -2
- package/dist/js/app-legacy.7687b23b.js +1 -0
- package/dist/js/app.7687b23b.js +1 -0
- package/dist/js/chunk-vendors-legacy.4c27cf51.js +15 -0
- package/dist/js/chunk-vendors.4c27cf51.js +15 -0
- package/dist/w-web-api.umd.js +2 -2
- package/dist/w-web-api.umd.js.map +1 -1
- package/docs/WWebApi.html +2 -2
- package/docs/index.html +1 -1
- package/docs/{WWebApi.mjs.html → server_WWebApi.mjs.html} +113 -66
- package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
- package/g.getSettings.mjs +3 -0
- package/logs/2026-06-19T16.log +6 -0
- package/logs/2026-06-20T11.log +4 -0
- package/logs/2026-06-20T14.log +2 -0
- package/logs/2026-06-21T20.log +1 -0
- package/logs/2026-06-21T21.log +4 -0
- package/logs/2026-06-22T07.log +12 -0
- package/logs/2026-06-22T08.log +808 -0
- package/logs/2026-06-22T09.log +104 -0
- package/logs/2026-06-22T10.log +26 -0
- package/logs/2026-06-22T11.log +860 -0
- package/logs/2026-06-22T12.log +430 -0
- package/logs/2026-06-22T23.log +1547 -0
- package/logs/2026-06-23T00.log +473 -0
- package/logs/2026-06-23T08.log +231 -0
- package/logs/2026-06-23T09.log +179 -0
- package/logs/2026-07-01T11.log +488 -0
- package/logs/2026-07-09T22.log +370 -0
- package/logs/2026-07-09T23.log +370 -0
- package/logs/2026-07-10T12.log +284 -0
- package/logs/2026-07-10T13.log +777 -0
- package/logs/2026-07-11T17.log +2 -0
- package/package.json +20 -15
- package/public/index.html +9 -2
- package/server/WWebApi.mjs +110 -63
- package/server/procApis.mjs +62 -0
- package/server/procLang.mjs +372 -66
- package/server/procProxy.mjs +120 -0
- package/server/srLog.mjs +30 -0
- package/server/staLogs/filterVpfsByWindow.mjs +27 -0
- package/server/staLogs/staEvent.mjs +131 -0
- package/server/staLogs/test_staEvent.mjs +198 -0
- package/settings.json +18 -0
- package/src/App.vue +11 -7
- package/src/assets/scalar-ui.css +113 -0
- package/src/components/Common/CheckYes.vue +102 -0
- package/src/components/Common/CheckYesNo.vue +115 -0
- package/src/components/Common/LoadingWinBar.vue +114 -0
- package/src/components/Layout.vue +8 -26
- package/src/components/LayoutContent.vue +299 -350
- package/src/components/LayoutContentEdit.vue +577 -0
- package/src/components/LayoutContentStats.vue +485 -0
- package/src/components/LayoutContentTest.vue +781 -0
- package/src/components/MdPanel.vue +80 -58
- package/src/main.js +11 -8
- package/src/plugins/mUI.mjs +19 -39
- package/src/schema/tables/apis.mjs +30 -0
- package/src/store/mutations.mjs +0 -14
- package/src/store/types.mjs +0 -3
- package/srv.mjs +50 -20
- package/tableTags.json +1 -1
- package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +246 -0
- package/.github/workflows/ci-test.yml +0 -24
- package/.vscode/launch.json +0 -18
- package/db/wapis/apis/data.mdb +0 -0
- package/db/wapis/apis/lock.mdb +0 -0
- package/dist/css/app.b5cf2ef5.css +0 -1
- package/dist/js/app-legacy.927b5679.js +0 -1
- package/dist/js/app.927b5679.js +0 -1
- package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
- package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
- package/src/plugins/mDataSelectorSchema.mjs +0 -30
- package/src/plugins/mShare.mjs +0 -44
- package/tableTags-web-api.json +0 -1
- package/test/all.test.mjs +0 -10
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script>
|
|
8
|
-
// import get from 'lodash-es/get.js'
|
|
9
|
-
// import find from 'lodash-es/find.js'
|
|
10
|
-
// import each from 'lodash-es/each.js'
|
|
11
|
-
// import map from 'lodash-es/map.js'
|
|
12
|
-
// import size from 'lodash-es/size.js'
|
|
13
|
-
// import sortBy from 'lodash-es/sortBy.js'
|
|
14
|
-
// import isNumber from 'lodash-es/isNumber.js'
|
|
15
|
-
// import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
8
|
+
// import get from 'lodash-es/get.js'
|
|
9
|
+
// import find from 'lodash-es/find.js'
|
|
10
|
+
// import each from 'lodash-es/each.js'
|
|
11
|
+
// import map from 'lodash-es/map.js'
|
|
12
|
+
// import size from 'lodash-es/size.js'
|
|
13
|
+
// import sortBy from 'lodash-es/sortBy.js'
|
|
14
|
+
// import isNumber from 'lodash-es/isNumber.js'
|
|
15
|
+
// import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
16
16
|
// import sep from 'wsemi/src/sep.mjs'
|
|
17
17
|
// import isobj from 'wsemi/src/isobj.mjs'
|
|
18
18
|
// import iseobj from 'wsemi/src/iseobj.mjs'
|
|
@@ -73,80 +73,102 @@ export default {
|
|
|
73
73
|
</script>
|
|
74
74
|
|
|
75
75
|
<style scoped>
|
|
76
|
+
/* Scalar 風格 markdown 渲染:無外框、細列分隔、等寬欄、名稱欄加粗、標題退場感 */
|
|
77
|
+
.md {
|
|
78
|
+
font-size: 13px;
|
|
79
|
+
color: var(--c-1, #1b1b1b);
|
|
80
|
+
}
|
|
76
81
|
|
|
77
82
|
.md >>> table {
|
|
78
83
|
border-collapse: collapse;
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
width: 100%;
|
|
85
|
+
font-size: 13px;
|
|
86
|
+
margin: 2px 0 8px;
|
|
81
87
|
word-break: initial;
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
.md >>> tr {
|
|
85
|
-
margin: 0;
|
|
86
|
-
padding: 0;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
90
|
.md >>> table tr th {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
text-align: left;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
font-size: 11.5px;
|
|
94
|
+
letter-spacing: .03em;
|
|
95
|
+
color: var(--c-2, #6b7280);
|
|
96
|
+
background: transparent;
|
|
97
|
+
border: none;
|
|
98
|
+
border-bottom: 1px solid var(--border, #e6e8ec);
|
|
94
99
|
margin: 0;
|
|
95
|
-
padding:
|
|
100
|
+
padding: 8px 18px 8px 0;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
.md >>> table tr td {
|
|
99
|
-
border:
|
|
104
|
+
border: none;
|
|
105
|
+
border-bottom: 1px solid var(--border-soft, #eef0f3);
|
|
106
|
+
color: var(--c-1, #1b1b1b);
|
|
107
|
+
font-family: var(--font-code, ui-monospace, Menlo, Consolas, monospace);
|
|
108
|
+
font-size: 12.5px;
|
|
109
|
+
vertical-align: top;
|
|
100
110
|
margin: 0;
|
|
101
|
-
padding:
|
|
111
|
+
padding: 8px 18px 8px 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.md >>> table tbody tr:last-child td {
|
|
115
|
+
border-bottom: none;
|
|
102
116
|
}
|
|
103
117
|
|
|
104
|
-
.md >>>
|
|
105
|
-
font-weight:
|
|
106
|
-
|
|
107
|
-
line-height: 1.2rem;
|
|
108
|
-
margin-top: 0.5rem;
|
|
109
|
-
margin-bottom: 0.5rem;
|
|
118
|
+
.md >>> table tr td:first-child {
|
|
119
|
+
font-weight: 600;
|
|
120
|
+
color: var(--c-1, #1b1b1b);
|
|
110
121
|
}
|
|
111
122
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
line-height: 1.1rem;
|
|
116
|
-
margin-top: 0.5rem;
|
|
117
|
-
margin-bottom: 0.5rem;
|
|
123
|
+
/* 對齊 mockup:型別欄(第2欄)綠字、範例欄(第3欄)灰字 */
|
|
124
|
+
.md >>> table tr td:nth-child(2) {
|
|
125
|
+
color: var(--m-post, #069061);
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
.md >>>
|
|
121
|
-
|
|
122
|
-
font-size: 1rem;
|
|
123
|
-
line-height: 1rem;
|
|
124
|
-
margin-top: 0.5rem;
|
|
125
|
-
margin-bottom: 0.5rem;
|
|
128
|
+
.md >>> table tr td:nth-child(3) {
|
|
129
|
+
color: var(--c-2, #6b7280);
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
.md >>>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
.md >>> h1,
|
|
133
|
+
.md >>> h2,
|
|
134
|
+
.md >>> h3,
|
|
135
|
+
.md >>> h4,
|
|
136
|
+
.md >>> h5,
|
|
137
|
+
.md >>> h6 {
|
|
138
|
+
font-weight: 600;
|
|
139
|
+
font-size: 13px;
|
|
140
|
+
line-height: 1.4;
|
|
141
|
+
color: var(--c-2, #6b7280);
|
|
142
|
+
margin: 8px 0 6px;
|
|
134
143
|
}
|
|
135
144
|
|
|
136
|
-
.md >>>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
margin-top: 0.5rem;
|
|
141
|
-
margin-bottom: 0.5rem;
|
|
145
|
+
.md >>> p {
|
|
146
|
+
color: var(--c-2, #6b7280);
|
|
147
|
+
line-height: 1.6;
|
|
148
|
+
margin: 4px 0;
|
|
142
149
|
}
|
|
143
150
|
|
|
144
|
-
.md >>>
|
|
145
|
-
font-
|
|
146
|
-
font-size:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
.md >>> code {
|
|
152
|
+
font-family: var(--font-code, ui-monospace, Menlo, Consolas, monospace);
|
|
153
|
+
font-size: 12px;
|
|
154
|
+
background: var(--bg-3, #eceef1);
|
|
155
|
+
border-radius: 4px;
|
|
156
|
+
padding: 1px 5px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.md >>> pre {
|
|
160
|
+
font-family: var(--font-code, ui-monospace, Menlo, Consolas, monospace);
|
|
161
|
+
font-size: 12px;
|
|
162
|
+
background: var(--bg-2, #f7f8fa);
|
|
163
|
+
border: 1px solid var(--border, #e6e8ec);
|
|
164
|
+
border-radius: 8px;
|
|
165
|
+
padding: 12px 14px;
|
|
166
|
+
overflow: auto;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.md >>> pre code {
|
|
170
|
+
background: transparent;
|
|
171
|
+
padding: 0;
|
|
150
172
|
}
|
|
151
173
|
|
|
152
174
|
</style>
|
package/src/main.js
CHANGED
|
@@ -4,6 +4,7 @@ import get from 'lodash-es/get.js'
|
|
|
4
4
|
// import 'regenerator-runtime/runtime'
|
|
5
5
|
// import 'intersection-observer' //需供Vuetify的Intersection Observer, 專案內有使用v-intersect才需引入, 而w-component-vue沒用v-intersect
|
|
6
6
|
import Vue from 'vue'
|
|
7
|
+
import './assets/scalar-ui.css'
|
|
7
8
|
import WServHapiClient from 'w-serv-hapi/src/WServHapiClient.mjs'
|
|
8
9
|
import WAlert from 'w-component-vue/src/components/WAlert.mjs'
|
|
9
10
|
import domMutation from 'w-component-vue/src/js/domMutation.mjs'
|
|
@@ -12,8 +13,6 @@ import domDragDrop from 'w-component-vue/src/js/domDragDrop.mjs'
|
|
|
12
13
|
import App from './App.vue'
|
|
13
14
|
import store from './store/index.mjs'
|
|
14
15
|
import ui from './plugins/mUI.mjs'
|
|
15
|
-
import mDataSelectorSchema from './plugins/mDataSelectorSchema.mjs'
|
|
16
|
-
import * as s from './plugins/mShare.mjs'
|
|
17
16
|
import ds from './schema/index.mjs'
|
|
18
17
|
// console.log('globalState', globalState)
|
|
19
18
|
// console.log('ds', ds)
|
|
@@ -31,14 +30,16 @@ Vue.prototype.$alert = function() {
|
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
//dssm
|
|
35
|
-
let dssm = mDataSelectorSchema(ds)
|
|
36
|
-
|
|
37
33
|
//prototype
|
|
38
34
|
Vue.prototype.$ui = ui
|
|
39
35
|
Vue.prototype.$t = ui.getKpText
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
//$transErr:後端 reject 之 err-key → 依當前 lang 反查顯示文字。
|
|
37
|
+
//非字串或查無對應 key(getKpText 查不到會原樣回 key)則 fallback 'anUnexpectedErrorOccurred',避免顯示生 key。
|
|
38
|
+
Vue.prototype.$transErr = (err) => {
|
|
39
|
+
let key = (typeof err === 'string' && err) ? err : 'anUnexpectedErrorOccurred'
|
|
40
|
+
let msg = ui.getKpText(key)
|
|
41
|
+
return (msg && msg !== key) ? msg : ui.getKpText('anUnexpectedErrorOccurred')
|
|
42
|
+
}
|
|
42
43
|
Vue.prototype.$ds = ds
|
|
43
44
|
Vue.prototype.$dg = {}
|
|
44
45
|
|
|
@@ -79,7 +80,9 @@ WServHapiClient({
|
|
|
79
80
|
|
|
80
81
|
})
|
|
81
82
|
.catch((err) => {
|
|
82
|
-
console.log(err)
|
|
83
|
+
console.log('getWebInfor failed', err)
|
|
84
|
+
//getWebInfor 失敗時導向連線錯誤態,避免 ready(需 webInfor) 永假而卡在「已登入」轉圈無回饋
|
|
85
|
+
ui.updateConnState('csErrConn')
|
|
83
86
|
})
|
|
84
87
|
|
|
85
88
|
},
|
package/src/plugins/mUI.mjs
CHANGED
|
@@ -1,47 +1,12 @@
|
|
|
1
1
|
import Vue from 'vue'
|
|
2
|
-
import min from 'lodash-es/min.js'
|
|
3
|
-
import size from 'lodash-es/size.js'
|
|
4
|
-
import take from 'lodash-es/take.js'
|
|
5
|
-
import isEqual from 'lodash-es/isEqual.js'
|
|
6
|
-
import uniq from 'lodash-es/uniq.js'
|
|
7
|
-
import set from 'lodash-es/set.js'
|
|
8
2
|
import get from 'lodash-es/get.js'
|
|
9
3
|
import each from 'lodash-es/each.js'
|
|
10
|
-
import map from 'lodash-es/map.js'
|
|
11
|
-
import filter from 'lodash-es/filter.js'
|
|
12
|
-
import last from 'lodash-es/last.js'
|
|
13
|
-
import split from 'lodash-es/split.js'
|
|
14
|
-
import join from 'lodash-es/join.js'
|
|
15
|
-
import drop from 'lodash-es/drop.js'
|
|
16
|
-
import dropRight from 'lodash-es/dropRight.js'
|
|
17
|
-
import groupBy from 'lodash-es/groupBy.js'
|
|
18
|
-
import sortBy from 'lodash-es/sortBy.js'
|
|
19
4
|
import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
20
|
-
import cint from 'wsemi/src/cint.mjs'
|
|
21
5
|
import delay from 'wsemi/src/delay.mjs'
|
|
22
|
-
import isarr from 'wsemi/src/isarr.mjs'
|
|
23
6
|
import isestr from 'wsemi/src/isestr.mjs'
|
|
24
7
|
import isfun from 'wsemi/src/isfun.mjs'
|
|
25
8
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
26
|
-
import isearr from 'wsemi/src/isearr.mjs'
|
|
27
|
-
import isEle from 'wsemi/src/isEle.mjs'
|
|
28
|
-
import strleft from 'wsemi/src/strleft.mjs'
|
|
29
|
-
import strdelleft from 'wsemi/src/strdelleft.mjs'
|
|
30
|
-
import sep from 'wsemi/src/sep.mjs'
|
|
31
|
-
import aes2str from 'wsemi/src/aes2str.mjs'
|
|
32
|
-
import str2aes from 'wsemi/src/str2aes.mjs'
|
|
33
|
-
import haskey from 'wsemi/src/haskey.mjs'
|
|
34
|
-
import genPm from 'wsemi/src/genPm.mjs'
|
|
35
|
-
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
36
9
|
import waitFun from 'wsemi/src/waitFun.mjs'
|
|
37
|
-
import browserView from 'wsemi/src/browserView.mjs'
|
|
38
|
-
import arrHas from 'wsemi/src/arrHas.mjs'
|
|
39
|
-
import arrSort from 'wsemi/src/arrSort.mjs'
|
|
40
|
-
import arrInsert from 'wsemi/src/arrInsert.mjs'
|
|
41
|
-
import replace from 'wsemi/src/replace.mjs'
|
|
42
|
-
import timemsTZ2past from 'wsemi/src/timemsTZ2past.mjs'
|
|
43
|
-
import convertToTree from 'wsemi/src/convertToTree.mjs'
|
|
44
|
-
// import WUiDwload from 'w-ui-dwload/src/WUiDwload.mjs'
|
|
45
10
|
|
|
46
11
|
|
|
47
12
|
let kpFallback = {
|
|
@@ -132,16 +97,31 @@ function validLang(lang) {
|
|
|
132
97
|
function getLang() {
|
|
133
98
|
let lang = ''
|
|
134
99
|
|
|
135
|
-
//from
|
|
100
|
+
//from URL ?lang=(最高優先;供「以指定語系載入初始畫面」用,如分享連結 /?lang=cht,對齊 w-web-sso getLang)
|
|
101
|
+
if (!isestr(lang)) {
|
|
102
|
+
let _lang = ''
|
|
103
|
+
try {
|
|
104
|
+
_lang = new URLSearchParams(get(window, 'location.search', '')).get('lang') || ''
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
_lang = ''
|
|
108
|
+
}
|
|
109
|
+
if (isestr(_lang)) {
|
|
110
|
+
lang = validLang(_lang) //URL 帶非預期 lang 時 validLang 退回 eng
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//from window ___pmwperm___.language(server 注入之初始語系;對齊 w-web-sso window 注入來源)。
|
|
115
|
+
//須在 store 之前:store.state.lang 預設為非空 'eng'(mutations.mjs),若 store 在前會永遠 shadow 掉 window 注入值。
|
|
116
|
+
//dev 未注入時為模板符號 {language} → validLang 退回 eng。
|
|
136
117
|
if (!isestr(lang)) {
|
|
137
118
|
let _lang = get(window, '___pmwperm___.language', '')
|
|
138
|
-
// console.log('_lang(from window)', _lang)
|
|
139
119
|
if (isestr(_lang)) {
|
|
140
|
-
lang = validLang(_lang)
|
|
120
|
+
lang = validLang(_lang)
|
|
141
121
|
}
|
|
142
122
|
}
|
|
143
123
|
|
|
144
|
-
//from store
|
|
124
|
+
//from store(使用者執行期切換之語系;切換以 setLang(明確值) 直接寫入、其後無 setLang(null) 故能持久)
|
|
145
125
|
if (!isestr(lang)) {
|
|
146
126
|
let _lang = get(vo, '$store.state.lang', '')
|
|
147
127
|
// console.log('_lang(from store)', _lang)
|
|
@@ -86,6 +86,34 @@ let settings = {
|
|
|
86
86
|
name: '輸出範例',
|
|
87
87
|
type: 'STRING',
|
|
88
88
|
},
|
|
89
|
+
'testBaseUrl': {
|
|
90
|
+
name: '測試基底網址',
|
|
91
|
+
type: 'STRING',
|
|
92
|
+
},
|
|
93
|
+
'authType': {
|
|
94
|
+
name: '認證類型',
|
|
95
|
+
type: 'STRING',
|
|
96
|
+
},
|
|
97
|
+
'authConfigJson': {
|
|
98
|
+
name: '認證設定JSON',
|
|
99
|
+
type: 'TEXT',
|
|
100
|
+
},
|
|
101
|
+
'defaultHeadersJson': {
|
|
102
|
+
name: '預設標頭JSON',
|
|
103
|
+
type: 'TEXT',
|
|
104
|
+
},
|
|
105
|
+
'defaultQueryJson': {
|
|
106
|
+
name: '預設查詢參數JSON',
|
|
107
|
+
type: 'TEXT',
|
|
108
|
+
},
|
|
109
|
+
'defaultBodyJson': {
|
|
110
|
+
name: '預設請求內容JSON',
|
|
111
|
+
type: 'TEXT',
|
|
112
|
+
},
|
|
113
|
+
'contentType': {
|
|
114
|
+
name: '內容類型',
|
|
115
|
+
type: 'STRING',
|
|
116
|
+
},
|
|
89
117
|
'timeCreate': {
|
|
90
118
|
name: '創建時間',
|
|
91
119
|
type: 'STRING',
|
|
@@ -106,6 +134,8 @@ let funNew = (ndata = {}) => {
|
|
|
106
134
|
o.timeCreate = nowms2str()
|
|
107
135
|
o.timeUpdate = o.timeCreate
|
|
108
136
|
o.isActive = 'y'
|
|
137
|
+
o.authType = isestr(o.authType) ? o.authType : 'none'
|
|
138
|
+
o.contentType = isestr(o.contentType) ? o.contentType : 'application/json'
|
|
109
139
|
return o
|
|
110
140
|
}
|
|
111
141
|
|
package/src/store/mutations.mjs
CHANGED
|
@@ -79,12 +79,6 @@ export let mutations = {
|
|
|
79
79
|
state[msg.tableName] = msg.data
|
|
80
80
|
},
|
|
81
81
|
|
|
82
|
-
[types.UpdateData] (state, msg) {
|
|
83
|
-
//msg.path內為存取路徑, 需使用set處理
|
|
84
|
-
// console.log('UpdateData msg', msg)
|
|
85
|
-
set(state, msg.path, msg.data)
|
|
86
|
-
},
|
|
87
|
-
|
|
88
82
|
[types.UpdateHeightApp] (state, heightApp) {
|
|
89
83
|
state.heightApp = heightApp
|
|
90
84
|
},
|
|
@@ -93,14 +87,6 @@ export let mutations = {
|
|
|
93
87
|
state.heightAppEff = heightAppEff
|
|
94
88
|
},
|
|
95
89
|
|
|
96
|
-
[types.UpdateHeightToolbar] (state, heightToolbar) {
|
|
97
|
-
state.heightToolbar = heightToolbar
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
[types.UpdateMenu] (state, menu) {
|
|
101
|
-
state.menu = menu
|
|
102
|
-
},
|
|
103
|
-
|
|
104
90
|
[types.UpdateUserToken] (state, userToken) {
|
|
105
91
|
state.userToken = userToken
|
|
106
92
|
},
|
package/src/store/types.mjs
CHANGED
|
@@ -6,10 +6,7 @@ export const UpdateSyncState = 'UpdateSyncState'
|
|
|
6
6
|
export const UpdateLoading = 'UpdateLoading'
|
|
7
7
|
// export const UpdateViewState = 'UpdateViewState'
|
|
8
8
|
export const UpdateTableData = 'UpdateTableData'
|
|
9
|
-
export const UpdateData = 'UpdateData'
|
|
10
9
|
export const UpdateHeightApp = 'UpdateHeightApp'
|
|
11
10
|
export const UpdateHeightAppEff = 'UpdateHeightAppEff'
|
|
12
|
-
export const UpdateHeightToolbar = 'UpdateHeightToolbar'
|
|
13
|
-
export const UpdateMenu = 'UpdateMenu'
|
|
14
11
|
export const UpdateUserToken = 'UpdateUserToken'
|
|
15
12
|
export const UpdateUserSelf = 'UpdateUserSelf'
|
package/srv.mjs
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
import WOrm from 'w-orm-lmdb/src/WOrmLmdb.mjs'
|
|
2
2
|
import WWebApi from './server/WWebApi.mjs'
|
|
3
3
|
import getSettings from './g.getSettings.mjs'
|
|
4
|
+
import get from 'lodash-es/get.js'
|
|
5
|
+
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
6
|
+
import axios from 'axios'
|
|
7
|
+
import JSON5 from 'json5'
|
|
8
|
+
import fs from 'fs'
|
|
4
9
|
|
|
5
10
|
|
|
6
|
-
//st
|
|
11
|
+
//st(db 等系統參數由 g.getSettings 提供,供 g.mOrm 共用)
|
|
7
12
|
let st = getSettings()
|
|
8
13
|
|
|
14
|
+
//pathSettings:app 設定檔路徑,預設 ./settings.json;可由 `node srv.mjs <path>` 覆寫
|
|
15
|
+
//(供 e2e restartBackend / 部署帶不同設定,日後更細緻功能便於擴充)。settings.json 為 JSON5 格式。
|
|
16
|
+
let pathSettings = process.argv[2] || './settings.json'
|
|
17
|
+
let stApp = JSON5.parse(fs.readFileSync(pathSettings, 'utf8'))
|
|
18
|
+
|
|
9
19
|
let url = st.dbUrl
|
|
10
20
|
let db = st.dbName
|
|
21
|
+
let ssoBaseUrl = st.ssoBaseUrl
|
|
22
|
+
let ssoAppToken = st.ssoAppToken
|
|
23
|
+
let ssoLoginUrl = st.ssoLoginUrl
|
|
11
24
|
let opt = {
|
|
12
25
|
|
|
13
26
|
useCheckUser: false,
|
|
14
27
|
getUserById: null,
|
|
15
28
|
useExcludeWhenNotAdmin: false,
|
|
16
29
|
|
|
17
|
-
serverPort: 11005,
|
|
30
|
+
serverPort: get(stApp, 'serverPort', 11005),
|
|
18
31
|
subfolder: '', //mapi
|
|
19
|
-
urlRedirect:
|
|
32
|
+
urlRedirect: ssoLoginUrl, //未登入時導向SSO登入頁, 本機測試時得先編譯, 再瀏覽: http://localhost:11005/
|
|
33
|
+
|
|
34
|
+
//語系(來自 settings.json):language 由 WWebApi 注入 index.html ({language}) → 初始畫面即此語系;
|
|
35
|
+
//showLanguage 控右上語系選單顯隱。e2e 可用 restartBackend(genTempSettings({language})) 改 server 初始語系。
|
|
36
|
+
showLanguage: get(stApp, 'showLanguage', 'y'),
|
|
37
|
+
language: get(stApp, 'language', 'eng'),
|
|
38
|
+
|
|
39
|
+
//log 資料夾與輪檔間隔(srLog 寫入 + staEvent 統計皆讀此)。e2e 可用 genTempSettings({logFd}) 指向合成 log 達 hermetic。
|
|
40
|
+
logFd: get(stApp, 'logFd', './logs'),
|
|
41
|
+
logInterval: get(stApp, 'logInterval', 'hr'),
|
|
20
42
|
|
|
21
43
|
webName: {
|
|
22
44
|
'eng': 'API Service',
|
|
@@ -24,7 +46,7 @@ let opt = {
|
|
|
24
46
|
},
|
|
25
47
|
webDescription: {
|
|
26
48
|
'eng': 'A web service package as methods to send requests to and receive responses from an API.',
|
|
27
|
-
'cht': '
|
|
49
|
+
'cht': '一套以方法形式,用於發送請求至API並接收其回應的網頁服務套件。',
|
|
28
50
|
},
|
|
29
51
|
webLogo: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMyIDMyIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAzMiAzMiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PGcgaWQ9IkxheWVyXzIiLz48ZyBpZD0iTGF5ZXJfMyIvPjxnIGlkPSJMYXllcl80Ij48Zz48cGF0aCBkPSJNOS4wMiw2QzkuMDEyNyw2LDkuMDA2OCw1Ljk5OSw5LDZIMkMxLjQ0NzgsNiwxLDUuNTUyNywxLDVWMmMwLTAuNTUyNywwLjQ0NzgtMSwxLTFoNiAgICBjMC40MzA3LDAsMC44MTI1LDAuMjc1NCwwLjk0ODcsMC42ODM2bDAuOTQwNCwyLjgyMTNDOS45NzIyLDQuNjUxNCwxMC4wMiw0LjgyMDMsMTAuMDIsNUMxMC4wMiw1LjU1MjcsOS41NzIzLDYsOS4wMiw2eiBNMyw0ICAgIGg0LjYxMjhMNy4yNzkzLDNIM1Y0eiIgZmlsbD0iI0Y1RDgwMyIvPjwvZz48Zz48cGF0aCBkPSJNMjQuMDE5NSwyMmMtMC4wMDM5LDAtMC4wMTE3LDAuMDAxLTAuMDE5NSwwaC03Yy0wLjU1MjIsMC0xLTAuNDQ3My0xLTF2LTNjMC0wLjU1MjcsMC40NDc4LTEsMS0xaDYgICAgYzAuNDMwNywwLDAuODEyNSwwLjI3NTQsMC45NDgyLDAuNjgzNmwwLjk0MDQsMi44MjEzYzAuMDg0LDAuMTQ2NSwwLjEzMDksMC4zMTU0LDAuMTMwOSwwLjQ5NTEgICAgQzI1LjAxOTUsMjEuNTUyNywyNC41NzIzLDIyLDI0LjAxOTUsMjJ6IE0xOCwyMGg0LjYxMjNsLTAuMzMzLTFIMThWMjB6IiBmaWxsPSIjRjVEODAzIi8+PC9nPjxnPjxwYXRoIGQ9Ik0xNSwxNUgyYy0wLjU1MjIsMC0xLTAuNDQ3My0xLTFWNWMwLTAuNTUyNywwLjQ0NzgtMSwxLTFoMTNjMC41NTIyLDAsMSwwLjQ0NzMsMSwxdjkgICAgQzE2LDE0LjU1MjcsMTUuNTUyMiwxNSwxNSwxNXogTTMsMTNoMTFWNkgzVjEzeiIgZmlsbD0iIzAxODFCMCIvPjwvZz48Zz48cGF0aCBkPSJNMzAsMzFIMTdjLTAuNTUyMiwwLTEtMC40NDczLTEtMXYtOWMwLTAuNTUyNywwLjQ0NzgtMSwxLTFoMTNjMC41NTI3LDAsMSwwLjQ0NzMsMSwxdjkgICAgQzMxLDMwLjU1MjcsMzAuNTUyNywzMSwzMCwzMXogTTE4LDI5aDExdi03SDE4VjI5eiIgZmlsbD0iIzAxODFCMCIvPjwvZz48Zz48cGF0aCBkPSJNMjYsOGgtOGMtMC41NTI3LDAtMSwwLjQ0NzMtMSwxczAuNDQ3MywxLDEsMWg3djZjMCwwLjU1MjcsMC40NDczLDEsMSwxczEtMC40NDczLDEtMVY5ICAgIEMyNyw4LjQ0NzMsMjYuNTUyNyw4LDI2LDh6IiBmaWxsPSIjMDBBQ0JBIi8+PGc+PHBhdGggZD0iTTIwLDEyYy0wLjI1NTksMC0wLjUxMTctMC4wOTc3LTAuNzA3LTAuMjkzbC0yLTJjLTAuMzkwNi0wLjM5MDYtMC4zOTA2LTEuMDIzNCwwLTEuNDE0MWwyLTIgICAgIGMwLjM5MDYtMC4zOTA2LDEuMDIzNC0wLjM5MDYsMS40MTQxLDBzMC4zOTA2LDEuMDIzNCwwLDEuNDE0MUwxOS40MTQxLDlsMS4yOTMsMS4yOTNjMC4zOTA2LDAuMzkwNiwwLjM5MDYsMS4wMjM0LDAsMS40MTQxICAgICBDMjAuNTExNywxMS45MDIzLDIwLjI1NTksMTIsMjAsMTJ6IiBmaWxsPSIjRjVEODAzIi8+PC9nPjwvZz48Zz48cGF0aCBkPSJNMTQsMjVIN3YtNmMwLTAuNTUyNy0wLjQ0NzgtMS0xLTFzLTEsMC40NDczLTEsMXY3YzAsMC41NTI3LDAuNDQ3OCwxLDEsMWg4YzAuNTUyMiwwLDEtMC40NDczLDEtMSAgICBTMTQuNTUyMiwyNSwxNCwyNXoiIGZpbGw9IiMwMEFDQkEiLz48Zz48cGF0aCBkPSJNMTIsMjljLTAuMjU1OSwwLTAuNTExNy0wLjA5NzctMC43MDctMC4yOTNjLTAuMzkwNi0wLjM5MDYtMC4zOTA2LTEuMDIzNCwwLTEuNDE0MUwxMi41ODU5LDI2ICAgICBsLTEuMjkzLTEuMjkzYy0wLjM5MDYtMC4zOTA2LTAuMzkwNi0xLjAyMzQsMC0xLjQxNDFzMS4wMjM0LTAuMzkwNiwxLjQxNDEsMGwyLDJjMC4zOTA2LDAuMzkwNiwwLjM5MDYsMS4wMjM0LDAsMS40MTQxbC0yLDIgICAgIEMxMi41MTE3LDI4LjkwMjMsMTIuMjU1OSwyOSwxMiwyOXoiIGZpbGw9IiNGNUQ4MDMiLz48L2c+PC9nPjwvZz48ZyBpZD0iTGF5ZXJfNSIvPjxnIGlkPSJMYXllcl82Ii8+PGcgaWQ9IkxheWVyXzciLz48ZyBpZD0iTGF5ZXJfOCIvPjxnIGlkPSJMYXllcl85Ii8+PGcgaWQ9IkxheWVyXzEwIi8+PGcgaWQ9IkxheWVyXzExIi8+PGcgaWQ9IkxheWVyXzEyIi8+PGcgaWQ9IkxheWVyXzEzIi8+PGcgaWQ9IkxheWVyXzE0Ii8+PGcgaWQ9IkxheWVyXzE1Ii8+PGcgaWQ9IkxheWVyXzE2Ii8+PGcgaWQ9IkxheWVyXzE3Ii8+PGcgaWQ9IkxheWVyXzE4Ii8+PGcgaWQ9IkxheWVyXzE5Ii8+PGcgaWQ9IkxheWVyXzIwIi8+PGcgaWQ9IkxheWVyXzIxIi8+PGcgaWQ9IkxheWVyXzIyIi8+PGcgaWQ9IkxheWVyXzIzIi8+PGcgaWQ9IkxheWVyXzI0Ii8+PGcgaWQ9IkxheWVyXzI1Ii8+PGcgaWQ9IkxheWVyXzI2Ii8+PC9zdmc+',
|
|
30
52
|
|
|
@@ -32,25 +54,33 @@ let opt = {
|
|
|
32
54
|
|
|
33
55
|
let getUserByToken = async (token) => {
|
|
34
56
|
// return {} //測試無法登入
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
//'sys' 為開發捷徑(w-ui-loginout 於 localhost 自動帶入)。加環境守門:NODE_ENV==='production' 時不接受,
|
|
58
|
+
//避免 srv.mjs 若作正式入口時 'sys' 成為遠端管理員後門。e2e/dev 未設 NODE_ENV=production 故仍可用;
|
|
59
|
+
//正式部署設 NODE_ENV=production 即停用此捷徑(並應改提供真實 getUserByToken)。
|
|
60
|
+
if (token === 'sys' && process.env.NODE_ENV !== 'production') {
|
|
61
|
+
return { id: 'id-for-admin', name: '測試者', email: 'admin@example.com', isAdmin: 'y' }
|
|
62
|
+
}
|
|
63
|
+
//未設定 SSO app token 時(本機開發未接SSO), 不打SSO直接拒絕
|
|
64
|
+
if (!ssoAppToken) {
|
|
65
|
+
console.log('ssoAppToken 未設定, 略過 SSO 驗證')
|
|
66
|
+
return {}
|
|
42
67
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
//呼叫 SSO 解析 token -> user
|
|
69
|
+
try {
|
|
70
|
+
let url = `${ssoBaseUrl}/api/getSsoUserInfor?token=${encodeURIComponent(ssoAppToken)}&key=token&value=${encodeURIComponent(token)}`
|
|
71
|
+
let res = await axios.get(url)
|
|
72
|
+
let state = get(res, 'data.state', '')
|
|
73
|
+
let u = get(res, 'data.msg', null)
|
|
74
|
+
if (state !== 'success' || !iseobj(u)) {
|
|
75
|
+
console.log('SSO getSsoUserInfor 失敗', state)
|
|
76
|
+
return {}
|
|
49
77
|
}
|
|
78
|
+
return { id: u.id, name: u.name, email: u.email, isAdmin: u.isAdmin }
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.log('SSO getSsoUserInfor error', err.message)
|
|
82
|
+
return {}
|
|
50
83
|
}
|
|
51
|
-
console.log('invalid token', token)
|
|
52
|
-
console.log('於生產環境時得加入SSO等驗證token機制')
|
|
53
|
-
return {}
|
|
54
84
|
}
|
|
55
85
|
|
|
56
86
|
let verifyClientUser = (user, from) => {
|
package/tableTags.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"apis":"2026-
|
|
1
|
+
{"apis":"2026-07-11T17:47:54+08:00|7AQq2D"}
|