c-admin-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +232 -0
  2. package/dist/c-admin-kit.css +1 -0
  3. package/dist/c-admin-kit.js +2482 -0
  4. package/dist/c-admin-kit.umd.cjs +10 -0
  5. package/dist/components/AsyncButton/index.vue.d.ts +48 -0
  6. package/dist/components/CollapsibleContainer/index.vue.d.ts +73 -0
  7. package/dist/components/CustomDrawer/index.vue.d.ts +149 -0
  8. package/dist/components/ImagePreview/index.vue.d.ts +34 -0
  9. package/dist/components/SearchBox/index.vue.d.ts +122 -0
  10. package/dist/components/SelectWithAll/index.vue.d.ts +169 -0
  11. package/dist/components/SelectWithPage/index.vue.d.ts +78 -0
  12. package/dist/components/SimpleTable/index.vue.d.ts +337 -0
  13. package/dist/components/SimpleTable/useTableColumnConfig.d.ts +5 -0
  14. package/dist/components/diff/index.vue.d.ts +33 -0
  15. package/dist/components/index.d.ts +12 -0
  16. package/dist/composables/index.d.ts +6 -0
  17. package/dist/composables/useConfirmAction.d.ts +5 -0
  18. package/dist/composables/useConfirmSubmit.d.ts +5 -0
  19. package/dist/composables/useDialog.d.ts +5 -0
  20. package/dist/composables/useDownload.d.ts +5 -0
  21. package/dist/composables/useForm.d.ts +5 -0
  22. package/dist/composables/useListPage.d.ts +5 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/types.d.ts +282 -0
  25. package/dist/utils/index.d.ts +4 -0
  26. package/dist/utils/scroll-to.d.ts +7 -0
  27. package/dist/utils/searchFieldFactory.d.ts +34 -0
  28. package/dist/utils/treeManager.d.ts +64 -0
  29. package/dist/utils/validate.d.ts +30 -0
  30. package/package.json +86 -0
  31. package/src/components/AsyncButton/index.vue +58 -0
  32. package/src/components/CollapsibleContainer/index.vue +240 -0
  33. package/src/components/CustomDrawer/index.vue +167 -0
  34. package/src/components/ImagePreview/index.vue +88 -0
  35. package/src/components/SearchBox/index.vue +582 -0
  36. package/src/components/SelectWithAll/index.vue +281 -0
  37. package/src/components/SelectWithPage/index.vue +204 -0
  38. package/src/components/SimpleTable/index.vue +781 -0
  39. package/src/components/SimpleTable/useTableColumnConfig.ts +139 -0
  40. package/src/components/diff/index.vue +265 -0
  41. package/src/components/index.ts +35 -0
  42. package/src/composables/index.ts +6 -0
  43. package/src/composables/useConfirmAction.ts +62 -0
  44. package/src/composables/useConfirmSubmit.ts +68 -0
  45. package/src/composables/useDialog.ts +48 -0
  46. package/src/composables/useDownload.ts +83 -0
  47. package/src/composables/useForm.ts +114 -0
  48. package/src/composables/useListPage.ts +243 -0
  49. package/src/env.d.ts +7 -0
  50. package/src/index.ts +44 -0
  51. package/src/types.ts +344 -0
  52. package/src/utils/index.ts +4 -0
  53. package/src/utils/scroll-to.ts +60 -0
  54. package/src/utils/searchFieldFactory.ts +302 -0
  55. package/src/utils/treeManager.ts +218 -0
  56. package/src/utils/validate.ts +64 -0
