From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/hooks/web/useCrudSchemas.ts | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 326 insertions(+), 0 deletions(-)
diff --git a/src/hooks/web/useCrudSchemas.ts b/src/hooks/web/useCrudSchemas.ts
new file mode 100644
index 0000000..458b57e
--- /dev/null
+++ b/src/hooks/web/useCrudSchemas.ts
@@ -0,0 +1,326 @@
+import { reactive } from 'vue'
+import { AxiosPromise } from 'axios'
+import { findIndex } from '@/utils'
+import { eachTree, filter, treeMap } from '@/utils/tree'
+import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict'
+
+import { FormSchema } from '@/types/form'
+import { TableColumn } from '@/types/table'
+import { DescriptionsSchema } from '@/types/descriptions'
+import { ComponentOptions, ComponentProps } from '@/types/components'
+import { DictTag } from '@/components/DictTag'
+import { cloneDeep, merge } from 'lodash-es'
+
+export type CrudSchema = Omit<TableColumn, 'children'> & {
+ isSearch?: boolean // 鏄惁鍦ㄦ煡璇㈡樉绀�
+ search?: CrudSearchParams // 鏌ヨ鐨勮缁嗛厤缃�
+ isTable?: boolean // 鏄惁鍦ㄥ垪琛ㄦ樉绀�
+ table?: CrudTableParams // 鍒楄〃鐨勮缁嗛厤缃�
+ isForm?: boolean // 鏄惁鍦ㄨ〃鍗曟樉绀�
+ form?: CrudFormParams // 琛ㄥ崟鐨勮缁嗛厤缃�
+ isDetail?: boolean // 鏄惁鍦ㄨ鎯呮樉绀�
+ detail?: CrudDescriptionsParams // 璇︽儏鐨勮缁嗛厤缃�
+ children?: CrudSchema[]
+ dictType?: string // 瀛楀吀绫诲瀷
+ dictClass?: 'string' | 'number' | 'boolean' // 瀛楀吀鏁版嵁绫诲瀷 string | number | boolean
+}
+
+type CrudSearchParams = {
+ // 鏄惁鏄剧ず鍦ㄦ煡璇㈤」
+ show?: boolean
+ // 鎺ュ彛
+ api?: () => Promise<any>
+ // 鎼滅储瀛楁
+ field?: string
+} & Omit<FormSchema, 'field'>
+
+type CrudTableParams = {
+ // 鏄惁鏄剧ず琛ㄥご
+ show?: boolean
+ // 鍒楀閰嶇疆
+ width?: number | string
+ // 鍒楁槸鍚﹀浐瀹氬湪宸︿晶鎴栬�呭彸渚�
+ fixed?: 'left' | 'right'
+} & Omit<FormSchema, 'field'>
+type CrudFormParams = {
+ // 鏄惁鏄剧ず琛ㄥ崟椤�
+ show?: boolean
+ // 鎺ュ彛
+ api?: () => Promise<any>
+} & Omit<FormSchema, 'field'>
+
+type CrudDescriptionsParams = {
+ // 鏄惁鏄剧ず琛ㄥ崟椤�
+ show?: boolean
+} & Omit<DescriptionsSchema, 'field'>
+
+interface AllSchemas {
+ searchSchema: FormSchema[]
+ tableColumns: TableColumn[]
+ formSchema: FormSchema[]
+ detailSchema: DescriptionsSchema[]
+}
+
+const { t } = useI18n()
+
+// 杩囨护鎵�鏈夌粨鏋�
+export const useCrudSchemas = (
+ crudSchema: CrudSchema[]
+): {
+ allSchemas: AllSchemas
+} => {
+ // 鎵�鏈夌粨鏋勬暟鎹�
+ const allSchemas = reactive<AllSchemas>({
+ searchSchema: [],
+ tableColumns: [],
+ formSchema: [],
+ detailSchema: []
+ })
+
+ const searchSchema = filterSearchSchema(crudSchema, allSchemas)
+ allSchemas.searchSchema = searchSchema || []
+
+ const tableColumns = filterTableSchema(crudSchema)
+ allSchemas.tableColumns = tableColumns || []
+
+ const formSchema = filterFormSchema(crudSchema, allSchemas)
+ allSchemas.formSchema = formSchema
+
+ const detailSchema = filterDescriptionsSchema(crudSchema)
+ allSchemas.detailSchema = detailSchema
+
+ return {
+ allSchemas
+ }
+}
+
+// 杩囨护 Search 缁撴瀯
+const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
+ const searchSchema: FormSchema[] = []
+
+ // 鑾峰彇瀛楀吀鍒楄〃闃熷垪
+ const searchRequestTask: Array<() => Promise<void>> = []
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 鍒ゆ柇鏄惁鏄剧ず
+ if (schemaItem?.isSearch || schemaItem.search?.show) {
+ let component = schemaItem?.search?.component || 'Input'
+ const options: ComponentOptions[] = []
+ let comonentProps: ComponentProps = {}
+ if (schemaItem.dictType) {
+ const allOptions: ComponentOptions = { label: '鍏ㄩ儴', value: '' }
+ options.push(allOptions)
+ getDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ comonentProps = {
+ options: options
+ }
+ if (!schemaItem.search?.component) component = 'Select'
+ }
+
+ // updated by AKing: 瑙e喅浜嗗綋浣跨敤榛樿鐨刣ict閫夐」鏃讹紝form涓簨浠朵笉鑳借Е鍙戠殑闂
+ const searchSchemaItem = merge(
+ {
+ // 榛樿涓� input
+ component,
+ ...schemaItem.search,
+ field: schemaItem.field,
+ label: schemaItem.search?.label || schemaItem.label
+ },
+ { componentProps: comonentProps }
+ )
+ if (searchSchemaItem.api) {
+ searchRequestTask.push(async () => {
+ const res = await (searchSchemaItem.api as () => AxiosPromise)()
+ if (res) {
+ const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => {
+ return v.field === searchSchemaItem.field
+ })
+ if (index !== -1) {
+ allSchemas.searchSchema[index]!.componentProps!.options = filterOptions(
+ res,
+ searchSchemaItem.componentProps.optionsAlias?.labelField
+ )
+ }
+ }
+ })
+ }
+ // 鍒犻櫎涓嶅繀瑕佺殑瀛楁
+ delete searchSchemaItem.show
+
+ searchSchema.push(searchSchemaItem)
+ }
+ })
+ for (const task of searchRequestTask) {
+ task()
+ }
+ return searchSchema
+}
+
+// 杩囨护 table 缁撴瀯
+const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => {
+ const tableColumns = treeMap<CrudSchema>(crudSchema, {
+ conversion: (schema: CrudSchema) => {
+ if (schema?.isTable !== false && schema?.table?.show !== false) {
+ // add by 鑺嬭壙锛氬鍔犲 dict 瀛楀吀鏁版嵁鐨勬敮鎸�
+ if (!schema.formatter && schema.dictType) {
+ schema.formatter = (_: Recordable, __: TableColumn, cellValue: any) => {
+ return h(DictTag, {
+ type: schema.dictType!, // ! 琛ㄧず涓�瀹氫笉涓虹┖
+ value: cellValue
+ })
+ }
+ }
+ return {
+ ...schema.table,
+ ...schema
+ }
+ }
+ }
+ })
+
+ // 绗竴娆¤繃婊や細鏈� undefined 鎵�浠ラ渶瑕佷簩娆¤繃婊�
+ return filter<TableColumn>(tableColumns as TableColumn[], (data) => {
+ if (data.children === void 0) {
+ delete data.children
+ }
+ return !!data.field
+ })
+}
+
+// 杩囨护 form 缁撴瀯
+const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
+ const formSchema: FormSchema[] = []
+
+ // 鑾峰彇瀛楀吀鍒楄〃闃熷垪
+ const formRequestTask: Array<() => Promise<void>> = []
+
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 鍒ゆ柇鏄惁鏄剧ず
+ if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) {
+ let component = schemaItem?.form?.component || 'Input'
+ let defaultValue: any = ''
+ if (schemaItem.form?.value) {
+ defaultValue = schemaItem.form?.value
+ } else {
+ if (component === 'InputNumber') {
+ defaultValue = 0
+ }
+ }
+ let comonentProps: ComponentProps = {}
+ if (schemaItem.dictType) {
+ const options: ComponentOptions[] = []
+ if (schemaItem.dictClass && schemaItem.dictClass === 'number') {
+ getIntDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ } else if (schemaItem.dictClass && schemaItem.dictClass === 'boolean') {
+ getBoolDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ } else {
+ getDictOptions(schemaItem.dictType).forEach((dict) => {
+ options.push(dict)
+ })
+ }
+ comonentProps = {
+ options: options
+ }
+ if (!(schemaItem.form && schemaItem.form.component)) component = 'Select'
+ }
+
+ // updated by AKing: 瑙e喅浜嗗綋浣跨敤榛樿鐨刣ict閫夐」鏃讹紝form涓簨浠朵笉鑳借Е鍙戠殑闂
+ const formSchemaItem = merge(
+ {
+ // 榛樿涓� input
+ component,
+ value: defaultValue,
+ ...schemaItem.form,
+ field: schemaItem.field,
+ label: schemaItem.form?.label || schemaItem.label
+ },
+ { componentProps: comonentProps }
+ )
+
+ if (formSchemaItem.api) {
+ formRequestTask.push(async () => {
+ const res = await (formSchemaItem.api as () => AxiosPromise)()
+ if (res) {
+ const index = findIndex(allSchemas.formSchema, (v: FormSchema) => {
+ return v.field === formSchemaItem.field
+ })
+ if (index !== -1) {
+ allSchemas.formSchema[index]!.componentProps!.options = filterOptions(
+ res,
+ formSchemaItem.componentProps.optionsAlias?.labelField
+ )
+ }
+ }
+ })
+ }
+
+ // 鍒犻櫎涓嶅繀瑕佺殑瀛楁
+ delete formSchemaItem.show
+
+ formSchema.push(formSchemaItem)
+ }
+ })
+
+ for (const task of formRequestTask) {
+ task()
+ }
+ return formSchema
+}
+
+// 杩囨护 descriptions 缁撴瀯
+const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => {
+ const descriptionsSchema: FormSchema[] = []
+
+ eachTree(crudSchema, (schemaItem: CrudSchema) => {
+ // 鍒ゆ柇鏄惁鏄剧ず
+ if (schemaItem?.isDetail !== false && schemaItem.detail?.show !== false) {
+ const descriptionsSchemaItem = {
+ ...schemaItem.detail,
+ field: schemaItem.field,
+ label: schemaItem.detail?.label || schemaItem.label
+ }
+ if (schemaItem.dictType) {
+ descriptionsSchemaItem.dictType = schemaItem.dictType
+ }
+ if (schemaItem.detail?.dateFormat || schemaItem.formatter == 'formatDate') {
+ // 浼樺厛浣跨敤 detail 涓嬬殑閰嶇疆锛屽鏋滄病鏈夐粯璁や负 YYYY-MM-DD HH:mm:ss
+ descriptionsSchemaItem.dateFormat = schemaItem?.detail?.dateFormat
+ ? schemaItem?.detail?.dateFormat
+ : 'YYYY-MM-DD HH:mm:ss'
+ }
+
+ // 鍒犻櫎涓嶅繀瑕佺殑瀛楁
+ delete descriptionsSchemaItem.show
+
+ descriptionsSchema.push(descriptionsSchemaItem)
+ }
+ })
+
+ return descriptionsSchema
+}
+
+// 缁檕ptions娣诲姞鍥介檯鍖�
+const filterOptions = (options: Recordable, labelField?: string) => {
+ return options?.map((v: Recordable) => {
+ if (labelField) {
+ v['labelField'] = t(v.labelField)
+ } else {
+ v['label'] = t(v.label)
+ }
+ return v
+ })
+}
+
+// 灏� tableColumns 鎸囧畾 fields 鏀惧埌鏈�鍓嶉潰
+export const sortTableColumns = (tableColumns: TableColumn[], field: string) => {
+ const fieldIndex = tableColumns.findIndex((item) => item.field === field)
+ const fieldColumn = cloneDeep(tableColumns[fieldIndex])
+ tableColumns.splice(fieldIndex, 1)
+ // 娣诲姞鍒板紑澶�
+ tableColumns.unshift(fieldColumn)
+}
--
Gitblit v1.8.0