w-web-api 1.0.52 → 1.0.53

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 (84) hide show
  1. package/_gh-pages-deploy/.nojekyll +0 -0
  2. package/_gh-pages-deploy/WWebApi.html +898 -0
  3. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  4. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  5. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  6. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  7. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  8. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  9. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  10. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  11. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  12. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  13. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  14. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  15. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  16. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  17. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  18. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  19. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  20. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  21. package/_gh-pages-deploy/index.html +84 -0
  22. package/_gh-pages-deploy/scripts/collapse.js +39 -0
  23. package/_gh-pages-deploy/scripts/commonNav.js +28 -0
  24. package/_gh-pages-deploy/scripts/linenumber.js +25 -0
  25. package/_gh-pages-deploy/scripts/nav.js +12 -0
  26. package/_gh-pages-deploy/scripts/polyfill.js +4 -0
  27. package/_gh-pages-deploy/scripts/prettify/Apache-License-2.0.txt +202 -0
  28. package/_gh-pages-deploy/scripts/prettify/lang-css.js +2 -0
  29. package/_gh-pages-deploy/scripts/prettify/prettify.js +28 -0
  30. package/_gh-pages-deploy/scripts/search.js +99 -0
  31. package/{docs/WWebApi.mjs.html → _gh-pages-deploy/server_WWebApi.mjs.html} +96 -39
  32. package/_gh-pages-deploy/src_components_Common_CheckYesNo.vue.html +187 -0
  33. package/_gh-pages-deploy/styles/jsdoc.css +776 -0
  34. package/_gh-pages-deploy/styles/prettify.css +80 -0
  35. package/dist/css/app.fe69497a.css +1 -0
  36. package/dist/index.tmp +4 -2
  37. package/dist/js/app-legacy.15819aa7.js +1 -0
  38. package/dist/js/app.15819aa7.js +1 -0
  39. package/dist/js/chunk-vendors-legacy.c1a32dd1.js +15 -0
  40. package/dist/js/chunk-vendors.c1a32dd1.js +15 -0
  41. package/dist/w-web-api.umd.js +2 -2
  42. package/dist/w-web-api.umd.js.map +1 -1
  43. package/docs/WWebApi.html +2 -2
  44. package/docs/index.html +1 -1
  45. package/docs/server_WWebApi.mjs.html +1012 -0
  46. package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
  47. package/g.getSettings.mjs +3 -0
  48. package/package.json +15 -11
  49. package/public/index.html +9 -2
  50. package/server/WWebApi.mjs +93 -36
  51. package/server/procApis.mjs +62 -0
  52. package/server/procLang.mjs +386 -0
  53. package/server/procProxy.mjs +120 -0
  54. package/server/srLog.mjs +30 -0
  55. package/server/staLogs/staEvent.mjs +129 -0
  56. package/server/staLogs/test_staEvent.mjs +132 -0
  57. package/settings.json +14 -0
  58. package/src/App.vue +11 -7
  59. package/src/assets/scalar-ui.css +113 -0
  60. package/src/components/Common/CheckYes.vue +102 -0
  61. package/src/components/Common/CheckYesNo.vue +115 -0
  62. package/src/components/Common/LoadingWinBar.vue +114 -0
  63. package/src/components/Layout.vue +8 -7
  64. package/src/components/LayoutContent.vue +308 -333
  65. package/src/components/LayoutContentEdit.vue +577 -0
  66. package/src/components/LayoutContentStats.vue +485 -0
  67. package/src/components/LayoutContentTest.vue +799 -0
  68. package/src/components/MdPanel.vue +80 -58
  69. package/src/main.js +8 -0
  70. package/src/plugins/mUI.mjs +19 -4
  71. package/src/schema/tables/apis.mjs +30 -0
  72. package/srv.mjs +47 -19
  73. package/tableTags.json +1 -1
  74. package/.github/workflows/ci-test.yml +0 -24
  75. package/.vscode/launch.json +0 -18
  76. package/db/wapis/apis/data.mdb +0 -0
  77. package/db/wapis/apis/lock.mdb +0 -0
  78. package/dist/css/app.b5cf2ef5.css +0 -1
  79. package/dist/js/app-legacy.927b5679.js +0 -1
  80. package/dist/js/app.927b5679.js +0 -1
  81. package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
  82. package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
  83. package/tableTags-web-api.json +0 -1
  84. 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
