github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/hooks/web/useCrudSchemas.ts (about) 1 import { reactive } from 'vue' 2 import { eachTree, treeMap, filter } from '@/utils/tree' 3 import { findIndex } from '@/utils' 4 import { useDictStoreWithOut } from '@/store/modules/dict' 5 import { useI18n } from '@/hooks/web/useI18n' 6 import type { AxiosPromise } from 'axios' 7 import { FormSchema } from '@/types/form' 8 import { TableColumn } from '@/types/table' 9 import { DescriptionsSchema } from '@/types/descriptions' 10 11 export type CrudSchema = Omit<TableColumn, 'children'> & { 12 search?: CrudSearchParams 13 table?: CrudTableParams 14 form?: CrudFormParams 15 detail?: CrudDescriptionsParams 16 children?: CrudSchema[] 17 } 18 19 type CrudSearchParams = { 20 // 是否显示在查询项 21 show?: boolean 22 // 字典名称,会去取全局的字典 23 dictName?: string 24 // 接口 25 api?: () => Promise<any> 26 // 搜索字段 27 field?: string 28 } & Omit<FormSchema, 'field'> 29 30 type CrudTableParams = { 31 // 是否显示表头 32 show?: boolean 33 } & Omit<FormSchema, 'field'> 34 35 type CrudFormParams = { 36 // 字典名称,会去取全局的字典 37 dictName?: string 38 // 接口 39 api?: () => Promise<any> 40 // 是否显示表单项 41 show?: boolean 42 } & Omit<FormSchema, 'field'> 43 44 type CrudDescriptionsParams = { 45 // 是否显示表单项 46 show?: boolean 47 } & Omit<DescriptionsSchema, 'field'> 48 49 const dictStore = useDictStoreWithOut() 50 51 const { t } = useI18n() 52 53 interface AllSchemas { 54 searchSchema: FormSchema[] 55 tableColumns: TableColumn[] 56 formSchema: FormSchema[] 57 detailSchema: DescriptionsSchema[] 58 } 59 60 // 过滤所有结构 61 export const useCrudSchemas = ( 62 crudSchema: CrudSchema[] 63 ): { 64 allSchemas: AllSchemas 65 } => { 66 // 所有结构数据 67 const allSchemas = reactive<AllSchemas>({ 68 searchSchema: [], 69 tableColumns: [], 70 formSchema: [], 71 detailSchema: [] 72 }) 73 74 const searchSchema = filterSearchSchema(crudSchema, allSchemas) 75 allSchemas.searchSchema = searchSchema || [] 76 77 const tableColumns = filterTableSchema(crudSchema) 78 allSchemas.tableColumns = tableColumns || [] 79 80 const formSchema = filterFormSchema(crudSchema, allSchemas) 81 allSchemas.formSchema = formSchema 82 83 const detailSchema = filterDescriptionsSchema(crudSchema) 84 allSchemas.detailSchema = detailSchema 85 86 return { 87 allSchemas 88 } 89 } 90 91 // 过滤 Search 结构 92 const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { 93 const searchSchema: FormSchema[] = [] 94 95 // 获取字典列表队列 96 const searchRequestTask: Array<() => Promise<void>> = [] 97 98 eachTree(crudSchema, (schemaItem: CrudSchema) => { 99 // 判断是否显示 100 if (schemaItem?.search?.show) { 101 const searchSchemaItem = { 102 // 默认为 input 103 component: schemaItem.search.component || 'Input', 104 componentProps: {}, 105 ...schemaItem.search, 106 field: schemaItem?.search?.field || schemaItem.field, 107 label: schemaItem.search?.label || schemaItem.label 108 } 109 110 if (searchSchemaItem.dictName) { 111 // 如果有 dictName 则证明是从字典中获取数据 112 const dictArr = dictStore.getDictObj[searchSchemaItem.dictName] 113 searchSchemaItem.componentProps!.options = filterOptions(dictArr) 114 } else if (searchSchemaItem.api) { 115 searchRequestTask.push(async () => { 116 const res = await (searchSchemaItem.api as () => AxiosPromise)() 117 if (res) { 118 const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => { 119 return v.field === searchSchemaItem.field 120 }) 121 if (index !== -1) { 122 allSchemas.searchSchema[index]!.componentProps!.options = filterOptions( 123 res, 124 searchSchemaItem.componentProps.optionsAlias?.labelField 125 ) 126 } 127 } 128 }) 129 } 130 131 // 删除不必要的字段 132 delete searchSchemaItem.show 133 delete searchSchemaItem.dictName 134 135 searchSchema.push(searchSchemaItem) 136 } 137 }) 138 139 for (const task of searchRequestTask) { 140 task() 141 } 142 143 return searchSchema 144 } 145 146 // 过滤 table 结构 147 const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => { 148 const tableColumns = treeMap<CrudSchema>(crudSchema, { 149 conversion: (schema: CrudSchema) => { 150 if (schema?.table?.show !== false) { 151 return { 152 ...schema.table, 153 ...schema 154 } 155 } 156 } 157 }) 158 159 // 第一次过滤会有 undefined 所以需要二次过滤 160 return filter<TableColumn>(tableColumns as TableColumn[], (data) => { 161 if (data.children === void 0) { 162 delete data.children 163 } 164 return !!data.field 165 }) 166 } 167 168 // 过滤 form 结构 169 const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => { 170 const formSchema: FormSchema[] = [] 171 172 // 获取字典列表队列 173 const formRequestTask: Array<() => Promise<void>> = [] 174 175 eachTree(crudSchema, (schemaItem: CrudSchema) => { 176 // 判断是否显示 177 if (schemaItem?.form?.show !== false) { 178 const formSchemaItem = { 179 // 默认为 input 180 component: schemaItem?.form?.component || 'Input', 181 componentProps: {}, 182 ...schemaItem.form, 183 field: schemaItem.field, 184 label: schemaItem.search?.label || schemaItem.label 185 } 186 187 if (formSchemaItem.dictName) { 188 // 如果有 dictName 则证明是从字典中获取数据 189 const dictArr = dictStore.getDictObj[formSchemaItem.dictName] 190 formSchemaItem.componentProps!.options = filterOptions(dictArr) 191 } else if (formSchemaItem.api) { 192 formRequestTask.push(async () => { 193 const res = await (formSchemaItem.api as () => AxiosPromise)() 194 if (res) { 195 const index = findIndex(allSchemas.formSchema, (v: FormSchema) => { 196 return v.field === formSchemaItem.field 197 }) 198 if (index !== -1) { 199 allSchemas.formSchema[index]!.componentProps!.options = filterOptions( 200 res, 201 formSchemaItem.componentProps.optionsAlias?.labelField 202 ) 203 } 204 } 205 }) 206 } 207 208 // 删除不必要的字段 209 delete formSchemaItem.show 210 delete formSchemaItem.dictName 211 212 formSchema.push(formSchemaItem) 213 } 214 }) 215 216 for (const task of formRequestTask) { 217 task() 218 } 219 return formSchema 220 } 221 222 // 过滤 descriptions 结构 223 const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[] => { 224 const descriptionsSchema: FormSchema[] = [] 225 226 eachTree(crudSchema, (schemaItem: CrudSchema) => { 227 // 判断是否显示 228 if (schemaItem?.detail?.show !== false) { 229 const descriptionsSchemaItem = { 230 ...schemaItem.detail, 231 field: schemaItem.field, 232 label: schemaItem.detail?.label || schemaItem.label 233 } 234 235 // 删除不必要的字段 236 delete descriptionsSchemaItem.show 237 238 descriptionsSchema.push(descriptionsSchemaItem) 239 } 240 }) 241 242 return descriptionsSchema 243 } 244 245 // 给options添加国际化 246 const filterOptions = (options: Recordable, labelField?: string) => { 247 return options?.map((v: Recordable) => { 248 if (labelField) { 249 v['labelField'] = t(v.labelField) 250 } else { 251 v['label'] = t(v.label) 252 } 253 return v 254 }) 255 }