ch3chi-commons-vue 1.2.0 → 1.8.1
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/package.json +2 -1
- package/src/api/ApiService.ts +869 -0
- package/src/auth/AuthorizationService.ts +138 -0
- package/src/auth/PermissionDescriptor.ts +99 -0
- package/src/auth/keys.ts +5 -0
- package/src/components/CAlert.vue +188 -0
- package/src/components/CAlertDefine.ts +20 -0
- package/src/components/CBSToast.vue +119 -0
- package/src/components/CGlobalSpinner.vue +84 -0
- package/src/components/CImage.vue +67 -0
- package/src/components/CRowCheckBox.vue +75 -0
- package/src/components/CRowTextInput.vue +27 -0
- package/src/components/CTable.vue +524 -0
- package/src/components/CTableDefine.ts +566 -0
- package/src/components/CTableTD.vue +28 -0
- package/src/components/HasPermission.vue +28 -0
- package/src/components/form/CChangePasswordFormField.vue +146 -0
- package/src/components/form/CCheckBoxFormField.vue +91 -0
- package/src/components/form/CCheckBoxPlatFormField.vue +94 -0
- package/src/components/form/CDateFormField.vue +149 -0
- package/src/components/form/CDateQueryField.vue +111 -0
- package/src/components/form/CDateRangeFormField.vue +138 -0
- package/src/components/form/CFilePickerFormField.vue +471 -0
- package/src/components/form/CRadioFormField.vue +62 -0
- package/src/components/form/CRadioPlatFormField.vue +67 -0
- package/src/components/form/CSelectFormField.vue +175 -0
- package/src/components/form/CTextAreaFormField.vue +84 -0
- package/src/components/form/CTextInputFormField.vue +99 -0
- package/src/components/form/CTinyMCEEditorFormField.vue +99 -0
- package/src/components/form/SCTextInputFormField.vue +129 -0
- package/src/composables/useCheckBoxFormField.ts +126 -0
- package/src/composables/useRadioFormField.ts +106 -0
- package/src/directive/CBootstrapDirective.ts +83 -0
- package/src/directive/CDateFormatterDirective.ts +37 -0
- package/src/directive/CFTurnstileDirective.ts +46 -0
- package/src/directive/CFormDirective.ts +57 -0
- package/src/directive/PermissionDirective.ts +102 -0
- package/src/env.d.ts +19 -0
- package/src/index.ts +83 -0
- package/src/model/BSFieldStyleConfig.ts +349 -0
- package/src/model/BaseDictionary.ts +86 -0
- package/src/model/BaseFormDataModel.ts +623 -0
- package/src/model/BaseListViewModel.ts +392 -0
- package/src/model/CBSModalViewModel.ts +91 -0
- package/src/model/CFileDataModel.ts +181 -0
- package/src/model/CImageViewModel.ts +34 -0
- package/src/model/CMenuItem.ts +199 -0
- package/src/model/EmailReceiverDataModel.ts +149 -0
- package/src/model/EmptyDataModel.ts +25 -0
- package/src/model/FormOptions.ts +112 -0
- package/src/model/LoginDataModel.ts +51 -0
- package/src/model/PasswordDataModel.ts +70 -0
- package/src/model/QueryParameter.ts +310 -0
- package/src/model/SessionUser.ts +110 -0
- package/src/model/ShowMessageDataModel.ts +69 -0
- package/src/model/TokenUser.ts +157 -0
- package/src/stores/FormDataStore.ts +73 -0
- package/src/stores/ViewStore.ts +701 -0
- package/src/stores/VueSessionStoreInstaller.ts +22 -0
- package/src/types/turnstile.d.ts +8 -0
- package/src/utils/CToolUtils.ts +133 -0
- package/dist/api/ApiService.d.ts +0 -233
- package/dist/auth/AuthorizationService.d.ts +0 -56
- package/dist/auth/PermissionDescriptor.d.ts +0 -37
- package/dist/components/CAlert.vue.d.ts +0 -17
- package/dist/components/CAlertDefine.d.ts +0 -14
- package/dist/components/CBSToast.vue.d.ts +0 -6
- package/dist/components/CGlobalSpinner.vue.d.ts +0 -13
- package/dist/components/CRowCheckBox.vue.d.ts +0 -14
- package/dist/components/CRowTextInput.vue.d.ts +0 -10
- package/dist/components/CTable.vue.d.ts +0 -24
- package/dist/components/CTableDefine.d.ts +0 -201
- package/dist/components/CTableTD.vue.d.ts +0 -7
- package/dist/components/form/CChangePasswordFormField.vue.d.ts +0 -14
- package/dist/components/form/CCheckBoxFormField.vue.d.ts +0 -30
- package/dist/components/form/CDateFormField.vue.d.ts +0 -17
- package/dist/components/form/CDateQueryField.vue.d.ts +0 -16
- package/dist/components/form/CDateRangeFormField.vue.d.ts +0 -17
- package/dist/components/form/CFilePickerFormField.vue.d.ts +0 -28
- package/dist/components/form/CRadioFormField.vue.d.ts +0 -30
- package/dist/components/form/CSelectFormField.vue.d.ts +0 -18
- package/dist/components/form/CTextAreaFormField.vue.d.ts +0 -16
- package/dist/components/form/CTextInputFormField.vue.d.ts +0 -22
- package/dist/directive/CBootstrapDirective.d.ts +0 -17
- package/dist/directive/CDateFormatterDirective.d.ts +0 -10
- package/dist/directive/CFTurnstileDirective.d.ts +0 -15
- package/dist/directive/CFormDirective.d.ts +0 -9
- package/dist/directive/PermissionDirective.d.ts +0 -15
- package/dist/index.cjs.js +0 -19103
- package/dist/index.d.ts +0 -45
- package/dist/index.es.js +0 -19086
- package/dist/model/BSFieldStyleConfig.d.ts +0 -121
- package/dist/model/BaseDictionary.d.ts +0 -34
- package/dist/model/BaseFormDataModel.d.ts +0 -199
- package/dist/model/BaseListViewModel.d.ts +0 -165
- package/dist/model/CBSModalViewModel.d.ts +0 -44
- package/dist/model/CFileDataModel.d.ts +0 -74
- package/dist/model/CImageViewModel.d.ts +0 -8
- package/dist/model/CMenuItem.d.ts +0 -86
- package/dist/model/EmailReceiverDataModel.d.ts +0 -57
- package/dist/model/EmptyDataModel.d.ts +0 -7
- package/dist/model/FormOptions.d.ts +0 -60
- package/dist/model/LoginDataModel.d.ts +0 -12
- package/dist/model/PasswordDataModel.d.ts +0 -15
- package/dist/model/QueryParameter.d.ts +0 -92
- package/dist/model/SessionUser.d.ts +0 -45
- package/dist/model/ShowMessageDataModel.d.ts +0 -44
- package/dist/model/TokenUser.d.ts +0 -50
- package/dist/stores/FormDataStore.d.ts +0 -31
- package/dist/stores/ViewStore.d.ts +0 -349
- package/dist/style.css +0 -223
- package/dist/utils/CToolUtils.d.ts +0 -53
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSFieldStyleConfig 配置物件
|
|
3
|
+
* 用於以配置方式自訂欄位外觀和行為
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface IBSFieldStyleConfig {
|
|
7
|
+
// ----- 容器配置 -----
|
|
8
|
+
containerClass?: string;
|
|
9
|
+
|
|
10
|
+
// ----- Label 配置 -----
|
|
11
|
+
labelClass?: string;
|
|
12
|
+
labelPrefix?: string; // label 前置內容
|
|
13
|
+
labelSuffix?: string; // label 後置內容
|
|
14
|
+
hideLabel?: boolean;
|
|
15
|
+
|
|
16
|
+
// ----- required label 配置 -----
|
|
17
|
+
requiredLabelClass?: string;
|
|
18
|
+
requiredLabelText?: string;
|
|
19
|
+
|
|
20
|
+
// plain text 配置
|
|
21
|
+
plainTextClass?: string;
|
|
22
|
+
|
|
23
|
+
// ----- Input 配置 -----
|
|
24
|
+
inputClass?: string;
|
|
25
|
+
inputPrefix?: {
|
|
26
|
+
text?: string;
|
|
27
|
+
class?: string;
|
|
28
|
+
};
|
|
29
|
+
inputSuffix?: {
|
|
30
|
+
text?: string;
|
|
31
|
+
class?: string;
|
|
32
|
+
};
|
|
33
|
+
wrapperClass?: string; // input-group 的 class
|
|
34
|
+
|
|
35
|
+
// ----- Select 配置 -----
|
|
36
|
+
selectClass?: string;
|
|
37
|
+
selectSize?: 'sm' | 'lg'; // Bootstrap select 大小
|
|
38
|
+
selectMultiple?: boolean; // 是否多選
|
|
39
|
+
selectPlaceholder?: string; // placeholder 文字
|
|
40
|
+
|
|
41
|
+
// ----- Textarea 配置 -----
|
|
42
|
+
textareaClass?: string;
|
|
43
|
+
textareaRows?: number; // 預設行數
|
|
44
|
+
textareaResize?: 'none' | 'both' | 'horizontal' | 'vertical'; // 調整大小方式
|
|
45
|
+
textareaAutoGrow?: boolean; // 自動調整高度
|
|
46
|
+
|
|
47
|
+
// ----- Checkbox/Radio 配置 -----
|
|
48
|
+
checkboxClass?: string;
|
|
49
|
+
checkboxLabelClass?: string;
|
|
50
|
+
checkboxWrapperClass?: string; // form-check div 的 class
|
|
51
|
+
checkboxHelperIconClass?: string; // checkbox helper icon class
|
|
52
|
+
radioClass?: string;
|
|
53
|
+
radioLabelClass?: string;
|
|
54
|
+
radioWrapperClass?: string; // form-check div 的 class
|
|
55
|
+
radioInline?: boolean; // 是否水平排列
|
|
56
|
+
radioHelperIconClass?: string; // radio helper icon class
|
|
57
|
+
|
|
58
|
+
// ----- File Input 配置 -----
|
|
59
|
+
fileClass?: string;
|
|
60
|
+
fileAccept?: string; // 允許的檔案類型
|
|
61
|
+
fileMultiple?: boolean; // 是否多檔案選擇
|
|
62
|
+
fileDragDrop?: boolean; // 是否支援拖放
|
|
63
|
+
|
|
64
|
+
// ----- Date Button 配置 -----
|
|
65
|
+
calendarIconClass?: string;
|
|
66
|
+
calendarClearIconClass?: string;
|
|
67
|
+
|
|
68
|
+
// ----- Button 配置 -----
|
|
69
|
+
changePasswordButtonClass?: string;
|
|
70
|
+
changePasswordButtonIcon?: string;
|
|
71
|
+
|
|
72
|
+
// ----- Error 配置 -----
|
|
73
|
+
errorClass?: string;
|
|
74
|
+
errorPrefix?: string;
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* BSFieldStyleConfig 類別
|
|
80
|
+
*/
|
|
81
|
+
export class BSFieldStyleConfig {
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 單一實例
|
|
85
|
+
*/
|
|
86
|
+
static instance: BSFieldStyleConfig = new BSFieldStyleConfig();
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 合併配置
|
|
90
|
+
* @param config 要合併到全域實例的配置
|
|
91
|
+
*/
|
|
92
|
+
static merge(config: IBSFieldStyleConfig) {
|
|
93
|
+
this.instance.config = { ...this.instance.config, ...config };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 混合多個樣式配置,建立新的 BSFieldStyleConfig 實例
|
|
98
|
+
* 優先順序:propStyle > defaultStyle > instance(全域設定)
|
|
99
|
+
*
|
|
100
|
+
* @param defaultStyle 預設樣式配置(例如組件內建的預設值)
|
|
101
|
+
* @param propStyle 組件 prop 傳入的樣式配置
|
|
102
|
+
* @returns 合併後的 BSFieldStyleConfig 實例
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // 在組件中使用
|
|
107
|
+
* const bStyleConfig = BSFieldStyleConfig.mix(
|
|
108
|
+
* { plainTextClass: 'form-control-plaintext bg-light' }, // 組件預設值
|
|
109
|
+
* props.styleConfig // 從 prop 傳入的值
|
|
110
|
+
* );
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
static mix(defaultStyle: IBSFieldStyleConfig, propStyle?: IBSFieldStyleConfig): BSFieldStyleConfig {
|
|
114
|
+
// 合併順序:預設樣式 <- 全域設定 <- prop 樣式
|
|
115
|
+
const mergedConfig = {
|
|
116
|
+
...defaultStyle,
|
|
117
|
+
...this.instance.config,
|
|
118
|
+
...(propStyle || {})
|
|
119
|
+
};
|
|
120
|
+
return new BSFieldStyleConfig(mergedConfig);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ~ ----------------------------------------------------------
|
|
124
|
+
// ~ constructor
|
|
125
|
+
|
|
126
|
+
constructor(public config: IBSFieldStyleConfig = {}) {
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 取得容器 class
|
|
130
|
+
get containerClass(): string {
|
|
131
|
+
return this.config.containerClass || 'form-group';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 取得 label class
|
|
135
|
+
get labelClass(): string {
|
|
136
|
+
return this.config.labelClass || 'form-label';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 取得 input class
|
|
140
|
+
get inputClass(): string {
|
|
141
|
+
return this.config.inputClass || 'form-control';
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 取得 wrapper class(用於 input-group)
|
|
145
|
+
get wrapperClass(): string {
|
|
146
|
+
return this.config.wrapperClass || 'input-group';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 取得 error class
|
|
150
|
+
get errorClass(): string {
|
|
151
|
+
return this.config.errorClass || 'invalid-feedback d-block mt-1';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 是否隱藏 label
|
|
155
|
+
get hideLabel(): boolean {
|
|
156
|
+
return this.config.hideLabel || false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 取得 required label class 樣式
|
|
160
|
+
get requiredLabelClass(): string {
|
|
161
|
+
return this.config.requiredLabelClass || 'text-danger px-1';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 取得 required label 文字
|
|
165
|
+
get requiredLabelText(): string {
|
|
166
|
+
return this.config.requiredLabelText || '*';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 取得 plain text class
|
|
170
|
+
get plainTextClass(): string {
|
|
171
|
+
return this.config.plainTextClass || 'form-control-plaintext';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 是否有 input prefix
|
|
175
|
+
get hasInputPrefix(): boolean {
|
|
176
|
+
return !!this.config.inputPrefix?.text;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 是否有 input suffix
|
|
180
|
+
get hasInputSuffix(): boolean {
|
|
181
|
+
return !!this.config.inputSuffix?.text;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 取得 input prefix text
|
|
185
|
+
get inputPrefixText(): string {
|
|
186
|
+
return this.config.inputPrefix?.text || '';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 取得 input suffix text
|
|
190
|
+
get inputSuffixText(): string {
|
|
191
|
+
return this.config.inputSuffix?.text || '';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 取得 input prefix class
|
|
195
|
+
get inputPrefixClass(): string {
|
|
196
|
+
return this.config.inputPrefix?.class || 'input-group-text';
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// 取得 input suffix class
|
|
200
|
+
get inputSuffixClass(): string {
|
|
201
|
+
return this.config.inputSuffix?.class || 'input-group-text';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ----- Select 相關屬性 -----
|
|
205
|
+
|
|
206
|
+
// 取得 select class
|
|
207
|
+
get selectClass(): string {
|
|
208
|
+
let baseClass = this.config.selectClass || 'form-select';
|
|
209
|
+
if (this.config.selectSize) {
|
|
210
|
+
baseClass += ` form-select-${this.config.selectSize}`;
|
|
211
|
+
}
|
|
212
|
+
return baseClass;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 是否多選 select
|
|
216
|
+
get selectMultiple(): boolean {
|
|
217
|
+
return this.config.selectMultiple || false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 取得 select placeholder
|
|
221
|
+
get selectPlaceholder(): string {
|
|
222
|
+
return this.config.selectPlaceholder || '';
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ----- Textarea 相關屬性 -----
|
|
226
|
+
|
|
227
|
+
// 取得 textarea class
|
|
228
|
+
get textareaClass(): string {
|
|
229
|
+
return this.config.textareaClass || 'form-control';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 取得 textarea rows
|
|
233
|
+
get textareaRows(): number {
|
|
234
|
+
return this.config.textareaRows || 3;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// 取得 textarea resize 樣式
|
|
238
|
+
get textareaResizeStyle(): string {
|
|
239
|
+
return this.config.textareaResize ? `resize: ${this.config.textareaResize}` : '';
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// 是否自動調整高度
|
|
243
|
+
get textareaAutoGrow(): boolean {
|
|
244
|
+
return this.config.textareaAutoGrow || false;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ----- Checkbox 相關屬性 -----
|
|
248
|
+
|
|
249
|
+
// 取得 checkbox class
|
|
250
|
+
get checkboxClass(): string {
|
|
251
|
+
return this.config.checkboxClass || 'form-check-input';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 取得 checkbox label class
|
|
255
|
+
get checkboxLabelClass(): string {
|
|
256
|
+
return this.config.checkboxLabelClass || 'form-check-label';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 取得 checkbox wrapper class
|
|
260
|
+
get checkboxWrapperClass(): string {
|
|
261
|
+
return this.config.checkboxWrapperClass || 'form-check';
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
get checkboxHelperIconClass(): string {
|
|
265
|
+
return this.config.checkboxHelperIconClass || '';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ----- Radio 相關屬性 -----
|
|
269
|
+
|
|
270
|
+
// 取得 radio class
|
|
271
|
+
get radioClass(): string {
|
|
272
|
+
return this.config.radioClass || 'form-check-input';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// 取得 radio label class
|
|
276
|
+
get radioLabelClass(): string {
|
|
277
|
+
return this.config.radioLabelClass || 'form-check-label';
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// 取得 radio wrapper class
|
|
281
|
+
get radioWrapperClass(): string {
|
|
282
|
+
let baseClass = this.config.radioWrapperClass || 'form-check';
|
|
283
|
+
if (this.config.radioInline) {
|
|
284
|
+
baseClass += ' form-check-inline';
|
|
285
|
+
}
|
|
286
|
+
return baseClass;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// 是否 radio inline 排列
|
|
290
|
+
get radioInline(): boolean {
|
|
291
|
+
return this.config.radioInline || false;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 取得 radio helper icon class
|
|
295
|
+
get radioHelperIconClass(): string {
|
|
296
|
+
return this.config.radioHelperIconClass || '';
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ----- File Input 相關屬性 -----
|
|
300
|
+
|
|
301
|
+
// 取得 file input class
|
|
302
|
+
get fileClass(): string {
|
|
303
|
+
return this.config.fileClass || 'form-control';
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 取得 file accept 屬性
|
|
307
|
+
get fileAccept(): string {
|
|
308
|
+
return this.config.fileAccept || '';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 是否多檔案選擇
|
|
312
|
+
get fileMultiple(): boolean {
|
|
313
|
+
return this.config.fileMultiple || false;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// 是否支援拖放
|
|
317
|
+
get fileDragDrop(): boolean {
|
|
318
|
+
return this.config.fileDragDrop || false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ----- Date Button 相關屬性 -----
|
|
322
|
+
|
|
323
|
+
// 取得 calendar icon class
|
|
324
|
+
get calendarIconClass(): string {
|
|
325
|
+
return this.config.calendarIconClass || 'bi bi-calendar-event';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 取得 calendar clear icon class
|
|
329
|
+
get calendarClearIconClass(): string {
|
|
330
|
+
return this.config.calendarClearIconClass || 'bi bi-x-circle' ;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ----- button -----
|
|
334
|
+
// 取得 change password button class
|
|
335
|
+
get changePasswordButtonClass(): string {
|
|
336
|
+
return this.config.changePasswordButtonClass || 'btn btn-warning';
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 取得 change password button icon
|
|
340
|
+
get changePasswordButtonIcon(): string {
|
|
341
|
+
return this.config.changePasswordButtonIcon || '';
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ~ ----------------------------------------------------------
|
|
346
|
+
|
|
347
|
+
// 防止 Vite/rollup tree-shake 掉 type export
|
|
348
|
+
export const __BSFieldStyleConfigDefine__ = null as unknown as
|
|
349
|
+
IBSFieldStyleConfig;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseDictionary class
|
|
3
|
+
* 用於 distionary store 的基底類別
|
|
4
|
+
*/
|
|
5
|
+
export abstract class BaseDictionary {
|
|
6
|
+
protected data: Record<string, any> = {};
|
|
7
|
+
dataProvider: (key: string) => Promise<any> | any = () => ({});
|
|
8
|
+
lastUpdatedAt: number = Date.now();
|
|
9
|
+
|
|
10
|
+
protected constructor(data: Partial<BaseDictionary> = {}) {
|
|
11
|
+
if (data) {
|
|
12
|
+
Object.assign(this, data);
|
|
13
|
+
}
|
|
14
|
+
this.init();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 初始化方法,讓子類別可以覆寫以進行自訂初始化
|
|
19
|
+
* @protected
|
|
20
|
+
*/
|
|
21
|
+
abstract init():void;
|
|
22
|
+
|
|
23
|
+
val(key: string): any {
|
|
24
|
+
return this.data[key];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setVal(key: string, value: any): void {
|
|
28
|
+
this.data[key] = value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
hasVal(key: string): boolean {
|
|
32
|
+
return key in this.data;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 載入所有字典資料
|
|
37
|
+
* 使用 Promise.allSettled 確保即使某個載入失敗,其他的也能繼續執行
|
|
38
|
+
*/
|
|
39
|
+
async loadAll(): Promise<void> {
|
|
40
|
+
const keys = Object.keys(this.data);
|
|
41
|
+
const results = await Promise.allSettled(keys.map(key => this.loadDictionary(key)));
|
|
42
|
+
// 可選:記錄失敗的項目
|
|
43
|
+
results.forEach((result, index) => {
|
|
44
|
+
if (result.status === 'rejected') {
|
|
45
|
+
console.error(`Failed to load dictionary for key "${keys[index]}":`, result.reason);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* load dictionary data
|
|
52
|
+
* 支援 Promise 或是直接回傳資料物件
|
|
53
|
+
* @param key
|
|
54
|
+
*/
|
|
55
|
+
async loadDictionary(key: string): Promise<Record<string, any>> {
|
|
56
|
+
const result = this.dataProvider(key);
|
|
57
|
+
if (result instanceof Promise) {
|
|
58
|
+
return result.then(data => {
|
|
59
|
+
this.data[key] = data;
|
|
60
|
+
this.lastUpdatedAt = Date.now();
|
|
61
|
+
return data;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.data[key] = result;
|
|
65
|
+
this.lastUpdatedAt = Date.now();
|
|
66
|
+
return Promise.resolve(result);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
loadFromStore(storeData: Record<string, any>): this {
|
|
70
|
+
this.data = storeData.data || {};
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ~ ----------------------------------------------------------
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class CBaseDictionary extends BaseDictionary {
|
|
78
|
+
|
|
79
|
+
constructor(data: Partial<CBaseDictionary> = {}) {
|
|
80
|
+
super(data);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
init(): void {
|
|
84
|
+
// 子類別可覆寫此方法進行初始化
|
|
85
|
+
}
|
|
86
|
+
}
|