- margin: 0;
80
- padding: 0;
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
- font-weight: bold;
91
- background: #eee;
92
- border: 1px solid #ddd;
93
- border-bottom: 0;
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: 6px 13px;
100
+ padding: 8px 18px 8px 0;
96
101
  }
97
102
 
98
103
  .md >>> table tr td {
99
- border: 1px solid #ddd;
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: 6px 13px;
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 >>> h1 {
105
- font-weight: bold;
106
- font-size: 1.2rem;
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
- .md >>> h2 {
113
- font-weight: bold;
114
- font-size: 1.1rem;
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 >>> h3 {
121
- font-weight: bold;
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 >>> h4 {
129
- font-weight: bold;
130
- font-size: 1rem;
131
- line-height: 1rem;
132
- margin-top: 0.5rem;
133
- margin-bottom: 0.5rem;
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 >>> h5 {
137
- font-weight: bold;
138
- font-size: 1rem;
139
- line-height: 1rem;
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 >>> h6 {
145
- font-weight: bold;
146
- font-size: 1rem;
147
- line-height: 1rem;
148
- margin-top: 0.5rem;
149
- margin-bottom: 0.5rem;
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'
@@ -37,6 +38,13 @@ let dssm = mDataSelectorSchema(ds)
37
38
  //prototype
38
39
  Vue.prototype.$ui = ui
39
40
  Vue.prototype.$t = ui.getKpText
41
+ //$transErr:後端 reject 之 err-key → 依當前 lang 反查顯示文字。
42
+ //非字串或查無對應 key(getKpText 查不到會原樣回 key)則 fallback 'anUnexpectedErrorOccurred',避免顯示生 key。
43
+ Vue.prototype.$transErr = (err) => {
44
+ let key = (typeof err === 'string' && err) ? err : 'anUnexpectedErrorOccurred'
45
+ let msg = ui.getKpText(key)
46
+ return (msg && msg !== key) ? msg : ui.getKpText('anUnexpectedErrorOccurred')
47
+ }
40
48
  Vue.prototype.$s = s
41
49
  Vue.prototype.$dssm = dssm
42
50
  Vue.prototype.$ds = ds
@@ -132,16 +132,31 @@ function validLang(lang) {
132
132
  function getLang() {
133
133
  let lang = ''
134
134
 
135
- //from window
135
+ //from URL ?lang=(最高優先;供「以指定語系載入初始畫面」用,如分享連結 /?lang=cht,對齊 w-web-sso getLang)
136
+ if (!isestr(lang)) {
137
+ let _lang = ''
138
+ try {
139
+ _lang = new URLSearchParams(get(window, 'location.search', '')).get('lang') || ''
140
+ }
141
+ catch (err) {
142
+ _lang = ''
143
+ }
144
+ if (isestr(_lang)) {
145
+ lang = validLang(_lang) //URL 帶非預期 lang 時 validLang 退回 eng
146
+ }
147
+ }
148
+
149
+ //from window ___pmwperm___.language(server 注入之初始語系;對齊 w-web-sso window 注入來源)。
150
+ //須在 store 之前:store.state.lang 預設為非空 'eng'(mutations.mjs),若 store 在前會永遠 shadow 掉 window 注入值。
151
+ //dev 未注入時為模板符號 {language} → validLang 退回 eng。
136
152
  if (!isestr(lang)) {
137
153
  let _lang = get(window, '___pmwperm___.language', '')
138
- // console.log('_lang(from window)', _lang)
139
154
  if (isestr(_lang)) {
140
- lang = validLang(_lang) //有可能取到未取代前模板符號
155
+ lang = validLang(_lang)
141
156
  }
142
157
  }
143
158
 
144
- //from store
159
+ //from store(使用者執行期切換之語系;切換以 setLang(明確值) 直接寫入、其後無 setLang(null) 故能持久)
145
160
  if (!isestr(lang)) {
146
161
  let _lang = get(vo, '$store.state.lang', '')
147
162
  // 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/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: 'https://www.google.com/', //本機測試時得先編譯, 再瀏覽: http://localhost:11005/
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',
@@ -32,25 +54,31 @@ let opt = {
32
54
 
33
55
  let getUserByToken = async (token) => {
34
56
  // return {} //測試無法登入
35
- if (token === '{token-for-application}') { //提供外部應用系統作為存取使用者
36
- return {
37
- id: 'id-for-application',
38
- name: 'application',
39
- email: 'application@example.com',
40
- isAdmin: 'y',
41
- }
57
+ //開發階段 w-ui-loginout localhost 自動給 token 'sys'
58
+ if (token === 'sys') {
59
+ return { id: 'id-for-admin', name: '測試者', email: 'admin@example.com', isAdmin: 'y' }
60
+ }
61
+ //未設定 SSO app token 時(本機開發未接SSO), 不打SSO直接拒絕
62
+ if (!ssoAppToken) {
63
+ console.log('ssoAppToken 未設定, 略過 SSO 驗證')
64
+ return {}
42
65
  }
43
- if (token === 'sys') { //開發階段w-ui-loginout自動給予browser使用者(且位於localhost)的token為sys
44
- return {
45
- id: 'id-for-admin',
46
- name: '測試者',
47
- email: 'admin@example.com',
48
- isAdmin: 'y',
66
+ //呼叫 SSO 解析 token -> user
67
+ try {
68
+ let url = `${ssoBaseUrl}/api/getSsoUserInfor?token=${encodeURIComponent(ssoAppToken)}&key=token&value=${encodeURIComponent(token)}`
69
+ let res = await axios.get(url)
70
+ let state = get(res, 'data.state', '')
71
+ let u = get(res, 'data.msg', null)
72
+ if (state !== 'success' || !iseobj(u)) {
73
+ console.log('SSO getSsoUserInfor 失敗', state)
74
+ return {}
49
75
  }
76
+ return { id: u.id, name: u.name, email: u.email, isAdmin: u.isAdmin }
77
+ }
78
+ catch (err) {
79
+ console.log('SSO getSsoUserInfor error', err.message)
80
+ return {}
50
81
  }
51
- console.log('invalid token', token)
52
- console.log('於生產環境時得加入SSO等驗證token機制')
53
- return {}
54
82
  }
55
83
 
56
84
  let verifyClientUser = (user, from) => {
package/tableTags.json CHANGED
@@ -1 +1 @@
1
- {"apis":"2026-03-28T23:37:07+08:00|m2kF53"}
1
+ {"apis":"2026-06-22T12:43:06+08:00|Yl6xfX"}
@@ -1,24 +0,0 @@
1
- name: Node.js CI
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
-
8
- runs-on: ubuntu-latest
9
-
10
- strategy:
11
- matrix:
12
- node-version: [22.x]
13
-
14
- steps:
15
- - uses: actions/checkout@v4
16
- - name: Use Node.js ${{ matrix.node-version }}
17
- uses: actions/setup-node@v1
18
- with:
19
- node-version: ${{ matrix.node-version }}
20
- - run: npm cache clean -f
21
- - run: npm install
22
- - run: npm test
23
- env:
24
- CI: true
@@ -1,18 +0,0 @@
1
- {
2
- // 使用 IntelliSense 以得知可用的屬性。
3
- // 暫留以檢視現有屬性的描述。
4
- // 如需詳細資訊,請瀏覽: https://go.microsoft.com/fwlink/?linkid=830387
5
- "version": "0.2.0",
6
- "configurations": [
7
- {
8
- "type": "node",
9
- "request": "launch",
10
- "name": "啟動程式",
11
- "skipFiles": [
12
- "<node_internals>/**"
13
- ],
14
- "program": "${workspaceFolder}/srv.mjs",
15
- "runtimeArgs": []
16
- }
17
- ]
18
- }
Binary file
Binary file
@@ -1 +0,0 @@
1
- .pgc-rotate[data-v-5b4e8bee]{width:100%;height:100%;margin:auto;position:absolute;top:0;bottom:0;left:0;right:0;z-index:1;-webkit-transition:all .6s ease-in-out;transition:all .6s ease-in-out;-webkit-animation:progress-circular-rotate-5b4e8bee 1.4s linear infinite;animation:progress-circular-rotate-5b4e8bee 1.4s linear infinite;-webkit-transform-origin:center center;transform-origin:center center}.pgc-dash[data-v-5b4e8bee]{-webkit-animation:progress-circular-dash-5b4e8bee 1.4s ease-in-out infinite;animation:progress-circular-dash-5b4e8bee 1.4s ease-in-out infinite;stroke-linecap:round;stroke-dasharray:80,200;stroke-dashoffset:0px}@-webkit-keyframes progress-circular-dash-5b4e8bee{0%{stroke-dasharray:1,200;stroke-dashoffset:0px}50%{stroke-dasharray:100,200;stroke-dashoffset:-15px}to{stroke-dasharray:100,200;stroke-dashoffset:-124px}}@keyframes progress-circular-dash-5b4e8bee{0%{stroke-dasharray:1,200;stroke-dashoffset:0px}50%{stroke-dasharray:100,200;stroke-dashoffset:-15px}to{stroke-dasharray:100,200;stroke-dashoffset:-124px}}@-webkit-keyframes progress-circular-rotate-5b4e8bee{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes progress-circular-rotate-5b4e8bee{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.WPopperFix[data-popper-reference-hidden][data-v-14d6bcb4]{visibility:hidden;pointer-events:none}.sb[data-v-6ce5bdb1]{-webkit-transition:opacity .3s;transition:opacity .3s;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.3) transparent}.sb[data-v-6ce5bdb1]::-webkit-scrollbar{width:8px;height:8px}.sb[data-v-6ce5bdb1]::-webkit-scrollbar-track{background:transparent}.sb[data-v-6ce5bdb1]::-webkit-scrollbar-thumb{background:rgba(0,0,0,.3);border-radius:20px;border:3px solid transparent}.ts[data-v-9a483320]{-webkit-transition:all .3s cubic-bezier(.25,.8,.5,1);transition:all .3s cubic-bezier(.25,.8,.5,1)}.bs[data-v-9a483320]{-webkit-box-shadow:0 8px 2px -8px rgba(0,0,0,.3),0 16px 24px 2px rgba(0,0,0,.3),0 6px 30px 5px rgba(0,0,0,.3);box-shadow:0 8px 2px -8px rgba(0,0,0,.3),0 16px 24px 2px rgba(0,0,0,.3),0 6px 30px 5px rgba(0,0,0,.3)}.fade-enter-active[data-v-a0c94508],.fade-leave-active[data-v-a0c94508]{-webkit-transition:all .3s;transition:all .3s}.fade-enter[data-v-a0c94508],.fade-leave-to[data-v-a0c94508]{-webkit-transform:scaleX(0);transform:scaleX(0)}.fade-enter-to[data-v-a0c94508],.fade-leave[data-v-a0c94508]{-webkit-transform:scaleX(100%);transform:scaleX(100%)}.caretRight[data-v-26dfca3e]{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:inline-block}.cc[data-v-26dfca3e]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.circle[data-v-26dfca3e]{width:22px;height:22px;min-width:22px;min-height:22px;max-width:22px;max-height:22px;border-radius:50%}.md[data-v-1a0f86f5] table{border-collapse:collapse;margin:0;padding:0;word-break:normal}.md[data-v-1a0f86f5] tr{margin:0;padding:0}.md[data-v-1a0f86f5] table tr th{font-weight:700;background:#eee;border:1px solid #ddd;border-bottom:0;margin:0;padding:6px 13px}.md[data-v-1a0f86f5] table tr td{border:1px solid #ddd;margin:0;padding:6px 13px}.md[data-v-1a0f86f5] h1{font-size:1.2rem;line-height:1.2rem}.md[data-v-1a0f86f5] h1,.md[data-v-1a0f86f5] h2{font-weight:700;margin-top:.5rem;margin-bottom:.5rem}.md[data-v-1a0f86f5] h2{font-size:1.1rem;line-height:1.1rem}.md[data-v-1a0f86f5] h3,.md[data-v-1a0f86f5] h4,.md[data-v-1a0f86f5] h5,.md[data-v-1a0f86f5] h6{font-weight:700;font-size:1rem;line-height:1rem;margin-top:.5rem;margin-bottom:.5rem}.bk[data-v-56f2385e]{display:inline-block;width:200px;padding:0 10px 10px 0;vertical-align:top}.bk-title[data-v-56f2385e]{padding:3px;font-size:.8rem;color:#888}.bk-item[data-v-56f2385e]{padding:3px 5px;font-size:.9rem;line-height:.9rem;border-radius:5px;border:1px solid #ddd;background:#fff}body,html{font-family:微軟正黑體,Microsoft JhengHei,MicrosoftJhengHeiRegular,Avenir,Helvetica,Arial,sans-serif;overflow-y:hidden}a,button,div,input,p,pre,span,textarea{font-family:inherit}.fade-enter-active{-webkit-animation:go 1s;animation:go 1s}.fade-leave-active{-webkit-animation:back 1s;animation:back 1s}@-webkit-keyframes go{0%{opacity:0}to{opacity:1}}@keyframes go{0%{opacity:0}to{opacity:1}}@-webkit-keyframes back{0%{opacity:1}to{opacity:0}}@keyframes back{0%{opacity:1}to{opacity:0}}