Commit 57138d7995379d5dd0ad371d4b29e0fa1f996fad

Authored by puhui999
1 parent b0f4a252

【功能完善】INFRA:代码生成 vben5 antd 主子表 normal 模版

yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/form.vue.vm
... ... @@ -112,10 +112,11 @@ const [Modal, modalApi] = useVbenModal({
112 112 #if ($subTable.subJoinMany) ## 一对多
113 113 ## TODO 列表值校验?
114 114 #else
115   - const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate();
116   - if (!${subClassNameVar}Valid) {
117   - subTabsName.value = '${subClassNameVar}';
118   - return;
  115 + try {
  116 + await ${subClassNameVar}FormRef.value?.validate()
  117 + } catch (e) {
  118 + subTabsName.value = '${subClassNameVar}'
  119 + return
119 120 }
120 121 #end
121 122 #end
... ... @@ -134,7 +135,7 @@ const [Modal, modalApi] = useVbenModal({
134 135 #if ($subTable.subJoinMany)
135 136 data.${subClassNameVar}s = ${subClassNameVar}FormRef.value?.getData();
136 137 #else
137   - data.${subClassNameVar} = await ${subClassNameVar}FormRef.value?.getValues();
  138 + data.${subClassNameVar} = ${subClassNameVar}FormRef.value?.getValues();
138 139 #end
139 140 #end
140 141 #end
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm
... ... @@ -7,19 +7,19 @@
7 7 <script lang="ts" setup>
8 8 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
9 9  
  10 + import { message, Tabs, Form, Input, Textarea,Button, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker } from 'ant-design-vue';
10 11 import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
11 12 import { $t } from '#/locales';
  13 + import { DICT_TYPE, getDictOptions } from '#/utils/dict';
12 14  
13 15 #if ($subTable.subJoinMany) ## 一对多
  16 +import type { VxeTableInstance } from 'vxe-table';
14 17 import { Plus } from "@vben/icons";
15   -import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
16   -import type { OnActionClickParams } from '#/adapter/vxe-table';
17   -import { useVbenVxeGrid } from '#/adapter/vxe-table';
18   -import { use${subSimpleClassName}GridEditColumns } from '../data';
  18 +import { VxeColumn, VxeTable } from 'vxe-table';
19 19 import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
20 20 #else
21   -import { useVbenForm } from '#/adapter/form';
22   -import { use${subSimpleClassName}FormSchema } from '../data';
  21 +import type { Rule } from 'ant-design-vue/es/form';
  22 +import { Tinymce as RichTextarea } from '#/components/tinymce';
23 23 import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
24 24 #end
25 25  
... ... @@ -28,57 +28,27 @@ const props = defineProps&lt;{
28 28 }>()
29 29  
30 30 #if ($subTable.subJoinMany) ## 一对多
31   -/** 表格操作按钮的回调函数 */
32   -function onActionClick({
33   - code,
34   - row,
35   -}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
36   - switch (code) {
37   - case 'delete': {
38   - onDelete(row);
39   - break;
40   - }
41   - }
42   -}
43   -
44   -const [Grid, gridApi] = useVbenVxeGrid({
45   -gridOptions: {
46   - columns: use${subSimpleClassName}GridEditColumns(onActionClick),
47   - border: true,
48   - showOverflow: true,
49   - autoResize: true,
50   - keepSource: true,
51   - rowConfig: {
52   - keyField: 'id',
53   - },
54   - pagerConfig: {
55   - enabled: false,
56   - },
57   - toolbarConfig: {
58   - enabled: false,
59   - },
60   -},
61   -});
62   -
  31 +const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
  32 +const tableRef = ref<VxeTableInstance>();
63 33 /** 添加${subTable.classComment} */
64 34 const onAdd = async () => {
65   - await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  35 + await tableRef.value?.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
66 36 }
67 37  
68 38 /** 删除${subTable.classComment} */
69 39 const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
70   - await gridApi.grid.remove(row);
  40 + await tableRef.value?.remove(row);
71 41 }
72 42  
73 43 /** 提供获取表格数据的方法供父组件调用 */
74 44 defineExpose({
75 45 getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
76   - const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
77   - const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
78   - const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  46 + const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[];
  47 + const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  48 + const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
79 49 return data
80 50 .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
81   - .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
  51 + ?.concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
82 52 },
83 53 });
84 54  
... ... @@ -89,32 +59,35 @@ watch(
89 59 if (!val) {
90 60 return;
91 61 }
92   - await nextTick();
93   - await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  62 + list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
94 63 },
95 64 { immediate: true },
96 65 );
97 66 #else
98   -const [Form, formApi] = useVbenForm({
99   - commonConfig: {
100   - componentProps: {
101   - class: 'w-full',
102   - },
103   - formItemClass: 'col-span-2',
104   - labelWidth: 80,
105   - },
106   - layout: 'horizontal',
107   - schema: use${subSimpleClassName}FormSchema(),
108   - showDefaultActions: false
  67 +const formRef = ref();
  68 +const formData = ref<Partial<${simpleClassName}Api.${subSimpleClassName}>>({
  69 + #foreach ($column in $subColumns)
  70 + #if ($column.createOperation || $column.updateOperation)
  71 + #if ($column.htmlType == "checkbox")
  72 + $column.javaField: [],
  73 + #else
  74 + $column.javaField: undefined,
  75 + #end
  76 + #end
  77 + #end
109 78 });
110   -
  79 +const rules: Record<string, Rule[]> = {
  80 + #foreach ($column in $subColumns)
  81 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  82 + #set($comment=$column.columnComment)
  83 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
  84 + #end
  85 + #end
  86 +};
111 87 /** 暴露出表单校验方法和表单值获取方法 */
112 88 defineExpose({
113   - validate: async () => {
114   - const { valid } = await formApi.validate();
115   - return valid;
116   - },
117   - getValues: formApi.getValues,
  89 + validate: async () => await formRef.value?.validate(),
  90 + getValues: ()=> formData.value,
118 91 });
119 92  
120 93 /** 监听主表的关联字段的变化,加载对应的子表数据 */
... ... @@ -125,7 +98,7 @@ watch(
125 98 return;
126 99 }
127 100 await nextTick();
128   - await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  101 + formData.value = await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
129 102 },
130 103 { immediate: true },
131 104 );
... ... @@ -134,66 +107,232 @@ watch(
134 107  
135 108 <template>
136 109 #if ($subTable.subJoinMany) ## 一对多
137   - <Grid class="mx-4">
  110 + <vxe-table ref="tableRef" :data="list" show-overflow class="mx-4">
138 111 #foreach($column in $subColumns)
139 112 #if ($column.createOperation || $column.updateOperation)
  113 + #set ($comment = $column.columnComment)
140 114 #set ($javaField = $column.javaField)
  115 + #set ($javaType = $column.javaType)
  116 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  117 + #set ($dictMethod = "number")
  118 + #elseif ($javaType == "String")
  119 + #set ($dictMethod = "string")
  120 + #elseif ($javaType == "Boolean")
  121 + #set ($dictMethod = "boolean")
  122 + #end
141 123 #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
142 124 #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
143   - <template #${javaField}="{ row }">
144   - <Input v-model:value="row.${javaField}" />
145   - </template>
  125 + <vxe-column field="${javaField}" title="${comment}" align="center">
  126 + <template #default="{row}">
  127 + <Input v-model:value="row.${javaField}" />
  128 + </template>
  129 + </vxe-column>
  130 + #elseif($column.htmlType == "imageUpload")## 图片上传
  131 + <vxe-column field="${javaField}" title="${comment}" align="center">
  132 + <template #default="{row}">
  133 + <ImageUpload v-model:value="row.${javaField}" />
  134 + </template>
  135 + </vxe-column>
  136 + #elseif($column.htmlType == "fileUpload")## 文件上传
  137 + <vxe-column field="${javaField}" title="${comment}" align="center">
  138 + <template #default="{row}">
  139 + <FileUpload v-model:value="row.${javaField}" />
  140 + </template>
  141 + </vxe-column>
  142 + #elseif($column.htmlType == "select")## 下拉框
  143 + <vxe-column field="${javaField}" title="${comment}" align="center">
  144 + <template #default="{row}">
  145 + <Select v-model:value="row.${javaField}" placeholder="请选择${comment}">
  146 + #if ("" != $dictType)## 有数据字典
  147 + <Select.Option
  148 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  149 + :key="dict.value"
  150 + :value="dict.value"
  151 + >
  152 + {{ dict.label }}
  153 + </Select.Option>
  154 + #else##没数据字典
  155 + <Select.Option label="请选择字典生成" value="" />
  156 + #end
  157 + </Select>
  158 + </template>
  159 + </vxe-column>
  160 + #elseif($column.htmlType == "checkbox")## 多选框
  161 + <vxe-column field="${javaField}" title="${comment}" align="center">
  162 + <template #default="{row}">
  163 + <CheckboxGroup v-model:value="row.${javaField}">
  164 + #if ("" != $dictType)## 有数据字典
  165 + <Checkbox
  166 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  167 + :key="dict.value"
  168 + :value="dict.value"
  169 + >
  170 + {{ dict.label }}
  171 + </Checkbox>
  172 + #else##没数据字典
  173 + <Checkbox label="请选择字典生成" />
  174 + #end
  175 + </CheckboxGroup>
  176 + </template>
  177 + </vxe-column>
  178 + #elseif($column.htmlType == "radio")## 单选框
  179 + <vxe-column field="${javaField}" title="${comment}" align="center">
  180 + <template #default="{row}">
  181 + <RadioGroup v-model:value="row.${javaField}">
  182 + #if ("" != $dictType)## 有数据字典
  183 + <Radio
  184 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  185 + :key="dict.value"
  186 + :value="dict.value"
  187 + >
  188 + {{ dict.label }}
  189 + </Radio>
  190 + #else##没数据字典
  191 + <Radio value="1">请选择字典生成</Radio>
  192 + #end
  193 + </RadioGroup>
  194 + </template>
  195 + </vxe-column>
  196 + #elseif($column.htmlType == "datetime")## 时间框
  197 + <vxe-column field="${javaField}" title="${comment}" align="center">
  198 + <template #default="{row}">
  199 + <DatePicker
  200 + v-model:value="row.${javaField}"
  201 + :showTime="true"
  202 + format="YYYY-MM-DD HH:mm:ss"
  203 + valueFormat='x'
  204 + />
  205 + </template>
  206 + </vxe-column>
  207 + #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框
  208 + <vxe-column field="${javaField}" title="${comment}" align="center">
  209 + <template #default="{row}">
  210 + <Textarea v-model:value="row.${javaField}" />
  211 + </template>
  212 + </vxe-column>
  213 + #end
  214 + #end
  215 + #end
  216 + <vxe-column field="operation" title="操作" align="center">
  217 + <template #default="{row}">
  218 + <Button
  219 + size="small"
  220 + type="link"
  221 + danger
  222 + @click="onDelete(row as any)"
  223 + v-access:code="['${permissionPrefix}:delete']"
  224 + >
  225 + {{ $t('ui.actionTitle.delete') }}
  226 + </Button>
  227 + </template>
  228 + </vxe-column>
  229 + </vxe-table>
  230 + <div class="flex justify-center mt-4">
  231 + <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${permissionPrefix}:create']">
  232 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  233 + </Button>
  234 + </div>
  235 +#else
  236 + <Form
  237 + ref="formRef"
  238 + class="mx-4"
  239 + :model="formData"
  240 + :rules="rules"
  241 + :label-col="{ span: 5 }"
  242 + :wrapper-col="{ span: 18 }"
  243 + >
  244 + #foreach($column in $subColumns)
  245 + #if ($column.createOperation || $column.updateOperation)
  246 + #set ($dictType = $column.dictType)
  247 + #set ($javaField = $column.javaField)
  248 + #set ($javaType = $column.javaType)
  249 + #set ($comment = $column.columnComment)
  250 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  251 + #set ($dictMethod = "number")
  252 + #elseif ($javaType == "String")
  253 + #set ($dictMethod = "string")
  254 + #elseif ($javaType == "Boolean")
  255 + #set ($dictMethod = "boolean")
  256 + #end
  257 + #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  258 + <Form.Item label="${comment}" name="${javaField}">
  259 + <Input v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  260 + </Form.Item>
146 261 #elseif($column.htmlType == "imageUpload")## 图片上传
147   - <template #${javaField}="{ row }">
148   - <UploadImg v-model:value="row.${javaField}" />
149   - </template>
  262 + <Form.Item label="${comment}" name="${javaField}">
  263 + <ImageUpload v-model:value="formData.${javaField}" />
  264 + </Form.Item>
150 265 #elseif($column.htmlType == "fileUpload")## 文件上传
151   - <template #${javaField}="{ row }">
152   - <UploadFile v-model:value="row.${javaField}" />
153   - </template>
  266 + <Form.Item label="${comment}" name="${javaField}">
  267 + <FileUpload v-model:value="formData.${javaField}" />
  268 + </Form.Item>
154 269 #elseif($column.htmlType == "editor")## 文本编辑器
155   - <template #${javaField}="{ row }">
156   - <Textarea v-model:value="row.${javaField}" />
157   - </template>
  270 + <Form.Item label="${comment}" name="${javaField}">
  271 + <RichTextarea v-model="formData.${javaField}" height="500px" />
  272 + </Form.Item>
158 273 #elseif($column.htmlType == "select")## 下拉框
159   - <template #${javaField}="{ row, column }">
160   - <Select v-model:value="row.${javaField}" class="w-full">
161   - <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
162   - {{ option.label }}
163   - </Select.Option>
  274 + <Form.Item label="${comment}" name="${javaField}">
  275 + <Select v-model:value="formData.${javaField}" placeholder="请选择${comment}">
  276 + #if ("" != $dictType)## 有数据字典
  277 + <Select.Option
  278 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  279 + :key="dict.value"
  280 + :value="dict.value"
  281 + >
  282 + {{ dict.label }}
  283 + </Select.Option>
  284 + #else##没数据字典
  285 + <Select.Option label="请选择字典生成" value="" />
  286 + #end
164 287 </Select>
165   - </template>
  288 + </Form.Item>
166 289 #elseif($column.htmlType == "checkbox")## 多选框
167   - <template #${javaField}="{ row, column }">
168   - <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
169   - </template>
  290 + <Form.Item label="${comment}" name="${javaField}">
  291 + <CheckboxGroup v-model:value="formData.${javaField}">
  292 + #if ("" != $dictType)## 有数据字典
  293 + <Checkbox
  294 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  295 + :key="dict.value"
  296 + :value="dict.value"
  297 + >
  298 + {{ dict.label }}
  299 + </Checkbox>
  300 + #else##没数据字典
  301 + <Checkbox label="请选择字典生成" />
  302 + #end
  303 + </CheckboxGroup>
  304 + </Form.Item>
170 305 #elseif($column.htmlType == "radio")## 单选框
171   - <template #${javaField}="{ row, column }">
172   - <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
173   - </template>
  306 + <Form.Item label="${comment}" name="${javaField}">
  307 + <RadioGroup v-model:value="formData.${javaField}">
  308 + #if ("" != $dictType)## 有数据字典
  309 + <Radio
  310 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  311 + :key="dict.value"
  312 + :value="dict.value"
  313 + >
  314 + {{ dict.label }}
  315 + </Radio>
  316 + #else##没数据字典
  317 + <Radio value="1">请选择字典生成</Radio>
  318 + #end
  319 + </RadioGroup>
  320 + </Form.Item>
174 321 #elseif($column.htmlType == "datetime")## 时间框
175   - <template #${javaField}="{ row }">
  322 + <Form.Item label="${comment}" name="${javaField}">
176 323 <DatePicker
177   - v-model:value="row.${javaField}"
178   - :showTime="true"
179   - format="YYYY-MM-DD HH:mm:ss"
180   - valueFormat='x'
  324 + v-model:value="formData.${javaField}"
  325 + valueFormat="x"
  326 + placeholder="选择${comment}"
181 327 />
182   - </template>
  328 + </Form.Item>
183 329 #elseif($column.htmlType == "textarea")## 文本框
184   - <template #${javaField}="{ row }">
185   - <Textarea v-model:value="row.${javaField}" />
186   - </template>
  330 + <Form.Item label="${comment}" name="${javaField}">
  331 + <Textarea v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  332 + </Form.Item>
187 333 #end
188 334 #end
189 335 #end
190   - </Grid>
191   - <div class="flex justify-center -mt-4">
192   - <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
193   - {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
194   - </Button>
195   - </div>
196   -#else
197   - <Form class="mx-4" />
  336 + </Form>
198 337 #end
199 338 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm
... ... @@ -13,6 +13,7 @@
13 13 #if ($subTable.subJoinMany) ## 一对多
14 14 import { Plus } from "@vben/icons";
15 15 import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
  16 +import { ImageUpload, FileUpload } from "#/components/upload";
16 17 import type { OnActionClickParams } from '#/adapter/vxe-table';
17 18 import { useVbenVxeGrid } from '#/adapter/vxe-table';
18 19 import { use${subSimpleClassName}GridEditColumns } from '../data';
... ... @@ -145,15 +146,11 @@ watch(
145 146 </template>
146 147 #elseif($column.htmlType == "imageUpload")## 图片上传
147 148 <template #${javaField}="{ row }">
148   - <UploadImg v-model:value="row.${javaField}" />
  149 + <ImageUpload v-model:value="row.${javaField}" />
149 150 </template>
150 151 #elseif($column.htmlType == "fileUpload")## 文件上传
151 152 <template #${javaField}="{ row }">
152   - <UploadFile v-model:value="row.${javaField}" />
153   - </template>
154   - #elseif($column.htmlType == "editor")## 文本编辑器
155   - <template #${javaField}="{ row }">
156   - <Textarea v-model:value="row.${javaField}" />
  153 + <FileUpload v-model:value="row.${javaField}" />
157 154 </template>
158 155 #elseif($column.htmlType == "select")## 下拉框
159 156 <template #${javaField}="{ row, column }">
... ... @@ -180,7 +177,7 @@ watch(
180 177 valueFormat='x'
181 178 />
182 179 </template>
183   - #elseif($column.htmlType == "textarea")## 文本框
  180 + #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框
184 181 <template #${javaField}="{ row }">
185 182 <Textarea v-model:value="row.${javaField}" />
186 183 </template>
... ...