Commit 3ed98e152a0c3efd22dcd26dfeecbbdb60bfb52f
1 parent
c8a584c5
fix(infra): 修复前端代码生成模板的组件绑定与主子表行为
修复 Vben5 字典控件、日期及树选择属性、导入文件移除和 API 导入路径。 修复主子表数据获取、临时编号、必填校验和主表切换后的旧数据残留。 补齐工具方法与组件导入,修正 Ele 工具栏标签及 Vue3 单选多选绑定。 同步 Vue2 组件标签与 prop 声明、旧 Vben 日期范围格式。 更新生成快照,增加跨前端组件契约测试。 验证:85 条 CodegenEngine 测试、138 份 Vue 模板编译通过; Codex、Qwen、DeepSeek 三路评审通过。
Showing
120 changed files
with
3131 additions
and
1753 deletions
yudao-module-infra/src/main/resources/codegen/vue/views/components/form_sub_normal.vue.vm
| @@ -244,9 +244,13 @@ | @@ -244,9 +244,13 @@ | ||
| 244 | Editor, | 244 | Editor, |
| 245 | #end | 245 | #end |
| 246 | }, | 246 | }, |
| 247 | - props:[ | ||
| 248 | - '${subJoinColumn.javaField}' | ||
| 249 | - ],// ${subJoinColumn.columnComment}(主表的关联字段) | 247 | + props: { |
| 248 | + // ${subJoinColumn.columnComment}(主表的关联字段) | ||
| 249 | + ${subJoinColumn.javaField}: { | ||
| 250 | + type: #if ($subJoinColumn.javaType == "String")String#else Number#end, | ||
| 251 | + default: undefined | ||
| 252 | + } | ||
| 253 | + }, | ||
| 250 | data() { | 254 | data() { |
| 251 | return { | 255 | return { |
| 252 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | 256 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
yudao-module-infra/src/main/resources/codegen/vue/views/components/list_sub_erp.vue.vm
| @@ -78,7 +78,7 @@ | @@ -78,7 +78,7 @@ | ||
| 78 | </el-table> | 78 | </el-table> |
| 79 | #if ($table.templateType == 11) | 79 | #if ($table.templateType == 11) |
| 80 | <!-- 分页组件 --> | 80 | <!-- 分页组件 --> |
| 81 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 81 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 82 | @pagination="getList"/> | 82 | @pagination="getList"/> |
| 83 | <!-- 对话框(添加 / 修改) --> | 83 | <!-- 对话框(添加 / 修改) --> |
| 84 | <${subSimpleClassName}Form ref="formRef" @success="getList" /> | 84 | <${subSimpleClassName}Form ref="formRef" @success="getList" /> |
| @@ -98,9 +98,13 @@ | @@ -98,9 +98,13 @@ | ||
| 98 | ${subSimpleClassName}Form | 98 | ${subSimpleClassName}Form |
| 99 | }, | 99 | }, |
| 100 | #end | 100 | #end |
| 101 | - props:[ | ||
| 102 | - '${subJoinColumn.javaField}' | ||
| 103 | - ],// ${subJoinColumn.columnComment}(主表的关联字段) | 101 | + props: { |
| 102 | + // ${subJoinColumn.columnComment}(主表的关联字段) | ||
| 103 | + ${subJoinColumn.javaField}: { | ||
| 104 | + type: #if ($subJoinColumn.javaType == "String")String#else Number#end, | ||
| 105 | + default: undefined | ||
| 106 | + } | ||
| 107 | + }, | ||
| 104 | data() { | 108 | data() { |
| 105 | return { | 109 | return { |
| 106 | // 遮罩层 | 110 | // 遮罩层 |
yudao-module-infra/src/main/resources/codegen/vue/views/index.vue.vm
| @@ -86,7 +86,7 @@ | @@ -86,7 +86,7 @@ | ||
| 86 | </el-button> | 86 | </el-button> |
| 87 | </el-col> | 87 | </el-col> |
| 88 | #end | 88 | #end |
| 89 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 89 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 90 | </el-row> | 90 | </el-row> |
| 91 | #if ($importEnable) | 91 | #if ($importEnable) |
| 92 | <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> | 92 | <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> |
| @@ -186,7 +186,7 @@ | @@ -186,7 +186,7 @@ | ||
| 186 | ## 特殊:树表专属逻辑(树不需要分页) | 186 | ## 特殊:树表专属逻辑(树不需要分页) |
| 187 | #if ( $table.templateType != 2 ) | 187 | #if ( $table.templateType != 2 ) |
| 188 | <!-- 分页组件 --> | 188 | <!-- 分页组件 --> |
| 189 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 189 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 190 | @pagination="getList"/> | 190 | @pagination="getList"/> |
| 191 | #end | 191 | #end |
| 192 | <!-- 对话框(添加 / 修改) --> | 192 | <!-- 对话框(添加 / 修改) --> |
yudao-module-infra/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm
| @@ -79,7 +79,7 @@ | @@ -79,7 +79,7 @@ | ||
| 79 | <el-radio | 79 | <el-radio |
| 80 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | 80 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" |
| 81 | :key="dict.value" | 81 | :key="dict.value" |
| 82 | - :label="dict.value" | 82 | + :value="dict.value" |
| 83 | > | 83 | > |
| 84 | {{ dict.label }} | 84 | {{ dict.label }} |
| 85 | </el-radio> | 85 | </el-radio> |
yudao-module-infra/src/main/resources/codegen/vue3/views/components/form_sub_normal.vue.vm
| @@ -111,7 +111,7 @@ | @@ -111,7 +111,7 @@ | ||
| 111 | <el-radio | 111 | <el-radio |
| 112 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | 112 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" |
| 113 | :key="dict.value" | 113 | :key="dict.value" |
| 114 | - :label="dict.value" | 114 | + :value="dict.value" |
| 115 | > | 115 | > |
| 116 | {{ dict.label }} | 116 | {{ dict.label }} |
| 117 | </el-radio> | 117 | </el-radio> |
| @@ -233,7 +233,7 @@ | @@ -233,7 +233,7 @@ | ||
| 233 | <el-radio | 233 | <el-radio |
| 234 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | 234 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" |
| 235 | :key="dict.value" | 235 | :key="dict.value" |
| 236 | - :label="dict.value" | 236 | + :value="dict.value" |
| 237 | > | 237 | > |
| 238 | {{ dict.label }} | 238 | {{ dict.label }} |
| 239 | </el-radio> | 239 | </el-radio> |
yudao-module-infra/src/main/resources/codegen/vue3/views/form.vue.vm
| @@ -90,7 +90,7 @@ | @@ -90,7 +90,7 @@ | ||
| 90 | <el-radio | 90 | <el-radio |
| 91 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" | 91 | v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())" |
| 92 | :key="dict.value" | 92 | :key="dict.value" |
| 93 | - :label="dict.value" | 93 | + :value="dict.value" |
| 94 | > | 94 | > |
| 95 | {{ dict.label }} | 95 | {{ dict.label }} |
| 96 | </el-radio> | 96 | </el-radio> |
yudao-module-infra/src/main/resources/codegen/vue3_vben/views/data.ts.vm
| @@ -78,6 +78,12 @@ export const searchFormSchema: FormSchema[] = [ | @@ -78,6 +78,12 @@ export const searchFormSchema: FormSchema[] = [ | ||
| 78 | }, | 78 | }, |
| 79 | #elseif($column.htmlType == "datetime") | 79 | #elseif($column.htmlType == "datetime") |
| 80 | component: 'RangePicker', | 80 | component: 'RangePicker', |
| 81 | + componentProps: { | ||
| 82 | + showTime: true, | ||
| 83 | + format: 'YYYY-MM-DD HH:mm:ss', | ||
| 84 | + valueFormat: 'YYYY-MM-DD HH:mm:ss', | ||
| 85 | + allowClear: true, | ||
| 86 | + }, | ||
| 81 | #end | 87 | #end |
| 82 | colProps: { span: 8 }, | 88 | colProps: { span: 8 }, |
| 83 | }, | 89 | }, |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/form.vue.vm
| @@ -112,7 +112,10 @@ const [Modal, modalApi] = useVbenModal({ | @@ -112,7 +112,10 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 112 | #set ($index = $foreach.count - 1) | 112 | #set ($index = $foreach.count - 1) |
| 113 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 113 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 114 | #if ($subTable.subJoinMany) ## 一对多 | 114 | #if ($subTable.subJoinMany) ## 一对多 |
| 115 | - ## TODO 列表值校验? | 115 | + if (!${subClassNameVar}FormRef.value?.validate()) { |
| 116 | + subTabsName.value = '${subClassNameVar}'; | ||
| 117 | + return; | ||
| 118 | + } | ||
| 116 | #else | 119 | #else |
| 117 | try { | 120 | try { |
| 118 | await ${subClassNameVar}FormRef.value?.validate() | 121 | await ${subClassNameVar}FormRef.value?.validate() |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/import.vue.vm
| @@ -48,6 +48,11 @@ function beforeUpload(file: FileType) { | @@ -48,6 +48,11 @@ function beforeUpload(file: FileType) { | ||
| 48 | return false; | 48 | return false; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | +/** 移除文件 */ | ||
| 52 | +function handleRemove() { | ||
| 53 | + fileRef.value = null; | ||
| 54 | +} | ||
| 55 | + | ||
| 51 | /** 下载导入模板 */ | 56 | /** 下载导入模板 */ |
| 52 | async function handleDownload() { | 57 | async function handleDownload() { |
| 53 | const data = await import${simpleClassName}Template(); | 58 | const data = await import${simpleClassName}Template(); |
| @@ -58,7 +63,12 @@ async function handleDownload() { | @@ -58,7 +63,12 @@ async function handleDownload() { | ||
| 58 | <template> | 63 | <template> |
| 59 | <Modal title="导入${table.classComment}" class="w-1/3"> | 64 | <Modal title="导入${table.classComment}" class="w-1/3"> |
| 60 | <div class="mx-4"> | 65 | <div class="mx-4"> |
| 61 | - <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload"> | 66 | + <Upload |
| 67 | + :max-count="1" | ||
| 68 | + accept=".xls,.xlsx" | ||
| 69 | + :before-upload="beforeUpload" | ||
| 70 | + :on-remove="handleRemove" | ||
| 71 | + > | ||
| 62 | <Button type="primary"> 选择 Excel 文件 </Button> | 72 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 63 | </Upload> | 73 | </Upload> |
| 64 | </div> | 74 | </div> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm
| @@ -65,12 +65,7 @@ const queryParams = reactive({ | @@ -65,12 +65,7 @@ const queryParams = reactive({ | ||
| 65 | #end | 65 | #end |
| 66 | #foreach ($column in $columns) | 66 | #foreach ($column in $columns) |
| 67 | #if ($column.listOperation) | 67 | #if ($column.listOperation) |
| 68 | - #if ($column.listOperationCondition != 'BETWEEN') | ||
| 69 | - $column.javaField: undefined, | ||
| 70 | - #end | ||
| 71 | - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 72 | - $column.javaField: undefined, | ||
| 73 | - #end | 68 | + $column.javaField: undefined, |
| 74 | #end | 69 | #end |
| 75 | #end | 70 | #end |
| 76 | }) | 71 | }) |
| @@ -197,7 +192,17 @@ function handleRowCheckboxChange({ | @@ -197,7 +192,17 @@ function handleRowCheckboxChange({ | ||
| 197 | async function handleExport() { | 192 | async function handleExport() { |
| 198 | try { | 193 | try { |
| 199 | exportLoading.value = true; | 194 | exportLoading.value = true; |
| 200 | - const data = await export${simpleClassName}(queryParams); | 195 | + const params = cloneDeep(queryParams) as any; |
| 196 | + #foreach ($column in $columns) | ||
| 197 | + #if ($column.listOperation) | ||
| 198 | + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 199 | + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) { | ||
| 200 | + params.${column.javaField} = (params.${column.javaField} as string[]).join(','); | ||
| 201 | + } | ||
| 202 | + #end | ||
| 203 | + #end | ||
| 204 | + #end | ||
| 205 | + const data = await export${simpleClassName}(params); | ||
| 201 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); | 206 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); |
| 202 | }finally { | 207 | }finally { |
| 203 | exportLoading.value = false; | 208 | exportLoading.value = false; |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm
| @@ -46,25 +46,54 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | @@ -46,25 +46,54 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | ||
| 46 | await tableRef.value?.remove(row); | 46 | await tableRef.value?.remove(row); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 50 | -defineExpose({ | ||
| 51 | - getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => { | ||
| 52 | - const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 53 | - const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 54 | - const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 55 | - return [ | ||
| 56 | - ...data.filter( | ||
| 57 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 58 | - ), | ||
| 59 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 60 | - ]; | ||
| 61 | - }, | ||
| 62 | -}); | 49 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 50 | +function getData(): ${simpleClassName}Api.${subSimpleClassName}[] { | ||
| 51 | + const table = tableRef.value; | ||
| 52 | + if (!table) { | ||
| 53 | + return []; | ||
| 54 | + } | ||
| 55 | + const { fullData } = table.getTableData(); | ||
| 56 | + const inserted = new Set(table.getInsertRecords()); | ||
| 57 | + return fullData.map((row) => | ||
| 58 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 59 | + ); | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +#set ($hasRequiredColumn = false) | ||
| 63 | +#foreach ($column in $subColumns) | ||
| 64 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 65 | +#set ($hasRequiredColumn = true) | ||
| 66 | +#end | ||
| 67 | +#end | ||
| 68 | +/** 校验子表必填字段 */ | ||
| 69 | +function validate(): boolean { | ||
| 70 | +#if ($hasRequiredColumn) | ||
| 71 | + for (const [index, row] of getData().entries()) { | ||
| 72 | +#foreach ($column in $subColumns) | ||
| 73 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 74 | + if ( | ||
| 75 | + row.${column.javaField} === null || | ||
| 76 | + row.${column.javaField} === undefined || | ||
| 77 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 78 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 79 | + ) { | ||
| 80 | + message.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 81 | + return false; | ||
| 82 | + } | ||
| 83 | +#end | ||
| 84 | +#end | ||
| 85 | + } | ||
| 86 | +#end | ||
| 87 | + return true; | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +defineExpose({ getData, validate }); | ||
| 63 | 91 | ||
| 64 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 92 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 65 | watch( | 93 | watch( |
| 66 | () => props.${subJoinColumn.javaField}, | 94 | () => props.${subJoinColumn.javaField}, |
| 67 | async (val) => { | 95 | async (val) => { |
| 96 | + list.value = []; | ||
| 68 | if (!val) { | 97 | if (!val) { |
| 69 | return; | 98 | return; |
| 70 | } | 99 | } |
| @@ -103,6 +132,17 @@ defineExpose({ | @@ -103,6 +132,17 @@ defineExpose({ | ||
| 103 | watch( | 132 | watch( |
| 104 | () => props.${subJoinColumn.javaField}, | 133 | () => props.${subJoinColumn.javaField}, |
| 105 | async (val) => { | 134 | async (val) => { |
| 135 | + formData.value = { | ||
| 136 | +#foreach ($column in $subColumns) | ||
| 137 | +#if ($column.createOperation || $column.updateOperation) | ||
| 138 | +#if ($column.htmlType == "checkbox") | ||
| 139 | + $column.javaField: [], | ||
| 140 | +#else | ||
| 141 | + $column.javaField: undefined, | ||
| 142 | +#end | ||
| 143 | +#end | ||
| 144 | +#end | ||
| 145 | + }; | ||
| 106 | if (!val) { | 146 | if (!val) { |
| 107 | return; | 147 | return; |
| 108 | } | 148 | } |
| @@ -120,6 +160,7 @@ watch( | @@ -120,6 +160,7 @@ watch( | ||
| 120 | #foreach($column in $subColumns) | 160 | #foreach($column in $subColumns) |
| 121 | #if ($column.createOperation || $column.updateOperation) | 161 | #if ($column.createOperation || $column.updateOperation) |
| 122 | #set ($comment = $column.columnComment) | 162 | #set ($comment = $column.columnComment) |
| 163 | + #set ($dictType = $column.dictType) | ||
| 123 | #set ($javaField = $column.javaField) | 164 | #set ($javaField = $column.javaField) |
| 124 | #set ($javaType = $column.javaType) | 165 | #set ($javaType = $column.javaType) |
| 125 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 166 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
| @@ -36,7 +36,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -36,7 +36,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 36 | id: 0, | 36 | id: 0, |
| 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', | 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', |
| 38 | }); | 38 | }); |
| 39 | - return handleTree(data); | 39 | + return handleTree(data, 'id', '${treeParentColumn.javaField}'); |
| 40 | }, | 40 | }, |
| 41 | labelField: '${treeNameColumn.javaField}', | 41 | labelField: '${treeNameColumn.javaField}', |
| 42 | valueField: 'id', | 42 | valueField: 'id', |
| @@ -89,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -89,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 89 | placeholder: '请选择${comment}', | 89 | placeholder: '请选择${comment}', |
| 90 | }, | 90 | }, |
| 91 | #elseif($column.htmlType == "checkbox")## 多选框 | 91 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 92 | - component: 'Checkbox', | 92 | + component: 'CheckboxGroup', |
| 93 | componentProps: { | 93 | componentProps: { |
| 94 | #if ("" != $dictType)## 有数据字典 | 94 | #if ("" != $dictType)## 有数据字典 |
| 95 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 95 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -306,7 +306,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | @@ -306,7 +306,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | ||
| 306 | placeholder: '请选择${comment}', | 306 | placeholder: '请选择${comment}', |
| 307 | }, | 307 | }, |
| 308 | #elseif($column.htmlType == "checkbox")## 多选框 | 308 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 309 | - component: 'Checkbox', | 309 | + component: 'CheckboxGroup', |
| 310 | componentProps: { | 310 | componentProps: { |
| 311 | #if ("" != $dictType)## 有数据字典 | 311 | #if ("" != $dictType)## 有数据字典 |
| 312 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 312 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -446,6 +446,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -446,6 +446,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 446 | #if ($column.createOperation || $column.updateOperation) | 446 | #if ($column.createOperation || $column.updateOperation) |
| 447 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 | 447 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 |
| 448 | #set ($dictType = $column.dictType) | 448 | #set ($dictType = $column.dictType) |
| 449 | + #set ($javaType = $column.javaType) | ||
| 449 | #set ($javaField = $column.javaField) | 450 | #set ($javaField = $column.javaField) |
| 450 | #set ($comment = $column.columnComment) | 451 | #set ($comment = $column.columnComment) |
| 451 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 452 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
| @@ -540,7 +541,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -540,7 +541,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 540 | placeholder: '请选择${comment}', | 541 | placeholder: '请选择${comment}', |
| 541 | }, | 542 | }, |
| 542 | #elseif($column.htmlType == "checkbox")## 多选框 | 543 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 543 | - component: 'Checkbox', | 544 | + component: 'CheckboxGroup', |
| 544 | componentProps: { | 545 | componentProps: { |
| 545 | #if ("" != $dictType)## 有数据字典 | 546 | #if ("" != $dictType)## 有数据字典 |
| 546 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 547 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -590,7 +591,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -590,7 +591,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 590 | #end | 591 | #end |
| 591 | #if ($table.templateType == 12) ## 内嵌情况 | 592 | #if ($table.templateType == 12) ## 内嵌情况 |
| 592 | /** 列表的字段 */ | 593 | /** 列表的字段 */ |
| 593 | - export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] { | 594 | + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] { |
| 594 | return [ | 595 | return [ |
| 595 | #foreach($column in $subColumns) | 596 | #foreach($column in $subColumns) |
| 596 | #if ($column.listOperationResult) | 597 | #if ($column.listOperationResult) |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/form.vue.vm
| @@ -6,7 +6,7 @@ import { computed, ref } from 'vue'; | @@ -6,7 +6,7 @@ import { computed, ref } from 'vue'; | ||
| 6 | 6 | ||
| 7 | import { useVbenModal } from '@vben/common-ui'; | 7 | import { useVbenModal } from '@vben/common-ui'; |
| 8 | 8 | ||
| 9 | -import { message#if ($table.templateType == 11), Tabs#end } from 'ant-design-vue'; | 9 | +import { message#if ($table.templateType == 10 || $table.templateType == 12), Tabs#end } from 'ant-design-vue'; |
| 10 | 10 | ||
| 11 | import { useVbenForm } from '#/adapter/form'; | 11 | import { useVbenForm } from '#/adapter/form'; |
| 12 | import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; | 12 | import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 69 | #foreach ($subTable in $subTables) | 69 | #foreach ($subTable in $subTables) |
| 70 | #set ($index = $foreach.count - 1) | 70 | #set ($index = $foreach.count - 1) |
| 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 72 | - #if ($subTable.subJoinMany) ## 一对多 | ||
| 73 | - ## TODO 列表值校验? | ||
| 74 | - #else | ||
| 75 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); | 72 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); |
| 76 | if (!${subClassNameVar}Valid) { | 73 | if (!${subClassNameVar}Valid) { |
| 77 | subTabsName.value = '${subClassNameVar}'; | 74 | subTabsName.value = '${subClassNameVar}'; |
| 78 | return; | 75 | return; |
| 79 | } | 76 | } |
| 80 | - #end | ||
| 81 | #end | 77 | #end |
| 82 | #end | 78 | #end |
| 83 | #end | 79 | #end |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/import.vue.vm
| @@ -51,6 +51,11 @@ function beforeUpload(file: FileType) { | @@ -51,6 +51,11 @@ function beforeUpload(file: FileType) { | ||
| 51 | return false; | 51 | return false; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | +/** 移除文件 */ | ||
| 55 | +function handleRemove() { | ||
| 56 | + formApi.setFieldValue('file', undefined); | ||
| 57 | +} | ||
| 58 | + | ||
| 54 | /** 下载模板 */ | 59 | /** 下载模板 */ |
| 55 | async function handleDownload() { | 60 | async function handleDownload() { |
| 56 | const data = await import${simpleClassName}Template(); | 61 | const data = await import${simpleClassName}Template(); |
| @@ -67,6 +72,7 @@ async function handleDownload() { | @@ -67,6 +72,7 @@ async function handleDownload() { | ||
| 67 | :max-count="1" | 72 | :max-count="1" |
| 68 | accept=".xls,.xlsx" | 73 | accept=".xls,.xlsx" |
| 69 | :before-upload="beforeUpload" | 74 | :before-upload="beforeUpload" |
| 75 | + :on-remove="handleRemove" | ||
| 70 | > | 76 | > |
| 71 | <Button type="primary"> 选择 Excel 文件 </Button> | 77 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 72 | </Upload> | 78 | </Upload> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | 14 | ||
| 15 | #if ($subTable.subJoinMany) ## 一对多 | 15 | #if ($subTable.subJoinMany) ## 一对多 |
| 16 | import { Plus } from "@vben/icons"; | 16 | import { Plus } from "@vben/icons"; |
| 17 | -import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue'; | 17 | +import { Button, Checkbox, CheckboxGroup, DatePicker, Input, message, RadioGroup, Select, Tabs, Textarea } from 'ant-design-vue'; |
| 18 | import { ImageUpload, FileUpload } from "#/components/upload"; | 18 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 19 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 19 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 20 | import { use${subSimpleClassName}GridEditColumns } from '../data'; | 20 | import { use${subSimpleClassName}GridEditColumns } from '../data'; |
| @@ -59,26 +59,54 @@ const handleDelete = async (row: ${apiName}.${subSimpleClassName}) => { | @@ -59,26 +59,54 @@ const handleDelete = async (row: ${apiName}.${subSimpleClassName}) => { | ||
| 59 | await gridApi.grid.remove(row); | 59 | await gridApi.grid.remove(row); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 63 | -defineExpose({ | ||
| 64 | - getData: (): ${apiName}.${subSimpleClassName}[] => { | ||
| 65 | - const data = gridApi.grid.getData() as ${apiName}.${subSimpleClassName}[]; | ||
| 66 | - const removeRecords = gridApi.grid.getRemoveRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 67 | - const insertRecords = gridApi.grid.getInsertRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 68 | - return data | ||
| 69 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 70 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 71 | - }, | ||
| 72 | -}); | 62 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 63 | +function getData(): ${apiName}.${subSimpleClassName}[] { | ||
| 64 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 65 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 66 | + return fullData.map((row) => | ||
| 67 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 68 | + ); | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +#set ($hasRequiredColumn = false) | ||
| 72 | +#foreach ($column in $subColumns) | ||
| 73 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 74 | +#set ($hasRequiredColumn = true) | ||
| 75 | +#end | ||
| 76 | +#end | ||
| 77 | +/** 校验子表必填字段 */ | ||
| 78 | +function validate(): boolean { | ||
| 79 | +#if ($hasRequiredColumn) | ||
| 80 | + for (const [index, row] of getData().entries()) { | ||
| 81 | +#foreach ($column in $subColumns) | ||
| 82 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 83 | + if ( | ||
| 84 | + row.${column.javaField} === null || | ||
| 85 | + row.${column.javaField} === undefined || | ||
| 86 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 87 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 88 | + ) { | ||
| 89 | + message.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 90 | + return false; | ||
| 91 | + } | ||
| 92 | +#end | ||
| 93 | +#end | ||
| 94 | + } | ||
| 95 | +#end | ||
| 96 | + return true; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +defineExpose({ getData, validate }); | ||
| 73 | 100 | ||
| 74 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 101 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 75 | watch( | 102 | watch( |
| 76 | () => props.${subJoinColumn.javaField}, | 103 | () => props.${subJoinColumn.javaField}, |
| 77 | async (val) => { | 104 | async (val) => { |
| 105 | + await nextTick(); | ||
| 78 | if (!val) { | 106 | if (!val) { |
| 107 | + await gridApi.grid.loadData([]); | ||
| 79 | return; | 108 | return; |
| 80 | } | 109 | } |
| 81 | - await nextTick(); | ||
| 82 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 110 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 83 | }, | 111 | }, |
| 84 | { immediate: true }, | 112 | { immediate: true }, |
| @@ -110,10 +138,11 @@ defineExpose({ | @@ -110,10 +138,11 @@ defineExpose({ | ||
| 110 | watch( | 138 | watch( |
| 111 | () => props.${subJoinColumn.javaField}, | 139 | () => props.${subJoinColumn.javaField}, |
| 112 | async (val) => { | 140 | async (val) => { |
| 141 | + await nextTick(); | ||
| 142 | + await formApi.resetForm(); | ||
| 113 | if (!val) { | 143 | if (!val) { |
| 114 | return; | 144 | return; |
| 115 | } | 145 | } |
| 116 | - await nextTick(); | ||
| 117 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 146 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 118 | }, | 147 | }, |
| 119 | { immediate: true }, | 148 | { immediate: true }, |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/general/views/form.vue.vm
| @@ -118,7 +118,10 @@ const [Modal, modalApi] = useVbenModal({ | @@ -118,7 +118,10 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 118 | #set ($index = $foreach.count - 1) | 118 | #set ($index = $foreach.count - 1) |
| 119 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 119 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 120 | #if ($subTable.subJoinMany) ## 一对多 | 120 | #if ($subTable.subJoinMany) ## 一对多 |
| 121 | - ## TODO 列表值校验? | 121 | + if (!${subClassNameVar}FormRef.value?.validate()) { |
| 122 | + subTabsName.value = '${subClassNameVar}'; | ||
| 123 | + return; | ||
| 124 | + } | ||
| 122 | #else | 125 | #else |
| 123 | try { | 126 | try { |
| 124 | await ${subClassNameVar}FormRef.value?.validate() | 127 | await ${subClassNameVar}FormRef.value?.validate() |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/general/views/import.vue.vm
| @@ -46,6 +46,11 @@ function beforeUpload(file: File) { | @@ -46,6 +46,11 @@ function beforeUpload(file: File) { | ||
| 46 | return false; | 46 | return false; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | +/** 移除文件 */ | ||
| 50 | +function handleRemove() { | ||
| 51 | + fileRef.value = null; | ||
| 52 | +} | ||
| 53 | + | ||
| 49 | /** 下载导入模板 */ | 54 | /** 下载导入模板 */ |
| 50 | async function handleDownload() { | 55 | async function handleDownload() { |
| 51 | const data = await import${simpleClassName}Template(); | 56 | const data = await import${simpleClassName}Template(); |
| @@ -56,7 +61,8 @@ async function handleDownload() { | @@ -56,7 +61,8 @@ async function handleDownload() { | ||
| 56 | <template> | 61 | <template> |
| 57 | <Modal title="导入${table.classComment}" class="w-1/3"> | 62 | <Modal title="导入${table.classComment}" class="w-1/3"> |
| 58 | <div class="mx-4"> | 63 | <div class="mx-4"> |
| 59 | - <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload"> | 64 | + <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload" |
| 65 | + :on-remove="handleRemove"> | ||
| 60 | <Button type="primary"> 选择 Excel 文件 </Button> | 66 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 61 | </Upload> | 67 | </Upload> |
| 62 | </div> | 68 | </div> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/general/views/index.vue.vm
| @@ -77,12 +77,7 @@ const queryParams = reactive({ | @@ -77,12 +77,7 @@ const queryParams = reactive({ | ||
| 77 | #end | 77 | #end |
| 78 | #foreach ($column in $columns) | 78 | #foreach ($column in $columns) |
| 79 | #if ($column.listOperation) | 79 | #if ($column.listOperation) |
| 80 | - #if ($column.listOperationCondition != 'BETWEEN') | ||
| 81 | - $column.javaField: undefined, | ||
| 82 | - #end | ||
| 83 | - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 84 | - $column.javaField: undefined, | ||
| 85 | - #end | 80 | + $column.javaField: undefined, |
| 86 | #end | 81 | #end |
| 87 | #end | 82 | #end |
| 88 | }) | 83 | }) |
| @@ -209,7 +204,17 @@ function handleRowCheckboxChange({ | @@ -209,7 +204,17 @@ function handleRowCheckboxChange({ | ||
| 209 | async function handleExport() { | 204 | async function handleExport() { |
| 210 | try { | 205 | try { |
| 211 | exportLoading.value = true; | 206 | exportLoading.value = true; |
| 212 | - const data = await export${simpleClassName}(queryParams); | 207 | + const params = cloneDeep(queryParams) as any; |
| 208 | + #foreach ($column in $columns) | ||
| 209 | + #if ($column.listOperation) | ||
| 210 | + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 211 | + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) { | ||
| 212 | + params.${column.javaField} = (params.${column.javaField} as string[]).join(','); | ||
| 213 | + } | ||
| 214 | + #end | ||
| 215 | + #end | ||
| 216 | + #end | ||
| 217 | + const data = await export${simpleClassName}(params); | ||
| 213 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); | 218 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); |
| 214 | }finally { | 219 | }finally { |
| 215 | exportLoading.value = false; | 220 | exportLoading.value = false; |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/general/views/modules/form_sub_normal.vue.vm
| @@ -18,7 +18,7 @@ import { computed, ref, h, onMounted, watch, nextTick } from 'vue'; | @@ -18,7 +18,7 @@ import { computed, ref, h, onMounted, watch, nextTick } from 'vue'; | ||
| 18 | import { DICT_TYPE } from '@vben/constants'; | 18 | import { DICT_TYPE } from '@vben/constants'; |
| 19 | import { getDictOptions } from '@vben/hooks'; | 19 | import { getDictOptions } from '@vben/hooks'; |
| 20 | 20 | ||
| 21 | -import { Button, Checkbox, CheckboxGroup, DatePicker#if (!$subTable.subJoinMany), Form, FormItem#end, Input, Radio, RadioGroup, Select#if ($selectOptionEnable), SelectOption#end, TextArea } from 'antdv-next'; | 21 | +import { Button, Checkbox, CheckboxGroup, DatePicker#if (!$subTable.subJoinMany), Form, FormItem#end, Input#if ($subTable.subJoinMany), message#end, Radio, RadioGroup, Select#if ($selectOptionEnable), SelectOption#end, TextArea } from 'antdv-next'; |
| 22 | import { $t } from '#/locales'; | 22 | import { $t } from '#/locales'; |
| 23 | 23 | ||
| 24 | #if ($subTable.subJoinMany) ## 一对多 | 24 | #if ($subTable.subJoinMany) ## 一对多 |
| @@ -52,25 +52,54 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | @@ -52,25 +52,54 @@ async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | ||
| 52 | await tableRef.value?.remove(row); | 52 | await tableRef.value?.remove(row); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 56 | -defineExpose({ | ||
| 57 | - getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => { | ||
| 58 | - const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 59 | - const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 60 | - const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 61 | - return [ | ||
| 62 | - ...data.filter( | ||
| 63 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 64 | - ), | ||
| 65 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 66 | - ]; | ||
| 67 | - }, | ||
| 68 | -}); | 55 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 56 | +function getData(): ${simpleClassName}Api.${subSimpleClassName}[] { | ||
| 57 | + const table = tableRef.value; | ||
| 58 | + if (!table) { | ||
| 59 | + return []; | ||
| 60 | + } | ||
| 61 | + const { fullData } = table.getTableData(); | ||
| 62 | + const inserted = new Set(table.getInsertRecords()); | ||
| 63 | + return fullData.map((row) => | ||
| 64 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 65 | + ); | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +#set ($hasRequiredColumn = false) | ||
| 69 | +#foreach ($column in $subColumns) | ||
| 70 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 71 | +#set ($hasRequiredColumn = true) | ||
| 72 | +#end | ||
| 73 | +#end | ||
| 74 | +/** 校验子表必填字段 */ | ||
| 75 | +function validate(): boolean { | ||
| 76 | +#if ($hasRequiredColumn) | ||
| 77 | + for (const [index, row] of getData().entries()) { | ||
| 78 | +#foreach ($column in $subColumns) | ||
| 79 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 80 | + if ( | ||
| 81 | + row.${column.javaField} === null || | ||
| 82 | + row.${column.javaField} === undefined || | ||
| 83 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 84 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 85 | + ) { | ||
| 86 | + message.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 87 | + return false; | ||
| 88 | + } | ||
| 89 | +#end | ||
| 90 | +#end | ||
| 91 | + } | ||
| 92 | +#end | ||
| 93 | + return true; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +defineExpose({ getData, validate }); | ||
| 69 | 97 | ||
| 70 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 98 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 71 | watch( | 99 | watch( |
| 72 | () => props.${subJoinColumn.javaField}, | 100 | () => props.${subJoinColumn.javaField}, |
| 73 | async (val) => { | 101 | async (val) => { |
| 102 | + list.value = []; | ||
| 74 | if (!val) { | 103 | if (!val) { |
| 75 | return; | 104 | return; |
| 76 | } | 105 | } |
| @@ -109,6 +138,17 @@ defineExpose({ | @@ -109,6 +138,17 @@ defineExpose({ | ||
| 109 | watch( | 138 | watch( |
| 110 | () => props.${subJoinColumn.javaField}, | 139 | () => props.${subJoinColumn.javaField}, |
| 111 | async (val) => { | 140 | async (val) => { |
| 141 | + formData.value = { | ||
| 142 | +#foreach ($column in $subColumns) | ||
| 143 | +#if ($column.createOperation || $column.updateOperation) | ||
| 144 | +#if ($column.htmlType == "checkbox") | ||
| 145 | + $column.javaField: [], | ||
| 146 | +#else | ||
| 147 | + $column.javaField: undefined, | ||
| 148 | +#end | ||
| 149 | +#end | ||
| 150 | +#end | ||
| 151 | + }; | ||
| 112 | if (!val) { | 152 | if (!val) { |
| 113 | return; | 153 | return; |
| 114 | } | 154 | } |
| @@ -126,6 +166,7 @@ watch( | @@ -126,6 +166,7 @@ watch( | ||
| 126 | #foreach($column in $subColumns) | 166 | #foreach($column in $subColumns) |
| 127 | #if ($column.createOperation || $column.updateOperation) | 167 | #if ($column.createOperation || $column.updateOperation) |
| 128 | #set ($comment = $column.columnComment) | 168 | #set ($comment = $column.columnComment) |
| 169 | + #set ($dictType = $column.dictType) | ||
| 129 | #set ($javaField = $column.javaField) | 170 | #set ($javaField = $column.javaField) |
| 130 | #set ($javaType = $column.javaType) | 171 | #set ($javaType = $column.javaType) |
| 131 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 172 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/schema/views/data.ts.vm
| @@ -36,7 +36,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -36,7 +36,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 36 | id: 0, | 36 | id: 0, |
| 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', | 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', |
| 38 | }); | 38 | }); |
| 39 | - return handleTree(data); | 39 | + return handleTree(data, 'id', '${treeParentColumn.javaField}'); |
| 40 | }, | 40 | }, |
| 41 | labelField: '${treeNameColumn.javaField}', | 41 | labelField: '${treeNameColumn.javaField}', |
| 42 | valueField: 'id', | 42 | valueField: 'id', |
| @@ -89,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -89,7 +89,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 89 | placeholder: '请选择${comment}', | 89 | placeholder: '请选择${comment}', |
| 90 | }, | 90 | }, |
| 91 | #elseif($column.htmlType == "checkbox")## 多选框 | 91 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 92 | - component: 'Checkbox', | 92 | + component: 'CheckboxGroup', |
| 93 | componentProps: { | 93 | componentProps: { |
| 94 | #if ("" != $dictType)## 有数据字典 | 94 | #if ("" != $dictType)## 有数据字典 |
| 95 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 95 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -305,7 +305,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | @@ -305,7 +305,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | ||
| 305 | placeholder: '请选择${comment}', | 305 | placeholder: '请选择${comment}', |
| 306 | }, | 306 | }, |
| 307 | #elseif($column.htmlType == "checkbox")## 多选框 | 307 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 308 | - component: 'Checkbox', | 308 | + component: 'CheckboxGroup', |
| 309 | componentProps: { | 309 | componentProps: { |
| 310 | #if ("" != $dictType)## 有数据字典 | 310 | #if ("" != $dictType)## 有数据字典 |
| 311 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 311 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -444,6 +444,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -444,6 +444,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 444 | #if ($column.createOperation || $column.updateOperation) | 444 | #if ($column.createOperation || $column.updateOperation) |
| 445 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 | 445 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 |
| 446 | #set ($dictType = $column.dictType) | 446 | #set ($dictType = $column.dictType) |
| 447 | + #set ($javaType = $column.javaType) | ||
| 447 | #set ($javaField = $column.javaField) | 448 | #set ($javaField = $column.javaField) |
| 448 | #set ($comment = $column.columnComment) | 449 | #set ($comment = $column.columnComment) |
| 449 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 450 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
| @@ -538,7 +539,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -538,7 +539,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 538 | placeholder: '请选择${comment}', | 539 | placeholder: '请选择${comment}', |
| 539 | }, | 540 | }, |
| 540 | #elseif($column.htmlType == "checkbox")## 多选框 | 541 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 541 | - component: 'Checkbox', | 542 | + component: 'CheckboxGroup', |
| 542 | componentProps: { | 543 | componentProps: { |
| 543 | #if ("" != $dictType)## 有数据字典 | 544 | #if ("" != $dictType)## 有数据字典 |
| 544 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 545 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -587,7 +588,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -587,7 +588,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 587 | #end | 588 | #end |
| 588 | #if ($table.templateType == 12) ## 内嵌情况 | 589 | #if ($table.templateType == 12) ## 内嵌情况 |
| 589 | /** 列表的字段 */ | 590 | /** 列表的字段 */ |
| 590 | - export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] { | 591 | + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] { |
| 591 | return [ | 592 | return [ |
| 592 | #foreach($column in $subColumns) | 593 | #foreach($column in $subColumns) |
| 593 | #if ($column.listOperationResult) | 594 | #if ($column.listOperationResult) |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/schema/views/form.vue.vm
| @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 69 | #foreach ($subTable in $subTables) | 69 | #foreach ($subTable in $subTables) |
| 70 | #set ($index = $foreach.count - 1) | 70 | #set ($index = $foreach.count - 1) |
| 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 72 | - #if ($subTable.subJoinMany) ## 一对多 | ||
| 73 | - ## TODO 列表值校验? | ||
| 74 | - #else | ||
| 75 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); | 72 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); |
| 76 | if (!${subClassNameVar}Valid) { | 73 | if (!${subClassNameVar}Valid) { |
| 77 | subTabsName.value = '${subClassNameVar}'; | 74 | subTabsName.value = '${subClassNameVar}'; |
| 78 | return; | 75 | return; |
| 79 | } | 76 | } |
| 80 | - #end | ||
| 81 | #end | 77 | #end |
| 82 | #end | 78 | #end |
| 83 | #end | 79 | #end |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/schema/views/import.vue.vm
| @@ -49,6 +49,11 @@ function beforeUpload(file: File) { | @@ -49,6 +49,11 @@ function beforeUpload(file: File) { | ||
| 49 | return false; | 49 | return false; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | +/** 移除文件 */ | ||
| 53 | +function handleRemove() { | ||
| 54 | + formApi.setFieldValue('file', undefined); | ||
| 55 | +} | ||
| 56 | + | ||
| 52 | /** 下载模板 */ | 57 | /** 下载模板 */ |
| 53 | async function handleDownload() { | 58 | async function handleDownload() { |
| 54 | const data = await import${simpleClassName}Template(); | 59 | const data = await import${simpleClassName}Template(); |
| @@ -65,6 +70,7 @@ async function handleDownload() { | @@ -65,6 +70,7 @@ async function handleDownload() { | ||
| 65 | :max-count="1" | 70 | :max-count="1" |
| 66 | accept=".xls,.xlsx" | 71 | accept=".xls,.xlsx" |
| 67 | :before-upload="beforeUpload" | 72 | :before-upload="beforeUpload" |
| 73 | + :on-remove="handleRemove" | ||
| 68 | > | 74 | > |
| 69 | <Button type="primary"> 选择 Excel 文件 </Button> | 75 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 70 | </Upload> | 76 | </Upload> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antdv_next/schema/views/modules/form_sub_normal.vue.vm
| @@ -26,6 +26,7 @@ import { | @@ -26,6 +26,7 @@ import { | ||
| 26 | CheckboxGroup, | 26 | CheckboxGroup, |
| 27 | DatePicker, | 27 | DatePicker, |
| 28 | Input, | 28 | Input, |
| 29 | + message, | ||
| 29 | RadioGroup, | 30 | RadioGroup, |
| 30 | Select, | 31 | Select, |
| 31 | #if ($selectOptionEnable) | 32 | #if ($selectOptionEnable) |
| @@ -77,26 +78,54 @@ const handleDelete = async (row: ${apiName}.${subSimpleClassName}) => { | @@ -77,26 +78,54 @@ const handleDelete = async (row: ${apiName}.${subSimpleClassName}) => { | ||
| 77 | await gridApi.grid.remove(row); | 78 | await gridApi.grid.remove(row); |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 81 | -defineExpose({ | ||
| 82 | - getData: (): ${apiName}.${subSimpleClassName}[] => { | ||
| 83 | - const data = gridApi.grid.getData() as ${apiName}.${subSimpleClassName}[]; | ||
| 84 | - const removeRecords = gridApi.grid.getRemoveRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 85 | - const insertRecords = gridApi.grid.getInsertRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 86 | - return data | ||
| 87 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 88 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 89 | - }, | ||
| 90 | -}); | 81 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 82 | +function getData(): ${apiName}.${subSimpleClassName}[] { | ||
| 83 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 84 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 85 | + return fullData.map((row) => | ||
| 86 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 87 | + ); | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +#set ($hasRequiredColumn = false) | ||
| 91 | +#foreach ($column in $subColumns) | ||
| 92 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 93 | +#set ($hasRequiredColumn = true) | ||
| 94 | +#end | ||
| 95 | +#end | ||
| 96 | +/** 校验子表必填字段 */ | ||
| 97 | +function validate(): boolean { | ||
| 98 | +#if ($hasRequiredColumn) | ||
| 99 | + for (const [index, row] of getData().entries()) { | ||
| 100 | +#foreach ($column in $subColumns) | ||
| 101 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 102 | + if ( | ||
| 103 | + row.${column.javaField} === null || | ||
| 104 | + row.${column.javaField} === undefined || | ||
| 105 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 106 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 107 | + ) { | ||
| 108 | + message.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 109 | + return false; | ||
| 110 | + } | ||
| 111 | +#end | ||
| 112 | +#end | ||
| 113 | + } | ||
| 114 | +#end | ||
| 115 | + return true; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +defineExpose({ getData, validate }); | ||
| 91 | 119 | ||
| 92 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 120 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 93 | watch( | 121 | watch( |
| 94 | () => props.${subJoinColumn.javaField}, | 122 | () => props.${subJoinColumn.javaField}, |
| 95 | async (val) => { | 123 | async (val) => { |
| 124 | + await nextTick(); | ||
| 96 | if (!val) { | 125 | if (!val) { |
| 126 | + await gridApi.grid.loadData([]); | ||
| 97 | return; | 127 | return; |
| 98 | } | 128 | } |
| 99 | - await nextTick(); | ||
| 100 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 129 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 101 | }, | 130 | }, |
| 102 | { immediate: true }, | 131 | { immediate: true }, |
| @@ -128,10 +157,11 @@ defineExpose({ | @@ -128,10 +157,11 @@ defineExpose({ | ||
| 128 | watch( | 157 | watch( |
| 129 | () => props.${subJoinColumn.javaField}, | 158 | () => props.${subJoinColumn.javaField}, |
| 130 | async (val) => { | 159 | async (val) => { |
| 160 | + await nextTick(); | ||
| 161 | + await formApi.resetForm(); | ||
| 131 | if (!val) { | 162 | if (!val) { |
| 132 | return; | 163 | return; |
| 133 | } | 164 | } |
| 134 | - await nextTick(); | ||
| 135 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 165 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 136 | }, | 166 | }, |
| 137 | { immediate: true }, | 167 | { immediate: true }, |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/form.vue.vm
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 2 | +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -9,7 +9,7 @@ import { Tinymce as RichTextarea } from '#/components/tinymce'; | @@ -9,7 +9,7 @@ import { Tinymce as RichTextarea } from '#/components/tinymce'; | ||
| 9 | import { ImageUpload, FileUpload } from "#/components/upload"; | 9 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 10 | import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus'; | 10 | import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus'; |
| 11 | #if($table.templateType == 2)## 树表需要导入这些 | 11 | #if($table.templateType == 2)## 树表需要导入这些 |
| 12 | -import { get${simpleClassName}List } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 12 | +import { get${simpleClassName}List } from '#/api/${table.moduleName}/${table.businessName}'; |
| 13 | import { handleTree } from '@vben/utils' | 13 | import { handleTree } from '@vben/utils' |
| 14 | #end | 14 | #end |
| 15 | ## 特殊:主子表专属逻辑 | 15 | ## 特殊:主子表专属逻辑 |
| @@ -23,7 +23,7 @@ import { handleTree } from '@vben/utils' | @@ -23,7 +23,7 @@ import { handleTree } from '@vben/utils' | ||
| 23 | 23 | ||
| 24 | import { computed, ref, reactive } from 'vue'; | 24 | import { computed, ref, reactive } from 'vue'; |
| 25 | import { $t } from '#/locales'; | 25 | import { $t } from '#/locales'; |
| 26 | -import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 26 | +import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 27 | 27 | ||
| 28 | const emit = defineEmits(['success']); | 28 | const emit = defineEmits(['success']); |
| 29 | 29 | ||
| @@ -111,7 +111,10 @@ const [Modal, modalApi] = useVbenModal({ | @@ -111,7 +111,10 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 111 | #set ($index = $foreach.count - 1) | 111 | #set ($index = $foreach.count - 1) |
| 112 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 112 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 113 | #if ($subTable.subJoinMany) ## 一对多 | 113 | #if ($subTable.subJoinMany) ## 一对多 |
| 114 | - ## TODO 列表值校验? | 114 | + if (!${subClassNameVar}FormRef.value?.validate()) { |
| 115 | + subTabsName.value = '${subClassNameVar}'; | ||
| 116 | + return; | ||
| 117 | + } | ||
| 115 | #else | 118 | #else |
| 116 | try { | 119 | try { |
| 117 | await ${subClassNameVar}FormRef.value?.validate() | 120 | await ${subClassNameVar}FormRef.value?.validate() |
| @@ -180,7 +183,7 @@ const [Modal, modalApi] = useVbenModal({ | @@ -180,7 +183,7 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 180 | 183 | ||
| 181 | <template> | 184 | <template> |
| 182 | <Modal :title="getTitle"> | 185 | <Modal :title="getTitle"> |
| 183 | - <el-form | 186 | + <ElForm |
| 184 | ref="formRef" | 187 | ref="formRef" |
| 185 | :model="formData" | 188 | :model="formData" |
| 186 | :rules="rules" | 189 | :rules="rules" |
| @@ -201,8 +204,8 @@ const [Modal, modalApi] = useVbenModal({ | @@ -201,8 +204,8 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 201 | #set ($dictMethod = "boolean") | 204 | #set ($dictMethod = "boolean") |
| 202 | #end | 205 | #end |
| 203 | #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id ) | 206 | #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id ) |
| 204 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 205 | - <el-tree-select | 207 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 208 | + <ElTreeSelect | ||
| 206 | v-model="formData.${javaField}" | 209 | v-model="formData.${javaField}" |
| 207 | :data="${classNameVar}Tree" | 210 | :data="${classNameVar}Tree" |
| 208 | #if ($treeNameColumn.javaField == "name") | 211 | #if ($treeNameColumn.javaField == "name") |
| @@ -222,100 +225,100 @@ const [Modal, modalApi] = useVbenModal({ | @@ -222,100 +225,100 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 222 | default-expand-all | 225 | default-expand-all |
| 223 | placeholder="请选择${comment}" | 226 | placeholder="请选择${comment}" |
| 224 | /> | 227 | /> |
| 225 | - </el-form-item> | 228 | + </ElFormItem> |
| 226 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 | 229 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 |
| 227 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 228 | - <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 229 | - </el-form-item> | 230 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 231 | + <ElInput v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 232 | + </ElFormItem> | ||
| 230 | #elseif($column.htmlType == "imageUpload")## 图片上传 | 233 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 231 | - <el-form-item label="${comment}" prop="${javaField}"> | 234 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 232 | <ImageUpload v-model="formData.${javaField}" /> | 235 | <ImageUpload v-model="formData.${javaField}" /> |
| 233 | - </el-form-item> | 236 | + </ElFormItem> |
| 234 | #elseif($column.htmlType == "fileUpload")## 文件上传 | 237 | #elseif($column.htmlType == "fileUpload")## 文件上传 |
| 235 | - <el-form-item label="${comment}" prop="${javaField}"> | 238 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 236 | <FileUpload v-model="formData.${javaField}" /> | 239 | <FileUpload v-model="formData.${javaField}" /> |
| 237 | - </el-form-item> | 240 | + </ElFormItem> |
| 238 | #elseif($column.htmlType == "editor")## 文本编辑器 | 241 | #elseif($column.htmlType == "editor")## 文本编辑器 |
| 239 | - <el-form-item label="${comment}" prop="${javaField}"> | 242 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 240 | <RichTextarea v-model="formData.${javaField}" height="500px" /> | 243 | <RichTextarea v-model="formData.${javaField}" height="500px" /> |
| 241 | - </el-form-item> | 244 | + </ElFormItem> |
| 242 | #elseif($column.htmlType == "select")## 下拉框 | 245 | #elseif($column.htmlType == "select")## 下拉框 |
| 243 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 244 | - <el-select v-model="formData.${javaField}" placeholder="请选择${comment}"> | 246 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 247 | + <ElSelect v-model="formData.${javaField}" placeholder="请选择${comment}"> | ||
| 245 | #if ("" != $dictType)## 有数据字典 | 248 | #if ("" != $dictType)## 有数据字典 |
| 246 | - <el-option | 249 | + <ElOption |
| 247 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 250 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 248 | :key="dict.value" | 251 | :key="dict.value" |
| 249 | :value="dict.value" | 252 | :value="dict.value" |
| 250 | :label="dict.label" | 253 | :label="dict.label" |
| 251 | /> | 254 | /> |
| 252 | #else##没数据字典 | 255 | #else##没数据字典 |
| 253 | - <el-option label="请选择字典生成" value="" /> | 256 | + <ElOption label="请选择字典生成" value="" /> |
| 254 | #end | 257 | #end |
| 255 | - </el-select> | ||
| 256 | - </el-form-item> | 258 | + </ElSelect> |
| 259 | + </ElFormItem> | ||
| 257 | #elseif($column.htmlType == "checkbox")## 多选框 | 260 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 258 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 259 | - <el-checkbox-group v-model="formData.${javaField}"> | 261 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 262 | + <ElCheckboxGroup v-model="formData.${javaField}"> | ||
| 260 | #if ("" != $dictType)## 有数据字典 | 263 | #if ("" != $dictType)## 有数据字典 |
| 261 | - <el-checkbox | 264 | + <ElCheckbox |
| 262 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 265 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 263 | :key="dict.value" | 266 | :key="dict.value" |
| 264 | - :label="dict.value" | 267 | + :value="dict.value" |
| 265 | > | 268 | > |
| 266 | {{ dict.label }} | 269 | {{ dict.label }} |
| 267 | - </el-checkbox> | 270 | + </ElCheckbox> |
| 268 | #else##没数据字典 | 271 | #else##没数据字典 |
| 269 | - <el-checkbox label="请选择字典生成" /> | 272 | + <ElCheckbox label="请选择字典生成" /> |
| 270 | #end | 273 | #end |
| 271 | - </el-checkbox-group> | ||
| 272 | - </el-form-item> | 274 | + </ElCheckboxGroup> |
| 275 | + </ElFormItem> | ||
| 273 | #elseif($column.htmlType == "radio")## 单选框 | 276 | #elseif($column.htmlType == "radio")## 单选框 |
| 274 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 275 | - <el-radio-group v-model="formData.${javaField}"> | 277 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 278 | + <ElRadioGroup v-model="formData.${javaField}"> | ||
| 276 | #if ("" != $dictType)## 有数据字典 | 279 | #if ("" != $dictType)## 有数据字典 |
| 277 | - <el-radio | 280 | + <ElRadio |
| 278 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 281 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 279 | :key="dict.value" | 282 | :key="dict.value" |
| 280 | - :label="dict.value" | 283 | + :value="dict.value" |
| 281 | > | 284 | > |
| 282 | {{ dict.label }} | 285 | {{ dict.label }} |
| 283 | - </el-radio> | 286 | + </ElRadio> |
| 284 | #else##没数据字典 | 287 | #else##没数据字典 |
| 285 | - <el-radio :label="1">请选择字典生成</el-radio> | 288 | + <ElRadio :label="1">请选择字典生成</ElRadio> |
| 286 | #end | 289 | #end |
| 287 | - </el-radio-group> | ||
| 288 | - </el-form-item> | 290 | + </ElRadioGroup> |
| 291 | + </ElFormItem> | ||
| 289 | #elseif($column.htmlType == "datetime")## 时间框 | 292 | #elseif($column.htmlType == "datetime")## 时间框 |
| 290 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 291 | - <el-date-picker | 293 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 294 | + <ElDatePicker | ||
| 292 | v-model="formData.${javaField}" | 295 | v-model="formData.${javaField}" |
| 293 | value-format="x" | 296 | value-format="x" |
| 294 | placeholder="选择${comment}" | 297 | placeholder="选择${comment}" |
| 295 | /> | 298 | /> |
| 296 | - </el-form-item> | 299 | + </ElFormItem> |
| 297 | #elseif($column.htmlType == "textarea")## 文本框 | 300 | #elseif($column.htmlType == "textarea")## 文本框 |
| 298 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 299 | - <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 300 | - </el-form-item> | 301 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 302 | + <ElInput v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 303 | + </ElFormItem> | ||
| 301 | #end | 304 | #end |
| 302 | #end | 305 | #end |
| 303 | #end | 306 | #end |
| 304 | - </el-form> | 307 | + </ElForm> |
| 305 | ## 特殊:主子表专属逻辑 | 308 | ## 特殊:主子表专属逻辑 |
| 306 | #if ( $table.templateType == 10 || $table.templateType == 12 ) | 309 | #if ( $table.templateType == 10 || $table.templateType == 12 ) |
| 307 | <!-- 子表的表单 --> | 310 | <!-- 子表的表单 --> |
| 308 | - <el-tabs v-model="subTabsName"> | 311 | + <ElTabs v-model="subTabsName"> |
| 309 | #foreach ($subTable in $subTables) | 312 | #foreach ($subTable in $subTables) |
| 310 | #set ($index = $foreach.count - 1) | 313 | #set ($index = $foreach.count - 1) |
| 311 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 314 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 312 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) | 315 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) |
| 313 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) | 316 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) |
| 314 | - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}"> | 317 | + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}"> |
| 315 | <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" /> | 318 | <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" /> |
| 316 | - </el-tab-pane> | 319 | + </ElTabPane> |
| 317 | #end | 320 | #end |
| 318 | - </el-tabs> | 321 | + </ElTabs> |
| 319 | #end | 322 | #end |
| 320 | </Modal> | 323 | </Modal> |
| 321 | </template> | 324 | </template> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/import.vue.vm
| @@ -47,6 +47,16 @@ function handleChange(file: any) { | @@ -47,6 +47,16 @@ function handleChange(file: any) { | ||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | +/** 移除文件 */ | ||
| 51 | +function handleRemove() { | ||
| 52 | + fileRef.value = null; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/** 超出文件数量 */ | ||
| 56 | +function handleExceed() { | ||
| 57 | + ElMessage.warning('只能选择一个文件,请先移除已选文件'); | ||
| 58 | +} | ||
| 59 | + | ||
| 50 | /** 下载导入模板 */ | 60 | /** 下载导入模板 */ |
| 51 | async function handleDownload() { | 61 | async function handleDownload() { |
| 52 | const data = await import${simpleClassName}Template(); | 62 | const data = await import${simpleClassName}Template(); |
| @@ -61,6 +71,8 @@ async function handleDownload() { | @@ -61,6 +71,8 @@ async function handleDownload() { | ||
| 61 | :limit="1" | 71 | :limit="1" |
| 62 | accept=".xls,.xlsx" | 72 | accept=".xls,.xlsx" |
| 63 | :on-change="handleChange" | 73 | :on-change="handleChange" |
| 74 | + :on-remove="handleRemove" | ||
| 75 | + :on-exceed="handleExceed" | ||
| 64 | :auto-upload="false" | 76 | :auto-upload="false" |
| 65 | > | 77 | > |
| 66 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> | 78 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/index.vue.vm
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 2 | +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -26,10 +26,10 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -26,10 +26,10 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 26 | import { $t } from '#/locales'; | 26 | import { $t } from '#/locales'; |
| 27 | #if (${table.templateType} == 2)## 树表接口 | 27 | #if (${table.templateType} == 2)## 树表接口 |
| 28 | import { handleTree,isEmpty } from '@vben/utils' | 28 | import { handleTree,isEmpty } from '@vben/utils' |
| 29 | -import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 29 | +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 30 | #else## 标准表接口 | 30 | #else## 标准表接口 |
| 31 | import { isEmpty } from '@vben/utils'; | 31 | import { isEmpty } from '@vben/utils'; |
| 32 | -import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 32 | +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 33 | #end | 33 | #end |
| 34 | #if ($importEnable) | 34 | #if ($importEnable) |
| 35 | import ${simpleClassName}Import from './modules/import-form.vue'; | 35 | import ${simpleClassName}Import from './modules/import-form.vue'; |
| @@ -65,12 +65,7 @@ const queryParams = reactive({ | @@ -65,12 +65,7 @@ const queryParams = reactive({ | ||
| 65 | #end | 65 | #end |
| 66 | #foreach ($column in $columns) | 66 | #foreach ($column in $columns) |
| 67 | #if ($column.listOperation) | 67 | #if ($column.listOperation) |
| 68 | - #if ($column.listOperationCondition != 'BETWEEN') | ||
| 69 | - $column.javaField: undefined, | ||
| 70 | - #end | ||
| 71 | - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 72 | - $column.javaField: undefined, | ||
| 73 | - #end | 68 | + $column.javaField: undefined, |
| 74 | #end | 69 | #end |
| 75 | #end | 70 | #end |
| 76 | }) | 71 | }) |
| @@ -195,7 +190,17 @@ function handleRowCheckboxChange({ | @@ -195,7 +190,17 @@ function handleRowCheckboxChange({ | ||
| 195 | async function handleExport() { | 190 | async function handleExport() { |
| 196 | try { | 191 | try { |
| 197 | exportLoading.value = true; | 192 | exportLoading.value = true; |
| 198 | - const data = await export${simpleClassName}(queryParams); | 193 | + const params = cloneDeep(queryParams) as any; |
| 194 | + #foreach ($column in $columns) | ||
| 195 | + #if ($column.listOperation) | ||
| 196 | + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN") | ||
| 197 | + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) { | ||
| 198 | + params.${column.javaField} = (params.${column.javaField} as string[]).join(','); | ||
| 199 | + } | ||
| 200 | + #end | ||
| 201 | + #end | ||
| 202 | + #end | ||
| 203 | + const data = await export${simpleClassName}(params); | ||
| 199 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); | 204 | downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data }); |
| 200 | }finally { | 205 | }finally { |
| 201 | exportLoading.value = false; | 206 | exportLoading.value = false; |
| @@ -228,7 +233,7 @@ onMounted(() => { | @@ -228,7 +233,7 @@ onMounted(() => { | ||
| 228 | 233 | ||
| 229 | <ContentWrap v-if="!hiddenSearchBar"> | 234 | <ContentWrap v-if="!hiddenSearchBar"> |
| 230 | <!-- 搜索工作栏 --> | 235 | <!-- 搜索工作栏 --> |
| 231 | - <el-form | 236 | + <ElForm |
| 232 | :model="queryParams" | 237 | :model="queryParams" |
| 233 | ref="queryFormRef" | 238 | ref="queryFormRef" |
| 234 | inline | 239 | inline |
| @@ -247,49 +252,49 @@ onMounted(() => { | @@ -247,49 +252,49 @@ onMounted(() => { | ||
| 247 | #set ($dictMethod = "boolean") | 252 | #set ($dictMethod = "boolean") |
| 248 | #end | 253 | #end |
| 249 | #if ($column.htmlType == "input") | 254 | #if ($column.htmlType == "input") |
| 250 | - <el-form-item label="${comment}"> | ||
| 251 | - <el-input | 255 | + <ElFormItem label="${comment}"> |
| 256 | + <ElInput | ||
| 252 | v-model="queryParams.${javaField}" | 257 | v-model="queryParams.${javaField}" |
| 253 | placeholder="请输入${comment}" | 258 | placeholder="请输入${comment}" |
| 254 | clearable | 259 | clearable |
| 255 | @keyup.enter="handleQuery" | 260 | @keyup.enter="handleQuery" |
| 256 | class="!w-[240px]" | 261 | class="!w-[240px]" |
| 257 | /> | 262 | /> |
| 258 | - </el-form-item> | 263 | + </ElFormItem> |
| 259 | #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") | 264 | #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") |
| 260 | - <el-form-item label="${comment}"> | ||
| 261 | - <el-select | 265 | + <ElFormItem label="${comment}"> |
| 266 | + <ElSelect | ||
| 262 | v-model="queryParams.${javaField}" | 267 | v-model="queryParams.${javaField}" |
| 263 | placeholder="请选择${comment}" | 268 | placeholder="请选择${comment}" |
| 264 | clearable | 269 | clearable |
| 265 | class="!w-[240px]" | 270 | class="!w-[240px]" |
| 266 | > | 271 | > |
| 267 | #if ("" != $dictType)## 设置了 dictType 数据字典的情况 | 272 | #if ("" != $dictType)## 设置了 dictType 数据字典的情况 |
| 268 | - <el-option | 273 | + <ElOption |
| 269 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 274 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 270 | :key="dict.value" | 275 | :key="dict.value" |
| 271 | :value="dict.value" | 276 | :value="dict.value" |
| 272 | :label="dict.label" | 277 | :label="dict.label" |
| 273 | /> | 278 | /> |
| 274 | #else## 未设置 dictType 数据字典的情况 | 279 | #else## 未设置 dictType 数据字典的情况 |
| 275 | - <el-option label="请选择字典生成" value="" /> | 280 | + <ElOption label="请选择字典生成" value="" /> |
| 276 | #end | 281 | #end |
| 277 | - </el-select> | ||
| 278 | - </el-form-item> | 282 | + </ElSelect> |
| 283 | + </ElFormItem> | ||
| 279 | #elseif($column.htmlType == "datetime") | 284 | #elseif($column.htmlType == "datetime") |
| 280 | #if ($column.listOperationCondition != "BETWEEN")## 非范围 | 285 | #if ($column.listOperationCondition != "BETWEEN")## 非范围 |
| 281 | - <el-form-item label="${comment}"> | ||
| 282 | - <el-date-picker | 286 | + <ElFormItem label="${comment}"> |
| 287 | + <ElDatePicker | ||
| 283 | v-model="queryParams.${javaField}" | 288 | v-model="queryParams.${javaField}" |
| 284 | value-format="YYYY-MM-DD" | 289 | value-format="YYYY-MM-DD" |
| 285 | placeholder="选择${comment}" | 290 | placeholder="选择${comment}" |
| 286 | clearable | 291 | clearable |
| 287 | class="!w-[240px]" | 292 | class="!w-[240px]" |
| 288 | /> | 293 | /> |
| 289 | - </el-form-item> | 294 | + </ElFormItem> |
| 290 | #else## 范围 | 295 | #else## 范围 |
| 291 | - <el-form-item label="${comment}"> | ||
| 292 | - <el-date-picker | 296 | + <ElFormItem label="${comment}"> |
| 297 | + <ElDatePicker | ||
| 293 | v-model="queryParams.${javaField}" | 298 | v-model="queryParams.${javaField}" |
| 294 | type="daterange" | 299 | type="daterange" |
| 295 | value-format="YYYY-MM-DD" | 300 | value-format="YYYY-MM-DD" |
| @@ -298,33 +303,33 @@ onMounted(() => { | @@ -298,33 +303,33 @@ onMounted(() => { | ||
| 298 | end-placeholder="结束日期" | 303 | end-placeholder="结束日期" |
| 299 | class="!w-[240px]" | 304 | class="!w-[240px]" |
| 300 | /> | 305 | /> |
| 301 | - </el-form-item> | 306 | + </ElFormItem> |
| 302 | #end | 307 | #end |
| 303 | #end | 308 | #end |
| 304 | #end | 309 | #end |
| 305 | #end | 310 | #end |
| 306 | - <el-form-item> | ||
| 307 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 308 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 311 | + <ElFormItem> |
| 312 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 313 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 309 | 搜索 | 314 | 搜索 |
| 310 | - </el-button> | ||
| 311 | - </el-form-item> | ||
| 312 | - </el-form> | 315 | + </ElButton> |
| 316 | + </ElFormItem> | ||
| 317 | + </ElForm> | ||
| 313 | </ContentWrap> | 318 | </ContentWrap> |
| 314 | 319 | ||
| 315 | <!-- 列表 --> | 320 | <!-- 列表 --> |
| 316 | <ContentWrap title="${table.classComment}"> | 321 | <ContentWrap title="${table.classComment}"> |
| 317 | <template #extra> | 322 | <template #extra> |
| 318 | - <TableToolbar | 323 | + <VbenVxeTableToolbar |
| 319 | ref="tableToolbarRef" | 324 | ref="tableToolbarRef" |
| 320 | v-model:hidden-search="hiddenSearchBar" | 325 | v-model:hidden-search="hiddenSearchBar" |
| 321 | > | 326 | > |
| 322 | #if (${table.templateType} == 2) | 327 | #if (${table.templateType} == 2) |
| 323 | - <el-button @click="handleExpand" class="mr-2"> | 328 | + <ElButton @click="handleExpand" class="mr-2"> |
| 324 | {{ isExpanded ? '收缩' : '展开' }} | 329 | {{ isExpanded ? '收缩' : '展开' }} |
| 325 | - </el-button> | 330 | + </ElButton> |
| 326 | #end | 331 | #end |
| 327 | - <el-button | 332 | + <ElButton |
| 328 | class="ml-2" | 333 | class="ml-2" |
| 329 | :icon="h(Plus)" | 334 | :icon="h(Plus)" |
| 330 | type="primary" | 335 | type="primary" |
| @@ -332,18 +337,18 @@ onMounted(() => { | @@ -332,18 +337,18 @@ onMounted(() => { | ||
| 332 | v-access:code="['${permissionPrefix}:create']" | 337 | v-access:code="['${permissionPrefix}:create']" |
| 333 | > | 338 | > |
| 334 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} | 339 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} |
| 335 | - </el-button> | 340 | + </ElButton> |
| 336 | #if ($importEnable) | 341 | #if ($importEnable) |
| 337 | - <el-button | 342 | + <ElButton |
| 338 | class="ml-2" | 343 | class="ml-2" |
| 339 | type="primary" | 344 | type="primary" |
| 340 | @click="handleImport" | 345 | @click="handleImport" |
| 341 | v-access:code="['${permissionPrefix}:import']" | 346 | v-access:code="['${permissionPrefix}:import']" |
| 342 | > | 347 | > |
| 343 | 导入 | 348 | 导入 |
| 344 | - </el-button> | 349 | + </ElButton> |
| 345 | #end | 350 | #end |
| 346 | - <el-button | 351 | + <ElButton |
| 347 | :icon="h(Download)" | 352 | :icon="h(Download)" |
| 348 | type="primary" | 353 | type="primary" |
| 349 | class="ml-2" | 354 | class="ml-2" |
| @@ -352,9 +357,9 @@ onMounted(() => { | @@ -352,9 +357,9 @@ onMounted(() => { | ||
| 352 | v-access:code="['${permissionPrefix}:export']" | 357 | v-access:code="['${permissionPrefix}:export']" |
| 353 | > | 358 | > |
| 354 | {{ $t('ui.actionTitle.export') }} | 359 | {{ $t('ui.actionTitle.export') }} |
| 355 | - </el-button> | 360 | + </ElButton> |
| 356 | #if ($table.templateType != 2 && $deleteBatchEnable) | 361 | #if ($table.templateType != 2 && $deleteBatchEnable) |
| 357 | - <el-button | 362 | + <ElButton |
| 358 | :icon="h(Trash2)" | 363 | :icon="h(Trash2)" |
| 359 | type="danger" | 364 | type="danger" |
| 360 | class="ml-2" | 365 | class="ml-2" |
| @@ -363,11 +368,11 @@ onMounted(() => { | @@ -363,11 +368,11 @@ onMounted(() => { | ||
| 363 | v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']" | 368 | v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']" |
| 364 | > | 369 | > |
| 365 | 批量删除 | 370 | 批量删除 |
| 366 | - </el-button> | 371 | + </ElButton> |
| 367 | #end | 372 | #end |
| 368 | - </TableToolbar> | 373 | + </VbenVxeTableToolbar> |
| 369 | </template> | 374 | </template> |
| 370 | - <vxe-table | 375 | + <VxeTable |
| 371 | ref="tableRef" | 376 | ref="tableRef" |
| 372 | :data="list" | 377 | :data="list" |
| 373 | #if ( $table.templateType == 2 ) | 378 | #if ( $table.templateType == 2 ) |
| @@ -395,27 +400,27 @@ onMounted(() => { | @@ -395,27 +400,27 @@ onMounted(() => { | ||
| 395 | #end | 400 | #end |
| 396 | > | 401 | > |
| 397 | #if ($table.templateType != 2 && $deleteBatchEnable) | 402 | #if ($table.templateType != 2 && $deleteBatchEnable) |
| 398 | - <vxe-column type="checkbox" width="40"></vxe-column> | 403 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 399 | #end | 404 | #end |
| 400 | ## 特殊:主子表专属逻辑 | 405 | ## 特殊:主子表专属逻辑 |
| 401 | #if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 ) | 406 | #if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 ) |
| 402 | <!-- 子表的列表 --> | 407 | <!-- 子表的列表 --> |
| 403 | - <vxe-column type="expand" width="60"> | 408 | + <VxeColumn type="expand" width="60"> |
| 404 | <template #content="{ row }"> | 409 | <template #content="{ row }"> |
| 405 | <!-- 子表的表单 --> | 410 | <!-- 子表的表单 --> |
| 406 | - <el-tabs v-model="subTabsName" class="mx-8"> | 411 | + <ElTabs v-model="subTabsName" class="mx-8"> |
| 407 | #foreach ($subTable in $subTables) | 412 | #foreach ($subTable in $subTables) |
| 408 | #set ($index = $foreach.count - 1) | 413 | #set ($index = $foreach.count - 1) |
| 409 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 414 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 410 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) | 415 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) |
| 411 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) | 416 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) |
| 412 | - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}"> | 417 | + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}"> |
| 413 | <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" /> | 418 | <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" /> |
| 414 | - </el-tab-pane> | 419 | + </ElTabPane> |
| 415 | #end | 420 | #end |
| 416 | - </el-tabs> | 421 | + </ElTabs> |
| 417 | </template> | 422 | </template> |
| 418 | - </vxe-column> | 423 | + </VxeColumn> |
| 419 | #end | 424 | #end |
| 420 | #foreach($column in $columns) | 425 | #foreach($column in $columns) |
| 421 | #if ($column.listOperationResult) | 426 | #if ($column.listOperationResult) |
| @@ -424,28 +429,28 @@ onMounted(() => { | @@ -424,28 +429,28 @@ onMounted(() => { | ||
| 424 | #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) | 429 | #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) |
| 425 | #set ($comment=$column.columnComment) | 430 | #set ($comment=$column.columnComment) |
| 426 | #if ($column.javaType == "LocalDateTime")## 时间类型 | 431 | #if ($column.javaType == "LocalDateTime")## 时间类型 |
| 427 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 432 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 428 | <template #default="{row}"> | 433 | <template #default="{row}"> |
| 429 | {{formatDateTime(row.${javaField})}} | 434 | {{formatDateTime(row.${javaField})}} |
| 430 | </template> | 435 | </template> |
| 431 | - </vxe-column> | 436 | + </VxeColumn> |
| 432 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 | 437 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 |
| 433 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 438 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 434 | <template #default="{row}"> | 439 | <template #default="{row}"> |
| 435 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> | 440 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> |
| 436 | </template> | 441 | </template> |
| 437 | - </vxe-column> | 442 | + </VxeColumn> |
| 438 | #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField) | 443 | #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField) |
| 439 | - <vxe-column field="${javaField}" title="${comment}" align="center" tree-node/> | 444 | + <VxeColumn field="${javaField}" title="${comment}" align="center" tree-node/> |
| 440 | #else | 445 | #else |
| 441 | - <vxe-column field="${javaField}" title="${comment}" align="center" /> | 446 | + <VxeColumn field="${javaField}" title="${comment}" align="center" /> |
| 442 | #end | 447 | #end |
| 443 | #end | 448 | #end |
| 444 | #end | 449 | #end |
| 445 | - <vxe-column field="operation" title="操作" align="center"> | 450 | + <VxeColumn field="operation" title="操作" align="center"> |
| 446 | <template #default="{row}"> | 451 | <template #default="{row}"> |
| 447 | #if ( $table.templateType == 2 ) | 452 | #if ( $table.templateType == 2 ) |
| 448 | - <el-button | 453 | + <ElButton |
| 449 | size="small" | 454 | size="small" |
| 450 | type="primary" | 455 | type="primary" |
| 451 | link | 456 | link |
| @@ -453,9 +458,9 @@ onMounted(() => { | @@ -453,9 +458,9 @@ onMounted(() => { | ||
| 453 | v-access:code="['${permissionPrefix}:create']" | 458 | v-access:code="['${permissionPrefix}:create']" |
| 454 | > | 459 | > |
| 455 | 新增下级 | 460 | 新增下级 |
| 456 | - </el-button> | 461 | + </ElButton> |
| 457 | #end | 462 | #end |
| 458 | - <el-button | 463 | + <ElButton |
| 459 | size="small" | 464 | size="small" |
| 460 | type="primary" | 465 | type="primary" |
| 461 | link | 466 | link |
| @@ -463,8 +468,8 @@ onMounted(() => { | @@ -463,8 +468,8 @@ onMounted(() => { | ||
| 463 | v-access:code="['${permissionPrefix}:update']" | 468 | v-access:code="['${permissionPrefix}:update']" |
| 464 | > | 469 | > |
| 465 | {{ $t('ui.actionTitle.edit') }} | 470 | {{ $t('ui.actionTitle.edit') }} |
| 466 | - </el-button> | ||
| 467 | - <el-button | 471 | + </ElButton> |
| 472 | + <ElButton | ||
| 468 | size="small" | 473 | size="small" |
| 469 | type="danger" | 474 | type="danger" |
| 470 | link | 475 | link |
| @@ -476,14 +481,14 @@ onMounted(() => { | @@ -476,14 +481,14 @@ onMounted(() => { | ||
| 476 | v-access:code="['${permissionPrefix}:delete']" | 481 | v-access:code="['${permissionPrefix}:delete']" |
| 477 | > | 482 | > |
| 478 | {{ $t('ui.actionTitle.delete') }} | 483 | {{ $t('ui.actionTitle.delete') }} |
| 479 | - </el-button> | 484 | + </ElButton> |
| 480 | </template> | 485 | </template> |
| 481 | - </vxe-column> | ||
| 482 | - </vxe-table> | 486 | + </VxeColumn> |
| 487 | + </VxeTable> | ||
| 483 | #if ( $table.templateType != 2 ) | 488 | #if ( $table.templateType != 2 ) |
| 484 | <!-- 分页 --> | 489 | <!-- 分页 --> |
| 485 | <div class="mt-2 flex justify-end"> | 490 | <div class="mt-2 flex justify-end"> |
| 486 | - <el-pagination | 491 | + <ElPagination |
| 487 | :total="total" | 492 | :total="total" |
| 488 | v-model:current-page="queryParams.pageNo" | 493 | v-model:current-page="queryParams.pageNo" |
| 489 | v-model:page-size="queryParams.pageSize" | 494 | v-model:page-size="queryParams.pageSize" |
| @@ -498,17 +503,17 @@ onMounted(() => { | @@ -498,17 +503,17 @@ onMounted(() => { | ||
| 498 | #if ($table.templateType == 11) ## erp情况 | 503 | #if ($table.templateType == 11) ## erp情况 |
| 499 | <ContentWrap> | 504 | <ContentWrap> |
| 500 | <!-- 子表的表单 --> | 505 | <!-- 子表的表单 --> |
| 501 | - <el-tabs v-model="subTabsName"> | 506 | + <ElTabs v-model="subTabsName"> |
| 502 | #foreach ($subTable in $subTables) | 507 | #foreach ($subTable in $subTables) |
| 503 | #set ($index = $foreach.count - 1) | 508 | #set ($index = $foreach.count - 1) |
| 504 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 509 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 505 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) | 510 | #set ($subSimpleClassName = $subSimpleClassNames.get($index)) |
| 506 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) | 511 | #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) |
| 507 | - <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}"> | 512 | + <ElTabPane name="$subClassNameVar" label="${subTable.classComment}"> |
| 508 | <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" /> | 513 | <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" /> |
| 509 | - </el-tab-pane> | 514 | + </ElTabPane> |
| 510 | #end | 515 | #end |
| 511 | - </el-tabs> | 516 | + </ElTabs> |
| 512 | </ContentWrap> | 517 | </ContentWrap> |
| 513 | #end | 518 | #end |
| 514 | </Page> | 519 | </Page> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_erp.vue.vm
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 | 3 | #set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 |
| 4 | #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) | 4 | #set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) |
| 5 | <script lang="ts" setup> | 5 | <script lang="ts" setup> |
| 6 | - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 6 | + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}'; |
| 7 | import type { FormRules } from 'element-plus'; | 7 | import type { FormRules } from 'element-plus'; |
| 8 | 8 | ||
| 9 | import { computed, ref, reactive } from 'vue'; | 9 | import { computed, ref, reactive } from 'vue'; |
| @@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
| 17 | 17 | ||
| 18 | import { $t } from '#/locales'; | 18 | import { $t } from '#/locales'; |
| 19 | 19 | ||
| 20 | - import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 20 | + import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 21 | 21 | ||
| 22 | const emit = defineEmits(['success']); | 22 | const emit = defineEmits(['success']); |
| 23 | const getTitle = computed(() => { | 23 | const getTitle = computed(() => { |
| @@ -107,7 +107,7 @@ | @@ -107,7 +107,7 @@ | ||
| 107 | 107 | ||
| 108 | <template> | 108 | <template> |
| 109 | <Modal :title="getTitle"> | 109 | <Modal :title="getTitle"> |
| 110 | - <el-form | 110 | + <ElForm |
| 111 | ref="formRef" | 111 | ref="formRef" |
| 112 | :model="formData" | 112 | :model="formData" |
| 113 | :rules="rules" | 113 | :rules="rules" |
| @@ -128,83 +128,83 @@ | @@ -128,83 +128,83 @@ | ||
| 128 | #set ($dictMethod = "boolean") | 128 | #set ($dictMethod = "boolean") |
| 129 | #end | 129 | #end |
| 130 | #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 | 130 | #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 |
| 131 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 132 | - <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 133 | - </el-form-item> | 131 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 132 | + <ElInput v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 133 | + </ElFormItem> | ||
| 134 | #elseif($column.htmlType == "imageUpload")## 图片上传 | 134 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 135 | - <el-form-item label="${comment}" prop="${javaField}"> | 135 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 136 | <ImageUpload v-model="formData.${javaField}" /> | 136 | <ImageUpload v-model="formData.${javaField}" /> |
| 137 | - </el-form-item> | 137 | + </ElFormItem> |
| 138 | #elseif($column.htmlType == "fileUpload")## 文件上传 | 138 | #elseif($column.htmlType == "fileUpload")## 文件上传 |
| 139 | - <el-form-item label="${comment}" prop="${javaField}"> | 139 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 140 | <FileUpload v-model="formData.${javaField}" /> | 140 | <FileUpload v-model="formData.${javaField}" /> |
| 141 | - </el-form-item> | 141 | + </ElFormItem> |
| 142 | #elseif($column.htmlType == "editor")## 文本编辑器 | 142 | #elseif($column.htmlType == "editor")## 文本编辑器 |
| 143 | - <el-form-item label="${comment}" prop="${javaField}"> | 143 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 144 | <RichTextarea v-model="formData.${javaField}" height="500px" /> | 144 | <RichTextarea v-model="formData.${javaField}" height="500px" /> |
| 145 | - </el-form-item> | 145 | + </ElFormItem> |
| 146 | #elseif($column.htmlType == "select")## 下拉框 | 146 | #elseif($column.htmlType == "select")## 下拉框 |
| 147 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 148 | - <el-select v-model="formData.${javaField}" placeholder="请选择${comment}"> | 147 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 148 | + <ElSelect v-model="formData.${javaField}" placeholder="请选择${comment}"> | ||
| 149 | #if ("" != $dictType)## 有数据字典 | 149 | #if ("" != $dictType)## 有数据字典 |
| 150 | - <el-option | 150 | + <ElOption |
| 151 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 151 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 152 | :key="dict.value" | 152 | :key="dict.value" |
| 153 | :value="dict.value" | 153 | :value="dict.value" |
| 154 | :label="dict.label" | 154 | :label="dict.label" |
| 155 | /> | 155 | /> |
| 156 | #else##没数据字典 | 156 | #else##没数据字典 |
| 157 | - <el-option label="请选择字典生成" value="" /> | 157 | + <ElOption label="请选择字典生成" value="" /> |
| 158 | #end | 158 | #end |
| 159 | - </el-select> | ||
| 160 | - </el-form-item> | 159 | + </ElSelect> |
| 160 | + </ElFormItem> | ||
| 161 | #elseif($column.htmlType == "checkbox")## 多选框 | 161 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 162 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 163 | - <el-checkbox-group v-model="formData.${javaField}"> | 162 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 163 | + <ElCheckboxGroup v-model="formData.${javaField}"> | ||
| 164 | #if ("" != $dictType)## 有数据字典 | 164 | #if ("" != $dictType)## 有数据字典 |
| 165 | - <el-checkbox | 165 | + <ElCheckbox |
| 166 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 166 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 167 | :key="dict.value" | 167 | :key="dict.value" |
| 168 | - :label="dict.value" | 168 | + :value="dict.value" |
| 169 | > | 169 | > |
| 170 | {{ dict.label }} | 170 | {{ dict.label }} |
| 171 | - </el-checkbox> | 171 | + </ElCheckbox> |
| 172 | #else##没数据字典 | 172 | #else##没数据字典 |
| 173 | - <el-checkbox label="请选择字典生成" /> | 173 | + <ElCheckbox label="请选择字典生成" /> |
| 174 | #end | 174 | #end |
| 175 | - </el-checkbox-group> | ||
| 176 | - </el-form-item> | 175 | + </ElCheckboxGroup> |
| 176 | + </ElFormItem> | ||
| 177 | #elseif($column.htmlType == "radio")## 单选框 | 177 | #elseif($column.htmlType == "radio")## 单选框 |
| 178 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 179 | - <el-radio-group v-model="formData.${javaField}"> | 178 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 179 | + <ElRadioGroup v-model="formData.${javaField}"> | ||
| 180 | #if ("" != $dictType)## 有数据字典 | 180 | #if ("" != $dictType)## 有数据字典 |
| 181 | - <el-radio | 181 | + <ElRadio |
| 182 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 182 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 183 | :key="dict.value" | 183 | :key="dict.value" |
| 184 | - :label="dict.value" | 184 | + :value="dict.value" |
| 185 | > | 185 | > |
| 186 | {{ dict.label }} | 186 | {{ dict.label }} |
| 187 | - </el-radio> | 187 | + </ElRadio> |
| 188 | #else##没数据字典 | 188 | #else##没数据字典 |
| 189 | - <el-radio :label="1">请选择字典生成</el-radio> | 189 | + <ElRadio :label="1">请选择字典生成</ElRadio> |
| 190 | #end | 190 | #end |
| 191 | - </el-radio-group> | ||
| 192 | - </el-form-item> | 191 | + </ElRadioGroup> |
| 192 | + </ElFormItem> | ||
| 193 | #elseif($column.htmlType == "datetime")## 时间框 | 193 | #elseif($column.htmlType == "datetime")## 时间框 |
| 194 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 195 | - <el-date-picker | 194 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 195 | + <ElDatePicker | ||
| 196 | v-model="formData.${javaField}" | 196 | v-model="formData.${javaField}" |
| 197 | value-format="x" | 197 | value-format="x" |
| 198 | placeholder="选择${comment}" | 198 | placeholder="选择${comment}" |
| 199 | /> | 199 | /> |
| 200 | - </el-form-item> | 200 | + </ElFormItem> |
| 201 | #elseif($column.htmlType == "textarea")## 文本框 | 201 | #elseif($column.htmlType == "textarea")## 文本框 |
| 202 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 203 | - <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 204 | - </el-form-item> | 202 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 203 | + <ElInput v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 204 | + </ElFormItem> | ||
| 205 | #end | 205 | #end |
| 206 | #end | 206 | #end |
| 207 | #end | 207 | #end |
| 208 | - </el-form> | 208 | + </ElForm> |
| 209 | </Modal> | 209 | </Modal> |
| 210 | </template> | 210 | </template> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_normal.vue.vm
| @@ -5,26 +5,61 @@ | @@ -5,26 +5,61 @@ | ||
| 5 | #set ($subClassNameVar = $subClassNameVars.get($subIndex)) | 5 | #set ($subClassNameVar = $subClassNameVars.get($subIndex)) |
| 6 | #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 | 6 | #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 |
| 7 | <script lang="ts" setup> | 7 | <script lang="ts" setup> |
| 8 | -import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 8 | +#if ($subTable.subJoinMany) |
| 9 | +import type { VxeTableInstance } from '#/adapter/vxe-table'; | ||
| 10 | +#else | ||
| 11 | +import type { FormRules } from 'element-plus'; | ||
| 12 | +#end | ||
| 13 | +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}'; | ||
| 9 | 14 | ||
| 10 | -import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue'; | 15 | +#if ($subTable.subJoinMany) |
| 16 | +import { ref, watch } from 'vue'; | ||
| 17 | +#else | ||
| 18 | +import { nextTick, reactive, ref, watch } from 'vue'; | ||
| 19 | +#end | ||
| 11 | 20 | ||
| 12 | import { DICT_TYPE } from '@vben/constants'; | 21 | import { DICT_TYPE } from '@vben/constants'; |
| 13 | import { getDictOptions } from '@vben/hooks'; | 22 | import { getDictOptions } from '@vben/hooks'; |
| 23 | +#if ($subTable.subJoinMany) | ||
| 24 | +import { Plus } from '@vben/icons'; | ||
| 25 | +#end | ||
| 14 | 26 | ||
| 15 | -import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus'; | ||
| 16 | -import { $t } from '#/locales'; | 27 | +#set ($hasCheckbox = false) |
| 28 | +#foreach ($column in $subColumns) | ||
| 29 | +#if (($column.createOperation || $column.updateOperation) && $column.id != $subJoinColumn.id && $column.htmlType == "checkbox") | ||
| 30 | +#set ($hasCheckbox = true) | ||
| 31 | +#end | ||
| 32 | +#end | ||
| 33 | +import { | ||
| 34 | +#if ($subTable.subJoinMany) | ||
| 35 | + ElButton, | ||
| 36 | +#else | ||
| 37 | + ElForm, | ||
| 38 | + ElFormItem, | ||
| 39 | +#end | ||
| 40 | +#if ($hasCheckbox) | ||
| 41 | + ElCheckbox, | ||
| 42 | + ElCheckboxGroup, | ||
| 43 | +#end | ||
| 44 | + ElDatePicker, | ||
| 45 | + ElInput, | ||
| 46 | +#if ($subTable.subJoinMany) | ||
| 47 | + ElMessage, | ||
| 48 | +#end | ||
| 49 | + ElOption, | ||
| 50 | + ElRadio, | ||
| 51 | + ElRadioGroup, | ||
| 52 | + ElSelect, | ||
| 53 | +} from 'element-plus'; | ||
| 17 | 54 | ||
| 18 | #if ($subTable.subJoinMany) ## 一对多 | 55 | #if ($subTable.subJoinMany) ## 一对多 |
| 19 | -import type { VxeTableInstance } from '#/adapter/vxe-table'; | ||
| 20 | -import { Plus } from "@vben/icons"; | ||
| 21 | import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | 56 | import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; |
| 22 | -import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 57 | +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 23 | #else | 58 | #else |
| 24 | -import type { FormRules } from 'element-plus'; | ||
| 25 | import { Tinymce as RichTextarea } from '#/components/tinymce'; | 59 | import { Tinymce as RichTextarea } from '#/components/tinymce'; |
| 26 | -import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 60 | +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 27 | #end | 61 | #end |
| 62 | +import { $t } from '#/locales'; | ||
| 28 | 63 | ||
| 29 | const props = defineProps<{ | 64 | const props = defineProps<{ |
| 30 | ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段) | 65 | ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段) |
| @@ -43,24 +78,54 @@ async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | @@ -43,24 +78,54 @@ async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) { | ||
| 43 | await tableRef.value?.remove(row); | 78 | await tableRef.value?.remove(row); |
| 44 | } | 79 | } |
| 45 | 80 | ||
| 46 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 47 | -defineExpose({ | ||
| 48 | - getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => { | ||
| 49 | - const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 50 | - const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 51 | - const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[]; | ||
| 52 | - return [ | ||
| 53 | - ...data.filter( | ||
| 54 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 55 | - ), | ||
| 56 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 57 | - }, | ||
| 58 | -}); | 81 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 82 | +function getData(): ${simpleClassName}Api.${subSimpleClassName}[] { | ||
| 83 | + const table = tableRef.value; | ||
| 84 | + if (!table) { | ||
| 85 | + return []; | ||
| 86 | + } | ||
| 87 | + const { fullData } = table.getTableData(); | ||
| 88 | + const inserted = new Set(table.getInsertRecords()); | ||
| 89 | + return fullData.map((row) => | ||
| 90 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 91 | + ); | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +#set ($hasRequiredColumn = false) | ||
| 95 | +#foreach ($column in $subColumns) | ||
| 96 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 97 | +#set ($hasRequiredColumn = true) | ||
| 98 | +#end | ||
| 99 | +#end | ||
| 100 | +/** 校验子表必填字段 */ | ||
| 101 | +function validate(): boolean { | ||
| 102 | +#if ($hasRequiredColumn) | ||
| 103 | + for (const [index, row] of getData().entries()) { | ||
| 104 | +#foreach ($column in $subColumns) | ||
| 105 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 106 | + if ( | ||
| 107 | + row.${column.javaField} === null || | ||
| 108 | + row.${column.javaField} === undefined || | ||
| 109 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 110 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 111 | + ) { | ||
| 112 | + ElMessage.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 113 | + return false; | ||
| 114 | + } | ||
| 115 | +#end | ||
| 116 | +#end | ||
| 117 | + } | ||
| 118 | +#end | ||
| 119 | + return true; | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +defineExpose({ getData, validate }); | ||
| 59 | 123 | ||
| 60 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 124 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 61 | watch( | 125 | watch( |
| 62 | () => props.${subJoinColumn.javaField}, | 126 | () => props.${subJoinColumn.javaField}, |
| 63 | async (val) => { | 127 | async (val) => { |
| 128 | + list.value = []; | ||
| 64 | if (!val) { | 129 | if (!val) { |
| 65 | return; | 130 | return; |
| 66 | } | 131 | } |
| @@ -99,6 +164,17 @@ defineExpose({ | @@ -99,6 +164,17 @@ defineExpose({ | ||
| 99 | watch( | 164 | watch( |
| 100 | () => props.${subJoinColumn.javaField}, | 165 | () => props.${subJoinColumn.javaField}, |
| 101 | async (val) => { | 166 | async (val) => { |
| 167 | + formData.value = { | ||
| 168 | +#foreach ($column in $subColumns) | ||
| 169 | +#if ($column.createOperation || $column.updateOperation) | ||
| 170 | +#if ($column.htmlType == "checkbox") | ||
| 171 | + $column.javaField: [], | ||
| 172 | +#else | ||
| 173 | + $column.javaField: undefined, | ||
| 174 | +#end | ||
| 175 | +#end | ||
| 176 | +#end | ||
| 177 | + }; | ||
| 102 | if (!val) { | 178 | if (!val) { |
| 103 | return; | 179 | return; |
| 104 | } | 180 | } |
| @@ -112,10 +188,11 @@ watch( | @@ -112,10 +188,11 @@ watch( | ||
| 112 | 188 | ||
| 113 | <template> | 189 | <template> |
| 114 | #if ($subTable.subJoinMany) ## 一对多 | 190 | #if ($subTable.subJoinMany) ## 一对多 |
| 115 | - <vxe-table ref="tableRef" :data="list" show-overflow class="mx-4"> | 191 | + <VxeTable ref="tableRef" :data="list" show-overflow class="mx-4"> |
| 116 | #foreach($column in $subColumns) | 192 | #foreach($column in $subColumns) |
| 117 | #if ($column.createOperation || $column.updateOperation) | 193 | #if ($column.createOperation || $column.updateOperation) |
| 118 | #set ($comment = $column.columnComment) | 194 | #set ($comment = $column.columnComment) |
| 195 | + #set ($dictType = $column.dictType) | ||
| 119 | #set ($javaField = $column.javaField) | 196 | #set ($javaField = $column.javaField) |
| 120 | #set ($javaType = $column.javaType) | 197 | #set ($javaType = $column.javaType) |
| 121 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 198 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
| @@ -127,99 +204,99 @@ watch( | @@ -127,99 +204,99 @@ watch( | ||
| 127 | #end | 204 | #end |
| 128 | #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 | 205 | #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 |
| 129 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 | 206 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 |
| 130 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 207 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 131 | <template #default="{row}"> | 208 | <template #default="{row}"> |
| 132 | - <el-input v-model="row.${javaField}" /> | 209 | + <ElInput v-model="row.${javaField}" /> |
| 133 | </template> | 210 | </template> |
| 134 | - </vxe-column> | 211 | + </VxeColumn> |
| 135 | #elseif($column.htmlType == "imageUpload")## 图片上传 | 212 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 136 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 213 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 137 | <template #default="{row}"> | 214 | <template #default="{row}"> |
| 138 | <ImageUpload v-model="row.${javaField}" /> | 215 | <ImageUpload v-model="row.${javaField}" /> |
| 139 | </template> | 216 | </template> |
| 140 | - </vxe-column> | 217 | + </VxeColumn> |
| 141 | #elseif($column.htmlType == "fileUpload")## 文件上传 | 218 | #elseif($column.htmlType == "fileUpload")## 文件上传 |
| 142 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 219 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 143 | <template #default="{row}"> | 220 | <template #default="{row}"> |
| 144 | <FileUpload v-model="row.${javaField}" /> | 221 | <FileUpload v-model="row.${javaField}" /> |
| 145 | </template> | 222 | </template> |
| 146 | - </vxe-column> | 223 | + </VxeColumn> |
| 147 | #elseif($column.htmlType == "select")## 下拉框 | 224 | #elseif($column.htmlType == "select")## 下拉框 |
| 148 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 225 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 149 | <template #default="{row}"> | 226 | <template #default="{row}"> |
| 150 | - <el-select v-model="row.${javaField}" placeholder="请选择${comment}"> | 227 | + <ElSelect v-model="row.${javaField}" placeholder="请选择${comment}"> |
| 151 | #if ("" != $dictType)## 有数据字典 | 228 | #if ("" != $dictType)## 有数据字典 |
| 152 | - <el-option | 229 | + <ElOption |
| 153 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 230 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 154 | :key="dict.value" | 231 | :key="dict.value" |
| 155 | :value="dict.value" | 232 | :value="dict.value" |
| 156 | :label="dict.label" | 233 | :label="dict.label" |
| 157 | /> | 234 | /> |
| 158 | #else##没数据字典 | 235 | #else##没数据字典 |
| 159 | - <el-option label="请选择字典生成" value="" /> | 236 | + <ElOption label="请选择字典生成" value="" /> |
| 160 | #end | 237 | #end |
| 161 | - </el-select> | 238 | + </ElSelect> |
| 162 | </template> | 239 | </template> |
| 163 | - </vxe-column> | 240 | + </VxeColumn> |
| 164 | #elseif($column.htmlType == "checkbox")## 多选框 | 241 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 165 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 242 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 166 | <template #default="{row}"> | 243 | <template #default="{row}"> |
| 167 | - <el-checkbox-group v-model="row.${javaField}"> | 244 | + <ElCheckboxGroup v-model="row.${javaField}"> |
| 168 | #if ("" != $dictType)## 有数据字典 | 245 | #if ("" != $dictType)## 有数据字典 |
| 169 | - <el-checkbox | 246 | + <ElCheckbox |
| 170 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 247 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 171 | :key="dict.value" | 248 | :key="dict.value" |
| 172 | - :label="dict.value" | 249 | + :value="dict.value" |
| 173 | > | 250 | > |
| 174 | {{ dict.label }} | 251 | {{ dict.label }} |
| 175 | - </el-checkbox> | 252 | + </ElCheckbox> |
| 176 | #else##没数据字典 | 253 | #else##没数据字典 |
| 177 | - <el-checkbox label="请选择字典生成" /> | 254 | + <ElCheckbox label="请选择字典生成" /> |
| 178 | #end | 255 | #end |
| 179 | - </el-checkbox-group> | 256 | + </ElCheckboxGroup> |
| 180 | </template> | 257 | </template> |
| 181 | - </vxe-column> | 258 | + </VxeColumn> |
| 182 | #elseif($column.htmlType == "radio")## 单选框 | 259 | #elseif($column.htmlType == "radio")## 单选框 |
| 183 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 260 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 184 | <template #default="{row}"> | 261 | <template #default="{row}"> |
| 185 | - <el-radio-group v-model="row.${javaField}"> | 262 | + <ElRadioGroup v-model="row.${javaField}"> |
| 186 | #if ("" != $dictType)## 有数据字典 | 263 | #if ("" != $dictType)## 有数据字典 |
| 187 | - <el-radio | 264 | + <ElRadio |
| 188 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 265 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 189 | :key="dict.value" | 266 | :key="dict.value" |
| 190 | - :label="dict.value" | 267 | + :value="dict.value" |
| 191 | > | 268 | > |
| 192 | {{ dict.label }} | 269 | {{ dict.label }} |
| 193 | - </el-radio> | 270 | + </ElRadio> |
| 194 | #else##没数据字典 | 271 | #else##没数据字典 |
| 195 | - <el-radio :label="1">请选择字典生成</el-radio> | 272 | + <ElRadio :label="1">请选择字典生成</ElRadio> |
| 196 | #end | 273 | #end |
| 197 | - </el-radio-group> | 274 | + </ElRadioGroup> |
| 198 | </template> | 275 | </template> |
| 199 | - </vxe-column> | 276 | + </VxeColumn> |
| 200 | #elseif($column.htmlType == "datetime")## 时间框 | 277 | #elseif($column.htmlType == "datetime")## 时间框 |
| 201 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 278 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 202 | <template #default="{row}"> | 279 | <template #default="{row}"> |
| 203 | - <el-date-picker | 280 | + <ElDatePicker |
| 204 | v-model="row.${javaField}" | 281 | v-model="row.${javaField}" |
| 205 | type="datetime" | 282 | type="datetime" |
| 206 | value-format="x" | 283 | value-format="x" |
| 207 | format="YYYY-MM-DD HH:mm:ss" | 284 | format="YYYY-MM-DD HH:mm:ss" |
| 208 | /> | 285 | /> |
| 209 | </template> | 286 | </template> |
| 210 | - </vxe-column> | 287 | + </VxeColumn> |
| 211 | #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框 | 288 | #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框 |
| 212 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 289 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 213 | <template #default="{row}"> | 290 | <template #default="{row}"> |
| 214 | - <el-input v-model="row.${javaField}" type="textarea" /> | 291 | + <ElInput v-model="row.${javaField}" type="textarea" /> |
| 215 | </template> | 292 | </template> |
| 216 | - </vxe-column> | 293 | + </VxeColumn> |
| 217 | #end | 294 | #end |
| 218 | #end | 295 | #end |
| 219 | #end | 296 | #end |
| 220 | - <vxe-column field="operation" title="操作" align="center"> | 297 | + <VxeColumn field="operation" title="操作" align="center"> |
| 221 | <template #default="{row}"> | 298 | <template #default="{row}"> |
| 222 | - <el-button | 299 | + <ElButton |
| 223 | size="small" | 300 | size="small" |
| 224 | type="danger" | 301 | type="danger" |
| 225 | link | 302 | link |
| @@ -227,17 +304,17 @@ watch( | @@ -227,17 +304,17 @@ watch( | ||
| 227 | v-access:code="['${permissionPrefix}:delete']" | 304 | v-access:code="['${permissionPrefix}:delete']" |
| 228 | > | 305 | > |
| 229 | {{ $t('ui.actionTitle.delete') }} | 306 | {{ $t('ui.actionTitle.delete') }} |
| 230 | - </el-button> | 307 | + </ElButton> |
| 231 | </template> | 308 | </template> |
| 232 | - </vxe-column> | ||
| 233 | - </vxe-table> | 309 | + </VxeColumn> |
| 310 | + </VxeTable> | ||
| 234 | <div class="flex justify-center mt-4"> | 311 | <div class="flex justify-center mt-4"> |
| 235 | - <el-button :icon="h(Plus)" type="primary" plain @click="handleAdd" v-access:code="['${permissionPrefix}:create']"> | 312 | + <ElButton :icon="Plus" type="primary" plain @click="handleAdd" v-access:code="['${permissionPrefix}:create']"> |
| 236 | {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }} | 313 | {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }} |
| 237 | - </el-button> | 314 | + </ElButton> |
| 238 | </div> | 315 | </div> |
| 239 | #else | 316 | #else |
| 240 | - <el-form | 317 | + <ElForm |
| 241 | ref="formRef" | 318 | ref="formRef" |
| 242 | class="mx-4" | 319 | class="mx-4" |
| 243 | :model="formData" | 320 | :model="formData" |
| @@ -259,83 +336,83 @@ watch( | @@ -259,83 +336,83 @@ watch( | ||
| 259 | #set ($dictMethod = "boolean") | 336 | #set ($dictMethod = "boolean") |
| 260 | #end | 337 | #end |
| 261 | #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 | 338 | #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 |
| 262 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 263 | - <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 264 | - </el-form-item> | 339 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 340 | + <ElInput v-model="formData.${javaField}" placeholder="请输入${comment}" /> | ||
| 341 | + </ElFormItem> | ||
| 265 | #elseif($column.htmlType == "imageUpload")## 图片上传 | 342 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 266 | - <el-form-item label="${comment}" prop="${javaField}"> | 343 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 267 | <ImageUpload v-model="formData.${javaField}" /> | 344 | <ImageUpload v-model="formData.${javaField}" /> |
| 268 | - </el-form-item> | 345 | + </ElFormItem> |
| 269 | #elseif($column.htmlType == "fileUpload")## 文件上传 | 346 | #elseif($column.htmlType == "fileUpload")## 文件上传 |
| 270 | - <el-form-item label="${comment}" prop="${javaField}"> | 347 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 271 | <FileUpload v-model="formData.${javaField}" /> | 348 | <FileUpload v-model="formData.${javaField}" /> |
| 272 | - </el-form-item> | 349 | + </ElFormItem> |
| 273 | #elseif($column.htmlType == "editor")## 文本编辑器 | 350 | #elseif($column.htmlType == "editor")## 文本编辑器 |
| 274 | - <el-form-item label="${comment}" prop="${javaField}"> | 351 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 275 | <RichTextarea v-model="formData.${javaField}" height="500px" /> | 352 | <RichTextarea v-model="formData.${javaField}" height="500px" /> |
| 276 | - </el-form-item> | 353 | + </ElFormItem> |
| 277 | #elseif($column.htmlType == "select")## 下拉框 | 354 | #elseif($column.htmlType == "select")## 下拉框 |
| 278 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 279 | - <el-select v-model="formData.${javaField}" placeholder="请选择${comment}"> | 355 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 356 | + <ElSelect v-model="formData.${javaField}" placeholder="请选择${comment}"> | ||
| 280 | #if ("" != $dictType)## 有数据字典 | 357 | #if ("" != $dictType)## 有数据字典 |
| 281 | - <el-option | 358 | + <ElOption |
| 282 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 359 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 283 | :key="dict.value" | 360 | :key="dict.value" |
| 284 | :value="dict.value" | 361 | :value="dict.value" |
| 285 | :label="dict.label" | 362 | :label="dict.label" |
| 286 | /> | 363 | /> |
| 287 | #else##没数据字典 | 364 | #else##没数据字典 |
| 288 | - <el-option label="请选择字典生成" value="" /> | 365 | + <ElOption label="请选择字典生成" value="" /> |
| 289 | #end | 366 | #end |
| 290 | - </el-select> | ||
| 291 | - </el-form-item> | 367 | + </ElSelect> |
| 368 | + </ElFormItem> | ||
| 292 | #elseif($column.htmlType == "checkbox")## 多选框 | 369 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 293 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 294 | - <el-checkbox-group v-model="formData.${javaField}"> | 370 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 371 | + <ElCheckboxGroup v-model="formData.${javaField}"> | ||
| 295 | #if ("" != $dictType)## 有数据字典 | 372 | #if ("" != $dictType)## 有数据字典 |
| 296 | - <el-checkbox | 373 | + <ElCheckbox |
| 297 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 374 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 298 | :key="dict.value" | 375 | :key="dict.value" |
| 299 | - :label="dict.value" | 376 | + :value="dict.value" |
| 300 | > | 377 | > |
| 301 | {{ dict.label }} | 378 | {{ dict.label }} |
| 302 | - </el-checkbox> | 379 | + </ElCheckbox> |
| 303 | #else##没数据字典 | 380 | #else##没数据字典 |
| 304 | - <el-checkbox label="请选择字典生成" /> | 381 | + <ElCheckbox label="请选择字典生成" /> |
| 305 | #end | 382 | #end |
| 306 | - </el-checkbox-group> | ||
| 307 | - </el-form-item> | 383 | + </ElCheckboxGroup> |
| 384 | + </ElFormItem> | ||
| 308 | #elseif($column.htmlType == "radio")## 单选框 | 385 | #elseif($column.htmlType == "radio")## 单选框 |
| 309 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 310 | - <el-radio-group v-model="formData.${javaField}"> | 386 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 387 | + <ElRadioGroup v-model="formData.${javaField}"> | ||
| 311 | #if ("" != $dictType)## 有数据字典 | 388 | #if ("" != $dictType)## 有数据字典 |
| 312 | - <el-radio | 389 | + <ElRadio |
| 313 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 390 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 314 | :key="dict.value" | 391 | :key="dict.value" |
| 315 | - :label="dict.value" | 392 | + :value="dict.value" |
| 316 | > | 393 | > |
| 317 | {{ dict.label }} | 394 | {{ dict.label }} |
| 318 | - </el-radio> | 395 | + </ElRadio> |
| 319 | #else##没数据字典 | 396 | #else##没数据字典 |
| 320 | - <el-radio :label="1">请选择字典生成</el-radio> | 397 | + <ElRadio :label="1">请选择字典生成</ElRadio> |
| 321 | #end | 398 | #end |
| 322 | - </el-radio-group> | ||
| 323 | - </el-form-item> | 399 | + </ElRadioGroup> |
| 400 | + </ElFormItem> | ||
| 324 | #elseif($column.htmlType == "datetime")## 时间框 | 401 | #elseif($column.htmlType == "datetime")## 时间框 |
| 325 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 326 | - <el-date-picker | 402 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 403 | + <ElDatePicker | ||
| 327 | v-model="formData.${javaField}" | 404 | v-model="formData.${javaField}" |
| 328 | value-format="x" | 405 | value-format="x" |
| 329 | placeholder="选择${comment}" | 406 | placeholder="选择${comment}" |
| 330 | /> | 407 | /> |
| 331 | - </el-form-item> | 408 | + </ElFormItem> |
| 332 | #elseif($column.htmlType == "textarea")## 文本框 | 409 | #elseif($column.htmlType == "textarea")## 文本框 |
| 333 | - <el-form-item label="${comment}" prop="${javaField}"> | ||
| 334 | - <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 335 | - </el-form-item> | 410 | + <ElFormItem label="${comment}" prop="${javaField}"> |
| 411 | + <ElInput v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" /> | ||
| 412 | + </ElFormItem> | ||
| 336 | #end | 413 | #end |
| 337 | #end | 414 | #end |
| 338 | #end | 415 | #end |
| 339 | - </el-form> | 416 | + </ElForm> |
| 340 | #end | 417 | #end |
| 341 | </template> | 418 | </template> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/list_sub_erp.vue.vm
| @@ -6,13 +6,14 @@ | @@ -6,13 +6,14 @@ | ||
| 6 | #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex)) | 6 | #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex)) |
| 7 | #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 | 7 | #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 |
| 8 | <script lang="ts" setup> | 8 | <script lang="ts" setup> |
| 9 | - import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 9 | + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}'; |
| 10 | import type { VxeTableInstance } from '#/adapter/vxe-table'; | 10 | import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 11 | 11 | ||
| 12 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; | 12 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; |
| 13 | 13 | ||
| 14 | import { DICT_TYPE } from '@vben/constants'; | 14 | import { DICT_TYPE } from '@vben/constants'; |
| 15 | import { getDictOptions } from '@vben/hooks'; | 15 | import { getDictOptions } from '@vben/hooks'; |
| 16 | +import { formatDateTime } from '@vben/utils'; | ||
| 16 | 17 | ||
| 17 | import { DictTag } from '#/components/dict-tag'; | 18 | import { DictTag } from '#/components/dict-tag'; |
| 18 | import { getRangePickerDefaultProps } from '#/utils'; | 19 | import { getRangePickerDefaultProps } from '#/utils'; |
| @@ -31,13 +32,13 @@ | @@ -31,13 +32,13 @@ | ||
| 31 | #end | 32 | #end |
| 32 | 33 | ||
| 33 | #if ($table.templateType == 11) ## erp | 34 | #if ($table.templateType == 11) ## erp |
| 34 | - import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | ||
| 35 | - import { isEmpty } from '@vben/utils'; | 35 | + import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${table.businessName}'; |
| 36 | + import { cloneDeep, isEmpty } from '@vben/utils'; | ||
| 36 | #else | 37 | #else |
| 37 | #if ($subTable.subJoinMany) ## 一对多 | 38 | #if ($subTable.subJoinMany) ## 一对多 |
| 38 | - import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 39 | + import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 39 | #else | 40 | #else |
| 40 | - import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; | 41 | + import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 41 | #end | 42 | #end |
| 42 | #end | 43 | #end |
| 43 | 44 | ||
| @@ -203,7 +204,7 @@ onMounted(() => { | @@ -203,7 +204,7 @@ onMounted(() => { | ||
| 203 | <div class="h-[600px]"> | 204 | <div class="h-[600px]"> |
| 204 | <ContentWrap v-if="!hiddenSearchBar"> | 205 | <ContentWrap v-if="!hiddenSearchBar"> |
| 205 | <!-- 搜索工作栏 --> | 206 | <!-- 搜索工作栏 --> |
| 206 | - <el-form | 207 | + <ElForm |
| 207 | :model="queryParams" | 208 | :model="queryParams" |
| 208 | ref="queryFormRef" | 209 | ref="queryFormRef" |
| 209 | inline | 210 | inline |
| @@ -222,49 +223,49 @@ onMounted(() => { | @@ -222,49 +223,49 @@ onMounted(() => { | ||
| 222 | #set ($dictMethod = "boolean") | 223 | #set ($dictMethod = "boolean") |
| 223 | #end | 224 | #end |
| 224 | #if ($column.htmlType == "input") | 225 | #if ($column.htmlType == "input") |
| 225 | - <el-form-item label="${comment}"> | ||
| 226 | - <el-input | 226 | + <ElFormItem label="${comment}"> |
| 227 | + <ElInput | ||
| 227 | v-model="queryParams.${javaField}" | 228 | v-model="queryParams.${javaField}" |
| 228 | placeholder="请输入${comment}" | 229 | placeholder="请输入${comment}" |
| 229 | clearable | 230 | clearable |
| 230 | @keyup.enter="handleQuery" | 231 | @keyup.enter="handleQuery" |
| 231 | class="!w-[240px]" | 232 | class="!w-[240px]" |
| 232 | /> | 233 | /> |
| 233 | - </el-form-item> | 234 | + </ElFormItem> |
| 234 | #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") | 235 | #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox") |
| 235 | - <el-form-item label="${comment}"> | ||
| 236 | - <el-select | 236 | + <ElFormItem label="${comment}"> |
| 237 | + <ElSelect | ||
| 237 | v-model="queryParams.${javaField}" | 238 | v-model="queryParams.${javaField}" |
| 238 | placeholder="请选择${comment}" | 239 | placeholder="请选择${comment}" |
| 239 | clearable | 240 | clearable |
| 240 | class="!w-[240px]" | 241 | class="!w-[240px]" |
| 241 | > | 242 | > |
| 242 | #if ("" != $dictType)## 设置了 dictType 数据字典的情况 | 243 | #if ("" != $dictType)## 设置了 dictType 数据字典的情况 |
| 243 | - <el-option | 244 | + <ElOption |
| 244 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" | 245 | v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')" |
| 245 | :key="dict.value" | 246 | :key="dict.value" |
| 246 | :value="dict.value" | 247 | :value="dict.value" |
| 247 | :label="dict.label" | 248 | :label="dict.label" |
| 248 | /> | 249 | /> |
| 249 | #else## 未设置 dictType 数据字典的情况 | 250 | #else## 未设置 dictType 数据字典的情况 |
| 250 | - <el-option label="请选择字典生成" value="" /> | 251 | + <ElOption label="请选择字典生成" value="" /> |
| 251 | #end | 252 | #end |
| 252 | - </el-select> | ||
| 253 | - </el-form-item> | 253 | + </ElSelect> |
| 254 | + </ElFormItem> | ||
| 254 | #elseif($column.htmlType == "datetime") | 255 | #elseif($column.htmlType == "datetime") |
| 255 | #if ($column.listOperationCondition != "BETWEEN")## 非范围 | 256 | #if ($column.listOperationCondition != "BETWEEN")## 非范围 |
| 256 | - <el-form-item label="${comment}"> | ||
| 257 | - <el-date-picker | 257 | + <ElFormItem label="${comment}"> |
| 258 | + <ElDatePicker | ||
| 258 | v-model="queryParams.${javaField}" | 259 | v-model="queryParams.${javaField}" |
| 259 | value-format="YYYY-MM-DD" | 260 | value-format="YYYY-MM-DD" |
| 260 | placeholder="选择${comment}" | 261 | placeholder="选择${comment}" |
| 261 | clearable | 262 | clearable |
| 262 | class="!w-[240px]" | 263 | class="!w-[240px]" |
| 263 | /> | 264 | /> |
| 264 | - </el-form-item> | 265 | + </ElFormItem> |
| 265 | #else## 范围 | 266 | #else## 范围 |
| 266 | - <el-form-item label="${comment}"> | ||
| 267 | - <el-date-picker | 267 | + <ElFormItem label="${comment}"> |
| 268 | + <ElDatePicker | ||
| 268 | v-model="queryParams.${javaField}" | 269 | v-model="queryParams.${javaField}" |
| 269 | type="daterange" | 270 | type="daterange" |
| 270 | value-format="YYYY-MM-DD" | 271 | value-format="YYYY-MM-DD" |
| @@ -273,18 +274,18 @@ onMounted(() => { | @@ -273,18 +274,18 @@ onMounted(() => { | ||
| 273 | end-placeholder="结束日期" | 274 | end-placeholder="结束日期" |
| 274 | class="!w-[240px]" | 275 | class="!w-[240px]" |
| 275 | /> | 276 | /> |
| 276 | - </el-form-item> | 277 | + </ElFormItem> |
| 277 | #end | 278 | #end |
| 278 | #end | 279 | #end |
| 279 | #end | 280 | #end |
| 280 | #end | 281 | #end |
| 281 | - <el-form-item> | ||
| 282 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 283 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 282 | + <ElFormItem> |
| 283 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 284 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 284 | 搜索 | 285 | 搜索 |
| 285 | - </el-button> | ||
| 286 | - </el-form-item> | ||
| 287 | - </el-form> | 286 | + </ElButton> |
| 287 | + </ElFormItem> | ||
| 288 | + </ElForm> | ||
| 288 | </ContentWrap> | 289 | </ContentWrap> |
| 289 | 290 | ||
| 290 | <!-- 列表 --> | 291 | <!-- 列表 --> |
| @@ -294,7 +295,7 @@ onMounted(() => { | @@ -294,7 +295,7 @@ onMounted(() => { | ||
| 294 | ref="tableToolbarRef" | 295 | ref="tableToolbarRef" |
| 295 | v-model:hidden-search="hiddenSearchBar" | 296 | v-model:hidden-search="hiddenSearchBar" |
| 296 | > | 297 | > |
| 297 | - <el-button | 298 | + <ElButton |
| 298 | class="ml-2" | 299 | class="ml-2" |
| 299 | :icon="h(Plus)" | 300 | :icon="h(Plus)" |
| 300 | type="primary" | 301 | type="primary" |
| @@ -302,9 +303,9 @@ onMounted(() => { | @@ -302,9 +303,9 @@ onMounted(() => { | ||
| 302 | v-access:code="['${permissionPrefix}:create']" | 303 | v-access:code="['${permissionPrefix}:create']" |
| 303 | > | 304 | > |
| 304 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} | 305 | {{ $t('ui.actionTitle.create', ['${table.classComment}']) }} |
| 305 | - </el-button> | 306 | + </ElButton> |
| 306 | #if ($deleteBatchEnable) | 307 | #if ($deleteBatchEnable) |
| 307 | - <el-button | 308 | + <ElButton |
| 308 | :icon="h(Trash2)" | 309 | :icon="h(Trash2)" |
| 309 | type="danger" | 310 | type="danger" |
| 310 | class="ml-2" | 311 | class="ml-2" |
| @@ -313,11 +314,11 @@ onMounted(() => { | @@ -313,11 +314,11 @@ onMounted(() => { | ||
| 313 | v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']" | 314 | v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']" |
| 314 | > | 315 | > |
| 315 | 批量删除 | 316 | 批量删除 |
| 316 | - </el-button> | 317 | + </ElButton> |
| 317 | #end | 318 | #end |
| 318 | - </TableToolbar> | 319 | + </VbenVxeTableToolbar> |
| 319 | </template> | 320 | </template> |
| 320 | - <vxe-table | 321 | + <VxeTable |
| 321 | ref="tableRef" | 322 | ref="tableRef" |
| 322 | :data="list" | 323 | :data="list" |
| 323 | show-overflow | 324 | show-overflow |
| @@ -328,7 +329,7 @@ onMounted(() => { | @@ -328,7 +329,7 @@ onMounted(() => { | ||
| 328 | #end | 329 | #end |
| 329 | > | 330 | > |
| 330 | #if ($deleteBatchEnable) | 331 | #if ($deleteBatchEnable) |
| 331 | - <vxe-column type="checkbox" width="40"></vxe-column> | 332 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 332 | #end | 333 | #end |
| 333 | #foreach($column in $subColumns) | 334 | #foreach($column in $subColumns) |
| 334 | #if ($column.listOperationResult) | 335 | #if ($column.listOperationResult) |
| @@ -336,27 +337,27 @@ onMounted(() => { | @@ -336,27 +337,27 @@ onMounted(() => { | ||
| 336 | #set ($javaField = $column.javaField) | 337 | #set ($javaField = $column.javaField) |
| 337 | #set ($comment=$column.columnComment) | 338 | #set ($comment=$column.columnComment) |
| 338 | #if ($column.javaType == "LocalDateTime")## 时间类型 | 339 | #if ($column.javaType == "LocalDateTime")## 时间类型 |
| 339 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 340 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 340 | <template #default="{row}"> | 341 | <template #default="{row}"> |
| 341 | {{formatDateTime(row.${javaField})}} | 342 | {{formatDateTime(row.${javaField})}} |
| 342 | </template> | 343 | </template> |
| 343 | - </vxe-column> | 344 | + </VxeColumn> |
| 344 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 | 345 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 |
| 345 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 346 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 346 | <template #default="{row}"> | 347 | <template #default="{row}"> |
| 347 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> | 348 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> |
| 348 | </template> | 349 | </template> |
| 349 | - </vxe-column> | 350 | + </VxeColumn> |
| 350 | #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField) | 351 | #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField) |
| 351 | - <vxe-column field="${javaField}" title="${comment}" align="center" tree-node/> | 352 | + <VxeColumn field="${javaField}" title="${comment}" align="center" tree-node/> |
| 352 | #else | 353 | #else |
| 353 | - <vxe-column field="${javaField}" title="${comment}" align="center" /> | 354 | + <VxeColumn field="${javaField}" title="${comment}" align="center" /> |
| 354 | #end | 355 | #end |
| 355 | #end | 356 | #end |
| 356 | #end | 357 | #end |
| 357 | - <vxe-column field="operation" title="操作" align="center"> | 358 | + <VxeColumn field="operation" title="操作" align="center"> |
| 358 | <template #default="{row}"> | 359 | <template #default="{row}"> |
| 359 | - <el-button | 360 | + <ElButton |
| 360 | size="small" | 361 | size="small" |
| 361 | type="primary" | 362 | type="primary" |
| 362 | link | 363 | link |
| @@ -364,8 +365,8 @@ onMounted(() => { | @@ -364,8 +365,8 @@ onMounted(() => { | ||
| 364 | v-access:code="['${permissionPrefix}:update']" | 365 | v-access:code="['${permissionPrefix}:update']" |
| 365 | > | 366 | > |
| 366 | {{ $t('ui.actionTitle.edit') }} | 367 | {{ $t('ui.actionTitle.edit') }} |
| 367 | - </el-button> | ||
| 368 | - <el-button | 368 | + </ElButton> |
| 369 | + <ElButton | ||
| 369 | size="small" | 370 | size="small" |
| 370 | type="danger" | 371 | type="danger" |
| 371 | link | 372 | link |
| @@ -374,13 +375,13 @@ onMounted(() => { | @@ -374,13 +375,13 @@ onMounted(() => { | ||
| 374 | v-access:code="['${permissionPrefix}:delete']" | 375 | v-access:code="['${permissionPrefix}:delete']" |
| 375 | > | 376 | > |
| 376 | {{ $t('ui.actionTitle.delete') }} | 377 | {{ $t('ui.actionTitle.delete') }} |
| 377 | - </el-button> | 378 | + </ElButton> |
| 378 | </template> | 379 | </template> |
| 379 | - </vxe-column> | ||
| 380 | - </vxe-table> | 380 | + </VxeColumn> |
| 381 | + </VxeTable> | ||
| 381 | <!-- 分页 --> | 382 | <!-- 分页 --> |
| 382 | <div class="mt-2 flex justify-end"> | 383 | <div class="mt-2 flex justify-end"> |
| 383 | - <el-pagination | 384 | + <ElPagination |
| 384 | :total="total" | 385 | :total="total" |
| 385 | v-model:current-page="queryParams.pageNo" | 386 | v-model:current-page="queryParams.pageNo" |
| 386 | v-model:page-size="queryParams.pageSize" | 387 | v-model:page-size="queryParams.pageSize" |
| @@ -394,7 +395,7 @@ onMounted(() => { | @@ -394,7 +395,7 @@ onMounted(() => { | ||
| 394 | </div> | 395 | </div> |
| 395 | #else | 396 | #else |
| 396 | <ContentWrap title="${subTable.classComment}列表"> | 397 | <ContentWrap title="${subTable.classComment}列表"> |
| 397 | - <vxe-table | 398 | + <VxeTable |
| 398 | :data="list" | 399 | :data="list" |
| 399 | show-overflow | 400 | show-overflow |
| 400 | :loading="loading" | 401 | :loading="loading" |
| @@ -405,23 +406,23 @@ onMounted(() => { | @@ -405,23 +406,23 @@ onMounted(() => { | ||
| 405 | #set ($javaField = $column.javaField) | 406 | #set ($javaField = $column.javaField) |
| 406 | #set ($comment=$column.columnComment) | 407 | #set ($comment=$column.columnComment) |
| 407 | #if ($column.javaType == "LocalDateTime")## 时间类型 | 408 | #if ($column.javaType == "LocalDateTime")## 时间类型 |
| 408 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 409 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 409 | <template #default="{row}"> | 410 | <template #default="{row}"> |
| 410 | {{formatDateTime(row.${javaField})}} | 411 | {{formatDateTime(row.${javaField})}} |
| 411 | </template> | 412 | </template> |
| 412 | - </vxe-column> | 413 | + </VxeColumn> |
| 413 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 | 414 | #elseif($column.dictType && "" != $column.dictType)## 数据字典 |
| 414 | - <vxe-column field="${javaField}" title="${comment}" align="center"> | 415 | + <VxeColumn field="${javaField}" title="${comment}" align="center"> |
| 415 | <template #default="{row}"> | 416 | <template #default="{row}"> |
| 416 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> | 417 | <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" /> |
| 417 | </template> | 418 | </template> |
| 418 | - </vxe-column> | 419 | + </VxeColumn> |
| 419 | #else | 420 | #else |
| 420 | - <vxe-column field="${javaField}" title="${comment}" align="center" /> | 421 | + <VxeColumn field="${javaField}" title="${comment}" align="center" /> |
| 421 | #end | 422 | #end |
| 422 | #end | 423 | #end |
| 423 | #end | 424 | #end |
| 424 | - </vxe-table> | 425 | + </VxeTable> |
| 425 | </ContentWrap> | 426 | </ContentWrap> |
| 426 | #end | 427 | #end |
| 427 | </template> | 428 | </template> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm
| @@ -36,13 +36,14 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -36,13 +36,14 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 36 | id: 0, | 36 | id: 0, |
| 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', | 37 | ${treeNameColumn.javaField}: '顶级${table.classComment}', |
| 38 | }); | 38 | }); |
| 39 | - return handleTree(data); | 39 | + return handleTree(data, 'id', '${treeParentColumn.javaField}'); |
| 40 | }, | 40 | }, |
| 41 | labelField: '${treeNameColumn.javaField}', | 41 | labelField: '${treeNameColumn.javaField}', |
| 42 | valueField: 'id', | 42 | valueField: 'id', |
| 43 | childrenField: 'children', | 43 | childrenField: 'children', |
| 44 | placeholder: '请选择上级${table.classComment}', | 44 | placeholder: '请选择上级${table.classComment}', |
| 45 | - treeDefaultExpandAll: true, | 45 | + defaultExpandAll: true, |
| 46 | + checkStrictly: true, | ||
| 46 | }, | 47 | }, |
| 47 | rules: 'selectRequired', | 48 | rules: 'selectRequired', |
| 48 | }, | 49 | }, |
| @@ -89,7 +90,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -89,7 +90,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 89 | placeholder: '请选择${comment}', | 90 | placeholder: '请选择${comment}', |
| 90 | }, | 91 | }, |
| 91 | #elseif($column.htmlType == "checkbox")## 多选框 | 92 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 92 | - component: 'Checkbox', | 93 | + component: 'CheckboxGroup', |
| 93 | componentProps: { | 94 | componentProps: { |
| 94 | #if ("" != $dictType)## 有数据字典 | 95 | #if ("" != $dictType)## 有数据字典 |
| 95 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 96 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -105,13 +106,12 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -105,13 +106,12 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 105 | #else##没数据字典 | 106 | #else##没数据字典 |
| 106 | options: [], | 107 | options: [], |
| 107 | #end | 108 | #end |
| 108 | - buttonStyle: 'solid', | ||
| 109 | - optionType: 'button', | 109 | + isButton: true, |
| 110 | }, | 110 | }, |
| 111 | #elseif($column.htmlType == "datetime")## 时间框 | 111 | #elseif($column.htmlType == "datetime")## 时间框 |
| 112 | component: 'DatePicker', | 112 | component: 'DatePicker', |
| 113 | componentProps: { | 113 | componentProps: { |
| 114 | - showTime: true, | 114 | + type: 'datetime', |
| 115 | format: 'YYYY-MM-DD HH:mm:ss', | 115 | format: 'YYYY-MM-DD HH:mm:ss', |
| 116 | valueFormat: 'x', | 116 | valueFormat: 'x', |
| 117 | class: '!w-full', | 117 | class: '!w-full', |
| @@ -308,7 +308,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | @@ -308,7 +308,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | ||
| 308 | placeholder: '请选择${comment}', | 308 | placeholder: '请选择${comment}', |
| 309 | }, | 309 | }, |
| 310 | #elseif($column.htmlType == "checkbox")## 多选框 | 310 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 311 | - component: 'Checkbox', | 311 | + component: 'CheckboxGroup', |
| 312 | componentProps: { | 312 | componentProps: { |
| 313 | #if ("" != $dictType)## 有数据字典 | 313 | #if ("" != $dictType)## 有数据字典 |
| 314 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 314 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -324,13 +324,12 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | @@ -324,13 +324,12 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { | ||
| 324 | #else##没数据字典 | 324 | #else##没数据字典 |
| 325 | options: [], | 325 | options: [], |
| 326 | #end | 326 | #end |
| 327 | - buttonStyle: 'solid', | ||
| 328 | - optionType: 'button', | 327 | + isButton: true, |
| 329 | }, | 328 | }, |
| 330 | #elseif($column.htmlType == "datetime")## 时间框 | 329 | #elseif($column.htmlType == "datetime")## 时间框 |
| 331 | component: 'DatePicker', | 330 | component: 'DatePicker', |
| 332 | componentProps: { | 331 | componentProps: { |
| 333 | - showTime: true, | 332 | + type: 'datetime', |
| 334 | format: 'YYYY-MM-DD HH:mm:ss', | 333 | format: 'YYYY-MM-DD HH:mm:ss', |
| 335 | valueFormat: 'x', | 334 | valueFormat: 'x', |
| 336 | class: '!w-full', | 335 | class: '!w-full', |
| @@ -450,6 +449,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -450,6 +449,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 450 | #if ($column.createOperation || $column.updateOperation) | 449 | #if ($column.createOperation || $column.updateOperation) |
| 451 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 | 450 | #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 |
| 452 | #set ($dictType = $column.dictType) | 451 | #set ($dictType = $column.dictType) |
| 452 | + #set ($javaType = $column.javaType) | ||
| 453 | #set ($javaField = $column.javaField) | 453 | #set ($javaField = $column.javaField) |
| 454 | #set ($comment = $column.columnComment) | 454 | #set ($comment = $column.columnComment) |
| 455 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") | 455 | #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") |
| @@ -544,7 +544,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -544,7 +544,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 544 | placeholder: '请选择${comment}', | 544 | placeholder: '请选择${comment}', |
| 545 | }, | 545 | }, |
| 546 | #elseif($column.htmlType == "checkbox")## 多选框 | 546 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 547 | - component: 'Checkbox', | 547 | + component: 'CheckboxGroup', |
| 548 | componentProps: { | 548 | componentProps: { |
| 549 | #if ("" != $dictType)## 有数据字典 | 549 | #if ("" != $dictType)## 有数据字典 |
| 550 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), | 550 | options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), |
| @@ -560,13 +560,12 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -560,13 +560,12 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 560 | #else##没数据字典 | 560 | #else##没数据字典 |
| 561 | options: [], | 561 | options: [], |
| 562 | #end | 562 | #end |
| 563 | - buttonStyle: 'solid', | ||
| 564 | - optionType: 'button', | 563 | + isButton: true, |
| 565 | }, | 564 | }, |
| 566 | #elseif($column.htmlType == "datetime")## 时间框 | 565 | #elseif($column.htmlType == "datetime")## 时间框 |
| 567 | component: 'DatePicker', | 566 | component: 'DatePicker', |
| 568 | componentProps: { | 567 | componentProps: { |
| 569 | - showTime: true, | 568 | + type: 'datetime', |
| 570 | format: 'YYYY-MM-DD HH:mm:ss', | 569 | format: 'YYYY-MM-DD HH:mm:ss', |
| 571 | valueFormat: 'x', | 570 | valueFormat: 'x', |
| 572 | class: '!w-full', | 571 | class: '!w-full', |
| @@ -596,7 +595,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | @@ -596,7 +595,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api | ||
| 596 | #end | 595 | #end |
| 597 | #if ($table.templateType == 12) ## 内嵌情况 | 596 | #if ($table.templateType == 12) ## 内嵌情况 |
| 598 | /** 列表的字段 */ | 597 | /** 列表的字段 */ |
| 599 | - export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] { | 598 | + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${apiName}.${subSimpleClassName}>['columns'] { |
| 600 | return [ | 599 | return [ |
| 601 | #foreach($column in $subColumns) | 600 | #foreach($column in $subColumns) |
| 602 | #if ($column.listOperationResult) | 601 | #if ($column.listOperationResult) |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/form.vue.vm
| @@ -6,7 +6,7 @@ import { computed, ref } from 'vue'; | @@ -6,7 +6,7 @@ import { computed, ref } from 'vue'; | ||
| 6 | 6 | ||
| 7 | import { useVbenModal } from '@vben/common-ui'; | 7 | import { useVbenModal } from '@vben/common-ui'; |
| 8 | 8 | ||
| 9 | -import { ElMessage#if ($table.templateType == 11), ElTabs, ElTabPane#end } from 'element-plus'; | 9 | +import { ElMessage#if ($table.templateType == 10 || $table.templateType == 12), ElTabPane, ElTabs#end } from 'element-plus'; |
| 10 | 10 | ||
| 11 | import { useVbenForm } from '#/adapter/form'; | 11 | import { useVbenForm } from '#/adapter/form'; |
| 12 | import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; | 12 | import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -69,15 +69,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 69 | #foreach ($subTable in $subTables) | 69 | #foreach ($subTable in $subTables) |
| 70 | #set ($index = $foreach.count - 1) | 70 | #set ($index = $foreach.count - 1) |
| 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) | 71 | #set ($subClassNameVar = $subClassNameVars.get($index)) |
| 72 | - #if ($subTable.subJoinMany) ## 一对多 | ||
| 73 | - ## TODO 列表值校验? | ||
| 74 | - #else | ||
| 75 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); | 72 | const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate(); |
| 76 | if (!${subClassNameVar}Valid) { | 73 | if (!${subClassNameVar}Valid) { |
| 77 | subTabsName.value = '${subClassNameVar}'; | 74 | subTabsName.value = '${subClassNameVar}'; |
| 78 | return; | 75 | return; |
| 79 | } | 76 | } |
| 80 | - #end | ||
| 81 | #end | 77 | #end |
| 82 | #end | 78 | #end |
| 83 | #end | 79 | #end |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/import.vue.vm
| @@ -50,6 +50,16 @@ function handleChange(file: any) { | @@ -50,6 +50,16 @@ function handleChange(file: any) { | ||
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | +/** 移除文件 */ | ||
| 54 | +function handleRemove() { | ||
| 55 | + formApi.setFieldValue('file', undefined); | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +/** 超出文件数量 */ | ||
| 59 | +function handleExceed() { | ||
| 60 | + ElMessage.warning('只能选择一个文件,请先移除已选文件'); | ||
| 61 | +} | ||
| 62 | + | ||
| 53 | /** 下载模板 */ | 63 | /** 下载模板 */ |
| 54 | async function handleDownload() { | 64 | async function handleDownload() { |
| 55 | const data = await import${simpleClassName}Template(); | 65 | const data = await import${simpleClassName}Template(); |
| @@ -66,6 +76,8 @@ async function handleDownload() { | @@ -66,6 +76,8 @@ async function handleDownload() { | ||
| 66 | :limit="1" | 76 | :limit="1" |
| 67 | accept=".xls,.xlsx" | 77 | accept=".xls,.xlsx" |
| 68 | :on-change="handleChange" | 78 | :on-change="handleChange" |
| 79 | + :on-remove="handleRemove" | ||
| 80 | + :on-exceed="handleExceed" | ||
| 69 | :auto-upload="false" | 81 | :auto-upload="false" |
| 70 | > | 82 | > |
| 71 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> | 83 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> |
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_normal.vue.vm
| @@ -14,10 +14,9 @@ | @@ -14,10 +14,9 @@ | ||
| 14 | 14 | ||
| 15 | #if ($subTable.subJoinMany) ## 一对多 | 15 | #if ($subTable.subJoinMany) ## 一对多 |
| 16 | import { Plus } from "@vben/icons"; | 16 | import { Plus } from "@vben/icons"; |
| 17 | -import { ElButton, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElOption, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus'; | 17 | +import { ElButton, ElCheckbox, ElCheckboxGroup, ElDatePicker, ElInput, ElMessage, ElOption, ElRadio, ElRadioGroup, ElSelect, ElTabPane, ElTabs } from 'element-plus'; |
| 18 | import { ImageUpload, FileUpload } from "#/components/upload"; | 18 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 19 | -import type { OnActionClickParams } from '#/adapter/vxe-table'; | ||
| 20 | -import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 19 | +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 21 | import { use${subSimpleClassName}GridEditColumns } from '../data'; | 20 | import { use${subSimpleClassName}GridEditColumns } from '../data'; |
| 22 | import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; | 21 | import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}'; |
| 23 | #else | 22 | #else |
| @@ -31,22 +30,9 @@ const props = defineProps<{ | @@ -31,22 +30,9 @@ const props = defineProps<{ | ||
| 31 | }>() | 30 | }>() |
| 32 | 31 | ||
| 33 | #if ($subTable.subJoinMany) ## 一对多 | 32 | #if ($subTable.subJoinMany) ## 一对多 |
| 34 | -/** 表格操作按钮的回调函数 */ | ||
| 35 | -function onActionClick({ | ||
| 36 | - code, | ||
| 37 | - row, | ||
| 38 | -}: OnActionClickParams<${apiName}.${subSimpleClassName}>) { | ||
| 39 | - switch (code) { | ||
| 40 | - case 'delete': { | ||
| 41 | - onDelete(row); | ||
| 42 | - break; | ||
| 43 | - } | ||
| 44 | - } | ||
| 45 | -} | ||
| 46 | - | ||
| 47 | const [Grid, gridApi] = useVbenVxeGrid({ | 33 | const [Grid, gridApi] = useVbenVxeGrid({ |
| 48 | gridOptions: { | 34 | gridOptions: { |
| 49 | - columns: use${subSimpleClassName}GridEditColumns(onActionClick), | 35 | + columns: use${subSimpleClassName}GridEditColumns(), |
| 50 | border: true, | 36 | border: true, |
| 51 | showOverflow: true, | 37 | showOverflow: true, |
| 52 | autoResize: true, | 38 | autoResize: true, |
| @@ -65,7 +51,7 @@ gridOptions: { | @@ -65,7 +51,7 @@ gridOptions: { | ||
| 65 | 51 | ||
| 66 | /** 添加${subTable.classComment} */ | 52 | /** 添加${subTable.classComment} */ |
| 67 | const onAdd = async () => { | 53 | const onAdd = async () => { |
| 68 | - await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1); | 54 | + await gridApi.grid.insertAt({} as ${apiName}.${subSimpleClassName}, -1); |
| 69 | } | 55 | } |
| 70 | 56 | ||
| 71 | /** 删除${subTable.classComment} */ | 57 | /** 删除${subTable.classComment} */ |
| @@ -73,26 +59,54 @@ const onDelete = async (row: ${apiName}.${subSimpleClassName}) => { | @@ -73,26 +59,54 @@ const onDelete = async (row: ${apiName}.${subSimpleClassName}) => { | ||
| 73 | await gridApi.grid.remove(row); | 59 | await gridApi.grid.remove(row); |
| 74 | } | 60 | } |
| 75 | 61 | ||
| 76 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 77 | -defineExpose({ | ||
| 78 | - getData: (): ${apiName}.${subSimpleClassName}[] => { | ||
| 79 | - const data = gridApi.grid.getData() as ${apiName}.${subSimpleClassName}[]; | ||
| 80 | - const removeRecords = gridApi.grid.getRemoveRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 81 | - const insertRecords = gridApi.grid.getInsertRecords() as ${apiName}.${subSimpleClassName}[]; | ||
| 82 | - return data | ||
| 83 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 84 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 85 | - }, | ||
| 86 | -}); | 62 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 63 | +function getData(): ${apiName}.${subSimpleClassName}[] { | ||
| 64 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 65 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 66 | + return fullData.map((row) => | ||
| 67 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 68 | + ); | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +#set ($hasRequiredColumn = false) | ||
| 72 | +#foreach ($column in $subColumns) | ||
| 73 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 74 | +#set ($hasRequiredColumn = true) | ||
| 75 | +#end | ||
| 76 | +#end | ||
| 77 | +/** 校验子表必填字段 */ | ||
| 78 | +function validate(): boolean { | ||
| 79 | +#if ($hasRequiredColumn) | ||
| 80 | + for (const [index, row] of getData().entries()) { | ||
| 81 | +#foreach ($column in $subColumns) | ||
| 82 | +#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey && $column.id != $subJoinColumn.id) | ||
| 83 | + if ( | ||
| 84 | + row.${column.javaField} === null || | ||
| 85 | + row.${column.javaField} === undefined || | ||
| 86 | + (typeof row.${column.javaField} === 'string' && String(row.${column.javaField}).trim() === '') || | ||
| 87 | + (Array.isArray(row.${column.javaField}) && row.${column.javaField}.length === 0) | ||
| 88 | + ) { | ||
| 89 | + ElMessage.error(`第 #[[${index + 1}]]# 行:${column.columnComment}不能为空`); | ||
| 90 | + return false; | ||
| 91 | + } | ||
| 92 | +#end | ||
| 93 | +#end | ||
| 94 | + } | ||
| 95 | +#end | ||
| 96 | + return true; | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +defineExpose({ getData, validate }); | ||
| 87 | 100 | ||
| 88 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 101 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 89 | watch( | 102 | watch( |
| 90 | () => props.${subJoinColumn.javaField}, | 103 | () => props.${subJoinColumn.javaField}, |
| 91 | async (val) => { | 104 | async (val) => { |
| 105 | + await nextTick(); | ||
| 92 | if (!val) { | 106 | if (!val) { |
| 107 | + await gridApi.grid.loadData([]); | ||
| 93 | return; | 108 | return; |
| 94 | } | 109 | } |
| 95 | - await nextTick(); | ||
| 96 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 110 | await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 97 | }, | 111 | }, |
| 98 | { immediate: true }, | 112 | { immediate: true }, |
| @@ -124,10 +138,11 @@ defineExpose({ | @@ -124,10 +138,11 @@ defineExpose({ | ||
| 124 | watch( | 138 | watch( |
| 125 | () => props.${subJoinColumn.javaField}, | 139 | () => props.${subJoinColumn.javaField}, |
| 126 | async (val) => { | 140 | async (val) => { |
| 141 | + await nextTick(); | ||
| 142 | + await formApi.resetForm(); | ||
| 127 | if (!val) { | 143 | if (!val) { |
| 128 | return; | 144 | return; |
| 129 | } | 145 | } |
| 130 | - await nextTick(); | ||
| 131 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); | 146 | await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)); |
| 132 | }, | 147 | }, |
| 133 | { immediate: true }, | 148 | { immediate: true }, |
| @@ -144,7 +159,7 @@ watch( | @@ -144,7 +159,7 @@ watch( | ||
| 144 | #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 | 159 | #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写 |
| 145 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 | 160 | #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 |
| 146 | <template #${javaField}="{ row }"> | 161 | <template #${javaField}="{ row }"> |
| 147 | - <el-input v-model="row.${javaField}" /> | 162 | + <ElInput v-model="row.${javaField}" /> |
| 148 | </template> | 163 | </template> |
| 149 | #elseif($column.htmlType == "imageUpload")## 图片上传 | 164 | #elseif($column.htmlType == "imageUpload")## 图片上传 |
| 150 | <template #${javaField}="{ row }"> | 165 | <template #${javaField}="{ row }"> |
| @@ -156,29 +171,29 @@ watch( | @@ -156,29 +171,29 @@ watch( | ||
| 156 | </template> | 171 | </template> |
| 157 | #elseif($column.htmlType == "select")## 下拉框 | 172 | #elseif($column.htmlType == "select")## 下拉框 |
| 158 | <template #${javaField}="{ row, column }"> | 173 | <template #${javaField}="{ row, column }"> |
| 159 | - <el-select v-model="row.${javaField}" class="w-full"> | ||
| 160 | - <el-option v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 161 | - </el-select> | 174 | + <ElSelect v-model="row.${javaField}" class="w-full"> |
| 175 | + <ElOption v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 176 | + </ElSelect> | ||
| 162 | </template> | 177 | </template> |
| 163 | #elseif($column.htmlType == "checkbox")## 多选框 | 178 | #elseif($column.htmlType == "checkbox")## 多选框 |
| 164 | <template #${javaField}="{ row, column }"> | 179 | <template #${javaField}="{ row, column }"> |
| 165 | - <el-checkbox-group v-model="row.${javaField}"> | ||
| 166 | - <el-checkbox v-for="option in column.params.options" :key="option.value" :label="option.value"> | 180 | + <ElCheckboxGroup v-model="row.${javaField}"> |
| 181 | + <ElCheckbox v-for="option in column.params.options" :key="option.value" :value="option.value"> | ||
| 167 | {{ option.label }} | 182 | {{ option.label }} |
| 168 | - </el-checkbox> | ||
| 169 | - </el-checkbox-group> | 183 | + </ElCheckbox> |
| 184 | + </ElCheckboxGroup> | ||
| 170 | </template> | 185 | </template> |
| 171 | #elseif($column.htmlType == "radio")## 单选框 | 186 | #elseif($column.htmlType == "radio")## 单选框 |
| 172 | <template #${javaField}="{ row, column }"> | 187 | <template #${javaField}="{ row, column }"> |
| 173 | - <el-radio-group v-model="row.${javaField}"> | ||
| 174 | - <el-radio v-for="option in column.params.options" :key="option.value" :label="option.value"> | 188 | + <ElRadioGroup v-model="row.${javaField}"> |
| 189 | + <ElRadio v-for="option in column.params.options" :key="option.value" :value="option.value"> | ||
| 175 | {{ option.label }} | 190 | {{ option.label }} |
| 176 | - </el-radio> | ||
| 177 | - </el-radio-group> | 191 | + </ElRadio> |
| 192 | + </ElRadioGroup> | ||
| 178 | </template> | 193 | </template> |
| 179 | #elseif($column.htmlType == "datetime")## 时间框 | 194 | #elseif($column.htmlType == "datetime")## 时间框 |
| 180 | <template #${javaField}="{ row }"> | 195 | <template #${javaField}="{ row }"> |
| 181 | - <el-date-picker | 196 | + <ElDatePicker |
| 182 | v-model="row.${javaField}" | 197 | v-model="row.${javaField}" |
| 183 | type="datetime" | 198 | type="datetime" |
| 184 | value-format="x" | 199 | value-format="x" |
| @@ -187,16 +202,29 @@ watch( | @@ -187,16 +202,29 @@ watch( | ||
| 187 | </template> | 202 | </template> |
| 188 | #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框 | 203 | #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框 |
| 189 | <template #${javaField}="{ row }"> | 204 | <template #${javaField}="{ row }"> |
| 190 | - <el-input v-model="row.${javaField}" type="textarea" /> | 205 | + <ElInput v-model="row.${javaField}" type="textarea" /> |
| 191 | </template> | 206 | </template> |
| 192 | #end | 207 | #end |
| 193 | #end | 208 | #end |
| 194 | #end | 209 | #end |
| 210 | + <template #actions="{ row }"> | ||
| 211 | + <TableAction | ||
| 212 | + :actions="[ | ||
| 213 | + { | ||
| 214 | + label: $t('common.delete'), | ||
| 215 | + type: 'danger', link: true, | ||
| 216 | + icon: ACTION_ICON.DELETE, | ||
| 217 | + auth: ['${permissionPrefix}:delete'], | ||
| 218 | + onClick: onDelete.bind(null, row), | ||
| 219 | + }, | ||
| 220 | + ]" | ||
| 221 | + /> | ||
| 222 | + </template> | ||
| 195 | </Grid> | 223 | </Grid> |
| 196 | <div class="flex justify-center -mt-4"> | 224 | <div class="flex justify-center -mt-4"> |
| 197 | - <el-button :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']"> | 225 | + <ElButton :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']"> |
| 198 | {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }} | 226 | {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }} |
| 199 | - </el-button> | 227 | + </ElButton> |
| 200 | </div> | 228 | </div> |
| 201 | #else | 229 | #else |
| 202 | <Form class="mx-4" /> | 230 | <Form class="mx-4" /> |
yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineFrontendContractTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.service.codegen.inner; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; | ||
| 4 | +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; | ||
| 5 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; | ||
| 7 | +import com.baomidou.mybatisplus.annotation.DbType; | ||
| 8 | +import org.junit.jupiter.api.Test; | ||
| 9 | +import org.junit.jupiter.params.ParameterizedTest; | ||
| 10 | +import org.junit.jupiter.params.provider.EnumSource; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * {@link CodegenEngine} 的前端组件契约回归测试 | ||
| 19 | + * | ||
| 20 | + * @author 芋道源码 | ||
| 21 | + */ | ||
| 22 | +public class CodegenEngineFrontendContractTest extends CodegenEngineAbstractTest { | ||
| 23 | + | ||
| 24 | + @ParameterizedTest | ||
| 25 | + @EnumSource(value = CodegenFrontTypeEnum.class, names = { | ||
| 26 | + "VUE3_VBEN5_ANTD_SCHEMA", "VUE3_VBEN5_ANTDV_NEXT_SCHEMA", "VUE3_VBEN5_EP_SCHEMA"}) | ||
| 27 | + public void testExecute_dictionaryControls(CodegenFrontTypeEnum frontType) { | ||
| 28 | + // 准备参数:同一字典的多选、单选和数字必填字段 | ||
| 29 | + CodegenTableDO table = getTable("student").setFrontType(frontType.getType()) | ||
| 30 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | ||
| 31 | + List<CodegenColumnDO> columns = getColumnList("student"); | ||
| 32 | + columns.add(new CodegenColumnDO().setJavaField("tags").setJavaType("String") | ||
| 33 | + .setColumnComment("标签").setDictType("system_user_sex").setHtmlType("checkbox") | ||
| 34 | + .setCreateOperation(true).setUpdateOperation(true).setNullable(false).setPrimaryKey(false)); | ||
| 35 | + columns.add(new CodegenColumnDO().setJavaField("status").setJavaType("Integer") | ||
| 36 | + .setColumnComment("状态").setDictType("system_user_sex").setHtmlType("radio") | ||
| 37 | + .setCreateOperation(true).setUpdateOperation(true).setNullable(false).setPrimaryKey(false)); | ||
| 38 | + columns.add(new CodegenColumnDO().setJavaField("amount").setJavaType("Integer") | ||
| 39 | + .setColumnComment("金额").setHtmlType("inputNumber").setDictType("") | ||
| 40 | + .setCreateOperation(true).setUpdateOperation(true).setNullable(false).setPrimaryKey(false)); | ||
| 41 | + | ||
| 42 | + // 调用 | ||
| 43 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null); | ||
| 44 | + // 调试用:导出真实生成结果,供前端组件验证 | ||
| 45 | + String outputPath = System.getProperty("codegen.contractOutput"); | ||
| 46 | + if (outputPath != null) { | ||
| 47 | + writeResult(result, outputPath + "/" + frontType.name()); | ||
| 48 | + } | ||
| 49 | + // 断言:组选项不能变成 boolean Checkbox,必填数字不能被 Zod 推导为 null | ||
| 50 | + String data = findFile(result, "/data.ts"); | ||
| 51 | + assertTrue(data.contains("component: 'CheckboxGroup'")); | ||
| 52 | + assertFalse(data.contains("component: 'Checkbox',")); | ||
| 53 | + assertTrue(data.contains("rules: 'required'")); | ||
| 54 | + assertFalse(data.contains("z.number(")); | ||
| 55 | + if (frontType == CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA) { | ||
| 56 | + assertTrue(data.contains("isButton: true")); | ||
| 57 | + assertFalse(data.contains("buttonStyle:")); | ||
| 58 | + assertFalse(data.contains("optionType:")); | ||
| 59 | + assertFalse(data.contains("allowClear:")); | ||
| 60 | + } else { | ||
| 61 | + assertTrue(data.contains("optionType: 'button'")); | ||
| 62 | + assertFalse(data.contains("clearable:")); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @Test | ||
| 67 | + public void testExecute_eleTreeParentSelectable() { | ||
| 68 | + // 准备参数 | ||
| 69 | + CodegenTableDO table = getTable("category").setFrontType(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType()) | ||
| 70 | + .setTemplateType(CodegenTemplateTypeEnum.TREE.getType()); | ||
| 71 | + // 调用 | ||
| 72 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("category"), null, null); | ||
| 73 | + // 断言:父节点可作为上级,使用 Element Plus 属性 | ||
| 74 | + String data = findFile(result, "/data.ts"); | ||
| 75 | + assertTrue(data.contains("defaultExpandAll: true")); | ||
| 76 | + assertTrue(data.contains("checkStrictly: true")); | ||
| 77 | + assertFalse(data.contains("treeDefaultExpandAll")); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + @ParameterizedTest | ||
| 81 | + @EnumSource(value = CodegenFrontTypeEnum.class, names = { | ||
| 82 | + "VUE3_VBEN5_ANTD_SCHEMA", "VUE3_VBEN5_ANTD_GENERAL", | ||
| 83 | + "VUE3_VBEN5_ANTDV_NEXT_SCHEMA", "VUE3_VBEN5_ANTDV_NEXT_GENERAL", | ||
| 84 | + "VUE3_VBEN5_EP_SCHEMA", "VUE3_VBEN5_EP_GENERAL"}) | ||
| 85 | + public void testExecute_importRemovalClearsPayload(CodegenFrontTypeEnum frontType) { | ||
| 86 | + // 准备参数 | ||
| 87 | + codegenProperties.setImportEnable(true); | ||
| 88 | + codegenEngine.initGlobalBindingMap(); | ||
| 89 | + CodegenTableDO table = getTable("student").setFrontType(frontType.getType()) | ||
| 90 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | ||
| 91 | + // 调用 | ||
| 92 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), null, null); | ||
| 93 | + // 断言:移除可视文件时也清空提交来源 | ||
| 94 | + String form = findFile(result, "/import-form.vue"); | ||
| 95 | + assertTrue(form.contains(":on-remove=\"handleRemove\"")); | ||
| 96 | + assertTrue(form.contains("formApi.setFieldValue('file', undefined)") || form.contains("fileRef.value = null")); | ||
| 97 | + if (frontType == CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA | ||
| 98 | + || frontType == CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL) { | ||
| 99 | + assertTrue(form.contains(":on-exceed=\"handleExceed\"")); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @ParameterizedTest | ||
| 104 | + @EnumSource(value = CodegenFrontTypeEnum.class, names = { | ||
| 105 | + "VUE3_VBEN5_ANTD_SCHEMA", "VUE3_VBEN5_ANTD_GENERAL", | ||
| 106 | + "VUE3_VBEN5_ANTDV_NEXT_SCHEMA", "VUE3_VBEN5_ANTDV_NEXT_GENERAL", | ||
| 107 | + "VUE3_VBEN5_EP_SCHEMA", "VUE3_VBEN5_EP_GENERAL"}) | ||
| 108 | + public void testExecute_masterChildEditing(CodegenFrontTypeEnum frontType) { | ||
| 109 | + // 准备参数:一对多联系人和一对一班主任 | ||
| 110 | + CodegenTableDO table = getTable("student").setFrontType(frontType.getType()) | ||
| 111 | + .setTemplateType(CodegenTemplateTypeEnum.MASTER_NORMAL.getType()); | ||
| 112 | + CodegenTableDO contact = getTable("contact").setFrontType(frontType.getType()) | ||
| 113 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()).setSubJoinColumnId(100L).setSubJoinMany(true); | ||
| 114 | + CodegenTableDO teacher = getTable("teacher").setFrontType(frontType.getType()) | ||
| 115 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()).setSubJoinColumnId(200L).setSubJoinMany(false); | ||
| 116 | + // 调用 | ||
| 117 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), | ||
| 118 | + List.of(contact, teacher), List.of(getColumnList("contact"), getColumnList("teacher"))); | ||
| 119 | + // 断言:新增和删除以当前表格为准,不重复追加,新增临时编号不提交 | ||
| 120 | + String form = findFile(result, "/student-contact-form.vue"); | ||
| 121 | + assertTrue(form.contains("getTableData()")); | ||
| 122 | + assertTrue(form.contains("inserted.has(row) ? { ...row, id: undefined } : { ...row }")); | ||
| 123 | + assertFalse(form.contains("getRemoveRecords()")); | ||
| 124 | + assertFalse(form.contains(".concat(insertRecords")); | ||
| 125 | + assertFalse(form.contains("$dictType")); | ||
| 126 | + assertTrue(form.contains("getStudentContactListByStudentId")); | ||
| 127 | + if (frontType.name().endsWith("SCHEMA")) { | ||
| 128 | + assertTrue(form.contains("<template #actions=")); | ||
| 129 | + } | ||
| 130 | + result.forEach((path, content) -> { | ||
| 131 | + if (path.endsWith(".vue") || path.endsWith("data.ts")) { | ||
| 132 | + assertFalse(content.contains("#/api/infra/student"), path + ":API 导入必须匹配生成目录"); | ||
| 133 | + assertFalse(content.contains("VxeTableGridOptions<StudentApi.StudentContact>") && content.contains("import type { InfraStudentApi }"), | ||
| 134 | + path + ":子表命名空间应与导入一致"); | ||
| 135 | + } | ||
| 136 | + }); | ||
| 137 | + if (frontType == CodegenFrontTypeEnum.VUE3_VBEN5_ANTDV_NEXT_GENERAL) { | ||
| 138 | + assertTrue(form.matches("(?s).*import\\s*\\{[^}]*\\bmessage\\b[^}]*}\\s*from 'antdv-next'.*"), | ||
| 139 | + "子表校验提示必须导入实际的消息组件"); | ||
| 140 | + } | ||
| 141 | + if (frontType == CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL) { | ||
| 142 | + assertTrue(form.contains(":icon=\"Plus\"")); | ||
| 143 | + assertFalse(form.contains("h(Plus)"), "图标使用导入的组件,避免未绑定的 h"); | ||
| 144 | + } | ||
| 145 | + assertTrue(form.contains("function validate(): boolean")); | ||
| 146 | + assertTrue(form.contains("=== undefined")); | ||
| 147 | + assertTrue(form.contains("loadData([])") || form.contains("list.value = []")); | ||
| 148 | + String parentForm = findFile(result, "/modules/form.vue"); | ||
| 149 | + assertTrue(parentForm.contains("studentContactFormRef.value?.validate()")); | ||
| 150 | + assertFalse(parentForm.contains("TODO 列表值校验")); | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + @ParameterizedTest | ||
| 154 | + @EnumSource(value = CodegenTemplateTypeEnum.class, names = { "MASTER_ERP", "MASTER_INNER" }) | ||
| 155 | + public void testExecute_eleChildListImports(CodegenTemplateTypeEnum templateType) { | ||
| 156 | + // 准备参数 | ||
| 157 | + CodegenFrontTypeEnum frontType = CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL; | ||
| 158 | + CodegenTableDO table = getTable("student").setFrontType(frontType.getType()) | ||
| 159 | + .setTemplateType(templateType.getType()); | ||
| 160 | + CodegenTableDO contact = getTable("contact").setFrontType(frontType.getType()) | ||
| 161 | + .setTemplateType(CodegenTemplateTypeEnum.SUB.getType()).setSubJoinColumnId(100L).setSubJoinMany(true); | ||
| 162 | + // 调用 | ||
| 163 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), | ||
| 164 | + List.of(contact), List.of(getColumnList("contact"))); | ||
| 165 | + // 断言:ERP 子表查询实际调用的工具必须导入 | ||
| 166 | + String index = findFile(result, "/index.vue"); | ||
| 167 | + assertTrue(index.contains("<VbenVxeTableToolbar")); | ||
| 168 | + assertTrue(index.contains("</VbenVxeTableToolbar>")); | ||
| 169 | + assertFalse(index.contains("<TableToolbar")); | ||
| 170 | + String list = findFile(result, "/student-contact-list.vue"); | ||
| 171 | + if (templateType == CodegenTemplateTypeEnum.MASTER_ERP) { | ||
| 172 | + assertTrue(list.contains("<VbenVxeTableToolbar")); | ||
| 173 | + assertTrue(list.contains("</VbenVxeTableToolbar>")); | ||
| 174 | + assertFalse(list.contains("</TableToolbar>")); | ||
| 175 | + assertTrue(list.contains("cloneDeep(queryParams)")); | ||
| 176 | + assertTrue(list.matches("(?s).*import\\s*\\{[^}]*\\bcloneDeep\\b[^}]*}\\s*from '@vben/utils'.*")); | ||
| 177 | + } | ||
| 178 | + assertTrue(list.contains("formatDateTime(row.")); | ||
| 179 | + assertTrue(list.matches("(?s).*import\\s*\\{[^}]*\\bformatDateTime\\b[^}]*}\\s*from '@vben/utils'.*")); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + @Test | ||
| 183 | + public void testExecute_vue3ImportUploadResponse() { | ||
| 184 | + // 准备参数 | ||
| 185 | + codegenProperties.setImportEnable(true); | ||
| 186 | + codegenEngine.initGlobalBindingMap(); | ||
| 187 | + CodegenTableDO table = getTable("student").setFrontType(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType()) | ||
| 188 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | ||
| 189 | + // 调用 | ||
| 190 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), null, null); | ||
| 191 | + // 断言 | ||
| 192 | + String form = findFile(result, "/StudentImportForm.vue"); | ||
| 193 | + assertTrue(form.contains("const res = await StudentApi.importStudent(formData)")); | ||
| 194 | + assertTrue(form.contains("const data = res.data")); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + | ||
| 198 | + @Test | ||
| 199 | + public void testExecute_vben2DateRangeFormat() { | ||
| 200 | + // 准备参数 | ||
| 201 | + CodegenTableDO table = getTable("student").setFrontType(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType()) | ||
| 202 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | ||
| 203 | + // 调用 | ||
| 204 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), null, null); | ||
| 205 | + // 断言:查询区间提交后端需要的时间字符串 | ||
| 206 | + String data = findFile(result, ".data.ts"); | ||
| 207 | + assertTrue(data.contains("valueFormat: 'YYYY-MM-DD HH:mm:ss'")); | ||
| 208 | + assertTrue(data.contains("allowClear: true")); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + @Test | ||
| 212 | + public void testExecute_uniappPaginationContract() { | ||
| 213 | + // 准备参数 | ||
| 214 | + CodegenTableDO table = getTable("student").setFrontType(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType()) | ||
| 215 | + .setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); | ||
| 216 | + // 调用 | ||
| 217 | + Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, getColumnList("student"), null, null); | ||
| 218 | + // 断言:移动端已有分页/失败恢复契约保持有效,避免机械套用 PC 组件写法 | ||
| 219 | + String api = findFile(result, "/index.ts"); | ||
| 220 | + assertTrue(api.contains("params: PageParam")); | ||
| 221 | + assertFalse(api.contains("PageReqVO")); | ||
| 222 | + String list = result.entrySet().stream() | ||
| 223 | + .filter(entry -> entry.getKey().endsWith("/index.vue") && entry.getValue().contains("<z-paging")) | ||
| 224 | + .findFirst().orElseThrow().getValue(); | ||
| 225 | + assertTrue(list.contains("completeByTotal(data.list, data.total)")); | ||
| 226 | + assertTrue(list.contains("complete(false)")); | ||
| 227 | + assertTrue(list.contains("uni.$off(")); | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + private static String findFile(Map<String, String> result, String suffix) { | ||
| 231 | + return result.entrySet().stream().filter(entry -> entry.getKey().endsWith(suffix)) | ||
| 232 | + .findFirst().orElseThrow(() -> new AssertionError("缺少生成文件:" + suffix)).getValue(); | ||
| 233 | + } | ||
| 234 | +} |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/vue/index
| @@ -35,12 +35,11 @@ const total = ref(0) // 列表的总页数 | @@ -35,12 +35,11 @@ const total = ref(0) // 列表的总页数 | ||
| 35 | const queryParams = reactive({ | 35 | const queryParams = reactive({ |
| 36 | pageNo: 1, | 36 | pageNo: 1, |
| 37 | pageSize: 10, | 37 | pageSize: 10, |
| 38 | - name: undefined, | ||
| 39 | - birthday: undefined, | ||
| 40 | - birthday: undefined, | ||
| 41 | - sex: undefined, | ||
| 42 | - enabled: undefined, | ||
| 43 | - createTime: undefined, | 38 | + name: undefined, |
| 39 | + birthday: undefined, | ||
| 40 | + sex: undefined, | ||
| 41 | + enabled: undefined, | ||
| 42 | + createTime: undefined, | ||
| 44 | }) | 43 | }) |
| 45 | const queryFormRef = ref() // 搜索的表单 | 44 | const queryFormRef = ref() // 搜索的表单 |
| 46 | const exportLoading = ref(false) // 导出的加载中 | 45 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -136,7 +135,14 @@ function handleRowCheckboxChange({ | @@ -136,7 +135,14 @@ function handleRowCheckboxChange({ | ||
| 136 | async function handleExport() { | 135 | async function handleExport() { |
| 137 | try { | 136 | try { |
| 138 | exportLoading.value = true; | 137 | exportLoading.value = true; |
| 139 | - const data = await exportStudent(queryParams); | 138 | + const params = cloneDeep(queryParams) as any; |
| 139 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 140 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 141 | + } | ||
| 142 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 143 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 144 | + } | ||
| 145 | + const data = await exportStudent(params); | ||
| 140 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 146 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 141 | }finally { | 147 | }finally { |
| 142 | exportLoading.value = false; | 148 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/vue/form
| @@ -72,7 +72,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -72,7 +72,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 72 | async onConfirm() { | 72 | async onConfirm() { |
| 73 | await formRef.value?.validate(); | 73 | await formRef.value?.validate(); |
| 74 | // 校验子表单 | 74 | // 校验子表单 |
| 75 | - try { | 75 | + if (!studentContactFormRef.value?.validate()) { |
| 76 | + subTabsName.value = 'studentContact'; | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + try { | ||
| 76 | await studentTeacherFormRef.value?.validate() | 80 | await studentTeacherFormRef.value?.validate() |
| 77 | } catch (e) { | 81 | } catch (e) { |
| 78 | subTabsName.value = 'studentTeacher' | 82 | subTabsName.value = 'studentTeacher' |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/vue/index
| @@ -31,12 +31,11 @@ const total = ref(0) // 列表的总页数 | @@ -31,12 +31,11 @@ const total = ref(0) // 列表的总页数 | ||
| 31 | const queryParams = reactive({ | 31 | const queryParams = reactive({ |
| 32 | pageNo: 1, | 32 | pageNo: 1, |
| 33 | pageSize: 10, | 33 | pageSize: 10, |
| 34 | - name: undefined, | ||
| 35 | - birthday: undefined, | ||
| 36 | - birthday: undefined, | ||
| 37 | - sex: undefined, | ||
| 38 | - enabled: undefined, | ||
| 39 | - createTime: undefined, | 34 | + name: undefined, |
| 35 | + birthday: undefined, | ||
| 36 | + sex: undefined, | ||
| 37 | + enabled: undefined, | ||
| 38 | + createTime: undefined, | ||
| 40 | }) | 39 | }) |
| 41 | const queryFormRef = ref() // 搜索的表单 | 40 | const queryFormRef = ref() // 搜索的表单 |
| 42 | const exportLoading = ref(false) // 导出的加载中 | 41 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -132,7 +131,14 @@ function handleRowCheckboxChange({ | @@ -132,7 +131,14 @@ function handleRowCheckboxChange({ | ||
| 132 | async function handleExport() { | 131 | async function handleExport() { |
| 133 | try { | 132 | try { |
| 134 | exportLoading.value = true; | 133 | exportLoading.value = true; |
| 135 | - const data = await exportStudent(queryParams); | 134 | + const params = cloneDeep(queryParams) as any; |
| 135 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 136 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 137 | + } | ||
| 138 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 139 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 140 | + } | ||
| 141 | + const data = await exportStudent(params); | ||
| 136 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 142 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 137 | }finally { | 143 | }finally { |
| 138 | exportLoading.value = false; | 144 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/vue/student-contact-form
| @@ -32,25 +32,96 @@ async function handleDelete(row: StudentApi.StudentContact) { | @@ -32,25 +32,96 @@ async function handleDelete(row: StudentApi.StudentContact) { | ||
| 32 | await tableRef.value?.remove(row); | 32 | await tableRef.value?.remove(row); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 36 | -defineExpose({ | ||
| 37 | - getData: (): StudentApi.StudentContact[] => { | ||
| 38 | - const data = list.value as StudentApi.StudentContact[]; | ||
| 39 | - const removeRecords = tableRef.value?.getRemoveRecords() as StudentApi.StudentContact[]; | ||
| 40 | - const insertRecords = tableRef.value?.getInsertRecords() as StudentApi.StudentContact[]; | ||
| 41 | - return [ | ||
| 42 | - ...data.filter( | ||
| 43 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 44 | - ), | ||
| 45 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 46 | - ]; | ||
| 47 | - }, | ||
| 48 | -}); | 35 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 36 | +function getData(): StudentApi.StudentContact[] { | ||
| 37 | + const table = tableRef.value; | ||
| 38 | + if (!table) { | ||
| 39 | + return []; | ||
| 40 | + } | ||
| 41 | + const { fullData } = table.getTableData(); | ||
| 42 | + const inserted = new Set(table.getInsertRecords()); | ||
| 43 | + return fullData.map((row) => | ||
| 44 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 45 | + ); | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +/** 校验子表必填字段 */ | ||
| 49 | +function validate(): boolean { | ||
| 50 | + for (const [index, row] of getData().entries()) { | ||
| 51 | + if ( | ||
| 52 | + row.name === null || | ||
| 53 | + row.name === undefined || | ||
| 54 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 55 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 56 | + ) { | ||
| 57 | + message.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | + if ( | ||
| 61 | + row.description === null || | ||
| 62 | + row.description === undefined || | ||
| 63 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 64 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 65 | + ) { | ||
| 66 | + message.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.birthday === null || | ||
| 71 | + row.birthday === undefined || | ||
| 72 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 73 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 74 | + ) { | ||
| 75 | + message.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.sex === null || | ||
| 80 | + row.sex === undefined || | ||
| 81 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 82 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 83 | + ) { | ||
| 84 | + message.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.enabled === null || | ||
| 89 | + row.enabled === undefined || | ||
| 90 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 91 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 92 | + ) { | ||
| 93 | + message.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.avatar === null || | ||
| 98 | + row.avatar === undefined || | ||
| 99 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 100 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 101 | + ) { | ||
| 102 | + message.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.memo === null || | ||
| 107 | + row.memo === undefined || | ||
| 108 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 109 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 110 | + ) { | ||
| 111 | + message.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + return true; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +defineExpose({ getData, validate }); | ||
| 49 | 119 | ||
| 50 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 120 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 51 | watch( | 121 | watch( |
| 52 | () => props.studentId, | 122 | () => props.studentId, |
| 53 | async (val) => { | 123 | async (val) => { |
| 124 | + list.value = []; | ||
| 54 | if (!val) { | 125 | if (!val) { |
| 55 | return; | 126 | return; |
| 56 | } | 127 | } |
| @@ -86,7 +157,7 @@ watch( | @@ -86,7 +157,7 @@ watch( | ||
| 86 | <template #default="{ row }"> | 157 | <template #default="{ row }"> |
| 87 | <Select v-model:value="row.sex" placeholder="请选择性别"> | 158 | <Select v-model:value="row.sex" placeholder="请选择性别"> |
| 88 | <Select.Option | 159 | <Select.Option |
| 89 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number')" | 160 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 90 | :key="dict.value" | 161 | :key="dict.value" |
| 91 | :value="dict.value" | 162 | :value="dict.value" |
| 92 | > | 163 | > |
| @@ -99,7 +170,7 @@ watch( | @@ -99,7 +170,7 @@ watch( | ||
| 99 | <template #default="{ row }"> | 170 | <template #default="{ row }"> |
| 100 | <RadioGroup v-model:value="row.enabled"> | 171 | <RadioGroup v-model:value="row.enabled"> |
| 101 | <Radio | 172 | <Radio |
| 102 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'boolean')" | 173 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 103 | :key="dict.value" | 174 | :key="dict.value" |
| 104 | :value="dict.value" | 175 | :value="dict.value" |
| 105 | > | 176 | > |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/vue/student-teacher-form
| @@ -51,6 +51,18 @@ defineExpose({ | @@ -51,6 +51,18 @@ defineExpose({ | ||
| 51 | watch( | 51 | watch( |
| 52 | () => props.studentId, | 52 | () => props.studentId, |
| 53 | async (val) => { | 53 | async (val) => { |
| 54 | + formData.value = { | ||
| 55 | + id: undefined, | ||
| 56 | + studentId: undefined, | ||
| 57 | + name: undefined, | ||
| 58 | + description: undefined, | ||
| 59 | + birthday: undefined, | ||
| 60 | + sex: undefined, | ||
| 61 | + enabled: undefined, | ||
| 62 | + avatar: undefined, | ||
| 63 | + video: undefined, | ||
| 64 | + memo: undefined, | ||
| 65 | + }; | ||
| 54 | if (!val) { | 66 | if (!val) { |
| 55 | return; | 67 | return; |
| 56 | } | 68 | } |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/vue/form
| @@ -72,7 +72,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -72,7 +72,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 72 | async onConfirm() { | 72 | async onConfirm() { |
| 73 | await formRef.value?.validate(); | 73 | await formRef.value?.validate(); |
| 74 | // 校验子表单 | 74 | // 校验子表单 |
| 75 | - try { | 75 | + if (!studentContactFormRef.value?.validate()) { |
| 76 | + subTabsName.value = 'studentContact'; | ||
| 77 | + return; | ||
| 78 | + } | ||
| 79 | + try { | ||
| 76 | await studentTeacherFormRef.value?.validate() | 80 | await studentTeacherFormRef.value?.validate() |
| 77 | } catch (e) { | 81 | } catch (e) { |
| 78 | subTabsName.value = 'studentTeacher' | 82 | subTabsName.value = 'studentTeacher' |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/vue/index
| @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | ||
| 27 | const queryParams = reactive({ | 27 | const queryParams = reactive({ |
| 28 | pageNo: 1, | 28 | pageNo: 1, |
| 29 | pageSize: 10, | 29 | pageSize: 10, |
| 30 | - name: undefined, | ||
| 31 | - birthday: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - sex: undefined, | ||
| 34 | - enabled: undefined, | ||
| 35 | - createTime: undefined, | 30 | + name: undefined, |
| 31 | + birthday: undefined, | ||
| 32 | + sex: undefined, | ||
| 33 | + enabled: undefined, | ||
| 34 | + createTime: undefined, | ||
| 36 | }) | 35 | }) |
| 37 | const queryFormRef = ref() // 搜索的表单 | 36 | const queryFormRef = ref() // 搜索的表单 |
| 38 | const exportLoading = ref(false) // 导出的加载中 | 37 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -128,7 +127,14 @@ function handleRowCheckboxChange({ | @@ -128,7 +127,14 @@ function handleRowCheckboxChange({ | ||
| 128 | async function handleExport() { | 127 | async function handleExport() { |
| 129 | try { | 128 | try { |
| 130 | exportLoading.value = true; | 129 | exportLoading.value = true; |
| 131 | - const data = await exportStudent(queryParams); | 130 | + const params = cloneDeep(queryParams) as any; |
| 131 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 132 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 133 | + } | ||
| 134 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 135 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 136 | + } | ||
| 137 | + const data = await exportStudent(params); | ||
| 132 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 138 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 133 | }finally { | 139 | }finally { |
| 134 | exportLoading.value = false; | 140 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/vue/student-contact-form
| @@ -32,25 +32,96 @@ async function handleDelete(row: StudentApi.StudentContact) { | @@ -32,25 +32,96 @@ async function handleDelete(row: StudentApi.StudentContact) { | ||
| 32 | await tableRef.value?.remove(row); | 32 | await tableRef.value?.remove(row); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 36 | -defineExpose({ | ||
| 37 | - getData: (): StudentApi.StudentContact[] => { | ||
| 38 | - const data = list.value as StudentApi.StudentContact[]; | ||
| 39 | - const removeRecords = tableRef.value?.getRemoveRecords() as StudentApi.StudentContact[]; | ||
| 40 | - const insertRecords = tableRef.value?.getInsertRecords() as StudentApi.StudentContact[]; | ||
| 41 | - return [ | ||
| 42 | - ...data.filter( | ||
| 43 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 44 | - ), | ||
| 45 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 46 | - ]; | ||
| 47 | - }, | ||
| 48 | -}); | 35 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 36 | +function getData(): StudentApi.StudentContact[] { | ||
| 37 | + const table = tableRef.value; | ||
| 38 | + if (!table) { | ||
| 39 | + return []; | ||
| 40 | + } | ||
| 41 | + const { fullData } = table.getTableData(); | ||
| 42 | + const inserted = new Set(table.getInsertRecords()); | ||
| 43 | + return fullData.map((row) => | ||
| 44 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 45 | + ); | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +/** 校验子表必填字段 */ | ||
| 49 | +function validate(): boolean { | ||
| 50 | + for (const [index, row] of getData().entries()) { | ||
| 51 | + if ( | ||
| 52 | + row.name === null || | ||
| 53 | + row.name === undefined || | ||
| 54 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 55 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 56 | + ) { | ||
| 57 | + message.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | + if ( | ||
| 61 | + row.description === null || | ||
| 62 | + row.description === undefined || | ||
| 63 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 64 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 65 | + ) { | ||
| 66 | + message.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.birthday === null || | ||
| 71 | + row.birthday === undefined || | ||
| 72 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 73 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 74 | + ) { | ||
| 75 | + message.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.sex === null || | ||
| 80 | + row.sex === undefined || | ||
| 81 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 82 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 83 | + ) { | ||
| 84 | + message.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.enabled === null || | ||
| 89 | + row.enabled === undefined || | ||
| 90 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 91 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 92 | + ) { | ||
| 93 | + message.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.avatar === null || | ||
| 98 | + row.avatar === undefined || | ||
| 99 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 100 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 101 | + ) { | ||
| 102 | + message.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.memo === null || | ||
| 107 | + row.memo === undefined || | ||
| 108 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 109 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 110 | + ) { | ||
| 111 | + message.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + return true; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +defineExpose({ getData, validate }); | ||
| 49 | 119 | ||
| 50 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 120 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 51 | watch( | 121 | watch( |
| 52 | () => props.studentId, | 122 | () => props.studentId, |
| 53 | async (val) => { | 123 | async (val) => { |
| 124 | + list.value = []; | ||
| 54 | if (!val) { | 125 | if (!val) { |
| 55 | return; | 126 | return; |
| 56 | } | 127 | } |
| @@ -86,7 +157,7 @@ watch( | @@ -86,7 +157,7 @@ watch( | ||
| 86 | <template #default="{ row }"> | 157 | <template #default="{ row }"> |
| 87 | <Select v-model:value="row.sex" placeholder="请选择性别"> | 158 | <Select v-model:value="row.sex" placeholder="请选择性别"> |
| 88 | <Select.Option | 159 | <Select.Option |
| 89 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number')" | 160 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 90 | :key="dict.value" | 161 | :key="dict.value" |
| 91 | :value="dict.value" | 162 | :value="dict.value" |
| 92 | > | 163 | > |
| @@ -99,7 +170,7 @@ watch( | @@ -99,7 +170,7 @@ watch( | ||
| 99 | <template #default="{ row }"> | 170 | <template #default="{ row }"> |
| 100 | <RadioGroup v-model:value="row.enabled"> | 171 | <RadioGroup v-model:value="row.enabled"> |
| 101 | <Radio | 172 | <Radio |
| 102 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'boolean')" | 173 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 103 | :key="dict.value" | 174 | :key="dict.value" |
| 104 | :value="dict.value" | 175 | :value="dict.value" |
| 105 | > | 176 | > |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/vue/student-teacher-form
| @@ -51,6 +51,18 @@ defineExpose({ | @@ -51,6 +51,18 @@ defineExpose({ | ||
| 51 | watch( | 51 | watch( |
| 52 | () => props.studentId, | 52 | () => props.studentId, |
| 53 | async (val) => { | 53 | async (val) => { |
| 54 | + formData.value = { | ||
| 55 | + id: undefined, | ||
| 56 | + studentId: undefined, | ||
| 57 | + name: undefined, | ||
| 58 | + description: undefined, | ||
| 59 | + birthday: undefined, | ||
| 60 | + sex: undefined, | ||
| 61 | + enabled: undefined, | ||
| 62 | + avatar: undefined, | ||
| 63 | + video: undefined, | ||
| 64 | + memo: undefined, | ||
| 65 | + }; | ||
| 54 | if (!val) { | 66 | if (!val) { |
| 55 | return; | 67 | return; |
| 56 | } | 68 | } |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/vue/index
| @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | ||
| 27 | const queryParams = reactive({ | 27 | const queryParams = reactive({ |
| 28 | pageNo: 1, | 28 | pageNo: 1, |
| 29 | pageSize: 10, | 29 | pageSize: 10, |
| 30 | - name: undefined, | ||
| 31 | - birthday: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - sex: undefined, | ||
| 34 | - enabled: undefined, | ||
| 35 | - createTime: undefined, | 30 | + name: undefined, |
| 31 | + birthday: undefined, | ||
| 32 | + sex: undefined, | ||
| 33 | + enabled: undefined, | ||
| 34 | + createTime: undefined, | ||
| 36 | }) | 35 | }) |
| 37 | const queryFormRef = ref() // 搜索的表单 | 36 | const queryFormRef = ref() // 搜索的表单 |
| 38 | const exportLoading = ref(false) // 导出的加载中 | 37 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -128,7 +127,14 @@ function handleRowCheckboxChange({ | @@ -128,7 +127,14 @@ function handleRowCheckboxChange({ | ||
| 128 | async function handleExport() { | 127 | async function handleExport() { |
| 129 | try { | 128 | try { |
| 130 | exportLoading.value = true; | 129 | exportLoading.value = true; |
| 131 | - const data = await exportStudent(queryParams); | 130 | + const params = cloneDeep(queryParams) as any; |
| 131 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 132 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 133 | + } | ||
| 134 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 135 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 136 | + } | ||
| 137 | + const data = await exportStudent(params); | ||
| 132 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 138 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 133 | }finally { | 139 | }finally { |
| 134 | exportLoading.value = false; | 140 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/vue/import-form
| @@ -48,6 +48,11 @@ function beforeUpload(file: FileType) { | @@ -48,6 +48,11 @@ function beforeUpload(file: FileType) { | ||
| 48 | return false; | 48 | return false; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | +/** 移除文件 */ | ||
| 52 | +function handleRemove() { | ||
| 53 | + fileRef.value = null; | ||
| 54 | +} | ||
| 55 | + | ||
| 51 | /** 下载导入模板 */ | 56 | /** 下载导入模板 */ |
| 52 | async function handleDownload() { | 57 | async function handleDownload() { |
| 53 | const data = await importStudentTemplate(); | 58 | const data = await importStudentTemplate(); |
| @@ -58,7 +63,12 @@ async function handleDownload() { | @@ -58,7 +63,12 @@ async function handleDownload() { | ||
| 58 | <template> | 63 | <template> |
| 59 | <Modal title="导入学生" class="w-1/3"> | 64 | <Modal title="导入学生" class="w-1/3"> |
| 60 | <div class="mx-4"> | 65 | <div class="mx-4"> |
| 61 | - <Upload :max-count="1" accept=".xls,.xlsx" :before-upload="beforeUpload"> | 66 | + <Upload |
| 67 | + :max-count="1" | ||
| 68 | + accept=".xls,.xlsx" | ||
| 69 | + :before-upload="beforeUpload" | ||
| 70 | + :on-remove="handleRemove" | ||
| 71 | + > | ||
| 62 | <Button type="primary"> 选择 Excel 文件 </Button> | 72 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 63 | </Upload> | 73 | </Upload> |
| 64 | </div> | 74 | </div> |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/vue/index
| @@ -28,12 +28,11 @@ const total = ref(0) // 列表的总页数 | @@ -28,12 +28,11 @@ const total = ref(0) // 列表的总页数 | ||
| 28 | const queryParams = reactive({ | 28 | const queryParams = reactive({ |
| 29 | pageNo: 1, | 29 | pageNo: 1, |
| 30 | pageSize: 10, | 30 | pageSize: 10, |
| 31 | - name: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - birthday: undefined, | ||
| 34 | - sex: undefined, | ||
| 35 | - enabled: undefined, | ||
| 36 | - createTime: undefined, | 31 | + name: undefined, |
| 32 | + birthday: undefined, | ||
| 33 | + sex: undefined, | ||
| 34 | + enabled: undefined, | ||
| 35 | + createTime: undefined, | ||
| 37 | }) | 36 | }) |
| 38 | const queryFormRef = ref() // 搜索的表单 | 37 | const queryFormRef = ref() // 搜索的表单 |
| 39 | const exportLoading = ref(false) // 导出的加载中 | 38 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -138,7 +137,14 @@ function handleRowCheckboxChange({ | @@ -138,7 +137,14 @@ function handleRowCheckboxChange({ | ||
| 138 | async function handleExport() { | 137 | async function handleExport() { |
| 139 | try { | 138 | try { |
| 140 | exportLoading.value = true; | 139 | exportLoading.value = true; |
| 141 | - const data = await exportStudent(queryParams); | 140 | + const params = cloneDeep(queryParams) as any; |
| 141 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 142 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 143 | + } | ||
| 144 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 145 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 146 | + } | ||
| 147 | + const data = await exportStudent(params); | ||
| 142 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 148 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 143 | }finally { | 149 | }finally { |
| 144 | exportLoading.value = false; | 150 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/vue/index
| @@ -24,7 +24,7 @@ const loading = ref(true) // 列表的加载中 | @@ -24,7 +24,7 @@ const loading = ref(true) // 列表的加载中 | ||
| 24 | const list = ref<any[]>([]) // 树列表的数据 | 24 | const list = ref<any[]>([]) // 树列表的数据 |
| 25 | 25 | ||
| 26 | const queryParams = reactive({ | 26 | const queryParams = reactive({ |
| 27 | - name: undefined, | 27 | + name: undefined, |
| 28 | }) | 28 | }) |
| 29 | const queryFormRef = ref() // 搜索的表单 | 29 | const queryFormRef = ref() // 搜索的表单 |
| 30 | const exportLoading = ref(false) // 导出的加载中 | 30 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -91,7 +91,8 @@ async function handleDelete(row: CategoryApi.Category) { | @@ -91,7 +91,8 @@ async function handleDelete(row: CategoryApi.Category) { | ||
| 91 | async function handleExport() { | 91 | async function handleExport() { |
| 92 | try { | 92 | try { |
| 93 | exportLoading.value = true; | 93 | exportLoading.value = true; |
| 94 | - const data = await exportCategory(queryParams); | 94 | + const params = cloneDeep(queryParams) as any; |
| 95 | + const data = await exportCategory(params); | ||
| 95 | downloadFileFromBlobPart({ fileName: '分类.xls', source: data }); | 96 | downloadFileFromBlobPart({ fileName: '分类.xls', source: data }); |
| 96 | }finally { | 97 | }finally { |
| 97 | exportLoading.value = false; | 98 | exportLoading.value = false; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { message, Tabs } from 'ant-design-vue'; | 8 | +import { message } from 'ant-design-vue'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/ts/data
| @@ -269,7 +269,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -269,7 +269,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 269 | minWidth: 120, | 269 | minWidth: 120, |
| 270 | slots: { default: 'sex' }, | 270 | slots: { default: 'sex' }, |
| 271 | params: { | 271 | params: { |
| 272 | - options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'boolean'), | 272 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), |
| 273 | }, | 273 | }, |
| 274 | }, | 274 | }, |
| 275 | { | 275 | { |
| @@ -309,7 +309,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -309,7 +309,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /** 列表的字段 */ | 311 | /** 列表的字段 */ |
| 312 | - export function useStudentContactGridColumns(): VxeTableGridOptions<StudentApi.StudentContact>['columns'] { | 312 | + export function useStudentContactGridColumns(): VxeTableGridOptions<InfraStudentApi.StudentContact>['columns'] { |
| 313 | return [ | 313 | return [ |
| 314 | { | 314 | { |
| 315 | field: 'id', | 315 | field: 'id', |
| @@ -490,7 +490,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -490,7 +490,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | /** 列表的字段 */ | 492 | /** 列表的字段 */ |
| 493 | - export function useStudentTeacherGridColumns(): VxeTableGridOptions<StudentApi.StudentTeacher>['columns'] { | 493 | + export function useStudentTeacherGridColumns(): VxeTableGridOptions<InfraStudentApi.StudentTeacher>['columns'] { |
| 494 | return [ | 494 | return [ |
| 495 | { | 495 | { |
| 496 | field: 'id', | 496 | field: 'id', |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { message } from 'ant-design-vue'; | 8 | +import { message, Tabs } from 'ant-design-vue'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
| @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 48 | return; | 48 | return; |
| 49 | } | 49 | } |
| 50 | // 校验子表单 | 50 | // 校验子表单 |
| 51 | - const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | 51 | + const studentContactValid = await studentContactFormRef.value?.validate(); |
| 52 | + if (!studentContactValid) { | ||
| 53 | + subTabsName.value = 'studentContact'; | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | ||
| 52 | if (!studentTeacherValid) { | 57 | if (!studentTeacherValid) { |
| 53 | subTabsName.value = 'studentTeacher'; | 58 | subTabsName.value = 'studentTeacher'; |
| 54 | return; | 59 | return; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/vue/student-contact-form
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | import { $t } from '#/locales'; | 6 | import { $t } from '#/locales'; |
| 7 | 7 | ||
| 8 | import { Plus } from "@vben/icons"; | 8 | import { Plus } from "@vben/icons"; |
| 9 | -import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue'; | 9 | +import { Button, Checkbox, CheckboxGroup, DatePicker, Input, message, RadioGroup, Select, Tabs, Textarea } from 'ant-design-vue'; |
| 10 | import { ImageUpload, FileUpload } from "#/components/upload"; | 10 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 11 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 11 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 12 | import { useStudentContactGridEditColumns } from '../data'; | 12 | import { useStudentContactGridEditColumns } from '../data'; |
| @@ -45,26 +45,96 @@ const handleDelete = async (row: InfraStudentApi.StudentContact) => { | @@ -45,26 +45,96 @@ const handleDelete = async (row: InfraStudentApi.StudentContact) => { | ||
| 45 | await gridApi.grid.remove(row); | 45 | await gridApi.grid.remove(row); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 49 | -defineExpose({ | ||
| 50 | - getData: (): InfraStudentApi.StudentContact[] => { | ||
| 51 | - const data = gridApi.grid.getData() as InfraStudentApi.StudentContact[]; | ||
| 52 | - const removeRecords = gridApi.grid.getRemoveRecords() as InfraStudentApi.StudentContact[]; | ||
| 53 | - const insertRecords = gridApi.grid.getInsertRecords() as InfraStudentApi.StudentContact[]; | ||
| 54 | - return data | ||
| 55 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 56 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 57 | - }, | ||
| 58 | -}); | 48 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 49 | +function getData(): InfraStudentApi.StudentContact[] { | ||
| 50 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 51 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 52 | + return fullData.map((row) => | ||
| 53 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 54 | + ); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +/** 校验子表必填字段 */ | ||
| 58 | +function validate(): boolean { | ||
| 59 | + for (const [index, row] of getData().entries()) { | ||
| 60 | + if ( | ||
| 61 | + row.name === null || | ||
| 62 | + row.name === undefined || | ||
| 63 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 64 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 65 | + ) { | ||
| 66 | + message.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.description === null || | ||
| 71 | + row.description === undefined || | ||
| 72 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 73 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 74 | + ) { | ||
| 75 | + message.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.birthday === null || | ||
| 80 | + row.birthday === undefined || | ||
| 81 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 82 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 83 | + ) { | ||
| 84 | + message.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.sex === null || | ||
| 89 | + row.sex === undefined || | ||
| 90 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 91 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 92 | + ) { | ||
| 93 | + message.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.enabled === null || | ||
| 98 | + row.enabled === undefined || | ||
| 99 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 100 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 101 | + ) { | ||
| 102 | + message.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.avatar === null || | ||
| 107 | + row.avatar === undefined || | ||
| 108 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 109 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 110 | + ) { | ||
| 111 | + message.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + if ( | ||
| 115 | + row.memo === null || | ||
| 116 | + row.memo === undefined || | ||
| 117 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 118 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 119 | + ) { | ||
| 120 | + message.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 121 | + return false; | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + return true; | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +defineExpose({ getData, validate }); | ||
| 59 | 128 | ||
| 60 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 129 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 61 | watch( | 130 | watch( |
| 62 | () => props.studentId, | 131 | () => props.studentId, |
| 63 | async (val) => { | 132 | async (val) => { |
| 133 | + await nextTick(); | ||
| 64 | if (!val) { | 134 | if (!val) { |
| 135 | + await gridApi.grid.loadData([]); | ||
| 65 | return; | 136 | return; |
| 66 | } | 137 | } |
| 67 | - await nextTick(); | ||
| 68 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); | 138 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); |
| 69 | }, | 139 | }, |
| 70 | { immediate: true }, | 140 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/vue/student-teacher-form
| @@ -39,10 +39,11 @@ defineExpose({ | @@ -39,10 +39,11 @@ defineExpose({ | ||
| 39 | watch( | 39 | watch( |
| 40 | () => props.studentId, | 40 | () => props.studentId, |
| 41 | async (val) => { | 41 | async (val) => { |
| 42 | + await nextTick(); | ||
| 43 | + await formApi.resetForm(); | ||
| 42 | if (!val) { | 44 | if (!val) { |
| 43 | return; | 45 | return; |
| 44 | } | 46 | } |
| 45 | - await nextTick(); | ||
| 46 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); | 47 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); |
| 47 | }, | 48 | }, |
| 48 | { immediate: true }, | 49 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/ts/data
| @@ -268,7 +268,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -268,7 +268,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 268 | minWidth: 120, | 268 | minWidth: 120, |
| 269 | slots: { default: 'sex' }, | 269 | slots: { default: 'sex' }, |
| 270 | params: { | 270 | params: { |
| 271 | - options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'boolean'), | 271 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), |
| 272 | }, | 272 | }, |
| 273 | }, | 273 | }, |
| 274 | { | 274 | { |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { message } from 'ant-design-vue'; | 8 | +import { message, Tabs } from 'ant-design-vue'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
| @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 48 | return; | 48 | return; |
| 49 | } | 49 | } |
| 50 | // 校验子表单 | 50 | // 校验子表单 |
| 51 | - const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | 51 | + const studentContactValid = await studentContactFormRef.value?.validate(); |
| 52 | + if (!studentContactValid) { | ||
| 53 | + subTabsName.value = 'studentContact'; | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | ||
| 52 | if (!studentTeacherValid) { | 57 | if (!studentTeacherValid) { |
| 53 | subTabsName.value = 'studentTeacher'; | 58 | subTabsName.value = 'studentTeacher'; |
| 54 | return; | 59 | return; |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/vue/student-contact-form
| @@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
| 6 | import { $t } from '#/locales'; | 6 | import { $t } from '#/locales'; |
| 7 | 7 | ||
| 8 | import { Plus } from "@vben/icons"; | 8 | import { Plus } from "@vben/icons"; |
| 9 | -import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue'; | 9 | +import { Button, Checkbox, CheckboxGroup, DatePicker, Input, message, RadioGroup, Select, Tabs, Textarea } from 'ant-design-vue'; |
| 10 | import { ImageUpload, FileUpload } from "#/components/upload"; | 10 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 11 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 11 | import { useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 12 | import { useStudentContactGridEditColumns } from '../data'; | 12 | import { useStudentContactGridEditColumns } from '../data'; |
| @@ -45,26 +45,96 @@ const handleDelete = async (row: InfraStudentApi.StudentContact) => { | @@ -45,26 +45,96 @@ const handleDelete = async (row: InfraStudentApi.StudentContact) => { | ||
| 45 | await gridApi.grid.remove(row); | 45 | await gridApi.grid.remove(row); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 49 | -defineExpose({ | ||
| 50 | - getData: (): InfraStudentApi.StudentContact[] => { | ||
| 51 | - const data = gridApi.grid.getData() as InfraStudentApi.StudentContact[]; | ||
| 52 | - const removeRecords = gridApi.grid.getRemoveRecords() as InfraStudentApi.StudentContact[]; | ||
| 53 | - const insertRecords = gridApi.grid.getInsertRecords() as InfraStudentApi.StudentContact[]; | ||
| 54 | - return data | ||
| 55 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 56 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 57 | - }, | ||
| 58 | -}); | 48 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 49 | +function getData(): InfraStudentApi.StudentContact[] { | ||
| 50 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 51 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 52 | + return fullData.map((row) => | ||
| 53 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 54 | + ); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +/** 校验子表必填字段 */ | ||
| 58 | +function validate(): boolean { | ||
| 59 | + for (const [index, row] of getData().entries()) { | ||
| 60 | + if ( | ||
| 61 | + row.name === null || | ||
| 62 | + row.name === undefined || | ||
| 63 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 64 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 65 | + ) { | ||
| 66 | + message.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.description === null || | ||
| 71 | + row.description === undefined || | ||
| 72 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 73 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 74 | + ) { | ||
| 75 | + message.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.birthday === null || | ||
| 80 | + row.birthday === undefined || | ||
| 81 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 82 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 83 | + ) { | ||
| 84 | + message.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.sex === null || | ||
| 89 | + row.sex === undefined || | ||
| 90 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 91 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 92 | + ) { | ||
| 93 | + message.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.enabled === null || | ||
| 98 | + row.enabled === undefined || | ||
| 99 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 100 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 101 | + ) { | ||
| 102 | + message.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.avatar === null || | ||
| 107 | + row.avatar === undefined || | ||
| 108 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 109 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 110 | + ) { | ||
| 111 | + message.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + if ( | ||
| 115 | + row.memo === null || | ||
| 116 | + row.memo === undefined || | ||
| 117 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 118 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 119 | + ) { | ||
| 120 | + message.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 121 | + return false; | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + return true; | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +defineExpose({ getData, validate }); | ||
| 59 | 128 | ||
| 60 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 129 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 61 | watch( | 130 | watch( |
| 62 | () => props.studentId, | 131 | () => props.studentId, |
| 63 | async (val) => { | 132 | async (val) => { |
| 133 | + await nextTick(); | ||
| 64 | if (!val) { | 134 | if (!val) { |
| 135 | + await gridApi.grid.loadData([]); | ||
| 65 | return; | 136 | return; |
| 66 | } | 137 | } |
| 67 | - await nextTick(); | ||
| 68 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); | 138 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); |
| 69 | }, | 139 | }, |
| 70 | { immediate: true }, | 140 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/vue/student-teacher-form
| @@ -39,10 +39,11 @@ defineExpose({ | @@ -39,10 +39,11 @@ defineExpose({ | ||
| 39 | watch( | 39 | watch( |
| 40 | () => props.studentId, | 40 | () => props.studentId, |
| 41 | async (val) => { | 41 | async (val) => { |
| 42 | + await nextTick(); | ||
| 43 | + await formApi.resetForm(); | ||
| 42 | if (!val) { | 44 | if (!val) { |
| 43 | return; | 45 | return; |
| 44 | } | 46 | } |
| 45 | - await nextTick(); | ||
| 46 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); | 47 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); |
| 47 | }, | 48 | }, |
| 48 | { immediate: true }, | 49 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/vue/import-form
| @@ -51,6 +51,11 @@ function beforeUpload(file: FileType) { | @@ -51,6 +51,11 @@ function beforeUpload(file: FileType) { | ||
| 51 | return false; | 51 | return false; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | +/** 移除文件 */ | ||
| 55 | +function handleRemove() { | ||
| 56 | + formApi.setFieldValue('file', undefined); | ||
| 57 | +} | ||
| 58 | + | ||
| 54 | /** 下载模板 */ | 59 | /** 下载模板 */ |
| 55 | async function handleDownload() { | 60 | async function handleDownload() { |
| 56 | const data = await importStudentTemplate(); | 61 | const data = await importStudentTemplate(); |
| @@ -67,6 +72,7 @@ async function handleDownload() { | @@ -67,6 +72,7 @@ async function handleDownload() { | ||
| 67 | :max-count="1" | 72 | :max-count="1" |
| 68 | accept=".xls,.xlsx" | 73 | accept=".xls,.xlsx" |
| 69 | :before-upload="beforeUpload" | 74 | :before-upload="beforeUpload" |
| 75 | + :on-remove="handleRemove" | ||
| 70 | > | 76 | > |
| 71 | <Button type="primary"> 选择 Excel 文件 </Button> | 77 | <Button type="primary"> 选择 Excel 文件 </Button> |
| 72 | </Upload> | 78 | </Upload> |
yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/ts/data
| @@ -32,7 +32,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -32,7 +32,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 32 | id: 0, | 32 | id: 0, |
| 33 | name: '顶级分类', | 33 | name: '顶级分类', |
| 34 | }); | 34 | }); |
| 35 | - return handleTree(data); | 35 | + return handleTree(data, 'id', 'parentId'); |
| 36 | }, | 36 | }, |
| 37 | labelField: 'name', | 37 | labelField: 'name', |
| 38 | valueField: 'id', | 38 | valueField: 'id', |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | ||
| 11 | 11 | ||
| 12 | import { computed, ref, reactive } from 'vue'; | 12 | import { computed, ref, reactive } from 'vue'; |
| 13 | import { $t } from '#/locales'; | 13 | import { $t } from '#/locales'; |
| 14 | -import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | 14 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; |
| 15 | 15 | ||
| 16 | const emit = defineEmits(['success']); | 16 | const emit = defineEmits(['success']); |
| 17 | 17 | ||
| @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 102 | 102 | ||
| 103 | <template> | 103 | <template> |
| 104 | <Modal :title="getTitle"> | 104 | <Modal :title="getTitle"> |
| 105 | - <el-form | 105 | + <ElForm |
| 106 | ref="formRef" | 106 | ref="formRef" |
| 107 | :model="formData" | 107 | :model="formData" |
| 108 | :rules="rules" | 108 | :rules="rules" |
| 109 | label-width="120px" | 109 | label-width="120px" |
| 110 | label-position="right" | 110 | label-position="right" |
| 111 | > | 111 | > |
| 112 | - <el-form-item label="名字" prop="name"> | ||
| 113 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | - </el-form-item> | ||
| 115 | - <el-form-item label="简介" prop="description"> | ||
| 116 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | - </el-form-item> | ||
| 118 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 119 | - <el-date-picker | 112 | + <ElFormItem label="名字" prop="name"> |
| 113 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | + </ElFormItem> | ||
| 115 | + <ElFormItem label="简介" prop="description"> | ||
| 116 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | + </ElFormItem> | ||
| 118 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 119 | + <ElDatePicker | ||
| 120 | v-model="formData.birthday" | 120 | v-model="formData.birthday" |
| 121 | value-format="x" | 121 | value-format="x" |
| 122 | placeholder="选择出生日期" | 122 | placeholder="选择出生日期" |
| 123 | /> | 123 | /> |
| 124 | - </el-form-item> | ||
| 125 | - <el-form-item label="性别" prop="sex"> | ||
| 126 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | - <el-option | 124 | + </ElFormItem> |
| 125 | + <ElFormItem label="性别" prop="sex"> | ||
| 126 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | + <ElOption | ||
| 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 129 | :key="dict.value" | 129 | :key="dict.value" |
| 130 | :value="dict.value" | 130 | :value="dict.value" |
| 131 | :label="dict.label" | 131 | :label="dict.label" |
| 132 | /> | 132 | /> |
| 133 | - </el-select> | ||
| 134 | - </el-form-item> | ||
| 135 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 136 | - <el-radio-group v-model="formData.enabled"> | ||
| 137 | - <el-radio | 133 | + </ElSelect> |
| 134 | + </ElFormItem> | ||
| 135 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 136 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 137 | + <ElRadio | ||
| 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 139 | :key="dict.value" | 139 | :key="dict.value" |
| 140 | - :label="dict.value" | 140 | + :value="dict.value" |
| 141 | > | 141 | > |
| 142 | {{ dict.label }} | 142 | {{ dict.label }} |
| 143 | - </el-radio> | ||
| 144 | - </el-radio-group> | ||
| 145 | - </el-form-item> | ||
| 146 | - <el-form-item label="头像" prop="avatar"> | 143 | + </ElRadio> |
| 144 | + </ElRadioGroup> | ||
| 145 | + </ElFormItem> | ||
| 146 | + <ElFormItem label="头像" prop="avatar"> | ||
| 147 | <ImageUpload v-model="formData.avatar" /> | 147 | <ImageUpload v-model="formData.avatar" /> |
| 148 | - </el-form-item> | ||
| 149 | - <el-form-item label="附件" prop="video"> | 148 | + </ElFormItem> |
| 149 | + <ElFormItem label="附件" prop="video"> | ||
| 150 | <FileUpload v-model="formData.video" /> | 150 | <FileUpload v-model="formData.video" /> |
| 151 | - </el-form-item> | ||
| 152 | - <el-form-item label="备注" prop="memo"> | 151 | + </ElFormItem> |
| 152 | + <ElFormItem label="备注" prop="memo"> | ||
| 153 | <RichTextarea v-model="formData.memo" height="500px" /> | 153 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 154 | - </el-form-item> | ||
| 155 | - </el-form> | 154 | + </ElFormItem> |
| 155 | + </ElForm> | ||
| 156 | </Modal> | 156 | </Modal> |
| 157 | </template> | 157 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -19,7 +19,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -19,7 +19,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 19 | 19 | ||
| 20 | import { $t } from '#/locales'; | 20 | import { $t } from '#/locales'; |
| 21 | import { isEmpty } from '@vben/utils'; | 21 | import { isEmpty } from '@vben/utils'; |
| 22 | -import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | 22 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; |
| 23 | 23 | ||
| 24 | /** 子表的列表 */ | 24 | /** 子表的列表 */ |
| 25 | const subTabsName = ref('studentContact') | 25 | const subTabsName = ref('studentContact') |
| @@ -35,12 +35,11 @@ const total = ref(0) // 列表的总页数 | @@ -35,12 +35,11 @@ const total = ref(0) // 列表的总页数 | ||
| 35 | const queryParams = reactive({ | 35 | const queryParams = reactive({ |
| 36 | pageNo: 1, | 36 | pageNo: 1, |
| 37 | pageSize: 10, | 37 | pageSize: 10, |
| 38 | - name: undefined, | ||
| 39 | - birthday: undefined, | ||
| 40 | - birthday: undefined, | ||
| 41 | - sex: undefined, | ||
| 42 | - enabled: undefined, | ||
| 43 | - createTime: undefined, | 38 | + name: undefined, |
| 39 | + birthday: undefined, | ||
| 40 | + sex: undefined, | ||
| 41 | + enabled: undefined, | ||
| 42 | + createTime: undefined, | ||
| 44 | }) | 43 | }) |
| 45 | const queryFormRef = ref() // 搜索的表单 | 44 | const queryFormRef = ref() // 搜索的表单 |
| 46 | const exportLoading = ref(false) // 导出的加载中 | 45 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -134,7 +133,14 @@ function handleRowCheckboxChange({ | @@ -134,7 +133,14 @@ function handleRowCheckboxChange({ | ||
| 134 | async function handleExport() { | 133 | async function handleExport() { |
| 135 | try { | 134 | try { |
| 136 | exportLoading.value = true; | 135 | exportLoading.value = true; |
| 137 | - const data = await exportStudent(queryParams); | 136 | + const params = cloneDeep(queryParams) as any; |
| 137 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 138 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 139 | + } | ||
| 140 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 141 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 142 | + } | ||
| 143 | + const data = await exportStudent(params); | ||
| 138 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 144 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 139 | }finally { | 145 | }finally { |
| 140 | exportLoading.value = false; | 146 | exportLoading.value = false; |
| @@ -156,61 +162,61 @@ onMounted(() => { | @@ -156,61 +162,61 @@ onMounted(() => { | ||
| 156 | 162 | ||
| 157 | <ContentWrap v-if="!hiddenSearchBar"> | 163 | <ContentWrap v-if="!hiddenSearchBar"> |
| 158 | <!-- 搜索工作栏 --> | 164 | <!-- 搜索工作栏 --> |
| 159 | - <el-form | 165 | + <ElForm |
| 160 | :model="queryParams" | 166 | :model="queryParams" |
| 161 | ref="queryFormRef" | 167 | ref="queryFormRef" |
| 162 | inline | 168 | inline |
| 163 | > | 169 | > |
| 164 | - <el-form-item label="名字"> | ||
| 165 | - <el-input | 170 | + <ElFormItem label="名字"> |
| 171 | + <ElInput | ||
| 166 | v-model="queryParams.name" | 172 | v-model="queryParams.name" |
| 167 | placeholder="请输入名字" | 173 | placeholder="请输入名字" |
| 168 | clearable | 174 | clearable |
| 169 | @keyup.enter="handleQuery" | 175 | @keyup.enter="handleQuery" |
| 170 | class="!w-[240px]" | 176 | class="!w-[240px]" |
| 171 | /> | 177 | /> |
| 172 | - </el-form-item> | ||
| 173 | - <el-form-item label="出生日期"> | ||
| 174 | - <el-date-picker | 178 | + </ElFormItem> |
| 179 | + <ElFormItem label="出生日期"> | ||
| 180 | + <ElDatePicker | ||
| 175 | v-model="queryParams.birthday" | 181 | v-model="queryParams.birthday" |
| 176 | value-format="YYYY-MM-DD" | 182 | value-format="YYYY-MM-DD" |
| 177 | placeholder="选择出生日期" | 183 | placeholder="选择出生日期" |
| 178 | clearable | 184 | clearable |
| 179 | class="!w-[240px]" | 185 | class="!w-[240px]" |
| 180 | /> | 186 | /> |
| 181 | - </el-form-item> | ||
| 182 | - <el-form-item label="性别"> | ||
| 183 | - <el-select | 187 | + </ElFormItem> |
| 188 | + <ElFormItem label="性别"> | ||
| 189 | + <ElSelect | ||
| 184 | v-model="queryParams.sex" | 190 | v-model="queryParams.sex" |
| 185 | placeholder="请选择性别" | 191 | placeholder="请选择性别" |
| 186 | clearable | 192 | clearable |
| 187 | class="!w-[240px]" | 193 | class="!w-[240px]" |
| 188 | > | 194 | > |
| 189 | - <el-option | 195 | + <ElOption |
| 190 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 196 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 191 | :key="dict.value" | 197 | :key="dict.value" |
| 192 | :value="dict.value" | 198 | :value="dict.value" |
| 193 | :label="dict.label" | 199 | :label="dict.label" |
| 194 | /> | 200 | /> |
| 195 | - </el-select> | ||
| 196 | - </el-form-item> | ||
| 197 | - <el-form-item label="是否有效"> | ||
| 198 | - <el-select | 201 | + </ElSelect> |
| 202 | + </ElFormItem> | ||
| 203 | + <ElFormItem label="是否有效"> | ||
| 204 | + <ElSelect | ||
| 199 | v-model="queryParams.enabled" | 205 | v-model="queryParams.enabled" |
| 200 | placeholder="请选择是否有效" | 206 | placeholder="请选择是否有效" |
| 201 | clearable | 207 | clearable |
| 202 | class="!w-[240px]" | 208 | class="!w-[240px]" |
| 203 | > | 209 | > |
| 204 | - <el-option | 210 | + <ElOption |
| 205 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 211 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 206 | :key="dict.value" | 212 | :key="dict.value" |
| 207 | :value="dict.value" | 213 | :value="dict.value" |
| 208 | :label="dict.label" | 214 | :label="dict.label" |
| 209 | /> | 215 | /> |
| 210 | - </el-select> | ||
| 211 | - </el-form-item> | ||
| 212 | - <el-form-item label="创建时间"> | ||
| 213 | - <el-date-picker | 216 | + </ElSelect> |
| 217 | + </ElFormItem> | ||
| 218 | + <ElFormItem label="创建时间"> | ||
| 219 | + <ElDatePicker | ||
| 214 | v-model="queryParams.createTime" | 220 | v-model="queryParams.createTime" |
| 215 | type="daterange" | 221 | type="daterange" |
| 216 | value-format="YYYY-MM-DD" | 222 | value-format="YYYY-MM-DD" |
| @@ -219,24 +225,24 @@ onMounted(() => { | @@ -219,24 +225,24 @@ onMounted(() => { | ||
| 219 | end-placeholder="结束日期" | 225 | end-placeholder="结束日期" |
| 220 | class="!w-[240px]" | 226 | class="!w-[240px]" |
| 221 | /> | 227 | /> |
| 222 | - </el-form-item> | ||
| 223 | - <el-form-item> | ||
| 224 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 225 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 228 | + </ElFormItem> |
| 229 | + <ElFormItem> | ||
| 230 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 231 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 226 | 搜索 | 232 | 搜索 |
| 227 | - </el-button> | ||
| 228 | - </el-form-item> | ||
| 229 | - </el-form> | 233 | + </ElButton> |
| 234 | + </ElFormItem> | ||
| 235 | + </ElForm> | ||
| 230 | </ContentWrap> | 236 | </ContentWrap> |
| 231 | 237 | ||
| 232 | <!-- 列表 --> | 238 | <!-- 列表 --> |
| 233 | <ContentWrap title="学生"> | 239 | <ContentWrap title="学生"> |
| 234 | <template #extra> | 240 | <template #extra> |
| 235 | - <TableToolbar | 241 | + <VbenVxeTableToolbar |
| 236 | ref="tableToolbarRef" | 242 | ref="tableToolbarRef" |
| 237 | v-model:hidden-search="hiddenSearchBar" | 243 | v-model:hidden-search="hiddenSearchBar" |
| 238 | > | 244 | > |
| 239 | - <el-button | 245 | + <ElButton |
| 240 | class="ml-2" | 246 | class="ml-2" |
| 241 | :icon="h(Plus)" | 247 | :icon="h(Plus)" |
| 242 | type="primary" | 248 | type="primary" |
| @@ -244,8 +250,8 @@ onMounted(() => { | @@ -244,8 +250,8 @@ onMounted(() => { | ||
| 244 | v-access:code="['infra:student:create']" | 250 | v-access:code="['infra:student:create']" |
| 245 | > | 251 | > |
| 246 | {{ $t('ui.actionTitle.create', ['学生']) }} | 252 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 247 | - </el-button> | ||
| 248 | - <el-button | 253 | + </ElButton> |
| 254 | + <ElButton | ||
| 249 | :icon="h(Download)" | 255 | :icon="h(Download)" |
| 250 | type="primary" | 256 | type="primary" |
| 251 | class="ml-2" | 257 | class="ml-2" |
| @@ -254,8 +260,8 @@ onMounted(() => { | @@ -254,8 +260,8 @@ onMounted(() => { | ||
| 254 | v-access:code="['infra:student:export']" | 260 | v-access:code="['infra:student:export']" |
| 255 | > | 261 | > |
| 256 | {{ $t('ui.actionTitle.export') }} | 262 | {{ $t('ui.actionTitle.export') }} |
| 257 | - </el-button> | ||
| 258 | - <el-button | 263 | + </ElButton> |
| 264 | + <ElButton | ||
| 259 | :icon="h(Trash2)" | 265 | :icon="h(Trash2)" |
| 260 | type="danger" | 266 | type="danger" |
| 261 | class="ml-2" | 267 | class="ml-2" |
| @@ -264,10 +270,10 @@ onMounted(() => { | @@ -264,10 +270,10 @@ onMounted(() => { | ||
| 264 | v-access:code="['infra:student:delete']" | 270 | v-access:code="['infra:student:delete']" |
| 265 | > | 271 | > |
| 266 | 批量删除 | 272 | 批量删除 |
| 267 | - </el-button> | ||
| 268 | - </TableToolbar> | 273 | + </ElButton> |
| 274 | + </VbenVxeTableToolbar> | ||
| 269 | </template> | 275 | </template> |
| 270 | - <vxe-table | 276 | + <VxeTable |
| 271 | ref="tableRef" | 277 | ref="tableRef" |
| 272 | :data="list" | 278 | :data="list" |
| 273 | @cell-click="onCellClick" | 279 | @cell-click="onCellClick" |
| @@ -281,36 +287,36 @@ onMounted(() => { | @@ -281,36 +287,36 @@ onMounted(() => { | ||
| 281 | @checkboxAll="handleRowCheckboxChange" | 287 | @checkboxAll="handleRowCheckboxChange" |
| 282 | @checkboxChange="handleRowCheckboxChange" | 288 | @checkboxChange="handleRowCheckboxChange" |
| 283 | > | 289 | > |
| 284 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 285 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 286 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 287 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 288 | - <vxe-column field="birthday" title="出生日期" align="center"> | 290 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 291 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 292 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 293 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 294 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 289 | <template #default="{row}"> | 295 | <template #default="{row}"> |
| 290 | {{formatDateTime(row.birthday)}} | 296 | {{formatDateTime(row.birthday)}} |
| 291 | </template> | 297 | </template> |
| 292 | - </vxe-column> | ||
| 293 | - <vxe-column field="sex" title="性别" align="center"> | 298 | + </VxeColumn> |
| 299 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 294 | <template #default="{row}"> | 300 | <template #default="{row}"> |
| 295 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 301 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 296 | </template> | 302 | </template> |
| 297 | - </vxe-column> | ||
| 298 | - <vxe-column field="enabled" title="是否有效" align="center"> | 303 | + </VxeColumn> |
| 304 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 299 | <template #default="{row}"> | 305 | <template #default="{row}"> |
| 300 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 306 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 301 | </template> | 307 | </template> |
| 302 | - </vxe-column> | ||
| 303 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 304 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 305 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 306 | - <vxe-column field="createTime" title="创建时间" align="center"> | 308 | + </VxeColumn> |
| 309 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 310 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 311 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 312 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 307 | <template #default="{row}"> | 313 | <template #default="{row}"> |
| 308 | {{formatDateTime(row.createTime)}} | 314 | {{formatDateTime(row.createTime)}} |
| 309 | </template> | 315 | </template> |
| 310 | - </vxe-column> | ||
| 311 | - <vxe-column field="operation" title="操作" align="center"> | 316 | + </VxeColumn> |
| 317 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 312 | <template #default="{row}"> | 318 | <template #default="{row}"> |
| 313 | - <el-button | 319 | + <ElButton |
| 314 | size="small" | 320 | size="small" |
| 315 | type="primary" | 321 | type="primary" |
| 316 | link | 322 | link |
| @@ -318,8 +324,8 @@ onMounted(() => { | @@ -318,8 +324,8 @@ onMounted(() => { | ||
| 318 | v-access:code="['infra:student:update']" | 324 | v-access:code="['infra:student:update']" |
| 319 | > | 325 | > |
| 320 | {{ $t('ui.actionTitle.edit') }} | 326 | {{ $t('ui.actionTitle.edit') }} |
| 321 | - </el-button> | ||
| 322 | - <el-button | 327 | + </ElButton> |
| 328 | + <ElButton | ||
| 323 | size="small" | 329 | size="small" |
| 324 | type="danger" | 330 | type="danger" |
| 325 | link | 331 | link |
| @@ -328,13 +334,13 @@ onMounted(() => { | @@ -328,13 +334,13 @@ onMounted(() => { | ||
| 328 | v-access:code="['infra:student:delete']" | 334 | v-access:code="['infra:student:delete']" |
| 329 | > | 335 | > |
| 330 | {{ $t('ui.actionTitle.delete') }} | 336 | {{ $t('ui.actionTitle.delete') }} |
| 331 | - </el-button> | 337 | + </ElButton> |
| 332 | </template> | 338 | </template> |
| 333 | - </vxe-column> | ||
| 334 | - </vxe-table> | 339 | + </VxeColumn> |
| 340 | + </VxeTable> | ||
| 335 | <!-- 分页 --> | 341 | <!-- 分页 --> |
| 336 | <div class="mt-2 flex justify-end"> | 342 | <div class="mt-2 flex justify-end"> |
| 337 | - <el-pagination | 343 | + <ElPagination |
| 338 | :total="total" | 344 | :total="total" |
| 339 | v-model:current-page="queryParams.pageNo" | 345 | v-model:current-page="queryParams.pageNo" |
| 340 | v-model:page-size="queryParams.pageSize" | 346 | v-model:page-size="queryParams.pageSize" |
| @@ -347,14 +353,14 @@ onMounted(() => { | @@ -347,14 +353,14 @@ onMounted(() => { | ||
| 347 | </ContentWrap> | 353 | </ContentWrap> |
| 348 | <ContentWrap> | 354 | <ContentWrap> |
| 349 | <!-- 子表的表单 --> | 355 | <!-- 子表的表单 --> |
| 350 | - <el-tabs v-model="subTabsName"> | ||
| 351 | - <el-tab-pane name="studentContact" label="学生联系人"> | 356 | + <ElTabs v-model="subTabsName"> |
| 357 | + <ElTabPane name="studentContact" label="学生联系人"> | ||
| 352 | <StudentContactList :student-id="selectStudent?.id" /> | 358 | <StudentContactList :student-id="selectStudent?.id" /> |
| 353 | - </el-tab-pane> | ||
| 354 | - <el-tab-pane name="studentTeacher" label="学生班主任"> | 359 | + </ElTabPane> |
| 360 | + <ElTabPane name="studentTeacher" label="学生班主任"> | ||
| 355 | <StudentTeacherList :student-id="selectStudent?.id" /> | 361 | <StudentTeacherList :student-id="selectStudent?.id" /> |
| 356 | - </el-tab-pane> | ||
| 357 | - </el-tabs> | 362 | + </ElTabPane> |
| 363 | + </ElTabs> | ||
| 358 | </ContentWrap> | 364 | </ContentWrap> |
| 359 | </Page> | 365 | </Page> |
| 360 | </template> | 366 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/student-contact-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { computed, ref, reactive } from 'vue'; | 5 | import { computed, ref, reactive } from 'vue'; |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | 13 | ||
| 14 | import { $t } from '#/locales'; | 14 | import { $t } from '#/locales'; |
| 15 | 15 | ||
| 16 | - import { getStudentContact, createStudentContact, updateStudentContact } from '#/api/infra/student'; | 16 | + import { getStudentContact, createStudentContact, updateStudentContact } from '#/api/infra/demo'; |
| 17 | 17 | ||
| 18 | const emit = defineEmits(['success']); | 18 | const emit = defineEmits(['success']); |
| 19 | const getTitle = computed(() => { | 19 | const getTitle = computed(() => { |
| @@ -107,56 +107,56 @@ | @@ -107,56 +107,56 @@ | ||
| 107 | 107 | ||
| 108 | <template> | 108 | <template> |
| 109 | <Modal :title="getTitle"> | 109 | <Modal :title="getTitle"> |
| 110 | - <el-form | 110 | + <ElForm |
| 111 | ref="formRef" | 111 | ref="formRef" |
| 112 | :model="formData" | 112 | :model="formData" |
| 113 | :rules="rules" | 113 | :rules="rules" |
| 114 | label-width="120px" | 114 | label-width="120px" |
| 115 | label-position="right" | 115 | label-position="right" |
| 116 | > | 116 | > |
| 117 | - <el-form-item label="名字" prop="name"> | ||
| 118 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 119 | - </el-form-item> | ||
| 120 | - <el-form-item label="简介" prop="description"> | ||
| 121 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 122 | - </el-form-item> | ||
| 123 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 124 | - <el-date-picker | 117 | + <ElFormItem label="名字" prop="name"> |
| 118 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 119 | + </ElFormItem> | ||
| 120 | + <ElFormItem label="简介" prop="description"> | ||
| 121 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 122 | + </ElFormItem> | ||
| 123 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 124 | + <ElDatePicker | ||
| 125 | v-model="formData.birthday" | 125 | v-model="formData.birthday" |
| 126 | value-format="x" | 126 | value-format="x" |
| 127 | placeholder="选择出生日期" | 127 | placeholder="选择出生日期" |
| 128 | /> | 128 | /> |
| 129 | - </el-form-item> | ||
| 130 | - <el-form-item label="性别" prop="sex"> | ||
| 131 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 132 | - <el-option | 129 | + </ElFormItem> |
| 130 | + <ElFormItem label="性别" prop="sex"> | ||
| 131 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 132 | + <ElOption | ||
| 133 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 133 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 134 | :key="dict.value" | 134 | :key="dict.value" |
| 135 | :value="dict.value" | 135 | :value="dict.value" |
| 136 | :label="dict.label" | 136 | :label="dict.label" |
| 137 | /> | 137 | /> |
| 138 | - </el-select> | ||
| 139 | - </el-form-item> | ||
| 140 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 141 | - <el-radio-group v-model="formData.enabled"> | ||
| 142 | - <el-radio | 138 | + </ElSelect> |
| 139 | + </ElFormItem> | ||
| 140 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 141 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 142 | + <ElRadio | ||
| 143 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 143 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 144 | :key="dict.value" | 144 | :key="dict.value" |
| 145 | - :label="dict.value" | 145 | + :value="dict.value" |
| 146 | > | 146 | > |
| 147 | {{ dict.label }} | 147 | {{ dict.label }} |
| 148 | - </el-radio> | ||
| 149 | - </el-radio-group> | ||
| 150 | - </el-form-item> | ||
| 151 | - <el-form-item label="头像" prop="avatar"> | 148 | + </ElRadio> |
| 149 | + </ElRadioGroup> | ||
| 150 | + </ElFormItem> | ||
| 151 | + <ElFormItem label="头像" prop="avatar"> | ||
| 152 | <ImageUpload v-model="formData.avatar" /> | 152 | <ImageUpload v-model="formData.avatar" /> |
| 153 | - </el-form-item> | ||
| 154 | - <el-form-item label="附件" prop="video"> | 153 | + </ElFormItem> |
| 154 | + <ElFormItem label="附件" prop="video"> | ||
| 155 | <FileUpload v-model="formData.video" /> | 155 | <FileUpload v-model="formData.video" /> |
| 156 | - </el-form-item> | ||
| 157 | - <el-form-item label="备注" prop="memo"> | 156 | + </ElFormItem> |
| 157 | + <ElFormItem label="备注" prop="memo"> | ||
| 158 | <RichTextarea v-model="formData.memo" height="500px" /> | 158 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 159 | - </el-form-item> | ||
| 160 | - </el-form> | 159 | + </ElFormItem> |
| 160 | + </ElForm> | ||
| 161 | </Modal> | 161 | </Modal> |
| 162 | </template> | 162 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/student-contact-list
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; | 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 4 | 4 | ||
| 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; | 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; |
| 6 | 6 | ||
| 7 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 8 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { formatDateTime } from '@vben/utils'; | ||
| 9 | 10 | ||
| 10 | import { DictTag } from '#/components/dict-tag'; | 11 | import { DictTag } from '#/components/dict-tag'; |
| 11 | import { getRangePickerDefaultProps } from '#/utils'; | 12 | import { getRangePickerDefaultProps } from '#/utils'; |
| @@ -21,8 +22,8 @@ | @@ -21,8 +22,8 @@ | ||
| 21 | import { Plus, Trash2 } from '@vben/icons'; | 22 | import { Plus, Trash2 } from '@vben/icons'; |
| 22 | import { $t } from '#/locales'; | 23 | import { $t } from '#/locales'; |
| 23 | 24 | ||
| 24 | - import { deleteStudentContact, deleteStudentContactList, getStudentContactPage } from '#/api/infra/student'; | ||
| 25 | - import { isEmpty } from '@vben/utils'; | 25 | + import { deleteStudentContact, deleteStudentContactList, getStudentContactPage } from '#/api/infra/demo'; |
| 26 | + import { cloneDeep, isEmpty } from '@vben/utils'; | ||
| 26 | 27 | ||
| 27 | const props = defineProps<{ | 28 | const props = defineProps<{ |
| 28 | studentId?: number // 学生编号(主表的关联字段) | 29 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -159,61 +160,61 @@ onMounted(() => { | @@ -159,61 +160,61 @@ onMounted(() => { | ||
| 159 | <div class="h-[600px]"> | 160 | <div class="h-[600px]"> |
| 160 | <ContentWrap v-if="!hiddenSearchBar"> | 161 | <ContentWrap v-if="!hiddenSearchBar"> |
| 161 | <!-- 搜索工作栏 --> | 162 | <!-- 搜索工作栏 --> |
| 162 | - <el-form | 163 | + <ElForm |
| 163 | :model="queryParams" | 164 | :model="queryParams" |
| 164 | ref="queryFormRef" | 165 | ref="queryFormRef" |
| 165 | inline | 166 | inline |
| 166 | > | 167 | > |
| 167 | - <el-form-item label="名字"> | ||
| 168 | - <el-input | 168 | + <ElFormItem label="名字"> |
| 169 | + <ElInput | ||
| 169 | v-model="queryParams.name" | 170 | v-model="queryParams.name" |
| 170 | placeholder="请输入名字" | 171 | placeholder="请输入名字" |
| 171 | clearable | 172 | clearable |
| 172 | @keyup.enter="handleQuery" | 173 | @keyup.enter="handleQuery" |
| 173 | class="!w-[240px]" | 174 | class="!w-[240px]" |
| 174 | /> | 175 | /> |
| 175 | - </el-form-item> | ||
| 176 | - <el-form-item label="出生日期"> | ||
| 177 | - <el-date-picker | 176 | + </ElFormItem> |
| 177 | + <ElFormItem label="出生日期"> | ||
| 178 | + <ElDatePicker | ||
| 178 | v-model="queryParams.birthday" | 179 | v-model="queryParams.birthday" |
| 179 | value-format="YYYY-MM-DD" | 180 | value-format="YYYY-MM-DD" |
| 180 | placeholder="选择出生日期" | 181 | placeholder="选择出生日期" |
| 181 | clearable | 182 | clearable |
| 182 | class="!w-[240px]" | 183 | class="!w-[240px]" |
| 183 | /> | 184 | /> |
| 184 | - </el-form-item> | ||
| 185 | - <el-form-item label="性别"> | ||
| 186 | - <el-select | 185 | + </ElFormItem> |
| 186 | + <ElFormItem label="性别"> | ||
| 187 | + <ElSelect | ||
| 187 | v-model="queryParams.sex" | 188 | v-model="queryParams.sex" |
| 188 | placeholder="请选择性别" | 189 | placeholder="请选择性别" |
| 189 | clearable | 190 | clearable |
| 190 | class="!w-[240px]" | 191 | class="!w-[240px]" |
| 191 | > | 192 | > |
| 192 | - <el-option | 193 | + <ElOption |
| 193 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 194 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 194 | :key="dict.value" | 195 | :key="dict.value" |
| 195 | :value="dict.value" | 196 | :value="dict.value" |
| 196 | :label="dict.label" | 197 | :label="dict.label" |
| 197 | /> | 198 | /> |
| 198 | - </el-select> | ||
| 199 | - </el-form-item> | ||
| 200 | - <el-form-item label="是否有效"> | ||
| 201 | - <el-select | 199 | + </ElSelect> |
| 200 | + </ElFormItem> | ||
| 201 | + <ElFormItem label="是否有效"> | ||
| 202 | + <ElSelect | ||
| 202 | v-model="queryParams.enabled" | 203 | v-model="queryParams.enabled" |
| 203 | placeholder="请选择是否有效" | 204 | placeholder="请选择是否有效" |
| 204 | clearable | 205 | clearable |
| 205 | class="!w-[240px]" | 206 | class="!w-[240px]" |
| 206 | > | 207 | > |
| 207 | - <el-option | 208 | + <ElOption |
| 208 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 209 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 209 | :key="dict.value" | 210 | :key="dict.value" |
| 210 | :value="dict.value" | 211 | :value="dict.value" |
| 211 | :label="dict.label" | 212 | :label="dict.label" |
| 212 | /> | 213 | /> |
| 213 | - </el-select> | ||
| 214 | - </el-form-item> | ||
| 215 | - <el-form-item label="创建时间"> | ||
| 216 | - <el-date-picker | 214 | + </ElSelect> |
| 215 | + </ElFormItem> | ||
| 216 | + <ElFormItem label="创建时间"> | ||
| 217 | + <ElDatePicker | ||
| 217 | v-model="queryParams.createTime" | 218 | v-model="queryParams.createTime" |
| 218 | type="daterange" | 219 | type="daterange" |
| 219 | value-format="YYYY-MM-DD" | 220 | value-format="YYYY-MM-DD" |
| @@ -222,14 +223,14 @@ onMounted(() => { | @@ -222,14 +223,14 @@ onMounted(() => { | ||
| 222 | end-placeholder="结束日期" | 223 | end-placeholder="结束日期" |
| 223 | class="!w-[240px]" | 224 | class="!w-[240px]" |
| 224 | /> | 225 | /> |
| 225 | - </el-form-item> | ||
| 226 | - <el-form-item> | ||
| 227 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 228 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 226 | + </ElFormItem> |
| 227 | + <ElFormItem> | ||
| 228 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 229 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 229 | 搜索 | 230 | 搜索 |
| 230 | - </el-button> | ||
| 231 | - </el-form-item> | ||
| 232 | - </el-form> | 231 | + </ElButton> |
| 232 | + </ElFormItem> | ||
| 233 | + </ElForm> | ||
| 233 | </ContentWrap> | 234 | </ContentWrap> |
| 234 | 235 | ||
| 235 | <!-- 列表 --> | 236 | <!-- 列表 --> |
| @@ -239,7 +240,7 @@ onMounted(() => { | @@ -239,7 +240,7 @@ onMounted(() => { | ||
| 239 | ref="tableToolbarRef" | 240 | ref="tableToolbarRef" |
| 240 | v-model:hidden-search="hiddenSearchBar" | 241 | v-model:hidden-search="hiddenSearchBar" |
| 241 | > | 242 | > |
| 242 | - <el-button | 243 | + <ElButton |
| 243 | class="ml-2" | 244 | class="ml-2" |
| 244 | :icon="h(Plus)" | 245 | :icon="h(Plus)" |
| 245 | type="primary" | 246 | type="primary" |
| @@ -247,8 +248,8 @@ onMounted(() => { | @@ -247,8 +248,8 @@ onMounted(() => { | ||
| 247 | v-access:code="['infra:student:create']" | 248 | v-access:code="['infra:student:create']" |
| 248 | > | 249 | > |
| 249 | {{ $t('ui.actionTitle.create', ['学生']) }} | 250 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 250 | - </el-button> | ||
| 251 | - <el-button | 251 | + </ElButton> |
| 252 | + <ElButton | ||
| 252 | :icon="h(Trash2)" | 253 | :icon="h(Trash2)" |
| 253 | type="danger" | 254 | type="danger" |
| 254 | class="ml-2" | 255 | class="ml-2" |
| @@ -257,10 +258,10 @@ onMounted(() => { | @@ -257,10 +258,10 @@ onMounted(() => { | ||
| 257 | v-access:code="['infra:student:delete']" | 258 | v-access:code="['infra:student:delete']" |
| 258 | > | 259 | > |
| 259 | 批量删除 | 260 | 批量删除 |
| 260 | - </el-button> | ||
| 261 | - </TableToolbar> | 261 | + </ElButton> |
| 262 | + </VbenVxeTableToolbar> | ||
| 262 | </template> | 263 | </template> |
| 263 | - <vxe-table | 264 | + <VxeTable |
| 264 | ref="tableRef" | 265 | ref="tableRef" |
| 265 | :data="list" | 266 | :data="list" |
| 266 | show-overflow | 267 | show-overflow |
| @@ -268,37 +269,37 @@ onMounted(() => { | @@ -268,37 +269,37 @@ onMounted(() => { | ||
| 268 | @checkboxAll="handleRowCheckboxChange" | 269 | @checkboxAll="handleRowCheckboxChange" |
| 269 | @checkboxChange="handleRowCheckboxChange" | 270 | @checkboxChange="handleRowCheckboxChange" |
| 270 | > | 271 | > |
| 271 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 272 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 273 | - <vxe-column field="studentId" title="学生编号" align="center" /> | ||
| 274 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 275 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 276 | - <vxe-column field="birthday" title="出生日期" align="center"> | 272 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 273 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 274 | + <VxeColumn field="studentId" title="学生编号" align="center" /> | ||
| 275 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 276 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 277 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 277 | <template #default="{row}"> | 278 | <template #default="{row}"> |
| 278 | {{formatDateTime(row.birthday)}} | 279 | {{formatDateTime(row.birthday)}} |
| 279 | </template> | 280 | </template> |
| 280 | - </vxe-column> | ||
| 281 | - <vxe-column field="sex" title="性别" align="center"> | 281 | + </VxeColumn> |
| 282 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 282 | <template #default="{row}"> | 283 | <template #default="{row}"> |
| 283 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 284 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 284 | </template> | 285 | </template> |
| 285 | - </vxe-column> | ||
| 286 | - <vxe-column field="enabled" title="是否有效" align="center"> | 286 | + </VxeColumn> |
| 287 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 287 | <template #default="{row}"> | 288 | <template #default="{row}"> |
| 288 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 289 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 289 | </template> | 290 | </template> |
| 290 | - </vxe-column> | ||
| 291 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 292 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 293 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 294 | - <vxe-column field="createTime" title="创建时间" align="center"> | 291 | + </VxeColumn> |
| 292 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 293 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 294 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 295 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 295 | <template #default="{row}"> | 296 | <template #default="{row}"> |
| 296 | {{formatDateTime(row.createTime)}} | 297 | {{formatDateTime(row.createTime)}} |
| 297 | </template> | 298 | </template> |
| 298 | - </vxe-column> | ||
| 299 | - <vxe-column field="operation" title="操作" align="center"> | 299 | + </VxeColumn> |
| 300 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 300 | <template #default="{row}"> | 301 | <template #default="{row}"> |
| 301 | - <el-button | 302 | + <ElButton |
| 302 | size="small" | 303 | size="small" |
| 303 | type="primary" | 304 | type="primary" |
| 304 | link | 305 | link |
| @@ -306,8 +307,8 @@ onMounted(() => { | @@ -306,8 +307,8 @@ onMounted(() => { | ||
| 306 | v-access:code="['infra:student:update']" | 307 | v-access:code="['infra:student:update']" |
| 307 | > | 308 | > |
| 308 | {{ $t('ui.actionTitle.edit') }} | 309 | {{ $t('ui.actionTitle.edit') }} |
| 309 | - </el-button> | ||
| 310 | - <el-button | 310 | + </ElButton> |
| 311 | + <ElButton | ||
| 311 | size="small" | 312 | size="small" |
| 312 | type="danger" | 313 | type="danger" |
| 313 | link | 314 | link |
| @@ -316,13 +317,13 @@ onMounted(() => { | @@ -316,13 +317,13 @@ onMounted(() => { | ||
| 316 | v-access:code="['infra:student:delete']" | 317 | v-access:code="['infra:student:delete']" |
| 317 | > | 318 | > |
| 318 | {{ $t('ui.actionTitle.delete') }} | 319 | {{ $t('ui.actionTitle.delete') }} |
| 319 | - </el-button> | 320 | + </ElButton> |
| 320 | </template> | 321 | </template> |
| 321 | - </vxe-column> | ||
| 322 | - </vxe-table> | 322 | + </VxeColumn> |
| 323 | + </VxeTable> | ||
| 323 | <!-- 分页 --> | 324 | <!-- 分页 --> |
| 324 | <div class="mt-2 flex justify-end"> | 325 | <div class="mt-2 flex justify-end"> |
| 325 | - <el-pagination | 326 | + <ElPagination |
| 326 | :total="total" | 327 | :total="total" |
| 327 | v-model:current-page="queryParams.pageNo" | 328 | v-model:current-page="queryParams.pageNo" |
| 328 | v-model:page-size="queryParams.pageSize" | 329 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/student-teacher-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { computed, ref, reactive } from 'vue'; | 5 | import { computed, ref, reactive } from 'vue'; |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | 13 | ||
| 14 | import { $t } from '#/locales'; | 14 | import { $t } from '#/locales'; |
| 15 | 15 | ||
| 16 | - import { getStudentTeacher, createStudentTeacher, updateStudentTeacher } from '#/api/infra/student'; | 16 | + import { getStudentTeacher, createStudentTeacher, updateStudentTeacher } from '#/api/infra/demo'; |
| 17 | 17 | ||
| 18 | const emit = defineEmits(['success']); | 18 | const emit = defineEmits(['success']); |
| 19 | const getTitle = computed(() => { | 19 | const getTitle = computed(() => { |
| @@ -107,56 +107,56 @@ | @@ -107,56 +107,56 @@ | ||
| 107 | 107 | ||
| 108 | <template> | 108 | <template> |
| 109 | <Modal :title="getTitle"> | 109 | <Modal :title="getTitle"> |
| 110 | - <el-form | 110 | + <ElForm |
| 111 | ref="formRef" | 111 | ref="formRef" |
| 112 | :model="formData" | 112 | :model="formData" |
| 113 | :rules="rules" | 113 | :rules="rules" |
| 114 | label-width="120px" | 114 | label-width="120px" |
| 115 | label-position="right" | 115 | label-position="right" |
| 116 | > | 116 | > |
| 117 | - <el-form-item label="名字" prop="name"> | ||
| 118 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 119 | - </el-form-item> | ||
| 120 | - <el-form-item label="简介" prop="description"> | ||
| 121 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 122 | - </el-form-item> | ||
| 123 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 124 | - <el-date-picker | 117 | + <ElFormItem label="名字" prop="name"> |
| 118 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 119 | + </ElFormItem> | ||
| 120 | + <ElFormItem label="简介" prop="description"> | ||
| 121 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 122 | + </ElFormItem> | ||
| 123 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 124 | + <ElDatePicker | ||
| 125 | v-model="formData.birthday" | 125 | v-model="formData.birthday" |
| 126 | value-format="x" | 126 | value-format="x" |
| 127 | placeholder="选择出生日期" | 127 | placeholder="选择出生日期" |
| 128 | /> | 128 | /> |
| 129 | - </el-form-item> | ||
| 130 | - <el-form-item label="性别" prop="sex"> | ||
| 131 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 132 | - <el-option | 129 | + </ElFormItem> |
| 130 | + <ElFormItem label="性别" prop="sex"> | ||
| 131 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 132 | + <ElOption | ||
| 133 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 133 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 134 | :key="dict.value" | 134 | :key="dict.value" |
| 135 | :value="dict.value" | 135 | :value="dict.value" |
| 136 | :label="dict.label" | 136 | :label="dict.label" |
| 137 | /> | 137 | /> |
| 138 | - </el-select> | ||
| 139 | - </el-form-item> | ||
| 140 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 141 | - <el-radio-group v-model="formData.enabled"> | ||
| 142 | - <el-radio | 138 | + </ElSelect> |
| 139 | + </ElFormItem> | ||
| 140 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 141 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 142 | + <ElRadio | ||
| 143 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 143 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 144 | :key="dict.value" | 144 | :key="dict.value" |
| 145 | - :label="dict.value" | 145 | + :value="dict.value" |
| 146 | > | 146 | > |
| 147 | {{ dict.label }} | 147 | {{ dict.label }} |
| 148 | - </el-radio> | ||
| 149 | - </el-radio-group> | ||
| 150 | - </el-form-item> | ||
| 151 | - <el-form-item label="头像" prop="avatar"> | 148 | + </ElRadio> |
| 149 | + </ElRadioGroup> | ||
| 150 | + </ElFormItem> | ||
| 151 | + <ElFormItem label="头像" prop="avatar"> | ||
| 152 | <ImageUpload v-model="formData.avatar" /> | 152 | <ImageUpload v-model="formData.avatar" /> |
| 153 | - </el-form-item> | ||
| 154 | - <el-form-item label="附件" prop="video"> | 153 | + </ElFormItem> |
| 154 | + <ElFormItem label="附件" prop="video"> | ||
| 155 | <FileUpload v-model="formData.video" /> | 155 | <FileUpload v-model="formData.video" /> |
| 156 | - </el-form-item> | ||
| 157 | - <el-form-item label="备注" prop="memo"> | 156 | + </ElFormItem> |
| 157 | + <ElFormItem label="备注" prop="memo"> | ||
| 158 | <RichTextarea v-model="formData.memo" height="500px" /> | 158 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 159 | - </el-form-item> | ||
| 160 | - </el-form> | 159 | + </ElFormItem> |
| 160 | + </ElForm> | ||
| 161 | </Modal> | 161 | </Modal> |
| 162 | </template> | 162 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/vue/student-teacher-list
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; | 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 4 | 4 | ||
| 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; | 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; |
| 6 | 6 | ||
| 7 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 8 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { formatDateTime } from '@vben/utils'; | ||
| 9 | 10 | ||
| 10 | import { DictTag } from '#/components/dict-tag'; | 11 | import { DictTag } from '#/components/dict-tag'; |
| 11 | import { getRangePickerDefaultProps } from '#/utils'; | 12 | import { getRangePickerDefaultProps } from '#/utils'; |
| @@ -21,8 +22,8 @@ | @@ -21,8 +22,8 @@ | ||
| 21 | import { Plus, Trash2 } from '@vben/icons'; | 22 | import { Plus, Trash2 } from '@vben/icons'; |
| 22 | import { $t } from '#/locales'; | 23 | import { $t } from '#/locales'; |
| 23 | 24 | ||
| 24 | - import { deleteStudentTeacher, deleteStudentTeacherList, getStudentTeacherPage } from '#/api/infra/student'; | ||
| 25 | - import { isEmpty } from '@vben/utils'; | 25 | + import { deleteStudentTeacher, deleteStudentTeacherList, getStudentTeacherPage } from '#/api/infra/demo'; |
| 26 | + import { cloneDeep, isEmpty } from '@vben/utils'; | ||
| 26 | 27 | ||
| 27 | const props = defineProps<{ | 28 | const props = defineProps<{ |
| 28 | studentId?: number // 学生编号(主表的关联字段) | 29 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -159,61 +160,61 @@ onMounted(() => { | @@ -159,61 +160,61 @@ onMounted(() => { | ||
| 159 | <div class="h-[600px]"> | 160 | <div class="h-[600px]"> |
| 160 | <ContentWrap v-if="!hiddenSearchBar"> | 161 | <ContentWrap v-if="!hiddenSearchBar"> |
| 161 | <!-- 搜索工作栏 --> | 162 | <!-- 搜索工作栏 --> |
| 162 | - <el-form | 163 | + <ElForm |
| 163 | :model="queryParams" | 164 | :model="queryParams" |
| 164 | ref="queryFormRef" | 165 | ref="queryFormRef" |
| 165 | inline | 166 | inline |
| 166 | > | 167 | > |
| 167 | - <el-form-item label="名字"> | ||
| 168 | - <el-input | 168 | + <ElFormItem label="名字"> |
| 169 | + <ElInput | ||
| 169 | v-model="queryParams.name" | 170 | v-model="queryParams.name" |
| 170 | placeholder="请输入名字" | 171 | placeholder="请输入名字" |
| 171 | clearable | 172 | clearable |
| 172 | @keyup.enter="handleQuery" | 173 | @keyup.enter="handleQuery" |
| 173 | class="!w-[240px]" | 174 | class="!w-[240px]" |
| 174 | /> | 175 | /> |
| 175 | - </el-form-item> | ||
| 176 | - <el-form-item label="出生日期"> | ||
| 177 | - <el-date-picker | 176 | + </ElFormItem> |
| 177 | + <ElFormItem label="出生日期"> | ||
| 178 | + <ElDatePicker | ||
| 178 | v-model="queryParams.birthday" | 179 | v-model="queryParams.birthday" |
| 179 | value-format="YYYY-MM-DD" | 180 | value-format="YYYY-MM-DD" |
| 180 | placeholder="选择出生日期" | 181 | placeholder="选择出生日期" |
| 181 | clearable | 182 | clearable |
| 182 | class="!w-[240px]" | 183 | class="!w-[240px]" |
| 183 | /> | 184 | /> |
| 184 | - </el-form-item> | ||
| 185 | - <el-form-item label="性别"> | ||
| 186 | - <el-select | 185 | + </ElFormItem> |
| 186 | + <ElFormItem label="性别"> | ||
| 187 | + <ElSelect | ||
| 187 | v-model="queryParams.sex" | 188 | v-model="queryParams.sex" |
| 188 | placeholder="请选择性别" | 189 | placeholder="请选择性别" |
| 189 | clearable | 190 | clearable |
| 190 | class="!w-[240px]" | 191 | class="!w-[240px]" |
| 191 | > | 192 | > |
| 192 | - <el-option | 193 | + <ElOption |
| 193 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 194 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 194 | :key="dict.value" | 195 | :key="dict.value" |
| 195 | :value="dict.value" | 196 | :value="dict.value" |
| 196 | :label="dict.label" | 197 | :label="dict.label" |
| 197 | /> | 198 | /> |
| 198 | - </el-select> | ||
| 199 | - </el-form-item> | ||
| 200 | - <el-form-item label="是否有效"> | ||
| 201 | - <el-select | 199 | + </ElSelect> |
| 200 | + </ElFormItem> | ||
| 201 | + <ElFormItem label="是否有效"> | ||
| 202 | + <ElSelect | ||
| 202 | v-model="queryParams.enabled" | 203 | v-model="queryParams.enabled" |
| 203 | placeholder="请选择是否有效" | 204 | placeholder="请选择是否有效" |
| 204 | clearable | 205 | clearable |
| 205 | class="!w-[240px]" | 206 | class="!w-[240px]" |
| 206 | > | 207 | > |
| 207 | - <el-option | 208 | + <ElOption |
| 208 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 209 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 209 | :key="dict.value" | 210 | :key="dict.value" |
| 210 | :value="dict.value" | 211 | :value="dict.value" |
| 211 | :label="dict.label" | 212 | :label="dict.label" |
| 212 | /> | 213 | /> |
| 213 | - </el-select> | ||
| 214 | - </el-form-item> | ||
| 215 | - <el-form-item label="创建时间"> | ||
| 216 | - <el-date-picker | 214 | + </ElSelect> |
| 215 | + </ElFormItem> | ||
| 216 | + <ElFormItem label="创建时间"> | ||
| 217 | + <ElDatePicker | ||
| 217 | v-model="queryParams.createTime" | 218 | v-model="queryParams.createTime" |
| 218 | type="daterange" | 219 | type="daterange" |
| 219 | value-format="YYYY-MM-DD" | 220 | value-format="YYYY-MM-DD" |
| @@ -222,14 +223,14 @@ onMounted(() => { | @@ -222,14 +223,14 @@ onMounted(() => { | ||
| 222 | end-placeholder="结束日期" | 223 | end-placeholder="结束日期" |
| 223 | class="!w-[240px]" | 224 | class="!w-[240px]" |
| 224 | /> | 225 | /> |
| 225 | - </el-form-item> | ||
| 226 | - <el-form-item> | ||
| 227 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 228 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 226 | + </ElFormItem> |
| 227 | + <ElFormItem> | ||
| 228 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 229 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 229 | 搜索 | 230 | 搜索 |
| 230 | - </el-button> | ||
| 231 | - </el-form-item> | ||
| 232 | - </el-form> | 231 | + </ElButton> |
| 232 | + </ElFormItem> | ||
| 233 | + </ElForm> | ||
| 233 | </ContentWrap> | 234 | </ContentWrap> |
| 234 | 235 | ||
| 235 | <!-- 列表 --> | 236 | <!-- 列表 --> |
| @@ -239,7 +240,7 @@ onMounted(() => { | @@ -239,7 +240,7 @@ onMounted(() => { | ||
| 239 | ref="tableToolbarRef" | 240 | ref="tableToolbarRef" |
| 240 | v-model:hidden-search="hiddenSearchBar" | 241 | v-model:hidden-search="hiddenSearchBar" |
| 241 | > | 242 | > |
| 242 | - <el-button | 243 | + <ElButton |
| 243 | class="ml-2" | 244 | class="ml-2" |
| 244 | :icon="h(Plus)" | 245 | :icon="h(Plus)" |
| 245 | type="primary" | 246 | type="primary" |
| @@ -247,8 +248,8 @@ onMounted(() => { | @@ -247,8 +248,8 @@ onMounted(() => { | ||
| 247 | v-access:code="['infra:student:create']" | 248 | v-access:code="['infra:student:create']" |
| 248 | > | 249 | > |
| 249 | {{ $t('ui.actionTitle.create', ['学生']) }} | 250 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 250 | - </el-button> | ||
| 251 | - <el-button | 251 | + </ElButton> |
| 252 | + <ElButton | ||
| 252 | :icon="h(Trash2)" | 253 | :icon="h(Trash2)" |
| 253 | type="danger" | 254 | type="danger" |
| 254 | class="ml-2" | 255 | class="ml-2" |
| @@ -257,10 +258,10 @@ onMounted(() => { | @@ -257,10 +258,10 @@ onMounted(() => { | ||
| 257 | v-access:code="['infra:student:delete']" | 258 | v-access:code="['infra:student:delete']" |
| 258 | > | 259 | > |
| 259 | 批量删除 | 260 | 批量删除 |
| 260 | - </el-button> | ||
| 261 | - </TableToolbar> | 261 | + </ElButton> |
| 262 | + </VbenVxeTableToolbar> | ||
| 262 | </template> | 263 | </template> |
| 263 | - <vxe-table | 264 | + <VxeTable |
| 264 | ref="tableRef" | 265 | ref="tableRef" |
| 265 | :data="list" | 266 | :data="list" |
| 266 | show-overflow | 267 | show-overflow |
| @@ -268,37 +269,37 @@ onMounted(() => { | @@ -268,37 +269,37 @@ onMounted(() => { | ||
| 268 | @checkboxAll="handleRowCheckboxChange" | 269 | @checkboxAll="handleRowCheckboxChange" |
| 269 | @checkboxChange="handleRowCheckboxChange" | 270 | @checkboxChange="handleRowCheckboxChange" |
| 270 | > | 271 | > |
| 271 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 272 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 273 | - <vxe-column field="studentId" title="学生编号" align="center" /> | ||
| 274 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 275 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 276 | - <vxe-column field="birthday" title="出生日期" align="center"> | 272 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 273 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 274 | + <VxeColumn field="studentId" title="学生编号" align="center" /> | ||
| 275 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 276 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 277 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 277 | <template #default="{row}"> | 278 | <template #default="{row}"> |
| 278 | {{formatDateTime(row.birthday)}} | 279 | {{formatDateTime(row.birthday)}} |
| 279 | </template> | 280 | </template> |
| 280 | - </vxe-column> | ||
| 281 | - <vxe-column field="sex" title="性别" align="center"> | 281 | + </VxeColumn> |
| 282 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 282 | <template #default="{row}"> | 283 | <template #default="{row}"> |
| 283 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 284 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 284 | </template> | 285 | </template> |
| 285 | - </vxe-column> | ||
| 286 | - <vxe-column field="enabled" title="是否有效" align="center"> | 286 | + </VxeColumn> |
| 287 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 287 | <template #default="{row}"> | 288 | <template #default="{row}"> |
| 288 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 289 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 289 | </template> | 290 | </template> |
| 290 | - </vxe-column> | ||
| 291 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 292 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 293 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 294 | - <vxe-column field="createTime" title="创建时间" align="center"> | 291 | + </VxeColumn> |
| 292 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 293 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 294 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 295 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 295 | <template #default="{row}"> | 296 | <template #default="{row}"> |
| 296 | {{formatDateTime(row.createTime)}} | 297 | {{formatDateTime(row.createTime)}} |
| 297 | </template> | 298 | </template> |
| 298 | - </vxe-column> | ||
| 299 | - <vxe-column field="operation" title="操作" align="center"> | 299 | + </VxeColumn> |
| 300 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 300 | <template #default="{row}"> | 301 | <template #default="{row}"> |
| 301 | - <el-button | 302 | + <ElButton |
| 302 | size="small" | 303 | size="small" |
| 303 | type="primary" | 304 | type="primary" |
| 304 | link | 305 | link |
| @@ -306,8 +307,8 @@ onMounted(() => { | @@ -306,8 +307,8 @@ onMounted(() => { | ||
| 306 | v-access:code="['infra:student:update']" | 307 | v-access:code="['infra:student:update']" |
| 307 | > | 308 | > |
| 308 | {{ $t('ui.actionTitle.edit') }} | 309 | {{ $t('ui.actionTitle.edit') }} |
| 309 | - </el-button> | ||
| 310 | - <el-button | 310 | + </ElButton> |
| 311 | + <ElButton | ||
| 311 | size="small" | 312 | size="small" |
| 312 | type="danger" | 313 | type="danger" |
| 313 | link | 314 | link |
| @@ -316,13 +317,13 @@ onMounted(() => { | @@ -316,13 +317,13 @@ onMounted(() => { | ||
| 316 | v-access:code="['infra:student:delete']" | 317 | v-access:code="['infra:student:delete']" |
| 317 | > | 318 | > |
| 318 | {{ $t('ui.actionTitle.delete') }} | 319 | {{ $t('ui.actionTitle.delete') }} |
| 319 | - </el-button> | 320 | + </ElButton> |
| 320 | </template> | 321 | </template> |
| 321 | - </vxe-column> | ||
| 322 | - </vxe-table> | 322 | + </VxeColumn> |
| 323 | + </VxeTable> | ||
| 323 | <!-- 分页 --> | 324 | <!-- 分页 --> |
| 324 | <div class="mt-2 flex justify-end"> | 325 | <div class="mt-2 flex justify-end"> |
| 325 | - <el-pagination | 326 | + <ElPagination |
| 326 | :total="total" | 327 | :total="total" |
| 327 | v-model:current-page="queryParams.pageNo" | 328 | v-model:current-page="queryParams.pageNo" |
| 328 | v-model:page-size="queryParams.pageSize" | 329 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -13,7 +13,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | @@ -13,7 +13,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | ||
| 13 | 13 | ||
| 14 | import { computed, ref, reactive } from 'vue'; | 14 | import { computed, ref, reactive } from 'vue'; |
| 15 | import { $t } from '#/locales'; | 15 | import { $t } from '#/locales'; |
| 16 | -import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | 16 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; |
| 17 | 17 | ||
| 18 | const emit = defineEmits(['success']); | 18 | const emit = defineEmits(['success']); |
| 19 | 19 | ||
| @@ -71,7 +71,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -71,7 +71,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 71 | async onConfirm() { | 71 | async onConfirm() { |
| 72 | await formRef.value?.validate(); | 72 | await formRef.value?.validate(); |
| 73 | // 校验子表单 | 73 | // 校验子表单 |
| 74 | - try { | 74 | + if (!studentContactFormRef.value?.validate()) { |
| 75 | + subTabsName.value = 'studentContact'; | ||
| 76 | + return; | ||
| 77 | + } | ||
| 78 | + try { | ||
| 75 | await studentTeacherFormRef.value?.validate() | 79 | await studentTeacherFormRef.value?.validate() |
| 76 | } catch (e) { | 80 | } catch (e) { |
| 77 | subTabsName.value = 'studentTeacher' | 81 | subTabsName.value = 'studentTeacher' |
| @@ -118,65 +122,65 @@ const [Modal, modalApi] = useVbenModal({ | @@ -118,65 +122,65 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 118 | 122 | ||
| 119 | <template> | 123 | <template> |
| 120 | <Modal :title="getTitle"> | 124 | <Modal :title="getTitle"> |
| 121 | - <el-form | 125 | + <ElForm |
| 122 | ref="formRef" | 126 | ref="formRef" |
| 123 | :model="formData" | 127 | :model="formData" |
| 124 | :rules="rules" | 128 | :rules="rules" |
| 125 | label-width="120px" | 129 | label-width="120px" |
| 126 | label-position="right" | 130 | label-position="right" |
| 127 | > | 131 | > |
| 128 | - <el-form-item label="名字" prop="name"> | ||
| 129 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 130 | - </el-form-item> | ||
| 131 | - <el-form-item label="简介" prop="description"> | ||
| 132 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 133 | - </el-form-item> | ||
| 134 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 135 | - <el-date-picker | 132 | + <ElFormItem label="名字" prop="name"> |
| 133 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 134 | + </ElFormItem> | ||
| 135 | + <ElFormItem label="简介" prop="description"> | ||
| 136 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 137 | + </ElFormItem> | ||
| 138 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 139 | + <ElDatePicker | ||
| 136 | v-model="formData.birthday" | 140 | v-model="formData.birthday" |
| 137 | value-format="x" | 141 | value-format="x" |
| 138 | placeholder="选择出生日期" | 142 | placeholder="选择出生日期" |
| 139 | /> | 143 | /> |
| 140 | - </el-form-item> | ||
| 141 | - <el-form-item label="性别" prop="sex"> | ||
| 142 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 143 | - <el-option | 144 | + </ElFormItem> |
| 145 | + <ElFormItem label="性别" prop="sex"> | ||
| 146 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 147 | + <ElOption | ||
| 144 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 148 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 145 | :key="dict.value" | 149 | :key="dict.value" |
| 146 | :value="dict.value" | 150 | :value="dict.value" |
| 147 | :label="dict.label" | 151 | :label="dict.label" |
| 148 | /> | 152 | /> |
| 149 | - </el-select> | ||
| 150 | - </el-form-item> | ||
| 151 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 152 | - <el-radio-group v-model="formData.enabled"> | ||
| 153 | - <el-radio | 153 | + </ElSelect> |
| 154 | + </ElFormItem> | ||
| 155 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 156 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 157 | + <ElRadio | ||
| 154 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 158 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 155 | :key="dict.value" | 159 | :key="dict.value" |
| 156 | - :label="dict.value" | 160 | + :value="dict.value" |
| 157 | > | 161 | > |
| 158 | {{ dict.label }} | 162 | {{ dict.label }} |
| 159 | - </el-radio> | ||
| 160 | - </el-radio-group> | ||
| 161 | - </el-form-item> | ||
| 162 | - <el-form-item label="头像" prop="avatar"> | 163 | + </ElRadio> |
| 164 | + </ElRadioGroup> | ||
| 165 | + </ElFormItem> | ||
| 166 | + <ElFormItem label="头像" prop="avatar"> | ||
| 163 | <ImageUpload v-model="formData.avatar" /> | 167 | <ImageUpload v-model="formData.avatar" /> |
| 164 | - </el-form-item> | ||
| 165 | - <el-form-item label="附件" prop="video"> | 168 | + </ElFormItem> |
| 169 | + <ElFormItem label="附件" prop="video"> | ||
| 166 | <FileUpload v-model="formData.video" /> | 170 | <FileUpload v-model="formData.video" /> |
| 167 | - </el-form-item> | ||
| 168 | - <el-form-item label="备注" prop="memo"> | 171 | + </ElFormItem> |
| 172 | + <ElFormItem label="备注" prop="memo"> | ||
| 169 | <RichTextarea v-model="formData.memo" height="500px" /> | 173 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 170 | - </el-form-item> | ||
| 171 | - </el-form> | 174 | + </ElFormItem> |
| 175 | + </ElForm> | ||
| 172 | <!-- 子表的表单 --> | 176 | <!-- 子表的表单 --> |
| 173 | - <el-tabs v-model="subTabsName"> | ||
| 174 | - <el-tab-pane name="studentContact" label="学生联系人"> | 177 | + <ElTabs v-model="subTabsName"> |
| 178 | + <ElTabPane name="studentContact" label="学生联系人"> | ||
| 175 | <StudentContactForm ref="studentContactFormRef" :student-id="formData?.id" /> | 179 | <StudentContactForm ref="studentContactFormRef" :student-id="formData?.id" /> |
| 176 | - </el-tab-pane> | ||
| 177 | - <el-tab-pane name="studentTeacher" label="学生班主任"> | 180 | + </ElTabPane> |
| 181 | + <ElTabPane name="studentTeacher" label="学生班主任"> | ||
| 178 | <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData?.id" /> | 182 | <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData?.id" /> |
| 179 | - </el-tab-pane> | ||
| 180 | - </el-tabs> | 183 | + </ElTabPane> |
| 184 | + </ElTabs> | ||
| 181 | </Modal> | 185 | </Modal> |
| 182 | </template> | 186 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -19,7 +19,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -19,7 +19,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 19 | 19 | ||
| 20 | import { $t } from '#/locales'; | 20 | import { $t } from '#/locales'; |
| 21 | import { isEmpty } from '@vben/utils'; | 21 | import { isEmpty } from '@vben/utils'; |
| 22 | -import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | 22 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; |
| 23 | 23 | ||
| 24 | /** 子表的列表 */ | 24 | /** 子表的列表 */ |
| 25 | const subTabsName = ref('studentContact') | 25 | const subTabsName = ref('studentContact') |
| @@ -31,12 +31,11 @@ const total = ref(0) // 列表的总页数 | @@ -31,12 +31,11 @@ const total = ref(0) // 列表的总页数 | ||
| 31 | const queryParams = reactive({ | 31 | const queryParams = reactive({ |
| 32 | pageNo: 1, | 32 | pageNo: 1, |
| 33 | pageSize: 10, | 33 | pageSize: 10, |
| 34 | - name: undefined, | ||
| 35 | - birthday: undefined, | ||
| 36 | - birthday: undefined, | ||
| 37 | - sex: undefined, | ||
| 38 | - enabled: undefined, | ||
| 39 | - createTime: undefined, | 34 | + name: undefined, |
| 35 | + birthday: undefined, | ||
| 36 | + sex: undefined, | ||
| 37 | + enabled: undefined, | ||
| 38 | + createTime: undefined, | ||
| 40 | }) | 39 | }) |
| 41 | const queryFormRef = ref() // 搜索的表单 | 40 | const queryFormRef = ref() // 搜索的表单 |
| 42 | const exportLoading = ref(false) // 导出的加载中 | 41 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -130,7 +129,14 @@ function handleRowCheckboxChange({ | @@ -130,7 +129,14 @@ function handleRowCheckboxChange({ | ||
| 130 | async function handleExport() { | 129 | async function handleExport() { |
| 131 | try { | 130 | try { |
| 132 | exportLoading.value = true; | 131 | exportLoading.value = true; |
| 133 | - const data = await exportStudent(queryParams); | 132 | + const params = cloneDeep(queryParams) as any; |
| 133 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 134 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 135 | + } | ||
| 136 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 137 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 138 | + } | ||
| 139 | + const data = await exportStudent(params); | ||
| 134 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 140 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 135 | }finally { | 141 | }finally { |
| 136 | exportLoading.value = false; | 142 | exportLoading.value = false; |
| @@ -152,61 +158,61 @@ onMounted(() => { | @@ -152,61 +158,61 @@ onMounted(() => { | ||
| 152 | 158 | ||
| 153 | <ContentWrap v-if="!hiddenSearchBar"> | 159 | <ContentWrap v-if="!hiddenSearchBar"> |
| 154 | <!-- 搜索工作栏 --> | 160 | <!-- 搜索工作栏 --> |
| 155 | - <el-form | 161 | + <ElForm |
| 156 | :model="queryParams" | 162 | :model="queryParams" |
| 157 | ref="queryFormRef" | 163 | ref="queryFormRef" |
| 158 | inline | 164 | inline |
| 159 | > | 165 | > |
| 160 | - <el-form-item label="名字"> | ||
| 161 | - <el-input | 166 | + <ElFormItem label="名字"> |
| 167 | + <ElInput | ||
| 162 | v-model="queryParams.name" | 168 | v-model="queryParams.name" |
| 163 | placeholder="请输入名字" | 169 | placeholder="请输入名字" |
| 164 | clearable | 170 | clearable |
| 165 | @keyup.enter="handleQuery" | 171 | @keyup.enter="handleQuery" |
| 166 | class="!w-[240px]" | 172 | class="!w-[240px]" |
| 167 | /> | 173 | /> |
| 168 | - </el-form-item> | ||
| 169 | - <el-form-item label="出生日期"> | ||
| 170 | - <el-date-picker | 174 | + </ElFormItem> |
| 175 | + <ElFormItem label="出生日期"> | ||
| 176 | + <ElDatePicker | ||
| 171 | v-model="queryParams.birthday" | 177 | v-model="queryParams.birthday" |
| 172 | value-format="YYYY-MM-DD" | 178 | value-format="YYYY-MM-DD" |
| 173 | placeholder="选择出生日期" | 179 | placeholder="选择出生日期" |
| 174 | clearable | 180 | clearable |
| 175 | class="!w-[240px]" | 181 | class="!w-[240px]" |
| 176 | /> | 182 | /> |
| 177 | - </el-form-item> | ||
| 178 | - <el-form-item label="性别"> | ||
| 179 | - <el-select | 183 | + </ElFormItem> |
| 184 | + <ElFormItem label="性别"> | ||
| 185 | + <ElSelect | ||
| 180 | v-model="queryParams.sex" | 186 | v-model="queryParams.sex" |
| 181 | placeholder="请选择性别" | 187 | placeholder="请选择性别" |
| 182 | clearable | 188 | clearable |
| 183 | class="!w-[240px]" | 189 | class="!w-[240px]" |
| 184 | > | 190 | > |
| 185 | - <el-option | 191 | + <ElOption |
| 186 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 192 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 187 | :key="dict.value" | 193 | :key="dict.value" |
| 188 | :value="dict.value" | 194 | :value="dict.value" |
| 189 | :label="dict.label" | 195 | :label="dict.label" |
| 190 | /> | 196 | /> |
| 191 | - </el-select> | ||
| 192 | - </el-form-item> | ||
| 193 | - <el-form-item label="是否有效"> | ||
| 194 | - <el-select | 197 | + </ElSelect> |
| 198 | + </ElFormItem> | ||
| 199 | + <ElFormItem label="是否有效"> | ||
| 200 | + <ElSelect | ||
| 195 | v-model="queryParams.enabled" | 201 | v-model="queryParams.enabled" |
| 196 | placeholder="请选择是否有效" | 202 | placeholder="请选择是否有效" |
| 197 | clearable | 203 | clearable |
| 198 | class="!w-[240px]" | 204 | class="!w-[240px]" |
| 199 | > | 205 | > |
| 200 | - <el-option | 206 | + <ElOption |
| 201 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 207 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 202 | :key="dict.value" | 208 | :key="dict.value" |
| 203 | :value="dict.value" | 209 | :value="dict.value" |
| 204 | :label="dict.label" | 210 | :label="dict.label" |
| 205 | /> | 211 | /> |
| 206 | - </el-select> | ||
| 207 | - </el-form-item> | ||
| 208 | - <el-form-item label="创建时间"> | ||
| 209 | - <el-date-picker | 212 | + </ElSelect> |
| 213 | + </ElFormItem> | ||
| 214 | + <ElFormItem label="创建时间"> | ||
| 215 | + <ElDatePicker | ||
| 210 | v-model="queryParams.createTime" | 216 | v-model="queryParams.createTime" |
| 211 | type="daterange" | 217 | type="daterange" |
| 212 | value-format="YYYY-MM-DD" | 218 | value-format="YYYY-MM-DD" |
| @@ -215,24 +221,24 @@ onMounted(() => { | @@ -215,24 +221,24 @@ onMounted(() => { | ||
| 215 | end-placeholder="结束日期" | 221 | end-placeholder="结束日期" |
| 216 | class="!w-[240px]" | 222 | class="!w-[240px]" |
| 217 | /> | 223 | /> |
| 218 | - </el-form-item> | ||
| 219 | - <el-form-item> | ||
| 220 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 221 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 224 | + </ElFormItem> |
| 225 | + <ElFormItem> | ||
| 226 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 227 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 222 | 搜索 | 228 | 搜索 |
| 223 | - </el-button> | ||
| 224 | - </el-form-item> | ||
| 225 | - </el-form> | 229 | + </ElButton> |
| 230 | + </ElFormItem> | ||
| 231 | + </ElForm> | ||
| 226 | </ContentWrap> | 232 | </ContentWrap> |
| 227 | 233 | ||
| 228 | <!-- 列表 --> | 234 | <!-- 列表 --> |
| 229 | <ContentWrap title="学生"> | 235 | <ContentWrap title="学生"> |
| 230 | <template #extra> | 236 | <template #extra> |
| 231 | - <TableToolbar | 237 | + <VbenVxeTableToolbar |
| 232 | ref="tableToolbarRef" | 238 | ref="tableToolbarRef" |
| 233 | v-model:hidden-search="hiddenSearchBar" | 239 | v-model:hidden-search="hiddenSearchBar" |
| 234 | > | 240 | > |
| 235 | - <el-button | 241 | + <ElButton |
| 236 | class="ml-2" | 242 | class="ml-2" |
| 237 | :icon="h(Plus)" | 243 | :icon="h(Plus)" |
| 238 | type="primary" | 244 | type="primary" |
| @@ -240,8 +246,8 @@ onMounted(() => { | @@ -240,8 +246,8 @@ onMounted(() => { | ||
| 240 | v-access:code="['infra:student:create']" | 246 | v-access:code="['infra:student:create']" |
| 241 | > | 247 | > |
| 242 | {{ $t('ui.actionTitle.create', ['学生']) }} | 248 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 243 | - </el-button> | ||
| 244 | - <el-button | 249 | + </ElButton> |
| 250 | + <ElButton | ||
| 245 | :icon="h(Download)" | 251 | :icon="h(Download)" |
| 246 | type="primary" | 252 | type="primary" |
| 247 | class="ml-2" | 253 | class="ml-2" |
| @@ -250,8 +256,8 @@ onMounted(() => { | @@ -250,8 +256,8 @@ onMounted(() => { | ||
| 250 | v-access:code="['infra:student:export']" | 256 | v-access:code="['infra:student:export']" |
| 251 | > | 257 | > |
| 252 | {{ $t('ui.actionTitle.export') }} | 258 | {{ $t('ui.actionTitle.export') }} |
| 253 | - </el-button> | ||
| 254 | - <el-button | 259 | + </ElButton> |
| 260 | + <ElButton | ||
| 255 | :icon="h(Trash2)" | 261 | :icon="h(Trash2)" |
| 256 | type="danger" | 262 | type="danger" |
| 257 | class="ml-2" | 263 | class="ml-2" |
| @@ -260,10 +266,10 @@ onMounted(() => { | @@ -260,10 +266,10 @@ onMounted(() => { | ||
| 260 | v-access:code="['infra:student:delete']" | 266 | v-access:code="['infra:student:delete']" |
| 261 | > | 267 | > |
| 262 | 批量删除 | 268 | 批量删除 |
| 263 | - </el-button> | ||
| 264 | - </TableToolbar> | 269 | + </ElButton> |
| 270 | + </VbenVxeTableToolbar> | ||
| 265 | </template> | 271 | </template> |
| 266 | - <vxe-table | 272 | + <VxeTable |
| 267 | ref="tableRef" | 273 | ref="tableRef" |
| 268 | :data="list" | 274 | :data="list" |
| 269 | show-overflow | 275 | show-overflow |
| @@ -271,50 +277,50 @@ onMounted(() => { | @@ -271,50 +277,50 @@ onMounted(() => { | ||
| 271 | @checkboxAll="handleRowCheckboxChange" | 277 | @checkboxAll="handleRowCheckboxChange" |
| 272 | @checkboxChange="handleRowCheckboxChange" | 278 | @checkboxChange="handleRowCheckboxChange" |
| 273 | > | 279 | > |
| 274 | - <vxe-column type="checkbox" width="40"></vxe-column> | 280 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 275 | <!-- 子表的列表 --> | 281 | <!-- 子表的列表 --> |
| 276 | - <vxe-column type="expand" width="60"> | 282 | + <VxeColumn type="expand" width="60"> |
| 277 | <template #content="{ row }"> | 283 | <template #content="{ row }"> |
| 278 | <!-- 子表的表单 --> | 284 | <!-- 子表的表单 --> |
| 279 | - <el-tabs v-model="subTabsName" class="mx-8"> | ||
| 280 | - <el-tab-pane name="studentContact" label="学生联系人"> | 285 | + <ElTabs v-model="subTabsName" class="mx-8"> |
| 286 | + <ElTabPane name="studentContact" label="学生联系人"> | ||
| 281 | <StudentContactList :student-id="row?.id" /> | 287 | <StudentContactList :student-id="row?.id" /> |
| 282 | - </el-tab-pane> | ||
| 283 | - <el-tab-pane name="studentTeacher" label="学生班主任"> | 288 | + </ElTabPane> |
| 289 | + <ElTabPane name="studentTeacher" label="学生班主任"> | ||
| 284 | <StudentTeacherList :student-id="row?.id" /> | 290 | <StudentTeacherList :student-id="row?.id" /> |
| 285 | - </el-tab-pane> | ||
| 286 | - </el-tabs> | 291 | + </ElTabPane> |
| 292 | + </ElTabs> | ||
| 287 | </template> | 293 | </template> |
| 288 | - </vxe-column> | ||
| 289 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 290 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 291 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 292 | - <vxe-column field="birthday" title="出生日期" align="center"> | 294 | + </VxeColumn> |
| 295 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 296 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 297 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 298 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 293 | <template #default="{row}"> | 299 | <template #default="{row}"> |
| 294 | {{formatDateTime(row.birthday)}} | 300 | {{formatDateTime(row.birthday)}} |
| 295 | </template> | 301 | </template> |
| 296 | - </vxe-column> | ||
| 297 | - <vxe-column field="sex" title="性别" align="center"> | 302 | + </VxeColumn> |
| 303 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 298 | <template #default="{row}"> | 304 | <template #default="{row}"> |
| 299 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 305 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 300 | </template> | 306 | </template> |
| 301 | - </vxe-column> | ||
| 302 | - <vxe-column field="enabled" title="是否有效" align="center"> | 307 | + </VxeColumn> |
| 308 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 303 | <template #default="{row}"> | 309 | <template #default="{row}"> |
| 304 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 310 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 305 | </template> | 311 | </template> |
| 306 | - </vxe-column> | ||
| 307 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 308 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 309 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 310 | - <vxe-column field="createTime" title="创建时间" align="center"> | 312 | + </VxeColumn> |
| 313 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 314 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 315 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 316 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 311 | <template #default="{row}"> | 317 | <template #default="{row}"> |
| 312 | {{formatDateTime(row.createTime)}} | 318 | {{formatDateTime(row.createTime)}} |
| 313 | </template> | 319 | </template> |
| 314 | - </vxe-column> | ||
| 315 | - <vxe-column field="operation" title="操作" align="center"> | 320 | + </VxeColumn> |
| 321 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 316 | <template #default="{row}"> | 322 | <template #default="{row}"> |
| 317 | - <el-button | 323 | + <ElButton |
| 318 | size="small" | 324 | size="small" |
| 319 | type="primary" | 325 | type="primary" |
| 320 | link | 326 | link |
| @@ -322,8 +328,8 @@ onMounted(() => { | @@ -322,8 +328,8 @@ onMounted(() => { | ||
| 322 | v-access:code="['infra:student:update']" | 328 | v-access:code="['infra:student:update']" |
| 323 | > | 329 | > |
| 324 | {{ $t('ui.actionTitle.edit') }} | 330 | {{ $t('ui.actionTitle.edit') }} |
| 325 | - </el-button> | ||
| 326 | - <el-button | 331 | + </ElButton> |
| 332 | + <ElButton | ||
| 327 | size="small" | 333 | size="small" |
| 328 | type="danger" | 334 | type="danger" |
| 329 | link | 335 | link |
| @@ -332,13 +338,13 @@ onMounted(() => { | @@ -332,13 +338,13 @@ onMounted(() => { | ||
| 332 | v-access:code="['infra:student:delete']" | 338 | v-access:code="['infra:student:delete']" |
| 333 | > | 339 | > |
| 334 | {{ $t('ui.actionTitle.delete') }} | 340 | {{ $t('ui.actionTitle.delete') }} |
| 335 | - </el-button> | 341 | + </ElButton> |
| 336 | </template> | 342 | </template> |
| 337 | - </vxe-column> | ||
| 338 | - </vxe-table> | 343 | + </VxeColumn> |
| 344 | + </VxeTable> | ||
| 339 | <!-- 分页 --> | 345 | <!-- 分页 --> |
| 340 | <div class="mt-2 flex justify-end"> | 346 | <div class="mt-2 flex justify-end"> |
| 341 | - <el-pagination | 347 | + <ElPagination |
| 342 | :total="total" | 348 | :total="total" |
| 343 | v-model:current-page="queryParams.pageNo" | 349 | v-model:current-page="queryParams.pageNo" |
| 344 | v-model:page-size="queryParams.pageSize" | 350 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/student-contact-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 3 | +import type { StudentApi } from '#/api/infra/demo'; | ||
| 3 | 4 | ||
| 4 | -import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue'; | 5 | +import { ref, watch } from 'vue'; |
| 5 | 6 | ||
| 6 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 7 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { Plus } from '@vben/icons'; | ||
| 8 | 10 | ||
| 9 | -import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus'; | ||
| 10 | -import { $t } from '#/locales'; | 11 | +import { |
| 12 | + ElButton, | ||
| 13 | + ElDatePicker, | ||
| 14 | + ElInput, | ||
| 15 | + ElMessage, | ||
| 16 | + ElOption, | ||
| 17 | + ElRadio, | ||
| 18 | + ElRadioGroup, | ||
| 19 | + ElSelect, | ||
| 20 | +} from 'element-plus'; | ||
| 11 | 21 | ||
| 12 | - import type { VxeTableInstance } from '#/adapter/vxe-table'; | ||
| 13 | -import { Plus } from "@vben/icons"; | ||
| 14 | -import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 15 | -import { getStudentContactListByStudentId } from '#/api/infra/student'; | 22 | + import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; |
| 23 | +import { getStudentContactListByStudentId } from '#/api/infra/demo'; | ||
| 24 | +import { $t } from '#/locales'; | ||
| 16 | 25 | ||
| 17 | const props = defineProps<{ | 26 | const props = defineProps<{ |
| 18 | studentId?: number // 学生编号(主表的关联字段) | 27 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -30,24 +39,96 @@ async function onDelete(row: StudentApi.StudentContact) { | @@ -30,24 +39,96 @@ async function onDelete(row: StudentApi.StudentContact) { | ||
| 30 | await tableRef.value?.remove(row); | 39 | await tableRef.value?.remove(row); |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 34 | -defineExpose({ | ||
| 35 | - getData: (): StudentApi.StudentContact[] => { | ||
| 36 | - const data = list.value as StudentApi.StudentContact[]; | ||
| 37 | - const removeRecords = tableRef.value?.getRemoveRecords() as StudentApi.StudentContact[]; | ||
| 38 | - const insertRecords = tableRef.value?.getInsertRecords() as StudentApi.StudentContact[]; | ||
| 39 | - return [ | ||
| 40 | - ...data.filter( | ||
| 41 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 42 | - ), | ||
| 43 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 44 | - }, | ||
| 45 | -}); | 42 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 43 | +function getData(): StudentApi.StudentContact[] { | ||
| 44 | + const table = tableRef.value; | ||
| 45 | + if (!table) { | ||
| 46 | + return []; | ||
| 47 | + } | ||
| 48 | + const { fullData } = table.getTableData(); | ||
| 49 | + const inserted = new Set(table.getInsertRecords()); | ||
| 50 | + return fullData.map((row) => | ||
| 51 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 52 | + ); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/** 校验子表必填字段 */ | ||
| 56 | +function validate(): boolean { | ||
| 57 | + for (const [index, row] of getData().entries()) { | ||
| 58 | + if ( | ||
| 59 | + row.name === null || | ||
| 60 | + row.name === undefined || | ||
| 61 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 62 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 63 | + ) { | ||
| 64 | + ElMessage.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 65 | + return false; | ||
| 66 | + } | ||
| 67 | + if ( | ||
| 68 | + row.description === null || | ||
| 69 | + row.description === undefined || | ||
| 70 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 71 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 72 | + ) { | ||
| 73 | + ElMessage.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 74 | + return false; | ||
| 75 | + } | ||
| 76 | + if ( | ||
| 77 | + row.birthday === null || | ||
| 78 | + row.birthday === undefined || | ||
| 79 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 80 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 81 | + ) { | ||
| 82 | + ElMessage.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 83 | + return false; | ||
| 84 | + } | ||
| 85 | + if ( | ||
| 86 | + row.sex === null || | ||
| 87 | + row.sex === undefined || | ||
| 88 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 89 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 90 | + ) { | ||
| 91 | + ElMessage.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 92 | + return false; | ||
| 93 | + } | ||
| 94 | + if ( | ||
| 95 | + row.enabled === null || | ||
| 96 | + row.enabled === undefined || | ||
| 97 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 98 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 99 | + ) { | ||
| 100 | + ElMessage.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 101 | + return false; | ||
| 102 | + } | ||
| 103 | + if ( | ||
| 104 | + row.avatar === null || | ||
| 105 | + row.avatar === undefined || | ||
| 106 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 107 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 108 | + ) { | ||
| 109 | + ElMessage.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 110 | + return false; | ||
| 111 | + } | ||
| 112 | + if ( | ||
| 113 | + row.memo === null || | ||
| 114 | + row.memo === undefined || | ||
| 115 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 116 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 117 | + ) { | ||
| 118 | + ElMessage.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 119 | + return false; | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + return true; | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +defineExpose({ getData, validate }); | ||
| 46 | 126 | ||
| 47 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 127 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 48 | watch( | 128 | watch( |
| 49 | () => props.studentId, | 129 | () => props.studentId, |
| 50 | async (val) => { | 130 | async (val) => { |
| 131 | + list.value = []; | ||
| 51 | if (!val) { | 132 | if (!val) { |
| 52 | return; | 133 | return; |
| 53 | } | 134 | } |
| @@ -58,70 +139,70 @@ watch( | @@ -58,70 +139,70 @@ watch( | ||
| 58 | </script> | 139 | </script> |
| 59 | 140 | ||
| 60 | <template> | 141 | <template> |
| 61 | - <vxe-table ref="tableRef" :data="list" show-overflow class="mx-4"> | ||
| 62 | - <vxe-column field="name" title="名字" align="center"> | 142 | + <VxeTable ref="tableRef" :data="list" show-overflow class="mx-4"> |
| 143 | + <VxeColumn field="name" title="名字" align="center"> | ||
| 63 | <template #default="{row}"> | 144 | <template #default="{row}"> |
| 64 | - <el-input v-model="row.name" /> | 145 | + <ElInput v-model="row.name" /> |
| 65 | </template> | 146 | </template> |
| 66 | - </vxe-column> | ||
| 67 | - <vxe-column field="description" title="简介" align="center"> | 147 | + </VxeColumn> |
| 148 | + <VxeColumn field="description" title="简介" align="center"> | ||
| 68 | <template #default="{row}"> | 149 | <template #default="{row}"> |
| 69 | - <el-input v-model="row.description" type="textarea" /> | 150 | + <ElInput v-model="row.description" type="textarea" /> |
| 70 | </template> | 151 | </template> |
| 71 | - </vxe-column> | ||
| 72 | - <vxe-column field="birthday" title="出生日期" align="center"> | 152 | + </VxeColumn> |
| 153 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 73 | <template #default="{row}"> | 154 | <template #default="{row}"> |
| 74 | - <el-date-picker | 155 | + <ElDatePicker |
| 75 | v-model="row.birthday" | 156 | v-model="row.birthday" |
| 76 | type="datetime" | 157 | type="datetime" |
| 77 | value-format="x" | 158 | value-format="x" |
| 78 | format="YYYY-MM-DD HH:mm:ss" | 159 | format="YYYY-MM-DD HH:mm:ss" |
| 79 | /> | 160 | /> |
| 80 | </template> | 161 | </template> |
| 81 | - </vxe-column> | ||
| 82 | - <vxe-column field="sex" title="性别" align="center"> | 162 | + </VxeColumn> |
| 163 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 83 | <template #default="{row}"> | 164 | <template #default="{row}"> |
| 84 | - <el-select v-model="row.sex" placeholder="请选择性别"> | ||
| 85 | - <el-option | ||
| 86 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number')" | 165 | + <ElSelect v-model="row.sex" placeholder="请选择性别"> |
| 166 | + <ElOption | ||
| 167 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | ||
| 87 | :key="dict.value" | 168 | :key="dict.value" |
| 88 | :value="dict.value" | 169 | :value="dict.value" |
| 89 | :label="dict.label" | 170 | :label="dict.label" |
| 90 | /> | 171 | /> |
| 91 | - </el-select> | 172 | + </ElSelect> |
| 92 | </template> | 173 | </template> |
| 93 | - </vxe-column> | ||
| 94 | - <vxe-column field="enabled" title="是否有效" align="center"> | 174 | + </VxeColumn> |
| 175 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 95 | <template #default="{row}"> | 176 | <template #default="{row}"> |
| 96 | - <el-radio-group v-model="row.enabled"> | ||
| 97 | - <el-radio | ||
| 98 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'boolean')" | 177 | + <ElRadioGroup v-model="row.enabled"> |
| 178 | + <ElRadio | ||
| 179 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | ||
| 99 | :key="dict.value" | 180 | :key="dict.value" |
| 100 | - :label="dict.value" | 181 | + :value="dict.value" |
| 101 | > | 182 | > |
| 102 | {{ dict.label }} | 183 | {{ dict.label }} |
| 103 | - </el-radio> | ||
| 104 | - </el-radio-group> | 184 | + </ElRadio> |
| 185 | + </ElRadioGroup> | ||
| 105 | </template> | 186 | </template> |
| 106 | - </vxe-column> | ||
| 107 | - <vxe-column field="avatar" title="头像" align="center"> | 187 | + </VxeColumn> |
| 188 | + <VxeColumn field="avatar" title="头像" align="center"> | ||
| 108 | <template #default="{row}"> | 189 | <template #default="{row}"> |
| 109 | <ImageUpload v-model="row.avatar" /> | 190 | <ImageUpload v-model="row.avatar" /> |
| 110 | </template> | 191 | </template> |
| 111 | - </vxe-column> | ||
| 112 | - <vxe-column field="video" title="附件" align="center"> | 192 | + </VxeColumn> |
| 193 | + <VxeColumn field="video" title="附件" align="center"> | ||
| 113 | <template #default="{row}"> | 194 | <template #default="{row}"> |
| 114 | <FileUpload v-model="row.video" /> | 195 | <FileUpload v-model="row.video" /> |
| 115 | </template> | 196 | </template> |
| 116 | - </vxe-column> | ||
| 117 | - <vxe-column field="memo" title="备注" align="center"> | 197 | + </VxeColumn> |
| 198 | + <VxeColumn field="memo" title="备注" align="center"> | ||
| 118 | <template #default="{row}"> | 199 | <template #default="{row}"> |
| 119 | - <el-input v-model="row.memo" type="textarea" /> | 200 | + <ElInput v-model="row.memo" type="textarea" /> |
| 120 | </template> | 201 | </template> |
| 121 | - </vxe-column> | ||
| 122 | - <vxe-column field="operation" title="操作" align="center"> | 202 | + </VxeColumn> |
| 203 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 123 | <template #default="{row}"> | 204 | <template #default="{row}"> |
| 124 | - <el-button | 205 | + <ElButton |
| 125 | size="small" | 206 | size="small" |
| 126 | type="danger" | 207 | type="danger" |
| 127 | link | 208 | link |
| @@ -129,13 +210,13 @@ watch( | @@ -129,13 +210,13 @@ watch( | ||
| 129 | v-access:code="['infra:student:delete']" | 210 | v-access:code="['infra:student:delete']" |
| 130 | > | 211 | > |
| 131 | {{ $t('ui.actionTitle.delete') }} | 212 | {{ $t('ui.actionTitle.delete') }} |
| 132 | - </el-button> | 213 | + </ElButton> |
| 133 | </template> | 214 | </template> |
| 134 | - </vxe-column> | ||
| 135 | - </vxe-table> | 215 | + </VxeColumn> |
| 216 | + </VxeTable> | ||
| 136 | <div class="flex justify-center mt-4"> | 217 | <div class="flex justify-center mt-4"> |
| 137 | - <el-button :icon="h(Plus)" type="primary" plain @click="handleAdd" v-access:code="['infra:student:create']"> | 218 | + <ElButton :icon="Plus" type="primary" plain @click="handleAdd" v-access:code="['infra:student:create']"> |
| 138 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} | 219 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} |
| 139 | - </el-button> | 220 | + </ElButton> |
| 140 | </div> | 221 | </div> |
| 141 | </template> | 222 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/student-contact-list
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; | 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 4 | 4 | ||
| 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; | 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; |
| 6 | 6 | ||
| 7 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 8 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { formatDateTime } from '@vben/utils'; | ||
| 9 | 10 | ||
| 10 | import { DictTag } from '#/components/dict-tag'; | 11 | import { DictTag } from '#/components/dict-tag'; |
| 11 | import { getRangePickerDefaultProps } from '#/utils'; | 12 | import { getRangePickerDefaultProps } from '#/utils'; |
| @@ -13,7 +14,7 @@ | @@ -13,7 +14,7 @@ | ||
| 13 | import { ContentWrap } from '#/components/content-wrap'; | 14 | import { ContentWrap } from '#/components/content-wrap'; |
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | - import { getStudentContactListByStudentId } from '#/api/infra/student'; | 17 | + import { getStudentContactListByStudentId } from '#/api/infra/demo'; |
| 17 | 18 | ||
| 18 | const props = defineProps<{ | 19 | const props = defineProps<{ |
| 19 | studentId?: number // 学生编号(主表的关联字段) | 20 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -52,38 +53,38 @@ watch( | @@ -52,38 +53,38 @@ watch( | ||
| 52 | 53 | ||
| 53 | <template> | 54 | <template> |
| 54 | <ContentWrap title="学生联系人列表"> | 55 | <ContentWrap title="学生联系人列表"> |
| 55 | - <vxe-table | 56 | + <VxeTable |
| 56 | :data="list" | 57 | :data="list" |
| 57 | show-overflow | 58 | show-overflow |
| 58 | :loading="loading" | 59 | :loading="loading" |
| 59 | > | 60 | > |
| 60 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 61 | - <vxe-column field="studentId" title="学生编号" align="center" /> | ||
| 62 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 63 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 64 | - <vxe-column field="birthday" title="出生日期" align="center"> | 61 | + <VxeColumn field="id" title="编号" align="center" /> |
| 62 | + <VxeColumn field="studentId" title="学生编号" align="center" /> | ||
| 63 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 64 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 65 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 65 | <template #default="{row}"> | 66 | <template #default="{row}"> |
| 66 | {{formatDateTime(row.birthday)}} | 67 | {{formatDateTime(row.birthday)}} |
| 67 | </template> | 68 | </template> |
| 68 | - </vxe-column> | ||
| 69 | - <vxe-column field="sex" title="性别" align="center"> | 69 | + </VxeColumn> |
| 70 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 70 | <template #default="{row}"> | 71 | <template #default="{row}"> |
| 71 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 72 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 72 | </template> | 73 | </template> |
| 73 | - </vxe-column> | ||
| 74 | - <vxe-column field="enabled" title="是否有效" align="center"> | 74 | + </VxeColumn> |
| 75 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 75 | <template #default="{row}"> | 76 | <template #default="{row}"> |
| 76 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 77 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 77 | </template> | 78 | </template> |
| 78 | - </vxe-column> | ||
| 79 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 80 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 81 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 82 | - <vxe-column field="createTime" title="创建时间" align="center"> | 79 | + </VxeColumn> |
| 80 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 81 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 82 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 83 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 83 | <template #default="{row}"> | 84 | <template #default="{row}"> |
| 84 | {{formatDateTime(row.createTime)}} | 85 | {{formatDateTime(row.createTime)}} |
| 85 | </template> | 86 | </template> |
| 86 | - </vxe-column> | ||
| 87 | - </vxe-table> | 87 | + </VxeColumn> |
| 88 | + </VxeTable> | ||
| 88 | </ContentWrap> | 89 | </ContentWrap> |
| 89 | </template> | 90 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/student-teacher-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { FormRules } from 'element-plus'; |
| 3 | +import type { StudentApi } from '#/api/infra/demo'; | ||
| 3 | 4 | ||
| 4 | -import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue'; | 5 | +import { nextTick, reactive, ref, watch } from 'vue'; |
| 5 | 6 | ||
| 6 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 7 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 8 | 9 | ||
| 9 | -import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus'; | ||
| 10 | -import { $t } from '#/locales'; | 10 | +import { |
| 11 | + ElForm, | ||
| 12 | + ElFormItem, | ||
| 13 | + ElDatePicker, | ||
| 14 | + ElInput, | ||
| 15 | + ElOption, | ||
| 16 | + ElRadio, | ||
| 17 | + ElRadioGroup, | ||
| 18 | + ElSelect, | ||
| 19 | +} from 'element-plus'; | ||
| 11 | 20 | ||
| 12 | -import type { FormRules } from 'element-plus'; | ||
| 13 | import { Tinymce as RichTextarea } from '#/components/tinymce'; | 21 | import { Tinymce as RichTextarea } from '#/components/tinymce'; |
| 14 | -import { getStudentTeacherByStudentId } from '#/api/infra/student'; | 22 | +import { getStudentTeacherByStudentId } from '#/api/infra/demo'; |
| 23 | +import { $t } from '#/locales'; | ||
| 15 | 24 | ||
| 16 | const props = defineProps<{ | 25 | const props = defineProps<{ |
| 17 | studentId?: number // 学生编号(主表的关联字段) | 26 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -50,6 +59,18 @@ defineExpose({ | @@ -50,6 +59,18 @@ defineExpose({ | ||
| 50 | watch( | 59 | watch( |
| 51 | () => props.studentId, | 60 | () => props.studentId, |
| 52 | async (val) => { | 61 | async (val) => { |
| 62 | + formData.value = { | ||
| 63 | + id: undefined, | ||
| 64 | + studentId: undefined, | ||
| 65 | + name: undefined, | ||
| 66 | + description: undefined, | ||
| 67 | + birthday: undefined, | ||
| 68 | + sex: undefined, | ||
| 69 | + enabled: undefined, | ||
| 70 | + avatar: undefined, | ||
| 71 | + video: undefined, | ||
| 72 | + memo: undefined, | ||
| 73 | + }; | ||
| 53 | if (!val) { | 74 | if (!val) { |
| 54 | return; | 75 | return; |
| 55 | } | 76 | } |
| @@ -61,7 +82,7 @@ watch( | @@ -61,7 +82,7 @@ watch( | ||
| 61 | </script> | 82 | </script> |
| 62 | 83 | ||
| 63 | <template> | 84 | <template> |
| 64 | - <el-form | 85 | + <ElForm |
| 65 | ref="formRef" | 86 | ref="formRef" |
| 66 | class="mx-4" | 87 | class="mx-4" |
| 67 | :model="formData" | 88 | :model="formData" |
| @@ -69,48 +90,48 @@ watch( | @@ -69,48 +90,48 @@ watch( | ||
| 69 | label-width="120px" | 90 | label-width="120px" |
| 70 | label-position="right" | 91 | label-position="right" |
| 71 | > | 92 | > |
| 72 | - <el-form-item label="名字" prop="name"> | ||
| 73 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 74 | - </el-form-item> | ||
| 75 | - <el-form-item label="简介" prop="description"> | ||
| 76 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 77 | - </el-form-item> | ||
| 78 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 79 | - <el-date-picker | 93 | + <ElFormItem label="名字" prop="name"> |
| 94 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 95 | + </ElFormItem> | ||
| 96 | + <ElFormItem label="简介" prop="description"> | ||
| 97 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 98 | + </ElFormItem> | ||
| 99 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 100 | + <ElDatePicker | ||
| 80 | v-model="formData.birthday" | 101 | v-model="formData.birthday" |
| 81 | value-format="x" | 102 | value-format="x" |
| 82 | placeholder="选择出生日期" | 103 | placeholder="选择出生日期" |
| 83 | /> | 104 | /> |
| 84 | - </el-form-item> | ||
| 85 | - <el-form-item label="性别" prop="sex"> | ||
| 86 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 87 | - <el-option | 105 | + </ElFormItem> |
| 106 | + <ElFormItem label="性别" prop="sex"> | ||
| 107 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 108 | + <ElOption | ||
| 88 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 109 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 89 | :key="dict.value" | 110 | :key="dict.value" |
| 90 | :value="dict.value" | 111 | :value="dict.value" |
| 91 | :label="dict.label" | 112 | :label="dict.label" |
| 92 | /> | 113 | /> |
| 93 | - </el-select> | ||
| 94 | - </el-form-item> | ||
| 95 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 96 | - <el-radio-group v-model="formData.enabled"> | ||
| 97 | - <el-radio | 114 | + </ElSelect> |
| 115 | + </ElFormItem> | ||
| 116 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 117 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 118 | + <ElRadio | ||
| 98 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 119 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 99 | :key="dict.value" | 120 | :key="dict.value" |
| 100 | - :label="dict.value" | 121 | + :value="dict.value" |
| 101 | > | 122 | > |
| 102 | {{ dict.label }} | 123 | {{ dict.label }} |
| 103 | - </el-radio> | ||
| 104 | - </el-radio-group> | ||
| 105 | - </el-form-item> | ||
| 106 | - <el-form-item label="头像" prop="avatar"> | 124 | + </ElRadio> |
| 125 | + </ElRadioGroup> | ||
| 126 | + </ElFormItem> | ||
| 127 | + <ElFormItem label="头像" prop="avatar"> | ||
| 107 | <ImageUpload v-model="formData.avatar" /> | 128 | <ImageUpload v-model="formData.avatar" /> |
| 108 | - </el-form-item> | ||
| 109 | - <el-form-item label="附件" prop="video"> | 129 | + </ElFormItem> |
| 130 | + <ElFormItem label="附件" prop="video"> | ||
| 110 | <FileUpload v-model="formData.video" /> | 131 | <FileUpload v-model="formData.video" /> |
| 111 | - </el-form-item> | ||
| 112 | - <el-form-item label="备注" prop="memo"> | 132 | + </ElFormItem> |
| 133 | + <ElFormItem label="备注" prop="memo"> | ||
| 113 | <RichTextarea v-model="formData.memo" height="500px" /> | 134 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 114 | - </el-form-item> | ||
| 115 | - </el-form> | 135 | + </ElFormItem> |
| 136 | + </ElForm> | ||
| 116 | </template> | 137 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/vue/student-teacher-list
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | - import type { StudentApi } from '#/api/infra/student'; | 2 | + import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; | 3 | import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 4 | 4 | ||
| 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; | 5 | import { reactive,ref, h, nextTick,watch,onMounted } from 'vue'; |
| 6 | 6 | ||
| 7 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 8 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { formatDateTime } from '@vben/utils'; | ||
| 9 | 10 | ||
| 10 | import { DictTag } from '#/components/dict-tag'; | 11 | import { DictTag } from '#/components/dict-tag'; |
| 11 | import { getRangePickerDefaultProps } from '#/utils'; | 12 | import { getRangePickerDefaultProps } from '#/utils'; |
| @@ -13,7 +14,7 @@ | @@ -13,7 +14,7 @@ | ||
| 13 | import { ContentWrap } from '#/components/content-wrap'; | 14 | import { ContentWrap } from '#/components/content-wrap'; |
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | - import { getStudentTeacherByStudentId } from '#/api/infra/student'; | 17 | + import { getStudentTeacherByStudentId } from '#/api/infra/demo'; |
| 17 | 18 | ||
| 18 | const props = defineProps<{ | 19 | const props = defineProps<{ |
| 19 | studentId?: number // 学生编号(主表的关联字段) | 20 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -52,38 +53,38 @@ watch( | @@ -52,38 +53,38 @@ watch( | ||
| 52 | 53 | ||
| 53 | <template> | 54 | <template> |
| 54 | <ContentWrap title="学生班主任列表"> | 55 | <ContentWrap title="学生班主任列表"> |
| 55 | - <vxe-table | 56 | + <VxeTable |
| 56 | :data="list" | 57 | :data="list" |
| 57 | show-overflow | 58 | show-overflow |
| 58 | :loading="loading" | 59 | :loading="loading" |
| 59 | > | 60 | > |
| 60 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 61 | - <vxe-column field="studentId" title="学生编号" align="center" /> | ||
| 62 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 63 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 64 | - <vxe-column field="birthday" title="出生日期" align="center"> | 61 | + <VxeColumn field="id" title="编号" align="center" /> |
| 62 | + <VxeColumn field="studentId" title="学生编号" align="center" /> | ||
| 63 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 64 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 65 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 65 | <template #default="{row}"> | 66 | <template #default="{row}"> |
| 66 | {{formatDateTime(row.birthday)}} | 67 | {{formatDateTime(row.birthday)}} |
| 67 | </template> | 68 | </template> |
| 68 | - </vxe-column> | ||
| 69 | - <vxe-column field="sex" title="性别" align="center"> | 69 | + </VxeColumn> |
| 70 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 70 | <template #default="{row}"> | 71 | <template #default="{row}"> |
| 71 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 72 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 72 | </template> | 73 | </template> |
| 73 | - </vxe-column> | ||
| 74 | - <vxe-column field="enabled" title="是否有效" align="center"> | 74 | + </VxeColumn> |
| 75 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 75 | <template #default="{row}"> | 76 | <template #default="{row}"> |
| 76 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 77 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 77 | </template> | 78 | </template> |
| 78 | - </vxe-column> | ||
| 79 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 80 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 81 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 82 | - <vxe-column field="createTime" title="创建时间" align="center"> | 79 | + </VxeColumn> |
| 80 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 81 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 82 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 83 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 83 | <template #default="{row}"> | 84 | <template #default="{row}"> |
| 84 | {{formatDateTime(row.createTime)}} | 85 | {{formatDateTime(row.createTime)}} |
| 85 | </template> | 86 | </template> |
| 86 | - </vxe-column> | ||
| 87 | - </vxe-table> | 87 | + </VxeColumn> |
| 88 | + </VxeTable> | ||
| 88 | </ContentWrap> | 89 | </ContentWrap> |
| 89 | </template> | 90 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -13,7 +13,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | @@ -13,7 +13,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | ||
| 13 | 13 | ||
| 14 | import { computed, ref, reactive } from 'vue'; | 14 | import { computed, ref, reactive } from 'vue'; |
| 15 | import { $t } from '#/locales'; | 15 | import { $t } from '#/locales'; |
| 16 | -import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | 16 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; |
| 17 | 17 | ||
| 18 | const emit = defineEmits(['success']); | 18 | const emit = defineEmits(['success']); |
| 19 | 19 | ||
| @@ -71,7 +71,11 @@ const [Modal, modalApi] = useVbenModal({ | @@ -71,7 +71,11 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 71 | async onConfirm() { | 71 | async onConfirm() { |
| 72 | await formRef.value?.validate(); | 72 | await formRef.value?.validate(); |
| 73 | // 校验子表单 | 73 | // 校验子表单 |
| 74 | - try { | 74 | + if (!studentContactFormRef.value?.validate()) { |
| 75 | + subTabsName.value = 'studentContact'; | ||
| 76 | + return; | ||
| 77 | + } | ||
| 78 | + try { | ||
| 75 | await studentTeacherFormRef.value?.validate() | 79 | await studentTeacherFormRef.value?.validate() |
| 76 | } catch (e) { | 80 | } catch (e) { |
| 77 | subTabsName.value = 'studentTeacher' | 81 | subTabsName.value = 'studentTeacher' |
| @@ -118,65 +122,65 @@ const [Modal, modalApi] = useVbenModal({ | @@ -118,65 +122,65 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 118 | 122 | ||
| 119 | <template> | 123 | <template> |
| 120 | <Modal :title="getTitle"> | 124 | <Modal :title="getTitle"> |
| 121 | - <el-form | 125 | + <ElForm |
| 122 | ref="formRef" | 126 | ref="formRef" |
| 123 | :model="formData" | 127 | :model="formData" |
| 124 | :rules="rules" | 128 | :rules="rules" |
| 125 | label-width="120px" | 129 | label-width="120px" |
| 126 | label-position="right" | 130 | label-position="right" |
| 127 | > | 131 | > |
| 128 | - <el-form-item label="名字" prop="name"> | ||
| 129 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 130 | - </el-form-item> | ||
| 131 | - <el-form-item label="简介" prop="description"> | ||
| 132 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 133 | - </el-form-item> | ||
| 134 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 135 | - <el-date-picker | 132 | + <ElFormItem label="名字" prop="name"> |
| 133 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 134 | + </ElFormItem> | ||
| 135 | + <ElFormItem label="简介" prop="description"> | ||
| 136 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 137 | + </ElFormItem> | ||
| 138 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 139 | + <ElDatePicker | ||
| 136 | v-model="formData.birthday" | 140 | v-model="formData.birthday" |
| 137 | value-format="x" | 141 | value-format="x" |
| 138 | placeholder="选择出生日期" | 142 | placeholder="选择出生日期" |
| 139 | /> | 143 | /> |
| 140 | - </el-form-item> | ||
| 141 | - <el-form-item label="性别" prop="sex"> | ||
| 142 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 143 | - <el-option | 144 | + </ElFormItem> |
| 145 | + <ElFormItem label="性别" prop="sex"> | ||
| 146 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 147 | + <ElOption | ||
| 144 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 148 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 145 | :key="dict.value" | 149 | :key="dict.value" |
| 146 | :value="dict.value" | 150 | :value="dict.value" |
| 147 | :label="dict.label" | 151 | :label="dict.label" |
| 148 | /> | 152 | /> |
| 149 | - </el-select> | ||
| 150 | - </el-form-item> | ||
| 151 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 152 | - <el-radio-group v-model="formData.enabled"> | ||
| 153 | - <el-radio | 153 | + </ElSelect> |
| 154 | + </ElFormItem> | ||
| 155 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 156 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 157 | + <ElRadio | ||
| 154 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 158 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 155 | :key="dict.value" | 159 | :key="dict.value" |
| 156 | - :label="dict.value" | 160 | + :value="dict.value" |
| 157 | > | 161 | > |
| 158 | {{ dict.label }} | 162 | {{ dict.label }} |
| 159 | - </el-radio> | ||
| 160 | - </el-radio-group> | ||
| 161 | - </el-form-item> | ||
| 162 | - <el-form-item label="头像" prop="avatar"> | 163 | + </ElRadio> |
| 164 | + </ElRadioGroup> | ||
| 165 | + </ElFormItem> | ||
| 166 | + <ElFormItem label="头像" prop="avatar"> | ||
| 163 | <ImageUpload v-model="formData.avatar" /> | 167 | <ImageUpload v-model="formData.avatar" /> |
| 164 | - </el-form-item> | ||
| 165 | - <el-form-item label="附件" prop="video"> | 168 | + </ElFormItem> |
| 169 | + <ElFormItem label="附件" prop="video"> | ||
| 166 | <FileUpload v-model="formData.video" /> | 170 | <FileUpload v-model="formData.video" /> |
| 167 | - </el-form-item> | ||
| 168 | - <el-form-item label="备注" prop="memo"> | 171 | + </ElFormItem> |
| 172 | + <ElFormItem label="备注" prop="memo"> | ||
| 169 | <RichTextarea v-model="formData.memo" height="500px" /> | 173 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 170 | - </el-form-item> | ||
| 171 | - </el-form> | 174 | + </ElFormItem> |
| 175 | + </ElForm> | ||
| 172 | <!-- 子表的表单 --> | 176 | <!-- 子表的表单 --> |
| 173 | - <el-tabs v-model="subTabsName"> | ||
| 174 | - <el-tab-pane name="studentContact" label="学生联系人"> | 177 | + <ElTabs v-model="subTabsName"> |
| 178 | + <ElTabPane name="studentContact" label="学生联系人"> | ||
| 175 | <StudentContactForm ref="studentContactFormRef" :student-id="formData?.id" /> | 179 | <StudentContactForm ref="studentContactFormRef" :student-id="formData?.id" /> |
| 176 | - </el-tab-pane> | ||
| 177 | - <el-tab-pane name="studentTeacher" label="学生班主任"> | 180 | + </ElTabPane> |
| 181 | + <ElTabPane name="studentTeacher" label="学生班主任"> | ||
| 178 | <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData?.id" /> | 182 | <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData?.id" /> |
| 179 | - </el-tab-pane> | ||
| 180 | - </el-tabs> | 183 | + </ElTabPane> |
| 184 | + </ElTabs> | ||
| 181 | </Modal> | 185 | </Modal> |
| 182 | </template> | 186 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 17 | 17 | ||
| 18 | import { $t } from '#/locales'; | 18 | import { $t } from '#/locales'; |
| 19 | import { isEmpty } from '@vben/utils'; | 19 | import { isEmpty } from '@vben/utils'; |
| 20 | -import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | 20 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | const loading = ref(true) // 列表的加载中 | 23 | const loading = ref(true) // 列表的加载中 |
| @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | ||
| 27 | const queryParams = reactive({ | 27 | const queryParams = reactive({ |
| 28 | pageNo: 1, | 28 | pageNo: 1, |
| 29 | pageSize: 10, | 29 | pageSize: 10, |
| 30 | - name: undefined, | ||
| 31 | - birthday: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - sex: undefined, | ||
| 34 | - enabled: undefined, | ||
| 35 | - createTime: undefined, | 30 | + name: undefined, |
| 31 | + birthday: undefined, | ||
| 32 | + sex: undefined, | ||
| 33 | + enabled: undefined, | ||
| 34 | + createTime: undefined, | ||
| 36 | }) | 35 | }) |
| 37 | const queryFormRef = ref() // 搜索的表单 | 36 | const queryFormRef = ref() // 搜索的表单 |
| 38 | const exportLoading = ref(false) // 导出的加载中 | 37 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -126,7 +125,14 @@ function handleRowCheckboxChange({ | @@ -126,7 +125,14 @@ function handleRowCheckboxChange({ | ||
| 126 | async function handleExport() { | 125 | async function handleExport() { |
| 127 | try { | 126 | try { |
| 128 | exportLoading.value = true; | 127 | exportLoading.value = true; |
| 129 | - const data = await exportStudent(queryParams); | 128 | + const params = cloneDeep(queryParams) as any; |
| 129 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 130 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 131 | + } | ||
| 132 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 133 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 134 | + } | ||
| 135 | + const data = await exportStudent(params); | ||
| 130 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 136 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 131 | }finally { | 137 | }finally { |
| 132 | exportLoading.value = false; | 138 | exportLoading.value = false; |
| @@ -148,61 +154,61 @@ onMounted(() => { | @@ -148,61 +154,61 @@ onMounted(() => { | ||
| 148 | 154 | ||
| 149 | <ContentWrap v-if="!hiddenSearchBar"> | 155 | <ContentWrap v-if="!hiddenSearchBar"> |
| 150 | <!-- 搜索工作栏 --> | 156 | <!-- 搜索工作栏 --> |
| 151 | - <el-form | 157 | + <ElForm |
| 152 | :model="queryParams" | 158 | :model="queryParams" |
| 153 | ref="queryFormRef" | 159 | ref="queryFormRef" |
| 154 | inline | 160 | inline |
| 155 | > | 161 | > |
| 156 | - <el-form-item label="名字"> | ||
| 157 | - <el-input | 162 | + <ElFormItem label="名字"> |
| 163 | + <ElInput | ||
| 158 | v-model="queryParams.name" | 164 | v-model="queryParams.name" |
| 159 | placeholder="请输入名字" | 165 | placeholder="请输入名字" |
| 160 | clearable | 166 | clearable |
| 161 | @keyup.enter="handleQuery" | 167 | @keyup.enter="handleQuery" |
| 162 | class="!w-[240px]" | 168 | class="!w-[240px]" |
| 163 | /> | 169 | /> |
| 164 | - </el-form-item> | ||
| 165 | - <el-form-item label="出生日期"> | ||
| 166 | - <el-date-picker | 170 | + </ElFormItem> |
| 171 | + <ElFormItem label="出生日期"> | ||
| 172 | + <ElDatePicker | ||
| 167 | v-model="queryParams.birthday" | 173 | v-model="queryParams.birthday" |
| 168 | value-format="YYYY-MM-DD" | 174 | value-format="YYYY-MM-DD" |
| 169 | placeholder="选择出生日期" | 175 | placeholder="选择出生日期" |
| 170 | clearable | 176 | clearable |
| 171 | class="!w-[240px]" | 177 | class="!w-[240px]" |
| 172 | /> | 178 | /> |
| 173 | - </el-form-item> | ||
| 174 | - <el-form-item label="性别"> | ||
| 175 | - <el-select | 179 | + </ElFormItem> |
| 180 | + <ElFormItem label="性别"> | ||
| 181 | + <ElSelect | ||
| 176 | v-model="queryParams.sex" | 182 | v-model="queryParams.sex" |
| 177 | placeholder="请选择性别" | 183 | placeholder="请选择性别" |
| 178 | clearable | 184 | clearable |
| 179 | class="!w-[240px]" | 185 | class="!w-[240px]" |
| 180 | > | 186 | > |
| 181 | - <el-option | 187 | + <ElOption |
| 182 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 188 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 183 | :key="dict.value" | 189 | :key="dict.value" |
| 184 | :value="dict.value" | 190 | :value="dict.value" |
| 185 | :label="dict.label" | 191 | :label="dict.label" |
| 186 | /> | 192 | /> |
| 187 | - </el-select> | ||
| 188 | - </el-form-item> | ||
| 189 | - <el-form-item label="是否有效"> | ||
| 190 | - <el-select | 193 | + </ElSelect> |
| 194 | + </ElFormItem> | ||
| 195 | + <ElFormItem label="是否有效"> | ||
| 196 | + <ElSelect | ||
| 191 | v-model="queryParams.enabled" | 197 | v-model="queryParams.enabled" |
| 192 | placeholder="请选择是否有效" | 198 | placeholder="请选择是否有效" |
| 193 | clearable | 199 | clearable |
| 194 | class="!w-[240px]" | 200 | class="!w-[240px]" |
| 195 | > | 201 | > |
| 196 | - <el-option | 202 | + <ElOption |
| 197 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 203 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 198 | :key="dict.value" | 204 | :key="dict.value" |
| 199 | :value="dict.value" | 205 | :value="dict.value" |
| 200 | :label="dict.label" | 206 | :label="dict.label" |
| 201 | /> | 207 | /> |
| 202 | - </el-select> | ||
| 203 | - </el-form-item> | ||
| 204 | - <el-form-item label="创建时间"> | ||
| 205 | - <el-date-picker | 208 | + </ElSelect> |
| 209 | + </ElFormItem> | ||
| 210 | + <ElFormItem label="创建时间"> | ||
| 211 | + <ElDatePicker | ||
| 206 | v-model="queryParams.createTime" | 212 | v-model="queryParams.createTime" |
| 207 | type="daterange" | 213 | type="daterange" |
| 208 | value-format="YYYY-MM-DD" | 214 | value-format="YYYY-MM-DD" |
| @@ -211,24 +217,24 @@ onMounted(() => { | @@ -211,24 +217,24 @@ onMounted(() => { | ||
| 211 | end-placeholder="结束日期" | 217 | end-placeholder="结束日期" |
| 212 | class="!w-[240px]" | 218 | class="!w-[240px]" |
| 213 | /> | 219 | /> |
| 214 | - </el-form-item> | ||
| 215 | - <el-form-item> | ||
| 216 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 217 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 220 | + </ElFormItem> |
| 221 | + <ElFormItem> | ||
| 222 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 223 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 218 | 搜索 | 224 | 搜索 |
| 219 | - </el-button> | ||
| 220 | - </el-form-item> | ||
| 221 | - </el-form> | 225 | + </ElButton> |
| 226 | + </ElFormItem> | ||
| 227 | + </ElForm> | ||
| 222 | </ContentWrap> | 228 | </ContentWrap> |
| 223 | 229 | ||
| 224 | <!-- 列表 --> | 230 | <!-- 列表 --> |
| 225 | <ContentWrap title="学生"> | 231 | <ContentWrap title="学生"> |
| 226 | <template #extra> | 232 | <template #extra> |
| 227 | - <TableToolbar | 233 | + <VbenVxeTableToolbar |
| 228 | ref="tableToolbarRef" | 234 | ref="tableToolbarRef" |
| 229 | v-model:hidden-search="hiddenSearchBar" | 235 | v-model:hidden-search="hiddenSearchBar" |
| 230 | > | 236 | > |
| 231 | - <el-button | 237 | + <ElButton |
| 232 | class="ml-2" | 238 | class="ml-2" |
| 233 | :icon="h(Plus)" | 239 | :icon="h(Plus)" |
| 234 | type="primary" | 240 | type="primary" |
| @@ -236,8 +242,8 @@ onMounted(() => { | @@ -236,8 +242,8 @@ onMounted(() => { | ||
| 236 | v-access:code="['infra:student:create']" | 242 | v-access:code="['infra:student:create']" |
| 237 | > | 243 | > |
| 238 | {{ $t('ui.actionTitle.create', ['学生']) }} | 244 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 239 | - </el-button> | ||
| 240 | - <el-button | 245 | + </ElButton> |
| 246 | + <ElButton | ||
| 241 | :icon="h(Download)" | 247 | :icon="h(Download)" |
| 242 | type="primary" | 248 | type="primary" |
| 243 | class="ml-2" | 249 | class="ml-2" |
| @@ -246,8 +252,8 @@ onMounted(() => { | @@ -246,8 +252,8 @@ onMounted(() => { | ||
| 246 | v-access:code="['infra:student:export']" | 252 | v-access:code="['infra:student:export']" |
| 247 | > | 253 | > |
| 248 | {{ $t('ui.actionTitle.export') }} | 254 | {{ $t('ui.actionTitle.export') }} |
| 249 | - </el-button> | ||
| 250 | - <el-button | 255 | + </ElButton> |
| 256 | + <ElButton | ||
| 251 | :icon="h(Trash2)" | 257 | :icon="h(Trash2)" |
| 252 | type="danger" | 258 | type="danger" |
| 253 | class="ml-2" | 259 | class="ml-2" |
| @@ -256,10 +262,10 @@ onMounted(() => { | @@ -256,10 +262,10 @@ onMounted(() => { | ||
| 256 | v-access:code="['infra:student:delete']" | 262 | v-access:code="['infra:student:delete']" |
| 257 | > | 263 | > |
| 258 | 批量删除 | 264 | 批量删除 |
| 259 | - </el-button> | ||
| 260 | - </TableToolbar> | 265 | + </ElButton> |
| 266 | + </VbenVxeTableToolbar> | ||
| 261 | </template> | 267 | </template> |
| 262 | - <vxe-table | 268 | + <VxeTable |
| 263 | ref="tableRef" | 269 | ref="tableRef" |
| 264 | :data="list" | 270 | :data="list" |
| 265 | show-overflow | 271 | show-overflow |
| @@ -267,36 +273,36 @@ onMounted(() => { | @@ -267,36 +273,36 @@ onMounted(() => { | ||
| 267 | @checkboxAll="handleRowCheckboxChange" | 273 | @checkboxAll="handleRowCheckboxChange" |
| 268 | @checkboxChange="handleRowCheckboxChange" | 274 | @checkboxChange="handleRowCheckboxChange" |
| 269 | > | 275 | > |
| 270 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 271 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 272 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 273 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 274 | - <vxe-column field="birthday" title="出生日期" align="center"> | 276 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 277 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 278 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 279 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 280 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 275 | <template #default="{row}"> | 281 | <template #default="{row}"> |
| 276 | {{formatDateTime(row.birthday)}} | 282 | {{formatDateTime(row.birthday)}} |
| 277 | </template> | 283 | </template> |
| 278 | - </vxe-column> | ||
| 279 | - <vxe-column field="sex" title="性别" align="center"> | 284 | + </VxeColumn> |
| 285 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 280 | <template #default="{row}"> | 286 | <template #default="{row}"> |
| 281 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 287 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 282 | </template> | 288 | </template> |
| 283 | - </vxe-column> | ||
| 284 | - <vxe-column field="enabled" title="是否有效" align="center"> | 289 | + </VxeColumn> |
| 290 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 285 | <template #default="{row}"> | 291 | <template #default="{row}"> |
| 286 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 292 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 287 | </template> | 293 | </template> |
| 288 | - </vxe-column> | ||
| 289 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 290 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 291 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 292 | - <vxe-column field="createTime" title="创建时间" align="center"> | 294 | + </VxeColumn> |
| 295 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 296 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 297 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 298 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 293 | <template #default="{row}"> | 299 | <template #default="{row}"> |
| 294 | {{formatDateTime(row.createTime)}} | 300 | {{formatDateTime(row.createTime)}} |
| 295 | </template> | 301 | </template> |
| 296 | - </vxe-column> | ||
| 297 | - <vxe-column field="operation" title="操作" align="center"> | 302 | + </VxeColumn> |
| 303 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 298 | <template #default="{row}"> | 304 | <template #default="{row}"> |
| 299 | - <el-button | 305 | + <ElButton |
| 300 | size="small" | 306 | size="small" |
| 301 | type="primary" | 307 | type="primary" |
| 302 | link | 308 | link |
| @@ -304,8 +310,8 @@ onMounted(() => { | @@ -304,8 +310,8 @@ onMounted(() => { | ||
| 304 | v-access:code="['infra:student:update']" | 310 | v-access:code="['infra:student:update']" |
| 305 | > | 311 | > |
| 306 | {{ $t('ui.actionTitle.edit') }} | 312 | {{ $t('ui.actionTitle.edit') }} |
| 307 | - </el-button> | ||
| 308 | - <el-button | 313 | + </ElButton> |
| 314 | + <ElButton | ||
| 309 | size="small" | 315 | size="small" |
| 310 | type="danger" | 316 | type="danger" |
| 311 | link | 317 | link |
| @@ -314,13 +320,13 @@ onMounted(() => { | @@ -314,13 +320,13 @@ onMounted(() => { | ||
| 314 | v-access:code="['infra:student:delete']" | 320 | v-access:code="['infra:student:delete']" |
| 315 | > | 321 | > |
| 316 | {{ $t('ui.actionTitle.delete') }} | 322 | {{ $t('ui.actionTitle.delete') }} |
| 317 | - </el-button> | 323 | + </ElButton> |
| 318 | </template> | 324 | </template> |
| 319 | - </vxe-column> | ||
| 320 | - </vxe-table> | 325 | + </VxeColumn> |
| 326 | + </VxeTable> | ||
| 321 | <!-- 分页 --> | 327 | <!-- 分页 --> |
| 322 | <div class="mt-2 flex justify-end"> | 328 | <div class="mt-2 flex justify-end"> |
| 323 | - <el-pagination | 329 | + <ElPagination |
| 324 | :total="total" | 330 | :total="total" |
| 325 | v-model:current-page="queryParams.pageNo" | 331 | v-model:current-page="queryParams.pageNo" |
| 326 | v-model:page-size="queryParams.pageSize" | 332 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/vue/student-contact-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { VxeTableInstance } from '#/adapter/vxe-table'; |
| 3 | +import type { StudentApi } from '#/api/infra/demo'; | ||
| 3 | 4 | ||
| 4 | -import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue'; | 5 | +import { ref, watch } from 'vue'; |
| 5 | 6 | ||
| 6 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 7 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 9 | +import { Plus } from '@vben/icons'; | ||
| 8 | 10 | ||
| 9 | -import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus'; | ||
| 10 | -import { $t } from '#/locales'; | 11 | +import { |
| 12 | + ElButton, | ||
| 13 | + ElDatePicker, | ||
| 14 | + ElInput, | ||
| 15 | + ElMessage, | ||
| 16 | + ElOption, | ||
| 17 | + ElRadio, | ||
| 18 | + ElRadioGroup, | ||
| 19 | + ElSelect, | ||
| 20 | +} from 'element-plus'; | ||
| 11 | 21 | ||
| 12 | - import type { VxeTableInstance } from '#/adapter/vxe-table'; | ||
| 13 | -import { Plus } from "@vben/icons"; | ||
| 14 | -import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 15 | -import { getStudentContactListByStudentId } from '#/api/infra/student'; | 22 | + import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; |
| 23 | +import { getStudentContactListByStudentId } from '#/api/infra/demo'; | ||
| 24 | +import { $t } from '#/locales'; | ||
| 16 | 25 | ||
| 17 | const props = defineProps<{ | 26 | const props = defineProps<{ |
| 18 | studentId?: number // 学生编号(主表的关联字段) | 27 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -30,24 +39,96 @@ async function onDelete(row: StudentApi.StudentContact) { | @@ -30,24 +39,96 @@ async function onDelete(row: StudentApi.StudentContact) { | ||
| 30 | await tableRef.value?.remove(row); | 39 | await tableRef.value?.remove(row); |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 34 | -defineExpose({ | ||
| 35 | - getData: (): StudentApi.StudentContact[] => { | ||
| 36 | - const data = list.value as StudentApi.StudentContact[]; | ||
| 37 | - const removeRecords = tableRef.value?.getRemoveRecords() as StudentApi.StudentContact[]; | ||
| 38 | - const insertRecords = tableRef.value?.getInsertRecords() as StudentApi.StudentContact[]; | ||
| 39 | - return [ | ||
| 40 | - ...data.filter( | ||
| 41 | - (row) => !removeRecords.some((removed) => removed.id === row.id), | ||
| 42 | - ), | ||
| 43 | - ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||
| 44 | - }, | ||
| 45 | -}); | 42 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 43 | +function getData(): StudentApi.StudentContact[] { | ||
| 44 | + const table = tableRef.value; | ||
| 45 | + if (!table) { | ||
| 46 | + return []; | ||
| 47 | + } | ||
| 48 | + const { fullData } = table.getTableData(); | ||
| 49 | + const inserted = new Set(table.getInsertRecords()); | ||
| 50 | + return fullData.map((row) => | ||
| 51 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 52 | + ); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/** 校验子表必填字段 */ | ||
| 56 | +function validate(): boolean { | ||
| 57 | + for (const [index, row] of getData().entries()) { | ||
| 58 | + if ( | ||
| 59 | + row.name === null || | ||
| 60 | + row.name === undefined || | ||
| 61 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 62 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 63 | + ) { | ||
| 64 | + ElMessage.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 65 | + return false; | ||
| 66 | + } | ||
| 67 | + if ( | ||
| 68 | + row.description === null || | ||
| 69 | + row.description === undefined || | ||
| 70 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 71 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 72 | + ) { | ||
| 73 | + ElMessage.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 74 | + return false; | ||
| 75 | + } | ||
| 76 | + if ( | ||
| 77 | + row.birthday === null || | ||
| 78 | + row.birthday === undefined || | ||
| 79 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 80 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 81 | + ) { | ||
| 82 | + ElMessage.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 83 | + return false; | ||
| 84 | + } | ||
| 85 | + if ( | ||
| 86 | + row.sex === null || | ||
| 87 | + row.sex === undefined || | ||
| 88 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 89 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 90 | + ) { | ||
| 91 | + ElMessage.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 92 | + return false; | ||
| 93 | + } | ||
| 94 | + if ( | ||
| 95 | + row.enabled === null || | ||
| 96 | + row.enabled === undefined || | ||
| 97 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 98 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 99 | + ) { | ||
| 100 | + ElMessage.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 101 | + return false; | ||
| 102 | + } | ||
| 103 | + if ( | ||
| 104 | + row.avatar === null || | ||
| 105 | + row.avatar === undefined || | ||
| 106 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 107 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 108 | + ) { | ||
| 109 | + ElMessage.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 110 | + return false; | ||
| 111 | + } | ||
| 112 | + if ( | ||
| 113 | + row.memo === null || | ||
| 114 | + row.memo === undefined || | ||
| 115 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 116 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 117 | + ) { | ||
| 118 | + ElMessage.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 119 | + return false; | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + return true; | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +defineExpose({ getData, validate }); | ||
| 46 | 126 | ||
| 47 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 127 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 48 | watch( | 128 | watch( |
| 49 | () => props.studentId, | 129 | () => props.studentId, |
| 50 | async (val) => { | 130 | async (val) => { |
| 131 | + list.value = []; | ||
| 51 | if (!val) { | 132 | if (!val) { |
| 52 | return; | 133 | return; |
| 53 | } | 134 | } |
| @@ -58,70 +139,70 @@ watch( | @@ -58,70 +139,70 @@ watch( | ||
| 58 | </script> | 139 | </script> |
| 59 | 140 | ||
| 60 | <template> | 141 | <template> |
| 61 | - <vxe-table ref="tableRef" :data="list" show-overflow class="mx-4"> | ||
| 62 | - <vxe-column field="name" title="名字" align="center"> | 142 | + <VxeTable ref="tableRef" :data="list" show-overflow class="mx-4"> |
| 143 | + <VxeColumn field="name" title="名字" align="center"> | ||
| 63 | <template #default="{row}"> | 144 | <template #default="{row}"> |
| 64 | - <el-input v-model="row.name" /> | 145 | + <ElInput v-model="row.name" /> |
| 65 | </template> | 146 | </template> |
| 66 | - </vxe-column> | ||
| 67 | - <vxe-column field="description" title="简介" align="center"> | 147 | + </VxeColumn> |
| 148 | + <VxeColumn field="description" title="简介" align="center"> | ||
| 68 | <template #default="{row}"> | 149 | <template #default="{row}"> |
| 69 | - <el-input v-model="row.description" type="textarea" /> | 150 | + <ElInput v-model="row.description" type="textarea" /> |
| 70 | </template> | 151 | </template> |
| 71 | - </vxe-column> | ||
| 72 | - <vxe-column field="birthday" title="出生日期" align="center"> | 152 | + </VxeColumn> |
| 153 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 73 | <template #default="{row}"> | 154 | <template #default="{row}"> |
| 74 | - <el-date-picker | 155 | + <ElDatePicker |
| 75 | v-model="row.birthday" | 156 | v-model="row.birthday" |
| 76 | type="datetime" | 157 | type="datetime" |
| 77 | value-format="x" | 158 | value-format="x" |
| 78 | format="YYYY-MM-DD HH:mm:ss" | 159 | format="YYYY-MM-DD HH:mm:ss" |
| 79 | /> | 160 | /> |
| 80 | </template> | 161 | </template> |
| 81 | - </vxe-column> | ||
| 82 | - <vxe-column field="sex" title="性别" align="center"> | 162 | + </VxeColumn> |
| 163 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 83 | <template #default="{row}"> | 164 | <template #default="{row}"> |
| 84 | - <el-select v-model="row.sex" placeholder="请选择性别"> | ||
| 85 | - <el-option | ||
| 86 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number')" | 165 | + <ElSelect v-model="row.sex" placeholder="请选择性别"> |
| 166 | + <ElOption | ||
| 167 | + v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | ||
| 87 | :key="dict.value" | 168 | :key="dict.value" |
| 88 | :value="dict.value" | 169 | :value="dict.value" |
| 89 | :label="dict.label" | 170 | :label="dict.label" |
| 90 | /> | 171 | /> |
| 91 | - </el-select> | 172 | + </ElSelect> |
| 92 | </template> | 173 | </template> |
| 93 | - </vxe-column> | ||
| 94 | - <vxe-column field="enabled" title="是否有效" align="center"> | 174 | + </VxeColumn> |
| 175 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 95 | <template #default="{row}"> | 176 | <template #default="{row}"> |
| 96 | - <el-radio-group v-model="row.enabled"> | ||
| 97 | - <el-radio | ||
| 98 | - v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'boolean')" | 177 | + <ElRadioGroup v-model="row.enabled"> |
| 178 | + <ElRadio | ||
| 179 | + v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | ||
| 99 | :key="dict.value" | 180 | :key="dict.value" |
| 100 | - :label="dict.value" | 181 | + :value="dict.value" |
| 101 | > | 182 | > |
| 102 | {{ dict.label }} | 183 | {{ dict.label }} |
| 103 | - </el-radio> | ||
| 104 | - </el-radio-group> | 184 | + </ElRadio> |
| 185 | + </ElRadioGroup> | ||
| 105 | </template> | 186 | </template> |
| 106 | - </vxe-column> | ||
| 107 | - <vxe-column field="avatar" title="头像" align="center"> | 187 | + </VxeColumn> |
| 188 | + <VxeColumn field="avatar" title="头像" align="center"> | ||
| 108 | <template #default="{row}"> | 189 | <template #default="{row}"> |
| 109 | <ImageUpload v-model="row.avatar" /> | 190 | <ImageUpload v-model="row.avatar" /> |
| 110 | </template> | 191 | </template> |
| 111 | - </vxe-column> | ||
| 112 | - <vxe-column field="video" title="附件" align="center"> | 192 | + </VxeColumn> |
| 193 | + <VxeColumn field="video" title="附件" align="center"> | ||
| 113 | <template #default="{row}"> | 194 | <template #default="{row}"> |
| 114 | <FileUpload v-model="row.video" /> | 195 | <FileUpload v-model="row.video" /> |
| 115 | </template> | 196 | </template> |
| 116 | - </vxe-column> | ||
| 117 | - <vxe-column field="memo" title="备注" align="center"> | 197 | + </VxeColumn> |
| 198 | + <VxeColumn field="memo" title="备注" align="center"> | ||
| 118 | <template #default="{row}"> | 199 | <template #default="{row}"> |
| 119 | - <el-input v-model="row.memo" type="textarea" /> | 200 | + <ElInput v-model="row.memo" type="textarea" /> |
| 120 | </template> | 201 | </template> |
| 121 | - </vxe-column> | ||
| 122 | - <vxe-column field="operation" title="操作" align="center"> | 202 | + </VxeColumn> |
| 203 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 123 | <template #default="{row}"> | 204 | <template #default="{row}"> |
| 124 | - <el-button | 205 | + <ElButton |
| 125 | size="small" | 206 | size="small" |
| 126 | type="danger" | 207 | type="danger" |
| 127 | link | 208 | link |
| @@ -129,13 +210,13 @@ watch( | @@ -129,13 +210,13 @@ watch( | ||
| 129 | v-access:code="['infra:student:delete']" | 210 | v-access:code="['infra:student:delete']" |
| 130 | > | 211 | > |
| 131 | {{ $t('ui.actionTitle.delete') }} | 212 | {{ $t('ui.actionTitle.delete') }} |
| 132 | - </el-button> | 213 | + </ElButton> |
| 133 | </template> | 214 | </template> |
| 134 | - </vxe-column> | ||
| 135 | - </vxe-table> | 215 | + </VxeColumn> |
| 216 | + </VxeTable> | ||
| 136 | <div class="flex justify-center mt-4"> | 217 | <div class="flex justify-center mt-4"> |
| 137 | - <el-button :icon="h(Plus)" type="primary" plain @click="handleAdd" v-access:code="['infra:student:create']"> | 218 | + <ElButton :icon="Plus" type="primary" plain @click="handleAdd" v-access:code="['infra:student:create']"> |
| 138 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} | 219 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} |
| 139 | - </el-button> | 220 | + </ElButton> |
| 140 | </div> | 221 | </div> |
| 141 | </template> | 222 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/vue/student-teacher-form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { FormRules } from 'element-plus'; |
| 3 | +import type { StudentApi } from '#/api/infra/demo'; | ||
| 3 | 4 | ||
| 4 | -import { computed, ref, reactive, h, onMounted,watch,nextTick } from 'vue'; | 5 | +import { nextTick, reactive, ref, watch } from 'vue'; |
| 5 | 6 | ||
| 6 | import { DICT_TYPE } from '@vben/constants'; | 7 | import { DICT_TYPE } from '@vben/constants'; |
| 7 | import { getDictOptions } from '@vben/hooks'; | 8 | import { getDictOptions } from '@vben/hooks'; |
| 8 | 9 | ||
| 9 | -import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElButton, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker } from 'element-plus'; | ||
| 10 | -import { $t } from '#/locales'; | 10 | +import { |
| 11 | + ElForm, | ||
| 12 | + ElFormItem, | ||
| 13 | + ElDatePicker, | ||
| 14 | + ElInput, | ||
| 15 | + ElOption, | ||
| 16 | + ElRadio, | ||
| 17 | + ElRadioGroup, | ||
| 18 | + ElSelect, | ||
| 19 | +} from 'element-plus'; | ||
| 11 | 20 | ||
| 12 | -import type { FormRules } from 'element-plus'; | ||
| 13 | import { Tinymce as RichTextarea } from '#/components/tinymce'; | 21 | import { Tinymce as RichTextarea } from '#/components/tinymce'; |
| 14 | -import { getStudentTeacherByStudentId } from '#/api/infra/student'; | 22 | +import { getStudentTeacherByStudentId } from '#/api/infra/demo'; |
| 23 | +import { $t } from '#/locales'; | ||
| 15 | 24 | ||
| 16 | const props = defineProps<{ | 25 | const props = defineProps<{ |
| 17 | studentId?: number // 学生编号(主表的关联字段) | 26 | studentId?: number // 学生编号(主表的关联字段) |
| @@ -50,6 +59,18 @@ defineExpose({ | @@ -50,6 +59,18 @@ defineExpose({ | ||
| 50 | watch( | 59 | watch( |
| 51 | () => props.studentId, | 60 | () => props.studentId, |
| 52 | async (val) => { | 61 | async (val) => { |
| 62 | + formData.value = { | ||
| 63 | + id: undefined, | ||
| 64 | + studentId: undefined, | ||
| 65 | + name: undefined, | ||
| 66 | + description: undefined, | ||
| 67 | + birthday: undefined, | ||
| 68 | + sex: undefined, | ||
| 69 | + enabled: undefined, | ||
| 70 | + avatar: undefined, | ||
| 71 | + video: undefined, | ||
| 72 | + memo: undefined, | ||
| 73 | + }; | ||
| 53 | if (!val) { | 74 | if (!val) { |
| 54 | return; | 75 | return; |
| 55 | } | 76 | } |
| @@ -61,7 +82,7 @@ watch( | @@ -61,7 +82,7 @@ watch( | ||
| 61 | </script> | 82 | </script> |
| 62 | 83 | ||
| 63 | <template> | 84 | <template> |
| 64 | - <el-form | 85 | + <ElForm |
| 65 | ref="formRef" | 86 | ref="formRef" |
| 66 | class="mx-4" | 87 | class="mx-4" |
| 67 | :model="formData" | 88 | :model="formData" |
| @@ -69,48 +90,48 @@ watch( | @@ -69,48 +90,48 @@ watch( | ||
| 69 | label-width="120px" | 90 | label-width="120px" |
| 70 | label-position="right" | 91 | label-position="right" |
| 71 | > | 92 | > |
| 72 | - <el-form-item label="名字" prop="name"> | ||
| 73 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 74 | - </el-form-item> | ||
| 75 | - <el-form-item label="简介" prop="description"> | ||
| 76 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 77 | - </el-form-item> | ||
| 78 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 79 | - <el-date-picker | 93 | + <ElFormItem label="名字" prop="name"> |
| 94 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 95 | + </ElFormItem> | ||
| 96 | + <ElFormItem label="简介" prop="description"> | ||
| 97 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 98 | + </ElFormItem> | ||
| 99 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 100 | + <ElDatePicker | ||
| 80 | v-model="formData.birthday" | 101 | v-model="formData.birthday" |
| 81 | value-format="x" | 102 | value-format="x" |
| 82 | placeholder="选择出生日期" | 103 | placeholder="选择出生日期" |
| 83 | /> | 104 | /> |
| 84 | - </el-form-item> | ||
| 85 | - <el-form-item label="性别" prop="sex"> | ||
| 86 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 87 | - <el-option | 105 | + </ElFormItem> |
| 106 | + <ElFormItem label="性别" prop="sex"> | ||
| 107 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 108 | + <ElOption | ||
| 88 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 109 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 89 | :key="dict.value" | 110 | :key="dict.value" |
| 90 | :value="dict.value" | 111 | :value="dict.value" |
| 91 | :label="dict.label" | 112 | :label="dict.label" |
| 92 | /> | 113 | /> |
| 93 | - </el-select> | ||
| 94 | - </el-form-item> | ||
| 95 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 96 | - <el-radio-group v-model="formData.enabled"> | ||
| 97 | - <el-radio | 114 | + </ElSelect> |
| 115 | + </ElFormItem> | ||
| 116 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 117 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 118 | + <ElRadio | ||
| 98 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 119 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 99 | :key="dict.value" | 120 | :key="dict.value" |
| 100 | - :label="dict.value" | 121 | + :value="dict.value" |
| 101 | > | 122 | > |
| 102 | {{ dict.label }} | 123 | {{ dict.label }} |
| 103 | - </el-radio> | ||
| 104 | - </el-radio-group> | ||
| 105 | - </el-form-item> | ||
| 106 | - <el-form-item label="头像" prop="avatar"> | 124 | + </ElRadio> |
| 125 | + </ElRadioGroup> | ||
| 126 | + </ElFormItem> | ||
| 127 | + <ElFormItem label="头像" prop="avatar"> | ||
| 107 | <ImageUpload v-model="formData.avatar" /> | 128 | <ImageUpload v-model="formData.avatar" /> |
| 108 | - </el-form-item> | ||
| 109 | - <el-form-item label="附件" prop="video"> | 129 | + </ElFormItem> |
| 130 | + <ElFormItem label="附件" prop="video"> | ||
| 110 | <FileUpload v-model="formData.video" /> | 131 | <FileUpload v-model="formData.video" /> |
| 111 | - </el-form-item> | ||
| 112 | - <el-form-item label="备注" prop="memo"> | 132 | + </ElFormItem> |
| 133 | + <ElFormItem label="备注" prop="memo"> | ||
| 113 | <RichTextarea v-model="formData.memo" height="500px" /> | 134 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 114 | - </el-form-item> | ||
| 115 | - </el-form> | 135 | + </ElFormItem> |
| 136 | + </ElForm> | ||
| 116 | </template> | 137 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | ||
| 11 | 11 | ||
| 12 | import { computed, ref, reactive } from 'vue'; | 12 | import { computed, ref, reactive } from 'vue'; |
| 13 | import { $t } from '#/locales'; | 13 | import { $t } from '#/locales'; |
| 14 | -import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | 14 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; |
| 15 | 15 | ||
| 16 | const emit = defineEmits(['success']); | 16 | const emit = defineEmits(['success']); |
| 17 | 17 | ||
| @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 102 | 102 | ||
| 103 | <template> | 103 | <template> |
| 104 | <Modal :title="getTitle"> | 104 | <Modal :title="getTitle"> |
| 105 | - <el-form | 105 | + <ElForm |
| 106 | ref="formRef" | 106 | ref="formRef" |
| 107 | :model="formData" | 107 | :model="formData" |
| 108 | :rules="rules" | 108 | :rules="rules" |
| 109 | label-width="120px" | 109 | label-width="120px" |
| 110 | label-position="right" | 110 | label-position="right" |
| 111 | > | 111 | > |
| 112 | - <el-form-item label="名字" prop="name"> | ||
| 113 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | - </el-form-item> | ||
| 115 | - <el-form-item label="简介" prop="description"> | ||
| 116 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | - </el-form-item> | ||
| 118 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 119 | - <el-date-picker | 112 | + <ElFormItem label="名字" prop="name"> |
| 113 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | + </ElFormItem> | ||
| 115 | + <ElFormItem label="简介" prop="description"> | ||
| 116 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | + </ElFormItem> | ||
| 118 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 119 | + <ElDatePicker | ||
| 120 | v-model="formData.birthday" | 120 | v-model="formData.birthday" |
| 121 | value-format="x" | 121 | value-format="x" |
| 122 | placeholder="选择出生日期" | 122 | placeholder="选择出生日期" |
| 123 | /> | 123 | /> |
| 124 | - </el-form-item> | ||
| 125 | - <el-form-item label="性别" prop="sex"> | ||
| 126 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | - <el-option | 124 | + </ElFormItem> |
| 125 | + <ElFormItem label="性别" prop="sex"> | ||
| 126 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | + <ElOption | ||
| 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 129 | :key="dict.value" | 129 | :key="dict.value" |
| 130 | :value="dict.value" | 130 | :value="dict.value" |
| 131 | :label="dict.label" | 131 | :label="dict.label" |
| 132 | /> | 132 | /> |
| 133 | - </el-select> | ||
| 134 | - </el-form-item> | ||
| 135 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 136 | - <el-radio-group v-model="formData.enabled"> | ||
| 137 | - <el-radio | 133 | + </ElSelect> |
| 134 | + </ElFormItem> | ||
| 135 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 136 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 137 | + <ElRadio | ||
| 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 139 | :key="dict.value" | 139 | :key="dict.value" |
| 140 | - :label="dict.value" | 140 | + :value="dict.value" |
| 141 | > | 141 | > |
| 142 | {{ dict.label }} | 142 | {{ dict.label }} |
| 143 | - </el-radio> | ||
| 144 | - </el-radio-group> | ||
| 145 | - </el-form-item> | ||
| 146 | - <el-form-item label="头像" prop="avatar"> | 143 | + </ElRadio> |
| 144 | + </ElRadioGroup> | ||
| 145 | + </ElFormItem> | ||
| 146 | + <ElFormItem label="头像" prop="avatar"> | ||
| 147 | <ImageUpload v-model="formData.avatar" /> | 147 | <ImageUpload v-model="formData.avatar" /> |
| 148 | - </el-form-item> | ||
| 149 | - <el-form-item label="附件" prop="video"> | 148 | + </ElFormItem> |
| 149 | + <ElFormItem label="附件" prop="video"> | ||
| 150 | <FileUpload v-model="formData.video" /> | 150 | <FileUpload v-model="formData.video" /> |
| 151 | - </el-form-item> | ||
| 152 | - <el-form-item label="备注" prop="memo"> | 151 | + </ElFormItem> |
| 152 | + <ElFormItem label="备注" prop="memo"> | ||
| 153 | <RichTextarea v-model="formData.memo" height="500px" /> | 153 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 154 | - </el-form-item> | ||
| 155 | - </el-form> | 154 | + </ElFormItem> |
| 155 | + </ElForm> | ||
| 156 | </Modal> | 156 | </Modal> |
| 157 | </template> | 157 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 17 | 17 | ||
| 18 | import { $t } from '#/locales'; | 18 | import { $t } from '#/locales'; |
| 19 | import { isEmpty } from '@vben/utils'; | 19 | import { isEmpty } from '@vben/utils'; |
| 20 | -import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | 20 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | const loading = ref(true) // 列表的加载中 | 23 | const loading = ref(true) // 列表的加载中 |
| @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | @@ -27,12 +27,11 @@ const total = ref(0) // 列表的总页数 | ||
| 27 | const queryParams = reactive({ | 27 | const queryParams = reactive({ |
| 28 | pageNo: 1, | 28 | pageNo: 1, |
| 29 | pageSize: 10, | 29 | pageSize: 10, |
| 30 | - name: undefined, | ||
| 31 | - birthday: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - sex: undefined, | ||
| 34 | - enabled: undefined, | ||
| 35 | - createTime: undefined, | 30 | + name: undefined, |
| 31 | + birthday: undefined, | ||
| 32 | + sex: undefined, | ||
| 33 | + enabled: undefined, | ||
| 34 | + createTime: undefined, | ||
| 36 | }) | 35 | }) |
| 37 | const queryFormRef = ref() // 搜索的表单 | 36 | const queryFormRef = ref() // 搜索的表单 |
| 38 | const exportLoading = ref(false) // 导出的加载中 | 37 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -126,7 +125,14 @@ function handleRowCheckboxChange({ | @@ -126,7 +125,14 @@ function handleRowCheckboxChange({ | ||
| 126 | async function handleExport() { | 125 | async function handleExport() { |
| 127 | try { | 126 | try { |
| 128 | exportLoading.value = true; | 127 | exportLoading.value = true; |
| 129 | - const data = await exportStudent(queryParams); | 128 | + const params = cloneDeep(queryParams) as any; |
| 129 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 130 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 131 | + } | ||
| 132 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 133 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 134 | + } | ||
| 135 | + const data = await exportStudent(params); | ||
| 130 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 136 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 131 | }finally { | 137 | }finally { |
| 132 | exportLoading.value = false; | 138 | exportLoading.value = false; |
| @@ -148,61 +154,61 @@ onMounted(() => { | @@ -148,61 +154,61 @@ onMounted(() => { | ||
| 148 | 154 | ||
| 149 | <ContentWrap v-if="!hiddenSearchBar"> | 155 | <ContentWrap v-if="!hiddenSearchBar"> |
| 150 | <!-- 搜索工作栏 --> | 156 | <!-- 搜索工作栏 --> |
| 151 | - <el-form | 157 | + <ElForm |
| 152 | :model="queryParams" | 158 | :model="queryParams" |
| 153 | ref="queryFormRef" | 159 | ref="queryFormRef" |
| 154 | inline | 160 | inline |
| 155 | > | 161 | > |
| 156 | - <el-form-item label="名字"> | ||
| 157 | - <el-input | 162 | + <ElFormItem label="名字"> |
| 163 | + <ElInput | ||
| 158 | v-model="queryParams.name" | 164 | v-model="queryParams.name" |
| 159 | placeholder="请输入名字" | 165 | placeholder="请输入名字" |
| 160 | clearable | 166 | clearable |
| 161 | @keyup.enter="handleQuery" | 167 | @keyup.enter="handleQuery" |
| 162 | class="!w-[240px]" | 168 | class="!w-[240px]" |
| 163 | /> | 169 | /> |
| 164 | - </el-form-item> | ||
| 165 | - <el-form-item label="出生日期"> | ||
| 166 | - <el-date-picker | 170 | + </ElFormItem> |
| 171 | + <ElFormItem label="出生日期"> | ||
| 172 | + <ElDatePicker | ||
| 167 | v-model="queryParams.birthday" | 173 | v-model="queryParams.birthday" |
| 168 | value-format="YYYY-MM-DD" | 174 | value-format="YYYY-MM-DD" |
| 169 | placeholder="选择出生日期" | 175 | placeholder="选择出生日期" |
| 170 | clearable | 176 | clearable |
| 171 | class="!w-[240px]" | 177 | class="!w-[240px]" |
| 172 | /> | 178 | /> |
| 173 | - </el-form-item> | ||
| 174 | - <el-form-item label="性别"> | ||
| 175 | - <el-select | 179 | + </ElFormItem> |
| 180 | + <ElFormItem label="性别"> | ||
| 181 | + <ElSelect | ||
| 176 | v-model="queryParams.sex" | 182 | v-model="queryParams.sex" |
| 177 | placeholder="请选择性别" | 183 | placeholder="请选择性别" |
| 178 | clearable | 184 | clearable |
| 179 | class="!w-[240px]" | 185 | class="!w-[240px]" |
| 180 | > | 186 | > |
| 181 | - <el-option | 187 | + <ElOption |
| 182 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 188 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 183 | :key="dict.value" | 189 | :key="dict.value" |
| 184 | :value="dict.value" | 190 | :value="dict.value" |
| 185 | :label="dict.label" | 191 | :label="dict.label" |
| 186 | /> | 192 | /> |
| 187 | - </el-select> | ||
| 188 | - </el-form-item> | ||
| 189 | - <el-form-item label="是否有效"> | ||
| 190 | - <el-select | 193 | + </ElSelect> |
| 194 | + </ElFormItem> | ||
| 195 | + <ElFormItem label="是否有效"> | ||
| 196 | + <ElSelect | ||
| 191 | v-model="queryParams.enabled" | 197 | v-model="queryParams.enabled" |
| 192 | placeholder="请选择是否有效" | 198 | placeholder="请选择是否有效" |
| 193 | clearable | 199 | clearable |
| 194 | class="!w-[240px]" | 200 | class="!w-[240px]" |
| 195 | > | 201 | > |
| 196 | - <el-option | 202 | + <ElOption |
| 197 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 203 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 198 | :key="dict.value" | 204 | :key="dict.value" |
| 199 | :value="dict.value" | 205 | :value="dict.value" |
| 200 | :label="dict.label" | 206 | :label="dict.label" |
| 201 | /> | 207 | /> |
| 202 | - </el-select> | ||
| 203 | - </el-form-item> | ||
| 204 | - <el-form-item label="创建时间"> | ||
| 205 | - <el-date-picker | 208 | + </ElSelect> |
| 209 | + </ElFormItem> | ||
| 210 | + <ElFormItem label="创建时间"> | ||
| 211 | + <ElDatePicker | ||
| 206 | v-model="queryParams.createTime" | 212 | v-model="queryParams.createTime" |
| 207 | type="daterange" | 213 | type="daterange" |
| 208 | value-format="YYYY-MM-DD" | 214 | value-format="YYYY-MM-DD" |
| @@ -211,24 +217,24 @@ onMounted(() => { | @@ -211,24 +217,24 @@ onMounted(() => { | ||
| 211 | end-placeholder="结束日期" | 217 | end-placeholder="结束日期" |
| 212 | class="!w-[240px]" | 218 | class="!w-[240px]" |
| 213 | /> | 219 | /> |
| 214 | - </el-form-item> | ||
| 215 | - <el-form-item> | ||
| 216 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 217 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 220 | + </ElFormItem> |
| 221 | + <ElFormItem> | ||
| 222 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 223 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 218 | 搜索 | 224 | 搜索 |
| 219 | - </el-button> | ||
| 220 | - </el-form-item> | ||
| 221 | - </el-form> | 225 | + </ElButton> |
| 226 | + </ElFormItem> | ||
| 227 | + </ElForm> | ||
| 222 | </ContentWrap> | 228 | </ContentWrap> |
| 223 | 229 | ||
| 224 | <!-- 列表 --> | 230 | <!-- 列表 --> |
| 225 | <ContentWrap title="学生"> | 231 | <ContentWrap title="学生"> |
| 226 | <template #extra> | 232 | <template #extra> |
| 227 | - <TableToolbar | 233 | + <VbenVxeTableToolbar |
| 228 | ref="tableToolbarRef" | 234 | ref="tableToolbarRef" |
| 229 | v-model:hidden-search="hiddenSearchBar" | 235 | v-model:hidden-search="hiddenSearchBar" |
| 230 | > | 236 | > |
| 231 | - <el-button | 237 | + <ElButton |
| 232 | class="ml-2" | 238 | class="ml-2" |
| 233 | :icon="h(Plus)" | 239 | :icon="h(Plus)" |
| 234 | type="primary" | 240 | type="primary" |
| @@ -236,8 +242,8 @@ onMounted(() => { | @@ -236,8 +242,8 @@ onMounted(() => { | ||
| 236 | v-access:code="['infra:student:create']" | 242 | v-access:code="['infra:student:create']" |
| 237 | > | 243 | > |
| 238 | {{ $t('ui.actionTitle.create', ['学生']) }} | 244 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 239 | - </el-button> | ||
| 240 | - <el-button | 245 | + </ElButton> |
| 246 | + <ElButton | ||
| 241 | :icon="h(Download)" | 247 | :icon="h(Download)" |
| 242 | type="primary" | 248 | type="primary" |
| 243 | class="ml-2" | 249 | class="ml-2" |
| @@ -246,8 +252,8 @@ onMounted(() => { | @@ -246,8 +252,8 @@ onMounted(() => { | ||
| 246 | v-access:code="['infra:student:export']" | 252 | v-access:code="['infra:student:export']" |
| 247 | > | 253 | > |
| 248 | {{ $t('ui.actionTitle.export') }} | 254 | {{ $t('ui.actionTitle.export') }} |
| 249 | - </el-button> | ||
| 250 | - <el-button | 255 | + </ElButton> |
| 256 | + <ElButton | ||
| 251 | :icon="h(Trash2)" | 257 | :icon="h(Trash2)" |
| 252 | type="danger" | 258 | type="danger" |
| 253 | class="ml-2" | 259 | class="ml-2" |
| @@ -256,10 +262,10 @@ onMounted(() => { | @@ -256,10 +262,10 @@ onMounted(() => { | ||
| 256 | v-access:code="['infra:student:delete']" | 262 | v-access:code="['infra:student:delete']" |
| 257 | > | 263 | > |
| 258 | 批量删除 | 264 | 批量删除 |
| 259 | - </el-button> | ||
| 260 | - </TableToolbar> | 265 | + </ElButton> |
| 266 | + </VbenVxeTableToolbar> | ||
| 261 | </template> | 267 | </template> |
| 262 | - <vxe-table | 268 | + <VxeTable |
| 263 | ref="tableRef" | 269 | ref="tableRef" |
| 264 | :data="list" | 270 | :data="list" |
| 265 | show-overflow | 271 | show-overflow |
| @@ -267,36 +273,36 @@ onMounted(() => { | @@ -267,36 +273,36 @@ onMounted(() => { | ||
| 267 | @checkboxAll="handleRowCheckboxChange" | 273 | @checkboxAll="handleRowCheckboxChange" |
| 268 | @checkboxChange="handleRowCheckboxChange" | 274 | @checkboxChange="handleRowCheckboxChange" |
| 269 | > | 275 | > |
| 270 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 271 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 272 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 273 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 274 | - <vxe-column field="birthday" title="出生日期" align="center"> | 276 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 277 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 278 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 279 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 280 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 275 | <template #default="{row}"> | 281 | <template #default="{row}"> |
| 276 | {{formatDateTime(row.birthday)}} | 282 | {{formatDateTime(row.birthday)}} |
| 277 | </template> | 283 | </template> |
| 278 | - </vxe-column> | ||
| 279 | - <vxe-column field="sex" title="性别" align="center"> | 284 | + </VxeColumn> |
| 285 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 280 | <template #default="{row}"> | 286 | <template #default="{row}"> |
| 281 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 287 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 282 | </template> | 288 | </template> |
| 283 | - </vxe-column> | ||
| 284 | - <vxe-column field="enabled" title="是否有效" align="center"> | 289 | + </VxeColumn> |
| 290 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 285 | <template #default="{row}"> | 291 | <template #default="{row}"> |
| 286 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 292 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 287 | </template> | 293 | </template> |
| 288 | - </vxe-column> | ||
| 289 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 290 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 291 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 292 | - <vxe-column field="createTime" title="创建时间" align="center"> | 294 | + </VxeColumn> |
| 295 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 296 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 297 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 298 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 293 | <template #default="{row}"> | 299 | <template #default="{row}"> |
| 294 | {{formatDateTime(row.createTime)}} | 300 | {{formatDateTime(row.createTime)}} |
| 295 | </template> | 301 | </template> |
| 296 | - </vxe-column> | ||
| 297 | - <vxe-column field="operation" title="操作" align="center"> | 302 | + </VxeColumn> |
| 303 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 298 | <template #default="{row}"> | 304 | <template #default="{row}"> |
| 299 | - <el-button | 305 | + <ElButton |
| 300 | size="small" | 306 | size="small" |
| 301 | type="primary" | 307 | type="primary" |
| 302 | link | 308 | link |
| @@ -304,8 +310,8 @@ onMounted(() => { | @@ -304,8 +310,8 @@ onMounted(() => { | ||
| 304 | v-access:code="['infra:student:update']" | 310 | v-access:code="['infra:student:update']" |
| 305 | > | 311 | > |
| 306 | {{ $t('ui.actionTitle.edit') }} | 312 | {{ $t('ui.actionTitle.edit') }} |
| 307 | - </el-button> | ||
| 308 | - <el-button | 313 | + </ElButton> |
| 314 | + <ElButton | ||
| 309 | size="small" | 315 | size="small" |
| 310 | type="danger" | 316 | type="danger" |
| 311 | link | 317 | link |
| @@ -314,13 +320,13 @@ onMounted(() => { | @@ -314,13 +320,13 @@ onMounted(() => { | ||
| 314 | v-access:code="['infra:student:delete']" | 320 | v-access:code="['infra:student:delete']" |
| 315 | > | 321 | > |
| 316 | {{ $t('ui.actionTitle.delete') }} | 322 | {{ $t('ui.actionTitle.delete') }} |
| 317 | - </el-button> | 323 | + </ElButton> |
| 318 | </template> | 324 | </template> |
| 319 | - </vxe-column> | ||
| 320 | - </vxe-table> | 325 | + </VxeColumn> |
| 326 | + </VxeTable> | ||
| 321 | <!-- 分页 --> | 327 | <!-- 分页 --> |
| 322 | <div class="mt-2 flex justify-end"> | 328 | <div class="mt-2 flex justify-end"> |
| 323 | - <el-pagination | 329 | + <ElPagination |
| 324 | :total="total" | 330 | :total="total" |
| 325 | v-model:current-page="queryParams.pageNo" | 331 | v-model:current-page="queryParams.pageNo" |
| 326 | v-model:page-size="queryParams.pageSize" | 332 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | @@ -11,7 +11,7 @@ import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, El | ||
| 11 | 11 | ||
| 12 | import { computed, ref, reactive } from 'vue'; | 12 | import { computed, ref, reactive } from 'vue'; |
| 13 | import { $t } from '#/locales'; | 13 | import { $t } from '#/locales'; |
| 14 | -import { getStudent, createStudent, updateStudent } from '#/api/infra/student'; | 14 | +import { getStudent, createStudent, updateStudent } from '#/api/infra/demo'; |
| 15 | 15 | ||
| 16 | const emit = defineEmits(['success']); | 16 | const emit = defineEmits(['success']); |
| 17 | 17 | ||
| @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | @@ -102,56 +102,56 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 102 | 102 | ||
| 103 | <template> | 103 | <template> |
| 104 | <Modal :title="getTitle"> | 104 | <Modal :title="getTitle"> |
| 105 | - <el-form | 105 | + <ElForm |
| 106 | ref="formRef" | 106 | ref="formRef" |
| 107 | :model="formData" | 107 | :model="formData" |
| 108 | :rules="rules" | 108 | :rules="rules" |
| 109 | label-width="120px" | 109 | label-width="120px" |
| 110 | label-position="right" | 110 | label-position="right" |
| 111 | > | 111 | > |
| 112 | - <el-form-item label="名字" prop="name"> | ||
| 113 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | - </el-form-item> | ||
| 115 | - <el-form-item label="简介" prop="description"> | ||
| 116 | - <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | - </el-form-item> | ||
| 118 | - <el-form-item label="出生日期" prop="birthday"> | ||
| 119 | - <el-date-picker | 112 | + <ElFormItem label="名字" prop="name"> |
| 113 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 114 | + </ElFormItem> | ||
| 115 | + <ElFormItem label="简介" prop="description"> | ||
| 116 | + <ElInput v-model="formData.description" type="textarea" placeholder="请输入简介" /> | ||
| 117 | + </ElFormItem> | ||
| 118 | + <ElFormItem label="出生日期" prop="birthday"> | ||
| 119 | + <ElDatePicker | ||
| 120 | v-model="formData.birthday" | 120 | v-model="formData.birthday" |
| 121 | value-format="x" | 121 | value-format="x" |
| 122 | placeholder="选择出生日期" | 122 | placeholder="选择出生日期" |
| 123 | /> | 123 | /> |
| 124 | - </el-form-item> | ||
| 125 | - <el-form-item label="性别" prop="sex"> | ||
| 126 | - <el-select v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | - <el-option | 124 | + </ElFormItem> |
| 125 | + <ElFormItem label="性别" prop="sex"> | ||
| 126 | + <ElSelect v-model="formData.sex" placeholder="请选择性别"> | ||
| 127 | + <ElOption | ||
| 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 128 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 129 | :key="dict.value" | 129 | :key="dict.value" |
| 130 | :value="dict.value" | 130 | :value="dict.value" |
| 131 | :label="dict.label" | 131 | :label="dict.label" |
| 132 | /> | 132 | /> |
| 133 | - </el-select> | ||
| 134 | - </el-form-item> | ||
| 135 | - <el-form-item label="是否有效" prop="enabled"> | ||
| 136 | - <el-radio-group v-model="formData.enabled"> | ||
| 137 | - <el-radio | 133 | + </ElSelect> |
| 134 | + </ElFormItem> | ||
| 135 | + <ElFormItem label="是否有效" prop="enabled"> | ||
| 136 | + <ElRadioGroup v-model="formData.enabled"> | ||
| 137 | + <ElRadio | ||
| 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 138 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 139 | :key="dict.value" | 139 | :key="dict.value" |
| 140 | - :label="dict.value" | 140 | + :value="dict.value" |
| 141 | > | 141 | > |
| 142 | {{ dict.label }} | 142 | {{ dict.label }} |
| 143 | - </el-radio> | ||
| 144 | - </el-radio-group> | ||
| 145 | - </el-form-item> | ||
| 146 | - <el-form-item label="头像" prop="avatar"> | 143 | + </ElRadio> |
| 144 | + </ElRadioGroup> | ||
| 145 | + </ElFormItem> | ||
| 146 | + <ElFormItem label="头像" prop="avatar"> | ||
| 147 | <ImageUpload v-model="formData.avatar" /> | 147 | <ImageUpload v-model="formData.avatar" /> |
| 148 | - </el-form-item> | ||
| 149 | - <el-form-item label="附件" prop="video"> | 148 | + </ElFormItem> |
| 149 | + <ElFormItem label="附件" prop="video"> | ||
| 150 | <FileUpload v-model="formData.video" /> | 150 | <FileUpload v-model="formData.video" /> |
| 151 | - </el-form-item> | ||
| 152 | - <el-form-item label="备注" prop="memo"> | 151 | + </ElFormItem> |
| 152 | + <ElFormItem label="备注" prop="memo"> | ||
| 153 | <RichTextarea v-model="formData.memo" height="500px" /> | 153 | <RichTextarea v-model="formData.memo" height="500px" /> |
| 154 | - </el-form-item> | ||
| 155 | - </el-form> | 154 | + </ElFormItem> |
| 155 | + </ElForm> | ||
| 156 | </Modal> | 156 | </Modal> |
| 157 | </template> | 157 | </template> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/import-form
| @@ -47,6 +47,16 @@ function handleChange(file: any) { | @@ -47,6 +47,16 @@ function handleChange(file: any) { | ||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | +/** 移除文件 */ | ||
| 51 | +function handleRemove() { | ||
| 52 | + fileRef.value = null; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/** 超出文件数量 */ | ||
| 56 | +function handleExceed() { | ||
| 57 | + ElMessage.warning('只能选择一个文件,请先移除已选文件'); | ||
| 58 | +} | ||
| 59 | + | ||
| 50 | /** 下载导入模板 */ | 60 | /** 下载导入模板 */ |
| 51 | async function handleDownload() { | 61 | async function handleDownload() { |
| 52 | const data = await importStudentTemplate(); | 62 | const data = await importStudentTemplate(); |
| @@ -61,6 +71,8 @@ async function handleDownload() { | @@ -61,6 +71,8 @@ async function handleDownload() { | ||
| 61 | :limit="1" | 71 | :limit="1" |
| 62 | accept=".xls,.xlsx" | 72 | accept=".xls,.xlsx" |
| 63 | :on-change="handleChange" | 73 | :on-change="handleChange" |
| 74 | + :on-remove="handleRemove" | ||
| 75 | + :on-exceed="handleExceed" | ||
| 64 | :auto-upload="false" | 76 | :auto-upload="false" |
| 65 | > | 77 | > |
| 66 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> | 78 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { StudentApi } from '#/api/infra/student'; | 2 | +import type { StudentApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -17,7 +17,7 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 17 | 17 | ||
| 18 | import { $t } from '#/locales'; | 18 | import { $t } from '#/locales'; |
| 19 | import { isEmpty } from '@vben/utils'; | 19 | import { isEmpty } from '@vben/utils'; |
| 20 | -import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/student'; | 20 | +import { getStudentPage, deleteStudent, deleteStudentList, exportStudent } from '#/api/infra/demo'; |
| 21 | import StudentImport from './modules/import-form.vue'; | 21 | import StudentImport from './modules/import-form.vue'; |
| 22 | 22 | ||
| 23 | 23 | ||
| @@ -28,12 +28,11 @@ const total = ref(0) // 列表的总页数 | @@ -28,12 +28,11 @@ const total = ref(0) // 列表的总页数 | ||
| 28 | const queryParams = reactive({ | 28 | const queryParams = reactive({ |
| 29 | pageNo: 1, | 29 | pageNo: 1, |
| 30 | pageSize: 10, | 30 | pageSize: 10, |
| 31 | - name: undefined, | ||
| 32 | - birthday: undefined, | ||
| 33 | - birthday: undefined, | ||
| 34 | - sex: undefined, | ||
| 35 | - enabled: undefined, | ||
| 36 | - createTime: undefined, | 31 | + name: undefined, |
| 32 | + birthday: undefined, | ||
| 33 | + sex: undefined, | ||
| 34 | + enabled: undefined, | ||
| 35 | + createTime: undefined, | ||
| 37 | }) | 36 | }) |
| 38 | const queryFormRef = ref() // 搜索的表单 | 37 | const queryFormRef = ref() // 搜索的表单 |
| 39 | const exportLoading = ref(false) // 导出的加载中 | 38 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -136,7 +135,14 @@ function handleRowCheckboxChange({ | @@ -136,7 +135,14 @@ function handleRowCheckboxChange({ | ||
| 136 | async function handleExport() { | 135 | async function handleExport() { |
| 137 | try { | 136 | try { |
| 138 | exportLoading.value = true; | 137 | exportLoading.value = true; |
| 139 | - const data = await exportStudent(queryParams); | 138 | + const params = cloneDeep(queryParams) as any; |
| 139 | + if (params.birthday && Array.isArray(params.birthday)) { | ||
| 140 | + params.birthday = (params.birthday as string[]).join(','); | ||
| 141 | + } | ||
| 142 | + if (params.createTime && Array.isArray(params.createTime)) { | ||
| 143 | + params.createTime = (params.createTime as string[]).join(','); | ||
| 144 | + } | ||
| 145 | + const data = await exportStudent(params); | ||
| 140 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | 146 | downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); |
| 141 | }finally { | 147 | }finally { |
| 142 | exportLoading.value = false; | 148 | exportLoading.value = false; |
| @@ -159,61 +165,61 @@ onMounted(() => { | @@ -159,61 +165,61 @@ onMounted(() => { | ||
| 159 | 165 | ||
| 160 | <ContentWrap v-if="!hiddenSearchBar"> | 166 | <ContentWrap v-if="!hiddenSearchBar"> |
| 161 | <!-- 搜索工作栏 --> | 167 | <!-- 搜索工作栏 --> |
| 162 | - <el-form | 168 | + <ElForm |
| 163 | :model="queryParams" | 169 | :model="queryParams" |
| 164 | ref="queryFormRef" | 170 | ref="queryFormRef" |
| 165 | inline | 171 | inline |
| 166 | > | 172 | > |
| 167 | - <el-form-item label="名字"> | ||
| 168 | - <el-input | 173 | + <ElFormItem label="名字"> |
| 174 | + <ElInput | ||
| 169 | v-model="queryParams.name" | 175 | v-model="queryParams.name" |
| 170 | placeholder="请输入名字" | 176 | placeholder="请输入名字" |
| 171 | clearable | 177 | clearable |
| 172 | @keyup.enter="handleQuery" | 178 | @keyup.enter="handleQuery" |
| 173 | class="!w-[240px]" | 179 | class="!w-[240px]" |
| 174 | /> | 180 | /> |
| 175 | - </el-form-item> | ||
| 176 | - <el-form-item label="出生日期"> | ||
| 177 | - <el-date-picker | 181 | + </ElFormItem> |
| 182 | + <ElFormItem label="出生日期"> | ||
| 183 | + <ElDatePicker | ||
| 178 | v-model="queryParams.birthday" | 184 | v-model="queryParams.birthday" |
| 179 | value-format="YYYY-MM-DD" | 185 | value-format="YYYY-MM-DD" |
| 180 | placeholder="选择出生日期" | 186 | placeholder="选择出生日期" |
| 181 | clearable | 187 | clearable |
| 182 | class="!w-[240px]" | 188 | class="!w-[240px]" |
| 183 | /> | 189 | /> |
| 184 | - </el-form-item> | ||
| 185 | - <el-form-item label="性别"> | ||
| 186 | - <el-select | 190 | + </ElFormItem> |
| 191 | + <ElFormItem label="性别"> | ||
| 192 | + <ElSelect | ||
| 187 | v-model="queryParams.sex" | 193 | v-model="queryParams.sex" |
| 188 | placeholder="请选择性别" | 194 | placeholder="请选择性别" |
| 189 | clearable | 195 | clearable |
| 190 | class="!w-[240px]" | 196 | class="!w-[240px]" |
| 191 | > | 197 | > |
| 192 | - <el-option | 198 | + <ElOption |
| 193 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | 199 | v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" |
| 194 | :key="dict.value" | 200 | :key="dict.value" |
| 195 | :value="dict.value" | 201 | :value="dict.value" |
| 196 | :label="dict.label" | 202 | :label="dict.label" |
| 197 | /> | 203 | /> |
| 198 | - </el-select> | ||
| 199 | - </el-form-item> | ||
| 200 | - <el-form-item label="是否有效"> | ||
| 201 | - <el-select | 204 | + </ElSelect> |
| 205 | + </ElFormItem> | ||
| 206 | + <ElFormItem label="是否有效"> | ||
| 207 | + <ElSelect | ||
| 202 | v-model="queryParams.enabled" | 208 | v-model="queryParams.enabled" |
| 203 | placeholder="请选择是否有效" | 209 | placeholder="请选择是否有效" |
| 204 | clearable | 210 | clearable |
| 205 | class="!w-[240px]" | 211 | class="!w-[240px]" |
| 206 | > | 212 | > |
| 207 | - <el-option | 213 | + <ElOption |
| 208 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" | 214 | v-for="dict in getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean')" |
| 209 | :key="dict.value" | 215 | :key="dict.value" |
| 210 | :value="dict.value" | 216 | :value="dict.value" |
| 211 | :label="dict.label" | 217 | :label="dict.label" |
| 212 | /> | 218 | /> |
| 213 | - </el-select> | ||
| 214 | - </el-form-item> | ||
| 215 | - <el-form-item label="创建时间"> | ||
| 216 | - <el-date-picker | 219 | + </ElSelect> |
| 220 | + </ElFormItem> | ||
| 221 | + <ElFormItem label="创建时间"> | ||
| 222 | + <ElDatePicker | ||
| 217 | v-model="queryParams.createTime" | 223 | v-model="queryParams.createTime" |
| 218 | type="daterange" | 224 | type="daterange" |
| 219 | value-format="YYYY-MM-DD" | 225 | value-format="YYYY-MM-DD" |
| @@ -222,24 +228,24 @@ onMounted(() => { | @@ -222,24 +228,24 @@ onMounted(() => { | ||
| 222 | end-placeholder="结束日期" | 228 | end-placeholder="结束日期" |
| 223 | class="!w-[240px]" | 229 | class="!w-[240px]" |
| 224 | /> | 230 | /> |
| 225 | - </el-form-item> | ||
| 226 | - <el-form-item> | ||
| 227 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 228 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 231 | + </ElFormItem> |
| 232 | + <ElFormItem> | ||
| 233 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 234 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 229 | 搜索 | 235 | 搜索 |
| 230 | - </el-button> | ||
| 231 | - </el-form-item> | ||
| 232 | - </el-form> | 236 | + </ElButton> |
| 237 | + </ElFormItem> | ||
| 238 | + </ElForm> | ||
| 233 | </ContentWrap> | 239 | </ContentWrap> |
| 234 | 240 | ||
| 235 | <!-- 列表 --> | 241 | <!-- 列表 --> |
| 236 | <ContentWrap title="学生"> | 242 | <ContentWrap title="学生"> |
| 237 | <template #extra> | 243 | <template #extra> |
| 238 | - <TableToolbar | 244 | + <VbenVxeTableToolbar |
| 239 | ref="tableToolbarRef" | 245 | ref="tableToolbarRef" |
| 240 | v-model:hidden-search="hiddenSearchBar" | 246 | v-model:hidden-search="hiddenSearchBar" |
| 241 | > | 247 | > |
| 242 | - <el-button | 248 | + <ElButton |
| 243 | class="ml-2" | 249 | class="ml-2" |
| 244 | :icon="h(Plus)" | 250 | :icon="h(Plus)" |
| 245 | type="primary" | 251 | type="primary" |
| @@ -247,16 +253,16 @@ onMounted(() => { | @@ -247,16 +253,16 @@ onMounted(() => { | ||
| 247 | v-access:code="['infra:student:create']" | 253 | v-access:code="['infra:student:create']" |
| 248 | > | 254 | > |
| 249 | {{ $t('ui.actionTitle.create', ['学生']) }} | 255 | {{ $t('ui.actionTitle.create', ['学生']) }} |
| 250 | - </el-button> | ||
| 251 | - <el-button | 256 | + </ElButton> |
| 257 | + <ElButton | ||
| 252 | class="ml-2" | 258 | class="ml-2" |
| 253 | type="primary" | 259 | type="primary" |
| 254 | @click="handleImport" | 260 | @click="handleImport" |
| 255 | v-access:code="['infra:student:import']" | 261 | v-access:code="['infra:student:import']" |
| 256 | > | 262 | > |
| 257 | 导入 | 263 | 导入 |
| 258 | - </el-button> | ||
| 259 | - <el-button | 264 | + </ElButton> |
| 265 | + <ElButton | ||
| 260 | :icon="h(Download)" | 266 | :icon="h(Download)" |
| 261 | type="primary" | 267 | type="primary" |
| 262 | class="ml-2" | 268 | class="ml-2" |
| @@ -265,8 +271,8 @@ onMounted(() => { | @@ -265,8 +271,8 @@ onMounted(() => { | ||
| 265 | v-access:code="['infra:student:export']" | 271 | v-access:code="['infra:student:export']" |
| 266 | > | 272 | > |
| 267 | {{ $t('ui.actionTitle.export') }} | 273 | {{ $t('ui.actionTitle.export') }} |
| 268 | - </el-button> | ||
| 269 | - <el-button | 274 | + </ElButton> |
| 275 | + <ElButton | ||
| 270 | :icon="h(Trash2)" | 276 | :icon="h(Trash2)" |
| 271 | type="danger" | 277 | type="danger" |
| 272 | class="ml-2" | 278 | class="ml-2" |
| @@ -275,10 +281,10 @@ onMounted(() => { | @@ -275,10 +281,10 @@ onMounted(() => { | ||
| 275 | v-access:code="['infra:student:delete']" | 281 | v-access:code="['infra:student:delete']" |
| 276 | > | 282 | > |
| 277 | 批量删除 | 283 | 批量删除 |
| 278 | - </el-button> | ||
| 279 | - </TableToolbar> | 284 | + </ElButton> |
| 285 | + </VbenVxeTableToolbar> | ||
| 280 | </template> | 286 | </template> |
| 281 | - <vxe-table | 287 | + <VxeTable |
| 282 | ref="tableRef" | 288 | ref="tableRef" |
| 283 | :data="list" | 289 | :data="list" |
| 284 | show-overflow | 290 | show-overflow |
| @@ -286,36 +292,36 @@ onMounted(() => { | @@ -286,36 +292,36 @@ onMounted(() => { | ||
| 286 | @checkboxAll="handleRowCheckboxChange" | 292 | @checkboxAll="handleRowCheckboxChange" |
| 287 | @checkboxChange="handleRowCheckboxChange" | 293 | @checkboxChange="handleRowCheckboxChange" |
| 288 | > | 294 | > |
| 289 | - <vxe-column type="checkbox" width="40"></vxe-column> | ||
| 290 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 291 | - <vxe-column field="name" title="名字" align="center" /> | ||
| 292 | - <vxe-column field="description" title="简介" align="center" /> | ||
| 293 | - <vxe-column field="birthday" title="出生日期" align="center"> | 295 | + <VxeColumn type="checkbox" width="40"></VxeColumn> |
| 296 | + <VxeColumn field="id" title="编号" align="center" /> | ||
| 297 | + <VxeColumn field="name" title="名字" align="center" /> | ||
| 298 | + <VxeColumn field="description" title="简介" align="center" /> | ||
| 299 | + <VxeColumn field="birthday" title="出生日期" align="center"> | ||
| 294 | <template #default="{row}"> | 300 | <template #default="{row}"> |
| 295 | {{formatDateTime(row.birthday)}} | 301 | {{formatDateTime(row.birthday)}} |
| 296 | </template> | 302 | </template> |
| 297 | - </vxe-column> | ||
| 298 | - <vxe-column field="sex" title="性别" align="center"> | 303 | + </VxeColumn> |
| 304 | + <VxeColumn field="sex" title="性别" align="center"> | ||
| 299 | <template #default="{row}"> | 305 | <template #default="{row}"> |
| 300 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | 306 | <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> |
| 301 | </template> | 307 | </template> |
| 302 | - </vxe-column> | ||
| 303 | - <vxe-column field="enabled" title="是否有效" align="center"> | 308 | + </VxeColumn> |
| 309 | + <VxeColumn field="enabled" title="是否有效" align="center"> | ||
| 304 | <template #default="{row}"> | 310 | <template #default="{row}"> |
| 305 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> | 311 | <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.enabled" /> |
| 306 | </template> | 312 | </template> |
| 307 | - </vxe-column> | ||
| 308 | - <vxe-column field="avatar" title="头像" align="center" /> | ||
| 309 | - <vxe-column field="video" title="附件" align="center" /> | ||
| 310 | - <vxe-column field="memo" title="备注" align="center" /> | ||
| 311 | - <vxe-column field="createTime" title="创建时间" align="center"> | 313 | + </VxeColumn> |
| 314 | + <VxeColumn field="avatar" title="头像" align="center" /> | ||
| 315 | + <VxeColumn field="video" title="附件" align="center" /> | ||
| 316 | + <VxeColumn field="memo" title="备注" align="center" /> | ||
| 317 | + <VxeColumn field="createTime" title="创建时间" align="center"> | ||
| 312 | <template #default="{row}"> | 318 | <template #default="{row}"> |
| 313 | {{formatDateTime(row.createTime)}} | 319 | {{formatDateTime(row.createTime)}} |
| 314 | </template> | 320 | </template> |
| 315 | - </vxe-column> | ||
| 316 | - <vxe-column field="operation" title="操作" align="center"> | 321 | + </VxeColumn> |
| 322 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 317 | <template #default="{row}"> | 323 | <template #default="{row}"> |
| 318 | - <el-button | 324 | + <ElButton |
| 319 | size="small" | 325 | size="small" |
| 320 | type="primary" | 326 | type="primary" |
| 321 | link | 327 | link |
| @@ -323,8 +329,8 @@ onMounted(() => { | @@ -323,8 +329,8 @@ onMounted(() => { | ||
| 323 | v-access:code="['infra:student:update']" | 329 | v-access:code="['infra:student:update']" |
| 324 | > | 330 | > |
| 325 | {{ $t('ui.actionTitle.edit') }} | 331 | {{ $t('ui.actionTitle.edit') }} |
| 326 | - </el-button> | ||
| 327 | - <el-button | 332 | + </ElButton> |
| 333 | + <ElButton | ||
| 328 | size="small" | 334 | size="small" |
| 329 | type="danger" | 335 | type="danger" |
| 330 | link | 336 | link |
| @@ -333,13 +339,13 @@ onMounted(() => { | @@ -333,13 +339,13 @@ onMounted(() => { | ||
| 333 | v-access:code="['infra:student:delete']" | 339 | v-access:code="['infra:student:delete']" |
| 334 | > | 340 | > |
| 335 | {{ $t('ui.actionTitle.delete') }} | 341 | {{ $t('ui.actionTitle.delete') }} |
| 336 | - </el-button> | 342 | + </ElButton> |
| 337 | </template> | 343 | </template> |
| 338 | - </vxe-column> | ||
| 339 | - </vxe-table> | 344 | + </VxeColumn> |
| 345 | + </VxeTable> | ||
| 340 | <!-- 分页 --> | 346 | <!-- 分页 --> |
| 341 | <div class="mt-2 flex justify-end"> | 347 | <div class="mt-2 flex justify-end"> |
| 342 | - <el-pagination | 348 | + <ElPagination |
| 343 | :total="total" | 349 | :total="total" |
| 344 | v-model:current-page="queryParams.pageNo" | 350 | v-model:current-page="queryParams.pageNo" |
| 345 | v-model:page-size="queryParams.pageSize" | 351 | v-model:page-size="queryParams.pageSize" |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/vue/form
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { CategoryApi } from '#/api/infra/category'; | 2 | +import type { CategoryApi } from '#/api/infra/demo'; |
| 3 | import type { FormRules } from 'element-plus'; | 3 | import type { FormRules } from 'element-plus'; |
| 4 | 4 | ||
| 5 | import { useVbenModal } from '@vben/common-ui'; | 5 | import { useVbenModal } from '@vben/common-ui'; |
| @@ -7,12 +7,12 @@ import { getDictOptions } from '@vben/hooks'; | @@ -7,12 +7,12 @@ import { getDictOptions } from '@vben/hooks'; | ||
| 7 | import { Tinymce as RichTextarea } from '#/components/tinymce'; | 7 | import { Tinymce as RichTextarea } from '#/components/tinymce'; |
| 8 | import { ImageUpload, FileUpload } from "#/components/upload"; | 8 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 9 | import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus'; | 9 | import { ElMessage, ElTabs, ElTabPane, ElForm, ElFormItem, ElInput, ElSelect, ElOption, ElRadioGroup, ElRadio, ElCheckboxGroup, ElCheckbox, ElDatePicker, ElTreeSelect } from 'element-plus'; |
| 10 | -import { getCategoryList } from '#/api/infra/category'; | 10 | +import { getCategoryList } from '#/api/infra/demo'; |
| 11 | import { handleTree } from '@vben/utils' | 11 | import { handleTree } from '@vben/utils' |
| 12 | 12 | ||
| 13 | import { computed, ref, reactive } from 'vue'; | 13 | import { computed, ref, reactive } from 'vue'; |
| 14 | import { $t } from '#/locales'; | 14 | import { $t } from '#/locales'; |
| 15 | -import { getCategory, createCategory, updateCategory } from '#/api/infra/category'; | 15 | +import { getCategory, createCategory, updateCategory } from '#/api/infra/demo'; |
| 16 | 16 | ||
| 17 | const emit = defineEmits(['success']); | 17 | const emit = defineEmits(['success']); |
| 18 | 18 | ||
| @@ -98,18 +98,18 @@ const [Modal, modalApi] = useVbenModal({ | @@ -98,18 +98,18 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 98 | 98 | ||
| 99 | <template> | 99 | <template> |
| 100 | <Modal :title="getTitle"> | 100 | <Modal :title="getTitle"> |
| 101 | - <el-form | 101 | + <ElForm |
| 102 | ref="formRef" | 102 | ref="formRef" |
| 103 | :model="formData" | 103 | :model="formData" |
| 104 | :rules="rules" | 104 | :rules="rules" |
| 105 | label-width="120px" | 105 | label-width="120px" |
| 106 | label-position="right" | 106 | label-position="right" |
| 107 | > | 107 | > |
| 108 | - <el-form-item label="名字" prop="name"> | ||
| 109 | - <el-input v-model="formData.name" placeholder="请输入名字" /> | ||
| 110 | - </el-form-item> | ||
| 111 | - <el-form-item label="父编号" prop="parentId"> | ||
| 112 | - <el-tree-select | 108 | + <ElFormItem label="名字" prop="name"> |
| 109 | + <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||
| 110 | + </ElFormItem> | ||
| 111 | + <ElFormItem label="父编号" prop="parentId"> | ||
| 112 | + <ElTreeSelect | ||
| 113 | v-model="formData.parentId" | 113 | v-model="formData.parentId" |
| 114 | :data="categoryTree" | 114 | :data="categoryTree" |
| 115 | :props="{ | 115 | :props="{ |
| @@ -121,7 +121,7 @@ const [Modal, modalApi] = useVbenModal({ | @@ -121,7 +121,7 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 121 | default-expand-all | 121 | default-expand-all |
| 122 | placeholder="请选择父编号" | 122 | placeholder="请选择父编号" |
| 123 | /> | 123 | /> |
| 124 | - </el-form-item> | ||
| 125 | - </el-form> | 124 | + </ElFormItem> |
| 125 | + </ElForm> | ||
| 126 | </Modal> | 126 | </Modal> |
| 127 | </template> | 127 | </template> |
| 128 | \ No newline at end of file | 128 | \ No newline at end of file |
yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/vue/index
| 1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
| 2 | -import type { CategoryApi } from '#/api/infra/category'; | 2 | +import type { CategoryApi } from '#/api/infra/demo'; |
| 3 | 3 | ||
| 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; | 4 | import { ref, h, reactive, onMounted, nextTick } from 'vue'; |
| 5 | 5 | ||
| @@ -16,14 +16,14 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | @@ -16,14 +16,14 @@ import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||
| 16 | 16 | ||
| 17 | import { $t } from '#/locales'; | 17 | import { $t } from '#/locales'; |
| 18 | import { handleTree,isEmpty } from '@vben/utils' | 18 | import { handleTree,isEmpty } from '@vben/utils' |
| 19 | -import { getCategoryList, deleteCategory, exportCategory } from '#/api/infra/category'; | 19 | +import { getCategoryList, deleteCategory, exportCategory } from '#/api/infra/demo'; |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | const loading = ref(true) // 列表的加载中 | 22 | const loading = ref(true) // 列表的加载中 |
| 23 | const list = ref<any[]>([]) // 树列表的数据 | 23 | const list = ref<any[]>([]) // 树列表的数据 |
| 24 | 24 | ||
| 25 | const queryParams = reactive({ | 25 | const queryParams = reactive({ |
| 26 | - name: undefined, | 26 | + name: undefined, |
| 27 | }) | 27 | }) |
| 28 | const queryFormRef = ref() // 搜索的表单 | 28 | const queryFormRef = ref() // 搜索的表单 |
| 29 | const exportLoading = ref(false) // 导出的加载中 | 29 | const exportLoading = ref(false) // 导出的加载中 |
| @@ -89,7 +89,8 @@ async function handleDelete(row: CategoryApi.Category) { | @@ -89,7 +89,8 @@ async function handleDelete(row: CategoryApi.Category) { | ||
| 89 | async function handleExport() { | 89 | async function handleExport() { |
| 90 | try { | 90 | try { |
| 91 | exportLoading.value = true; | 91 | exportLoading.value = true; |
| 92 | - const data = await exportCategory(queryParams); | 92 | + const params = cloneDeep(queryParams) as any; |
| 93 | + const data = await exportCategory(params); | ||
| 93 | downloadFileFromBlobPart({ fileName: '分类.xls', source: data }); | 94 | downloadFileFromBlobPart({ fileName: '分类.xls', source: data }); |
| 94 | }finally { | 95 | }finally { |
| 95 | exportLoading.value = false; | 96 | exportLoading.value = false; |
| @@ -117,40 +118,40 @@ onMounted(() => { | @@ -117,40 +118,40 @@ onMounted(() => { | ||
| 117 | 118 | ||
| 118 | <ContentWrap v-if="!hiddenSearchBar"> | 119 | <ContentWrap v-if="!hiddenSearchBar"> |
| 119 | <!-- 搜索工作栏 --> | 120 | <!-- 搜索工作栏 --> |
| 120 | - <el-form | 121 | + <ElForm |
| 121 | :model="queryParams" | 122 | :model="queryParams" |
| 122 | ref="queryFormRef" | 123 | ref="queryFormRef" |
| 123 | inline | 124 | inline |
| 124 | > | 125 | > |
| 125 | - <el-form-item label="名字"> | ||
| 126 | - <el-input | 126 | + <ElFormItem label="名字"> |
| 127 | + <ElInput | ||
| 127 | v-model="queryParams.name" | 128 | v-model="queryParams.name" |
| 128 | placeholder="请输入名字" | 129 | placeholder="请输入名字" |
| 129 | clearable | 130 | clearable |
| 130 | @keyup.enter="handleQuery" | 131 | @keyup.enter="handleQuery" |
| 131 | class="!w-[240px]" | 132 | class="!w-[240px]" |
| 132 | /> | 133 | /> |
| 133 | - </el-form-item> | ||
| 134 | - <el-form-item> | ||
| 135 | - <el-button class="ml-2" @click="resetQuery"> 重置 </el-button> | ||
| 136 | - <el-button class="ml-2" @click="handleQuery" type="primary"> | 134 | + </ElFormItem> |
| 135 | + <ElFormItem> | ||
| 136 | + <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||
| 137 | + <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||
| 137 | 搜索 | 138 | 搜索 |
| 138 | - </el-button> | ||
| 139 | - </el-form-item> | ||
| 140 | - </el-form> | 139 | + </ElButton> |
| 140 | + </ElFormItem> | ||
| 141 | + </ElForm> | ||
| 141 | </ContentWrap> | 142 | </ContentWrap> |
| 142 | 143 | ||
| 143 | <!-- 列表 --> | 144 | <!-- 列表 --> |
| 144 | <ContentWrap title="分类"> | 145 | <ContentWrap title="分类"> |
| 145 | <template #extra> | 146 | <template #extra> |
| 146 | - <TableToolbar | 147 | + <VbenVxeTableToolbar |
| 147 | ref="tableToolbarRef" | 148 | ref="tableToolbarRef" |
| 148 | v-model:hidden-search="hiddenSearchBar" | 149 | v-model:hidden-search="hiddenSearchBar" |
| 149 | > | 150 | > |
| 150 | - <el-button @click="handleExpand" class="mr-2"> | 151 | + <ElButton @click="handleExpand" class="mr-2"> |
| 151 | {{ isExpanded ? '收缩' : '展开' }} | 152 | {{ isExpanded ? '收缩' : '展开' }} |
| 152 | - </el-button> | ||
| 153 | - <el-button | 153 | + </ElButton> |
| 154 | + <ElButton | ||
| 154 | class="ml-2" | 155 | class="ml-2" |
| 155 | :icon="h(Plus)" | 156 | :icon="h(Plus)" |
| 156 | type="primary" | 157 | type="primary" |
| @@ -158,8 +159,8 @@ onMounted(() => { | @@ -158,8 +159,8 @@ onMounted(() => { | ||
| 158 | v-access:code="['infra:category:create']" | 159 | v-access:code="['infra:category:create']" |
| 159 | > | 160 | > |
| 160 | {{ $t('ui.actionTitle.create', ['分类']) }} | 161 | {{ $t('ui.actionTitle.create', ['分类']) }} |
| 161 | - </el-button> | ||
| 162 | - <el-button | 162 | + </ElButton> |
| 163 | + <ElButton | ||
| 163 | :icon="h(Download)" | 164 | :icon="h(Download)" |
| 164 | type="primary" | 165 | type="primary" |
| 165 | class="ml-2" | 166 | class="ml-2" |
| @@ -168,10 +169,10 @@ onMounted(() => { | @@ -168,10 +169,10 @@ onMounted(() => { | ||
| 168 | v-access:code="['infra:category:export']" | 169 | v-access:code="['infra:category:export']" |
| 169 | > | 170 | > |
| 170 | {{ $t('ui.actionTitle.export') }} | 171 | {{ $t('ui.actionTitle.export') }} |
| 171 | - </el-button> | ||
| 172 | - </TableToolbar> | 172 | + </ElButton> |
| 173 | + </VbenVxeTableToolbar> | ||
| 173 | </template> | 174 | </template> |
| 174 | - <vxe-table | 175 | + <VxeTable |
| 175 | ref="tableRef" | 176 | ref="tableRef" |
| 176 | :data="list" | 177 | :data="list" |
| 177 | :tree-config="{ | 178 | :tree-config="{ |
| @@ -184,12 +185,12 @@ onMounted(() => { | @@ -184,12 +185,12 @@ onMounted(() => { | ||
| 184 | show-overflow | 185 | show-overflow |
| 185 | :loading="loading" | 186 | :loading="loading" |
| 186 | > | 187 | > |
| 187 | - <vxe-column field="id" title="编号" align="center" /> | ||
| 188 | - <vxe-column field="name" title="名字" align="center" tree-node/> | ||
| 189 | - <vxe-column field="parentId" title="父编号" align="center" /> | ||
| 190 | - <vxe-column field="operation" title="操作" align="center"> | 188 | + <VxeColumn field="id" title="编号" align="center" /> |
| 189 | + <VxeColumn field="name" title="名字" align="center" tree-node/> | ||
| 190 | + <VxeColumn field="parentId" title="父编号" align="center" /> | ||
| 191 | + <VxeColumn field="operation" title="操作" align="center"> | ||
| 191 | <template #default="{row}"> | 192 | <template #default="{row}"> |
| 192 | - <el-button | 193 | + <ElButton |
| 193 | size="small" | 194 | size="small" |
| 194 | type="primary" | 195 | type="primary" |
| 195 | link | 196 | link |
| @@ -197,8 +198,8 @@ onMounted(() => { | @@ -197,8 +198,8 @@ onMounted(() => { | ||
| 197 | v-access:code="['infra:category:create']" | 198 | v-access:code="['infra:category:create']" |
| 198 | > | 199 | > |
| 199 | 新增下级 | 200 | 新增下级 |
| 200 | - </el-button> | ||
| 201 | - <el-button | 201 | + </ElButton> |
| 202 | + <ElButton | ||
| 202 | size="small" | 203 | size="small" |
| 203 | type="primary" | 204 | type="primary" |
| 204 | link | 205 | link |
| @@ -206,8 +207,8 @@ onMounted(() => { | @@ -206,8 +207,8 @@ onMounted(() => { | ||
| 206 | v-access:code="['infra:category:update']" | 207 | v-access:code="['infra:category:update']" |
| 207 | > | 208 | > |
| 208 | {{ $t('ui.actionTitle.edit') }} | 209 | {{ $t('ui.actionTitle.edit') }} |
| 209 | - </el-button> | ||
| 210 | - <el-button | 210 | + </ElButton> |
| 211 | + <ElButton | ||
| 211 | size="small" | 212 | size="small" |
| 212 | type="danger" | 213 | type="danger" |
| 213 | link | 214 | link |
| @@ -217,10 +218,10 @@ onMounted(() => { | @@ -217,10 +218,10 @@ onMounted(() => { | ||
| 217 | v-access:code="['infra:category:delete']" | 218 | v-access:code="['infra:category:delete']" |
| 218 | > | 219 | > |
| 219 | {{ $t('ui.actionTitle.delete') }} | 220 | {{ $t('ui.actionTitle.delete') }} |
| 220 | - </el-button> | 221 | + </ElButton> |
| 221 | </template> | 222 | </template> |
| 222 | - </vxe-column> | ||
| 223 | - </vxe-table> | 223 | + </VxeColumn> |
| 224 | + </VxeTable> | ||
| 224 | </ContentWrap> | 225 | </ContentWrap> |
| 225 | </Page> | 226 | </Page> |
| 226 | </template> | 227 | </template> |
| 227 | \ No newline at end of file | 228 | \ No newline at end of file |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/ts/data
| @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 42 | rules: 'required', | 42 | rules: 'required', |
| 43 | component: 'DatePicker', | 43 | component: 'DatePicker', |
| 44 | componentProps: { | 44 | componentProps: { |
| 45 | - showTime: true, | 45 | + type: 'datetime', |
| 46 | format: 'YYYY-MM-DD HH:mm:ss', | 46 | format: 'YYYY-MM-DD HH:mm:ss', |
| 47 | valueFormat: 'x', | 47 | valueFormat: 'x', |
| 48 | class: '!w-full', | 48 | class: '!w-full', |
| @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 65 | component: 'RadioGroup', | 65 | component: 'RadioGroup', |
| 66 | componentProps: { | 66 | componentProps: { |
| 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 68 | - buttonStyle: 'solid', | ||
| 69 | - optionType: 'button', | 68 | + isButton: true, |
| 70 | }, | 69 | }, |
| 71 | }, | 70 | }, |
| 72 | { | 71 | { |
| @@ -277,7 +276,7 @@ export function useStudentContactFormSchema(): VbenFormSchema[] { | @@ -277,7 +276,7 @@ export function useStudentContactFormSchema(): VbenFormSchema[] { | ||
| 277 | rules: 'required', | 276 | rules: 'required', |
| 278 | component: 'DatePicker', | 277 | component: 'DatePicker', |
| 279 | componentProps: { | 278 | componentProps: { |
| 280 | - showTime: true, | 279 | + type: 'datetime', |
| 281 | format: 'YYYY-MM-DD HH:mm:ss', | 280 | format: 'YYYY-MM-DD HH:mm:ss', |
| 282 | valueFormat: 'x', | 281 | valueFormat: 'x', |
| 283 | class: '!w-full', | 282 | class: '!w-full', |
| @@ -300,8 +299,7 @@ export function useStudentContactFormSchema(): VbenFormSchema[] { | @@ -300,8 +299,7 @@ export function useStudentContactFormSchema(): VbenFormSchema[] { | ||
| 300 | component: 'RadioGroup', | 299 | component: 'RadioGroup', |
| 301 | componentProps: { | 300 | componentProps: { |
| 302 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 301 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 303 | - buttonStyle: 'solid', | ||
| 304 | - optionType: 'button', | 302 | + isButton: true, |
| 305 | }, | 303 | }, |
| 306 | }, | 304 | }, |
| 307 | { | 305 | { |
| @@ -520,7 +518,7 @@ export function useStudentTeacherFormSchema(): VbenFormSchema[] { | @@ -520,7 +518,7 @@ export function useStudentTeacherFormSchema(): VbenFormSchema[] { | ||
| 520 | rules: 'required', | 518 | rules: 'required', |
| 521 | component: 'DatePicker', | 519 | component: 'DatePicker', |
| 522 | componentProps: { | 520 | componentProps: { |
| 523 | - showTime: true, | 521 | + type: 'datetime', |
| 524 | format: 'YYYY-MM-DD HH:mm:ss', | 522 | format: 'YYYY-MM-DD HH:mm:ss', |
| 525 | valueFormat: 'x', | 523 | valueFormat: 'x', |
| 526 | class: '!w-full', | 524 | class: '!w-full', |
| @@ -543,8 +541,7 @@ export function useStudentTeacherFormSchema(): VbenFormSchema[] { | @@ -543,8 +541,7 @@ export function useStudentTeacherFormSchema(): VbenFormSchema[] { | ||
| 543 | component: 'RadioGroup', | 541 | component: 'RadioGroup', |
| 544 | componentProps: { | 542 | componentProps: { |
| 545 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 543 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 546 | - buttonStyle: 'solid', | ||
| 547 | - optionType: 'button', | 544 | + isButton: true, |
| 548 | }, | 545 | }, |
| 549 | }, | 546 | }, |
| 550 | { | 547 | { |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { ElMessage, ElTabs, ElTabPane } from 'element-plus'; | 8 | +import { ElMessage } from 'element-plus'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/ts/data
| @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 42 | rules: 'required', | 42 | rules: 'required', |
| 43 | component: 'DatePicker', | 43 | component: 'DatePicker', |
| 44 | componentProps: { | 44 | componentProps: { |
| 45 | - showTime: true, | 45 | + type: 'datetime', |
| 46 | format: 'YYYY-MM-DD HH:mm:ss', | 46 | format: 'YYYY-MM-DD HH:mm:ss', |
| 47 | valueFormat: 'x', | 47 | valueFormat: 'x', |
| 48 | class: '!w-full', | 48 | class: '!w-full', |
| @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 65 | component: 'RadioGroup', | 65 | component: 'RadioGroup', |
| 66 | componentProps: { | 66 | componentProps: { |
| 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 68 | - buttonStyle: 'solid', | ||
| 69 | - optionType: 'button', | 68 | + isButton: true, |
| 70 | }, | 69 | }, |
| 71 | }, | 70 | }, |
| 72 | { | 71 | { |
| @@ -270,7 +269,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -270,7 +269,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 270 | minWidth: 120, | 269 | minWidth: 120, |
| 271 | slots: { default: 'sex' }, | 270 | slots: { default: 'sex' }, |
| 272 | params: { | 271 | params: { |
| 273 | - options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'boolean'), | 272 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), |
| 274 | }, | 273 | }, |
| 275 | }, | 274 | }, |
| 276 | { | 275 | { |
| @@ -310,7 +309,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -310,7 +309,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 310 | } | 309 | } |
| 311 | 310 | ||
| 312 | /** 列表的字段 */ | 311 | /** 列表的字段 */ |
| 313 | - export function useStudentContactGridColumns(): VxeTableGridOptions<StudentApi.StudentContact>['columns'] { | 312 | + export function useStudentContactGridColumns(): VxeTableGridOptions<InfraStudentApi.StudentContact>['columns'] { |
| 314 | return [ | 313 | return [ |
| 315 | { | 314 | { |
| 316 | field: 'id', | 315 | field: 'id', |
| @@ -444,7 +443,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -444,7 +443,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 444 | rules: 'required', | 443 | rules: 'required', |
| 445 | component: 'DatePicker', | 444 | component: 'DatePicker', |
| 446 | componentProps: { | 445 | componentProps: { |
| 447 | - showTime: true, | 446 | + type: 'datetime', |
| 448 | format: 'YYYY-MM-DD HH:mm:ss', | 447 | format: 'YYYY-MM-DD HH:mm:ss', |
| 449 | valueFormat: 'x', | 448 | valueFormat: 'x', |
| 450 | class: '!w-full', | 449 | class: '!w-full', |
| @@ -467,8 +466,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -467,8 +466,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 467 | component: 'RadioGroup', | 466 | component: 'RadioGroup', |
| 468 | componentProps: { | 467 | componentProps: { |
| 469 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 468 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 470 | - buttonStyle: 'solid', | ||
| 471 | - optionType: 'button', | 469 | + isButton: true, |
| 472 | }, | 470 | }, |
| 473 | }, | 471 | }, |
| 474 | { | 472 | { |
| @@ -492,7 +490,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -492,7 +490,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 492 | } | 490 | } |
| 493 | 491 | ||
| 494 | /** 列表的字段 */ | 492 | /** 列表的字段 */ |
| 495 | - export function useStudentTeacherGridColumns(): VxeTableGridOptions<StudentApi.StudentTeacher>['columns'] { | 493 | + export function useStudentTeacherGridColumns(): VxeTableGridOptions<InfraStudentApi.StudentTeacher>['columns'] { |
| 496 | return [ | 494 | return [ |
| 497 | { | 495 | { |
| 498 | field: 'id', | 496 | field: 'id', |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { ElMessage } from 'element-plus'; | 8 | +import { ElMessage, ElTabPane, ElTabs } from 'element-plus'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
| @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 48 | return; | 48 | return; |
| 49 | } | 49 | } |
| 50 | // 校验子表单 | 50 | // 校验子表单 |
| 51 | - const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | 51 | + const studentContactValid = await studentContactFormRef.value?.validate(); |
| 52 | + if (!studentContactValid) { | ||
| 53 | + subTabsName.value = 'studentContact'; | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | ||
| 52 | if (!studentTeacherValid) { | 57 | if (!studentTeacherValid) { |
| 53 | subTabsName.value = 'studentTeacher'; | 58 | subTabsName.value = 'studentTeacher'; |
| 54 | return; | 59 | return; |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/vue/student-contact-form
| @@ -6,10 +6,9 @@ | @@ -6,10 +6,9 @@ | ||
| 6 | import { $t } from '#/locales'; | 6 | import { $t } from '#/locales'; |
| 7 | 7 | ||
| 8 | import { Plus } from "@vben/icons"; | 8 | import { Plus } from "@vben/icons"; |
| 9 | -import { ElButton, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElOption, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus'; | 9 | +import { ElButton, ElCheckbox, ElCheckboxGroup, ElDatePicker, ElInput, ElMessage, ElOption, ElRadio, ElRadioGroup, ElSelect, ElTabPane, ElTabs } from 'element-plus'; |
| 10 | import { ImageUpload, FileUpload } from "#/components/upload"; | 10 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 11 | -import type { OnActionClickParams } from '#/adapter/vxe-table'; | ||
| 12 | -import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 11 | +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 13 | import { useStudentContactGridEditColumns } from '../data'; | 12 | import { useStudentContactGridEditColumns } from '../data'; |
| 14 | import { getStudentContactListByStudentId } from '#/api/infra/demo'; | 13 | import { getStudentContactListByStudentId } from '#/api/infra/demo'; |
| 15 | 14 | ||
| @@ -17,22 +16,9 @@ const props = defineProps<{ | @@ -17,22 +16,9 @@ const props = defineProps<{ | ||
| 17 | studentId?: number // 学生编号(主表的关联字段) | 16 | studentId?: number // 学生编号(主表的关联字段) |
| 18 | }>() | 17 | }>() |
| 19 | 18 | ||
| 20 | - /** 表格操作按钮的回调函数 */ | ||
| 21 | -function onActionClick({ | ||
| 22 | - code, | ||
| 23 | - row, | ||
| 24 | -}: OnActionClickParams<InfraStudentApi.StudentContact>) { | ||
| 25 | - switch (code) { | ||
| 26 | - case 'delete': { | ||
| 27 | - onDelete(row); | ||
| 28 | - break; | ||
| 29 | - } | ||
| 30 | - } | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -const [Grid, gridApi] = useVbenVxeGrid({ | 19 | + const [Grid, gridApi] = useVbenVxeGrid({ |
| 34 | gridOptions: { | 20 | gridOptions: { |
| 35 | - columns: useStudentContactGridEditColumns(onActionClick), | 21 | + columns: useStudentContactGridEditColumns(), |
| 36 | border: true, | 22 | border: true, |
| 37 | showOverflow: true, | 23 | showOverflow: true, |
| 38 | autoResize: true, | 24 | autoResize: true, |
| @@ -51,7 +37,7 @@ gridOptions: { | @@ -51,7 +37,7 @@ gridOptions: { | ||
| 51 | 37 | ||
| 52 | /** 添加学生联系人 */ | 38 | /** 添加学生联系人 */ |
| 53 | const onAdd = async () => { | 39 | const onAdd = async () => { |
| 54 | - await gridApi.grid.insertAt({} as StudentApi.StudentContact, -1); | 40 | + await gridApi.grid.insertAt({} as InfraStudentApi.StudentContact, -1); |
| 55 | } | 41 | } |
| 56 | 42 | ||
| 57 | /** 删除学生联系人 */ | 43 | /** 删除学生联系人 */ |
| @@ -59,26 +45,96 @@ const onDelete = async (row: InfraStudentApi.StudentContact) => { | @@ -59,26 +45,96 @@ const onDelete = async (row: InfraStudentApi.StudentContact) => { | ||
| 59 | await gridApi.grid.remove(row); | 45 | await gridApi.grid.remove(row); |
| 60 | } | 46 | } |
| 61 | 47 | ||
| 62 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 63 | -defineExpose({ | ||
| 64 | - getData: (): InfraStudentApi.StudentContact[] => { | ||
| 65 | - const data = gridApi.grid.getData() as InfraStudentApi.StudentContact[]; | ||
| 66 | - const removeRecords = gridApi.grid.getRemoveRecords() as InfraStudentApi.StudentContact[]; | ||
| 67 | - const insertRecords = gridApi.grid.getInsertRecords() as InfraStudentApi.StudentContact[]; | ||
| 68 | - return data | ||
| 69 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 70 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 71 | - }, | ||
| 72 | -}); | 48 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 49 | +function getData(): InfraStudentApi.StudentContact[] { | ||
| 50 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 51 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 52 | + return fullData.map((row) => | ||
| 53 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 54 | + ); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +/** 校验子表必填字段 */ | ||
| 58 | +function validate(): boolean { | ||
| 59 | + for (const [index, row] of getData().entries()) { | ||
| 60 | + if ( | ||
| 61 | + row.name === null || | ||
| 62 | + row.name === undefined || | ||
| 63 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 64 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 65 | + ) { | ||
| 66 | + ElMessage.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.description === null || | ||
| 71 | + row.description === undefined || | ||
| 72 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 73 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 74 | + ) { | ||
| 75 | + ElMessage.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.birthday === null || | ||
| 80 | + row.birthday === undefined || | ||
| 81 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 82 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 83 | + ) { | ||
| 84 | + ElMessage.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.sex === null || | ||
| 89 | + row.sex === undefined || | ||
| 90 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 91 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 92 | + ) { | ||
| 93 | + ElMessage.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.enabled === null || | ||
| 98 | + row.enabled === undefined || | ||
| 99 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 100 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 101 | + ) { | ||
| 102 | + ElMessage.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.avatar === null || | ||
| 107 | + row.avatar === undefined || | ||
| 108 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 109 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 110 | + ) { | ||
| 111 | + ElMessage.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + if ( | ||
| 115 | + row.memo === null || | ||
| 116 | + row.memo === undefined || | ||
| 117 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 118 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 119 | + ) { | ||
| 120 | + ElMessage.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 121 | + return false; | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + return true; | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +defineExpose({ getData, validate }); | ||
| 73 | 128 | ||
| 74 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 129 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 75 | watch( | 130 | watch( |
| 76 | () => props.studentId, | 131 | () => props.studentId, |
| 77 | async (val) => { | 132 | async (val) => { |
| 133 | + await nextTick(); | ||
| 78 | if (!val) { | 134 | if (!val) { |
| 135 | + await gridApi.grid.loadData([]); | ||
| 79 | return; | 136 | return; |
| 80 | } | 137 | } |
| 81 | - await nextTick(); | ||
| 82 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); | 138 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); |
| 83 | }, | 139 | }, |
| 84 | { immediate: true }, | 140 | { immediate: true }, |
| @@ -88,13 +144,13 @@ watch( | @@ -88,13 +144,13 @@ watch( | ||
| 88 | <template> | 144 | <template> |
| 89 | <Grid class="mx-4"> | 145 | <Grid class="mx-4"> |
| 90 | <template #name="{ row }"> | 146 | <template #name="{ row }"> |
| 91 | - <el-input v-model="row.name" /> | 147 | + <ElInput v-model="row.name" /> |
| 92 | </template> | 148 | </template> |
| 93 | <template #description="{ row }"> | 149 | <template #description="{ row }"> |
| 94 | - <el-input v-model="row.description" type="textarea" /> | 150 | + <ElInput v-model="row.description" type="textarea" /> |
| 95 | </template> | 151 | </template> |
| 96 | <template #birthday="{ row }"> | 152 | <template #birthday="{ row }"> |
| 97 | - <el-date-picker | 153 | + <ElDatePicker |
| 98 | v-model="row.birthday" | 154 | v-model="row.birthday" |
| 99 | type="datetime" | 155 | type="datetime" |
| 100 | value-format="x" | 156 | value-format="x" |
| @@ -102,16 +158,16 @@ watch( | @@ -102,16 +158,16 @@ watch( | ||
| 102 | /> | 158 | /> |
| 103 | </template> | 159 | </template> |
| 104 | <template #sex="{ row, column }"> | 160 | <template #sex="{ row, column }"> |
| 105 | - <el-select v-model="row.sex" class="w-full"> | ||
| 106 | - <el-option v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 107 | - </el-select> | 161 | + <ElSelect v-model="row.sex" class="w-full"> |
| 162 | + <ElOption v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 163 | + </ElSelect> | ||
| 108 | </template> | 164 | </template> |
| 109 | <template #enabled="{ row, column }"> | 165 | <template #enabled="{ row, column }"> |
| 110 | - <el-radio-group v-model="row.enabled"> | ||
| 111 | - <el-radio v-for="option in column.params.options" :key="option.value" :label="option.value"> | 166 | + <ElRadioGroup v-model="row.enabled"> |
| 167 | + <ElRadio v-for="option in column.params.options" :key="option.value" :value="option.value"> | ||
| 112 | {{ option.label }} | 168 | {{ option.label }} |
| 113 | - </el-radio> | ||
| 114 | - </el-radio-group> | 169 | + </ElRadio> |
| 170 | + </ElRadioGroup> | ||
| 115 | </template> | 171 | </template> |
| 116 | <template #avatar="{ row }"> | 172 | <template #avatar="{ row }"> |
| 117 | <ImageUpload v-model="row.avatar" /> | 173 | <ImageUpload v-model="row.avatar" /> |
| @@ -120,12 +176,25 @@ watch( | @@ -120,12 +176,25 @@ watch( | ||
| 120 | <FileUpload v-model="row.video" /> | 176 | <FileUpload v-model="row.video" /> |
| 121 | </template> | 177 | </template> |
| 122 | <template #memo="{ row }"> | 178 | <template #memo="{ row }"> |
| 123 | - <el-input v-model="row.memo" type="textarea" /> | 179 | + <ElInput v-model="row.memo" type="textarea" /> |
| 124 | </template> | 180 | </template> |
| 181 | + <template #actions="{ row }"> | ||
| 182 | + <TableAction | ||
| 183 | + :actions="[ | ||
| 184 | + { | ||
| 185 | + label: $t('common.delete'), | ||
| 186 | + type: 'danger', link: true, | ||
| 187 | + icon: ACTION_ICON.DELETE, | ||
| 188 | + auth: ['infra:student:delete'], | ||
| 189 | + onClick: onDelete.bind(null, row), | ||
| 190 | + }, | ||
| 191 | + ]" | ||
| 192 | + /> | ||
| 193 | + </template> | ||
| 125 | </Grid> | 194 | </Grid> |
| 126 | <div class="flex justify-center -mt-4"> | 195 | <div class="flex justify-center -mt-4"> |
| 127 | - <el-button :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['infra:student:create']"> | 196 | + <ElButton :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['infra:student:create']"> |
| 128 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} | 197 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} |
| 129 | - </el-button> | 198 | + </ElButton> |
| 130 | </div> | 199 | </div> |
| 131 | </template> | 200 | </template> |
| 132 | \ No newline at end of file | 201 | \ No newline at end of file |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/vue/student-teacher-form
| @@ -39,10 +39,11 @@ defineExpose({ | @@ -39,10 +39,11 @@ defineExpose({ | ||
| 39 | watch( | 39 | watch( |
| 40 | () => props.studentId, | 40 | () => props.studentId, |
| 41 | async (val) => { | 41 | async (val) => { |
| 42 | + await nextTick(); | ||
| 43 | + await formApi.resetForm(); | ||
| 42 | if (!val) { | 44 | if (!val) { |
| 43 | return; | 45 | return; |
| 44 | } | 46 | } |
| 45 | - await nextTick(); | ||
| 46 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); | 47 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); |
| 47 | }, | 48 | }, |
| 48 | { immediate: true }, | 49 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/ts/data
| @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 42 | rules: 'required', | 42 | rules: 'required', |
| 43 | component: 'DatePicker', | 43 | component: 'DatePicker', |
| 44 | componentProps: { | 44 | componentProps: { |
| 45 | - showTime: true, | 45 | + type: 'datetime', |
| 46 | format: 'YYYY-MM-DD HH:mm:ss', | 46 | format: 'YYYY-MM-DD HH:mm:ss', |
| 47 | valueFormat: 'x', | 47 | valueFormat: 'x', |
| 48 | class: '!w-full', | 48 | class: '!w-full', |
| @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 65 | component: 'RadioGroup', | 65 | component: 'RadioGroup', |
| 66 | componentProps: { | 66 | componentProps: { |
| 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 68 | - buttonStyle: 'solid', | ||
| 69 | - optionType: 'button', | 68 | + isButton: true, |
| 70 | }, | 69 | }, |
| 71 | }, | 70 | }, |
| 72 | { | 71 | { |
| @@ -269,7 +268,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -269,7 +268,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 269 | minWidth: 120, | 268 | minWidth: 120, |
| 270 | slots: { default: 'sex' }, | 269 | slots: { default: 'sex' }, |
| 271 | params: { | 270 | params: { |
| 272 | - options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'boolean'), | 271 | + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), |
| 273 | }, | 272 | }, |
| 274 | }, | 273 | }, |
| 275 | { | 274 | { |
| @@ -345,7 +344,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -345,7 +344,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 345 | rules: 'required', | 344 | rules: 'required', |
| 346 | component: 'DatePicker', | 345 | component: 'DatePicker', |
| 347 | componentProps: { | 346 | componentProps: { |
| 348 | - showTime: true, | 347 | + type: 'datetime', |
| 349 | format: 'YYYY-MM-DD HH:mm:ss', | 348 | format: 'YYYY-MM-DD HH:mm:ss', |
| 350 | valueFormat: 'x', | 349 | valueFormat: 'x', |
| 351 | class: '!w-full', | 350 | class: '!w-full', |
| @@ -368,8 +367,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | @@ -368,8 +367,7 @@ export function useGridColumns(): VxeTableGridOptions<InfraStudentApi.Student>[' | ||
| 368 | component: 'RadioGroup', | 367 | component: 'RadioGroup', |
| 369 | componentProps: { | 368 | componentProps: { |
| 370 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 369 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 371 | - buttonStyle: 'solid', | ||
| 372 | - optionType: 'button', | 370 | + isButton: true, |
| 373 | }, | 371 | }, |
| 374 | }, | 372 | }, |
| 375 | { | 373 | { |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/vue/form
| @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | @@ -5,7 +5,7 @@ import { computed, ref } from 'vue'; | ||
| 5 | 5 | ||
| 6 | import { useVbenModal } from '@vben/common-ui'; | 6 | import { useVbenModal } from '@vben/common-ui'; |
| 7 | 7 | ||
| 8 | -import { ElMessage } from 'element-plus'; | 8 | +import { ElMessage, ElTabPane, ElTabs } from 'element-plus'; |
| 9 | 9 | ||
| 10 | import { useVbenForm } from '#/adapter/form'; | 10 | import { useVbenForm } from '#/adapter/form'; |
| 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; | 11 | import { createStudent, getStudent, updateStudent } from '#/api/infra/demo'; |
| @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | @@ -48,7 +48,12 @@ const [Modal, modalApi] = useVbenModal({ | ||
| 48 | return; | 48 | return; |
| 49 | } | 49 | } |
| 50 | // 校验子表单 | 50 | // 校验子表单 |
| 51 | - const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | 51 | + const studentContactValid = await studentContactFormRef.value?.validate(); |
| 52 | + if (!studentContactValid) { | ||
| 53 | + subTabsName.value = 'studentContact'; | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + const studentTeacherValid = await studentTeacherFormRef.value?.validate(); | ||
| 52 | if (!studentTeacherValid) { | 57 | if (!studentTeacherValid) { |
| 53 | subTabsName.value = 'studentTeacher'; | 58 | subTabsName.value = 'studentTeacher'; |
| 54 | return; | 59 | return; |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/vue/student-contact-form
| @@ -6,10 +6,9 @@ | @@ -6,10 +6,9 @@ | ||
| 6 | import { $t } from '#/locales'; | 6 | import { $t } from '#/locales'; |
| 7 | 7 | ||
| 8 | import { Plus } from "@vben/icons"; | 8 | import { Plus } from "@vben/icons"; |
| 9 | -import { ElButton, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElOption, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus'; | 9 | +import { ElButton, ElCheckbox, ElCheckboxGroup, ElDatePicker, ElInput, ElMessage, ElOption, ElRadio, ElRadioGroup, ElSelect, ElTabPane, ElTabs } from 'element-plus'; |
| 10 | import { ImageUpload, FileUpload } from "#/components/upload"; | 10 | import { ImageUpload, FileUpload } from "#/components/upload"; |
| 11 | -import type { OnActionClickParams } from '#/adapter/vxe-table'; | ||
| 12 | -import { useVbenVxeGrid } from '#/adapter/vxe-table'; | 11 | +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| 13 | import { useStudentContactGridEditColumns } from '../data'; | 12 | import { useStudentContactGridEditColumns } from '../data'; |
| 14 | import { getStudentContactListByStudentId } from '#/api/infra/demo'; | 13 | import { getStudentContactListByStudentId } from '#/api/infra/demo'; |
| 15 | 14 | ||
| @@ -17,22 +16,9 @@ const props = defineProps<{ | @@ -17,22 +16,9 @@ const props = defineProps<{ | ||
| 17 | studentId?: number // 学生编号(主表的关联字段) | 16 | studentId?: number // 学生编号(主表的关联字段) |
| 18 | }>() | 17 | }>() |
| 19 | 18 | ||
| 20 | - /** 表格操作按钮的回调函数 */ | ||
| 21 | -function onActionClick({ | ||
| 22 | - code, | ||
| 23 | - row, | ||
| 24 | -}: OnActionClickParams<InfraStudentApi.StudentContact>) { | ||
| 25 | - switch (code) { | ||
| 26 | - case 'delete': { | ||
| 27 | - onDelete(row); | ||
| 28 | - break; | ||
| 29 | - } | ||
| 30 | - } | ||
| 31 | -} | ||
| 32 | - | ||
| 33 | -const [Grid, gridApi] = useVbenVxeGrid({ | 19 | + const [Grid, gridApi] = useVbenVxeGrid({ |
| 34 | gridOptions: { | 20 | gridOptions: { |
| 35 | - columns: useStudentContactGridEditColumns(onActionClick), | 21 | + columns: useStudentContactGridEditColumns(), |
| 36 | border: true, | 22 | border: true, |
| 37 | showOverflow: true, | 23 | showOverflow: true, |
| 38 | autoResize: true, | 24 | autoResize: true, |
| @@ -51,7 +37,7 @@ gridOptions: { | @@ -51,7 +37,7 @@ gridOptions: { | ||
| 51 | 37 | ||
| 52 | /** 添加学生联系人 */ | 38 | /** 添加学生联系人 */ |
| 53 | const onAdd = async () => { | 39 | const onAdd = async () => { |
| 54 | - await gridApi.grid.insertAt({} as StudentApi.StudentContact, -1); | 40 | + await gridApi.grid.insertAt({} as InfraStudentApi.StudentContact, -1); |
| 55 | } | 41 | } |
| 56 | 42 | ||
| 57 | /** 删除学生联系人 */ | 43 | /** 删除学生联系人 */ |
| @@ -59,26 +45,96 @@ const onDelete = async (row: InfraStudentApi.StudentContact) => { | @@ -59,26 +45,96 @@ const onDelete = async (row: InfraStudentApi.StudentContact) => { | ||
| 59 | await gridApi.grid.remove(row); | 45 | await gridApi.grid.remove(row); |
| 60 | } | 46 | } |
| 61 | 47 | ||
| 62 | -/** 提供获取表格数据的方法供父组件调用 */ | ||
| 63 | -defineExpose({ | ||
| 64 | - getData: (): InfraStudentApi.StudentContact[] => { | ||
| 65 | - const data = gridApi.grid.getData() as InfraStudentApi.StudentContact[]; | ||
| 66 | - const removeRecords = gridApi.grid.getRemoveRecords() as InfraStudentApi.StudentContact[]; | ||
| 67 | - const insertRecords = gridApi.grid.getInsertRecords() as InfraStudentApi.StudentContact[]; | ||
| 68 | - return data | ||
| 69 | - .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||
| 70 | - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||
| 71 | - }, | ||
| 72 | -}); | 48 | +/** 获取当前子表数据,新增行不提交表格生成的临时编号 */ |
| 49 | +function getData(): InfraStudentApi.StudentContact[] { | ||
| 50 | + const { fullData } = gridApi.grid.getTableData(); | ||
| 51 | + const inserted = new Set(gridApi.grid.getInsertRecords()); | ||
| 52 | + return fullData.map((row) => | ||
| 53 | + inserted.has(row) ? { ...row, id: undefined } : { ...row }, | ||
| 54 | + ); | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +/** 校验子表必填字段 */ | ||
| 58 | +function validate(): boolean { | ||
| 59 | + for (const [index, row] of getData().entries()) { | ||
| 60 | + if ( | ||
| 61 | + row.name === null || | ||
| 62 | + row.name === undefined || | ||
| 63 | + (typeof row.name === 'string' && String(row.name).trim() === '') || | ||
| 64 | + (Array.isArray(row.name) && row.name.length === 0) | ||
| 65 | + ) { | ||
| 66 | + ElMessage.error(`第 ${index + 1} 行:名字不能为空`); | ||
| 67 | + return false; | ||
| 68 | + } | ||
| 69 | + if ( | ||
| 70 | + row.description === null || | ||
| 71 | + row.description === undefined || | ||
| 72 | + (typeof row.description === 'string' && String(row.description).trim() === '') || | ||
| 73 | + (Array.isArray(row.description) && row.description.length === 0) | ||
| 74 | + ) { | ||
| 75 | + ElMessage.error(`第 ${index + 1} 行:简介不能为空`); | ||
| 76 | + return false; | ||
| 77 | + } | ||
| 78 | + if ( | ||
| 79 | + row.birthday === null || | ||
| 80 | + row.birthday === undefined || | ||
| 81 | + (typeof row.birthday === 'string' && String(row.birthday).trim() === '') || | ||
| 82 | + (Array.isArray(row.birthday) && row.birthday.length === 0) | ||
| 83 | + ) { | ||
| 84 | + ElMessage.error(`第 ${index + 1} 行:出生日期不能为空`); | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + if ( | ||
| 88 | + row.sex === null || | ||
| 89 | + row.sex === undefined || | ||
| 90 | + (typeof row.sex === 'string' && String(row.sex).trim() === '') || | ||
| 91 | + (Array.isArray(row.sex) && row.sex.length === 0) | ||
| 92 | + ) { | ||
| 93 | + ElMessage.error(`第 ${index + 1} 行:性别不能为空`); | ||
| 94 | + return false; | ||
| 95 | + } | ||
| 96 | + if ( | ||
| 97 | + row.enabled === null || | ||
| 98 | + row.enabled === undefined || | ||
| 99 | + (typeof row.enabled === 'string' && String(row.enabled).trim() === '') || | ||
| 100 | + (Array.isArray(row.enabled) && row.enabled.length === 0) | ||
| 101 | + ) { | ||
| 102 | + ElMessage.error(`第 ${index + 1} 行:是否有效不能为空`); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + if ( | ||
| 106 | + row.avatar === null || | ||
| 107 | + row.avatar === undefined || | ||
| 108 | + (typeof row.avatar === 'string' && String(row.avatar).trim() === '') || | ||
| 109 | + (Array.isArray(row.avatar) && row.avatar.length === 0) | ||
| 110 | + ) { | ||
| 111 | + ElMessage.error(`第 ${index + 1} 行:头像不能为空`); | ||
| 112 | + return false; | ||
| 113 | + } | ||
| 114 | + if ( | ||
| 115 | + row.memo === null || | ||
| 116 | + row.memo === undefined || | ||
| 117 | + (typeof row.memo === 'string' && String(row.memo).trim() === '') || | ||
| 118 | + (Array.isArray(row.memo) && row.memo.length === 0) | ||
| 119 | + ) { | ||
| 120 | + ElMessage.error(`第 ${index + 1} 行:备注不能为空`); | ||
| 121 | + return false; | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + return true; | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +defineExpose({ getData, validate }); | ||
| 73 | 128 | ||
| 74 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ | 129 | /** 监听主表的关联字段的变化,加载对应的子表数据 */ |
| 75 | watch( | 130 | watch( |
| 76 | () => props.studentId, | 131 | () => props.studentId, |
| 77 | async (val) => { | 132 | async (val) => { |
| 133 | + await nextTick(); | ||
| 78 | if (!val) { | 134 | if (!val) { |
| 135 | + await gridApi.grid.loadData([]); | ||
| 79 | return; | 136 | return; |
| 80 | } | 137 | } |
| 81 | - await nextTick(); | ||
| 82 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); | 138 | await gridApi.grid.loadData(await getStudentContactListByStudentId(props.studentId!)); |
| 83 | }, | 139 | }, |
| 84 | { immediate: true }, | 140 | { immediate: true }, |
| @@ -88,13 +144,13 @@ watch( | @@ -88,13 +144,13 @@ watch( | ||
| 88 | <template> | 144 | <template> |
| 89 | <Grid class="mx-4"> | 145 | <Grid class="mx-4"> |
| 90 | <template #name="{ row }"> | 146 | <template #name="{ row }"> |
| 91 | - <el-input v-model="row.name" /> | 147 | + <ElInput v-model="row.name" /> |
| 92 | </template> | 148 | </template> |
| 93 | <template #description="{ row }"> | 149 | <template #description="{ row }"> |
| 94 | - <el-input v-model="row.description" type="textarea" /> | 150 | + <ElInput v-model="row.description" type="textarea" /> |
| 95 | </template> | 151 | </template> |
| 96 | <template #birthday="{ row }"> | 152 | <template #birthday="{ row }"> |
| 97 | - <el-date-picker | 153 | + <ElDatePicker |
| 98 | v-model="row.birthday" | 154 | v-model="row.birthday" |
| 99 | type="datetime" | 155 | type="datetime" |
| 100 | value-format="x" | 156 | value-format="x" |
| @@ -102,16 +158,16 @@ watch( | @@ -102,16 +158,16 @@ watch( | ||
| 102 | /> | 158 | /> |
| 103 | </template> | 159 | </template> |
| 104 | <template #sex="{ row, column }"> | 160 | <template #sex="{ row, column }"> |
| 105 | - <el-select v-model="row.sex" class="w-full"> | ||
| 106 | - <el-option v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 107 | - </el-select> | 161 | + <ElSelect v-model="row.sex" class="w-full"> |
| 162 | + <ElOption v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" /> | ||
| 163 | + </ElSelect> | ||
| 108 | </template> | 164 | </template> |
| 109 | <template #enabled="{ row, column }"> | 165 | <template #enabled="{ row, column }"> |
| 110 | - <el-radio-group v-model="row.enabled"> | ||
| 111 | - <el-radio v-for="option in column.params.options" :key="option.value" :label="option.value"> | 166 | + <ElRadioGroup v-model="row.enabled"> |
| 167 | + <ElRadio v-for="option in column.params.options" :key="option.value" :value="option.value"> | ||
| 112 | {{ option.label }} | 168 | {{ option.label }} |
| 113 | - </el-radio> | ||
| 114 | - </el-radio-group> | 169 | + </ElRadio> |
| 170 | + </ElRadioGroup> | ||
| 115 | </template> | 171 | </template> |
| 116 | <template #avatar="{ row }"> | 172 | <template #avatar="{ row }"> |
| 117 | <ImageUpload v-model="row.avatar" /> | 173 | <ImageUpload v-model="row.avatar" /> |
| @@ -120,12 +176,25 @@ watch( | @@ -120,12 +176,25 @@ watch( | ||
| 120 | <FileUpload v-model="row.video" /> | 176 | <FileUpload v-model="row.video" /> |
| 121 | </template> | 177 | </template> |
| 122 | <template #memo="{ row }"> | 178 | <template #memo="{ row }"> |
| 123 | - <el-input v-model="row.memo" type="textarea" /> | 179 | + <ElInput v-model="row.memo" type="textarea" /> |
| 124 | </template> | 180 | </template> |
| 181 | + <template #actions="{ row }"> | ||
| 182 | + <TableAction | ||
| 183 | + :actions="[ | ||
| 184 | + { | ||
| 185 | + label: $t('common.delete'), | ||
| 186 | + type: 'danger', link: true, | ||
| 187 | + icon: ACTION_ICON.DELETE, | ||
| 188 | + auth: ['infra:student:delete'], | ||
| 189 | + onClick: onDelete.bind(null, row), | ||
| 190 | + }, | ||
| 191 | + ]" | ||
| 192 | + /> | ||
| 193 | + </template> | ||
| 125 | </Grid> | 194 | </Grid> |
| 126 | <div class="flex justify-center -mt-4"> | 195 | <div class="flex justify-center -mt-4"> |
| 127 | - <el-button :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['infra:student:create']"> | 196 | + <ElButton :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['infra:student:create']"> |
| 128 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} | 197 | {{ $t('ui.actionTitle.create', ['学生联系人']) }} |
| 129 | - </el-button> | 198 | + </ElButton> |
| 130 | </div> | 199 | </div> |
| 131 | </template> | 200 | </template> |
| 132 | \ No newline at end of file | 201 | \ No newline at end of file |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/vue/student-teacher-form
| @@ -39,10 +39,11 @@ defineExpose({ | @@ -39,10 +39,11 @@ defineExpose({ | ||
| 39 | watch( | 39 | watch( |
| 40 | () => props.studentId, | 40 | () => props.studentId, |
| 41 | async (val) => { | 41 | async (val) => { |
| 42 | + await nextTick(); | ||
| 43 | + await formApi.resetForm(); | ||
| 42 | if (!val) { | 44 | if (!val) { |
| 43 | return; | 45 | return; |
| 44 | } | 46 | } |
| 45 | - await nextTick(); | ||
| 46 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); | 47 | await formApi.setValues(await getStudentTeacherByStudentId(props.studentId!)); |
| 47 | }, | 48 | }, |
| 48 | { immediate: true }, | 49 | { immediate: true }, |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/ts/data
| @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 42 | rules: 'required', | 42 | rules: 'required', |
| 43 | component: 'DatePicker', | 43 | component: 'DatePicker', |
| 44 | componentProps: { | 44 | componentProps: { |
| 45 | - showTime: true, | 45 | + type: 'datetime', |
| 46 | format: 'YYYY-MM-DD HH:mm:ss', | 46 | format: 'YYYY-MM-DD HH:mm:ss', |
| 47 | valueFormat: 'x', | 47 | valueFormat: 'x', |
| 48 | class: '!w-full', | 48 | class: '!w-full', |
| @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 65 | component: 'RadioGroup', | 65 | component: 'RadioGroup', |
| 66 | componentProps: { | 66 | componentProps: { |
| 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 68 | - buttonStyle: 'solid', | ||
| 69 | - optionType: 'button', | 68 | + isButton: true, |
| 70 | }, | 69 | }, |
| 71 | }, | 70 | }, |
| 72 | { | 71 | { |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/ts/data
| @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -42,7 +42,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 42 | rules: 'required', | 42 | rules: 'required', |
| 43 | component: 'DatePicker', | 43 | component: 'DatePicker', |
| 44 | componentProps: { | 44 | componentProps: { |
| 45 | - showTime: true, | 45 | + type: 'datetime', |
| 46 | format: 'YYYY-MM-DD HH:mm:ss', | 46 | format: 'YYYY-MM-DD HH:mm:ss', |
| 47 | valueFormat: 'x', | 47 | valueFormat: 'x', |
| 48 | class: '!w-full', | 48 | class: '!w-full', |
| @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -65,8 +65,7 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 65 | component: 'RadioGroup', | 65 | component: 'RadioGroup', |
| 66 | componentProps: { | 66 | componentProps: { |
| 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), | 67 | options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), |
| 68 | - buttonStyle: 'solid', | ||
| 69 | - optionType: 'button', | 68 | + isButton: true, |
| 70 | }, | 69 | }, |
| 71 | }, | 70 | }, |
| 72 | { | 71 | { |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/vue/import-form
| @@ -50,6 +50,16 @@ function handleChange(file: any) { | @@ -50,6 +50,16 @@ function handleChange(file: any) { | ||
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | +/** 移除文件 */ | ||
| 54 | +function handleRemove() { | ||
| 55 | + formApi.setFieldValue('file', undefined); | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +/** 超出文件数量 */ | ||
| 59 | +function handleExceed() { | ||
| 60 | + ElMessage.warning('只能选择一个文件,请先移除已选文件'); | ||
| 61 | +} | ||
| 62 | + | ||
| 53 | /** 下载模板 */ | 63 | /** 下载模板 */ |
| 54 | async function handleDownload() { | 64 | async function handleDownload() { |
| 55 | const data = await importStudentTemplate(); | 65 | const data = await importStudentTemplate(); |
| @@ -66,6 +76,8 @@ async function handleDownload() { | @@ -66,6 +76,8 @@ async function handleDownload() { | ||
| 66 | :limit="1" | 76 | :limit="1" |
| 67 | accept=".xls,.xlsx" | 77 | accept=".xls,.xlsx" |
| 68 | :on-change="handleChange" | 78 | :on-change="handleChange" |
| 79 | + :on-remove="handleRemove" | ||
| 80 | + :on-exceed="handleExceed" | ||
| 69 | :auto-upload="false" | 81 | :auto-upload="false" |
| 70 | > | 82 | > |
| 71 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> | 83 | <ElButton type="primary"> 选择 Excel 文件 </ElButton> |
yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/ts/data
| @@ -32,13 +32,14 @@ export function useFormSchema(): VbenFormSchema[] { | @@ -32,13 +32,14 @@ export function useFormSchema(): VbenFormSchema[] { | ||
| 32 | id: 0, | 32 | id: 0, |
| 33 | name: '顶级分类', | 33 | name: '顶级分类', |
| 34 | }); | 34 | }); |
| 35 | - return handleTree(data); | 35 | + return handleTree(data, 'id', 'parentId'); |
| 36 | }, | 36 | }, |
| 37 | labelField: 'name', | 37 | labelField: 'name', |
| 38 | valueField: 'id', | 38 | valueField: 'id', |
| 39 | childrenField: 'children', | 39 | childrenField: 'children', |
| 40 | placeholder: '请选择上级分类', | 40 | placeholder: '请选择上级分类', |
| 41 | - treeDefaultExpandAll: true, | 41 | + defaultExpandAll: true, |
| 42 | + checkStrictly: true, | ||
| 42 | }, | 43 | }, |
| 43 | rules: 'selectRequired', | 44 | rules: 'selectRequired', |
| 44 | }, | 45 | }, |
yudao-module-infra/src/test/resources/codegen/vue2_master_erp/vue/StudentContactList
| @@ -64,7 +64,7 @@ | @@ -64,7 +64,7 @@ | ||
| 64 | </el-table-column> | 64 | </el-table-column> |
| 65 | </el-table> | 65 | </el-table> |
| 66 | <!-- 分页组件 --> | 66 | <!-- 分页组件 --> |
| 67 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 67 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 68 | @pagination="getList"/> | 68 | @pagination="getList"/> |
| 69 | <!-- 对话框(添加 / 修改) --> | 69 | <!-- 对话框(添加 / 修改) --> |
| 70 | <StudentContactForm ref="formRef" @success="getList" /> | 70 | <StudentContactForm ref="formRef" @success="getList" /> |
| @@ -79,9 +79,13 @@ | @@ -79,9 +79,13 @@ | ||
| 79 | components: { | 79 | components: { |
| 80 | StudentContactForm | 80 | StudentContactForm |
| 81 | }, | 81 | }, |
| 82 | - props:[ | ||
| 83 | - 'studentId' | ||
| 84 | - ],// 学生编号(主表的关联字段) | 82 | + props: { |
| 83 | + // 学生编号(主表的关联字段) | ||
| 84 | + studentId: { | ||
| 85 | + type: Number, | ||
| 86 | + default: undefined | ||
| 87 | + } | ||
| 88 | + }, | ||
| 85 | data() { | 89 | data() { |
| 86 | return { | 90 | return { |
| 87 | // 遮罩层 | 91 | // 遮罩层 |
yudao-module-infra/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherList
| @@ -64,7 +64,7 @@ | @@ -64,7 +64,7 @@ | ||
| 64 | </el-table-column> | 64 | </el-table-column> |
| 65 | </el-table> | 65 | </el-table> |
| 66 | <!-- 分页组件 --> | 66 | <!-- 分页组件 --> |
| 67 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 67 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 68 | @pagination="getList"/> | 68 | @pagination="getList"/> |
| 69 | <!-- 对话框(添加 / 修改) --> | 69 | <!-- 对话框(添加 / 修改) --> |
| 70 | <StudentTeacherForm ref="formRef" @success="getList" /> | 70 | <StudentTeacherForm ref="formRef" @success="getList" /> |
| @@ -79,9 +79,13 @@ | @@ -79,9 +79,13 @@ | ||
| 79 | components: { | 79 | components: { |
| 80 | StudentTeacherForm | 80 | StudentTeacherForm |
| 81 | }, | 81 | }, |
| 82 | - props:[ | ||
| 83 | - 'studentId' | ||
| 84 | - ],// 学生编号(主表的关联字段) | 82 | + props: { |
| 83 | + // 学生编号(主表的关联字段) | ||
| 84 | + studentId: { | ||
| 85 | + type: Number, | ||
| 86 | + default: undefined | ||
| 87 | + } | ||
| 88 | + }, | ||
| 85 | data() { | 89 | data() { |
| 86 | return { | 90 | return { |
| 87 | // 遮罩层 | 91 | // 遮罩层 |
yudao-module-infra/src/test/resources/codegen/vue2_master_erp/vue/index
| @@ -53,7 +53,7 @@ | @@ -53,7 +53,7 @@ | ||
| 53 | 批量删除 | 53 | 批量删除 |
| 54 | </el-button> | 54 | </el-button> |
| 55 | </el-col> | 55 | </el-col> |
| 56 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 56 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 57 | </el-row> | 57 | </el-row> |
| 58 | 58 | ||
| 59 | <el-table | 59 | <el-table |
| @@ -127,7 +127,7 @@ | @@ -127,7 +127,7 @@ | ||
| 127 | </el-table-column> | 127 | </el-table-column> |
| 128 | </el-table> | 128 | </el-table> |
| 129 | <!-- 分页组件 --> | 129 | <!-- 分页组件 --> |
| 130 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 130 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 131 | @pagination="getList"/> | 131 | @pagination="getList"/> |
| 132 | <!-- 对话框(添加 / 修改) --> | 132 | <!-- 对话框(添加 / 修改) --> |
| 133 | <StudentForm ref="formRef" @success="getList" /> | 133 | <StudentForm ref="formRef" @success="getList" /> |
yudao-module-infra/src/test/resources/codegen/vue2_master_inner/vue/StudentContactForm
| @@ -97,9 +97,13 @@ | @@ -97,9 +97,13 @@ | ||
| 97 | FileUpload, | 97 | FileUpload, |
| 98 | Editor, | 98 | Editor, |
| 99 | }, | 99 | }, |
| 100 | - props:[ | ||
| 101 | - 'studentId' | ||
| 102 | - ],// 学生编号(主表的关联字段) | 100 | + props: { |
| 101 | + // 学生编号(主表的关联字段) | ||
| 102 | + studentId: { | ||
| 103 | + type: Number, | ||
| 104 | + default: undefined | ||
| 105 | + } | ||
| 106 | + }, | ||
| 103 | data() { | 107 | data() { |
| 104 | return { | 108 | return { |
| 105 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | 109 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
yudao-module-infra/src/test/resources/codegen/vue2_master_inner/vue/StudentContactList
| @@ -48,9 +48,13 @@ | @@ -48,9 +48,13 @@ | ||
| 48 | import * as StudentApi from '@/api/infra/demo'; | 48 | import * as StudentApi from '@/api/infra/demo'; |
| 49 | export default { | 49 | export default { |
| 50 | name: "StudentContactList", | 50 | name: "StudentContactList", |
| 51 | - props:[ | ||
| 52 | - 'studentId' | ||
| 53 | - ],// 学生编号(主表的关联字段) | 51 | + props: { |
| 52 | + // 学生编号(主表的关联字段) | ||
| 53 | + studentId: { | ||
| 54 | + type: Number, | ||
| 55 | + default: undefined | ||
| 56 | + } | ||
| 57 | + }, | ||
| 54 | data() { | 58 | data() { |
| 55 | return { | 59 | return { |
| 56 | // 遮罩层 | 60 | // 遮罩层 |
yudao-module-infra/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherForm
| @@ -53,9 +53,13 @@ | @@ -53,9 +53,13 @@ | ||
| 53 | FileUpload, | 53 | FileUpload, |
| 54 | Editor, | 54 | Editor, |
| 55 | }, | 55 | }, |
| 56 | - props:[ | ||
| 57 | - 'studentId' | ||
| 58 | - ],// 学生编号(主表的关联字段) | 56 | + props: { |
| 57 | + // 学生编号(主表的关联字段) | ||
| 58 | + studentId: { | ||
| 59 | + type: Number, | ||
| 60 | + default: undefined | ||
| 61 | + } | ||
| 62 | + }, | ||
| 59 | data() { | 63 | data() { |
| 60 | return { | 64 | return { |
| 61 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | 65 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
yudao-module-infra/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherList
| @@ -48,9 +48,13 @@ | @@ -48,9 +48,13 @@ | ||
| 48 | import * as StudentApi from '@/api/infra/demo'; | 48 | import * as StudentApi from '@/api/infra/demo'; |
| 49 | export default { | 49 | export default { |
| 50 | name: "StudentTeacherList", | 50 | name: "StudentTeacherList", |
| 51 | - props:[ | ||
| 52 | - 'studentId' | ||
| 53 | - ],// 学生编号(主表的关联字段) | 51 | + props: { |
| 52 | + // 学生编号(主表的关联字段) | ||
| 53 | + studentId: { | ||
| 54 | + type: Number, | ||
| 55 | + default: undefined | ||
| 56 | + } | ||
| 57 | + }, | ||
| 54 | data() { | 58 | data() { |
| 55 | return { | 59 | return { |
| 56 | // 遮罩层 | 60 | // 遮罩层 |
yudao-module-infra/src/test/resources/codegen/vue2_master_inner/vue/index
| @@ -53,7 +53,7 @@ | @@ -53,7 +53,7 @@ | ||
| 53 | 批量删除 | 53 | 批量删除 |
| 54 | </el-button> | 54 | </el-button> |
| 55 | </el-col> | 55 | </el-col> |
| 56 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 56 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 57 | </el-row> | 57 | </el-row> |
| 58 | 58 | ||
| 59 | <el-table | 59 | <el-table |
| @@ -137,7 +137,7 @@ | @@ -137,7 +137,7 @@ | ||
| 137 | </el-table-column> | 137 | </el-table-column> |
| 138 | </el-table> | 138 | </el-table> |
| 139 | <!-- 分页组件 --> | 139 | <!-- 分页组件 --> |
| 140 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 140 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 141 | @pagination="getList"/> | 141 | @pagination="getList"/> |
| 142 | <!-- 对话框(添加 / 修改) --> | 142 | <!-- 对话框(添加 / 修改) --> |
| 143 | <StudentForm ref="formRef" @success="getList" /> | 143 | <StudentForm ref="formRef" @success="getList" /> |
yudao-module-infra/src/test/resources/codegen/vue2_master_normal/vue/StudentContactForm
| @@ -97,9 +97,13 @@ | @@ -97,9 +97,13 @@ | ||
| 97 | FileUpload, | 97 | FileUpload, |
| 98 | Editor, | 98 | Editor, |
| 99 | }, | 99 | }, |
| 100 | - props:[ | ||
| 101 | - 'studentId' | ||
| 102 | - ],// 学生编号(主表的关联字段) | 100 | + props: { |
| 101 | + // 学生编号(主表的关联字段) | ||
| 102 | + studentId: { | ||
| 103 | + type: Number, | ||
| 104 | + default: undefined | ||
| 105 | + } | ||
| 106 | + }, | ||
| 103 | data() { | 107 | data() { |
| 104 | return { | 108 | return { |
| 105 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | 109 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
yudao-module-infra/src/test/resources/codegen/vue2_master_normal/vue/StudentTeacherForm
| @@ -53,9 +53,13 @@ | @@ -53,9 +53,13 @@ | ||
| 53 | FileUpload, | 53 | FileUpload, |
| 54 | Editor, | 54 | Editor, |
| 55 | }, | 55 | }, |
| 56 | - props:[ | ||
| 57 | - 'studentId' | ||
| 58 | - ],// 学生编号(主表的关联字段) | 56 | + props: { |
| 57 | + // 学生编号(主表的关联字段) | ||
| 58 | + studentId: { | ||
| 59 | + type: Number, | ||
| 60 | + default: undefined | ||
| 61 | + } | ||
| 62 | + }, | ||
| 59 | data() { | 63 | data() { |
| 60 | return { | 64 | return { |
| 61 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | 65 | // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
yudao-module-infra/src/test/resources/codegen/vue2_master_normal/vue/index
| @@ -53,7 +53,7 @@ | @@ -53,7 +53,7 @@ | ||
| 53 | 批量删除 | 53 | 批量删除 |
| 54 | </el-button> | 54 | </el-button> |
| 55 | </el-col> | 55 | </el-col> |
| 56 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 56 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 57 | </el-row> | 57 | </el-row> |
| 58 | 58 | ||
| 59 | <el-table | 59 | <el-table |
| @@ -124,7 +124,7 @@ | @@ -124,7 +124,7 @@ | ||
| 124 | </el-table-column> | 124 | </el-table-column> |
| 125 | </el-table> | 125 | </el-table> |
| 126 | <!-- 分页组件 --> | 126 | <!-- 分页组件 --> |
| 127 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 127 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 128 | @pagination="getList"/> | 128 | @pagination="getList"/> |
| 129 | <!-- 对话框(添加 / 修改) --> | 129 | <!-- 对话框(添加 / 修改) --> |
| 130 | <StudentForm ref="formRef" @success="getList" /> | 130 | <StudentForm ref="formRef" @success="getList" /> |
yudao-module-infra/src/test/resources/codegen/vue2_one/vue/index
| @@ -53,7 +53,7 @@ | @@ -53,7 +53,7 @@ | ||
| 53 | 批量删除 | 53 | 批量删除 |
| 54 | </el-button> | 54 | </el-button> |
| 55 | </el-col> | 55 | </el-col> |
| 56 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 56 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 57 | </el-row> | 57 | </el-row> |
| 58 | 58 | ||
| 59 | <el-table | 59 | <el-table |
| @@ -124,7 +124,7 @@ | @@ -124,7 +124,7 @@ | ||
| 124 | </el-table-column> | 124 | </el-table-column> |
| 125 | </el-table> | 125 | </el-table> |
| 126 | <!-- 分页组件 --> | 126 | <!-- 分页组件 --> |
| 127 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 127 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 128 | @pagination="getList"/> | 128 | @pagination="getList"/> |
| 129 | <!-- 对话框(添加 / 修改) --> | 129 | <!-- 对话框(添加 / 修改) --> |
| 130 | <StudentForm ref="formRef" @success="getList" /> | 130 | <StudentForm ref="formRef" @success="getList" /> |
yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/vue/index
| @@ -61,7 +61,7 @@ | @@ -61,7 +61,7 @@ | ||
| 61 | 批量删除 | 61 | 批量删除 |
| 62 | </el-button> | 62 | </el-button> |
| 63 | </el-col> | 63 | </el-col> |
| 64 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 64 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 65 | </el-row> | 65 | </el-row> |
| 66 | <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> | 66 | <input ref="importFileRef" type="file" style="display: none" accept=".xls,.xlsx" @change="handleImportFileChange" /> |
| 67 | 67 | ||
| @@ -133,7 +133,7 @@ | @@ -133,7 +133,7 @@ | ||
| 133 | </el-table-column> | 133 | </el-table-column> |
| 134 | </el-table> | 134 | </el-table> |
| 135 | <!-- 分页组件 --> | 135 | <!-- 分页组件 --> |
| 136 | - <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" | 136 | + <Pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" |
| 137 | @pagination="getList"/> | 137 | @pagination="getList"/> |
| 138 | <!-- 对话框(添加 / 修改) --> | 138 | <!-- 对话框(添加 / 修改) --> |
| 139 | <StudentForm ref="formRef" @success="getList" /> | 139 | <StudentForm ref="formRef" @success="getList" /> |
yudao-module-infra/src/test/resources/codegen/vue2_tree/vue/index
| @@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
| 26 | 展开/折叠 | 26 | 展开/折叠 |
| 27 | </el-button> | 27 | </el-button> |
| 28 | </el-col> | 28 | </el-col> |
| 29 | - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> | 29 | + <RightToolbar :showSearch.sync="showSearch" @queryTable="getList"></RightToolbar> |
| 30 | </el-row> | 30 | </el-row> |
| 31 | 31 | ||
| 32 | <el-table | 32 | <el-table |
yudao-module-infra/src/test/resources/codegen/vue3_master_erp/vue/StudentContactForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_erp/vue/StudentForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_inner/vue/StudentContactForm
| @@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
| 56 | <el-radio | 56 | <el-radio |
| 57 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 57 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 58 | :key="dict.value" | 58 | :key="dict.value" |
| 59 | - :label="dict.value" | 59 | + :value="dict.value" |
| 60 | > | 60 | > |
| 61 | {{ dict.label }} | 61 | {{ dict.label }} |
| 62 | </el-radio> | 62 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_inner/vue/StudentForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherForm
| @@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
| 35 | <el-radio | 35 | <el-radio |
| 36 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 36 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 37 | :key="dict.value" | 37 | :key="dict.value" |
| 38 | - :label="dict.value" | 38 | + :value="dict.value" |
| 39 | > | 39 | > |
| 40 | {{ dict.label }} | 40 | {{ dict.label }} |
| 41 | </el-radio> | 41 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_normal/vue/StudentContactForm
| @@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
| 56 | <el-radio | 56 | <el-radio |
| 57 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 57 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 58 | :key="dict.value" | 58 | :key="dict.value" |
| 59 | - :label="dict.value" | 59 | + :value="dict.value" |
| 60 | > | 60 | > |
| 61 | {{ dict.label }} | 61 | {{ dict.label }} |
| 62 | </el-radio> | 62 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_normal/vue/StudentForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_master_normal/vue/StudentTeacherForm
| @@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
| 35 | <el-radio | 35 | <el-radio |
| 36 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 36 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 37 | :key="dict.value" | 37 | :key="dict.value" |
| 38 | - :label="dict.value" | 38 | + :value="dict.value" |
| 39 | > | 39 | > |
| 40 | {{ dict.label }} | 40 | {{ dict.label }} |
| 41 | </el-radio> | 41 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_one/vue/StudentForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |
yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/vue/StudentForm
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | <el-radio | 36 | <el-radio |
| 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" | 37 | v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)" |
| 38 | :key="dict.value" | 38 | :key="dict.value" |
| 39 | - :label="dict.value" | 39 | + :value="dict.value" |
| 40 | > | 40 | > |
| 41 | {{ dict.label }} | 41 | {{ dict.label }} |
| 42 | </el-radio> | 42 | </el-radio> |