Commit 08eb75ea0d8adedef82e5833bd1979dac0c66c12

Authored by 芋道源码
Committed by Gitee
2 parents 7c940854 e1fa4e1a

!1326 代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成

Merge pull request !1326 from puhui999/master-jdk17
Showing 11 changed files with 1123 additions and 80 deletions
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
... ... @@ -146,23 +146,24 @@ public class CodegenEngine {
146 146 vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
147 147 // VUE3_VBEN5_ANTD_SCHEMA
148 148 // TODO @puhui999:目录改成 vue3_vben5_antd;然后里面有 schema(目前我们在写的)和 general(你微信里提的,原生的,感觉也要搞!)
149   - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/data.ts"),
  149 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/data.ts"),
150 150 vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts"))
151   - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/index.vue"),
  151 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/index.vue"),
152 152 vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
153   - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/form.vue"),
  153 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/form.vue"),
154 154 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue"))
155   - .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("api/api.ts"),
  155 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"),
156 156 vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
157   - // 主子表模板配置 - Vue3 vben5 schema 模版
158   - //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_data.ts"),
159   - // vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts"))
160   - //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_index.vue"),
161   - // vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
162   - //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/master_slave_form.vue"),
163   - // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue"))
164   - //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/sub_table.vue"),
165   - // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/sub_table.vue"))
  157 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑
  158 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  159 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑
  160 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  161 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑
  162 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}Form.vue"))
  163 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑
  164 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
  165 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑
  166 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName}List.vue"))
