@kine-design/crud 0.0.1-beta.24 → 0.0.1-beta.26
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/.vlaude/last-session-id +1 -1
- package/components/crudPage/KCrudPage.tsx +6 -4
- package/components/editableTable/KEditableTable.tsx +11 -9
- package/components/formPage/KApprovalDialog.tsx +24 -23
- package/components/formPage/KFormPage.tsx +10 -5
- package/components/formPage/KMasterDetailPage.tsx +8 -6
- package/components/layout/KSider.tsx +4 -1
- package/components/login/KLoginPage.tsx +8 -6
- package/components/searchTable/KSearchTable.tsx +6 -3
- package/components/upload/KFileList.tsx +16 -8
- package/components/upload/KImageUpload.tsx +4 -2
- package/components/upload/KUpload.tsx +4 -2
- package/composables/error/dispatchError.ts +9 -7
- package/composables/form/renderFormField.tsx +6 -4
- package/composables/form/useFormPage.ts +3 -1
- package/composables/page/types.ts +2 -0
- package/composables/page/useCrudPage.ts +1 -0
- package/composables/request/requestBuilder.ts +8 -5
- package/composables/request/transport/xhrTransport.ts +3 -1
- package/composables/request/types.ts +8 -5
- package/composables/request/upload.ts +4 -2
- package/composables/router/defineCrudRoutes.ts +5 -3
- package/dist/components/editableTable/KEditableTable.d.ts +5 -5
- package/dist/composables/page/types.d.ts +2 -0
- package/dist/crud.css +57 -57
- package/dist/crud.js +1742 -1164
- package/package.json +3 -3
- package/tsconfig.json +12 -12
package/dist/crud.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Comment, Fragment, Teleport, cloneVNode, computed, createApp, createTextVNode, createVNode, defineComponent, h, inject, isRef, mergeProps, nextTick, onBeforeUnmount, onMounted, onUnmounted, provide, reactive, ref, resolveComponent, shallowRef, toRef, triggerRef, watch } from "vue";
|
|
2
|
-
import { QueryClient, VueQueryPlugin, useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
|
|
3
2
|
import { createPinia, defineStore } from "pinia";
|
|
3
|
+
import { QueryClient, VueQueryPlugin, useMutation, useQuery, useQueryClient } from "@tanstack/vue-query";
|
|
4
4
|
import { useRoute, useRouter } from "vue-router";
|
|
5
5
|
//#region \0rolldown/runtime.js
|
|
6
6
|
var __create = Object.create;
|
|
@@ -88,979 +88,594 @@ var KLayout_default = /* @__PURE__ */ defineComponent({
|
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
//#endregion
|
|
91
|
-
//#region components/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
collapsed: isCollapsed.value,
|
|
133
|
-
toggle
|
|
134
|
-
}) : defaultTrigger()])
|
|
135
|
-
]);
|
|
91
|
+
//#region ../core/components/base/input/api.ts
|
|
92
|
+
var props$10 = {
|
|
93
|
+
type: {
|
|
94
|
+
type: String,
|
|
95
|
+
default: "text"
|
|
96
|
+
},
|
|
97
|
+
placeholder: {
|
|
98
|
+
type: String,
|
|
99
|
+
default: ""
|
|
100
|
+
},
|
|
101
|
+
modelValue: {
|
|
102
|
+
type: [String, Number],
|
|
103
|
+
default: ""
|
|
104
|
+
},
|
|
105
|
+
readonly: {
|
|
106
|
+
type: Boolean,
|
|
107
|
+
default: false
|
|
108
|
+
},
|
|
109
|
+
disabled: {
|
|
110
|
+
type: Boolean,
|
|
111
|
+
default: false
|
|
112
|
+
},
|
|
113
|
+
autofocus: {
|
|
114
|
+
type: Boolean,
|
|
115
|
+
default: false
|
|
116
|
+
},
|
|
117
|
+
clearable: {
|
|
118
|
+
type: Boolean,
|
|
119
|
+
default: false
|
|
120
|
+
},
|
|
121
|
+
size: {
|
|
122
|
+
type: String,
|
|
123
|
+
default: void 0
|
|
124
|
+
},
|
|
125
|
+
maxlength: {
|
|
126
|
+
type: Number,
|
|
127
|
+
default: void 0
|
|
128
|
+
},
|
|
129
|
+
showWordLimit: {
|
|
130
|
+
type: Boolean,
|
|
131
|
+
default: false
|
|
136
132
|
}
|
|
137
|
-
}
|
|
133
|
+
};
|
|
138
134
|
//#endregion
|
|
139
|
-
//#region components/
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
135
|
+
//#region ../core/components/base/input/useInput.ts
|
|
136
|
+
function useInput(props, ctx) {
|
|
137
|
+
const isInput = props.type !== "textarea";
|
|
138
|
+
const inputType = isInput ? "input" : "textarea";
|
|
139
|
+
const inputClass = isInput ? "m-input-inner" : "m-textarea-inner";
|
|
140
|
+
const rowInfo = isInput ? {} : { rows: 10 };
|
|
141
|
+
const baseProps = {
|
|
142
|
+
autofocus: props.autofocus,
|
|
143
|
+
value: props.modelValue,
|
|
144
|
+
placeholder: props.placeholder,
|
|
145
|
+
disabled: props.disabled,
|
|
146
|
+
type: props.type,
|
|
147
|
+
readOnly: props.readonly,
|
|
148
|
+
maxLength: props.maxlength
|
|
149
|
+
};
|
|
150
|
+
const onInput = (e) => {
|
|
151
|
+
ctx.emit("update:modelValue", e.target.value);
|
|
152
|
+
ctx.emit("input", e.target.value);
|
|
153
|
+
};
|
|
154
|
+
const onFocus = (e) => {
|
|
155
|
+
ctx.emit("focus", e);
|
|
156
|
+
};
|
|
157
|
+
const onBlur = (e) => {
|
|
158
|
+
ctx.emit("blur", e);
|
|
159
|
+
};
|
|
160
|
+
const onClear = () => {
|
|
161
|
+
ctx.emit("update:modelValue", "");
|
|
162
|
+
ctx.emit("input", "");
|
|
163
|
+
ctx.emit("clear");
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
baseProps,
|
|
167
|
+
inputType,
|
|
168
|
+
inputClass,
|
|
169
|
+
rowInfo,
|
|
170
|
+
onInput,
|
|
171
|
+
onFocus,
|
|
172
|
+
onBlur,
|
|
173
|
+
onClear
|
|
174
|
+
};
|
|
175
|
+
}
|
|
162
176
|
//#endregion
|
|
163
|
-
//#region components/
|
|
177
|
+
//#region ../core/components/base/input/index.ts
|
|
164
178
|
/**
|
|
165
|
-
* @description
|
|
179
|
+
* @description
|
|
166
180
|
* @author 阿怪
|
|
167
|
-
* @date
|
|
168
|
-
* @version
|
|
181
|
+
* @date 2024/11/29 10:24
|
|
182
|
+
* @version v1.0.0
|
|
169
183
|
*
|
|
170
184
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
171
185
|
*/
|
|
172
|
-
var
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
});
|
|
186
|
+
var InputCore = {
|
|
187
|
+
props: props$10,
|
|
188
|
+
useInput
|
|
189
|
+
};
|
|
178
190
|
//#endregion
|
|
179
|
-
//#region ../core/components/
|
|
180
|
-
var props$
|
|
181
|
-
|
|
182
|
-
type: Array,
|
|
183
|
-
default: () => []
|
|
184
|
-
},
|
|
185
|
-
height: {
|
|
191
|
+
//#region ../core/components/base/button/api.ts
|
|
192
|
+
var props$9 = {
|
|
193
|
+
text: {
|
|
186
194
|
type: String,
|
|
187
|
-
default:
|
|
195
|
+
default: ""
|
|
188
196
|
},
|
|
189
|
-
|
|
197
|
+
link: {
|
|
198
|
+
type: Boolean,
|
|
199
|
+
default: false
|
|
200
|
+
},
|
|
201
|
+
disabled: {
|
|
190
202
|
type: Boolean,
|
|
191
203
|
default: false
|
|
192
204
|
},
|
|
193
205
|
loading: {
|
|
194
206
|
type: Boolean,
|
|
195
207
|
default: false
|
|
208
|
+
},
|
|
209
|
+
plain: {
|
|
210
|
+
type: Boolean,
|
|
211
|
+
default: false
|
|
212
|
+
},
|
|
213
|
+
type: {
|
|
214
|
+
type: String,
|
|
215
|
+
default: "default",
|
|
216
|
+
enum: [
|
|
217
|
+
"default",
|
|
218
|
+
"primary",
|
|
219
|
+
"success",
|
|
220
|
+
"warning",
|
|
221
|
+
"danger",
|
|
222
|
+
"info"
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
size: {
|
|
226
|
+
type: String,
|
|
227
|
+
default: void 0,
|
|
228
|
+
enum: [
|
|
229
|
+
"large",
|
|
230
|
+
"medium",
|
|
231
|
+
"small"
|
|
232
|
+
]
|
|
196
233
|
}
|
|
197
234
|
};
|
|
198
235
|
//#endregion
|
|
199
|
-
//#region ../core/components/
|
|
236
|
+
//#region ../core/components/base/button/useButton.ts
|
|
237
|
+
function useButton(props, { slots }) {
|
|
238
|
+
const domType = props.link ? "a" : "button";
|
|
239
|
+
const slot = slots.default?.() ?? props.text;
|
|
240
|
+
const isDisabled = props.disabled || props.loading;
|
|
241
|
+
return {
|
|
242
|
+
domType,
|
|
243
|
+
slot,
|
|
244
|
+
domProps: {
|
|
245
|
+
class: [
|
|
246
|
+
"m-button",
|
|
247
|
+
{ "m-button-disabled": isDisabled },
|
|
248
|
+
{ "m-button-loading": props.loading },
|
|
249
|
+
{ "m-button-plain": props.plain },
|
|
250
|
+
`m-button-${props.type ?? "default"}`,
|
|
251
|
+
`m-button-${props.size ?? "medium"}`
|
|
252
|
+
],
|
|
253
|
+
disabled: isDisabled
|
|
254
|
+
},
|
|
255
|
+
isDisabled
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region ../core/components/base/button/index.ts
|
|
200
260
|
/**
|
|
201
|
-
* @description
|
|
261
|
+
* @description
|
|
202
262
|
* @author 阿怪
|
|
203
|
-
* @date
|
|
263
|
+
* @date 2024/12/16 09:44
|
|
204
264
|
* @version v1.0.0
|
|
205
265
|
*
|
|
206
266
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
207
267
|
*/
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
268
|
+
var ButtonCore = {
|
|
269
|
+
props: props$9,
|
|
270
|
+
useButton
|
|
271
|
+
};
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region ../core/components/base/select/api.ts
|
|
274
|
+
var props$8 = {
|
|
275
|
+
modelValue: {
|
|
276
|
+
type: void 0,
|
|
277
|
+
default: ""
|
|
278
|
+
},
|
|
279
|
+
options: {
|
|
280
|
+
type: Array,
|
|
281
|
+
default: () => []
|
|
282
|
+
},
|
|
283
|
+
inputParam: {
|
|
284
|
+
type: String,
|
|
285
|
+
default: void 0
|
|
286
|
+
},
|
|
287
|
+
optionParam: {
|
|
288
|
+
type: String,
|
|
289
|
+
default: void 0
|
|
290
|
+
},
|
|
291
|
+
valueParam: {
|
|
292
|
+
type: String,
|
|
293
|
+
default: void 0
|
|
294
|
+
},
|
|
295
|
+
readonly: {
|
|
296
|
+
type: Boolean,
|
|
297
|
+
default: true
|
|
298
|
+
},
|
|
299
|
+
disabled: {
|
|
300
|
+
type: Boolean,
|
|
301
|
+
default: false
|
|
302
|
+
},
|
|
303
|
+
placeholder: {
|
|
304
|
+
type: String,
|
|
305
|
+
default: void 0
|
|
306
|
+
},
|
|
307
|
+
toMatch: {
|
|
308
|
+
type: Function,
|
|
309
|
+
default: void 0
|
|
310
|
+
},
|
|
311
|
+
multiple: {
|
|
312
|
+
type: Boolean,
|
|
313
|
+
default: false
|
|
314
|
+
},
|
|
315
|
+
checkbox: {
|
|
316
|
+
type: Boolean,
|
|
317
|
+
default: true
|
|
318
|
+
},
|
|
319
|
+
filterable: {
|
|
320
|
+
type: Boolean,
|
|
321
|
+
default: false
|
|
322
|
+
},
|
|
323
|
+
filter: {
|
|
324
|
+
type: Function,
|
|
325
|
+
default: void 0
|
|
326
|
+
},
|
|
327
|
+
optionsH: {
|
|
328
|
+
type: [Number, String],
|
|
329
|
+
default: void 0
|
|
330
|
+
},
|
|
331
|
+
needFetch: {
|
|
332
|
+
type: Boolean,
|
|
333
|
+
default: false
|
|
334
|
+
},
|
|
335
|
+
fetch: {
|
|
336
|
+
type: Function,
|
|
337
|
+
default: void 0
|
|
338
|
+
},
|
|
339
|
+
clearable: {
|
|
340
|
+
type: Boolean,
|
|
341
|
+
default: false
|
|
342
|
+
},
|
|
343
|
+
size: {
|
|
344
|
+
type: String,
|
|
345
|
+
default: void 0
|
|
346
|
+
},
|
|
347
|
+
loading: {
|
|
348
|
+
type: Boolean,
|
|
349
|
+
default: false
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region ../core/components/base/select/useSelectTools.ts
|
|
354
|
+
function useSelectTools(props) {
|
|
355
|
+
/** 从 option 中取指定 key 的值 */
|
|
356
|
+
const getInfoWithKey = (option, key) => {
|
|
357
|
+
const paramKey = props[key];
|
|
358
|
+
if (!paramKey) {
|
|
359
|
+
if (option && typeof option === "object") {
|
|
360
|
+
if ("label" in option) return option.label;
|
|
361
|
+
if ("name" in option) return option.name;
|
|
362
|
+
if ("text" in option) return option.text;
|
|
225
363
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
* 初始化表头,同时将每列对应的 td 推入 tbodyTrList
|
|
248
|
-
*/
|
|
249
|
-
const initTHead = () => {
|
|
250
|
-
const ths = (columns ?? []).filter((column) => {
|
|
251
|
-
if (!column.props) {
|
|
252
|
-
error("column.props is undefined, column without param will be ignored!");
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
return true;
|
|
256
|
-
}).map((column) => {
|
|
257
|
-
const slots = renders.initSlot(column);
|
|
258
|
-
let bodySlot;
|
|
259
|
-
let headSlot;
|
|
260
|
-
const style = getStyle(column.props);
|
|
261
|
-
if (slots) {
|
|
262
|
-
bodySlot = slots.body;
|
|
263
|
-
headSlot = slots.head;
|
|
264
|
-
}
|
|
265
|
-
pushTd(column.props.param, bodySlot, style);
|
|
266
|
-
return renders.theadTh({
|
|
267
|
-
label: column.props.label,
|
|
268
|
-
param: column.props.param,
|
|
269
|
-
slot: headSlot,
|
|
270
|
-
style
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
return renders.thead(ths);
|
|
274
|
-
};
|
|
275
|
-
return {
|
|
276
|
-
thead: initTHead(),
|
|
277
|
-
tbody: tbodyTrList.length > 0 ? renders.tbody(tbodyTrList.map((tds, i) => renders.tbodyTrs(tds, i))) : renders.empty
|
|
278
|
-
};
|
|
364
|
+
return option;
|
|
365
|
+
}
|
|
366
|
+
try {
|
|
367
|
+
return option[paramKey];
|
|
368
|
+
} catch {
|
|
369
|
+
return option;
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
/** 输入框显示值 */
|
|
373
|
+
const getInputValue = (option) => {
|
|
374
|
+
return String(getInfoWithKey(option, "inputParam") ?? "");
|
|
375
|
+
};
|
|
376
|
+
/** 下拉列表显示值 */
|
|
377
|
+
const getOptionValue = (option) => {
|
|
378
|
+
return String(getInfoWithKey(option, "optionParam") ?? "");
|
|
379
|
+
};
|
|
380
|
+
/** modelValue 绑定值 */
|
|
381
|
+
const getModelValue = (option) => {
|
|
382
|
+
if (props.valueParam) return getInfoWithKey(option, "valueParam");
|
|
383
|
+
if (option && typeof option === "object" && "value" in option) return option.value;
|
|
384
|
+
return option;
|
|
279
385
|
};
|
|
280
386
|
return {
|
|
281
|
-
|
|
282
|
-
|
|
387
|
+
getInfoWithKey,
|
|
388
|
+
getInputValue,
|
|
389
|
+
getOptionValue,
|
|
390
|
+
getModelValue
|
|
283
391
|
};
|
|
284
392
|
}
|
|
285
393
|
//#endregion
|
|
286
|
-
//#region ../core/components/
|
|
394
|
+
//#region ../core/components/base/select/useSelect.ts
|
|
287
395
|
/**
|
|
288
|
-
* @description
|
|
396
|
+
* @description select 核心 composable
|
|
289
397
|
* @author 阿怪
|
|
290
|
-
* @date 2026/2/25
|
|
291
|
-
* @version v1.0.
|
|
398
|
+
* @date 2026/2/25 14:40
|
|
399
|
+
* @version v1.0.1
|
|
292
400
|
*
|
|
293
401
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
294
|
-
*/
|
|
295
|
-
var TableCore = {
|
|
296
|
-
props: props$10,
|
|
297
|
-
useTable
|
|
298
|
-
};
|
|
299
|
-
//#endregion
|
|
300
|
-
//#region ../core/compositions/common/testAnchor.ts
|
|
301
|
-
/**
|
|
302
|
-
* @description Test anchor system: provide/inject keys, types, and kDefineComponent wrapper
|
|
303
|
-
* @author kine-design
|
|
304
|
-
* @date 2026/4/28
|
|
305
|
-
* @version v1.0.0
|
|
306
402
|
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
var K_TEST_ANCHOR_KEY = Symbol("k-test-anchor");
|
|
312
|
-
/** Field identity provided by KFormItem so child inputs inherit field name */
|
|
313
|
-
var K_FIELD_KEY = Symbol("k-field");
|
|
314
|
-
/**
|
|
315
|
-
* Extract text content from a VNode tree (for slotText mode).
|
|
316
|
-
* Walks children recursively, concatenating string segments.
|
|
317
|
-
*/
|
|
318
|
-
function extractSlotText(nodes) {
|
|
319
|
-
if (!nodes) return "";
|
|
320
|
-
let text = "";
|
|
321
|
-
for (const node of nodes) if (typeof node.children === "string") text += node.children;
|
|
322
|
-
else if (Array.isArray(node.children)) text += extractSlotText(node.children);
|
|
323
|
-
return text.trim();
|
|
324
|
-
}
|
|
325
|
-
/**
|
|
326
|
-
* Resolve the data-k value for a component instance.
|
|
327
|
-
* Returns undefined when testAnchor is off or no identity can be derived.
|
|
328
|
-
*/
|
|
329
|
-
function resolveDataK(config, props, attrs, fieldFromParent, slotNodes) {
|
|
330
|
-
const override = attrs[`k-${config.type}`];
|
|
331
|
-
if (typeof override === "string" && override) return `${config.type}:${override}`;
|
|
332
|
-
if (config.prop) {
|
|
333
|
-
const val = props[config.prop];
|
|
334
|
-
if (typeof val === "string" && val) return `${config.type}:${val}`;
|
|
335
|
-
}
|
|
336
|
-
if (config.slotText && slotNodes) {
|
|
337
|
-
const text = extractSlotText(slotNodes);
|
|
338
|
-
if (text) return `${config.type}:${text}`;
|
|
339
|
-
}
|
|
340
|
-
if (config.slotText && typeof props.text === "string" && props.text) return `${config.type}:${props.text}`;
|
|
341
|
-
if (config.type === "field" && !config.prop && fieldFromParent) return `${config.type}:${fieldFromParent}`;
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Inject data-k attribute into a VNode.
|
|
345
|
-
* Uses cloneVNode to avoid mutating the original.
|
|
403
|
+
* 用 computed + ref 替代原 class 继承方案
|
|
404
|
+
* 单选/多选通过 props.multiple 分支处理
|
|
405
|
+
* fetch 通过 IntersectionObserver 观察最后一个选项实现
|
|
406
|
+
* v1.0.1 新增 filterable 支持:开启后 inputReadonly 为 false,可输入过滤 阿怪 2026/2/27
|
|
346
407
|
*/
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if (
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
408
|
+
function useSelect$1(props, ctx) {
|
|
409
|
+
const tools = useSelectTools(props);
|
|
410
|
+
const optionsRef = toRef(() => props.options ?? []);
|
|
411
|
+
const modelValueRef = toRef(() => props.modelValue);
|
|
412
|
+
const multipleRef = toRef(() => props.multiple ?? false);
|
|
413
|
+
/**
|
|
414
|
+
* 输入框是否只读:
|
|
415
|
+
* - filterable=true 时强制可编辑(忽略 readonly prop)
|
|
416
|
+
* - 否则沿用 props.readonly(默认 true)
|
|
417
|
+
*/
|
|
418
|
+
const inputReadonly = toRef(() => props.filterable ? false : props.readonly ?? true);
|
|
419
|
+
const inputValue = ref("");
|
|
420
|
+
const isOpen = ref(false);
|
|
421
|
+
const fetchLoading = ref(false);
|
|
422
|
+
/** 多选时记录选中的索引集合 */
|
|
423
|
+
const selectedIndices = ref(/* @__PURE__ */ new Set());
|
|
424
|
+
/** 判断某个 option 是否选中 */
|
|
425
|
+
const isSelected = (option, index) => {
|
|
426
|
+
if (multipleRef.value) return selectedIndices.value.has(index);
|
|
427
|
+
if (props.toMatch) return props.toMatch(option, modelValueRef.value);
|
|
428
|
+
return modelValueRef.value === tools.getModelValue(option);
|
|
429
|
+
};
|
|
430
|
+
/** 全量选项(带 isSelected 标记) */
|
|
431
|
+
const allOptions = computed(() => {
|
|
432
|
+
return optionsRef.value.map((o, i) => ({
|
|
433
|
+
value: o,
|
|
434
|
+
index: i,
|
|
435
|
+
isSelected: isSelected(o, i)
|
|
436
|
+
}));
|
|
437
|
+
});
|
|
438
|
+
/** 过滤后的显示选项 */
|
|
439
|
+
const displayOptions = computed(() => {
|
|
440
|
+
return allOptions.value.filter((o) => {
|
|
441
|
+
if (inputReadonly.value) return true;
|
|
442
|
+
if (!inputValue.value) return true;
|
|
443
|
+
if (props.filter) return props.filter(o.value, inputValue.value);
|
|
444
|
+
return tools.getOptionValue(o.value).toLowerCase().includes(inputValue.value.toLowerCase());
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
/** 多选已选标签 */
|
|
448
|
+
const selectedTags = computed(() => {
|
|
449
|
+
if (!multipleRef.value) return [];
|
|
450
|
+
return allOptions.value.filter((o) => o.isSelected);
|
|
451
|
+
});
|
|
452
|
+
const syncInputFromModelValue = () => {
|
|
453
|
+
if (multipleRef.value) {
|
|
454
|
+
inputValue.value = "";
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
const mv = modelValueRef.value;
|
|
458
|
+
if (mv == null || mv === "") {
|
|
459
|
+
inputValue.value = "";
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
const found = optionsRef.value.find((o) => {
|
|
463
|
+
if (props.toMatch) return props.toMatch(o, mv);
|
|
464
|
+
return tools.getModelValue(o) === mv;
|
|
465
|
+
});
|
|
466
|
+
inputValue.value = found ? tools.getInputValue(found) : "";
|
|
467
|
+
};
|
|
468
|
+
/** 初始化多选选中状态 */
|
|
469
|
+
const syncSelectedFromModelValue = () => {
|
|
470
|
+
if (!multipleRef.value) return;
|
|
471
|
+
const mv = modelValueRef.value;
|
|
472
|
+
const newSet = /* @__PURE__ */ new Set();
|
|
473
|
+
if (Array.isArray(mv)) optionsRef.value.forEach((o, i) => {
|
|
474
|
+
const val = tools.getModelValue(o);
|
|
475
|
+
if (mv.includes(val)) newSet.add(i);
|
|
476
|
+
if (props.toMatch && mv.some((v) => props.toMatch(o, v))) newSet.add(i);
|
|
477
|
+
});
|
|
478
|
+
selectedIndices.value = newSet;
|
|
479
|
+
};
|
|
480
|
+
syncSelectedFromModelValue();
|
|
481
|
+
syncInputFromModelValue();
|
|
482
|
+
/** 点击选项 */
|
|
483
|
+
const onSelect = (index) => {
|
|
484
|
+
const option = optionsRef.value[index];
|
|
485
|
+
if (!option) return;
|
|
486
|
+
if (option.disabled) return;
|
|
487
|
+
if (multipleRef.value) {
|
|
488
|
+
const newSet = new Set(selectedIndices.value);
|
|
489
|
+
if (newSet.has(index)) newSet.delete(index);
|
|
490
|
+
else newSet.add(index);
|
|
491
|
+
selectedIndices.value = newSet;
|
|
492
|
+
inputValue.value = "";
|
|
493
|
+
const newModelValue = optionsRef.value.filter((_, i) => newSet.has(i)).map((o) => tools.getModelValue(o));
|
|
494
|
+
ctx.emit("update:modelValue", newModelValue);
|
|
495
|
+
ctx.emit("select", option);
|
|
496
|
+
} else {
|
|
497
|
+
inputValue.value = tools.getInputValue(option);
|
|
498
|
+
ctx.emit("update:modelValue", tools.getModelValue(option));
|
|
499
|
+
ctx.emit("select", option);
|
|
500
|
+
isOpen.value = false;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
/** 删除多选标签 */
|
|
504
|
+
const onDeleteTag = (index) => {
|
|
505
|
+
const newSet = new Set(selectedIndices.value);
|
|
506
|
+
newSet.delete(index);
|
|
507
|
+
selectedIndices.value = newSet;
|
|
508
|
+
const newModelValue = optionsRef.value.filter((_, i) => newSet.has(i)).map((o) => tools.getModelValue(o));
|
|
509
|
+
ctx.emit("update:modelValue", newModelValue);
|
|
510
|
+
};
|
|
511
|
+
/** 输入事件 */
|
|
512
|
+
const onInput = () => {
|
|
513
|
+
ctx.emit("input", inputValue.value);
|
|
514
|
+
};
|
|
515
|
+
/** 聚焦 */
|
|
516
|
+
const onFocus = (e) => {
|
|
517
|
+
if (inputReadonly.value) return;
|
|
518
|
+
ctx.emit("focus", e, inputValue.value);
|
|
519
|
+
};
|
|
520
|
+
/** 失焦 */
|
|
521
|
+
const onBlur = (e) => {
|
|
522
|
+
if (inputReadonly.value) return;
|
|
523
|
+
ctx.emit("blur", e, inputValue.value);
|
|
524
|
+
if (!multipleRef.value) {
|
|
525
|
+
const matched = displayOptions.value.find((o) => o.isSelected);
|
|
526
|
+
if (matched && inputValue.value === tools.getInputValue(matched.value)) return;
|
|
527
|
+
if (!inputValue.value) ctx.emit("update:modelValue", void 0);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
const lastOptionRef = ref(null);
|
|
531
|
+
const optionsContainerRef = ref(null);
|
|
532
|
+
let fetchObserver;
|
|
533
|
+
const cleanupFetchObserver = () => {
|
|
534
|
+
if (fetchObserver) {
|
|
535
|
+
fetchObserver.disconnect();
|
|
536
|
+
fetchObserver = void 0;
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
/** 更新 fetch observer:观察最后一个选项元素 */
|
|
540
|
+
const updateFetchObserver = () => {
|
|
541
|
+
cleanupFetchObserver();
|
|
542
|
+
if (!props.needFetch || !lastOptionRef.value || !optionsContainerRef.value) return;
|
|
543
|
+
fetchObserver = new IntersectionObserver(async (entries) => {
|
|
544
|
+
if (entries[0]?.isIntersecting && props.needFetch) {
|
|
545
|
+
fetchLoading.value = true;
|
|
546
|
+
await props.fetch?.();
|
|
547
|
+
fetchLoading.value = false;
|
|
385
548
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
549
|
+
}, {
|
|
550
|
+
root: optionsContainerRef.value,
|
|
551
|
+
threshold: 1
|
|
552
|
+
});
|
|
553
|
+
fetchObserver.observe(lastOptionRef.value);
|
|
554
|
+
};
|
|
555
|
+
watch(modelValueRef, () => {
|
|
556
|
+
syncSelectedFromModelValue();
|
|
557
|
+
syncInputFromModelValue();
|
|
558
|
+
});
|
|
559
|
+
watch(optionsRef, () => {
|
|
560
|
+
syncSelectedFromModelValue();
|
|
561
|
+
syncInputFromModelValue();
|
|
562
|
+
}, { deep: true });
|
|
563
|
+
watch(lastOptionRef, () => {
|
|
564
|
+
updateFetchObserver();
|
|
565
|
+
});
|
|
566
|
+
onBeforeUnmount(cleanupFetchObserver);
|
|
567
|
+
return {
|
|
568
|
+
inputValue,
|
|
569
|
+
isOpen,
|
|
570
|
+
fetchLoading,
|
|
571
|
+
inputReadonly,
|
|
572
|
+
displayOptions,
|
|
573
|
+
selectedTags,
|
|
574
|
+
lastOptionRef,
|
|
575
|
+
optionsContainerRef,
|
|
576
|
+
onSelect,
|
|
577
|
+
onDeleteTag,
|
|
578
|
+
onInput,
|
|
579
|
+
onFocus,
|
|
580
|
+
onBlur,
|
|
581
|
+
tools,
|
|
582
|
+
updateFetchObserver
|
|
583
|
+
};
|
|
389
584
|
}
|
|
390
585
|
//#endregion
|
|
391
|
-
//#region ../
|
|
586
|
+
//#region ../core/components/base/select/index.ts
|
|
392
587
|
/**
|
|
393
|
-
* @description
|
|
588
|
+
* @description select core 导出
|
|
394
589
|
* @author 阿怪
|
|
395
|
-
* @date 2026/2/
|
|
396
|
-
* @version
|
|
590
|
+
* @date 2026/2/25 14:50
|
|
591
|
+
* @version v2.0.0
|
|
397
592
|
*
|
|
398
593
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
594
|
+
*/
|
|
595
|
+
var SelectCore = {
|
|
596
|
+
props: props$8,
|
|
597
|
+
useSelect: useSelect$1
|
|
598
|
+
};
|
|
599
|
+
//#endregion
|
|
600
|
+
//#region ../core/components/base/tag/index.ts
|
|
601
|
+
/**
|
|
602
|
+
* @description tag core
|
|
603
|
+
* @author 阿怪
|
|
604
|
+
* @date 2025/02/25 00:00
|
|
605
|
+
* @version v1.0.0
|
|
399
606
|
*
|
|
400
|
-
*
|
|
607
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
401
608
|
*/
|
|
402
|
-
var { props:
|
|
403
|
-
var KTable_default = kDefineComponent((_props, { slots }) => {
|
|
404
|
-
const p = _props;
|
|
405
|
-
const { initTable } = useTable();
|
|
406
|
-
const testAnchor = inject(K_TEST_ANCHOR_KEY, void 0);
|
|
407
|
-
return () => {
|
|
408
|
-
const columns = [];
|
|
409
|
-
(slots.default?.() ?? []).forEach((s) => {
|
|
410
|
-
if (s.type === Fragment) {
|
|
411
|
-
s.children?.forEach((c) => columns.push(c));
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
if (s.type === Comment) return;
|
|
415
|
-
if (typeof s.type === "object" && s.type.name === "KTableColumn") columns.push(s);
|
|
416
|
-
});
|
|
417
|
-
const style = p.height ? { height: p.height } : void 0;
|
|
418
|
-
const { thead, tbody } = initTable({
|
|
419
|
-
empty: createVNode("tbody", { "class": "m-table-empty k-table-empty" }, [createVNode("tr", null, [createVNode("th", { "colspan": columns.length }, [slots.empty?.() ?? "暂无数据"])])]),
|
|
420
|
-
tbodyTr: ({ data, param, slot, style: cellStyle, slotInfo }) => createVNode("td", {
|
|
421
|
-
"style": cellStyle,
|
|
422
|
-
"data-k": testAnchor?.value && param ? `col:${param}` : void 0,
|
|
423
|
-
"class": [
|
|
424
|
-
"m-td",
|
|
425
|
-
"k-td",
|
|
426
|
-
p.paramClass ? `m-td-${param}` : null,
|
|
427
|
-
p.paramClass ? `k-td-${param}` : null
|
|
428
|
-
]
|
|
429
|
-
}, [slot ? slot({
|
|
430
|
-
data: slotInfo?.data,
|
|
431
|
-
row: slotInfo?.data,
|
|
432
|
-
index: slotInfo?.index
|
|
433
|
-
}) : data]),
|
|
434
|
-
theadTh: ({ label, param, slot, style: cellStyle }) => createVNode("th", {
|
|
435
|
-
"class": [
|
|
436
|
-
"m-th",
|
|
437
|
-
"k-th",
|
|
438
|
-
p.paramClass ? `m-th-${param}` : null,
|
|
439
|
-
p.paramClass ? `k-th-${param}` : null
|
|
440
|
-
],
|
|
441
|
-
"style": cellStyle
|
|
442
|
-
}, [slot ? slot() : label]),
|
|
443
|
-
thead: (ths) => createVNode("thead", { "class": "m-thead k-thead" }, [createVNode("tr", { "class": "m-tr k-tr" }, [ths])]),
|
|
444
|
-
tbody: (trs) => createVNode("tbody", { "class": "m-tbody k-tbody" }, [trs]),
|
|
445
|
-
tbodyTrs: (tds, i) => createVNode("tr", {
|
|
446
|
-
"class": "m-tr k-tr",
|
|
447
|
-
"key": i
|
|
448
|
-
}, [...tds]),
|
|
449
|
-
initSlot: (tableColumn) => {
|
|
450
|
-
const children = tableColumn.children;
|
|
451
|
-
if (!children || Array.isArray(children) || typeof children !== "object") return;
|
|
452
|
-
return {
|
|
453
|
-
body: children.default,
|
|
454
|
-
head: children.head
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
}, columns, p.data);
|
|
458
|
-
return createVNode("div", {
|
|
459
|
-
"class": [
|
|
460
|
-
"m-table",
|
|
461
|
-
"k-table",
|
|
462
|
-
p.loading && "k-table-loading-wrap"
|
|
463
|
-
],
|
|
464
|
-
"style": style
|
|
465
|
-
}, [p.loading && createVNode("div", { "class": "k-table-loading-overlay" }, [createVNode("div", { "class": "k-table-loading-spinner" }, null)]), createVNode("table", { "class": "m-table-inner k-table-inner" }, [thead, tbody])]);
|
|
466
|
-
};
|
|
467
|
-
}, {
|
|
468
|
-
name: "KTable",
|
|
469
|
-
props: props$9,
|
|
470
|
-
kAnchor: {
|
|
471
|
-
type: "table",
|
|
472
|
-
prop: "name"
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
//#endregion
|
|
476
|
-
//#region ../core/components/base/input/api.ts
|
|
477
|
-
var props$8 = {
|
|
609
|
+
var TagCore = { props: {
|
|
478
610
|
type: {
|
|
479
611
|
type: String,
|
|
480
|
-
default: "
|
|
481
|
-
},
|
|
482
|
-
placeholder: {
|
|
483
|
-
type: String,
|
|
484
|
-
default: ""
|
|
485
|
-
},
|
|
486
|
-
modelValue: {
|
|
487
|
-
type: [String, Number],
|
|
488
|
-
default: ""
|
|
489
|
-
},
|
|
490
|
-
readonly: {
|
|
491
|
-
type: Boolean,
|
|
492
|
-
default: false
|
|
493
|
-
},
|
|
494
|
-
disabled: {
|
|
495
|
-
type: Boolean,
|
|
496
|
-
default: false
|
|
497
|
-
},
|
|
498
|
-
autofocus: {
|
|
499
|
-
type: Boolean,
|
|
500
|
-
default: false
|
|
501
|
-
},
|
|
502
|
-
clearable: {
|
|
503
|
-
type: Boolean,
|
|
504
|
-
default: false
|
|
612
|
+
default: "default"
|
|
505
613
|
},
|
|
506
614
|
size: {
|
|
507
615
|
type: String,
|
|
508
616
|
default: void 0
|
|
509
617
|
},
|
|
510
|
-
|
|
511
|
-
type: Number,
|
|
512
|
-
default: void 0
|
|
513
|
-
},
|
|
514
|
-
showWordLimit: {
|
|
515
|
-
type: Boolean,
|
|
516
|
-
default: false
|
|
517
|
-
}
|
|
518
|
-
};
|
|
519
|
-
//#endregion
|
|
520
|
-
//#region ../core/components/base/input/useInput.ts
|
|
521
|
-
function useInput(props, ctx) {
|
|
522
|
-
const isInput = props.type !== "textarea";
|
|
523
|
-
const inputType = isInput ? "input" : "textarea";
|
|
524
|
-
const inputClass = isInput ? "m-input-inner" : "m-textarea-inner";
|
|
525
|
-
const rowInfo = isInput ? {} : { rows: 10 };
|
|
526
|
-
const baseProps = {
|
|
527
|
-
autofocus: props.autofocus,
|
|
528
|
-
value: props.modelValue,
|
|
529
|
-
placeholder: props.placeholder,
|
|
530
|
-
disabled: props.disabled,
|
|
531
|
-
type: props.type,
|
|
532
|
-
readOnly: props.readonly,
|
|
533
|
-
maxLength: props.maxlength
|
|
534
|
-
};
|
|
535
|
-
const onInput = (e) => {
|
|
536
|
-
ctx.emit("update:modelValue", e.target.value);
|
|
537
|
-
ctx.emit("input", e.target.value);
|
|
538
|
-
};
|
|
539
|
-
const onFocus = (e) => {
|
|
540
|
-
ctx.emit("focus", e);
|
|
541
|
-
};
|
|
542
|
-
const onBlur = (e) => {
|
|
543
|
-
ctx.emit("blur", e);
|
|
544
|
-
};
|
|
545
|
-
const onClear = () => {
|
|
546
|
-
ctx.emit("update:modelValue", "");
|
|
547
|
-
ctx.emit("input", "");
|
|
548
|
-
ctx.emit("clear");
|
|
549
|
-
};
|
|
550
|
-
return {
|
|
551
|
-
baseProps,
|
|
552
|
-
inputType,
|
|
553
|
-
inputClass,
|
|
554
|
-
rowInfo,
|
|
555
|
-
onInput,
|
|
556
|
-
onFocus,
|
|
557
|
-
onBlur,
|
|
558
|
-
onClear
|
|
559
|
-
};
|
|
560
|
-
}
|
|
561
|
-
//#endregion
|
|
562
|
-
//#region ../core/components/base/input/index.ts
|
|
563
|
-
/**
|
|
564
|
-
* @description
|
|
565
|
-
* @author 阿怪
|
|
566
|
-
* @date 2024/11/29 10:24
|
|
567
|
-
* @version v1.0.0
|
|
568
|
-
*
|
|
569
|
-
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
570
|
-
*/
|
|
571
|
-
var InputCore = {
|
|
572
|
-
props: props$8,
|
|
573
|
-
useInput
|
|
574
|
-
};
|
|
575
|
-
//#endregion
|
|
576
|
-
//#region ../core/components/base/button/api.ts
|
|
577
|
-
var props$7 = {
|
|
578
|
-
text: {
|
|
579
|
-
type: String,
|
|
580
|
-
default: ""
|
|
581
|
-
},
|
|
582
|
-
link: {
|
|
618
|
+
closable: {
|
|
583
619
|
type: Boolean,
|
|
584
620
|
default: false
|
|
585
621
|
},
|
|
586
622
|
disabled: {
|
|
587
623
|
type: Boolean,
|
|
588
624
|
default: false
|
|
589
|
-
},
|
|
590
|
-
loading: {
|
|
591
|
-
type: Boolean,
|
|
592
|
-
default: false
|
|
593
|
-
},
|
|
594
|
-
plain: {
|
|
595
|
-
type: Boolean,
|
|
596
|
-
default: false
|
|
597
|
-
},
|
|
598
|
-
type: {
|
|
599
|
-
type: String,
|
|
600
|
-
default: "default",
|
|
601
|
-
enum: [
|
|
602
|
-
"default",
|
|
603
|
-
"primary",
|
|
604
|
-
"success",
|
|
605
|
-
"warning",
|
|
606
|
-
"danger",
|
|
607
|
-
"info"
|
|
608
|
-
]
|
|
609
|
-
},
|
|
610
|
-
size: {
|
|
611
|
-
type: String,
|
|
612
|
-
default: void 0,
|
|
613
|
-
enum: [
|
|
614
|
-
"large",
|
|
615
|
-
"medium",
|
|
616
|
-
"small"
|
|
617
|
-
]
|
|
618
625
|
}
|
|
619
|
-
};
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
function
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
{ "m-button-disabled": isDisabled },
|
|
633
|
-
{ "m-button-loading": props.loading },
|
|
634
|
-
{ "m-button-plain": props.plain },
|
|
635
|
-
`m-button-${props.type ?? "default"}`,
|
|
636
|
-
`m-button-${props.size ?? "medium"}`
|
|
637
|
-
],
|
|
638
|
-
disabled: isDisabled
|
|
639
|
-
},
|
|
640
|
-
isDisabled
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
//#endregion
|
|
644
|
-
//#region ../core/components/base/button/index.ts
|
|
645
|
-
/**
|
|
646
|
-
* @description
|
|
647
|
-
* @author 阿怪
|
|
648
|
-
* @date 2024/12/16 09:44
|
|
649
|
-
* @version v1.0.0
|
|
650
|
-
*
|
|
651
|
-
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
652
|
-
*/
|
|
653
|
-
var ButtonCore = {
|
|
654
|
-
props: props$7,
|
|
655
|
-
useButton
|
|
656
|
-
};
|
|
657
|
-
//#endregion
|
|
658
|
-
//#region ../core/components/base/select/api.ts
|
|
659
|
-
var props$6 = {
|
|
660
|
-
modelValue: {
|
|
661
|
-
type: void 0,
|
|
662
|
-
default: ""
|
|
663
|
-
},
|
|
664
|
-
options: {
|
|
665
|
-
type: Array,
|
|
666
|
-
default: () => []
|
|
667
|
-
},
|
|
668
|
-
inputParam: {
|
|
669
|
-
type: String,
|
|
670
|
-
default: void 0
|
|
671
|
-
},
|
|
672
|
-
optionParam: {
|
|
673
|
-
type: String,
|
|
674
|
-
default: void 0
|
|
675
|
-
},
|
|
676
|
-
valueParam: {
|
|
677
|
-
type: String,
|
|
678
|
-
default: void 0
|
|
679
|
-
},
|
|
680
|
-
readonly: {
|
|
681
|
-
type: Boolean,
|
|
682
|
-
default: true
|
|
683
|
-
},
|
|
684
|
-
disabled: {
|
|
685
|
-
type: Boolean,
|
|
686
|
-
default: false
|
|
687
|
-
},
|
|
688
|
-
placeholder: {
|
|
689
|
-
type: String,
|
|
690
|
-
default: "请选择..."
|
|
691
|
-
},
|
|
692
|
-
toMatch: {
|
|
693
|
-
type: Function,
|
|
694
|
-
default: void 0
|
|
695
|
-
},
|
|
696
|
-
multiple: {
|
|
697
|
-
type: Boolean,
|
|
698
|
-
default: false
|
|
699
|
-
},
|
|
700
|
-
checkbox: {
|
|
701
|
-
type: Boolean,
|
|
702
|
-
default: true
|
|
703
|
-
},
|
|
704
|
-
filterable: {
|
|
705
|
-
type: Boolean,
|
|
706
|
-
default: false
|
|
707
|
-
},
|
|
708
|
-
filter: {
|
|
709
|
-
type: Function,
|
|
710
|
-
default: void 0
|
|
711
|
-
},
|
|
712
|
-
optionsH: {
|
|
713
|
-
type: [Number, String],
|
|
714
|
-
default: void 0
|
|
715
|
-
},
|
|
716
|
-
needFetch: {
|
|
717
|
-
type: Boolean,
|
|
718
|
-
default: false
|
|
719
|
-
},
|
|
720
|
-
fetch: {
|
|
721
|
-
type: Function,
|
|
722
|
-
default: void 0
|
|
723
|
-
},
|
|
724
|
-
clearable: {
|
|
725
|
-
type: Boolean,
|
|
726
|
-
default: false
|
|
727
|
-
},
|
|
728
|
-
size: {
|
|
729
|
-
type: String,
|
|
730
|
-
default: void 0
|
|
731
|
-
},
|
|
732
|
-
loading: {
|
|
733
|
-
type: Boolean,
|
|
734
|
-
default: false
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
//#endregion
|
|
738
|
-
//#region ../core/components/base/select/useSelectTools.ts
|
|
739
|
-
function useSelectTools(props) {
|
|
740
|
-
/** 从 option 中取指定 key 的值 */
|
|
741
|
-
const getInfoWithKey = (option, key) => {
|
|
742
|
-
const paramKey = props[key];
|
|
743
|
-
if (!paramKey) {
|
|
744
|
-
if (option && typeof option === "object") {
|
|
745
|
-
if ("label" in option) return option.label;
|
|
746
|
-
if ("name" in option) return option.name;
|
|
747
|
-
if ("text" in option) return option.text;
|
|
626
|
+
} };
|
|
627
|
+
(/* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
628
|
+
(function(t, e) {
|
|
629
|
+
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).interact = e();
|
|
630
|
+
})(exports, (function() {
|
|
631
|
+
"use strict";
|
|
632
|
+
function t(t, e) {
|
|
633
|
+
var n = Object.keys(t);
|
|
634
|
+
if (Object.getOwnPropertySymbols) {
|
|
635
|
+
var r = Object.getOwnPropertySymbols(t);
|
|
636
|
+
e && (r = r.filter((function(e) {
|
|
637
|
+
return Object.getOwnPropertyDescriptor(t, e).enumerable;
|
|
638
|
+
}))), n.push.apply(n, r);
|
|
748
639
|
}
|
|
749
|
-
return
|
|
640
|
+
return n;
|
|
750
641
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
642
|
+
function e(e) {
|
|
643
|
+
for (var n = 1; n < arguments.length; n++) {
|
|
644
|
+
var r = null != arguments[n] ? arguments[n] : {};
|
|
645
|
+
n % 2 ? t(Object(r), !0).forEach((function(t) {
|
|
646
|
+
a(e, t, r[t]);
|
|
647
|
+
})) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(r)) : t(Object(r)).forEach((function(t) {
|
|
648
|
+
Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(r, t));
|
|
649
|
+
}));
|
|
650
|
+
}
|
|
651
|
+
return e;
|
|
755
652
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
const getOptionValue = (option) => {
|
|
763
|
-
return String(getInfoWithKey(option, "optionParam") ?? "");
|
|
764
|
-
};
|
|
765
|
-
/** modelValue 绑定值 */
|
|
766
|
-
const getModelValue = (option) => {
|
|
767
|
-
if (props.valueParam) return getInfoWithKey(option, "valueParam");
|
|
768
|
-
if (option && typeof option === "object" && "value" in option) return option.value;
|
|
769
|
-
return option;
|
|
770
|
-
};
|
|
771
|
-
return {
|
|
772
|
-
getInfoWithKey,
|
|
773
|
-
getInputValue,
|
|
774
|
-
getOptionValue,
|
|
775
|
-
getModelValue
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
//#endregion
|
|
779
|
-
//#region ../core/components/base/select/useSelect.ts
|
|
780
|
-
/**
|
|
781
|
-
* @description select 核心 composable
|
|
782
|
-
* @author 阿怪
|
|
783
|
-
* @date 2026/2/25 14:40
|
|
784
|
-
* @version v1.0.1
|
|
785
|
-
*
|
|
786
|
-
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
787
|
-
*
|
|
788
|
-
* 用 computed + ref 替代原 class 继承方案
|
|
789
|
-
* 单选/多选通过 props.multiple 分支处理
|
|
790
|
-
* fetch 通过 IntersectionObserver 观察最后一个选项实现
|
|
791
|
-
* v1.0.1 新增 filterable 支持:开启后 inputReadonly 为 false,可输入过滤 阿怪 2026/2/27
|
|
792
|
-
*/
|
|
793
|
-
function useSelect$1(props, ctx) {
|
|
794
|
-
const tools = useSelectTools(props);
|
|
795
|
-
const optionsRef = toRef(() => props.options ?? []);
|
|
796
|
-
const modelValueRef = toRef(() => props.modelValue);
|
|
797
|
-
const multipleRef = toRef(() => props.multiple ?? false);
|
|
798
|
-
/**
|
|
799
|
-
* 输入框是否只读:
|
|
800
|
-
* - filterable=true 时强制可编辑(忽略 readonly prop)
|
|
801
|
-
* - 否则沿用 props.readonly(默认 true)
|
|
802
|
-
*/
|
|
803
|
-
const inputReadonly = toRef(() => props.filterable ? false : props.readonly ?? true);
|
|
804
|
-
const inputValue = ref("");
|
|
805
|
-
const isOpen = ref(false);
|
|
806
|
-
const fetchLoading = ref(false);
|
|
807
|
-
/** 多选时记录选中的索引集合 */
|
|
808
|
-
const selectedIndices = ref(/* @__PURE__ */ new Set());
|
|
809
|
-
/** 判断某个 option 是否选中 */
|
|
810
|
-
const isSelected = (option, index) => {
|
|
811
|
-
if (multipleRef.value) return selectedIndices.value.has(index);
|
|
812
|
-
if (props.toMatch) return props.toMatch(option, modelValueRef.value);
|
|
813
|
-
return modelValueRef.value === tools.getModelValue(option);
|
|
814
|
-
};
|
|
815
|
-
/** 全量选项(带 isSelected 标记) */
|
|
816
|
-
const allOptions = computed(() => {
|
|
817
|
-
return optionsRef.value.map((o, i) => ({
|
|
818
|
-
value: o,
|
|
819
|
-
index: i,
|
|
820
|
-
isSelected: isSelected(o, i)
|
|
821
|
-
}));
|
|
822
|
-
});
|
|
823
|
-
/** 过滤后的显示选项 */
|
|
824
|
-
const displayOptions = computed(() => {
|
|
825
|
-
return allOptions.value.filter((o) => {
|
|
826
|
-
if (inputReadonly.value) return true;
|
|
827
|
-
if (!inputValue.value) return true;
|
|
828
|
-
if (props.filter) return props.filter(o.value, inputValue.value);
|
|
829
|
-
return tools.getOptionValue(o.value).toLowerCase().includes(inputValue.value.toLowerCase());
|
|
830
|
-
});
|
|
831
|
-
});
|
|
832
|
-
/** 多选已选标签 */
|
|
833
|
-
const selectedTags = computed(() => {
|
|
834
|
-
if (!multipleRef.value) return [];
|
|
835
|
-
return allOptions.value.filter((o) => o.isSelected);
|
|
836
|
-
});
|
|
837
|
-
const syncInputFromModelValue = () => {
|
|
838
|
-
if (multipleRef.value) {
|
|
839
|
-
inputValue.value = "";
|
|
840
|
-
return;
|
|
653
|
+
function n(t) {
|
|
654
|
+
return n = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
|
|
655
|
+
return typeof t;
|
|
656
|
+
} : function(t) {
|
|
657
|
+
return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t;
|
|
658
|
+
}, n(t);
|
|
841
659
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
inputValue.value = "";
|
|
845
|
-
return;
|
|
660
|
+
function r(t, e) {
|
|
661
|
+
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function");
|
|
846
662
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
};
|
|
853
|
-
/** 初始化多选选中状态 */
|
|
854
|
-
const syncSelectedFromModelValue = () => {
|
|
855
|
-
if (!multipleRef.value) return;
|
|
856
|
-
const mv = modelValueRef.value;
|
|
857
|
-
const newSet = /* @__PURE__ */ new Set();
|
|
858
|
-
if (Array.isArray(mv)) optionsRef.value.forEach((o, i) => {
|
|
859
|
-
const val = tools.getModelValue(o);
|
|
860
|
-
if (mv.includes(val)) newSet.add(i);
|
|
861
|
-
if (props.toMatch && mv.some((v) => props.toMatch(o, v))) newSet.add(i);
|
|
862
|
-
});
|
|
863
|
-
selectedIndices.value = newSet;
|
|
864
|
-
};
|
|
865
|
-
syncSelectedFromModelValue();
|
|
866
|
-
syncInputFromModelValue();
|
|
867
|
-
/** 点击选项 */
|
|
868
|
-
const onSelect = (index) => {
|
|
869
|
-
const option = optionsRef.value[index];
|
|
870
|
-
if (!option) return;
|
|
871
|
-
if (option.disabled) return;
|
|
872
|
-
if (multipleRef.value) {
|
|
873
|
-
const newSet = new Set(selectedIndices.value);
|
|
874
|
-
if (newSet.has(index)) newSet.delete(index);
|
|
875
|
-
else newSet.add(index);
|
|
876
|
-
selectedIndices.value = newSet;
|
|
877
|
-
inputValue.value = "";
|
|
878
|
-
const newModelValue = optionsRef.value.filter((_, i) => newSet.has(i)).map((o) => tools.getModelValue(o));
|
|
879
|
-
ctx.emit("update:modelValue", newModelValue);
|
|
880
|
-
ctx.emit("select", option);
|
|
881
|
-
} else {
|
|
882
|
-
inputValue.value = tools.getInputValue(option);
|
|
883
|
-
ctx.emit("update:modelValue", tools.getModelValue(option));
|
|
884
|
-
ctx.emit("select", option);
|
|
885
|
-
isOpen.value = false;
|
|
663
|
+
function i(t, e) {
|
|
664
|
+
for (var n = 0; n < e.length; n++) {
|
|
665
|
+
var r = e[n];
|
|
666
|
+
r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(t, d(r.key), r);
|
|
667
|
+
}
|
|
886
668
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
const onDeleteTag = (index) => {
|
|
890
|
-
const newSet = new Set(selectedIndices.value);
|
|
891
|
-
newSet.delete(index);
|
|
892
|
-
selectedIndices.value = newSet;
|
|
893
|
-
const newModelValue = optionsRef.value.filter((_, i) => newSet.has(i)).map((o) => tools.getModelValue(o));
|
|
894
|
-
ctx.emit("update:modelValue", newModelValue);
|
|
895
|
-
};
|
|
896
|
-
/** 输入事件 */
|
|
897
|
-
const onInput = () => {
|
|
898
|
-
ctx.emit("input", inputValue.value);
|
|
899
|
-
};
|
|
900
|
-
/** 聚焦 */
|
|
901
|
-
const onFocus = (e) => {
|
|
902
|
-
if (inputReadonly.value) return;
|
|
903
|
-
ctx.emit("focus", e, inputValue.value);
|
|
904
|
-
};
|
|
905
|
-
/** 失焦 */
|
|
906
|
-
const onBlur = (e) => {
|
|
907
|
-
if (inputReadonly.value) return;
|
|
908
|
-
ctx.emit("blur", e, inputValue.value);
|
|
909
|
-
if (!multipleRef.value) {
|
|
910
|
-
const matched = displayOptions.value.find((o) => o.isSelected);
|
|
911
|
-
if (matched && inputValue.value === tools.getInputValue(matched.value)) return;
|
|
912
|
-
if (!inputValue.value) ctx.emit("update:modelValue", void 0);
|
|
669
|
+
function o(t, e, n) {
|
|
670
|
+
return e && i(t.prototype, e), n && i(t, n), Object.defineProperty(t, "prototype", { writable: !1 }), t;
|
|
913
671
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
fetchObserver = void 0;
|
|
922
|
-
}
|
|
923
|
-
};
|
|
924
|
-
/** 更新 fetch observer:观察最后一个选项元素 */
|
|
925
|
-
const updateFetchObserver = () => {
|
|
926
|
-
cleanupFetchObserver();
|
|
927
|
-
if (!props.needFetch || !lastOptionRef.value || !optionsContainerRef.value) return;
|
|
928
|
-
fetchObserver = new IntersectionObserver(async (entries) => {
|
|
929
|
-
if (entries[0]?.isIntersecting && props.needFetch) {
|
|
930
|
-
fetchLoading.value = true;
|
|
931
|
-
await props.fetch?.();
|
|
932
|
-
fetchLoading.value = false;
|
|
933
|
-
}
|
|
934
|
-
}, {
|
|
935
|
-
root: optionsContainerRef.value,
|
|
936
|
-
threshold: 1
|
|
937
|
-
});
|
|
938
|
-
fetchObserver.observe(lastOptionRef.value);
|
|
939
|
-
};
|
|
940
|
-
watch(modelValueRef, () => {
|
|
941
|
-
syncSelectedFromModelValue();
|
|
942
|
-
syncInputFromModelValue();
|
|
943
|
-
});
|
|
944
|
-
watch(optionsRef, () => {
|
|
945
|
-
syncSelectedFromModelValue();
|
|
946
|
-
syncInputFromModelValue();
|
|
947
|
-
}, { deep: true });
|
|
948
|
-
watch(lastOptionRef, () => {
|
|
949
|
-
updateFetchObserver();
|
|
950
|
-
});
|
|
951
|
-
onBeforeUnmount(cleanupFetchObserver);
|
|
952
|
-
return {
|
|
953
|
-
inputValue,
|
|
954
|
-
isOpen,
|
|
955
|
-
fetchLoading,
|
|
956
|
-
inputReadonly,
|
|
957
|
-
displayOptions,
|
|
958
|
-
selectedTags,
|
|
959
|
-
lastOptionRef,
|
|
960
|
-
optionsContainerRef,
|
|
961
|
-
onSelect,
|
|
962
|
-
onDeleteTag,
|
|
963
|
-
onInput,
|
|
964
|
-
onFocus,
|
|
965
|
-
onBlur,
|
|
966
|
-
tools,
|
|
967
|
-
updateFetchObserver
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
//#endregion
|
|
971
|
-
//#region ../core/components/base/select/index.ts
|
|
972
|
-
/**
|
|
973
|
-
* @description select core 导出
|
|
974
|
-
* @author 阿怪
|
|
975
|
-
* @date 2026/2/25 14:50
|
|
976
|
-
* @version v2.0.0
|
|
977
|
-
*
|
|
978
|
-
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
979
|
-
*/
|
|
980
|
-
var SelectCore = {
|
|
981
|
-
props: props$6,
|
|
982
|
-
useSelect: useSelect$1
|
|
983
|
-
};
|
|
984
|
-
//#endregion
|
|
985
|
-
//#region ../core/components/base/tag/index.ts
|
|
986
|
-
/**
|
|
987
|
-
* @description tag core
|
|
988
|
-
* @author 阿怪
|
|
989
|
-
* @date 2025/02/25 00:00
|
|
990
|
-
* @version v1.0.0
|
|
991
|
-
*
|
|
992
|
-
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
993
|
-
*/
|
|
994
|
-
var TagCore = { props: {
|
|
995
|
-
type: {
|
|
996
|
-
type: String,
|
|
997
|
-
default: "default"
|
|
998
|
-
},
|
|
999
|
-
size: {
|
|
1000
|
-
type: String,
|
|
1001
|
-
default: void 0
|
|
1002
|
-
},
|
|
1003
|
-
closable: {
|
|
1004
|
-
type: Boolean,
|
|
1005
|
-
default: false
|
|
1006
|
-
},
|
|
1007
|
-
disabled: {
|
|
1008
|
-
type: Boolean,
|
|
1009
|
-
default: false
|
|
1010
|
-
}
|
|
1011
|
-
} };
|
|
1012
|
-
(/* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
1013
|
-
(function(t, e) {
|
|
1014
|
-
"object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).interact = e();
|
|
1015
|
-
})(exports, (function() {
|
|
1016
|
-
"use strict";
|
|
1017
|
-
function t(t, e) {
|
|
1018
|
-
var n = Object.keys(t);
|
|
1019
|
-
if (Object.getOwnPropertySymbols) {
|
|
1020
|
-
var r = Object.getOwnPropertySymbols(t);
|
|
1021
|
-
e && (r = r.filter((function(e) {
|
|
1022
|
-
return Object.getOwnPropertyDescriptor(t, e).enumerable;
|
|
1023
|
-
}))), n.push.apply(n, r);
|
|
1024
|
-
}
|
|
1025
|
-
return n;
|
|
1026
|
-
}
|
|
1027
|
-
function e(e) {
|
|
1028
|
-
for (var n = 1; n < arguments.length; n++) {
|
|
1029
|
-
var r = null != arguments[n] ? arguments[n] : {};
|
|
1030
|
-
n % 2 ? t(Object(r), !0).forEach((function(t) {
|
|
1031
|
-
a(e, t, r[t]);
|
|
1032
|
-
})) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(r)) : t(Object(r)).forEach((function(t) {
|
|
1033
|
-
Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(r, t));
|
|
1034
|
-
}));
|
|
1035
|
-
}
|
|
1036
|
-
return e;
|
|
1037
|
-
}
|
|
1038
|
-
function n(t) {
|
|
1039
|
-
return n = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) {
|
|
1040
|
-
return typeof t;
|
|
1041
|
-
} : function(t) {
|
|
1042
|
-
return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t;
|
|
1043
|
-
}, n(t);
|
|
1044
|
-
}
|
|
1045
|
-
function r(t, e) {
|
|
1046
|
-
if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function");
|
|
1047
|
-
}
|
|
1048
|
-
function i(t, e) {
|
|
1049
|
-
for (var n = 0; n < e.length; n++) {
|
|
1050
|
-
var r = e[n];
|
|
1051
|
-
r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(t, d(r.key), r);
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
function o(t, e, n) {
|
|
1055
|
-
return e && i(t.prototype, e), n && i(t, n), Object.defineProperty(t, "prototype", { writable: !1 }), t;
|
|
1056
|
-
}
|
|
1057
|
-
function a(t, e, n) {
|
|
1058
|
-
return (e = d(e)) in t ? Object.defineProperty(t, e, {
|
|
1059
|
-
value: n,
|
|
1060
|
-
enumerable: !0,
|
|
1061
|
-
configurable: !0,
|
|
1062
|
-
writable: !0
|
|
1063
|
-
}) : t[e] = n, t;
|
|
672
|
+
function a(t, e, n) {
|
|
673
|
+
return (e = d(e)) in t ? Object.defineProperty(t, e, {
|
|
674
|
+
value: n,
|
|
675
|
+
enumerable: !0,
|
|
676
|
+
configurable: !0,
|
|
677
|
+
writable: !0
|
|
678
|
+
}) : t[e] = n, t;
|
|
1064
679
|
}
|
|
1065
680
|
function s(t, e) {
|
|
1066
681
|
if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
|
|
@@ -6328,7 +5943,7 @@ var computePosition = (reference, floating, options) => {
|
|
|
6328
5943
|
};
|
|
6329
5944
|
//#endregion
|
|
6330
5945
|
//#region ../core/components/template/pagination/api.ts
|
|
6331
|
-
var props$
|
|
5946
|
+
var props$6 = {
|
|
6332
5947
|
total: {
|
|
6333
5948
|
type: Number,
|
|
6334
5949
|
default: 0
|
|
@@ -6487,7 +6102,7 @@ function usePagination(props, currentValue) {
|
|
|
6487
6102
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6488
6103
|
*/
|
|
6489
6104
|
var PaginationCore = {
|
|
6490
|
-
props: props$
|
|
6105
|
+
props: props$6,
|
|
6491
6106
|
usePagination
|
|
6492
6107
|
};
|
|
6493
6108
|
//#endregion
|
|
@@ -6906,177 +6521,1085 @@ function useMenu(props, emit) {
|
|
|
6906
6521
|
}));
|
|
6907
6522
|
})))();
|
|
6908
6523
|
//#endregion
|
|
6909
|
-
//#region ../core/components/template/
|
|
6524
|
+
//#region ../core/components/template/table/api.ts
|
|
6525
|
+
var props$5 = {
|
|
6526
|
+
data: {
|
|
6527
|
+
type: Array,
|
|
6528
|
+
default: () => []
|
|
6529
|
+
},
|
|
6530
|
+
height: {
|
|
6531
|
+
type: String,
|
|
6532
|
+
default: null
|
|
6533
|
+
},
|
|
6534
|
+
paramClass: {
|
|
6535
|
+
type: Boolean,
|
|
6536
|
+
default: false
|
|
6537
|
+
},
|
|
6538
|
+
loading: {
|
|
6539
|
+
type: Boolean,
|
|
6540
|
+
default: false
|
|
6541
|
+
}
|
|
6542
|
+
};
|
|
6543
|
+
//#endregion
|
|
6544
|
+
//#region ../core/components/template/table/useTable.ts
|
|
6545
|
+
/**
|
|
6546
|
+
* @description core table hook
|
|
6547
|
+
* @author 阿怪
|
|
6548
|
+
* @date 2026/2/25
|
|
6549
|
+
* @version v1.0.0
|
|
6550
|
+
*
|
|
6551
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6552
|
+
*/
|
|
6553
|
+
function useTable() {
|
|
6554
|
+
const error = (msg) => console.warn(`[水墨UI表格组件] ${msg}`);
|
|
6555
|
+
const initTable = (renders, columns, data) => {
|
|
6556
|
+
const tbodyTrList = [];
|
|
6557
|
+
data.forEach(() => {
|
|
6558
|
+
tbodyTrList.push([]);
|
|
6559
|
+
});
|
|
6560
|
+
/** 从 data[i] 中安全取值 */
|
|
6561
|
+
const getData = (i, param) => {
|
|
6562
|
+
if (data[i] == null) return "";
|
|
6563
|
+
return data[i][param] ?? "";
|
|
6564
|
+
};
|
|
6565
|
+
/** 向每行的 td 列表中追加一列 */
|
|
6566
|
+
const pushTd = (param, bodySlot, style) => {
|
|
6567
|
+
if (!param && !bodySlot) {
|
|
6568
|
+
error("param is undefined, column without param or slot will be ignored!");
|
|
6569
|
+
return;
|
|
6570
|
+
}
|
|
6571
|
+
tbodyTrList.forEach((t, i) => {
|
|
6572
|
+
t.push(renders.tbodyTr({
|
|
6573
|
+
data: param ? getData(i, param) : "",
|
|
6574
|
+
style,
|
|
6575
|
+
param: param ?? "",
|
|
6576
|
+
slot: bodySlot,
|
|
6577
|
+
slotInfo: {
|
|
6578
|
+
data: data[i],
|
|
6579
|
+
index: i
|
|
6580
|
+
}
|
|
6581
|
+
}));
|
|
6582
|
+
});
|
|
6583
|
+
};
|
|
6584
|
+
/** 将列宽 prop 转换为 style 对象 */
|
|
6585
|
+
const getStyle = (options) => {
|
|
6586
|
+
if (!options || !options.width) return {};
|
|
6587
|
+
const numberWidth = Number(options.width);
|
|
6588
|
+
if (!isNaN(numberWidth)) return { width: numberWidth + "px" };
|
|
6589
|
+
return { width: options.width };
|
|
6590
|
+
};
|
|
6591
|
+
/**
|
|
6592
|
+
* 初始化表头,同时将每列对应的 td 推入 tbodyTrList
|
|
6593
|
+
*/
|
|
6594
|
+
const initTHead = () => {
|
|
6595
|
+
const ths = (columns ?? []).filter((column) => {
|
|
6596
|
+
if (!column.props) {
|
|
6597
|
+
error("column.props is undefined, column without param will be ignored!");
|
|
6598
|
+
return false;
|
|
6599
|
+
}
|
|
6600
|
+
return true;
|
|
6601
|
+
}).map((column) => {
|
|
6602
|
+
const slots = renders.initSlot(column);
|
|
6603
|
+
let bodySlot;
|
|
6604
|
+
let headSlot;
|
|
6605
|
+
const style = getStyle(column.props);
|
|
6606
|
+
if (slots) {
|
|
6607
|
+
bodySlot = slots.body;
|
|
6608
|
+
headSlot = slots.head;
|
|
6609
|
+
}
|
|
6610
|
+
pushTd(column.props.param, bodySlot, style);
|
|
6611
|
+
return renders.theadTh({
|
|
6612
|
+
label: column.props.label,
|
|
6613
|
+
param: column.props.param,
|
|
6614
|
+
slot: headSlot,
|
|
6615
|
+
style
|
|
6616
|
+
});
|
|
6617
|
+
});
|
|
6618
|
+
return renders.thead(ths);
|
|
6619
|
+
};
|
|
6620
|
+
return {
|
|
6621
|
+
thead: initTHead(),
|
|
6622
|
+
tbody: tbodyTrList.length > 0 ? renders.tbody(tbodyTrList.map((tds, i) => renders.tbodyTrs(tds, i))) : renders.empty
|
|
6623
|
+
};
|
|
6624
|
+
};
|
|
6625
|
+
return {
|
|
6626
|
+
initTable,
|
|
6627
|
+
error
|
|
6628
|
+
};
|
|
6629
|
+
}
|
|
6630
|
+
//#endregion
|
|
6631
|
+
//#region ../core/components/template/table/index.ts
|
|
6632
|
+
/**
|
|
6633
|
+
* @description table core 导出
|
|
6634
|
+
* @author 阿怪
|
|
6635
|
+
* @date 2026/2/25
|
|
6636
|
+
* @version v1.0.0
|
|
6637
|
+
*
|
|
6638
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6639
|
+
*/
|
|
6640
|
+
var TableCore = {
|
|
6641
|
+
props: props$5,
|
|
6642
|
+
useTable
|
|
6643
|
+
};
|
|
6644
|
+
//#endregion
|
|
6645
|
+
//#region ../core/components/template/tableColumn/index.ts
|
|
6646
|
+
/**
|
|
6647
|
+
* @description tableColumn core 导출
|
|
6648
|
+
* @author 阿怪
|
|
6649
|
+
* @date 2026/2/25
|
|
6650
|
+
* @version v1.0.0
|
|
6651
|
+
*
|
|
6652
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6653
|
+
*/
|
|
6654
|
+
var TableColumnCore = { props: {
|
|
6655
|
+
width: {
|
|
6656
|
+
type: String,
|
|
6657
|
+
default: ""
|
|
6658
|
+
},
|
|
6659
|
+
param: {
|
|
6660
|
+
type: String,
|
|
6661
|
+
default: ""
|
|
6662
|
+
},
|
|
6663
|
+
label: {
|
|
6664
|
+
type: String,
|
|
6665
|
+
default: ""
|
|
6666
|
+
}
|
|
6667
|
+
} };
|
|
6668
|
+
//#endregion
|
|
6669
|
+
//#region ../core/components/base/image/api.ts
|
|
6670
|
+
var props$3 = {
|
|
6671
|
+
src: {
|
|
6672
|
+
type: String,
|
|
6673
|
+
required: true
|
|
6674
|
+
},
|
|
6675
|
+
alt: {
|
|
6676
|
+
type: String,
|
|
6677
|
+
default: ""
|
|
6678
|
+
},
|
|
6679
|
+
fit: {
|
|
6680
|
+
type: String,
|
|
6681
|
+
default: "cover",
|
|
6682
|
+
enum: [
|
|
6683
|
+
"contain",
|
|
6684
|
+
"cover",
|
|
6685
|
+
"fill",
|
|
6686
|
+
"none",
|
|
6687
|
+
"scale-down"
|
|
6688
|
+
]
|
|
6689
|
+
},
|
|
6690
|
+
width: {
|
|
6691
|
+
type: [String, Number],
|
|
6692
|
+
default: void 0
|
|
6693
|
+
},
|
|
6694
|
+
height: {
|
|
6695
|
+
type: [String, Number],
|
|
6696
|
+
default: void 0
|
|
6697
|
+
},
|
|
6698
|
+
lazy: {
|
|
6699
|
+
type: Boolean,
|
|
6700
|
+
default: false
|
|
6701
|
+
},
|
|
6702
|
+
previewSrcList: {
|
|
6703
|
+
type: Array,
|
|
6704
|
+
default: () => []
|
|
6705
|
+
},
|
|
6706
|
+
zIndex: {
|
|
6707
|
+
type: Number,
|
|
6708
|
+
default: 2e3
|
|
6709
|
+
}
|
|
6710
|
+
};
|
|
6711
|
+
//#endregion
|
|
6712
|
+
//#region ../core/components/base/image/useImage.ts
|
|
6713
|
+
/**
|
|
6714
|
+
* @description image hook
|
|
6715
|
+
* @author 阿怪
|
|
6716
|
+
* @date 2026/2/26
|
|
6717
|
+
* @version v1.0.0
|
|
6718
|
+
*
|
|
6719
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6720
|
+
*/
|
|
6721
|
+
function useImage(props, emit) {
|
|
6722
|
+
const status = ref("loading");
|
|
6723
|
+
const previewVisible = ref(false);
|
|
6724
|
+
const previewIndex = ref(0);
|
|
6725
|
+
const previewScale = ref(1);
|
|
6726
|
+
const previewRotate = ref(0);
|
|
6727
|
+
/** 重置加载状态(src 变化时调用) */
|
|
6728
|
+
const reset = () => {
|
|
6729
|
+
status.value = "loading";
|
|
6730
|
+
};
|
|
6731
|
+
const handleLoad = (e) => {
|
|
6732
|
+
status.value = "loaded";
|
|
6733
|
+
emit("load", e);
|
|
6734
|
+
};
|
|
6735
|
+
const handleError = (e) => {
|
|
6736
|
+
status.value = "error";
|
|
6737
|
+
emit("error", e);
|
|
6738
|
+
};
|
|
6739
|
+
/** 打开全屏预览,定位到 src 在 previewSrcList 中的位置 */
|
|
6740
|
+
const openPreview = () => {
|
|
6741
|
+
if (!props.previewSrcList || props.previewSrcList.length === 0) return;
|
|
6742
|
+
const idx = props.previewSrcList.indexOf(props.src);
|
|
6743
|
+
previewIndex.value = idx >= 0 ? idx : 0;
|
|
6744
|
+
previewScale.value = 1;
|
|
6745
|
+
previewRotate.value = 0;
|
|
6746
|
+
previewVisible.value = true;
|
|
6747
|
+
};
|
|
6748
|
+
const closePreview = () => {
|
|
6749
|
+
previewVisible.value = false;
|
|
6750
|
+
};
|
|
6751
|
+
/** 预览切换到上一张 */
|
|
6752
|
+
const previewPrev = () => {
|
|
6753
|
+
const total = props.previewSrcList.length;
|
|
6754
|
+
if (total === 0) return;
|
|
6755
|
+
previewIndex.value = (previewIndex.value - 1 + total) % total;
|
|
6756
|
+
previewScale.value = 1;
|
|
6757
|
+
previewRotate.value = 0;
|
|
6758
|
+
emit("switch", previewIndex.value);
|
|
6759
|
+
};
|
|
6760
|
+
/** 预览切换到下一张 */
|
|
6761
|
+
const previewNext = () => {
|
|
6762
|
+
const total = props.previewSrcList.length;
|
|
6763
|
+
if (total === 0) return;
|
|
6764
|
+
previewIndex.value = (previewIndex.value + 1) % total;
|
|
6765
|
+
previewScale.value = 1;
|
|
6766
|
+
previewRotate.value = 0;
|
|
6767
|
+
emit("switch", previewIndex.value);
|
|
6768
|
+
};
|
|
6769
|
+
/** 预览放大 */
|
|
6770
|
+
const zoomIn = () => {
|
|
6771
|
+
previewScale.value = Math.min(previewScale.value + .25, 5);
|
|
6772
|
+
};
|
|
6773
|
+
/** 预览缩小 */
|
|
6774
|
+
const zoomOut = () => {
|
|
6775
|
+
previewScale.value = Math.max(previewScale.value - .25, .25);
|
|
6776
|
+
};
|
|
6777
|
+
/** 顺时针旋转 90° */
|
|
6778
|
+
const rotate = () => {
|
|
6779
|
+
previewRotate.value = (previewRotate.value + 90) % 360;
|
|
6780
|
+
};
|
|
6781
|
+
watch(() => props.src, reset);
|
|
6782
|
+
onMounted(() => {
|
|
6783
|
+
if (props.lazy) status.value = "loading";
|
|
6784
|
+
});
|
|
6785
|
+
return {
|
|
6786
|
+
status,
|
|
6787
|
+
previewVisible,
|
|
6788
|
+
previewIndex,
|
|
6789
|
+
previewScale,
|
|
6790
|
+
previewRotate,
|
|
6791
|
+
handleLoad,
|
|
6792
|
+
handleError,
|
|
6793
|
+
openPreview,
|
|
6794
|
+
closePreview,
|
|
6795
|
+
previewPrev,
|
|
6796
|
+
previewNext,
|
|
6797
|
+
zoomIn,
|
|
6798
|
+
zoomOut,
|
|
6799
|
+
rotate
|
|
6800
|
+
};
|
|
6801
|
+
}
|
|
6802
|
+
//#endregion
|
|
6803
|
+
//#region ../core/components/base/image/index.ts
|
|
6804
|
+
/**
|
|
6805
|
+
* @description image core 导出
|
|
6806
|
+
* @author 阿怪
|
|
6807
|
+
* @date 2026/2/26
|
|
6808
|
+
* @version v1.0.0
|
|
6809
|
+
*
|
|
6810
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6811
|
+
*/
|
|
6812
|
+
var ImageCore = {
|
|
6813
|
+
props: props$3,
|
|
6814
|
+
useImage
|
|
6815
|
+
};
|
|
6816
|
+
//#endregion
|
|
6817
|
+
//#region ../core/compositions/overlay/useOverlayStack.ts
|
|
6910
6818
|
/**
|
|
6911
|
-
* @description
|
|
6912
|
-
* @author
|
|
6913
|
-
* @date 2026/
|
|
6819
|
+
* @description overlay stack manager — unified z-index and ESC handling for all popups
|
|
6820
|
+
* @author kine-design
|
|
6821
|
+
* @date 2026/5/22 00:00
|
|
6914
6822
|
* @version v1.0.0
|
|
6915
6823
|
*
|
|
6916
6824
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
6917
6825
|
*/
|
|
6918
|
-
var
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6826
|
+
var Z_INDEX_BASE = 100;
|
|
6827
|
+
defineStore("overlayStack", () => {
|
|
6828
|
+
const overlayStack = ref([]);
|
|
6829
|
+
const isEmpty = computed(() => overlayStack.value.length === 0);
|
|
6830
|
+
const topItem = computed(() => overlayStack.value.length > 0 ? overlayStack.value[overlayStack.value.length - 1] : void 0);
|
|
6831
|
+
const push = (item) => {
|
|
6832
|
+
const zIndex = overlayStack.value.length + Z_INDEX_BASE;
|
|
6833
|
+
const entry = {
|
|
6834
|
+
...item,
|
|
6835
|
+
zIndex
|
|
6836
|
+
};
|
|
6837
|
+
overlayStack.value.push(entry);
|
|
6838
|
+
return entry;
|
|
6839
|
+
};
|
|
6840
|
+
const pop = () => {
|
|
6841
|
+
const item = overlayStack.value.pop();
|
|
6842
|
+
if (item) item.close();
|
|
6843
|
+
return item;
|
|
6844
|
+
};
|
|
6845
|
+
const remove = (id) => {
|
|
6846
|
+
const index = overlayStack.value.findIndex((item) => item.id === id);
|
|
6847
|
+
if (index !== -1) {
|
|
6848
|
+
overlayStack.value.splice(index, 1);
|
|
6849
|
+
recalculateZIndices();
|
|
6850
|
+
}
|
|
6851
|
+
};
|
|
6852
|
+
const recalculateZIndices = () => {
|
|
6853
|
+
overlayStack.value.forEach((item, index) => {
|
|
6854
|
+
item.zIndex = index + Z_INDEX_BASE;
|
|
6855
|
+
});
|
|
6856
|
+
};
|
|
6857
|
+
const handleEsc = (e) => {
|
|
6858
|
+
if (e.key === "Escape" && !isEmpty.value) pop();
|
|
6859
|
+
};
|
|
6860
|
+
let listenerAttached = false;
|
|
6861
|
+
const attachEscListener = () => {
|
|
6862
|
+
if (!listenerAttached) {
|
|
6863
|
+
document.addEventListener("keydown", handleEsc);
|
|
6864
|
+
listenerAttached = true;
|
|
6865
|
+
}
|
|
6866
|
+
};
|
|
6867
|
+
const detachEscListener = () => {
|
|
6868
|
+
if (listenerAttached) {
|
|
6869
|
+
document.removeEventListener("keydown", handleEsc);
|
|
6870
|
+
listenerAttached = false;
|
|
6871
|
+
}
|
|
6872
|
+
};
|
|
6873
|
+
return {
|
|
6874
|
+
overlayStack,
|
|
6875
|
+
isEmpty,
|
|
6876
|
+
topItem,
|
|
6877
|
+
push,
|
|
6878
|
+
pop,
|
|
6879
|
+
remove,
|
|
6880
|
+
attachEscListener,
|
|
6881
|
+
detachEscListener
|
|
6882
|
+
};
|
|
6883
|
+
});
|
|
6884
|
+
//#endregion
|
|
6885
|
+
//#region ../core/locale/index.ts
|
|
6886
|
+
/**
|
|
6887
|
+
* @description kine-design locale entry — built-in language packs + types.
|
|
6888
|
+
*
|
|
6889
|
+
* The library ships only the two general languages (zh / en). To use another
|
|
6890
|
+
* language, build a full dictionary that satisfies `KineLocaleMessages` in the
|
|
6891
|
+
* consuming app and pass it straight to the provider:
|
|
6892
|
+
*
|
|
6893
|
+
* import type { KineLocaleMessages } from '@kine-design/core';
|
|
6894
|
+
* const bn: KineLocaleMessages = { ...full Bengali dictionary... };
|
|
6895
|
+
* // <KConfigProvider :locale="bn"> ... </KConfigProvider>
|
|
6896
|
+
*
|
|
6897
|
+
* TypeScript enforces full key coverage, so a partial/forgotten key is a
|
|
6898
|
+
* compile error in the app — the same guarantee the built-in packs enjoy.
|
|
6899
|
+
* @author kine-design
|
|
6900
|
+
* @version v1.0.0
|
|
6901
|
+
*/
|
|
6902
|
+
/** Built-in language packs, keyed by locale name. */
|
|
6903
|
+
var locales = {
|
|
6904
|
+
zh: {
|
|
6905
|
+
common: {
|
|
6906
|
+
confirm: "确定",
|
|
6907
|
+
cancel: "取消",
|
|
6908
|
+
close: "关闭",
|
|
6909
|
+
search: "搜索",
|
|
6910
|
+
reset: "重置",
|
|
6911
|
+
all: "全部",
|
|
6912
|
+
noData: "暂无数据",
|
|
6913
|
+
loading: "加载中...",
|
|
6914
|
+
save: "保存"
|
|
6915
|
+
},
|
|
6916
|
+
pagination: {
|
|
6917
|
+
totalPrefix: "共 ",
|
|
6918
|
+
totalSuffix: " 条"
|
|
6919
|
+
},
|
|
6920
|
+
datePicker: {
|
|
6921
|
+
placeholder: "请选择日期...",
|
|
6922
|
+
year: (year) => `${year}年`,
|
|
6923
|
+
month: (month) => `${month}月`,
|
|
6924
|
+
hour: "时",
|
|
6925
|
+
minute: "分",
|
|
6926
|
+
second: "秒",
|
|
6927
|
+
confirm: "确定",
|
|
6928
|
+
weekNames: [
|
|
6929
|
+
"日",
|
|
6930
|
+
"一",
|
|
6931
|
+
"二",
|
|
6932
|
+
"三",
|
|
6933
|
+
"四",
|
|
6934
|
+
"五",
|
|
6935
|
+
"六"
|
|
6936
|
+
],
|
|
6937
|
+
monthNames: [
|
|
6938
|
+
"1月",
|
|
6939
|
+
"2月",
|
|
6940
|
+
"3月",
|
|
6941
|
+
"4月",
|
|
6942
|
+
"5月",
|
|
6943
|
+
"6月",
|
|
6944
|
+
"7月",
|
|
6945
|
+
"8月",
|
|
6946
|
+
"9月",
|
|
6947
|
+
"10月",
|
|
6948
|
+
"11月",
|
|
6949
|
+
"12月"
|
|
6950
|
+
]
|
|
6951
|
+
},
|
|
6952
|
+
timePicker: {
|
|
6953
|
+
placeholder: "请选择时间...",
|
|
6954
|
+
hour: "时",
|
|
6955
|
+
minute: "分",
|
|
6956
|
+
second: "秒"
|
|
6957
|
+
},
|
|
6958
|
+
select: {
|
|
6959
|
+
placeholder: "请选择...",
|
|
6960
|
+
clear: "清空",
|
|
6961
|
+
noData: "暂无数据",
|
|
6962
|
+
loading: "加载中..."
|
|
6963
|
+
},
|
|
6964
|
+
autoComplete: {
|
|
6965
|
+
placeholder: "请输入...",
|
|
6966
|
+
loading: "加载中",
|
|
6967
|
+
clear: "清空",
|
|
6968
|
+
noData: "暂无建议"
|
|
6969
|
+
},
|
|
6970
|
+
cascader: {
|
|
6971
|
+
placeholder: "请选择",
|
|
6972
|
+
noMatch: "暂无匹配数据"
|
|
6973
|
+
},
|
|
6974
|
+
image: {
|
|
6975
|
+
loadError: "加载失败",
|
|
6976
|
+
zoomOut: "缩小",
|
|
6977
|
+
zoomIn: "放大",
|
|
6978
|
+
rotate: "旋转",
|
|
6979
|
+
close: "关闭"
|
|
6980
|
+
},
|
|
6981
|
+
transfer: {
|
|
6982
|
+
sourceTitle: "源列表",
|
|
6983
|
+
targetTitle: "目标列表",
|
|
6984
|
+
noData: "暂无数据",
|
|
6985
|
+
filterPlaceholder: "请输入搜索内容"
|
|
6986
|
+
},
|
|
6987
|
+
empty: { description: "暂无数据" },
|
|
6988
|
+
a11y: {
|
|
6989
|
+
rate: "评分",
|
|
6990
|
+
tagClose: "关闭",
|
|
6991
|
+
anchorNav: "锚点导航",
|
|
6992
|
+
backTop: "回到顶部",
|
|
6993
|
+
carouselPrev: "上一张",
|
|
6994
|
+
carouselNext: "下一张",
|
|
6995
|
+
toLightMode: "切换到亮色模式",
|
|
6996
|
+
toDarkMode: "切换到暗色模式",
|
|
6997
|
+
expandSider: "展开侧边栏",
|
|
6998
|
+
collapseSider: "折叠侧边栏"
|
|
6999
|
+
},
|
|
7000
|
+
upload: {
|
|
7001
|
+
trigger: "点击或拖拽文件到此处上传",
|
|
7002
|
+
triggerSimple: "点击上传文件",
|
|
7003
|
+
oversize: (name, max) => max ? `文件 "${name}" 超过大小限制(最大 ${max})` : `文件 "${name}" 超过大小限制`,
|
|
7004
|
+
uploadFailed: "上传失败",
|
|
7005
|
+
statusWaiting: "等待中",
|
|
7006
|
+
statusUploading: "上传中",
|
|
7007
|
+
statusDone: "已完成",
|
|
7008
|
+
statusFailed: "上传失败"
|
|
7009
|
+
},
|
|
7010
|
+
searchTable: {
|
|
7011
|
+
search: "搜索",
|
|
7012
|
+
reset: "重置"
|
|
7013
|
+
},
|
|
7014
|
+
editableTable: {
|
|
7015
|
+
summary: "合计",
|
|
7016
|
+
addRow: "+ 添加行",
|
|
7017
|
+
addFirstRow: "添加第一行",
|
|
7018
|
+
confirmDelete: "确定删除这一行?",
|
|
7019
|
+
delete: "删除",
|
|
7020
|
+
cancel: "取消",
|
|
7021
|
+
noData: "暂无数据"
|
|
7022
|
+
},
|
|
7023
|
+
formPage: {
|
|
7024
|
+
loading: "加载中...",
|
|
7025
|
+
cancel: "取消",
|
|
7026
|
+
saveDraft: "保存草稿",
|
|
7027
|
+
save: "保存",
|
|
7028
|
+
saving: "保存中...",
|
|
7029
|
+
submit: "提交",
|
|
7030
|
+
submitting: "提交中...",
|
|
7031
|
+
basicInfo: "基本信息",
|
|
7032
|
+
editTitle: (title) => `编辑${title}`,
|
|
7033
|
+
createTitle: (title) => `新建${title}`
|
|
7034
|
+
},
|
|
7035
|
+
approvalDialog: {
|
|
7036
|
+
submitTitle: "提交审批",
|
|
7037
|
+
submitConfirm: "确认提交",
|
|
7038
|
+
approveTitle: "审批通过",
|
|
7039
|
+
approveConfirm: "确认通过",
|
|
7040
|
+
rejectTitle: "驳回申请",
|
|
7041
|
+
rejectConfirm: "确认驳回",
|
|
7042
|
+
rejectPlaceholder: "请输入驳回原因...",
|
|
7043
|
+
remarkPlaceholder: "添加备注(可选)...",
|
|
7044
|
+
required: "* 必填",
|
|
7045
|
+
cancel: "取消",
|
|
7046
|
+
processing: "处理中..."
|
|
7047
|
+
},
|
|
7048
|
+
crudPage: {
|
|
7049
|
+
all: "全部",
|
|
7050
|
+
fieldPlaceholder: (label) => `请输入${label}`
|
|
7051
|
+
},
|
|
7052
|
+
login: {
|
|
7053
|
+
username: "用户名",
|
|
7054
|
+
usernamePlaceholder: "请输入用户名",
|
|
7055
|
+
password: "密码",
|
|
7056
|
+
passwordPlaceholder: "请输入密码",
|
|
7057
|
+
remember: "记住我",
|
|
7058
|
+
login: "登 录",
|
|
7059
|
+
loggingIn: "登录中..."
|
|
7060
|
+
},
|
|
7061
|
+
form: {
|
|
7062
|
+
inputPlaceholder: (label) => `请输入${label}`,
|
|
7063
|
+
selectPlaceholder: (label) => `请选择${label}`
|
|
7064
|
+
},
|
|
7065
|
+
routes: {
|
|
7066
|
+
createSuffix: " - 新建",
|
|
7067
|
+
editSuffix: " - 编辑",
|
|
7068
|
+
detailSuffix: " - 详情"
|
|
7069
|
+
},
|
|
7070
|
+
request: {
|
|
7071
|
+
success: "操作成功",
|
|
7072
|
+
opFailed: "操作失败",
|
|
7073
|
+
failed: "请求失败",
|
|
7074
|
+
failedWithStatus: (status) => `请求失败(${status})`,
|
|
7075
|
+
failedWithMsg: (msg) => `请求失败: ${msg}`,
|
|
7076
|
+
timeout: "请求超时",
|
|
7077
|
+
timeoutRetry: "请求超时,请稍后重试",
|
|
7078
|
+
canceled: "请求已取消",
|
|
7079
|
+
permissionDenied: "权限不足,无法执行此操作",
|
|
7080
|
+
invalidUrl: (url) => `无效的请求地址: ${url}`,
|
|
7081
|
+
decodeFailed: (reason) => `解码失败: ${reason}`,
|
|
7082
|
+
parseFailed: "数据解析失败",
|
|
7083
|
+
networkError: "网络错误",
|
|
7084
|
+
networkException: "网络异常,请检查网络连接",
|
|
7085
|
+
unknownError: (error) => `未知错误: ${error}`,
|
|
7086
|
+
unknown: "发生了未知错误",
|
|
7087
|
+
uploadFailed: "上传失败",
|
|
7088
|
+
uploadCanceled: "上传已取消"
|
|
7089
|
+
},
|
|
7090
|
+
aiChat: {
|
|
7091
|
+
inputPlaceholder: "输入消息…",
|
|
7092
|
+
send: "发送",
|
|
7093
|
+
defaultTitle: (n) => `对话 ${n}`,
|
|
7094
|
+
phaseTyping: "正在输入…",
|
|
7095
|
+
phaseThinking: "思考中…",
|
|
7096
|
+
phaseReplying: "回复中…",
|
|
7097
|
+
phaseSending: "发送中…"
|
|
7098
|
+
}
|
|
6926
7099
|
},
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
7100
|
+
en: {
|
|
7101
|
+
common: {
|
|
7102
|
+
confirm: "OK",
|
|
7103
|
+
cancel: "Cancel",
|
|
7104
|
+
close: "Close",
|
|
7105
|
+
search: "Search",
|
|
7106
|
+
reset: "Reset",
|
|
7107
|
+
all: "All",
|
|
7108
|
+
noData: "No data",
|
|
7109
|
+
loading: "Loading...",
|
|
7110
|
+
save: "Save"
|
|
7111
|
+
},
|
|
7112
|
+
pagination: {
|
|
7113
|
+
totalPrefix: "",
|
|
7114
|
+
totalSuffix: " items"
|
|
7115
|
+
},
|
|
7116
|
+
datePicker: {
|
|
7117
|
+
placeholder: "Select date...",
|
|
7118
|
+
year: (year) => `${year}`,
|
|
7119
|
+
month: (month) => `${month}`,
|
|
7120
|
+
hour: "Hour",
|
|
7121
|
+
minute: "Min",
|
|
7122
|
+
second: "Sec",
|
|
7123
|
+
confirm: "OK",
|
|
7124
|
+
weekNames: [
|
|
7125
|
+
"Sun",
|
|
7126
|
+
"Mon",
|
|
7127
|
+
"Tue",
|
|
7128
|
+
"Wed",
|
|
7129
|
+
"Thu",
|
|
7130
|
+
"Fri",
|
|
7131
|
+
"Sat"
|
|
7132
|
+
],
|
|
7133
|
+
monthNames: [
|
|
7134
|
+
"Jan",
|
|
7135
|
+
"Feb",
|
|
7136
|
+
"Mar",
|
|
7137
|
+
"Apr",
|
|
7138
|
+
"May",
|
|
7139
|
+
"Jun",
|
|
7140
|
+
"Jul",
|
|
7141
|
+
"Aug",
|
|
7142
|
+
"Sep",
|
|
7143
|
+
"Oct",
|
|
7144
|
+
"Nov",
|
|
7145
|
+
"Dec"
|
|
7146
|
+
]
|
|
7147
|
+
},
|
|
7148
|
+
timePicker: {
|
|
7149
|
+
placeholder: "Select time...",
|
|
7150
|
+
hour: "Hour",
|
|
7151
|
+
minute: "Min",
|
|
7152
|
+
second: "Sec"
|
|
7153
|
+
},
|
|
7154
|
+
select: {
|
|
7155
|
+
placeholder: "Select...",
|
|
7156
|
+
clear: "Clear",
|
|
7157
|
+
noData: "No data",
|
|
7158
|
+
loading: "Loading..."
|
|
7159
|
+
},
|
|
7160
|
+
autoComplete: {
|
|
7161
|
+
placeholder: "Enter...",
|
|
7162
|
+
loading: "Loading",
|
|
7163
|
+
clear: "Clear",
|
|
7164
|
+
noData: "No suggestions"
|
|
7165
|
+
},
|
|
7166
|
+
cascader: {
|
|
7167
|
+
placeholder: "Select",
|
|
7168
|
+
noMatch: "No matching data"
|
|
7169
|
+
},
|
|
7170
|
+
image: {
|
|
7171
|
+
loadError: "Load failed",
|
|
7172
|
+
zoomOut: "Zoom out",
|
|
7173
|
+
zoomIn: "Zoom in",
|
|
7174
|
+
rotate: "Rotate",
|
|
7175
|
+
close: "Close"
|
|
7176
|
+
},
|
|
7177
|
+
transfer: {
|
|
7178
|
+
sourceTitle: "Source",
|
|
7179
|
+
targetTitle: "Target",
|
|
7180
|
+
noData: "No data",
|
|
7181
|
+
filterPlaceholder: "Search..."
|
|
7182
|
+
},
|
|
7183
|
+
empty: { description: "No data" },
|
|
7184
|
+
a11y: {
|
|
7185
|
+
rate: "Rating",
|
|
7186
|
+
tagClose: "Close",
|
|
7187
|
+
anchorNav: "Anchor navigation",
|
|
7188
|
+
backTop: "Back to top",
|
|
7189
|
+
carouselPrev: "Previous",
|
|
7190
|
+
carouselNext: "Next",
|
|
7191
|
+
toLightMode: "Switch to light mode",
|
|
7192
|
+
toDarkMode: "Switch to dark mode",
|
|
7193
|
+
expandSider: "Expand sidebar",
|
|
7194
|
+
collapseSider: "Collapse sidebar"
|
|
7195
|
+
},
|
|
7196
|
+
upload: {
|
|
7197
|
+
trigger: "Click or drag file here to upload",
|
|
7198
|
+
triggerSimple: "Click to upload",
|
|
7199
|
+
oversize: (name, max) => max ? `File "${name}" exceeds size limit (max ${max})` : `File "${name}" exceeds size limit`,
|
|
7200
|
+
uploadFailed: "Upload failed",
|
|
7201
|
+
statusWaiting: "Waiting",
|
|
7202
|
+
statusUploading: "Uploading",
|
|
7203
|
+
statusDone: "Done",
|
|
7204
|
+
statusFailed: "Failed"
|
|
7205
|
+
},
|
|
7206
|
+
searchTable: {
|
|
7207
|
+
search: "Search",
|
|
7208
|
+
reset: "Reset"
|
|
7209
|
+
},
|
|
7210
|
+
editableTable: {
|
|
7211
|
+
summary: "Total",
|
|
7212
|
+
addRow: "+ Add row",
|
|
7213
|
+
addFirstRow: "Add first row",
|
|
7214
|
+
confirmDelete: "Delete this row?",
|
|
7215
|
+
delete: "Delete",
|
|
7216
|
+
cancel: "Cancel",
|
|
7217
|
+
noData: "No data"
|
|
7218
|
+
},
|
|
7219
|
+
formPage: {
|
|
7220
|
+
loading: "Loading...",
|
|
7221
|
+
cancel: "Cancel",
|
|
7222
|
+
saveDraft: "Save draft",
|
|
7223
|
+
save: "Save",
|
|
7224
|
+
saving: "Saving...",
|
|
7225
|
+
submit: "Submit",
|
|
7226
|
+
submitting: "Submitting...",
|
|
7227
|
+
basicInfo: "Basic info",
|
|
7228
|
+
editTitle: (title) => `Edit ${title}`,
|
|
7229
|
+
createTitle: (title) => `New ${title}`
|
|
7230
|
+
},
|
|
7231
|
+
approvalDialog: {
|
|
7232
|
+
submitTitle: "Submit for approval",
|
|
7233
|
+
submitConfirm: "Confirm submission",
|
|
7234
|
+
approveTitle: "Approve",
|
|
7235
|
+
approveConfirm: "Confirm approval",
|
|
7236
|
+
rejectTitle: "Reject",
|
|
7237
|
+
rejectConfirm: "Confirm rejection",
|
|
7238
|
+
rejectPlaceholder: "Enter rejection reason...",
|
|
7239
|
+
remarkPlaceholder: "Add remark (optional)...",
|
|
7240
|
+
required: "* Required",
|
|
7241
|
+
cancel: "Cancel",
|
|
7242
|
+
processing: "Processing..."
|
|
7243
|
+
},
|
|
7244
|
+
crudPage: {
|
|
7245
|
+
all: "All",
|
|
7246
|
+
fieldPlaceholder: (label) => `Enter ${label}`
|
|
7247
|
+
},
|
|
7248
|
+
login: {
|
|
7249
|
+
username: "Username",
|
|
7250
|
+
usernamePlaceholder: "Enter username",
|
|
7251
|
+
password: "Password",
|
|
7252
|
+
passwordPlaceholder: "Enter password",
|
|
7253
|
+
remember: "Remember me",
|
|
7254
|
+
login: "Log in",
|
|
7255
|
+
loggingIn: "Logging in..."
|
|
7256
|
+
},
|
|
7257
|
+
form: {
|
|
7258
|
+
inputPlaceholder: (label) => `Enter ${label}`,
|
|
7259
|
+
selectPlaceholder: (label) => `Select ${label}`
|
|
7260
|
+
},
|
|
7261
|
+
routes: {
|
|
7262
|
+
createSuffix: " - New",
|
|
7263
|
+
editSuffix: " - Edit",
|
|
7264
|
+
detailSuffix: " - Details"
|
|
7265
|
+
},
|
|
7266
|
+
request: {
|
|
7267
|
+
success: "Success",
|
|
7268
|
+
opFailed: "Operation failed",
|
|
7269
|
+
failed: "Request failed",
|
|
7270
|
+
failedWithStatus: (status) => `Request failed (${status})`,
|
|
7271
|
+
failedWithMsg: (msg) => `Request failed: ${msg}`,
|
|
7272
|
+
timeout: "Request timed out",
|
|
7273
|
+
timeoutRetry: "Request timed out, please try again",
|
|
7274
|
+
canceled: "Request canceled",
|
|
7275
|
+
permissionDenied: "Permission denied",
|
|
7276
|
+
invalidUrl: (url) => `Invalid request URL: ${url}`,
|
|
7277
|
+
decodeFailed: (reason) => `Decode failed: ${reason}`,
|
|
7278
|
+
parseFailed: "Failed to parse data",
|
|
7279
|
+
networkError: "Network error",
|
|
7280
|
+
networkException: "Network error, please check your connection",
|
|
7281
|
+
unknownError: (error) => `Unknown error: ${error}`,
|
|
7282
|
+
unknown: "An unknown error occurred",
|
|
7283
|
+
uploadFailed: "Upload failed",
|
|
7284
|
+
uploadCanceled: "Upload canceled"
|
|
7285
|
+
},
|
|
7286
|
+
aiChat: {
|
|
7287
|
+
inputPlaceholder: "Type a message…",
|
|
7288
|
+
send: "Send",
|
|
7289
|
+
defaultTitle: (n) => `Chat ${n}`,
|
|
7290
|
+
phaseTyping: "Typing…",
|
|
7291
|
+
phaseThinking: "Thinking…",
|
|
7292
|
+
phaseReplying: "Replying…",
|
|
7293
|
+
phaseSending: "Sending…"
|
|
7294
|
+
}
|
|
6930
7295
|
}
|
|
6931
|
-
}
|
|
7296
|
+
};
|
|
6932
7297
|
//#endregion
|
|
6933
|
-
//#region ../core/
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
7298
|
+
//#region ../core/compositions/common/useLocale.ts
|
|
7299
|
+
/**
|
|
7300
|
+
* @description composable for unified component locale with global injection
|
|
7301
|
+
* support — the i18n counterpart of `useComponentSize`. Components call
|
|
7302
|
+
* `useLocale()` to get the active message dictionary (a computed ref) and read
|
|
7303
|
+
* their user-facing strings from it instead of hardcoding text.
|
|
7304
|
+
* @author kine-design
|
|
7305
|
+
* @version v1.0.0
|
|
7306
|
+
*
|
|
7307
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
7308
|
+
*/
|
|
7309
|
+
var KINE_LOCALE_KEY = Symbol("kine-locale");
|
|
7310
|
+
function resolveMessages(config) {
|
|
7311
|
+
if (!config) return locales["zh"];
|
|
7312
|
+
if (typeof config === "string") return locales[config] ?? locales["zh"];
|
|
7313
|
+
return config;
|
|
7314
|
+
}
|
|
7315
|
+
/**
|
|
7316
|
+
* Resolve the active message dictionary from the nearest `KConfigProvider`.
|
|
7317
|
+
* Falls back to the default (zh) pack when no provider is present.
|
|
7318
|
+
*/
|
|
7319
|
+
function useLocale() {
|
|
7320
|
+
const injected = inject(KINE_LOCALE_KEY, void 0);
|
|
7321
|
+
return computed(() => resolveMessages(injected?.value));
|
|
7322
|
+
}
|
|
7323
|
+
var activeLocaleMessages = locales["zh"];
|
|
7324
|
+
/** Read the global active dictionary from non-component (pure-function) code. */
|
|
7325
|
+
function getActiveLocaleMessages() {
|
|
7326
|
+
return activeLocaleMessages;
|
|
7327
|
+
}
|
|
7328
|
+
//#endregion
|
|
7329
|
+
//#region components/layout/KSider.tsx
|
|
7330
|
+
/**
|
|
7331
|
+
* @description KSider 侧边栏组件,支持折叠动画和自定义 trigger
|
|
7332
|
+
* @author 阿怪
|
|
7333
|
+
* @date 2026/2/26
|
|
7334
|
+
* @version v0.0.1
|
|
7335
|
+
*
|
|
7336
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
7337
|
+
*/
|
|
7338
|
+
var KSider_default = /* @__PURE__ */ defineComponent({
|
|
7339
|
+
name: "KSider",
|
|
7340
|
+
setup(_, ctx) {
|
|
7341
|
+
const t = useLocale();
|
|
7342
|
+
const collapsed = inject(LAYOUT_COLLAPSED_KEY);
|
|
7343
|
+
const toggle = inject(LAYOUT_TOGGLE_KEY);
|
|
7344
|
+
const drawerOpen = inject(LAYOUT_DRAWER_OPEN_KEY, ref(false));
|
|
7345
|
+
const siderWidth = inject(LAYOUT_SIDER_WIDTH_KEY, "240px");
|
|
7346
|
+
const collapsedWidth = inject(LAYOUT_COLLAPSED_WIDTH_KEY, "64px");
|
|
7347
|
+
const currentWidth = computed(() => {
|
|
7348
|
+
if (!collapsed) return siderWidth;
|
|
7349
|
+
return collapsed.value ? collapsedWidth : siderWidth;
|
|
7350
|
+
});
|
|
7351
|
+
const isCollapsed = computed(() => collapsed?.value ?? false);
|
|
7352
|
+
const handleTriggerClick = () => {
|
|
7353
|
+
toggle?.();
|
|
7354
|
+
};
|
|
7355
|
+
const defaultTrigger = () => createVNode("button", {
|
|
7356
|
+
"class": "k-crud-sider-trigger-btn",
|
|
7357
|
+
"onClick": handleTriggerClick,
|
|
7358
|
+
"title": isCollapsed.value ? t.value.a11y.expandSider : t.value.a11y.collapseSider
|
|
7359
|
+
}, [createVNode("span", { "class": ["k-crud-sider-trigger-icon", isCollapsed.value && "k-crud-sider-trigger-icon--collapsed"] }, ["‹"])]);
|
|
7360
|
+
return () => createVNode("aside", {
|
|
7361
|
+
"class": [
|
|
7362
|
+
"k-crud-sider",
|
|
7363
|
+
isCollapsed.value && "k-crud-sider--collapsed",
|
|
7364
|
+
drawerOpen.value && "k-crud-sider--drawer-open"
|
|
7365
|
+
],
|
|
7366
|
+
"style": { width: currentWidth.value }
|
|
7367
|
+
}, [
|
|
7368
|
+
ctx.slots.logo && createVNode("div", { "class": "k-crud-sider-logo" }, [ctx.slots.logo()]),
|
|
7369
|
+
createVNode("div", { "class": "k-crud-sider-body" }, [ctx.slots.default?.()]),
|
|
7370
|
+
createVNode("div", { "class": "k-crud-sider-trigger" }, [ctx.slots.trigger ? ctx.slots.trigger({
|
|
7371
|
+
collapsed: isCollapsed.value,
|
|
7372
|
+
toggle
|
|
7373
|
+
}) : defaultTrigger()])
|
|
7374
|
+
]);
|
|
7375
|
+
}
|
|
7376
|
+
});
|
|
7377
|
+
//#endregion
|
|
7378
|
+
//#region components/layout/KHeader.tsx
|
|
7379
|
+
/**
|
|
7380
|
+
* @description KHeader 顶部栏组件
|
|
7381
|
+
* @author 阿怪
|
|
7382
|
+
* @date 2026/2/26
|
|
7383
|
+
* @version v0.0.1
|
|
7384
|
+
*
|
|
7385
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
7386
|
+
*/
|
|
7387
|
+
var KHeader_default = /* @__PURE__ */ defineComponent({
|
|
7388
|
+
name: "KHeader",
|
|
7389
|
+
setup(_, ctx) {
|
|
7390
|
+
const toggleDrawer = inject(LAYOUT_TOGGLE_DRAWER_KEY, () => {});
|
|
7391
|
+
return () => createVNode("header", { "class": "k-crud-header" }, [
|
|
7392
|
+
createVNode("button", {
|
|
7393
|
+
"class": "k-crud-header-hamburger",
|
|
7394
|
+
"onClick": toggleDrawer
|
|
7395
|
+
}, [createVNode("span", { "class": "k-crud-header-hamburger-icon" }, null)]),
|
|
7396
|
+
createVNode("div", { "class": "k-crud-header-main" }, [ctx.slots.default?.()]),
|
|
7397
|
+
ctx.slots.extra && createVNode("div", { "class": "k-crud-header-extra" }, [ctx.slots.extra()])
|
|
7398
|
+
]);
|
|
7399
|
+
}
|
|
7400
|
+
});
|
|
7401
|
+
//#endregion
|
|
7402
|
+
//#region components/layout/KContent.tsx
|
|
7403
|
+
/**
|
|
7404
|
+
* @description KContent 主内容区组件
|
|
7405
|
+
* @author 阿怪
|
|
7406
|
+
* @date 2026/2/26
|
|
7407
|
+
* @version v0.0.1
|
|
7408
|
+
*
|
|
7409
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
7410
|
+
*/
|
|
7411
|
+
var KContent_default = /* @__PURE__ */ defineComponent({
|
|
7412
|
+
name: "KContent",
|
|
7413
|
+
setup(_, ctx) {
|
|
7414
|
+
return () => createVNode("main", { "class": "k-crud-content" }, [ctx.slots.default?.()]);
|
|
7415
|
+
}
|
|
7416
|
+
});
|
|
7417
|
+
//#endregion
|
|
7418
|
+
//#region ../core/compositions/common/testAnchor.ts
|
|
7419
|
+
/**
|
|
7420
|
+
* @description Test anchor system: provide/inject keys, types, and kDefineComponent wrapper
|
|
7421
|
+
* @author kine-design
|
|
7422
|
+
* @date 2026/4/28
|
|
7423
|
+
* @version v1.0.0
|
|
7424
|
+
*
|
|
7425
|
+
* Renders business-semantic `data-k` attributes on DOM elements when testAnchor is enabled,
|
|
7426
|
+
* allowing E2E tests to target components by stable identifiers.
|
|
7427
|
+
*/
|
|
7428
|
+
/** Global switch provided by KConfigProvider to enable data-k rendering */
|
|
7429
|
+
var K_TEST_ANCHOR_KEY = Symbol("k-test-anchor");
|
|
7430
|
+
/** Field identity provided by KFormItem so child inputs inherit field name */
|
|
7431
|
+
var K_FIELD_KEY = Symbol("k-field");
|
|
7432
|
+
/**
|
|
7433
|
+
* Extract text content from a VNode tree (for slotText mode).
|
|
7434
|
+
* Walks children recursively, concatenating string segments.
|
|
7435
|
+
*/
|
|
7436
|
+
function extractSlotText(nodes) {
|
|
7437
|
+
if (!nodes) return "";
|
|
7438
|
+
let text = "";
|
|
7439
|
+
for (const node of nodes) if (typeof node.children === "string") text += node.children;
|
|
7440
|
+
else if (Array.isArray(node.children)) text += extractSlotText(node.children);
|
|
7441
|
+
return text.trim();
|
|
7442
|
+
}
|
|
7443
|
+
/**
|
|
7444
|
+
* Resolve the data-k value for a component instance.
|
|
7445
|
+
* Returns undefined when testAnchor is off or no identity can be derived.
|
|
7446
|
+
*/
|
|
7447
|
+
function resolveDataK(config, props, attrs, fieldFromParent, slotNodes) {
|
|
7448
|
+
const override = attrs[`k-${config.type}`];
|
|
7449
|
+
if (typeof override === "string" && override) return `${config.type}:${override}`;
|
|
7450
|
+
if (config.prop) {
|
|
7451
|
+
const val = props[config.prop];
|
|
7452
|
+
if (typeof val === "string" && val) return `${config.type}:${val}`;
|
|
6973
7453
|
}
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
7454
|
+
if (config.slotText && slotNodes) {
|
|
7455
|
+
const text = extractSlotText(slotNodes);
|
|
7456
|
+
if (text) return `${config.type}:${text}`;
|
|
7457
|
+
}
|
|
7458
|
+
if (config.slotText && typeof props.text === "string" && props.text) return `${config.type}:${props.text}`;
|
|
7459
|
+
if (config.type === "field" && !config.prop && fieldFromParent) return `${config.type}:${fieldFromParent}`;
|
|
7460
|
+
}
|
|
6977
7461
|
/**
|
|
6978
|
-
*
|
|
6979
|
-
*
|
|
6980
|
-
|
|
6981
|
-
|
|
7462
|
+
* Inject data-k attribute into a VNode.
|
|
7463
|
+
* Uses cloneVNode to avoid mutating the original.
|
|
7464
|
+
*/
|
|
7465
|
+
function injectDataK(vnode, dataK) {
|
|
7466
|
+
return cloneVNode(vnode, { "data-k": dataK });
|
|
7467
|
+
}
|
|
7468
|
+
/**
|
|
7469
|
+
* Wrapper around Vue's defineComponent that automatically injects `data-k`
|
|
7470
|
+
* test anchor attributes when testAnchor is enabled via KConfigProvider.
|
|
6982
7471
|
*
|
|
6983
|
-
*
|
|
7472
|
+
* Usage:
|
|
7473
|
+
* ```tsx
|
|
7474
|
+
* export default kDefineComponent((_props, ctx) => {
|
|
7475
|
+
* return () => <div class="k-form-item">...</div>;
|
|
7476
|
+
* }, {
|
|
7477
|
+
* name: 'KFormItem',
|
|
7478
|
+
* props: FormCore.formItemProps,
|
|
7479
|
+
* kAnchor: { type: 'field', prop: 'prop' },
|
|
7480
|
+
* });
|
|
7481
|
+
* ```
|
|
6984
7482
|
*/
|
|
6985
|
-
function
|
|
6986
|
-
const
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
previewRotate.value = 0;
|
|
7010
|
-
previewVisible.value = true;
|
|
7011
|
-
};
|
|
7012
|
-
const closePreview = () => {
|
|
7013
|
-
previewVisible.value = false;
|
|
7014
|
-
};
|
|
7015
|
-
/** 预览切换到上一张 */
|
|
7016
|
-
const previewPrev = () => {
|
|
7017
|
-
const total = props.previewSrcList.length;
|
|
7018
|
-
if (total === 0) return;
|
|
7019
|
-
previewIndex.value = (previewIndex.value - 1 + total) % total;
|
|
7020
|
-
previewScale.value = 1;
|
|
7021
|
-
previewRotate.value = 0;
|
|
7022
|
-
emit("switch", previewIndex.value);
|
|
7023
|
-
};
|
|
7024
|
-
/** 预览切换到下一张 */
|
|
7025
|
-
const previewNext = () => {
|
|
7026
|
-
const total = props.previewSrcList.length;
|
|
7027
|
-
if (total === 0) return;
|
|
7028
|
-
previewIndex.value = (previewIndex.value + 1) % total;
|
|
7029
|
-
previewScale.value = 1;
|
|
7030
|
-
previewRotate.value = 0;
|
|
7031
|
-
emit("switch", previewIndex.value);
|
|
7032
|
-
};
|
|
7033
|
-
/** 预览放大 */
|
|
7034
|
-
const zoomIn = () => {
|
|
7035
|
-
previewScale.value = Math.min(previewScale.value + .25, 5);
|
|
7036
|
-
};
|
|
7037
|
-
/** 预览缩小 */
|
|
7038
|
-
const zoomOut = () => {
|
|
7039
|
-
previewScale.value = Math.max(previewScale.value - .25, .25);
|
|
7040
|
-
};
|
|
7041
|
-
/** 顺时针旋转 90° */
|
|
7042
|
-
const rotate = () => {
|
|
7043
|
-
previewRotate.value = (previewRotate.value + 90) % 360;
|
|
7044
|
-
};
|
|
7045
|
-
watch(() => props.src, reset);
|
|
7046
|
-
onMounted(() => {
|
|
7047
|
-
if (props.lazy) status.value = "loading";
|
|
7048
|
-
});
|
|
7049
|
-
return {
|
|
7050
|
-
status,
|
|
7051
|
-
previewVisible,
|
|
7052
|
-
previewIndex,
|
|
7053
|
-
previewScale,
|
|
7054
|
-
previewRotate,
|
|
7055
|
-
handleLoad,
|
|
7056
|
-
handleError,
|
|
7057
|
-
openPreview,
|
|
7058
|
-
closePreview,
|
|
7059
|
-
previewPrev,
|
|
7060
|
-
previewNext,
|
|
7061
|
-
zoomIn,
|
|
7062
|
-
zoomOut,
|
|
7063
|
-
rotate
|
|
7064
|
-
};
|
|
7483
|
+
function kDefineComponent(setup, options) {
|
|
7484
|
+
const { kAnchor, ...defineOptions } = options;
|
|
7485
|
+
return defineComponent((rawProps, ctx) => {
|
|
7486
|
+
const render = setup(rawProps, ctx);
|
|
7487
|
+
if (!kAnchor) return render;
|
|
7488
|
+
const testAnchor = inject(K_TEST_ANCHOR_KEY, void 0);
|
|
7489
|
+
const parentField = kAnchor.type === "field" && !kAnchor.prop ? inject(K_FIELD_KEY, void 0) : void 0;
|
|
7490
|
+
return () => {
|
|
7491
|
+
const vnode = render();
|
|
7492
|
+
if (!testAnchor?.value) return vnode;
|
|
7493
|
+
const props = rawProps;
|
|
7494
|
+
const slotNodes = kAnchor.slotText ? ctx.slots.default?.() ?? void 0 : void 0;
|
|
7495
|
+
const dataK = resolveDataK(kAnchor, props, ctx.attrs, parentField?.value, slotNodes);
|
|
7496
|
+
if (!dataK) return vnode;
|
|
7497
|
+
if (vnode === null || vnode === void 0) return vnode;
|
|
7498
|
+
if (Array.isArray(vnode)) {
|
|
7499
|
+
if (vnode.length === 0) return vnode;
|
|
7500
|
+
const first = vnode[0];
|
|
7501
|
+
if (first && typeof first === "object") return [injectDataK(first, dataK), ...vnode.slice(1)];
|
|
7502
|
+
return vnode;
|
|
7503
|
+
}
|
|
7504
|
+
return injectDataK(vnode, dataK);
|
|
7505
|
+
};
|
|
7506
|
+
}, defineOptions);
|
|
7065
7507
|
}
|
|
7066
7508
|
//#endregion
|
|
7067
|
-
//#region ../
|
|
7509
|
+
//#region ../ui/components/table/KTable.tsx
|
|
7068
7510
|
/**
|
|
7069
|
-
* @description
|
|
7511
|
+
* @description kine-ui table 组件
|
|
7070
7512
|
* @author 阿怪
|
|
7071
7513
|
* @date 2026/2/26
|
|
7072
|
-
* @version v1.
|
|
7514
|
+
* @version v1.1.0
|
|
7073
7515
|
*
|
|
7074
7516
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
7517
|
+
*
|
|
7518
|
+
* v1.1.0 migrate to kDefineComponent for data-k test anchor 2026/4/28
|
|
7075
7519
|
*/
|
|
7076
|
-
var
|
|
7520
|
+
var { props: props$2 } = TableCore;
|
|
7521
|
+
var KTable_default = kDefineComponent((_props, { slots }) => {
|
|
7522
|
+
const p = _props;
|
|
7523
|
+
const { initTable } = useTable();
|
|
7524
|
+
const t = useLocale();
|
|
7525
|
+
const testAnchor = inject(K_TEST_ANCHOR_KEY, void 0);
|
|
7526
|
+
return () => {
|
|
7527
|
+
const columns = [];
|
|
7528
|
+
(slots.default?.() ?? []).forEach((s) => {
|
|
7529
|
+
if (s.type === Fragment) {
|
|
7530
|
+
s.children?.forEach((c) => columns.push(c));
|
|
7531
|
+
return;
|
|
7532
|
+
}
|
|
7533
|
+
if (s.type === Comment) return;
|
|
7534
|
+
if (typeof s.type === "object" && s.type.name === "KTableColumn") columns.push(s);
|
|
7535
|
+
});
|
|
7536
|
+
const style = p.height ? { height: p.height } : void 0;
|
|
7537
|
+
const { thead, tbody } = initTable({
|
|
7538
|
+
empty: createVNode("tbody", {
|
|
7539
|
+
"class": "m-table-empty k-table-empty",
|
|
7540
|
+
"data-k": "state:tableEmpty"
|
|
7541
|
+
}, [createVNode("tr", null, [createVNode("th", { "colspan": columns.length }, [slots.empty?.() ?? t.value.common.noData])])]),
|
|
7542
|
+
tbodyTr: ({ data, param, slot, style: cellStyle, slotInfo }) => createVNode("td", {
|
|
7543
|
+
"style": cellStyle,
|
|
7544
|
+
"data-k": testAnchor?.value && param ? `col:${param}` : void 0,
|
|
7545
|
+
"class": [
|
|
7546
|
+
"m-td",
|
|
7547
|
+
"k-td",
|
|
7548
|
+
p.paramClass ? `m-td-${param}` : null,
|
|
7549
|
+
p.paramClass ? `k-td-${param}` : null
|
|
7550
|
+
]
|
|
7551
|
+
}, [slot ? slot({
|
|
7552
|
+
data: slotInfo?.data,
|
|
7553
|
+
row: slotInfo?.data,
|
|
7554
|
+
index: slotInfo?.index
|
|
7555
|
+
}) : data]),
|
|
7556
|
+
theadTh: ({ label, param, slot, style: cellStyle }) => createVNode("th", {
|
|
7557
|
+
"class": [
|
|
7558
|
+
"m-th",
|
|
7559
|
+
"k-th",
|
|
7560
|
+
p.paramClass ? `m-th-${param}` : null,
|
|
7561
|
+
p.paramClass ? `k-th-${param}` : null
|
|
7562
|
+
],
|
|
7563
|
+
"style": cellStyle
|
|
7564
|
+
}, [slot ? slot() : label]),
|
|
7565
|
+
thead: (ths) => createVNode("thead", {
|
|
7566
|
+
"class": "m-thead k-thead",
|
|
7567
|
+
"data-k": "region:tableHead"
|
|
7568
|
+
}, [createVNode("tr", { "class": "m-tr k-tr" }, [ths])]),
|
|
7569
|
+
tbody: (trs) => createVNode("tbody", {
|
|
7570
|
+
"class": "m-tbody k-tbody",
|
|
7571
|
+
"data-k": "region:tableBody"
|
|
7572
|
+
}, [trs]),
|
|
7573
|
+
tbodyTrs: (tds, i) => createVNode("tr", {
|
|
7574
|
+
"class": "m-tr k-tr",
|
|
7575
|
+
"key": i
|
|
7576
|
+
}, [...tds]),
|
|
7577
|
+
initSlot: (tableColumn) => {
|
|
7578
|
+
const children = tableColumn.children;
|
|
7579
|
+
if (!children || Array.isArray(children) || typeof children !== "object") return;
|
|
7580
|
+
return {
|
|
7581
|
+
body: children.default,
|
|
7582
|
+
head: children.head
|
|
7583
|
+
};
|
|
7584
|
+
}
|
|
7585
|
+
}, columns, p.data);
|
|
7586
|
+
return createVNode("div", {
|
|
7587
|
+
"class": [
|
|
7588
|
+
"m-table",
|
|
7589
|
+
"k-table",
|
|
7590
|
+
p.loading && "k-table-loading-wrap"
|
|
7591
|
+
],
|
|
7592
|
+
"style": style
|
|
7593
|
+
}, [p.loading && createVNode("div", { "class": "k-table-loading-overlay" }, [createVNode("div", { "class": "k-table-loading-spinner" }, null)]), createVNode("table", { "class": "m-table-inner k-table-inner" }, [thead, tbody])]);
|
|
7594
|
+
};
|
|
7595
|
+
}, {
|
|
7596
|
+
name: "KTable",
|
|
7077
7597
|
props: props$2,
|
|
7078
|
-
|
|
7079
|
-
|
|
7598
|
+
kAnchor: {
|
|
7599
|
+
type: "table",
|
|
7600
|
+
prop: "name"
|
|
7601
|
+
}
|
|
7602
|
+
});
|
|
7080
7603
|
//#endregion
|
|
7081
7604
|
//#region ../ui/components/pagination/KPagination.tsx
|
|
7082
7605
|
/**
|
|
@@ -7090,6 +7613,7 @@ var ImageCore = {
|
|
|
7090
7613
|
var { props: paginationProps } = PaginationCore;
|
|
7091
7614
|
var KPagination_default = /* @__PURE__ */ defineComponent((_props, { emit }) => {
|
|
7092
7615
|
const p = _props;
|
|
7616
|
+
const t = useLocale();
|
|
7093
7617
|
const currentValue = ref(p.modelValue ?? p.defaultCurrent ?? 1);
|
|
7094
7618
|
watch(() => p.modelValue, (val) => {
|
|
7095
7619
|
if (val !== void 0) currentValue.value = val;
|
|
@@ -7119,9 +7643,9 @@ var KPagination_default = /* @__PURE__ */ defineComponent((_props, { emit }) =>
|
|
|
7119
7643
|
const totalPages = getPageBtnLength();
|
|
7120
7644
|
const btnGetter = {
|
|
7121
7645
|
total: () => createVNode("div", { "class": "m-page-total k-page-total" }, [
|
|
7122
|
-
|
|
7646
|
+
t.value.pagination.totalPrefix,
|
|
7123
7647
|
createVNode("span", null, [p.total]),
|
|
7124
|
-
|
|
7648
|
+
t.value.pagination.totalSuffix
|
|
7125
7649
|
]),
|
|
7126
7650
|
prev: () => createVNode("div", {
|
|
7127
7651
|
"class": [
|
|
@@ -7266,6 +7790,7 @@ var KSearchTable_default = /* @__PURE__ */ defineComponent({
|
|
|
7266
7790
|
"reset"
|
|
7267
7791
|
],
|
|
7268
7792
|
setup(props, ctx) {
|
|
7793
|
+
const t = useLocale();
|
|
7269
7794
|
/** 点击搜索按钮 */
|
|
7270
7795
|
const onSearch = () => {
|
|
7271
7796
|
ctx.emit("search");
|
|
@@ -7279,12 +7804,17 @@ var KSearchTable_default = /* @__PURE__ */ defineComponent({
|
|
|
7279
7804
|
ctx.emit("update:page", page);
|
|
7280
7805
|
};
|
|
7281
7806
|
return () => createVNode("div", { "class": ["k-search-table", props.loading ? "k-search-table--loading" : ""] }, [
|
|
7282
|
-
props.searchable && createVNode("div", { "class": "k-search-table-search" }, [createVNode("div", { "class": "k-search-table-search-form" }, [ctx.slots.search?.()]), createVNode("div", {
|
|
7807
|
+
props.searchable && createVNode("div", { "class": "k-search-table-search" }, [createVNode("div", { "class": "k-search-table-search-form" }, [ctx.slots.search?.()]), createVNode("div", {
|
|
7808
|
+
"class": "k-search-table-search-actions",
|
|
7809
|
+
"data-k": "action:searchActions"
|
|
7810
|
+
}, [createVNode(KButton_default, {
|
|
7283
7811
|
"type": "primary",
|
|
7284
|
-
"text":
|
|
7812
|
+
"text": t.value.searchTable.search,
|
|
7813
|
+
"data-k": "action:search",
|
|
7285
7814
|
"onClick": onSearch
|
|
7286
7815
|
}, null), createVNode(KButton_default, {
|
|
7287
|
-
"text":
|
|
7816
|
+
"text": t.value.searchTable.reset,
|
|
7817
|
+
"data-k": "action:reset",
|
|
7288
7818
|
"onClick": onReset
|
|
7289
7819
|
}, null)])]),
|
|
7290
7820
|
ctx.slots.toolbar && createVNode("div", { "class": "k-search-table-toolbar" }, [ctx.slots.toolbar()]),
|
|
@@ -7329,6 +7859,7 @@ var { props: props$1 } = TagCore;
|
|
|
7329
7859
|
var KTag_default = /* @__PURE__ */ defineComponent((_props, { slots, emit }) => {
|
|
7330
7860
|
const props = _props;
|
|
7331
7861
|
const componentSize = useComponentSize(props);
|
|
7862
|
+
const t = useLocale();
|
|
7332
7863
|
return () => {
|
|
7333
7864
|
const { type, closable, disabled } = props;
|
|
7334
7865
|
const classes = [
|
|
@@ -7355,7 +7886,7 @@ var KTag_default = /* @__PURE__ */ defineComponent((_props, { slots, emit }) =>
|
|
|
7355
7886
|
}, [slots.default?.() ?? "", closable && createVNode("span", {
|
|
7356
7887
|
"class": "k-tag-close",
|
|
7357
7888
|
"onClick": handleClose,
|
|
7358
|
-
"aria-label":
|
|
7889
|
+
"aria-label": t.value.a11y.tagClose
|
|
7359
7890
|
}, [createTextVNode("×")])]);
|
|
7360
7891
|
};
|
|
7361
7892
|
}, {
|
|
@@ -7404,7 +7935,7 @@ var LoadingPlaceholder = () => createVNode("div", { "class": "k-image-placeholde
|
|
|
7404
7935
|
}, null)
|
|
7405
7936
|
])]);
|
|
7406
7937
|
/** 加载失败占位图标 */
|
|
7407
|
-
var ErrorPlaceholder = () => createVNode("div", { "class": "k-image-placeholder k-image-error" }, [createVNode("svg", {
|
|
7938
|
+
var ErrorPlaceholder = ({ text }) => createVNode("div", { "class": "k-image-placeholder k-image-error" }, [createVNode("svg", {
|
|
7408
7939
|
"viewBox": "0 0 24 24",
|
|
7409
7940
|
"fill": "none",
|
|
7410
7941
|
"class": "k-image-placeholder-icon"
|
|
@@ -7421,9 +7952,10 @@ var ErrorPlaceholder = () => createVNode("div", { "class": "k-image-placeholder
|
|
|
7421
7952
|
"stroke": "currentColor",
|
|
7422
7953
|
"stroke-width": "1.5",
|
|
7423
7954
|
"stroke-linecap": "round"
|
|
7424
|
-
}, null)]), createVNode("span", { "class": "k-image-error-text" }, [
|
|
7955
|
+
}, null)]), createVNode("span", { "class": "k-image-error-text" }, [text])]);
|
|
7425
7956
|
var KImage_default = /* @__PURE__ */ defineComponent((_props, { slots, emit }) => {
|
|
7426
7957
|
const cProps = _props;
|
|
7958
|
+
const t = useLocale();
|
|
7427
7959
|
const { status, previewVisible, previewIndex, previewScale, previewRotate, handleLoad, handleError, openPreview, closePreview, previewPrev, previewNext, zoomIn, zoomOut, rotate } = useImage(cProps, (event, payload) => emit(event, payload));
|
|
7428
7960
|
const hasPreview = computed(() => cProps.previewSrcList && cProps.previewSrcList.length > 0);
|
|
7429
7961
|
return () => {
|
|
@@ -7437,7 +7969,7 @@ var KImage_default = /* @__PURE__ */ defineComponent((_props, { slots, emit }) =
|
|
|
7437
7969
|
"onClick": hasPreview.value ? openPreview : void 0
|
|
7438
7970
|
}, [
|
|
7439
7971
|
status.value === "loading" && (slots.placeholder ? slots.placeholder() : createVNode(LoadingPlaceholder, null, null)),
|
|
7440
|
-
status.value === "error" && (slots.error ? slots.error() : createVNode(ErrorPlaceholder,
|
|
7972
|
+
status.value === "error" && (slots.error ? slots.error() : createVNode(ErrorPlaceholder, { "text": t.value.image.loadError }, null)),
|
|
7441
7973
|
createVNode("img", {
|
|
7442
7974
|
"class": ["k-image-inner", status.value !== "loaded" ? "k-image-inner-hidden" : ""],
|
|
7443
7975
|
"src": cProps.src,
|
|
@@ -7458,23 +7990,23 @@ var KImage_default = /* @__PURE__ */ defineComponent((_props, { slots, emit }) =
|
|
|
7458
7990
|
createVNode("button", {
|
|
7459
7991
|
"class": "k-image-preview-btn",
|
|
7460
7992
|
"onClick": zoomOut,
|
|
7461
|
-
"title":
|
|
7993
|
+
"title": t.value.image.zoomOut
|
|
7462
7994
|
}, [createTextVNode("-")]),
|
|
7463
7995
|
createVNode("span", { "class": "k-image-preview-scale" }, [Math.round(previewScale.value * 100), createTextVNode("%")]),
|
|
7464
7996
|
createVNode("button", {
|
|
7465
7997
|
"class": "k-image-preview-btn",
|
|
7466
7998
|
"onClick": zoomIn,
|
|
7467
|
-
"title":
|
|
7999
|
+
"title": t.value.image.zoomIn
|
|
7468
8000
|
}, [createTextVNode("+")]),
|
|
7469
8001
|
createVNode("button", {
|
|
7470
8002
|
"class": "k-image-preview-btn",
|
|
7471
8003
|
"onClick": rotate,
|
|
7472
|
-
"title":
|
|
8004
|
+
"title": t.value.image.rotate
|
|
7473
8005
|
}, [createTextVNode("↻")]),
|
|
7474
8006
|
createVNode("button", {
|
|
7475
8007
|
"class": "k-image-preview-btn k-image-preview-close",
|
|
7476
8008
|
"onClick": closePreview,
|
|
7477
|
-
"title":
|
|
8009
|
+
"title": t.value.image.close
|
|
7478
8010
|
}, [createTextVNode("✕")])
|
|
7479
8011
|
]),
|
|
7480
8012
|
createVNode("img", {
|
|
@@ -7595,6 +8127,7 @@ var { props: selectProps, useSelect } = SelectCore;
|
|
|
7595
8127
|
var KSelect_default = kDefineComponent((_props, _ctx) => {
|
|
7596
8128
|
const props = _props;
|
|
7597
8129
|
const { slots, expose } = _ctx;
|
|
8130
|
+
const t = useLocale();
|
|
7598
8131
|
const componentSize = useComponentSize(props);
|
|
7599
8132
|
const { inputValue, isOpen, fetchLoading, inputReadonly, displayOptions, selectedTags, lastOptionRef, optionsContainerRef, onSelect, onDeleteTag, onInput, onFocus, onBlur, tools, updateFetchObserver } = useSelect(props, _ctx);
|
|
7600
8133
|
const triggerRef = ref(null);
|
|
@@ -7696,7 +8229,7 @@ var KSelect_default = kDefineComponent((_props, _ctx) => {
|
|
|
7696
8229
|
"class": "m-select-input k-select-input",
|
|
7697
8230
|
"type": "text",
|
|
7698
8231
|
"value": inputValue.value,
|
|
7699
|
-
"placeholder": selectedTags.value.length === 0 ? props.placeholder : "",
|
|
8232
|
+
"placeholder": selectedTags.value.length === 0 ? props.placeholder ?? t.value.select.placeholder : "",
|
|
7700
8233
|
"onInput": (e) => {
|
|
7701
8234
|
inputValue.value = e.target.value;
|
|
7702
8235
|
onInput();
|
|
@@ -7717,7 +8250,7 @@ var KSelect_default = kDefineComponent((_props, _ctx) => {
|
|
|
7717
8250
|
"value": inputValue.value,
|
|
7718
8251
|
"readonly": inputReadonly.value,
|
|
7719
8252
|
"disabled": props.disabled,
|
|
7720
|
-
"placeholder": props.placeholder,
|
|
8253
|
+
"placeholder": props.placeholder ?? t.value.select.placeholder,
|
|
7721
8254
|
"onInput": (e) => {
|
|
7722
8255
|
inputValue.value = e.target.value;
|
|
7723
8256
|
onInput();
|
|
@@ -7728,7 +8261,7 @@ var KSelect_default = kDefineComponent((_props, _ctx) => {
|
|
|
7728
8261
|
props.loading && createVNode("span", { "class": "k-select-loading-icon" }, null),
|
|
7729
8262
|
showClear && !props.loading && createVNode("span", {
|
|
7730
8263
|
"class": "k-select-clear",
|
|
7731
|
-
"aria-label":
|
|
8264
|
+
"aria-label": t.value.select.clear,
|
|
7732
8265
|
"onMousedown": (e) => {
|
|
7733
8266
|
e.preventDefault();
|
|
7734
8267
|
e.stopPropagation();
|
|
@@ -7758,7 +8291,7 @@ var KSelect_default = kDefineComponent((_props, _ctx) => {
|
|
|
7758
8291
|
if (i === lastIndex) lastOptionRef.value = el;
|
|
7759
8292
|
},
|
|
7760
8293
|
"onClick": () => handleOptionClick(o)
|
|
7761
|
-
}, [getOptionDisplay(o.value)])) : createVNode("div", { "class": "m-select-empty k-select-empty" }, [slots.empty ? slots.empty() : createVNode("span", null, [
|
|
8294
|
+
}, [getOptionDisplay(o.value)])) : createVNode("div", { "class": "m-select-empty k-select-empty" }, [slots.empty ? slots.empty() : createVNode("span", null, [t.value.select.noData])])]), fetchLoading.value && createVNode("div", { "class": "m-select-loading k-select-loading" }, [t.value.select.loading])])] });
|
|
7762
8295
|
};
|
|
7763
8296
|
return createVNode("div", { "class": [
|
|
7764
8297
|
"m-select",
|
|
@@ -8286,6 +8819,14 @@ var FetchTransport = class {
|
|
|
8286
8819
|
};
|
|
8287
8820
|
//#endregion
|
|
8288
8821
|
//#region composables/request/types.ts
|
|
8822
|
+
/**
|
|
8823
|
+
* @description 请求模块类型定义
|
|
8824
|
+
* @author 阿怪
|
|
8825
|
+
* @date 2026/3/15
|
|
8826
|
+
* @version v0.0.1
|
|
8827
|
+
*
|
|
8828
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
8829
|
+
*/
|
|
8289
8830
|
/** 业务错误:后端返回 success=false */
|
|
8290
8831
|
var BusinessError = class extends Error {
|
|
8291
8832
|
name = "BusinessError";
|
|
@@ -8303,13 +8844,14 @@ var NetworkRequestError = class extends Error {
|
|
|
8303
8844
|
}
|
|
8304
8845
|
};
|
|
8305
8846
|
function networkErrorMessage(e) {
|
|
8847
|
+
const t = getActiveLocaleMessages();
|
|
8306
8848
|
switch (e.type) {
|
|
8307
|
-
case "invalidURL": return
|
|
8308
|
-
case "timeout": return
|
|
8849
|
+
case "invalidURL": return t.request.invalidUrl(e.url);
|
|
8850
|
+
case "timeout": return t.request.timeout;
|
|
8309
8851
|
case "httpError": return `HTTP ${e.status} ${e.statusText}`;
|
|
8310
|
-
case "decodingFailed": return
|
|
8311
|
-
case "aborted": return
|
|
8312
|
-
case "unknown": return
|
|
8852
|
+
case "decodingFailed": return t.request.decodeFailed(e.reason);
|
|
8853
|
+
case "aborted": return t.request.canceled;
|
|
8854
|
+
case "unknown": return t.request.unknownError(String(e.error));
|
|
8313
8855
|
}
|
|
8314
8856
|
}
|
|
8315
8857
|
//#endregion
|
|
@@ -8344,11 +8886,12 @@ function toQueryString(params) {
|
|
|
8344
8886
|
}
|
|
8345
8887
|
/** 根据 Content-Type 解析响应,并检查 WrappedResponse */
|
|
8346
8888
|
async function unwrapResponse(response) {
|
|
8889
|
+
const t = getActiveLocaleMessages();
|
|
8347
8890
|
if (response.status < 200 || response.status >= 300) {
|
|
8348
8891
|
if (response.status >= 400) {
|
|
8349
8892
|
if ((response.headers["content-type"] ?? "").includes("application/json")) try {
|
|
8350
8893
|
const json = await response.json();
|
|
8351
|
-
if (isWrappedResponse$1(json) && !json.success) throw new BusinessError(json.message ||
|
|
8894
|
+
if (isWrappedResponse$1(json) && !json.success) throw new BusinessError(json.message || t.request.failedWithStatus(response.status));
|
|
8352
8895
|
} catch (e) {
|
|
8353
8896
|
if (e instanceof BusinessError) throw e;
|
|
8354
8897
|
}
|
|
@@ -8362,7 +8905,7 @@ async function unwrapResponse(response) {
|
|
|
8362
8905
|
if ((response.headers["content-type"] ?? "").includes("application/json")) {
|
|
8363
8906
|
const json = await response.json();
|
|
8364
8907
|
if (isWrappedResponse$1(json)) {
|
|
8365
|
-
if (!json.success) throw new BusinessError(json.message ||
|
|
8908
|
+
if (!json.success) throw new BusinessError(json.message || t.request.failed);
|
|
8366
8909
|
return json.data;
|
|
8367
8910
|
}
|
|
8368
8911
|
return json;
|
|
@@ -8461,6 +9004,7 @@ var RequestBuilder = class {
|
|
|
8461
9004
|
return this;
|
|
8462
9005
|
}
|
|
8463
9006
|
async execute() {
|
|
9007
|
+
const t = getActiveLocaleMessages();
|
|
8464
9008
|
const { transport, controlGate, baseURL, defaultHeaders, getToken, onUnauthorized, responseInterceptor, registerAbort } = this.context;
|
|
8465
9009
|
let fullURL = this.url.startsWith("http") ? this.url : `${baseURL}${this.url}`;
|
|
8466
9010
|
const abortController = new AbortController();
|
|
@@ -8516,12 +9060,12 @@ var RequestBuilder = class {
|
|
|
8516
9060
|
"PUT",
|
|
8517
9061
|
"PATCH",
|
|
8518
9062
|
"DELETE"
|
|
8519
|
-
].includes(this.method)) this.context.feedback.showSuccess(
|
|
9063
|
+
].includes(this.method)) this.context.feedback.showSuccess(t.request.success);
|
|
8520
9064
|
return finalResult;
|
|
8521
9065
|
} catch (error) {
|
|
8522
9066
|
if (error instanceof NetworkRequestError && error.detail.type === "httpError" && error.detail.status === 401) onUnauthorized?.();
|
|
8523
9067
|
if (this.context.feedback) {
|
|
8524
|
-
const msg = error instanceof BusinessError ? error.message : error instanceof NetworkRequestError ?
|
|
9068
|
+
const msg = error instanceof BusinessError ? error.message : error instanceof NetworkRequestError ? t.request.failedWithMsg(error.message) : t.request.opFailed;
|
|
8525
9069
|
this.context.feedback.showError(msg);
|
|
8526
9070
|
}
|
|
8527
9071
|
throw error;
|
|
@@ -8716,6 +9260,7 @@ var defaultFeedbackHandler = {
|
|
|
8716
9260
|
* createErrorHandler 和 useErrorHandler 共用此函数。
|
|
8717
9261
|
*/
|
|
8718
9262
|
function dispatchError(error, options) {
|
|
9263
|
+
const t = getActiveLocaleMessages();
|
|
8719
9264
|
const feedback = options.feedbackHandler ?? defaultFeedbackHandler;
|
|
8720
9265
|
if (error instanceof BusinessError) {
|
|
8721
9266
|
options.onBusinessError?.(error);
|
|
@@ -8732,28 +9277,28 @@ function dispatchError(error, options) {
|
|
|
8732
9277
|
return;
|
|
8733
9278
|
}
|
|
8734
9279
|
if (detail.status === 403) {
|
|
8735
|
-
feedback.showWarning(
|
|
9280
|
+
feedback.showWarning(t.request.permissionDenied);
|
|
8736
9281
|
return;
|
|
8737
9282
|
}
|
|
8738
|
-
feedback.showError(
|
|
9283
|
+
feedback.showError(t.request.failedWithStatus(detail.status));
|
|
8739
9284
|
return;
|
|
8740
9285
|
case "timeout":
|
|
8741
|
-
feedback.showWarning(
|
|
9286
|
+
feedback.showWarning(t.request.timeoutRetry);
|
|
8742
9287
|
return;
|
|
8743
9288
|
case "aborted": return;
|
|
8744
9289
|
case "invalidURL":
|
|
8745
|
-
feedback.showError(
|
|
9290
|
+
feedback.showError(t.request.invalidUrl(detail.url));
|
|
8746
9291
|
return;
|
|
8747
9292
|
case "decodingFailed":
|
|
8748
|
-
feedback.showError(
|
|
9293
|
+
feedback.showError(t.request.parseFailed);
|
|
8749
9294
|
return;
|
|
8750
9295
|
case "unknown":
|
|
8751
|
-
feedback.showError(
|
|
9296
|
+
feedback.showError(t.request.networkException);
|
|
8752
9297
|
return;
|
|
8753
9298
|
}
|
|
8754
9299
|
}
|
|
8755
9300
|
const message = error instanceof Error ? error.message : String(error);
|
|
8756
|
-
feedback.showError(message ||
|
|
9301
|
+
feedback.showError(message || t.request.unknown);
|
|
8757
9302
|
}
|
|
8758
9303
|
//#endregion
|
|
8759
9304
|
//#region composables/error/createErrorHandler.ts
|
|
@@ -8959,6 +9504,7 @@ function useCrudPage(config, tableBodyRef) {
|
|
|
8959
9504
|
loading.value = true;
|
|
8960
9505
|
try {
|
|
8961
9506
|
const params = {
|
|
9507
|
+
...config.defaultParams,
|
|
8962
9508
|
page: page.value,
|
|
8963
9509
|
pageSize: pageSize.value
|
|
8964
9510
|
};
|
|
@@ -9021,6 +9567,7 @@ var KCrudPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9021
9567
|
required: true
|
|
9022
9568
|
} },
|
|
9023
9569
|
setup(props, { slots }) {
|
|
9570
|
+
const t = useLocale();
|
|
9024
9571
|
const rootRef = ref();
|
|
9025
9572
|
const tableBodyRef = computed(() => rootRef.value?.querySelector(".k-search-table-body"));
|
|
9026
9573
|
const { page, pageSize, total, list, loading, filters, onPageChange, onSearch, onReset } = useCrudPage(props.config, tableBodyRef);
|
|
@@ -9109,6 +9656,7 @@ var KCrudPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9109
9656
|
if (!props.config.filters?.length) return null;
|
|
9110
9657
|
return props.config.filters.map((f) => createVNode("div", {
|
|
9111
9658
|
"class": "k-crud-page-filter-item",
|
|
9659
|
+
"data-k": `filter:${f.param}`,
|
|
9112
9660
|
"key": f.param
|
|
9113
9661
|
}, [createVNode("label", { "class": "k-crud-page-filter-label" }, [f.label]), f.type === "select" ? createVNode(KSelect_default, {
|
|
9114
9662
|
"class": "k-crud-page-filter-control",
|
|
@@ -9116,13 +9664,13 @@ var KCrudPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9116
9664
|
"options": f.options ?? [],
|
|
9117
9665
|
"optionParam": "label",
|
|
9118
9666
|
"valueParam": "value",
|
|
9119
|
-
"placeholder": f.placeholder ??
|
|
9667
|
+
"placeholder": f.placeholder ?? t.value.crudPage.all,
|
|
9120
9668
|
"onUpdate:modelValue": (v) => {
|
|
9121
9669
|
filters[f.param] = v || void 0;
|
|
9122
9670
|
}
|
|
9123
9671
|
}, null) : createVNode(KInput_default, {
|
|
9124
9672
|
"class": "k-crud-page-filter-control",
|
|
9125
|
-
"placeholder": f.placeholder ??
|
|
9673
|
+
"placeholder": f.placeholder ?? t.value.crudPage.fieldPlaceholder(f.label),
|
|
9126
9674
|
"modelValue": filters[f.param] ?? "",
|
|
9127
9675
|
"onUpdate:modelValue": (v) => {
|
|
9128
9676
|
filters[f.param] = v || void 0;
|
|
@@ -9131,6 +9679,7 @@ var KCrudPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9131
9679
|
};
|
|
9132
9680
|
return () => createVNode("div", {
|
|
9133
9681
|
"class": "k-crud-page",
|
|
9682
|
+
"data-k": "page:crudList",
|
|
9134
9683
|
"ref": rootRef
|
|
9135
9684
|
}, [createVNode(KPageHeader_default, { "title": props.config.title }, { extra: slots.headerExtra }), createVNode(KSearchTable_default, {
|
|
9136
9685
|
"data": list.value,
|
|
@@ -9185,6 +9734,7 @@ var KLoginPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9185
9734
|
}
|
|
9186
9735
|
},
|
|
9187
9736
|
setup(props, ctx) {
|
|
9737
|
+
const t = useLocale();
|
|
9188
9738
|
const username = ref("");
|
|
9189
9739
|
const password = ref("");
|
|
9190
9740
|
const remember = ref(false);
|
|
@@ -9204,17 +9754,17 @@ var KLoginPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9204
9754
|
"class": "k-login-form",
|
|
9205
9755
|
"onSubmit": handleSubmit
|
|
9206
9756
|
}, [
|
|
9207
|
-
createVNode("div", { "class": "k-login-form-item" }, [createVNode("label", null, [
|
|
9757
|
+
createVNode("div", { "class": "k-login-form-item" }, [createVNode("label", null, [t.value.login.username]), createVNode(KInput_default, {
|
|
9208
9758
|
"modelValue": username.value,
|
|
9209
|
-
"placeholder":
|
|
9759
|
+
"placeholder": t.value.login.usernamePlaceholder,
|
|
9210
9760
|
"onUpdate:modelValue": (v) => {
|
|
9211
9761
|
username.value = v;
|
|
9212
9762
|
}
|
|
9213
9763
|
}, null)]),
|
|
9214
|
-
createVNode("div", { "class": "k-login-form-item" }, [createVNode("label", null, [
|
|
9764
|
+
createVNode("div", { "class": "k-login-form-item" }, [createVNode("label", null, [t.value.login.password]), createVNode(KInput_default, {
|
|
9215
9765
|
"type": "password",
|
|
9216
9766
|
"modelValue": password.value,
|
|
9217
|
-
"placeholder":
|
|
9767
|
+
"placeholder": t.value.login.passwordPlaceholder,
|
|
9218
9768
|
"onUpdate:modelValue": (v) => {
|
|
9219
9769
|
password.value = v;
|
|
9220
9770
|
}
|
|
@@ -9225,10 +9775,10 @@ var KLoginPage_default = /* @__PURE__ */ defineComponent({
|
|
|
9225
9775
|
"onChange": (e) => {
|
|
9226
9776
|
remember.value = e.target.checked;
|
|
9227
9777
|
}
|
|
9228
|
-
}, null),
|
|
9778
|
+
}, null), t.value.login.remember]),
|
|
9229
9779
|
createVNode(KButton_default, {
|
|
9230
9780
|
"type": "primary",
|
|
9231
|
-
"text": props.loading ?
|
|
9781
|
+
"text": props.loading ? t.value.login.loggingIn : t.value.login.login,
|
|
9232
9782
|
"disabled": props.loading,
|
|
9233
9783
|
"loading": props.loading,
|
|
9234
9784
|
"onClick": handleSubmit
|
|
@@ -9688,6 +10238,7 @@ var KUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
9688
10238
|
"error"
|
|
9689
10239
|
],
|
|
9690
10240
|
setup(props, ctx) {
|
|
10241
|
+
const t = useLocale();
|
|
9691
10242
|
const inputRef = ref(null);
|
|
9692
10243
|
const isDragOver = ref(false);
|
|
9693
10244
|
const openFileDialog = () => {
|
|
@@ -9695,7 +10246,7 @@ var KUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
9695
10246
|
inputRef.value?.click();
|
|
9696
10247
|
};
|
|
9697
10248
|
const validateFile = (file) => {
|
|
9698
|
-
if (props.maxSize !== Infinity && file.size > props.maxSize) return
|
|
10249
|
+
if (props.maxSize !== Infinity && file.size > props.maxSize) return t.value.upload.oversize(file.name, formatSize$1(props.maxSize));
|
|
9699
10250
|
return null;
|
|
9700
10251
|
};
|
|
9701
10252
|
const processFiles = async (rawFiles) => {
|
|
@@ -9814,7 +10365,7 @@ var KUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
9814
10365
|
"accept": props.accept,
|
|
9815
10366
|
"multiple": props.multiple,
|
|
9816
10367
|
"onChange": onInputChange
|
|
9817
|
-
}, null), ctx.slots.default?.() ?? createVNode("div", { "class": "k-upload-placeholder" }, [createVNode("span", { "class": "k-upload-icon" }, [createTextVNode("↑")]), createVNode("span", { "class": "k-upload-text" }, [props.drag ?
|
|
10368
|
+
}, null), ctx.slots.default?.() ?? createVNode("div", { "class": "k-upload-placeholder" }, [createVNode("span", { "class": "k-upload-icon" }, [createTextVNode("↑")]), createVNode("span", { "class": "k-upload-text" }, [props.drag ? t.value.upload.trigger : t.value.upload.triggerSimple])])]);
|
|
9818
10369
|
};
|
|
9819
10370
|
}
|
|
9820
10371
|
});
|
|
@@ -9878,6 +10429,7 @@ var KImageUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
9878
10429
|
"error"
|
|
9879
10430
|
],
|
|
9880
10431
|
setup(props, ctx) {
|
|
10432
|
+
const t = useLocale();
|
|
9881
10433
|
const inputRef = ref(null);
|
|
9882
10434
|
const isDragOver = ref(false);
|
|
9883
10435
|
const objectUrlMap = ref(/* @__PURE__ */ new Map());
|
|
@@ -9913,7 +10465,7 @@ var KImageUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
9913
10465
|
if (props.maxSize !== Infinity && raw.size > props.maxSize) {
|
|
9914
10466
|
ctx.emit("error", {
|
|
9915
10467
|
file: raw,
|
|
9916
|
-
message:
|
|
10468
|
+
message: t.value.upload.oversize(raw.name)
|
|
9917
10469
|
});
|
|
9918
10470
|
continue;
|
|
9919
10471
|
}
|
|
@@ -10027,7 +10579,7 @@ var KImageUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
10027
10579
|
"class": "k-image-upload-progress",
|
|
10028
10580
|
"style": { height: `${file.percent}%` }
|
|
10029
10581
|
}, null), createVNode("span", { "class": "k-image-upload-percent" }, [file.percent, createTextVNode("%")])]),
|
|
10030
|
-
file.status === "error" && createVNode("div", { "class": "k-image-upload-overlay k-image-upload-overlay--error" }, [createVNode("span", null, [
|
|
10582
|
+
file.status === "error" && createVNode("div", { "class": "k-image-upload-overlay k-image-upload-overlay--error" }, [createVNode("span", null, [t.value.upload.uploadFailed])]),
|
|
10031
10583
|
!props.disabled && createVNode(KButton_default, {
|
|
10032
10584
|
"class": "k-image-upload-remove",
|
|
10033
10585
|
"plain": true,
|
|
@@ -10072,12 +10624,6 @@ var KImageUpload_default = /* @__PURE__ */ defineComponent({
|
|
|
10072
10624
|
*
|
|
10073
10625
|
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
10074
10626
|
*/
|
|
10075
|
-
var STATUS_TEXT = {
|
|
10076
|
-
pending: "等待中",
|
|
10077
|
-
uploading: "上传中",
|
|
10078
|
-
success: "已完成",
|
|
10079
|
-
error: "上传失败"
|
|
10080
|
-
};
|
|
10081
10627
|
function formatSize(bytes) {
|
|
10082
10628
|
if (bytes < 1024) return `${bytes} B`;
|
|
10083
10629
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
@@ -10097,6 +10643,16 @@ var KFileList_default = /* @__PURE__ */ defineComponent({
|
|
|
10097
10643
|
},
|
|
10098
10644
|
emits: ["remove"],
|
|
10099
10645
|
setup(props, ctx) {
|
|
10646
|
+
const t = useLocale();
|
|
10647
|
+
const statusText = (status) => {
|
|
10648
|
+
const u = t.value.upload;
|
|
10649
|
+
return {
|
|
10650
|
+
pending: u.statusWaiting,
|
|
10651
|
+
uploading: u.statusUploading,
|
|
10652
|
+
success: u.statusDone,
|
|
10653
|
+
error: u.statusFailed
|
|
10654
|
+
}[status];
|
|
10655
|
+
};
|
|
10100
10656
|
return () => {
|
|
10101
10657
|
if (props.files.length === 0) return null;
|
|
10102
10658
|
return createVNode("ul", { "class": "k-file-list" }, [props.files.map((file) => {
|
|
@@ -10120,7 +10676,7 @@ var KFileList_default = /* @__PURE__ */ defineComponent({
|
|
|
10120
10676
|
}, [file.name]) : file.name]), createVNode("span", { "class": "k-file-list-meta" }, [
|
|
10121
10677
|
formatSize(file.size),
|
|
10122
10678
|
createTextVNode(" · "),
|
|
10123
|
-
|
|
10679
|
+
statusText(file.status)
|
|
10124
10680
|
])]),
|
|
10125
10681
|
props.removable && createVNode(KButton_default, {
|
|
10126
10682
|
"class": "k-file-list-remove",
|
|
@@ -10140,6 +10696,14 @@ var KFileList_default = /* @__PURE__ */ defineComponent({
|
|
|
10140
10696
|
//#endregion
|
|
10141
10697
|
//#region composables/router/defineCrudRoutes.ts
|
|
10142
10698
|
/**
|
|
10699
|
+
* @description CRUD 路由便利函数 — 根据实体配置批量生成路由记录
|
|
10700
|
+
* @author 阿怪
|
|
10701
|
+
* @date 2026/2/26
|
|
10702
|
+
* @version v0.0.1
|
|
10703
|
+
*
|
|
10704
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
10705
|
+
*/
|
|
10706
|
+
/**
|
|
10143
10707
|
* 根据实体配置生成标准 CRUD 路由记录数组。
|
|
10144
10708
|
*
|
|
10145
10709
|
* 生成规则:
|
|
@@ -10166,6 +10730,7 @@ var KFileList_default = /* @__PURE__ */ defineComponent({
|
|
|
10166
10730
|
function defineCrudRoutes(config) {
|
|
10167
10731
|
const { name, path, permission, title, icon } = config;
|
|
10168
10732
|
const resource = permission ?? name.toLowerCase();
|
|
10733
|
+
const t = getActiveLocaleMessages();
|
|
10169
10734
|
const basePath = path.replace(/\/+$/, "");
|
|
10170
10735
|
const opSpecs = [
|
|
10171
10736
|
{
|
|
@@ -10182,7 +10747,7 @@ function defineCrudRoutes(config) {
|
|
|
10182
10747
|
suffix: "/new",
|
|
10183
10748
|
action: "create",
|
|
10184
10749
|
component: config.new,
|
|
10185
|
-
titleSuffix:
|
|
10750
|
+
titleSuffix: t.routes.createSuffix,
|
|
10186
10751
|
keepAlive: false,
|
|
10187
10752
|
hidden: true
|
|
10188
10753
|
},
|
|
@@ -10191,7 +10756,7 @@ function defineCrudRoutes(config) {
|
|
|
10191
10756
|
suffix: "/:id/edit",
|
|
10192
10757
|
action: "update",
|
|
10193
10758
|
component: config.modify,
|
|
10194
|
-
titleSuffix:
|
|
10759
|
+
titleSuffix: t.routes.editSuffix,
|
|
10195
10760
|
keepAlive: false,
|
|
10196
10761
|
hidden: true
|
|
10197
10762
|
},
|
|
@@ -10200,7 +10765,7 @@ function defineCrudRoutes(config) {
|
|
|
10200
10765
|
suffix: "/:id",
|
|
10201
10766
|
action: "read",
|
|
10202
10767
|
component: config.detail,
|
|
10203
|
-
titleSuffix:
|
|
10768
|
+
titleSuffix: t.routes.detailSuffix,
|
|
10204
10769
|
keepAlive: false,
|
|
10205
10770
|
hidden: true
|
|
10206
10771
|
}
|
|
@@ -10486,6 +11051,14 @@ function addTabFromRoute(tabStore, route) {
|
|
|
10486
11051
|
}
|
|
10487
11052
|
//#endregion
|
|
10488
11053
|
//#region composables/request/transport/xhrTransport.ts
|
|
11054
|
+
/**
|
|
11055
|
+
* @description 基于 XMLHttpRequest 的传输层实现,支持上传进度
|
|
11056
|
+
* @author 阿怪
|
|
11057
|
+
* @date 2026/3/15
|
|
11058
|
+
* @version v0.0.1
|
|
11059
|
+
*
|
|
11060
|
+
* 江湖的业务千篇一律,复杂的代码好几百行。
|
|
11061
|
+
*/
|
|
10489
11062
|
/** 解析 XHR 响应头字符串为 Record */
|
|
10490
11063
|
function parseResponseHeaders(rawHeaders) {
|
|
10491
11064
|
const headers = {};
|
|
@@ -10501,6 +11074,7 @@ function parseResponseHeaders(rawHeaders) {
|
|
|
10501
11074
|
}
|
|
10502
11075
|
var XhrTransport = class {
|
|
10503
11076
|
send(request) {
|
|
11077
|
+
const t = getActiveLocaleMessages();
|
|
10504
11078
|
return new Promise((resolve, reject) => {
|
|
10505
11079
|
const xhr = new XMLHttpRequest();
|
|
10506
11080
|
xhr.open(request.method, request.url, true);
|
|
@@ -10545,7 +11119,7 @@ var XhrTransport = class {
|
|
|
10545
11119
|
xhr.onerror = () => {
|
|
10546
11120
|
reject({
|
|
10547
11121
|
type: "unknown",
|
|
10548
|
-
error:
|
|
11122
|
+
error: new Error(t.request.networkError)
|
|
10549
11123
|
});
|
|
10550
11124
|
};
|
|
10551
11125
|
xhr.ontimeout = () => {
|
|
@@ -10796,11 +11370,12 @@ function createUploader(uploaderOptions = {}) {
|
|
|
10796
11370
|
return headers;
|
|
10797
11371
|
}
|
|
10798
11372
|
function doUpload(formData, options) {
|
|
11373
|
+
const t = getActiveLocaleMessages();
|
|
10799
11374
|
const progress = ref(0);
|
|
10800
11375
|
const abortController = new AbortController();
|
|
10801
11376
|
return {
|
|
10802
11377
|
progress,
|
|
10803
|
-
abort: () => abortController.abort(
|
|
11378
|
+
abort: () => abortController.abort(t.request.uploadCanceled),
|
|
10804
11379
|
promise: transport.send({
|
|
10805
11380
|
url: buildURL(options.url),
|
|
10806
11381
|
method: "POST",
|
|
@@ -10821,7 +11396,7 @@ function createUploader(uploaderOptions = {}) {
|
|
|
10821
11396
|
if ((response.headers["content-type"] ?? "").includes("application/json")) {
|
|
10822
11397
|
const json = await response.json();
|
|
10823
11398
|
if (isWrappedResponse(json)) {
|
|
10824
|
-
if (!json.success) throw new BusinessError(json.message ||
|
|
11399
|
+
if (!json.success) throw new BusinessError(json.message || t.request.uploadFailed);
|
|
10825
11400
|
return json.data;
|
|
10826
11401
|
}
|
|
10827
11402
|
return json;
|
|
@@ -11003,22 +11578,10 @@ var KStickyActionBar_default = /* @__PURE__ */ defineComponent({
|
|
|
11003
11578
|
* - approve: 绿色确认按钮
|
|
11004
11579
|
* - reject: 红色确认按钮,备注必填
|
|
11005
11580
|
*/
|
|
11006
|
-
var
|
|
11007
|
-
submit:
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
btnType: "primary"
|
|
11011
|
-
},
|
|
11012
|
-
approve: {
|
|
11013
|
-
title: "审批通过",
|
|
11014
|
-
confirmText: "确认通过",
|
|
11015
|
-
btnType: "success"
|
|
11016
|
-
},
|
|
11017
|
-
reject: {
|
|
11018
|
-
title: "驳回申请",
|
|
11019
|
-
confirmText: "确认驳回",
|
|
11020
|
-
btnType: "danger"
|
|
11021
|
-
}
|
|
11581
|
+
var BTN_TYPE = {
|
|
11582
|
+
submit: "primary",
|
|
11583
|
+
approve: "success",
|
|
11584
|
+
reject: "danger"
|
|
11022
11585
|
};
|
|
11023
11586
|
var KApprovalDialog_default = /* @__PURE__ */ defineComponent({
|
|
11024
11587
|
name: "KApprovalDialog",
|
|
@@ -11062,6 +11625,7 @@ var KApprovalDialog_default = /* @__PURE__ */ defineComponent({
|
|
|
11062
11625
|
"cancel"
|
|
11063
11626
|
],
|
|
11064
11627
|
setup(props, { emit, slots }) {
|
|
11628
|
+
const t = useLocale();
|
|
11065
11629
|
const remark = ref("");
|
|
11066
11630
|
const close = () => {
|
|
11067
11631
|
emit("update:visible", false);
|
|
@@ -11080,9 +11644,19 @@ var KApprovalDialog_default = /* @__PURE__ */ defineComponent({
|
|
|
11080
11644
|
};
|
|
11081
11645
|
return () => {
|
|
11082
11646
|
if (!props.visible) return null;
|
|
11083
|
-
const
|
|
11084
|
-
const
|
|
11085
|
-
|
|
11647
|
+
const ad = t.value.approvalDialog;
|
|
11648
|
+
const titleMap = {
|
|
11649
|
+
submit: ad.submitTitle,
|
|
11650
|
+
approve: ad.approveTitle,
|
|
11651
|
+
reject: ad.rejectTitle
|
|
11652
|
+
};
|
|
11653
|
+
const confirmMap = {
|
|
11654
|
+
submit: ad.submitConfirm,
|
|
11655
|
+
approve: ad.approveConfirm,
|
|
11656
|
+
reject: ad.rejectConfirm
|
|
11657
|
+
};
|
|
11658
|
+
const displayTitle = props.title || titleMap[props.type];
|
|
11659
|
+
const placeholder = props.remarkPlaceholder || (props.type === "reject" ? ad.rejectPlaceholder : ad.remarkPlaceholder);
|
|
11086
11660
|
return createVNode("div", {
|
|
11087
11661
|
"class": "k-approval-overlay",
|
|
11088
11662
|
"onClick": close
|
|
@@ -11108,14 +11682,14 @@ var KApprovalDialog_default = /* @__PURE__ */ defineComponent({
|
|
|
11108
11682
|
remark.value = v;
|
|
11109
11683
|
}
|
|
11110
11684
|
}, null),
|
|
11111
|
-
isRemarkRequired() && createVNode("span", { "class": "k-approval-dialog-required-hint" }, [
|
|
11685
|
+
isRemarkRequired() && createVNode("span", { "class": "k-approval-dialog-required-hint" }, [ad.required])
|
|
11112
11686
|
]),
|
|
11113
11687
|
createVNode("div", { "class": "k-approval-dialog-footer" }, [createVNode(KButton_default, {
|
|
11114
|
-
"text":
|
|
11688
|
+
"text": ad.cancel,
|
|
11115
11689
|
"onClick": close
|
|
11116
11690
|
}, null), createVNode(KButton_default, {
|
|
11117
|
-
"type":
|
|
11118
|
-
"text": props.loading ?
|
|
11691
|
+
"type": BTN_TYPE[props.type],
|
|
11692
|
+
"text": props.loading ? ad.processing : confirmMap[props.type],
|
|
11119
11693
|
"disabled": !canConfirm(),
|
|
11120
11694
|
"loading": props.loading,
|
|
11121
11695
|
"onClick": confirm
|
|
@@ -11177,7 +11751,7 @@ function useFormPage(options) {
|
|
|
11177
11751
|
}
|
|
11178
11752
|
if (field.required) {
|
|
11179
11753
|
if (value === void 0 || value === null || value === "") {
|
|
11180
|
-
const msg =
|
|
11754
|
+
const msg = getActiveLocaleMessages().form.inputPlaceholder(field.label);
|
|
11181
11755
|
errors.value[param] = msg;
|
|
11182
11756
|
return msg;
|
|
11183
11757
|
}
|
|
@@ -11251,6 +11825,7 @@ function useFormPage(options) {
|
|
|
11251
11825
|
* @param slots 组件 slots,用于支持 `field-{param}` 自定义插槽
|
|
11252
11826
|
*/
|
|
11253
11827
|
function renderFormField(field, formData, errors, validateField, slots) {
|
|
11828
|
+
const t = getActiveLocaleMessages();
|
|
11254
11829
|
const customSlot = slots[`field-${field.param}`];
|
|
11255
11830
|
if (customSlot) return customSlot({
|
|
11256
11831
|
formData,
|
|
@@ -11269,7 +11844,7 @@ function renderFormField(field, formData, errors, validateField, slots) {
|
|
|
11269
11844
|
field.disabled && "k-fp-input--disabled"
|
|
11270
11845
|
].filter(Boolean),
|
|
11271
11846
|
"modelValue": val,
|
|
11272
|
-
"placeholder": field.placeholder ??
|
|
11847
|
+
"placeholder": field.placeholder ?? t.form.inputPlaceholder(field.label),
|
|
11273
11848
|
"disabled": field.disabled,
|
|
11274
11849
|
"readonly": field.readonly,
|
|
11275
11850
|
"onUpdate:modelValue": (v) => {
|
|
@@ -11287,7 +11862,7 @@ function renderFormField(field, formData, errors, validateField, slots) {
|
|
|
11287
11862
|
field.disabled && "k-fp-input--disabled"
|
|
11288
11863
|
].filter(Boolean),
|
|
11289
11864
|
"modelValue": val,
|
|
11290
|
-
"placeholder": field.placeholder ??
|
|
11865
|
+
"placeholder": field.placeholder ?? t.form.inputPlaceholder(field.label),
|
|
11291
11866
|
"disabled": field.disabled,
|
|
11292
11867
|
"readonly": field.readonly,
|
|
11293
11868
|
"onUpdate:modelValue": (v) => {
|
|
@@ -11303,7 +11878,7 @@ function renderFormField(field, formData, errors, validateField, slots) {
|
|
|
11303
11878
|
"options": field.options ?? [],
|
|
11304
11879
|
"optionParam": "label",
|
|
11305
11880
|
"valueParam": "value",
|
|
11306
|
-
"placeholder": field.placeholder ??
|
|
11881
|
+
"placeholder": field.placeholder ?? t.form.selectPlaceholder(field.label),
|
|
11307
11882
|
"disabled": field.disabled,
|
|
11308
11883
|
"readonly": field.readonly,
|
|
11309
11884
|
"onUpdate:modelValue": (v) => {
|
|
@@ -11326,7 +11901,7 @@ function renderFormField(field, formData, errors, validateField, slots) {
|
|
|
11326
11901
|
field.disabled && "k-fp-input--disabled"
|
|
11327
11902
|
].filter(Boolean),
|
|
11328
11903
|
"modelValue": val,
|
|
11329
|
-
"placeholder": field.placeholder ??
|
|
11904
|
+
"placeholder": field.placeholder ?? t.form.inputPlaceholder(field.label),
|
|
11330
11905
|
"disabled": field.disabled,
|
|
11331
11906
|
"readonly": field.readonly,
|
|
11332
11907
|
"onUpdate:modelValue": (v) => {
|
|
@@ -11356,6 +11931,7 @@ var KFormPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11356
11931
|
required: true
|
|
11357
11932
|
} },
|
|
11358
11933
|
setup(props, { slots }) {
|
|
11934
|
+
const t = useLocale();
|
|
11359
11935
|
const { formData, isEdit, loading, submitting, errors, validateField, submit, saveDraft, goBack } = useFormPage({
|
|
11360
11936
|
api: props.config.api,
|
|
11361
11937
|
fields: props.config.fields,
|
|
@@ -11364,8 +11940,8 @@ var KFormPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11364
11940
|
});
|
|
11365
11941
|
const cols = props.config.columns ?? 2;
|
|
11366
11942
|
return () => {
|
|
11367
|
-
if (loading.value) return createVNode("div", { "class": "k-fp-loading" }, [
|
|
11368
|
-
const title = isEdit.value ?
|
|
11943
|
+
if (loading.value) return createVNode("div", { "class": "k-fp-loading" }, [t.value.formPage.loading]);
|
|
11944
|
+
const title = isEdit.value ? t.value.formPage.editTitle(props.config.title) : t.value.formPage.createTitle(props.config.title);
|
|
11369
11945
|
return createVNode("div", { "class": "k-form-page-wrapper" }, [createVNode("div", { "class": "k-form-page" }, [
|
|
11370
11946
|
createVNode("div", { "class": "k-fp-header" }, [createVNode("div", { "class": "k-fp-header-left" }, [createVNode(KButton_default, {
|
|
11371
11947
|
"text": "←",
|
|
@@ -11395,17 +11971,17 @@ var KFormPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11395
11971
|
submitting
|
|
11396
11972
|
}) ?? createVNode(Fragment, null, [
|
|
11397
11973
|
createVNode(KButton_default, {
|
|
11398
|
-
"text":
|
|
11974
|
+
"text": t.value.formPage.cancel,
|
|
11399
11975
|
"onClick": goBack
|
|
11400
11976
|
}, null),
|
|
11401
11977
|
props.config.showDraft && createVNode(KButton_default, {
|
|
11402
|
-
"text":
|
|
11978
|
+
"text": t.value.formPage.saveDraft,
|
|
11403
11979
|
"disabled": submitting.value,
|
|
11404
11980
|
"onClick": () => saveDraft()
|
|
11405
11981
|
}, null),
|
|
11406
11982
|
createVNode(KButton_default, {
|
|
11407
11983
|
"type": "primary",
|
|
11408
|
-
"text": submitting.value ?
|
|
11984
|
+
"text": submitting.value ? t.value.formPage.saving : props.config.submitText ?? t.value.formPage.save,
|
|
11409
11985
|
"disabled": submitting.value,
|
|
11410
11986
|
"loading": submitting.value,
|
|
11411
11987
|
"onClick": () => submit()
|
|
@@ -11459,11 +12035,11 @@ var KEditableTable_default = /* @__PURE__ */ defineComponent({
|
|
|
11459
12035
|
},
|
|
11460
12036
|
summaryLabel: {
|
|
11461
12037
|
type: String,
|
|
11462
|
-
default:
|
|
12038
|
+
default: void 0
|
|
11463
12039
|
},
|
|
11464
12040
|
addText: {
|
|
11465
12041
|
type: String,
|
|
11466
|
-
default:
|
|
12042
|
+
default: void 0
|
|
11467
12043
|
},
|
|
11468
12044
|
addable: {
|
|
11469
12045
|
type: Boolean,
|
|
@@ -11480,6 +12056,7 @@ var KEditableTable_default = /* @__PURE__ */ defineComponent({
|
|
|
11480
12056
|
"remove"
|
|
11481
12057
|
],
|
|
11482
12058
|
setup(props, { emit, slots }) {
|
|
12059
|
+
const t = useLocale();
|
|
11483
12060
|
const deletingId = ref(null);
|
|
11484
12061
|
const updateCell = (rowIdx, param, value) => {
|
|
11485
12062
|
const rows = [...props.modelValue];
|
|
@@ -11552,7 +12129,7 @@ var KEditableTable_default = /* @__PURE__ */ defineComponent({
|
|
|
11552
12129
|
return createVNode("div", { "class": "k-editable-table" }, [
|
|
11553
12130
|
(props.title || slots.header) && createVNode("div", { "class": "k-et-header" }, [createVNode("div", { "class": "k-et-header-left" }, [props.title && createVNode("span", { "class": "k-et-title" }, [props.title]), rows.length > 0 && createVNode("span", { "class": "k-et-count" }, [rows.length, createTextVNode(" items")])]), createVNode("div", { "class": "k-et-header-right" }, [slots.headerExtra?.(), props.addable && createVNode(KButton_default, {
|
|
11554
12131
|
"plain": true,
|
|
11555
|
-
"text": props.addText,
|
|
12132
|
+
"text": props.addText ?? t.value.editableTable.addRow,
|
|
11556
12133
|
"onClick": addRow
|
|
11557
12134
|
}, null)])]),
|
|
11558
12135
|
createVNode("table", { "class": "k-et-table" }, [
|
|
@@ -11574,17 +12151,17 @@ var KEditableTable_default = /* @__PURE__ */ defineComponent({
|
|
|
11574
12151
|
"colspan": cols.length + (props.showActions ? 1 : 0)
|
|
11575
12152
|
}, [createVNode("span", { "class": "k-et-delete-confirm" }, [
|
|
11576
12153
|
createVNode("s", { "class": "k-et-deleted-text" }, [row[cols[0].param] ?? ""]),
|
|
11577
|
-
createVNode("span", { "class": "k-et-delete-ask" }, [
|
|
12154
|
+
createVNode("span", { "class": "k-et-delete-ask" }, [t.value.editableTable.confirmDelete]),
|
|
11578
12155
|
createVNode(KButton_default, {
|
|
11579
12156
|
"type": "danger",
|
|
11580
12157
|
"size": "small",
|
|
11581
|
-
"text":
|
|
12158
|
+
"text": t.value.editableTable.delete,
|
|
11582
12159
|
"onClick": confirmDelete
|
|
11583
12160
|
}, null),
|
|
11584
12161
|
createVNode(KButton_default, {
|
|
11585
12162
|
"plain": true,
|
|
11586
12163
|
"size": "small",
|
|
11587
|
-
"text":
|
|
12164
|
+
"text": t.value.editableTable.cancel,
|
|
11588
12165
|
"onClick": cancelDelete
|
|
11589
12166
|
}, null)
|
|
11590
12167
|
])])]);
|
|
@@ -11610,13 +12187,13 @@ var KEditableTable_default = /* @__PURE__ */ defineComponent({
|
|
|
11610
12187
|
cols.map((col, ci) => createVNode("td", {
|
|
11611
12188
|
"key": col.param,
|
|
11612
12189
|
"class": ["k-et-td k-et-td-summary", col.align && `k-et-align-${col.align}`]
|
|
11613
|
-
}, [ci === 0 ? props.summaryLabel : "", col.summary ? createVNode("span", { "class": "k-et-summary-value" }, [props.currencyPrefix && col.summaryFormat === void 0 && ci === cols.length - 1 ? `${props.currencyPrefix} ` : "", getSummary(col)]) : ""])),
|
|
12190
|
+
}, [ci === 0 ? props.summaryLabel ?? t.value.editableTable.summary : "", col.summary ? createVNode("span", { "class": "k-et-summary-value" }, [props.currencyPrefix && col.summaryFormat === void 0 && ci === cols.length - 1 ? `${props.currencyPrefix} ` : "", getSummary(col)]) : ""])),
|
|
11614
12191
|
props.showActions && createVNode("td", { "class": "k-et-td" }, null)
|
|
11615
12192
|
])])
|
|
11616
12193
|
]),
|
|
11617
|
-
isEmpty && createVNode("div", { "class": "k-et-empty" }, [slots.empty?.() ?? createVNode(Fragment, null, [createVNode("span", { "class": "k-et-empty-text" }, [
|
|
12194
|
+
isEmpty && createVNode("div", { "class": "k-et-empty" }, [slots.empty?.() ?? createVNode(Fragment, null, [createVNode("span", { "class": "k-et-empty-text" }, [t.value.editableTable.noData]), props.addable && createVNode(KButton_default, {
|
|
11618
12195
|
"type": "primary",
|
|
11619
|
-
"text":
|
|
12196
|
+
"text": t.value.editableTable.addFirstRow,
|
|
11620
12197
|
"onClick": addRow
|
|
11621
12198
|
}, null)])])
|
|
11622
12199
|
]);
|
|
@@ -11644,6 +12221,7 @@ var KMasterDetailPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11644
12221
|
} },
|
|
11645
12222
|
setup(props, { slots }) {
|
|
11646
12223
|
const router = useRouter();
|
|
12224
|
+
const t = useLocale();
|
|
11647
12225
|
const { formData, isEdit, loading, submitting, errors, validateField, submit, saveDraft, goBack } = useFormPage({
|
|
11648
12226
|
api: props.config.api,
|
|
11649
12227
|
fields: props.config.fields,
|
|
@@ -11670,8 +12248,8 @@ var KMasterDetailPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11670
12248
|
formData[param] = newRows;
|
|
11671
12249
|
};
|
|
11672
12250
|
return () => {
|
|
11673
|
-
if (loading.value) return createVNode("div", { "class": "k-fp-loading" }, [
|
|
11674
|
-
const title = isEdit.value ? `${props.config.title}` :
|
|
12251
|
+
if (loading.value) return createVNode("div", { "class": "k-fp-loading" }, [t.value.formPage.loading]);
|
|
12252
|
+
const title = isEdit.value ? `${props.config.title}` : t.value.formPage.createTitle(props.config.title);
|
|
11675
12253
|
return createVNode("div", { "class": "k-form-page k-master-detail-page" }, [
|
|
11676
12254
|
createVNode("div", { "class": "k-fp-header" }, [createVNode("div", { "class": "k-fp-header-left" }, [props.config.breadcrumb ? createVNode("div", { "class": "k-fp-breadcrumb" }, [props.config.breadcrumb.map((item, i) => createVNode(Fragment, null, [i > 0 && createVNode("span", { "class": "k-fp-breadcrumb-sep" }, [createTextVNode("›")]), item.path ? createVNode("a", {
|
|
11677
12255
|
"class": "k-fp-breadcrumb-link",
|
|
@@ -11680,7 +12258,7 @@ var KMasterDetailPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11680
12258
|
"text": "←",
|
|
11681
12259
|
"onClick": goBack
|
|
11682
12260
|
}, null), createVNode("h1", { "class": "k-fp-title" }, [title])])]), createVNode("div", { "class": "k-fp-header-right" }, [slots.headerExtra?.({ formData })])]),
|
|
11683
|
-
createVNode(KFormCard_default, { "title":
|
|
12261
|
+
createVNode(KFormCard_default, { "title": t.value.formPage.basicInfo }, { default: () => createVNode("div", { "class": `k-fp-grid k-fp-grid--${cols}` }, [props.config.fields.map((field) => {
|
|
11684
12262
|
const span = field.span === "full" ? cols : field.span ?? 1;
|
|
11685
12263
|
return createVNode("div", {
|
|
11686
12264
|
"key": field.param,
|
|
@@ -11718,17 +12296,17 @@ var KMasterDetailPage_default = /* @__PURE__ */ defineComponent({
|
|
|
11718
12296
|
submitting
|
|
11719
12297
|
}) ?? createVNode(Fragment, null, [
|
|
11720
12298
|
createVNode(KButton_default, {
|
|
11721
|
-
"text":
|
|
12299
|
+
"text": t.value.formPage.cancel,
|
|
11722
12300
|
"onClick": goBack
|
|
11723
12301
|
}, null),
|
|
11724
12302
|
props.config.showDraft && createVNode(KButton_default, {
|
|
11725
|
-
"text":
|
|
12303
|
+
"text": t.value.formPage.saveDraft,
|
|
11726
12304
|
"disabled": submitting.value,
|
|
11727
12305
|
"onClick": () => saveDraft()
|
|
11728
12306
|
}, null),
|
|
11729
12307
|
createVNode(KButton_default, {
|
|
11730
12308
|
"type": "primary",
|
|
11731
|
-
"text": submitting.value ?
|
|
12309
|
+
"text": submitting.value ? t.value.formPage.saving : props.config.submitText ?? t.value.formPage.submit,
|
|
11732
12310
|
"disabled": submitting.value,
|
|
11733
12311
|
"loading": submitting.value,
|
|
11734
12312
|
"onClick": () => submit()
|