package/src/types.ts ADDED
@@ -0,0 +1,344 @@
1
+ import type { Component, Ref, VNode } from 'vue'
2
+
3
+ // ============================================================
4
+ // 通用基础类型
5
+ // ============================================================
6
+
7
+ /** 通用记录类型 */
8
+ export type AnyRecord = Record<string, any>
9
+
10
+ /** API 函数类型 */
11
+ export type ApiFn<P = AnyRecord, R = any> = (params: P) => Promise<R>
12
+
13
+ /** 路由跳转位置 */
14
+ export interface NavigateLocation {
15
+ path: string
16
+ query?: AnyRecord
17
+ }
18
+
19
+ // ============================================================
20
+ // Table Column 类型
21
+ // ============================================================
22
+
23
+ export interface StatusMapItem {
24
+ text: string
25
+ type: 'success' | 'danger' | 'warning' | 'info' | ''
26
+ }
27
+
28
+ export interface TableColumn {
29
+ /** 列类型 */
30
+ type?: 'selection' | 'index' | 'drag' | 'status'
31
+ /** 字段名 */
32
+ prop?: string
33
+ /** 列标题 */
34
+ label?: string
35
+ /** 列宽 */
36
+ width?: number | string
37
+ /** 最小列宽 */
38
+ minWidth?: number | string
39
+ /** 对齐方式 */
40
+ align?: 'left' | 'center' | 'right'
41
+ /** 固定列 */
42
+ fixed?: boolean | 'left' | 'right'
43
+ /** 是否可排序 */
44
+ sortable?: boolean | 'custom'
45
+ /** 是否显示溢出提示 */
46
+ showOverflowTooltip?: boolean
47
+ /** 插槽名 */
48
+ slot?: string
49
+ /** 头部插槽名 */
50
+ headerSlot?: string
51
+ /** 自定义渲染 */
52
+ render?: (row: AnyRecord, column: AnyRecord, index: number) => VNode
53
+ /** 格式化函数 */
54
+ formatter?: (row: AnyRecord, column: AnyRecord, cellValue: any, index: number) => string
55
+ /** 状态映射 */
56
+ statusMap?: Record<string | number, StatusMapItem>
57
+ /** Tag 效果 */
58
+ effect?: 'dark' | 'light' | 'plain'
59
+ /** Tag 尺寸 */
60
+ size?: 'large' | 'default' | 'small'
61
+ /** 内部标识 key */
62
+ _key?: string
63
+ [key: string]: any
64
+ }
65
+
66
+ // ============================================================
67
+ // Search Field 类型
68
+ // ============================================================
69
+
70
+ export interface SearchFieldBase {
71
+ prop: string
72
+ label: string
73
+ component?: string
74
+ type?: string
75
+ placeholder?: string
76
+ required?: boolean
77
+ visible?: boolean | ((form: AnyRecord) => boolean)
78
+ defaultValue?: any
79
+ multiple?: boolean
80
+ slotName?: string
81
+ props?: AnyRecord
82
+ [key: string]: any
83
+ }
84
+
85
+ export interface DateRangeConfig {
86
+ startField: string
87
+ endField: string
88
+ format: (date: any) => string
89
+ }
90
+
91
+ export interface RelationConfig {
92
+ dependOn: string
93
+ getOptions: ((parentValue: any, form?: AnyRecord) => any[] | Promise<any[]>) | Record<string, any[]>
94
+ }
95
+
96
+ export interface SearchField extends SearchFieldBase {
97
+ options?: Array<{ label: string; value: any; disabled?: boolean }>
98
+ dateRange?: DateRangeConfig
99
+ relation?: RelationConfig
100
+ defaultOptions?: Array<{ label: string; value: any }>
101
+ returnAllIds?: boolean
102
+ fileIds?: string[]
103
+ }
104
+
105
+ // ============================================================
106
+ // useListPage 类型
107
+ // ============================================================
108
+
109
+ export interface UseListPageOptions {
110
+ apiList?: ApiFn
111
+ apiChangeState?: ApiFn
112
+ apiDelete?: ApiFn & { batch?: ApiFn<{ ids: any[] }> }
113
+ apiBatchDelete?: ApiFn
114
+ apiExport?: ApiFn
115
+ addPath?: string
116
+ editPath?: string
117
+ navigate?: (location: NavigateLocation) => void
118
+ exportFileName?: string
119
+ stateKey?: string
120
+ idKey?: string
121
+ activeValue?: any
122
+ inactiveValue?: any
123
+ statusMap?: Record<string | number, string>
124
+ deleteConfirmText?: string
125
+ deleteSuccessText?: string
126
+ deleteErrorText?: string
127
+ openDialog?: (data?: any) => void
128
+ }
129
+
130
+ export interface UseListPageReturn {
131
+ tableRef: Ref<any>
132
+ searchParams: Ref<AnyRecord>
133
+ handleSearch: (params?: AnyRecord) => void
134
+ handleReset: () => void
135
+ changeState: (row: AnyRecord, callback?: (row: AnyRecord) => void) => Promise<void>
136
+ handleDelete: (row: AnyRecord, callback?: (row: AnyRecord) => void) => Promise<void>
137
+ handleBatchDelete: (rows: AnyRecord[], callback?: (rows: AnyRecord[]) => void) => Promise<void>
138
+ handleDialog: (data?: any) => void
139
+ exportExcel: () => Promise<void>
140
+ handleAdd: (query?: AnyRecord) => void
141
+ handleEdit: (row: AnyRecord, query?: AnyRecord) => void
142
+ handleView: (row: AnyRecord, detailPath: string, query?: AnyRecord) => void
143
+ refresh: () => void
144
+ apiList?: ApiFn
145
+ }
146
+
147
+ // ============================================================
148
+ // useForm 类型
149
+ // ============================================================
150
+
151
+ export interface UseFormOptions<T extends AnyRecord = AnyRecord> {
152
+ initFormData?: T | (() => T)
153
+ rules?: AnyRecord
154
+ onSuccess?: (result: any) => void
155
+ onError?: (error: any) => void
156
+ transform?: (formData: T) => any
157
+ }
158
+
159
+ export interface UseFormReturn<T extends AnyRecord = AnyRecord> {
160
+ formRef: Ref<any>
161
+ formData: T
162
+ loading: Ref<boolean>
163
+ rules: AnyRecord
164
+ submit: (
165
+ apiCall: ApiFn,
166
+ successMessage?: string,
167
+ customTransform?: (formData: T) => any,
168
+ skipValidate?: boolean,
169
+ ) => Promise<any>
170
+ validate: () => Promise<boolean>
171
+ validateField: (field: string, callback?: (...args: any[]) => void) => void
172
+ reset: () => void
173
+ clearValidate: (props?: string | string[]) => void
174
+ setFormData: (data: Partial<T>) => void
175
+ resetFormData: () => void
176
+ }
177
+
178
+ // ============================================================
179
+ // useConfirmAction 类型
180
+ // ============================================================
181
+
182
+ export type ConfirmType = 'success' | 'warning' | 'info' | 'error'
183
+
184
+ export interface UseConfirmActionOptions {
185
+ onSuccess?: (result: any) => void
186
+ onError?: (error: any) => void
187
+ confirmTitle?: string
188
+ confirmButtonText?: string
189
+ cancelButtonText?: string
190
+ confirmType?: ConfirmType
191
+ }
192
+
193
+ export interface UseConfirmActionReturn {
194
+ execute: (params: AnyRecord) => Promise<any>
195
+ loading: Ref<boolean>
196
+ }
197
+
198
+ // ============================================================
199
+ // useConfirmSubmit 类型
200
+ // ============================================================
201
+
202
+ export interface UseConfirmSubmitOptions {
203
+ title?: string
204
+ message?: string
205
+ confirmButtonText?: string
206
+ cancelButtonText?: string
207
+ type?: ConfirmType
208
+ successMessage?: string
209
+ cancelMessage?: string
210
+ errorMessage?: string
211
+ showCancelMessage?: boolean
212
+ messageBoxOptions?: AnyRecord
213
+ }
214
+
215
+ // ============================================================
216
+ // useDownload 类型
217
+ // ============================================================
218
+
219
+ export interface UseDownloadOptions {
220
+ filename?: string
221
+ fileExtension?: string
222
+ mimeType?: string
223
+ timeout?: number
224
+ loadingMessage?: string
225
+ successMessage?: string
226
+ }
227
+
228
+ export interface UseDownloadReturn {
229
+ downloading: Ref<boolean>
230
+ download: (params?: AnyRecord) => Promise<void>
231
+ }
232
+
233
+ // ============================================================
234
+ // useDialog 类型
235
+ // ============================================================
236
+
237
+ export interface UseDialogOptions {
238
+ width?: string
239
+ title?: string
240
+ beforeClose?: (done: () => void) => void
241
+ }
242
+
243
+ export interface UseDialogReturn {
244
+ visible: Ref<boolean>
245
+ dialogTitle: Ref<string>
246
+ dialogData: AnyRecord
247
+ width: string
248
+ open: (data?: AnyRecord, customTitle?: string) => void
249
+ close: () => void
250
+ handleClose: (done: () => void) => void
251
+ }
252
+
253
+ // ============================================================
254
+ // useTableColumnConfig 类型
255
+ // ============================================================
256
+
257
+ export interface TableColumnConfigProps {
258
+ columns?: TableColumn[]
259
+ tableKey?: string
260
+ getColumnConfigApi?: ApiFn | null
261
+ saveColumnConfigApi?: ApiFn | null
262
+ }
263
+
264
+ export interface UseTableColumnConfigReturn {
265
+ computedColumns: import('vue').ComputedRef<TableColumn[]>
266
+ settingColumns: import('vue').ComputedRef<TableColumn[]>
267
+ visibleColKeys: Ref<string[]>
268
+ tempVisibleColKeys: Ref<string[]>
269
+ popoverRef: Ref<any>
270
+ savingColumns: Ref<boolean>
271
+ initTableConfig: () => Promise<void>
272
+ handlePopoverShow: () => void
273
+ handleCancelSettings: () => void
274
+ handleConfirmSettings: () => Promise<void>
275
+ }
276
+
277
+ // ============================================================
278
+ // SearchFieldFactory 类型
279
+ // ============================================================
280
+
281
+ export interface DateRangeFieldConfig {
282
+ prop?: string
283
+ label?: string
284
+ startField?: string
285
+ endField?: string
286
+ format?: string
287
+ props?: AnyRecord
288
+ [key: string]: any
289
+ }
290
+
291
+ export interface InputFieldConfig {
292
+ prop: string
293
+ label: string
294
+ placeholder?: string
295
+ maxlength?: number
296
+ props?: AnyRecord
297
+ [key: string]: any
298
+ }
299
+
300
+ export interface SelectFieldConfig {
301
+ prop: string
302
+ label: string
303
+ options?: Array<{ label: string; value: any }>
304
+ multiple?: boolean
305
+ props?: AnyRecord
306
+ [key: string]: any
307
+ }
308
+
309
+ export interface CascadeSelectFieldConfig extends SelectFieldConfig {
310
+ dependOn: string
311
+ getOptions: (parentValue: any) => Promise<any[]>
312
+ defaultOptions?: Array<{ label: string; value: any }>
313
+ }
314
+
315
+ export interface CascaderFieldConfig {
316
+ prop: string
317
+ label: string
318
+ options?: any[]
319
+ labelKey?: string
320
+ valueKey?: string
321
+ checkStrictly?: boolean
322
+ returnAllIds?: boolean
323
+ props?: AnyRecord
324
+ [key: string]: any
325
+ }
326
+
327
+ export interface NumberFieldConfig {
328
+ prop: string
329
+ label: string
330
+ min?: number
331
+ max?: number
332
+ step?: number
333
+ props?: AnyRecord
334
+ [key: string]: any
335
+ }
336
+
337
+ export interface SwitchFieldConfig {
338
+ prop: string
339
+ label: string
340
+ activeValue?: any
341
+ inactiveValue?: any
342
+ props?: AnyRecord
343
+ [key: string]: any
344
+ }
@@ -0,0 +1,4 @@
1
+ export * from './searchFieldFactory'
2
+ export * from './validate'
3
+ export * from './scroll-to'
4
+ export * from './treeManager'
@@ -0,0 +1,60 @@
1
+ /**
2
+ * 缓动平滑滚动函数
3
+ */
4
+ function easeInOutQuad(t: number, b: number, c: number, d: number): number {
5
+ t /= d / 2
6
+ if (t < 1) {
7
+ return c / 2 * t * t + b
8
+ }
9
+ t--
10
+ return -c / 2 * (t * (t - 2) - 1) + b
11
+ }
12
+
13
+ const requestAnimFrame = (function() {
14
+ if (typeof window === 'undefined') return (_cb: FrameRequestCallback) => 0
15
+ return window.requestAnimationFrame ||
16
+ (window as any).webkitRequestAnimationFrame ||
17
+ (window as any).mozRequestAnimationFrame ||
18
+ function(callback: FrameRequestCallback) { return window.setTimeout(callback, 1000 / 60) }
19
+ })()
20
+
21
+ function move(amount: number): void {
22
+ if (typeof document === 'undefined') return
23
+ document.documentElement.scrollTop = amount
24
+ if (document.body.parentNode) {
25
+ ;(document.body.parentNode as HTMLElement).scrollTop = amount
26
+ }
27
+ document.body.scrollTop = amount
28
+ }
29
+
30
+ function position(): number {
31
+ if (typeof document === 'undefined') return 0
32
+ return document.documentElement.scrollTop || ((document.body.parentNode as HTMLElement)?.scrollTop) || document.body.scrollTop || 0
33
+ }
34
+
35
+ /**
36
+ * 平滑滚动到指定位置
37
+ * @param to 目标位置
38
+ * @param duration 滚动时长(ms)
39
+ * @param callback 完成回调
40
+ */
41
+ export function scrollTo(to: number, duration: number = 500, callback?: () => void): void {
42
+ const start = position()
43
+ const change = to - start
44
+ const increment = 20
45
+ let currentTime = 0
46
+
47
+ const animateScroll = function() {
48
+ currentTime += increment
49
+ const val = easeInOutQuad(currentTime, start, change, duration)
50
+ move(val)
51
+ if (currentTime < duration) {
52
+ requestAnimFrame(animateScroll)
53
+ } else {
54
+ if (typeof callback === 'function') {
55
+ callback()
56
+ }
57
+ }
58
+ }
59
+ animateScroll()
60
+ }
@@ -0,0 +1,302 @@
1
+ /**
2
+ * 搜索字段配置工厂函数
3
+ * 配合 CSearchBox 使用,用于快速生成规范的表单字段配置
4
+ */
5
+ import dayjs from "dayjs"
6
+ import type {
7
+ AnyRecord,
8
+ DateRangeFieldConfig,
9
+ InputFieldConfig,
10
+ SelectFieldConfig,
11
+ CascadeSelectFieldConfig,
12
+ CascaderFieldConfig,
13
+ NumberFieldConfig,
14
+ SwitchFieldConfig,
15
+ } from '../types'
16
+
17
+ /**
18
+ * 通用标准日期格式常量
19
+ */
20
+ export const DATE_FORMAT = {
21
+ DATE: "YYYY-MM-DD",
22
+ DATETIME: "YYYY-MM-DD HH:mm:ss",
23
+ TIME: "HH:mm:ss",
24
+ MONTH: "YYYY-MM",
25
+ YEAR: "YYYY",
26
+ DATE_CN: "YYYY年MM月DD日",
27
+ DATETIME_CN: "YYYY年MM月DD日 HH:mm:ss",
28
+ } as const
29
+
30
+ // 通用基础字段创建函数:自动透传所有剩余参数
31
+ const createField = (baseConfig: AnyRecord, config: AnyRecord = {}): AnyRecord => {
32
+ const { ...extra } = config
33
+ return {
34
+ ...baseConfig,
35
+ ...extra,
36
+ }
37
+ }
38
+
39
+ export const SearchFieldFactory = {
40
+ dateRange(config: DateRangeFieldConfig = {} as DateRangeFieldConfig): AnyRecord {
41
+ const {
42
+ prop = "updateTime",
43
+ label = "更新时间",
44
+ startField = "updateStartTime",
45
+ endField = "updateEndTime",
46
+ format = DATE_FORMAT.DATETIME,
47
+ props = {},
48
+ } = config
49
+
50
+ const base: AnyRecord = {
51
+ prop,
52
+ label,
53
+ component: "el-date-picker",
54
+ dateRange: {
55
+ startField,
56
+ endField,
57
+ format: (date: any) => (date ? dayjs(date).format(format) : ""),
58
+ },
59
+ props: {
60
+ type: "datetimerange",
61
+ rangeSeparator: "至",
62
+ startPlaceholder: "开始日期",
63
+ endPlaceholder: "结束日期",
64
+ valueFormat: DATE_FORMAT.DATETIME,
65
+ clearable: true,
66
+ defaultTime: [
67
+ new Date(2000, 1, 1, 0, 0, 0),
68
+ new Date(2000, 1, 1, 23, 59, 59),
69
+ ],
70
+ ...props,
71
+ },
72
+ }
73
+
74
+ return createField(base, config)
75
+ },
76
+
77
+ input(config: InputFieldConfig = {} as InputFieldConfig): AnyRecord | null {
78
+ const { prop, label, placeholder, maxlength, props = {} } = config
79
+
80
+ if (!prop || !label) {
81
+ console.error("input 字段配置缺少必填参数 prop 或 label:", config)
82
+ return null
83
+ }
84
+
85
+ const base: AnyRecord = {
86
+ label,
87
+ prop,
88
+ component: "el-input",
89
+ props: {
90
+ placeholder: placeholder || `请输入${label}`,
91
+ clearable: true,
92
+ maxlength,
93
+ showWordLimit: !!maxlength,
94
+ ...props,
95
+ },
96
+ }
97
+
98
+ return createField(base, config)
99
+ },
100
+
101
+ select(config: SelectFieldConfig = {} as SelectFieldConfig): AnyRecord | null {
102
+ const { prop, label, options = [], multiple = false, props = {} } = config
103
+
104
+ if (!prop || !label) {
105
+ console.error("select 字段配置缺少必填参数 prop 或 label:", config)
106
+ return null
107
+ }
108
+
109
+ const base: AnyRecord = {
110
+ label,
111
+ prop,
112
+ component: "el-select",
113
+ options,
114
+ props: {
115
+ placeholder: `请选择${label}`,
116
+ clearable: true,
117
+ multiple,
118
+ collapseTags: multiple,
119
+ collapseTagsTooltip: multiple,
120
+ filterable: true,
121
+ ...props,
122
+ },
123
+ }
124
+
125
+ return createField(base, config)
126
+ },
127
+
128
+ cascadeSelect(config: CascadeSelectFieldConfig = {} as CascadeSelectFieldConfig): AnyRecord | null {
129
+ const {
130
+ prop,
131
+ label,
132
+ dependOn,
133
+ getOptions,
134
+ defaultOptions = [],
135
+ multiple = false,
136
+ props = {},
137
+ } = config
138
+
139
+ if (!prop || !label || !dependOn || !getOptions) {
140
+ console.error("cascadeSelect 配置不完整:", config)
141
+ return null
142
+ }
143
+
144
+ const base: AnyRecord = {
145
+ label,
146
+ prop,
147
+ component: "el-select",
148
+ options: [],
149
+ relation: { dependOn, getOptions },
150
+ defaultOptions,
151
+ props: {
152
+ placeholder: `请选择${label}`,
153
+ clearable: true,
154
+ multiple,
155
+ collapseTags: multiple,
156
+ collapseTagsTooltip: multiple,
157
+ ...props,
158
+ },
159
+ }
160
+
161
+ return createField(base, config)
162
+ },
163
+
164
+ cascader(config: CascaderFieldConfig = {} as CascaderFieldConfig): AnyRecord | null {
165
+ const {
166
+ prop,
167
+ label,
168
+ options = [],
169
+ labelKey = "name",
170
+ valueKey = "id",
171
+ checkStrictly = true,
172
+ returnAllIds = true,
173
+ props = {},
174
+ } = config
175
+
176
+ if (!prop || !label) {
177
+ console.error("cascader 字段配置缺少必填参数 prop 或 label:", config)
178
+ return null
179
+ }
180
+
181
+ const base: AnyRecord = {
182
+ label,
183
+ prop,
184
+ component: "el-cascader",
185
+ returnAllIds,
186
+ props: {
187
+ options,
188
+ placeholder: `请选择${label}`,
189
+ clearable: true,
190
+ props: {
191
+ label: labelKey,
192
+ value: valueKey,
193
+ children: "children",
194
+ checkStrictly,
195
+ },
196
+ ...props,
197
+ },
198
+ }
199
+
200
+ return createField(base, config)
201
+ },
202
+
203
+ number(config: NumberFieldConfig = {} as NumberFieldConfig): AnyRecord | null {
204
+ const { prop, label, min, max, step = 1, props = {} } = config
205
+
206
+ if (!prop || !label) {
207
+ console.error("number 字段配置缺少必填参数 prop 或 label:", config)
208
+ return null
209
+ }
210
+
211
+ const base: AnyRecord = {
212
+ label,
213
+ prop,
214
+ component: "el-input-number",
215
+ props: {
216
+ placeholder: `请输入${label}`,
217
+ min,
218
+ max,
219
+ step,
220
+ controlsPosition: "right",
221
+ style: { width: "100%" },
222
+ ...props,
223
+ },
224
+ }
225
+
226
+ return createField(base, config)
227
+ },
228
+
229
+ date(config: AnyRecord = {}): AnyRecord | null {
230
+ const { prop, label, format = DATE_FORMAT.DATE, props = {} } = config
231
+
232
+ if (!prop || !label) {
233
+ console.error("date 字段配置缺少必填参数 prop 或 label:", config)
234
+ return null
235
+ }
236
+
237
+ const base: AnyRecord = {
238
+ prop,
239
+ label,
240
+ component: "el-date-picker",
241
+ props: {
242
+ type: "date",
243
+ placeholder: `请选择${label}`,
244
+ valueFormat: format,
245
+ clearable: true,
246
+ ...props,
247
+ },
248
+ }
249
+
250
+ return createField(base, config)
251
+ },
252
+
253
+ switch(config: SwitchFieldConfig = {} as SwitchFieldConfig): AnyRecord | null {
254
+ const {
255
+ prop,
256
+ label,
257
+ activeValue = 1,
258
+ inactiveValue = 0,
259
+ props = {},
260
+ } = config
261
+
262
+ if (!prop || !label) {
263
+ console.error("switch 字段配置缺少必填参数 prop 或 label:", config)
264
+ return null
265
+ }
266
+
267
+ const base: AnyRecord = {
268
+ label,
269
+ prop,
270
+ component: "el-switch",
271
+ props: {
272
+ activeValue,
273
+ inactiveValue,
274
+ ...props,
275
+ },
276
+ }
277
+
278
+ return createField(base, config)
279
+ },
280
+ }
281
+
282
+ // 常见预设字段快捷方式
283
+ export const CommonSearchFields = {
284
+ updateTimeRange(config: DateRangeFieldConfig = {} as DateRangeFieldConfig) {
285
+ return SearchFieldFactory.dateRange({ ...config })
286
+ },
287
+ createTimeRange(config: Partial<DateRangeFieldConfig> = {}) {
288
+ return SearchFieldFactory.dateRange(Object.assign({ prop: "createTime", label: "创建时间" }, config) as DateRangeFieldConfig)
289
+ },
290
+ status(options: Array<{ label: string; value: any }>, config: Partial<SelectFieldConfig> = {}) {
291
+ return SearchFieldFactory.select(Object.assign({ prop: "state", label: "状态" }, config, { options }) as SelectFieldConfig)
292
+ },
293
+ keyword(config: Partial<InputFieldConfig> = {}) {
294
+ return SearchFieldFactory.input(Object.assign({ prop: "keyword", label: "关键词" }, config) as InputFieldConfig)
295
+ },
296
+ name(config: Partial<InputFieldConfig> = {}) {
297
+ return SearchFieldFactory.input(Object.assign({ prop: "name", label: "名称" }, config) as InputFieldConfig)
298
+ },
299
+ category(options: any[], config: Partial<CascaderFieldConfig> = {}) {
300
+ return SearchFieldFactory.cascader(Object.assign({ prop: "categoryId", label: "目录" }, config, { options }) as CascaderFieldConfig)
301
+ },
302
+ }