166 167 .build();
167 168  
168 169 @Resource
... ... @@ -515,8 +516,12 @@ public class CodegenEngine {
515 516 return "codegen/vue3_vben/" + path + ".vm";
516 517 }
517 518  
518   - private static String vue3VbenNextSchemaTemplatePath(String path) {
519   - return "codegen/vue3_vben_next/schema/" + path + ".vm";
  519 + private static String vue3Vben5AntdSchemaTemplatePath(String path) {
  520 + return "codegen/vue3_vben5_antd/schema/" + path + ".vm";
  521 + }
  522 +
  523 + private static String vue3Vben5AntdGeneralTemplatePath(String path) {
  524 + return "codegen/vue3_vben5_antd/general/" + path + ".vm";
520 525 }
521 526  
522 527 private static boolean isSubTemplate(String path) {
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/ant_design_vue/index.vue.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/index.vue.vm
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/api/api.ts.vm
... ... @@ -4,6 +4,26 @@ import { requestClient } from '#/api/request';
4 4 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
5 5  
6 6 export namespace ${simpleClassName}Api {
  7 +## 特殊:主子表专属逻辑
  8 +#foreach ($subTable in $subTables)
  9 + #set ($index = $foreach.count - 1)
  10 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  11 + #set ($subColumns = $subColumnsList.get($index))##当前字段数组
  12 + /** ${subTable.classComment}信息 */
  13 + export interface ${subSimpleClassName} {
  14 + #foreach ($column in $subColumns)
  15 + #if ($column.createOperation || $column.updateOperation)
  16 + #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  17 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  18 + #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  19 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: Date; // ${column.columnComment}
  20 + #else
  21 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  22 + #end
  23 + #end
  24 + #end
  25 + }
  26 +#end
7 27 /** ${table.classComment}信息 */
8 28 export interface ${simpleClassName} {
9 29 #foreach ($column in $columns)
... ... @@ -20,6 +40,18 @@ export namespace ${simpleClassName}Api {
20 40 #if ( $table.templateType == 2 )
21 41 children?: ${simpleClassName}[];
22 42 #end
  43 +## 特殊:主子表专属逻辑
  44 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  45 + #foreach ($subTable in $subTables)
  46 + #set ($index = $foreach.count - 1)
  47 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  48 + #if ( $subTable.subJoinMany )
  49 + ${subSimpleClassName.toLowerCase()}s?: ${subSimpleClassName}[]
  50 + #else
  51 + ${subSimpleClassName.toLowerCase()}?: ${subSimpleClassName}
  52 + #end
  53 + #end
  54 +#end
23 55 }
24 56 }
25 57  
... ... @@ -76,31 +108,31 @@ export function export${simpleClassName}(params: any) {
76 108 #if ( $table.templateType == 11 )
77 109 /** 获得${subTable.classComment}分页 */
78 110 export function get${subSimpleClassName}Page(params: PageParam) {
79   - return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
  111 + return requestClient.get<PageResult<${simpleClassName}Api.${subSimpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
80 112 }
81 113 ## 情况二:非 MASTER_ERP 时,需要列表查询子表
82 114 #else
83 115 #if ( $subTable.subJoinMany )
84 116 /** 获得${subTable.classComment}列表 */
85 117 export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
86   - return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  118 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
87 119 }
88 120 #else
89 121 /** 获得${subTable.classComment} */
90 122 export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
91   - return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  123 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
92 124 }
93 125 #end
94 126 #end
95 127 ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
96 128 #if ( $table.templateType == 11 )
97 129 /** 新增${subTable.classComment} */
98   -export function create${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  130 +export function create${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
99 131 return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
100 132 }
101 133  
102 134 /** 修改${subTable.classComment} */
103   -export function update${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  135 +export function update${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
104 136 return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
105 137 }
106 138  
... ... @@ -111,7 +143,7 @@ export function delete${subSimpleClassName}(id: number) {
111 143  
112 144 /** 获得${subTable.classComment} */
113 145 export function get${subSimpleClassName}(id: number) {
114   - return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
  146 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
115 147 }
116 148 #end
117 149 #end
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
... ... @@ -9,6 +9,7 @@ import { get${simpleClassName}List } from &#39;#/api/${table.moduleName}/${simpleCla
9 9 import { handleTree } from '#/utils/tree';
10 10 #end
11 11 import { DICT_TYPE, getDictOptions } from '#/utils/dict';
  12 +import { getRangePickerDefaultProps } from '#/utils/date';
12 13 import { useAccess } from '@vben/access';
13 14  
14 15 const { hasAccessByCodes } = useAccess();
... ... @@ -166,13 +167,13 @@ export function useGridFormSchema(): VbenFormSchema[] {
166 167 {
167 168 fieldName: '${javaField}',
168 169 label: '${comment}',
169   - #if ($column.htmlType == "input")
  170 + #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
170 171 component: 'Input',
171 172 componentProps: {
172 173 allowClear: true,
173 174 placeholder: '请输入${comment}',
174 175 },
175   - #elseif ($column.htmlType == "select")
  176 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
176 177 component: 'Select',
177 178 componentProps: {
178 179 allowClear: true,
... ... @@ -183,19 +184,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
183 184 #end
184 185 placeholder: '请选择${comment}',
185 186 },
186   - #elseif ($column.htmlType == "radio")
187   - component: 'Select',
188   - componentProps: {
189   - allowClear: true,
190   - #if ("" != $dictType)## 设置了 dictType 数据字典的情况
191   - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
192   - #else## 未设置 dictType 数据字典的情况
193   - options: [],
194   - #end
195   - },
196 187 #elseif($column.htmlType == "datetime")
197 188 component: 'RangePicker',
198 189 componentProps: {
  190 + ...getRangePickerDefaultProps(),
199 191 allowClear: true,
200 192 },
201 193 #end
... ... @@ -210,6 +202,9 @@ export function useGridColumns(
210 202 onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>,
211 203 ): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
212 204 return [
  205 +#if ($table.templateType == 12) ## 内嵌情况
  206 + { type: 'expand', width: 80, slots: { content: 'expand_content' } },
  207 +#end
213 208 #foreach($column in $columns)
214 209 #if ($column.listOperationResult)
215 210 #set ($dictType = $column.dictType)
... ... @@ -237,7 +232,7 @@ export function useGridColumns(
237 232 field: 'operation',
238 233 title: '操作',
239 234 minWidth: 200,
240   - align: 'right',
  235 + align: 'center',
241 236 fixed: 'right',
242 237 headerAlign: 'center',
243 238 showOverflow: false,
... ... @@ -251,7 +246,7 @@ export function useGridColumns(
251 246 options: [
252 247 #if (${table.templateType} == 2)## 树表特有操作
253 248 {
254   - code: 'add_child',
  249 + code: 'append',
255 250 text: '新增下级',
256 251 show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']),
257 252 },
... ... @@ -274,3 +269,386 @@ export function useGridColumns(
274 269 },
275 270 ];
276 271 }
  272 +
  273 +## 标准模式和内嵌模式时,主子关系一对一则生成表单schema,一对多则生成列表schema(内嵌模式时表单schema也要生成)。erp 模式时都生成
  274 +## 特殊:主子表专属逻辑
  275 +#foreach ($subTable in $subTables)
  276 + #set ($index = $foreach.count - 1)
  277 + #set ($subColumns = $subColumnsList.get($index))##当前字段数组
  278 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  279 + #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  280 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  281 +// ==================== 子表($subTable.classComment) ====================
  282 +#if ($table.templateType == 11) ## erp 情况
  283 +/** 新增/修改的表单 */
  284 +export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
  285 + return [
  286 + {
  287 + fieldName: 'id',
  288 + component: 'Input',
  289 + dependencies: {
  290 + triggerFields: [''],
  291 + show: () => false,
  292 + },
  293 + },
  294 + #foreach($column in $subColumns)
  295 + #if ($column.createOperation || $column.updateOperation)
  296 + #if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  297 + #set ($dictType = $column.dictType)
  298 + #set ($javaType = $column.javaType)
  299 + #set ($javaField = $column.javaField)
  300 + #set ($comment = $column.columnComment)
  301 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  302 + #set ($dictMethod = "number")
  303 + #elseif ($javaType == "String")
  304 + #set ($dictMethod = "string")
  305 + #elseif ($javaType == "Boolean")
  306 + #set ($dictMethod = "boolean")
  307 + #end
  308 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  309 + #else
  310 + {
  311 + fieldName: '${javaField}',
  312 + label: '${comment}',
  313 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  314 + rules: 'required',
  315 + #end
  316 + #if ($column.htmlType == "input")
  317 + component: 'Input',
  318 + componentProps: {
  319 + placeholder: '请输入${comment}',
  320 + },
  321 + #elseif($column.htmlType == "imageUpload")## 图片上传
  322 + component: 'FileUpload',
  323 + componentProps: {
  324 + fileType: 'image',
  325 + maxCount: 1,
  326 + },
  327 + #elseif($column.htmlType == "fileUpload")## 文件上传
  328 + component: 'FileUpload',
  329 + componentProps: {
  330 + fileType: 'file',
  331 + maxCount: 1,
  332 + },
  333 + #elseif($column.htmlType == "editor")## 文本编辑器
  334 + component: 'Editor',
  335 + #elseif($column.htmlType == "select")## 下拉框
  336 + component: 'Select',
  337 + componentProps: {
  338 + #if ("" != $dictType)## 有数据字典
  339 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  340 + #else##没数据字典
  341 + options: [],
  342 + #end
  343 + placeholder: '请选择${comment}',
  344 + class: 'w-full',
  345 + },
  346 + #elseif($column.htmlType == "checkbox")## 多选框
  347 + component: 'Checkbox',
  348 + componentProps: {
  349 + #if ("" != $dictType)## 有数据字典
  350 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  351 + #else##没数据字典
  352 + options: [],
  353 + #end
  354 + },
  355 + #elseif($column.htmlType == "radio")## 单选框
  356 + component: 'RadioGroup',
  357 + componentProps: {
  358 + #if ("" != $dictType)## 有数据字典
  359 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  360 + #else##没数据字典
  361 + options: [],
  362 + #end
  363 + buttonStyle: 'solid',
  364 + optionType: 'button',
  365 + },
  366 + #elseif($column.htmlType == "datetime")## 时间框
  367 + component: 'DatePicker',
  368 + componentProps: {
  369 + showTime: true,
  370 + format: 'YYYY-MM-DD HH:mm:ss',
  371 + valueFormat: 'x',
  372 + },
  373 + #elseif($column.htmlType == "textarea")## 文本域
  374 + component: 'Textarea',
  375 + componentProps: {
  376 + placeholder: '请输入${comment}',
  377 + },
  378 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  379 + component: 'InputNumber',
  380 + componentProps: {
  381 + min: 0,
  382 + class: 'w-full',
  383 + controlsPosition: 'right',
  384 + placeholder: '请输入${comment}',
  385 + },
  386 + #end
  387 + },
  388 + #end
  389 + #end
  390 + #end
  391 + #end
  392 + ];
  393 +}
  394 +/** 列表的字段 */
  395 +export function use${subSimpleClassName}GridColumns(
  396 + onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
  397 +): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  398 + return [
  399 + #foreach($column in $subColumns)
  400 + #if ($column.listOperationResult)
  401 + #set ($dictType = $column.dictType)
  402 + #set ($javaField = $column.javaField)
  403 + #set ($comment = $column.columnComment)
  404 + {
  405 + field: '${javaField}',
  406 + title: '${comment}',
  407 + minWidth: 120,
  408 + #if ($column.javaType == "LocalDateTime")## 时间类型
  409 + formatter: 'formatDateTime',
  410 + #elseif("" != $dictType)## 数据字典
  411 + cellRender: {
  412 + name: 'CellDict',
  413 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  414 + },
  415 + #end
  416 + },
  417 + #end
  418 + #end
  419 + {
  420 + field: 'operation',
  421 + title: '操作',
  422 + minWidth: 200,
  423 + align: 'center',
  424 + fixed: 'right',
  425 + headerAlign: 'center',
  426 + showOverflow: false,
  427 + cellRender: {
  428 + attrs: {
  429 + nameField: '${columns[0].javaField}',
  430 + nameTitle: '${subTable.classComment}',
  431 + onClick: onActionClick,
  432 + },
  433 + name: 'CellOperation',
  434 + options: [
  435 + {
  436 + code: 'edit',
  437 + show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
  438 + },
  439 + {
  440 + code: 'delete',
  441 + show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
  442 + },
  443 + ],
  444 + },
  445 + },
  446 + ];
  447 +}
  448 +#else
  449 + #if ($subTable.subJoinMany) ## 一对多
  450 + /** 新增/修改列表的字段 */
  451 + export function use${subSimpleClassName}GridEditColumns(
  452 + onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
  453 + ): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  454 + return [
  455 + #foreach($column in $subColumns)
  456 + #if ($column.createOperation || $column.updateOperation)
  457 + #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  458 + #set ($dictType = $column.dictType)
  459 + #set ($javaField = $column.javaField)
  460 + #set ($comment = $column.columnComment)
  461 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  462 + #set ($dictMethod = "number")
  463 + #elseif ($javaType == "String")
  464 + #set ($dictMethod = "string")
  465 + #elseif ($javaType == "Boolean")
  466 + #set ($dictMethod = "boolean")
  467 + #end
  468 + {
  469 + field: '${javaField}',
  470 + title: '${comment}',
  471 + minWidth: 120,
  472 + slots: { default: '${javaField}' },
  473 + #if ($column.htmlType == "select" || $column.htmlType == "checkbox" || $column.htmlType == "radio")
  474 + #if ("" != $dictType)## 有数据字典
  475 + params: {
  476 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  477 + },
  478 + #else
  479 + params: {
  480 + options: [],
  481 + },
  482 + #end
  483 + #end
  484 + },
  485 + #end
  486 + #end
  487 + #end
  488 + {
  489 + field: 'operation',
  490 + title: '操作',
  491 + minWidth: 60,
  492 + align: 'center',
  493 + fixed: 'right',
  494 + headerAlign: 'center',
  495 + showOverflow: false,
  496 + cellRender: {
  497 + attrs: {
  498 + nameField: '${columns[0].javaField}',
  499 + nameTitle: '${table.classComment}',
  500 + onClick: onActionClick,
  501 + },
  502 + name: 'CellOperation',
  503 + options: [
  504 + {
  505 + code: 'delete',
  506 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
  507 + },
  508 + ],
  509 + },
  510 + },
  511 + ];
  512 + }
  513 + #else
  514 + /** 新增/修改的表单 */
  515 + export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
  516 + return [
  517 + {
  518 + fieldName: 'id',
  519 + component: 'Input',
  520 + dependencies: {
  521 + triggerFields: [''],
  522 + show: () => false,
  523 + },
  524 + },
  525 + #foreach($column in $subColumns)
  526 + #if ($column.createOperation || $column.updateOperation)
  527 + #if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  528 + #set ($dictType = $column.dictType)
  529 + #set ($javaType = $column.javaType)
  530 + #set ($javaField = $column.javaField)
  531 + #set ($comment = $column.columnComment)
  532 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  533 + #set ($dictMethod = "number")
  534 + #elseif ($javaType == "String")
  535 + #set ($dictMethod = "string")
  536 + #elseif ($javaType == "Boolean")
  537 + #set ($dictMethod = "boolean")
  538 + #end
  539 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  540 + #else
  541 + {
  542 + fieldName: '${javaField}',
  543 + label: '${comment}',
  544 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  545 + rules: 'required',
  546 + #end
  547 + #if ($column.htmlType == "input")
  548 + component: 'Input',
  549 + componentProps: {
  550 + placeholder: '请输入${comment}',
  551 + },
  552 + #elseif($column.htmlType == "imageUpload")## 图片上传
  553 + component: 'FileUpload',
  554 + componentProps: {
  555 + fileType: 'image',
  556 + maxCount: 1,
  557 + },
  558 + #elseif($column.htmlType == "fileUpload")## 文件上传
  559 + component: 'FileUpload',
  560 + componentProps: {
  561 + fileType: 'file',
  562 + maxCount: 1,
  563 + },
  564 + #elseif($column.htmlType == "editor")## 文本编辑器
  565 + component: 'Editor',
  566 + #elseif($column.htmlType == "select")## 下拉框
  567 + component: 'Select',
  568 + componentProps: {
  569 + #if ("" != $dictType)## 有数据字典
  570 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  571 + #else##没数据字典
  572 + options: [],
  573 + #end
  574 + placeholder: '请选择${comment}',
  575 + class: 'w-full',
  576 + },
  577 + #elseif($column.htmlType == "checkbox")## 多选框
  578 + component: 'Checkbox',
  579 + componentProps: {
  580 + #if ("" != $dictType)## 有数据字典
  581 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  582 + #else##没数据字典
  583 + options: [],
  584 + #end
  585 + },
  586 + #elseif($column.htmlType == "radio")## 单选框
  587 + component: 'RadioGroup',
  588 + componentProps: {
  589 + #if ("" != $dictType)## 有数据字典
  590 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  591 + #else##没数据字典
  592 + options: [],
  593 + #end
  594 + buttonStyle: 'solid',
  595 + optionType: 'button',
  596 + },
  597 + #elseif($column.htmlType == "datetime")## 时间框
  598 + component: 'DatePicker',
  599 + componentProps: {
  600 + showTime: true,
  601 + format: 'YYYY-MM-DD HH:mm:ss',
  602 + valueFormat: 'x',
  603 + },
  604 + #elseif($column.htmlType == "textarea")## 文本域
  605 + component: 'Textarea',
  606 + componentProps: {
  607 + placeholder: '请输入${comment}',
  608 + },
  609 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  610 + component: 'InputNumber',
  611 + componentProps: {
  612 + min: 0,
  613 + class: 'w-full',
  614 + controlsPosition: 'right',
  615 + placeholder: '请输入${comment}',
  616 + },
  617 + #end
  618 + },
  619 + #end
  620 + #end
  621 + #end
  622 + #end
  623 + ];
  624 + }
  625 + #end
  626 + #if ($table.templateType == 12) ## 内嵌情况
  627 + /** 列表的字段 */
  628 + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  629 + return [
  630 + #foreach($column in $subColumns)
  631 + #if ($column.listOperationResult)
  632 + #set ($dictType = $column.dictType)
  633 + #set ($javaField = $column.javaField)
  634 + #set ($comment = $column.columnComment)
  635 + {
  636 + field: '${javaField}',
  637 + title: '${comment}',
  638 + minWidth: 120,
  639 + #if ($column.javaType == "LocalDateTime")## 时间类型
  640 + formatter: 'formatDateTime',
  641 + #elseif("" != $dictType)## 数据字典
  642 + cellRender: {
  643 + name: 'CellDict',
  644 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  645 + },
  646 + #end
  647 + },
  648 + #end
  649 + #end
  650 + ];
  651 + }
  652 + #end
  653 +#end
  654 +#end
277 655 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/form.vue.vm
... ... @@ -2,7 +2,13 @@
2 2 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
3 3  
4 4 import { useVbenModal } from '@vben/common-ui';
5   -import { message } from 'ant-design-vue';
  5 +import { message, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
  6 +## 特殊:主子表专属逻辑
  7 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  8 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  9 + import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
  10 + #end
  11 +#end
6 12  
7 13 import { computed, ref } from 'vue';
8 14 import { $t } from '#/locales';
... ... @@ -32,6 +38,20 @@ const getTitle = computed(() =&gt; {
32 38 });
33 39 #end
34 40  
  41 +## 特殊:主子表专属逻辑
  42 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  43 + #if ( $subTables && $subTables.size() > 0 )
  44 +
  45 + /** 子表的表单 */
  46 + const subTabsName = ref('$subClassNameVars.get(0)')
  47 + #foreach ($subClassNameVar in $subClassNameVars)
  48 + #set ($index = $foreach.count - 1)
  49 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  50 + const ${subClassNameVar}FormRef = ref<InstanceType<typeof ${subSimpleClassName}Form>>()
  51 + #end
  52 + #end
  53 +#end
  54 +
35 55 const [Form, formApi] = useVbenForm({
36 56 layout: 'horizontal',
37 57 schema: useFormSchema(),
... ... @@ -44,9 +64,43 @@ const [Modal, modalApi] = useVbenModal({
44 64 if (!valid) {
45 65 return;
46 66 }
  67 + ## 特殊:主子表专属逻辑
  68 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  69 + #if ( $subTables && $subTables.size() > 0 )
  70 + // 校验子表单
  71 + #foreach ($subTable in $subTables)
  72 + #set ($index = $foreach.count - 1)
  73 + #set ($subClassNameVar = $subClassNameVars.get($index))
  74 + #if ($subTable.subJoinMany) ## 一对多
  75 + ## TODO 列表值校验?
  76 + #else
  77 + const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate();
  78 + if (!${subClassNameVar}Valid) {
  79 + subTabsName.value = '${subClassNameVar}';
  80 + return;
  81 + }
  82 + #end
  83 + #end
  84 + #end
  85 + #end
47 86 modalApi.lock();
48 87 // 提交表单
49 88 const data = (await formApi.getValues()) as ${simpleClassName}Api.${simpleClassName};
  89 + ## 特殊:主子表专属逻辑
  90 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  91 + #if ( $subTables && $subTables.size() > 0 )
  92 + // 拼接子表的数据
  93 + #foreach ($subTable in $subTables)
  94 + #set ($index = $foreach.count - 1)
  95 + #set ($subClassNameVar = $subClassNameVars.get($index))
  96 + #if ($subTable.subJoinMany)
  97 + data.${subClassNameVar}s = ${subClassNameVar}FormRef.value?.getData();
  98 + #else
  99 + data.${subClassNameVar} = await ${subClassNameVar}FormRef.value?.getValues();
  100 + #end
  101 + #end
  102 + #end
  103 + #end
50 104 try {
51 105 await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
52 106 // 关闭并提示
... ... @@ -62,51 +116,28 @@ const [Modal, modalApi] = useVbenModal({
62 116 },
63 117 async onOpenChange(isOpen: boolean) {
64 118 if (!isOpen) {
  119 + formData.value = undefined;
65 120 return;
66 121 }
  122 +
67 123 // 加载数据
68   -#if (${table.templateType} == 2)## 树表处理传入的父ID
69 124 let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
70   -#else## 标准表直接获取
71   - const data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
72   -#end
73 125 if (!data) {
74 126 return;
75 127 }
76 128  
77   -#if (${table.templateType} == 2)## 树表特有:处理新增下级的情况
78   - // 处理新增下级的情况
79   - if (!data.id && data.${treeParentColumn.javaField}) {
80   - parentId.value = data.${treeParentColumn.javaField};
81   - formData.value = { ${treeParentColumn.javaField}: parentId.value } as ${simpleClassName}Api.${simpleClassName};
82   - await formApi.setValues(formData.value);
83   - return;
84   - }
85   -#end
86   -
87 129 if (data.id) {
88 130 // 编辑
89 131 modalApi.lock();
90 132 try {
91   -#if (${table.templateType} == 2)## 树表获取数据后重新赋值
92 133 data = await get${simpleClassName}(data.id);
93   - formData.value = data;
94   -#else## 标准表设置表单数据
95   - formData.value = await get${simpleClassName}(data.id as number);
96   -#end
97   - await formApi.setValues(formData.value);
98 134 } finally {
99 135 modalApi.lock(false);
100 136 }
101   - } else {
102   - // 新增
103   -#if (${table.templateType} == 2)## 树表特有:设置顶级ID
104   - formData.value = { ${treeParentColumn.javaField}: 0 } as ${simpleClassName}Api.${simpleClassName};
105   -#else## 标准表:设置空值
106   - formData.value = data;
107   -#end
108   - await formApi.setValues(formData.value || {});
109 137 }
  138 + // 设置到 values
  139 + formData.value = data;
  140 + await formApi.setValues(formData.value);
110 141 },
111 142 });
112 143 </script>
... ... @@ -114,5 +145,20 @@ const [Modal, modalApi] = useVbenModal({
114 145 <template>
115 146 <Modal :title="getTitle">
116 147 <Form class="mx-4" />
  148 + ## 特殊:主子表专属逻辑
  149 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  150 + <!-- 子表的表单 -->
  151 + <Tabs v-model:active-key="subTabsName">
  152 + #foreach ($subTable in $subTables)
  153 + #set ($index = $foreach.count - 1)
  154 + #set ($subClassNameVar = $subClassNameVars.get($index))
  155 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  156 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  157 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  158 + <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" />
  159 + </Tabs.TabPane>
  160 + #end
  161 + </Tabs>
  162 + #end
117 163 </Modal>
118 164 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm renamed to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
... ... @@ -3,11 +3,18 @@ import type { OnActionClickParams, VxeTableGridOptions } from &#39;#/adapter/vxe-tab
3 3 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
4 4  
5 5 import { Page, useVbenModal } from '@vben/common-ui';
6   -import { Button, message } from 'ant-design-vue';
  6 +import { Button, message,Tabs } from 'ant-design-vue';
7 7 import { Download, Plus } from '@vben/icons';
8 8 import Form from './modules/form.vue';
9 9  
10   -import { ref } from 'vue';
  10 +## 特殊:主子表专属逻辑
  11 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  12 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  13 + import ${subSimpleClassName}List from './modules/${subSimpleClassName}List.vue'
  14 + #end
  15 +#end
  16 +
  17 +import { ref, h } from 'vue';
11 18 import { $t } from '#/locales';
12 19 import { useVbenVxeGrid } from '#/adapter/vxe-table';
13 20 #if (${table.templateType} == 2)## 树表接口
... ... @@ -19,6 +26,11 @@ import { downloadByData } from &#39;#/utils/download&#39;;
19 26  
20 27 import { useGridColumns, useGridFormSchema } from './data';
21 28  
  29 +#if ($table.templateType == 12) ## 内嵌情况
  30 +/** 子表的列表 */
  31 +const subTabsName = ref('$subClassNameVars.get(0)')
  32 +#end
  33 +
22 34 const [FormModal, formModalApi] = useVbenModal({
23 35 connectedComponent: Form,
24 36 destroyOnClose: true,
... ... @@ -35,7 +47,11 @@ function toggleExpand() {
35 47  
36 48 /** 刷新表格 */
37 49 function onRefresh() {
  50 +#if ($table.templateType == 12) ## 内嵌情况
  51 + gridApi.reload();
  52 +#else
38 53 gridApi.query();
  54 +#end
39 55 }
40 56  
41 57 /** 导出表格 */
... ... @@ -46,7 +62,7 @@ async function onExport() {
46 62  
47 63 /** 创建${table.classComment} */
48 64 function onCreate() {
49   - formModalApi.setData(null).open();
  65 + formModalApi.setData({}).open();
50 66 }
51 67  
52 68 /** 编辑${table.classComment} */
... ... @@ -56,7 +72,7 @@ function onEdit(row: ${simpleClassName}Api.${simpleClassName}) {
56 72  
57 73 #if (${table.templateType} == 2)## 树表特有:新增下级
58 74 /** 新增下级${table.classComment} */
59   -function onAddChild(row: ${simpleClassName}Api.${simpleClassName}) {
  75 +function onAppend(row: ${simpleClassName}Api.${simpleClassName}) {
60 76 formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
61 77 }
62 78 #end
... ... @@ -86,20 +102,20 @@ function onActionClick({
86 102 row,
87 103 }: OnActionClickParams<${simpleClassName}Api.${simpleClassName}>) {
88 104 switch (code) {
89   - case 'edit': {
90   - onEdit(row);
  105 + #if (${table.templateType} == 2)## 树表特有:新增下级
  106 + case 'append': {
  107 + onAppend(row);
91 108 break;
92 109 }
  110 + #end
93 111 case 'delete': {
94 112 onDelete(row);
95 113 break;
96 114 }
97   -#if (${table.templateType} == 2)## 树表特有:新增下级
98   - case 'add_child': {
99   - onAddChild(row);
  115 + case 'edit': {
  116 + onEdit(row);
100 117 break;
101 118 }
102   -#end
103 119 }
104 120 }
105 121  
... ... @@ -134,12 +150,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
134 150 },
135 151 #else## 标准表数据加载
136 152 query: async ({ page }, formValues) => {
137   - const { items, total } = await get${simpleClassName}Page({
  153 + return await get${simpleClassName}Page({
138 154 pageNo: page.currentPage,
139 155 pageSize: page.pageSize,
140 156 ...formValues,
141 157 });
142   - return { items, total };
143 158 },
144 159 #end
145 160 },
... ... @@ -161,18 +176,38 @@ const [Grid, gridApi] = useVbenVxeGrid({
161 176 <FormModal @success="onRefresh" />
162 177  
163 178 <Grid table-title="${table.classComment}列表">
  179 + #if ($table.templateType == 12) ## 内嵌情况
  180 + <template #expand_content="{ row }">
  181 + <!-- 子表的表单 -->
  182 + <Tabs v-model:active-key="subTabsName">
  183 + #foreach ($subTable in $subTables)
  184 + #set ($index = $foreach.count - 1)
  185 + #set ($subClassNameVar = $subClassNameVars.get($index))
  186 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  187 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  188 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  189 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
  190 + </Tabs.TabPane>
  191 + #end
  192 + </Tabs>
  193 + </template>
  194 + #end
164 195 <template #toolbar-tools>
165 196 #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
166 197 <Button @click="toggleExpand" class="mr-2">
167 198 {{ isExpanded ? '收缩' : '展开' }}
168 199 </Button>
169 200 #end
170   - <Button type="primary" @click="onCreate" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:create']">
171   - <Plus class="size-5" />
  201 + <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:create']">
172 202 {{ $t('ui.actionTitle.create', ['${table.classComment}']) }}
173 203 </Button>
174   - <Button type="primary" class="ml-2" @click="onExport" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:export']">
175   - <Download class="size-5" />
  204 + <Button
  205 + :icon="h(Download)"
  206 + type="primary"
  207 + class="ml-2"
  208 + @click="onExport"
  209 + v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:export']"
  210 + >
176 211 {{ $t('ui.actionTitle.export') }}
177 212 </Button>
178 213 </template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subClassNameVar = $subClassNameVars.get($subIndex))
  6 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +<script lang="ts" setup>
  8 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  9 +
  10 + import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  11 + import { $t } from '#/locales';
  12 +
  13 +#if ($subTable.subJoinMany) ## 一对多
  14 +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}GridColumns } from '../data';
  19 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  20 +#else
  21 +import { useVbenForm } from '#/adapter/form';
  22 +import { use${subSimpleClassName}FormSchema } from '../data';
  23 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  24 +#end
  25 +
  26 +const props = defineProps<{
  27 + ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
  28 +}>()
  29 +
  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 [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
  45 +gridOptions: {
  46 + columns: use${subSimpleClassName}GridColumns(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 +
  63 +/** 删除${subTable.classComment} */
  64 +const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  65 +await ${subClassNameVar}GridApi.grid.remove(row);
  66 +}
  67 +
  68 +/** 添加${subTable.classComment} */
  69 +const handleAdd = async () => {
  70 +await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  71 +}
  72 +
  73 +/** 提供获取表格数据的方法供父组件调用 */
  74 +defineExpose({
  75 +getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
  76 + return [
  77 + ...${subClassNameVar}GridApi.grid.getData(),
  78 + ...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
  79 + delete row.id;
  80 + return row;
  81 + }),
  82 + ];
  83 +},
  84 +});
  85 +
  86 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  87 +watch(
  88 + () => props.${subJoinColumn.javaField},
  89 + async (val) => {
  90 + if (!val) {
  91 + return;
  92 + }
  93 +
  94 + await nextTick();
  95 + await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  96 + },
  97 +);
  98 +#else
  99 +const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
  100 +layout: 'horizontal',
  101 +schema: use${subSimpleClassName}FormSchema(),
  102 +showDefaultActions: false
  103 +});
  104 +
  105 +/** 暴露出表单校验方法和表单值获取方法 */
  106 +defineExpose({
  107 +validate: async () => {
  108 + const { valid } = await ${subClassNameVar}FormApi.validate();
  109 + return valid;
  110 +},
  111 +getValues: ${subClassNameVar}FormApi.getValues,
  112 +});
  113 +
  114 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  115 +watch(
  116 + () => props.${subJoinColumn.javaField},
  117 + async (val) => {
  118 + if (!val) {
  119 + return;
  120 + }
  121 +
  122 + await nextTick();
  123 + await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  124 + },
  125 +);
  126 +#end
  127 +</script>
  128 +
  129 +<template>
  130 + #if ($subTable.subJoinMany) ## 一对多
  131 + <${subSimpleClassName}Grid class="mx-4">
  132 + #foreach($column in $subColumns)
  133 + #if ($column.createOperation || $column.updateOperation)
  134 + #set ($javaField = $column.javaField)
  135 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  136 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  137 + <template #${javaField}="{ row }">
  138 + <Input v-model:value="row.${javaField}" />
  139 + </template>
  140 + #elseif($column.htmlType == "imageUpload")## 图片上传
  141 + <template #${javaField}="{ row }">
  142 + <UploadImg v-model:value="row.${javaField}" />
  143 + </template>
  144 + #elseif($column.htmlType == "fileUpload")## 文件上传
  145 + <template #${javaField}="{ row }">
  146 + <UploadFile v-model:value="row.${javaField}" />
  147 + </template>
  148 + #elseif($column.htmlType == "editor")## 文本编辑器
  149 + <template #${javaField}="{ row }">
  150 + <Textarea v-model:value="row.${javaField}" />
  151 + </template>
  152 + #elseif($column.htmlType == "select")## 下拉框
  153 + <template #${javaField}="{ row, column }">
  154 + <Select v-model:value="row.${javaField}" class="w-full">
  155 + <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
  156 + {{ option.label }}
  157 + </Select.Option>
  158 + </Select>
  159 + </template>
  160 + #elseif($column.htmlType == "checkbox")## 多选框
  161 + <template #${javaField}="{ row, column }">
  162 + <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
  163 + </template>
  164 + #elseif($column.htmlType == "radio")## 单选框
  165 + <template #${javaField}="{ row, column }">
  166 + <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
  167 + </template>
  168 + #elseif($column.htmlType == "datetime")## 时间框
  169 + <template #${javaField}="{ row }">
  170 + <DatePicker
  171 + v-model:value="row.${javaField}"
  172 + :showTime="true"
  173 + format="YYYY-MM-DD HH:mm:ss"
  174 + valueFormat='x'
  175 + />
  176 + </template>
  177 + #elseif($column.htmlType == "textarea")## 文本框
  178 + <template #${javaField}="{ row }">
  179 + <Textarea v-model:value="row.${javaField}" />
  180 + </template>
  181 + #end
  182 + #end
  183 + #end
  184 + </${subSimpleClassName}Grid>
  185 + <div class="flex justify-center">
  186 + <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
  187 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  188 + </Button>
  189 + </div>
  190 + #else
  191 + <${subSimpleClassName}Form class="mx-4" />
  192 + #end
  193 +</template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_inner.vue.vm 0 → 100644
  1 +## 主表的 normal 和 inner 使用相同的 form 表单
  2 +#parse("codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm")
0 3 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subClassNameVar = $subClassNameVars.get($subIndex))
  6 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +<script lang="ts" setup>
  8 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  9 +
  10 + import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  11 + import { $t } from '#/locales';
  12 +
  13 +#if ($subTable.subJoinMany) ## 一对多
  14 +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';
  19 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  20 +#else
  21 +import { useVbenForm } from '#/adapter/form';
  22 +import { use${subSimpleClassName}FormSchema } from '../data';
  23 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  24 +#end
  25 +
  26 +const props = defineProps<{
  27 + ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
  28 +}>()
  29 +
  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 [${subSimpleClassName}Grid, ${subClassNameVar}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 +
  63 +/** 删除${subTable.classComment} */
  64 +const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  65 + await ${subClassNameVar}GridApi.grid.remove(row);
  66 +}
  67 +
  68 +/** 添加${subTable.classComment} */
  69 +const handleAdd = async () => {
  70 + await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  71 +}
  72 +
  73 +/** 提供获取表格数据的方法供父组件调用 */
  74 +defineExpose({
  75 + getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
  76 + // 获取当前数据,但排除已删除的记录
  77 + const allData = ${subClassNameVar}GridApi.grid.getData();
  78 + const removedData = ${subClassNameVar}GridApi.grid.getRemoveRecords();
  79 + const removedIds = new Set(removedData.map((row) => row.id));
  80 +
  81 + // 过滤掉已删除的记录
  82 + const currentData = allData.filter((row) => !removedIds.has(row.id));
  83 +
  84 + // 获取新插入的记录并移除id
  85 + const insertedData = ${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
  86 + delete row.id;
  87 + return row;
  88 + });
  89 +
  90 + return [...currentData, ...insertedData];
  91 + },
  92 +});
  93 +
  94 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  95 +watch(
  96 + () => props.${subJoinColumn.javaField},
  97 + async (val) => {
  98 + if (!val) {
  99 + return;
  100 + }
  101 +
  102 + await nextTick();
  103 + await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  104 + },
  105 + { immediate: true },
  106 +);
  107 +#else
  108 +const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
  109 +layout: 'horizontal',
  110 +schema: use${subSimpleClassName}FormSchema(),
  111 +showDefaultActions: false
  112 +});
  113 +
  114 +/** 暴露出表单校验方法和表单值获取方法 */
  115 +defineExpose({
  116 + validate: async () => {
  117 + const { valid } = await ${subClassNameVar}FormApi.validate();
  118 + return valid;
  119 + },
  120 + getValues: ${subClassNameVar}FormApi.getValues,
  121 +});
  122 +
  123 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  124 +watch(
  125 + () => props.${subJoinColumn.javaField},
  126 + async (val) => {
  127 + if (!val) {
  128 + return;
  129 + }
  130 +
  131 + await nextTick();
  132 + await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  133 + },
  134 + { immediate: true },
  135 +);
  136 +#end
  137 +</script>
  138 +
  139 +<template>
  140 +#if ($subTable.subJoinMany) ## 一对多
  141 + <${subSimpleClassName}Grid class="mx-4">
  142 + #foreach($column in $subColumns)
  143 + #if ($column.createOperation || $column.updateOperation)
  144 + #set ($javaField = $column.javaField)
  145 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  146 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  147 + <template #${javaField}="{ row }">
  148 + <Input v-model:value="row.${javaField}" />
  149 + </template>
  150 + #elseif($column.htmlType == "imageUpload")## 图片上传
  151 + <template #${javaField}="{ row }">
  152 + <UploadImg v-model:value="row.${javaField}" />
  153 + </template>
  154 + #elseif($column.htmlType == "fileUpload")## 文件上传
  155 + <template #${javaField}="{ row }">
  156 + <UploadFile v-model:value="row.${javaField}" />
  157 + </template>
  158 + #elseif($column.htmlType == "editor")## 文本编辑器
  159 + <template #${javaField}="{ row }">
  160 + <Textarea v-model:value="row.${javaField}" />
  161 + </template>
  162 + #elseif($column.htmlType == "select")## 下拉框
  163 + <template #${javaField}="{ row, column }">
  164 + <Select v-model:value="row.${javaField}" class="w-full">
  165 + <Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
  166 + {{ option.label }}
  167 + </Select.Option>
  168 + </Select>
  169 + </template>
  170 + #elseif($column.htmlType == "checkbox")## 多选框
  171 + <template #${javaField}="{ row, column }">
  172 + <CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
  173 + </template>
  174 + #elseif($column.htmlType == "radio")## 单选框
  175 + <template #${javaField}="{ row, column }">
  176 + <RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
  177 + </template>
  178 + #elseif($column.htmlType == "datetime")## 时间框
  179 + <template #${javaField}="{ row }">
  180 + <DatePicker
  181 + v-model:value="row.${javaField}"
  182 + :showTime="true"
  183 + format="YYYY-MM-DD HH:mm:ss"
  184 + valueFormat='x'
  185 + />
  186 + </template>
  187 + #elseif($column.htmlType == "textarea")## 文本框
  188 + <template #${javaField}="{ row }">
  189 + <Textarea v-model:value="row.${javaField}" />
  190 + </template>
  191 + #end
  192 + #end
  193 + #end
  194 + </${subSimpleClassName}Grid>
  195 + <div class="flex justify-center">
  196 + <Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
  197 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  198 + </Button>
  199 + </div>
  200 +#else
  201 + <${subSimpleClassName}Form class="mx-4" />
  202 +#end
  203 +</template>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  6 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  7 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  8 +<script lang="ts" setup>
  9 + import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
  10 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  11 +
  12 + import { useVbenModal } from '@vben/common-ui';
  13 + import { Button, message } from 'ant-design-vue';
  14 + import { Plus } from '@vben/icons';
  15 + import { ref, h, nextTick,watch } from 'vue';
  16 + import { $t } from '#/locales';
  17 + import { useVbenVxeGrid } from '#/adapter/vxe-table';
  18 +
  19 +
  20 +#if ($table.templateType == 11) ## erp
  21 + import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
  22 +#end
  23 + import { use${subSimpleClassName}GridColumns } from '../data';
  24 +#if ($subTable.subJoinMany) ## 一对多
  25 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  26 +#else
  27 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  28 +#end
  29 +
  30 +const props = defineProps<{
  31 + ${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
  32 +}>()
  33 +
  34 +#if ($table.templateType == 11) ## erp
  35 + const [FormModal, formModalApi] = useVbenModal({
  36 + connectedComponent: ${subSimpleClassName}Form,
  37 + destroyOnClose: true,
  38 + });
  39 +
  40 +/** 创建${subTable.classComment} */
  41 +function onCreate() {
  42 + formModalApi.setData({}).open();
  43 +}
  44 +
  45 +/** 编辑${subTable.classComment} */
  46 +function onEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  47 + formModalApi.setData(row).open();
  48 +}
  49 +/** 删除${subTable.classComment} */
  50 +async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  51 + const hideLoading = message.loading({
  52 + content: $t('ui.actionMessage.deleting', [row.id]),
  53 + duration: 0,
  54 + key: 'action_process_msg',
  55 + });
  56 + try {
  57 + await delete${subSimpleClassName}(row.id as number);
  58 + message.success({
  59 + content: $t('ui.actionMessage.deleteSuccess', [row.id]),
  60 + key: 'action_process_msg',
  61 + });
  62 + onRefresh();
  63 + } catch {
  64 + hideLoading();
  65 + }
  66 +}
  67 +
  68 +/** 表格操作按钮的回调函数 */
  69 +function onActionClick({
  70 + code,
  71 + row,
  72 +}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
  73 + switch (code) {
  74 + case 'delete': {
  75 + onDelete(row);
  76 + break;
  77 + }
  78 + case 'edit': {
  79 + onEdit(row);
  80 + break;
  81 + }
  82 + }
  83 +}
  84 +#end
  85 + const [Grid, gridApi] = useVbenVxeGrid({
  86 + gridOptions: {
  87 +#if ($table.templateType == 11)
  88 + columns: use${subSimpleClassName}GridColumns(onActionClick),
  89 +#else
  90 + columns: use${subSimpleClassName}GridColumns(),
  91 +#end
  92 + height: 'auto',
  93 + rowConfig: {
  94 + keyField: 'id',
  95 + isHover: true,
  96 + },
  97 + pagerConfig: {
  98 + enabled: false,
  99 + },
  100 + toolbarConfig: {
  101 + enabled: false,
  102 + },
  103 + } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  104 + });
  105 +
  106 +/** 刷新表格 */
  107 +const onRefresh = async ()=> {
  108 + #if ($subTable.subJoinMany) ## 一对多
  109 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  110 + #else
  111 + await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
  112 + #end
  113 +}
  114 +
  115 + /** 监听主表的关联字段的变化,加载对应的子表数据 */
  116 + watch(
  117 + () => props.${subJoinColumn.javaField},
  118 + async (val) => {
  119 + if (!val) {
  120 + return;
  121 + }
  122 +
  123 + await nextTick();
  124 + await onRefresh()
  125 + },
  126 + { immediate: true },
  127 + );
  128 +</script>
  129 +
  130 +<template>
  131 + <div class="mx-4">
  132 + #if ($table.templateType == 11) ## erp
  133 + <FormModal @success="onRefresh" />
  134 + <Grid table-title="${subTable.classComment}列表">
  135 + <template #toolbar-tools>
  136 + <Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${subTable.moduleName}:${subSimpleClassName_strikeCase}:create']">
  137 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  138 + </Button>
  139 + </template>
  140 + </Grid>
  141 + #else
  142 + <Grid table-title="${subTable.classComment}列表" />
  143 + #end
  144 + </div>
  145 +</template>
0 146 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_inner.vue.vm 0 → 100644
  1 +## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
  2 +## 1)inner 使用 list 不分页,erp 使用 page 分页
  3 +## 2)erp 支持单个子表的新增、修改、删除,inner 不支持
  4 +#parse("codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm")
0 5 \ No newline at end of file
... ...