Commit b4d16b368d5a7af029e3f6f3175097e7d742deaa

Authored by puhui999
2 parents 5ebebf15 df51a678

Merge remote-tracking branch 'yudao/feature/sub-table' into feature/sub-table

yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm
... ... @@ -63,7 +63,7 @@ export function export${simpleClassName}Excel(params) {
63 63 responseType: 'blob'
64 64 })
65 65 }
66   -## 特殊:主子表专属逻辑
  66 +## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对
67 67 #foreach ($subTable in $subTables)
68 68 #set ($index = $foreach.count - 1)
69 69 #set ($subSimpleClassName = $subSimpleClassNames.get($index))
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm
1 1 <template>
2 2 <Dialog :title="dialogTitle" v-model="dialogVisible">
3 3 <el-form
4   - ref="formRef"
5   - :model="formData"
6   - :rules="formRules"
7   - label-width="100px"
8   - v-loading="formLoading"
  4 + ref="formRef"
  5 + :model="formData"
  6 + :rules="formRules"
  7 + label-width="100px"
  8 + v-loading="formLoading"
9 9 >
10   - #foreach($column in $columns)
11   - #if ($column.createOperation || $column.updateOperation)
12   - #set ($dictType = $column.dictType)
13   - #set ($javaField = $column.javaField)
14   - #set ($javaType = $column.javaType)
15   - #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
16   - #set ($comment = $column.columnComment)
17   - #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
18   - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
19   - #set ($dictMethod = "getIntDictOptions")
20   - #elseif ($javaType == "String")
21   - #set ($dictMethod = "getStrDictOptions")
22   - #elseif ($javaType == "Boolean")
23   - #set ($dictMethod = "getBoolDictOptions")
  10 +#foreach($column in $columns)
  11 + #if ($column.createOperation || $column.updateOperation)
  12 + #set ($dictType = $column.dictType)
  13 + #set ($javaField = $column.javaField)
  14 + #set ($javaType = $column.javaType)
  15 + #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
  16 + #set ($comment = $column.columnComment)
  17 + #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
  18 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  19 + #set ($dictMethod = "getIntDictOptions")
  20 + #elseif ($javaType == "String")
  21 + #set ($dictMethod = "getStrDictOptions")
  22 + #elseif ($javaType == "Boolean")
  23 + #set ($dictMethod = "getBoolDictOptions")
  24 + #end
  25 + #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
  26 + <el-form-item label="${comment}" prop="${javaField}">
  27 + <el-tree-select
  28 + v-model="formData.${javaField}"
  29 + :data="${classNameVar}Tree"
  30 + #if ($treeNameColumn.javaField == "name")
  31 + :props="defaultProps"
  32 + #else
  33 + :props="{...defaultProps, label: '$treeNameColumn.javaField'}"
  34 + #end
  35 + check-strictly
  36 + default-expand-all
  37 + placeholder="请选择${comment}"
  38 + />
  39 + </el-form-item>
  40 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  41 + <el-form-item label="${comment}" prop="${javaField}">
  42 + <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
  43 + </el-form-item>
  44 + #elseif($column.htmlType == "imageUpload")## 图片上传
  45 + <el-form-item label="${comment}" prop="${javaField}">
  46 + <UploadImg v-model="formData.${javaField}" />
  47 + </el-form-item>
  48 + #elseif($column.htmlType == "fileUpload")## 文件上传
  49 + <el-form-item label="${comment}" prop="${javaField}">
  50 + <UploadFile v-model="formData.${javaField}" />
  51 + </el-form-item>
  52 + #elseif($column.htmlType == "editor")## 文本编辑器
  53 + <el-form-item label="${comment}" prop="${javaField}">
  54 + <Editor v-model="formData.${javaField}" height="150px" />
  55 + </el-form-item>
  56 + #elseif($column.htmlType == "select")## 下拉框
  57 + <el-form-item label="${comment}" prop="${javaField}">
  58 + <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
  59 + #if ("" != $dictType)## 有数据字典
  60 + <el-option
  61 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  62 + :key="dict.value"
  63 + :label="dict.label"
  64 + :value="dict.value"
  65 + />
  66 + #else##没数据字典
  67 + <el-option label="请选择字典生成" value="" />
24 68 #end
25   - #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
26   - <el-form-item label="${comment}" prop="${javaField}">
27   - <el-tree-select
28   - v-model="formData.${javaField}"
29   - :data="${classNameVar}Tree"
30   - #if ($treeNameColumn.javaField == "name")
31   - :props="defaultProps"
32   - #else
33   - :props="{...defaultProps, label: '$treeNameColumn.javaField'}"
34   - #end
35   - check-strictly
36   - default-expand-all
37   - placeholder="请选择${comment}"
38   - />
39   - </el-form-item>
40   - #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
41   - <el-form-item label="${comment}" prop="${javaField}">
42   - <el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
43   - </el-form-item>
44   - #elseif($column.htmlType == "imageUpload")## 图片上传
45   - <el-form-item label="${comment}" prop="${javaField}">
46   - <UploadImg v-model="formData.${javaField}" />
47   - </el-form-item>
48   - #elseif($column.htmlType == "fileUpload")## 文件上传
49   - <el-form-item label="${comment}" prop="${javaField}">
50   - <UploadFile v-model="formData.${javaField}" />
51   - </el-form-item>
52   - #elseif($column.htmlType == "editor")## 文本编辑器
53   - <el-form-item label="${comment}" prop="${javaField}">
54   - <Editor v-model="formData.${javaField}" height="150px" />
55   - </el-form-item>
56   - #elseif($column.htmlType == "select")## 下拉框
57   - <el-form-item label="${comment}" prop="${javaField}">
58   - <el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
59   - #if ("" != $dictType)## 有数据字典
60   - <el-option
61   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
62   - :key="dict.value"
63   - :label="dict.label"
64   - :value="dict.value"
65   - />
66   - #else##没数据字典
67   - <el-option label="请选择字典生成" value="" />
68   - #end
69   - </el-select>
70   - </el-form-item>
71   - #elseif($column.htmlType == "checkbox")## 多选框
72   - <el-form-item label="${comment}" prop="${javaField}">
73   - <el-checkbox-group v-model="formData.${javaField}">
74   - #if ("" != $dictType)## 有数据字典
75   - <el-checkbox
76   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
77   - :key="dict.value"
78   - :label="dict.value"
79   - >
80   - {{ dict.label }}
81   - </el-checkbox>
82   - #else##没数据字典
83   - <el-checkbox>请选择字典生成</el-checkbox>
84   - #end
85   - </el-checkbox-group>
86   - </el-form-item>
87   - #elseif($column.htmlType == "radio")## 单选框
88   - <el-form-item label="${comment}" prop="${javaField}">
89   - <el-radio-group v-model="formData.${javaField}">
90   - #if ("" != $dictType)## 有数据字典
91   - <el-radio
92   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
93   - :key="dict.value"
94   - :label="dict.value"
95   - >
96   - {{ dict.label }}
97   - </el-radio>
98   - #else##没数据字典
99   - <el-radio label="1">请选择字典生成</el-radio>
100   - #end
101   - </el-radio-group>
102   - </el-form-item>
103   - #elseif($column.htmlType == "datetime")## 时间框
104   - <el-form-item label="${comment}" prop="${javaField}">
105   - <el-date-picker
106   - v-model="formData.${javaField}"
107   - type="date"
108   - value-format="x"
109   - placeholder="选择${comment}"
110   - />
111   - </el-form-item>
112   - #elseif($column.htmlType == "textarea")## 文本框
113   - <el-form-item label="${comment}" prop="${javaField}">
114   - <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
115   - </el-form-item>
  69 + </el-select>
  70 + </el-form-item>
  71 + #elseif($column.htmlType == "checkbox")## 多选框
  72 + <el-form-item label="${comment}" prop="${javaField}">
  73 + <el-checkbox-group v-model="formData.${javaField}">
  74 + #if ("" != $dictType)## 有数据字典
  75 + <el-checkbox
  76 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  77 + :key="dict.value"
  78 + :label="dict.value"
  79 + >
  80 + {{ dict.label }}
  81 + </el-checkbox>
  82 + #else##没数据字典
  83 + <el-checkbox>请选择字典生成</el-checkbox>
116 84 #end
117   - #end
  85 + </el-checkbox-group>
  86 + </el-form-item>
  87 + #elseif($column.htmlType == "radio")## 单选框
  88 + <el-form-item label="${comment}" prop="${javaField}">
  89 + <el-radio-group v-model="formData.${javaField}">
  90 + #if ("" != $dictType)## 有数据字典
  91 + <el-radio
  92 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  93 + :key="dict.value"
  94 + :label="dict.value"
  95 + >
  96 + {{ dict.label }}
  97 + </el-radio>
  98 + #else##没数据字典
  99 + <el-radio label="1">请选择字典生成</el-radio>
  100 + #end
  101 + </el-radio-group>
  102 + </el-form-item>
  103 + #elseif($column.htmlType == "datetime")## 时间框
  104 + <el-form-item label="${comment}" prop="${javaField}">
  105 + <el-date-picker
  106 + v-model="formData.${javaField}"
  107 + type="date"
  108 + value-format="x"
  109 + placeholder="选择${comment}"
  110 + />
  111 + </el-form-item>
  112 + #elseif($column.htmlType == "textarea")## 文本框
  113 + <el-form-item label="${comment}" prop="${javaField}">
  114 + <el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
  115 + </el-form-item>
118 116 #end
  117 + #end
  118 +#end
119 119 </el-form>
120   - ## 特殊:主子表专属逻辑
121   - #if ( $table.templateType == 10 || $table.templateType == 12 )
122   - <!-- 子表的表单 -->
123   - <el-tabs v-model="subTabsName">
124   - #foreach ($subTable in $subTables)
125   - #set ($index = $foreach.count - 1)
126   - #set ($subClassNameVar = $subClassNameVars.get($index))
127   - #set ($subSimpleClassName = $subSimpleClassNames.get($index))
128   - #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
129   - <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
130   - <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" />
131   - </el-tab-pane>
132   - #end
133   - </el-tabs>
134   - #end
  120 +## 特殊:主子表专属逻辑
  121 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  122 + <!-- 子表的表单 -->
  123 + <el-tabs v-model="subTabsName">
  124 + #foreach ($subTable in $subTables)
  125 + #set ($index = $foreach.count - 1)
  126 + #set ($subClassNameVar = $subClassNameVars.get($index))
  127 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  128 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  129 + <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
  130 + <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" />
  131 + </el-tab-pane>
  132 + #end
  133 + </el-tabs>
  134 +#end
135 135 <template #footer>
136 136 <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
137 137 <el-button @click="dialogVisible = false">取 消</el-button>
... ... @@ -139,160 +139,160 @@
139 139 </Dialog>
140 140 </template>
141 141 <script setup lang="ts">
142   - import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
143   - import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
144   - ## 特殊:树表专属逻辑
145   - #if ( $table.templateType == 2 )
146   - import { defaultProps, handleTree } from '@/utils/tree'
147   - #end
148   - ## 特殊:主子表专属逻辑
149   - #if ( $table.templateType == 10 || $table.templateType == 12 )
150   - #foreach ($subSimpleClassName in $subSimpleClassNames)
151   - import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
152   - #end
153   - #end
  142 +import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  143 +import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
  144 +## 特殊:树表专属逻辑
  145 +#if ( $table.templateType == 2 )
  146 +import { defaultProps, handleTree } from '@/utils/tree'
  147 +#end
  148 +## 特殊:主子表专属逻辑
  149 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  150 +#foreach ($subSimpleClassName in $subSimpleClassNames)
  151 +import ${subSimpleClassName}Form from './components/${subSimpleClassName}Form.vue'
  152 +#end
  153 +#end
154 154  
155   - const { t } = useI18n() // 国际化
156   - const message = useMessage() // 消息弹窗
157   -
158   - const dialogVisible = ref(false) // 弹窗的是否展示
159   - const dialogTitle = ref('') // 弹窗的标题
160   - const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
161   - const formType = ref('') // 表单的类型:create - 新增;update - 修改
162   - const formData = ref({
163   - #foreach ($column in $columns)
164   - #if ($column.createOperation || $column.updateOperation)
165   - #if ($column.htmlType == "checkbox")
166   - $column.javaField: [],
167   - #else
168   - $column.javaField: undefined,
169   - #end
170   - #end
171   - #end
172   - })
173   - const formRules = reactive({
174   - #foreach ($column in $columns)
175   - #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
176   - #set($comment=$column.columnComment)
177   - $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
178   - #end
179   - #end
180   - })
181   - const formRef = ref() // 表单 Ref
182   - ## 特殊:树表专属逻辑
183   - #if ( $table.templateType == 2 )
184   - const ${classNameVar}Tree = ref() // 树形结构
185   - #end
186   - ## 特殊:主子表专属逻辑
187   - #if ( $table.templateType == 10 || $table.templateType == 12 )
188   - #if ( $subTables && $subTables.size() > 0 )
  155 +const { t } = useI18n() // 国际化
  156 +const message = useMessage() // 消息弹窗
189 157  
190   - /** 子表的表单 */
191   - const subTabsName = ref('$subClassNameVars.get(0)')
192   - #foreach ($subClassNameVar in $subClassNameVars)
193   - const ${subClassNameVar}FormRef = ref()
194   - #end
195   - #end
  158 +const dialogVisible = ref(false) // 弹窗的是否展示
  159 +const dialogTitle = ref('') // 弹窗的标题
  160 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  161 +const formType = ref('') // 表单的类型:create - 新增;update - 修改
  162 +const formData = ref({
  163 +#foreach ($column in $columns)
  164 + #if ($column.createOperation || $column.updateOperation)
  165 + #if ($column.htmlType == "checkbox")
  166 + $column.javaField: [],
  167 + #else
  168 + $column.javaField: undefined,
196 169 #end
  170 + #end
  171 +#end
  172 +})
  173 +const formRules = reactive({
  174 +#foreach ($column in $columns)
  175 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  176 + #set($comment=$column.columnComment)
  177 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
  178 + #end
  179 +#end
  180 +})
  181 +const formRef = ref() // 表单 Ref
  182 +## 特殊:树表专属逻辑
  183 +#if ( $table.templateType == 2 )
  184 +const ${classNameVar}Tree = ref() // 树形结构
  185 +#end
  186 +## 特殊:主子表专属逻辑
  187 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  188 +#if ( $subTables && $subTables.size() > 0 )
197 189  
198   - /** 打开弹窗 */
199   - const open = async (type: string, id?: number) => {
200   - dialogVisible.value = true
201   - dialogTitle.value = t('action.' + type)
202   - formType.value = type
203   - resetForm()
204   - // 修改时,设置数据
205   - if (id) {
206   - formLoading.value = true
207   - try {
208   - formData.value = await ${simpleClassName}Api.get${simpleClassName}(id)
209   - } finally {
210   - formLoading.value = false
211   - }
212   - }
213   - ## 特殊:树表专属逻辑
214   - #if ( $table.templateType == 2 )
215   - await get${simpleClassName}Tree()
216   - #end
217   - }
218   - defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  190 +/** 子表的表单 */
  191 +const subTabsName = ref('$subClassNameVars.get(0)')
  192 +#foreach ($subClassNameVar in $subClassNameVars)
  193 +const ${subClassNameVar}FormRef = ref()
  194 +#end
  195 +#end
  196 +#end
219 197  
220   - /** 提交表单 */
221   - const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
222   - const submitForm = async () => {
223   - // 校验表单
224   - await formRef.value.validate()
225   - ## 特殊:主子表专属逻辑
226   - #if ( $table.templateType == 10 || $table.templateType == 12 )
227   - #if ( $subTables && $subTables.size() > 0 )
228   - // 校验子表单
229   - #foreach ($subTable in $subTables)
230   - #set ($index = $foreach.count - 1)
231   - #set ($subClassNameVar = $subClassNameVars.get($index))
232   - try {
233   - await ${subClassNameVar}FormRef.value.validate()
234   - } catch (e) {
235   - subTabsName.value = '${subClassNameVar}'
236   - return
237   - }
238   - #end
239   - #end
240   - #end
241   - // 提交请求
  198 +/** 打开弹窗 */
  199 +const open = async (type: string, id?: number) => {
  200 + dialogVisible.value = true
  201 + dialogTitle.value = t('action.' + type)
  202 + formType.value = type
  203 + resetForm()
  204 + // 修改时,设置数据
  205 + if (id) {
242 206 formLoading.value = true
243 207 try {
244   - const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO
245   - ## 特殊:主子表专属逻辑
246   - #if ( $table.templateType == 10 || $table.templateType == 12 )
247   - #if ( $subTables && $subTables.size() > 0 )
248   - // 拼接子表的数据
249   - #foreach ($subTable in $subTables)
250   - #set ($index = $foreach.count - 1)
251   - #set ($subClassNameVar = $subClassNameVars.get($index))
252   - data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = ${subClassNameVar}FormRef.value.getData()
253   - #end
254   - #end
255   - #end
256   - if (formType.value === 'create') {
257   - await ${simpleClassName}Api.create${simpleClassName}(data)
258   - message.success(t('common.createSuccess'))
259   - } else {
260   - await ${simpleClassName}Api.update${simpleClassName}(data)
261   - message.success(t('common.updateSuccess'))
262   - }
263   - dialogVisible.value = false
264   - // 发送操作成功的事件
265   - emit('success')
  208 + formData.value = await ${simpleClassName}Api.get${simpleClassName}(id)
266 209 } finally {
267 210 formLoading.value = false
268 211 }
269 212 }
  213 +## 特殊:树表专属逻辑
  214 +#if ( $table.templateType == 2 )
  215 + await get${simpleClassName}Tree()
  216 +#end
  217 +}
  218 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗
270 219  
271   - /** 重置表单 */
272   - const resetForm = () => {
273   - formData.value = {
274   - #foreach ($column in $columns)
275   - #if ($column.createOperation || $column.updateOperation)
276   - #if ($column.htmlType == "checkbox")
277   - $column.javaField: [],
278   - #else
279   - $column.javaField: undefined,
280   - #end
281   - #end
282   - #end
  220 +/** 提交表单 */
  221 +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  222 +const submitForm = async () => {
  223 + // 校验表单
  224 + await formRef.value.validate()
  225 +## 特殊:主子表专属逻辑
  226 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  227 +#if ( $subTables && $subTables.size() > 0 )
  228 + // 校验子表单
  229 + #foreach ($subTable in $subTables)
  230 + #set ($index = $foreach.count - 1)
  231 + #set ($subClassNameVar = $subClassNameVars.get($index))
  232 + try {
  233 + await ${subClassNameVar}FormRef.value.validate()
  234 + } catch (e) {
  235 + subTabsName.value = '${subClassNameVar}'
  236 + return
  237 + }
  238 + #end
  239 +#end
  240 +#end
  241 + // 提交请求
  242 + formLoading.value = true
  243 + try {
  244 + const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO
  245 +## 特殊:主子表专属逻辑
  246 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  247 +#if ( $subTables && $subTables.size() > 0 )
  248 + // 拼接子表的数据
  249 + #foreach ($subTable in $subTables)
  250 + #set ($index = $foreach.count - 1)
  251 + #set ($subClassNameVar = $subClassNameVars.get($index))
  252 + data.${subClassNameVar}#if ( $subTable.subJoinMany)s#end = ${subClassNameVar}FormRef.value.getData()
  253 + #end
  254 +#end
  255 +#end
  256 + if (formType.value === 'create') {
  257 + await ${simpleClassName}Api.create${simpleClassName}(data)
  258 + message.success(t('common.createSuccess'))
  259 + } else {
  260 + await ${simpleClassName}Api.update${simpleClassName}(data)
  261 + message.success(t('common.updateSuccess'))
283 262 }
284   - formRef.value?.resetFields()
  263 + dialogVisible.value = false
  264 + // 发送操作成功的事件
  265 + emit('success')
  266 + } finally {
  267 + formLoading.value = false
285 268 }
286   - ## 特殊:树表专属逻辑
287   - #if ( $table.templateType == 2 )
  269 +}
288 270  
289   - /** 获得${table.classComment}树 */
290   - const get${simpleClassName}Tree = async () => {
291   - ${classNameVar}Tree.value = []
292   - const data = await ${simpleClassName}Api.get${simpleClassName}List()
293   - const root: Tree = { id: 0, name: '顶级${table.classComment}', children: [] }
294   - root.children = handleTree(data, 'id', '${treeParentColumn.javaField}')
295   - ${classNameVar}Tree.value.push(root)
296   - }
  271 +/** 重置表单 */
  272 +const resetForm = () => {
  273 + formData.value = {
  274 +#foreach ($column in $columns)
  275 + #if ($column.createOperation || $column.updateOperation)
  276 + #if ($column.htmlType == "checkbox")
  277 + $column.javaField: [],
  278 + #else
  279 + $column.javaField: undefined,
297 280 #end
  281 + #end
  282 +#end
  283 + }
  284 + formRef.value?.resetFields()
  285 +}
  286 +## 特殊:树表专属逻辑
  287 +#if ( $table.templateType == 2 )
  288 +
  289 +/** 获得${table.classComment}树 */
  290 +const get${simpleClassName}Tree = async () => {
  291 + ${classNameVar}Tree.value = []
  292 + const data = await ${simpleClassName}Api.get${simpleClassName}List()
  293 + const root: Tree = { id: 0, name: '顶级${table.classComment}', children: [] }
  294 + root.children = handleTree(data, 'id', '${treeParentColumn.javaField}')
  295 + ${classNameVar}Tree.value.push(root)
  296 +}
  297 +#end
298 298 </script>
299 299 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
... ... @@ -2,375 +2,372 @@
2 2 <ContentWrap>
3 3 <!-- 搜索工作栏 -->
4 4 <el-form
5   - class="-mb-15px"
6   - :model="queryParams"
7   - ref="queryFormRef"
8   - :inline="true"
9   - label-width="68px"
  5 + class="-mb-15px"
  6 + :model="queryParams"
  7 + ref="queryFormRef"
  8 + :inline="true"
  9 + label-width="68px"
10 10 >
11   - #foreach($column in $columns)
12   - #if ($column.listOperation)
13   - #set ($dictType = $column.dictType)
14   - #set ($javaField = $column.javaField)
15   - #set ($javaType = $column.javaType)
16   - #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
17   - #set ($comment = $column.columnComment)
18   - #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
19   - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
20   - #set ($dictMethod = "getIntDictOptions")
21   - #elseif ($javaType == "String")
22   - #set ($dictMethod = "getStrDictOptions")
23   - #elseif ($javaType == "Boolean")
24   - #set ($dictMethod = "getBoolDictOptions")
25   - #end
26   - #if ($column.htmlType == "input")
27   - <el-form-item label="${comment}" prop="${javaField}">
28   - <el-input
29   - v-model="queryParams.${javaField}"
30   - placeholder="请输入${comment}"
31   - clearable
32   - @keyup.enter="handleQuery"
33   - class="!w-240px"
34   - />
35   - </el-form-item>
36   - #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
37   - <el-form-item label="${comment}" prop="${javaField}">
38   - <el-select
39   - v-model="queryParams.${javaField}"
40   - placeholder="请选择${comment}"
41   - clearable
42   - class="!w-240px"
43   - >
44   - #if ("" != $dictType)## 设置了 dictType 数据字典的情况
45   - <el-option
46   - v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
47   - :key="dict.value"
48   - :label="dict.label"
49   - :value="dict.value"
50   - />
51   - #else## 未设置 dictType 数据字典的情况
52   - <el-option label="请选择字典生成" value="" />
53   - #end
54   - </el-select>
55   - </el-form-item>
56   - #elseif($column.htmlType == "datetime")
57   - #if ($column.listOperationCondition != "BETWEEN")## 非范围
58   - <el-form-item label="${comment}" prop="${javaField}">
59   - <el-date-picker
60   - v-model="queryParams.${javaField}"
61   - value-format="YYYY-MM-DD"
62   - type="date"
63   - placeholder="选择${comment}"
64   - clearable
65   - class="!w-240px"
66   - />
67   - </el-form-item>
68   - #else## 范围
69   - <el-form-item label="${comment}" prop="${javaField}">
70   - <el-date-picker
71   - v-model="queryParams.${javaField}"
72   - value-format="YYYY-MM-DD HH:mm:ss"
73   - type="daterange"
74   - start-placeholder="开始日期"
75   - end-placeholder="结束日期"
76   - :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
77   - class="!w-240px"
78   - />
79   - </el-form-item>
80   - #end
81   - #end
  11 + #foreach($column in $columns)
  12 + #if ($column.listOperation)
  13 + #set ($dictType = $column.dictType)
  14 + #set ($javaField = $column.javaField)
  15 + #set ($javaType = $column.javaType)
  16 + #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
  17 + #set ($comment = $column.columnComment)
  18 + #set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
  19 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  20 + #set ($dictMethod = "getIntDictOptions")
  21 + #elseif ($javaType == "String")
  22 + #set ($dictMethod = "getStrDictOptions")
  23 + #elseif ($javaType == "Boolean")
  24 + #set ($dictMethod = "getBoolDictOptions")
82 25 #end
83   - #end
  26 + #if ($column.htmlType == "input")
  27 + <el-form-item label="${comment}" prop="${javaField}">
  28 + <el-input
  29 + v-model="queryParams.${javaField}"
  30 + placeholder="请输入${comment}"
  31 + clearable
  32 + @keyup.enter="handleQuery"
  33 + class="!w-240px"
  34 + />
  35 + </el-form-item>
  36 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
  37 + <el-form-item label="${comment}" prop="${javaField}">
  38 + <el-select
  39 + v-model="queryParams.${javaField}"
  40 + placeholder="请选择${comment}"
  41 + clearable
  42 + class="!w-240px"
  43 + >
  44 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  45 + <el-option
  46 + v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
  47 + :key="dict.value"
  48 + :label="dict.label"
  49 + :value="dict.value"
  50 + />
  51 + #else## 未设置 dictType 数据字典的情况
  52 + <el-option label="请选择字典生成" value="" />
  53 + #end
  54 + </el-select>
  55 + </el-form-item>
  56 + #elseif($column.htmlType == "datetime")
  57 + #if ($column.listOperationCondition != "BETWEEN")## 非范围
  58 + <el-form-item label="${comment}" prop="${javaField}">
  59 + <el-date-picker
  60 + v-model="queryParams.${javaField}"
  61 + value-format="YYYY-MM-DD"
  62 + type="date"
  63 + placeholder="选择${comment}"
  64 + clearable
  65 + class="!w-240px"
  66 + />
  67 + </el-form-item>
  68 + #else## 范围
  69 + <el-form-item label="${comment}" prop="${javaField}">
  70 + <el-date-picker
  71 + v-model="queryParams.${javaField}"
  72 + value-format="YYYY-MM-DD HH:mm:ss"
  73 + type="daterange"
  74 + start-placeholder="开始日期"
  75 + end-placeholder="结束日期"
  76 + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  77 + class="!w-240px"
  78 + />
  79 + </el-form-item>
  80 + #end
  81 + #end
  82 + #end
  83 + #end
84 84 <el-form-item>
85 85 <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
86 86 <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
87 87 <el-button
88   - type="primary"
89   - plain
90   - @click="openForm('create')"
91   - v-hasPermi="['${permissionPrefix}:create']"
  88 + type="primary"
  89 + plain
  90 + @click="openForm('create')"
  91 + v-hasPermi="['${permissionPrefix}:create']"
92 92 >
93 93 <Icon icon="ep:plus" class="mr-5px" /> 新增
94 94 </el-button>
95 95 <el-button
96   - type="success"
97   - plain
98   - @click="handleExport"
99   - :loading="exportLoading"
100   - v-hasPermi="['${permissionPrefix}:export']"
  96 + type="success"
  97 + plain
  98 + @click="handleExport"
  99 + :loading="exportLoading"
  100 + v-hasPermi="['${permissionPrefix}:export']"
101 101 >
102 102 <Icon icon="ep:download" class="mr-5px" /> 导出
103 103 </el-button>
104   - ## 特殊:树表专属逻辑
105   - #if ( $table.templateType == 2 )
106   - <el-button type="danger" plain @click="toggleExpandAll">
107   - <Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
108   - </el-button>
109   - #end
  104 +## 特殊:树表专属逻辑
  105 +#if ( $table.templateType == 2 )
  106 + <el-button type="danger" plain @click="toggleExpandAll">
  107 + <Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
  108 + </el-button>
  109 +#end
110 110 </el-form-item>
111 111 </el-form>
112 112 </ContentWrap>
113 113  
114 114 <!-- 列表 -->
115 115 <ContentWrap>
116   - ## 特殊:主子表专属逻辑
117   - #if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
118   - <el-table
119   - v-loading="loading"
120   - :data="list"
121   - :stripe="true"
122   - :show-overflow-tooltip="true"
123   - highlight-current-row
124   - @current-change="handleCurrentChange"
125   - >
126   - ## 特殊:树表专属逻辑
127   - #elseif ( $table.templateType == 2 )
128   - <el-table
129   - v-loading="loading"
130   - :data="list"
131   - :stripe="true"
132   - :show-overflow-tooltip="true"
133   - row-key="id"
134   - :default-expand-all="isExpandAll"
135   - v-if="refreshTable"
136   - >
137   - #else
138   - <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
139   - #end
140   - ## 特殊:主子表专属逻辑
141   - #if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
142   - <!-- 子表的列表 -->
143   - <el-table-column type="expand">
144   - <template #default="scope">
145   - <el-tabs model-value="$subClassNameVars.get(0)">
146   - #foreach ($subTable in $subTables)
147   - #set ($index = $foreach.count - 1)
148   - #set ($subClassNameVar = $subClassNameVars.get($index))
149   - #set ($subSimpleClassName = $subSimpleClassNames.get($index))
150   - #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
151   - <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
152   - <${subSimpleClassName}List :${subJoinColumn_strikeCase}="scope.row.id" />
153   - </el-tab-pane>
154   - #end
155   - </el-tabs>
156   - </template>
157   - </el-table-column>
158   - #end
  116 +## 特殊:主子表专属逻辑
  117 +#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
  118 + <el-table
  119 + v-loading="loading"
  120 + :data="list"
  121 + :stripe="true"
  122 + :show-overflow-tooltip="true"
  123 + highlight-current-row
  124 + @current-change="handleCurrentChange"
  125 + >
  126 +## 特殊:树表专属逻辑
  127 +#elseif ( $table.templateType == 2 )
  128 + <el-table
  129 + v-loading="loading"
  130 + :data="list"
  131 + :stripe="true"
  132 + :show-overflow-tooltip="true"
  133 + row-key="id"
  134 + :default-expand-all="isExpandAll"
  135 + v-if="refreshTable"
  136 + >
  137 +#else
  138 + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
  139 +#end
  140 +## 特殊:主子表专属逻辑
  141 +#if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
  142 + <!-- 子表的列表 -->
  143 + <el-table-column type="expand">
  144 + <template #default="scope">
  145 + <el-tabs model-value="$subClassNameVars.get(0)">
  146 + #foreach ($subTable in $subTables)
  147 + #set ($index = $foreach.count - 1)
  148 + #set ($subClassNameVar = $subClassNameVars.get($index))
  149 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  150 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  151 + <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
  152 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="scope.row.id" />
  153 + </el-tab-pane>
  154 + #end
  155 + </el-tabs>
  156 + </template>
  157 + </el-table-column>
  158 +#end
159 159 #foreach($column in $columns)
160   - #if ($column.listOperationResult)
161   - #set ($dictType=$column.dictType)
162   - #set ($javaField = $column.javaField)
163   - #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
164   - #set ($comment=$column.columnComment)
165   - #if ($column.javaType == "LocalDateTime")## 时间类型
166   - <el-table-column
167   - label="${comment}"
168   - align="center"
169   - prop="${javaField}"
170   - :formatter="dateFormatter"
171   - width="180px"
172   - />
173   - #elseif($column.dictType && "" != $column.dictType)## 数据字典
174   - <el-table-column label="${comment}" align="center" prop="${javaField}">
175   - <template #default="scope">
176   - <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
177   - </template>
178   - </el-table-column>
179   - #else
180   - <el-table-column label="${comment}" align="center" prop="${javaField}" />
181   - #end
182   - #end
  160 + #if ($column.listOperationResult)
  161 + #set ($dictType=$column.dictType)
  162 + #set ($javaField = $column.javaField)
  163 + #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
  164 + #set ($comment=$column.columnComment)
  165 + #if ($column.javaType == "LocalDateTime")## 时间类型
  166 + <el-table-column
  167 + label="${comment}"
  168 + align="center"
  169 + prop="${javaField}"
  170 + :formatter="dateFormatter"
  171 + width="180px"
  172 + />
  173 + #elseif($column.dictType && "" != $column.dictType)## 数据字典
  174 + <el-table-column label="${comment}" align="center" prop="${javaField}">
  175 + <template #default="scope">
  176 + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
  177 + </template>
  178 + </el-table-column>
  179 + #else
  180 + <el-table-column label="${comment}" align="center" prop="${javaField}" />
  181 + #end
183 182 #end
184   - <el-table-column label="操作" align="center">
185   - <template #default="scope">
186   - <el-button
  183 + #end
  184 + <el-table-column label="操作" align="center">
  185 + <template #default="scope">
  186 + <el-button
187 187 link
188 188 type="primary"
189 189 @click="openForm('update', scope.row.id)"
190 190 v-hasPermi="['${permissionPrefix}:update']"
191   - >
192   - 编辑
193   - </el-button>
194   - <el-button
  191 + >
  192 + 编辑
  193 + </el-button>
  194 + <el-button
195 195 link
196 196 type="danger"
197 197 @click="handleDelete(scope.row.id)"
198 198 v-hasPermi="['${permissionPrefix}:delete']"
199   - >
200   - 删除
201   - </el-button>
202   - </template>
203   - </el-table-column>
204   - </el-table>
205   -## 特殊:树表专属逻辑(树不需要分页)
206   -#if ( $table.templateType != 2 )
  199 + >
  200 + 删除
  201 + </el-button>
  202 + </template>
  203 + </el-table-column>
  204 + </el-table>
207 205 <!-- 分页 -->
208 206 <Pagination
209   - :total="total"
210   - v-model:page="queryParams.pageNo"
211   - v-model:limit="queryParams.pageSize"
212   - @pagination="getList"
  207 + :total="total"
  208 + v-model:page="queryParams.pageNo"
  209 + v-model:limit="queryParams.pageSize"
  210 + @pagination="getList"
213 211 />
214   -#end
215 212 </ContentWrap>
216 213  
217 214 <!-- 表单弹窗:添加/修改 -->
218 215 <${simpleClassName}Form ref="formRef" @success="getList" />
219   - ## 特殊:主子表专属逻辑
220   - #if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
221   - <!-- 子表的列表 -->
222   - <ContentWrap>
223   - <el-tabs model-value="$subClassNameVars.get(0)">
224   - #foreach ($subTable in $subTables)
225   - #set ($index = $foreach.count - 1)
226   - #set ($subClassNameVar = $subClassNameVars.get($index))
227   - #set ($subSimpleClassName = $subSimpleClassNames.get($index))
228   - #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
229   - <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
230   - <${subSimpleClassName}List :${subJoinColumn_strikeCase}="currentRow.id" />
231   - </el-tab-pane>
232   - #end
233   - </el-tabs>
234   - </ContentWrap>
235   - #end
  216 +## 特殊:主子表专属逻辑
  217 +#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 )
  218 + <!-- 子表的列表 -->
  219 + <ContentWrap>
  220 + <el-tabs model-value="$subClassNameVars.get(0)">
  221 + #foreach ($subTable in $subTables)
  222 + #set ($index = $foreach.count - 1)
  223 + #set ($subClassNameVar = $subClassNameVars.get($index))
  224 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  225 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  226 + <el-tab-pane label="${subTable.classComment}" name="$subClassNameVar">
  227 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="currentRow.id" />
  228 + </el-tab-pane>
  229 + #end
  230 + </el-tabs>
  231 + </ContentWrap>
  232 +#end
236 233 </template>
237 234  
238 235 <script setup lang="ts">
239   - import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
240   - import { dateFormatter } from '@/utils/formatTime'
241   - ## 特殊:树表专属逻辑
242   - #if ( $table.templateType == 2 )
243   - import { handleTree } from '@/utils/tree'
244   - #end
245   - import download from '@/utils/download'
246   - import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
247   - import ${simpleClassName}Form from './${simpleClassName}Form.vue'
248   - ## 特殊:主子表专属逻辑
249   - #if ( $table.templateType != 10 )
250   - #foreach ($subSimpleClassName in $subSimpleClassNames)
251   - import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vue'
252   - #end
253   - #end
  236 +import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
  237 +import { dateFormatter } from '@/utils/formatTime'
  238 +## 特殊:树表专属逻辑
  239 +#if ( $table.templateType == 2 )
  240 +import { handleTree } from '@/utils/tree'
  241 +#end
  242 +import download from '@/utils/download'
  243 +import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${table.businessName}'
  244 +import ${simpleClassName}Form from './${simpleClassName}Form.vue'
  245 +## 特殊:主子表专属逻辑
  246 +#if ( $table.templateType != 10 )
  247 +#foreach ($subSimpleClassName in $subSimpleClassNames)
  248 +import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vue'
  249 +#end
  250 +#end
254 251  
255   - defineOptions({ name: '${table.className}' })
  252 +defineOptions({ name: '${table.className}' })
256 253  
257   - const message = useMessage() // 消息弹窗
258   - const { t } = useI18n() // 国际化
  254 +const message = useMessage() // 消息弹窗
  255 +const { t } = useI18n() // 国际化
259 256  
260   - const loading = ref(true) // 列表的加载中
261   - const list = ref([]) // 列表的数据
262   - ## 特殊:树表专属逻辑(树不需要分页接口)
263   - #if ( $table.templateType != 2 )
264   - const total = ref(0) // 列表的总页数
265   - #end
266   - const queryParams = reactive({
267   - ## 特殊:树表专属逻辑(树不需要分页接口)
268   - #if ( $table.templateType != 2 )
269   - pageNo: 1,
270   - pageSize: 10,
271   - #end
272   - #foreach ($column in $columns)
273   - #if ($column.listOperation)
274   - #if ($column.listOperationCondition != 'BETWEEN')
275   - $column.javaField: null,
276   - #end
277   - #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
278   - $column.javaField: [],
279   - #end
280   - #end
  257 +const loading = ref(true) // 列表的加载中
  258 +const list = ref([]) // 列表的数据
  259 +## 特殊:树表专属逻辑(树不需要分页接口)
  260 +#if ( $table.templateType != 2 )
  261 +const total = ref(0) // 列表的总页数
  262 +#end
  263 +const queryParams = reactive({
  264 +## 特殊:树表专属逻辑(树不需要分页接口)
  265 +#if ( $table.templateType != 2 )
  266 + pageNo: 1,
  267 + pageSize: 10,
  268 +#end
  269 + #foreach ($column in $columns)
  270 + #if ($column.listOperation)
  271 + #if ($column.listOperationCondition != 'BETWEEN')
  272 + $column.javaField: null,
  273 + #end
  274 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  275 + $column.javaField: [],
281 276 #end
282   - })
283   - const queryFormRef = ref() // 搜索的表单
284   - const exportLoading = ref(false) // 导出的加载中
  277 + #end
  278 + #end
  279 +})
  280 +const queryFormRef = ref() // 搜索的表单
  281 +const exportLoading = ref(false) // 导出的加载中
285 282  
286   - /** 查询列表 */
287   - const getList = async () => {
288   - loading.value = true
289   - try {
290   - ## 特殊:树表专属逻辑(树不需要分页接口)
291   - #if ( $table.templateType == 2 )
292   - const data = await ${simpleClassName}Api.get${simpleClassName}List(queryParams)
293   - list.value = handleTree(data, 'id', '${treeParentColumn.javaField}')
294   - #else
295   - const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
296   - list.value = data.list
297   - total.value = data.total
298   - #end
299   - } finally {
300   - loading.value = false
301   - }
  283 +/** 查询列表 */
  284 +const getList = async () => {
  285 + loading.value = true
  286 + try {
  287 +## 特殊:树表专属逻辑(树不需要分页接口)
  288 + #if ( $table.templateType == 2 )
  289 + const data = await ${simpleClassName}Api.get${simpleClassName}List(queryParams)
  290 + list.value = handleTree(data, 'id', '${treeParentColumn.javaField}')
  291 + #else
  292 + const data = await ${simpleClassName}Api.get${simpleClassName}Page(queryParams)
  293 + list.value = data.list
  294 + total.value = data.total
  295 + #end
  296 + } finally {
  297 + loading.value = false
302 298 }
  299 +}
303 300  
304   - /** 搜索按钮操作 */
305   - const handleQuery = () => {
306   - queryParams.pageNo = 1
307   - getList()
308   - }
  301 +/** 搜索按钮操作 */
  302 +const handleQuery = () => {
  303 + queryParams.pageNo = 1
  304 + getList()
  305 +}
309 306  
310   - /** 重置按钮操作 */
311   - const resetQuery = () => {
312   - queryFormRef.value.resetFields()
313   - handleQuery()
314   - }
  307 +/** 重置按钮操作 */
  308 +const resetQuery = () => {
  309 + queryFormRef.value.resetFields()
  310 + handleQuery()
  311 +}
315 312  
316   - /** 添加/修改操作 */
317   - const formRef = ref()
318   - const openForm = (type: string, id?: number) => {
319   - formRef.value.open(type, id)
320   - }
  313 +/** 添加/修改操作 */
  314 +const formRef = ref()
  315 +const openForm = (type: string, id?: number) => {
  316 + formRef.value.open(type, id)
  317 +}
321 318  
322   - /** 删除按钮操作 */
323   - const handleDelete = async (id: number) => {
324   - try {
325   - // 删除的二次确认
326   - await message.delConfirm()
327   - // 发起删除
328   - await ${simpleClassName}Api.delete${simpleClassName}(id)
329   - message.success(t('common.delSuccess'))
330   - // 刷新列表
331   - await getList()
332   - } catch {}
333   - }
  319 +/** 删除按钮操作 */
  320 +const handleDelete = async (id: number) => {
  321 + try {
  322 + // 删除的二次确认
  323 + await message.delConfirm()
  324 + // 发起删除
  325 + await ${simpleClassName}Api.delete${simpleClassName}(id)
  326 + message.success(t('common.delSuccess'))
  327 + // 刷新列表
  328 + await getList()
  329 + } catch {}
  330 +}
334 331  
335   - /** 导出按钮操作 */
336   - const handleExport = async () => {
337   - try {
338   - // 导出的二次确认
339   - await message.exportConfirm()
340   - // 发起导出
341   - exportLoading.value = true
342   - const data = await ${simpleClassName}Api.export${simpleClassName}(queryParams)
343   - download.excel(data, '${table.classComment}.xls')
344   - } catch {
345   - } finally {
346   - exportLoading.value = false
347   - }
  332 +/** 导出按钮操作 */
  333 +const handleExport = async () => {
  334 + try {
  335 + // 导出的二次确认
  336 + await message.exportConfirm()
  337 + // 发起导出
  338 + exportLoading.value = true
  339 + const data = await ${simpleClassName}Api.export${simpleClassName}(queryParams)
  340 + download.excel(data, '${table.classComment}.xls')
  341 + } catch {
  342 + } finally {
  343 + exportLoading.value = false
348 344 }
349   - ## 特殊:主子表专属逻辑
350   - #if ( $table.templateType == 11 )
  345 +}
  346 +## 特殊:主子表专属逻辑
  347 +#if ( $table.templateType == 11 )
351 348  
352   - /** 选中行操作 */
353   - const currentRow = ref({}) // 选中行
354   - const handleCurrentChange = (row) => {
355   - currentRow.value = row
356   - }
357   - #end
358   - ## 特殊:树表专属逻辑
359   - #if ( $table.templateType == 2 )
  349 +/** 选中行操作 */
  350 +const currentRow = ref({}) // 选中行
  351 +const handleCurrentChange = (row) => {
  352 + currentRow.value = row
  353 +}
  354 +#end
  355 +## 特殊:树表专属逻辑
  356 +#if ( $table.templateType == 2 )
360 357  
361   - /** 展开/折叠操作 */
362   - const isExpandAll = ref(true) // 是否展开,默认全部展开
363   - const refreshTable = ref(true) // 重新渲染表格状态
364   - const toggleExpandAll = async () => {
365   - refreshTable.value = false
366   - isExpandAll.value = !isExpandAll.value
367   - await nextTick()
368   - refreshTable.value = true
369   - }
370   - #end
  358 +/** 展开/折叠操作 */
  359 +const isExpandAll = ref(true) // 是否展开,默认全部展开
  360 +const refreshTable = ref(true) // 重新渲染表格状态
  361 +const toggleExpandAll = async () => {
  362 + refreshTable.value = false
  363 + isExpandAll.value = !isExpandAll.value
  364 + await nextTick()
  365 + refreshTable.value = true
  366 +}
  367 +#end
371 368  
372   - /** 初始化 **/
373   - onMounted(() => {
374   - getList()
375   - })
  369 +/** 初始化 **/
  370 +onMounted(() => {
  371 + getList()
  372 +})
376 373 </script>
377 374 \ No newline at end of file
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineAbstractTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.infra.service.codegen.inner;
  2 +
  3 +import cn.hutool.core.io.FileUtil;
  4 +import cn.hutool.core.io.IoUtil;
  5 +import cn.hutool.core.io.resource.ResourceUtil;
  6 +import cn.hutool.core.map.MapUtil;
  7 +import cn.hutool.core.util.StrUtil;
  8 +import cn.hutool.core.util.ZipUtil;
  9 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  10 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  11 +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
  12 +import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
  13 +import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
  14 +import org.junit.jupiter.api.BeforeEach;
  15 +import org.mockito.InjectMocks;
  16 +import org.mockito.Spy;
  17 +
  18 +import java.io.ByteArrayInputStream;
  19 +import java.io.ByteArrayOutputStream;
  20 +import java.util.ArrayList;
  21 +import java.util.HashMap;
  22 +import java.util.List;
  23 +import java.util.Map;
  24 +
  25 +import static org.junit.jupiter.api.Assertions.assertEquals;
  26 +
  27 +/**
  28 + * {@link CodegenEngine} 的单元测试抽象基类
  29 + *
  30 + * @author 芋道源码
  31 + */
  32 +public abstract class CodegenEngineAbstractTest extends BaseMockitoUnitTest {
  33 +
  34 + @InjectMocks
  35 + protected CodegenEngine codegenEngine;
  36 +
  37 + @Spy
  38 + protected CodegenProperties codegenProperties = new CodegenProperties()
  39 + .setBasePackage("cn.iocoder.yudao");
  40 +
  41 + @BeforeEach
  42 + public void setUp() {
  43 + codegenEngine.initGlobalBindingMap();
  44 + }
  45 +
  46 + protected static CodegenTableDO getTable(String name) {
  47 + String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
  48 + return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
  49 + }
  50 +
  51 + protected static List<CodegenColumnDO> getColumnList(String name) {
  52 + String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
  53 + List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
  54 + list.forEach(column -> {
  55 + if (column.getNullable() == null) {
  56 + column.setNullable(false);
  57 + }
  58 + if (column.getCreateOperation() == null) {
  59 + column.setCreateOperation(false);
  60 + }
  61 + if (column.getUpdateOperation() == null) {
  62 + column.setUpdateOperation(false);
  63 + }
  64 + if (column.getListOperation() == null) {
  65 + column.setListOperation(false);
  66 + }
  67 + if (column.getListOperationResult() == null) {
  68 + column.setListOperationResult(false);
  69 + }
  70 + });
  71 + return list;
  72 + }
  73 +
  74 + @SuppressWarnings("rawtypes")
  75 + protected static void assertResult(Map<String, String> result, String path) {
  76 + String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
  77 + List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
  78 + assertEquals(asserts.size(), result.size());
  79 + // 校验每个文件
  80 + asserts.forEach(assertMap -> {
  81 + String contentPath = (String) assertMap.get("contentPath");
  82 + String filePath = (String) assertMap.get("filePath");
  83 + String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
  84 + assertEquals(content, result.get(filePath), filePath + ":不匹配");
  85 + });
  86 + }
  87 +
  88 + // ==================== 调试专用 ====================
  89 +
  90 + /**
  91 + * 【调试使用】将生成的代码,写入到文件
  92 + *
  93 + * @param result 生成的代码
  94 + * @param path 写入文件的路径
  95 + */
  96 + protected void writeFile(Map<String, String> result, String path) {
  97 + // 生成压缩包
  98 + String[] paths = result.keySet().toArray(new String[0]);
  99 + ByteArrayInputStream[] ins = result.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
  100 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  101 + ZipUtil.zip(outputStream, paths, ins);
  102 + // 写入文件
  103 + FileUtil.writeBytes(outputStream.toByteArray(), path);
  104 + }
  105 +
  106 + /**
  107 + * 【调试使用】将生成的结果,写入到文件
  108 + *
  109 + * @param result 生成的代码
  110 + * @param basePath 写入文件的路径(绝对路径)
  111 + */
  112 + protected void writeResult(Map<String, String> result, String basePath) {
  113 + // 写入文件内容
  114 + List<Map<String, String>> asserts = new ArrayList<>();
  115 + result.forEach((filePath, fileContent) -> {
  116 + String lastFilePath = StrUtil.subAfter(filePath, '/', true);
  117 + String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
  118 + + '/' + StrUtil.subBefore(lastFilePath, '.', true);
  119 + asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
  120 + .put("contentPath", contentPath).build());
  121 + FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
  122 + });
  123 + // 写入 assert.json 文件
  124 + FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
  125 + }
  126 +
  127 +}
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue2Test.java
1 1 package cn.iocoder.yudao.module.infra.service.codegen.inner;
2 2  
3   -import cn.hutool.core.io.FileUtil;
4   -import cn.hutool.core.io.IoUtil;
5   -import cn.hutool.core.io.resource.ResourceUtil;
6   -import cn.hutool.core.map.MapUtil;
7   -import cn.hutool.core.util.StrUtil;
8   -import cn.hutool.core.util.ZipUtil;
9   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
10   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
11 3 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
12 4 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
13 5 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
14 6 import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
15   -import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
16   -import org.junit.jupiter.api.BeforeEach;
17 7 import org.junit.jupiter.api.Test;
18   -import org.mockito.InjectMocks;
19   -import org.mockito.Spy;
20 8  
21   -import java.io.ByteArrayInputStream;
22   -import java.io.ByteArrayOutputStream;
23   -import java.util.*;
24   -
25   -import static org.junit.jupiter.api.Assertions.assertEquals;
  9 +import java.util.Arrays;
  10 +import java.util.List;
  11 +import java.util.Map;
26 12  
27 13 /**
28   - * {@link CodegenEngine} 的单元测试
  14 + * {@link CodegenEngine} 的 Vue2 + Element UI 单元测试
29 15 *
30 16 * @author 芋道源码
31 17 */
32   -public class CodegenEngineVue2Test extends BaseMockitoUnitTest {
33   -
34   - @InjectMocks
35   - private CodegenEngine codegenEngine;
36   -
37   - @Spy
38   - private CodegenProperties codegenProperties = new CodegenProperties()
39   - .setBasePackage("cn.iocoder.yudao");
40   -
41   - @BeforeEach
42   - public void setUp() {
43   - codegenEngine.initGlobalBindingMap();
44   - }
  18 +public class CodegenEngineVue2Test extends CodegenEngineAbstractTest {
45 19  
46 20 @Test
47 21 public void testExecute_vue2_one() {
... ... @@ -118,85 +92,4 @@ public class CodegenEngineVue2Test extends BaseMockitoUnitTest {
118 92 // writeFile(result, "/Users/yunai/test/demo11.zip");
119 93 }
120 94  
121   - private static CodegenTableDO getTable(String name) {
122   - String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
123   - return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
124   - }
125   -
126   - private static List<CodegenColumnDO> getColumnList(String name) {
127   - String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
128   - List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
129   - list.forEach(column -> {
130   - if (column.getNullable() == null) {
131   - column.setNullable(false);
132   - }
133   - if (column.getCreateOperation() == null) {
134   - column.setCreateOperation(false);
135   - }
136   - if (column.getUpdateOperation() == null) {
137   - column.setUpdateOperation(false);
138   - }
139   - if (column.getListOperation() == null) {
140   - column.setListOperation(false);
141   - }
142   - if (column.getListOperationResult() == null) {
143   - column.setListOperationResult(false);
144   - }
145   - });
146   - return list;
147   - }
148   -
149   - @SuppressWarnings("rawtypes")
150   - private static void assertResult(Map<String, String> result, String path) {
151   - String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
152   - List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
153   - assertEquals(asserts.size(), result.size());
154   - // 校验每个文件
155   - asserts.forEach(assertMap -> {
156   - String contentPath = (String) assertMap.get("contentPath");
157   - String filePath = (String) assertMap.get("filePath");
158   - String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
159   - assertEquals(content, result.get(filePath), filePath + ":不匹配");
160   - });
161   - }
162   -
163   - // ==================== 调试专用 ====================
164   -
165   - /**
166   - * 【调试使用】将生成的代码,写入到文件
167   - *
168   - * @param result 生成的代码
169   - * @param path 写入文件的路径
170   - */
171   - private void writeFile(Map<String, String> result, String path) {
172   - // 生成压缩包
173   - String[] paths = result.keySet().toArray(new String[0]);
174   - ByteArrayInputStream[] ins = result.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
175   - ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
176   - ZipUtil.zip(outputStream, paths, ins);
177   - // 写入文件
178   - FileUtil.writeBytes(outputStream.toByteArray(), path);
179   - }
180   -
181   - /**
182   - * 【调试使用】将生成的结果,写入到文件
183   - *
184   - * @param result 生成的代码
185   - * @param basePath 写入文件的路径(绝对路径)
186   - */
187   - private void writeResult(Map<String, String> result, String basePath) {
188   - // 写入文件内容
189   - List<Map<String, String>> asserts = new ArrayList<>();
190   - result.forEach((filePath, fileContent) -> {
191   - String lastFilePath = StrUtil.subAfter(filePath, '/', true);
192   - String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
193   - + '/' + StrUtil.subBefore(lastFilePath, '.', true);
194   - asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
195   - .put("contentPath", contentPath).build());
196   - FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
197   - });
198   - // 写入 assert.json 文件
199   - FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
200   - }
201   -
202 95 }
... ...
yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineTest.java renamed to yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue3Test.java
1 1 package cn.iocoder.yudao.module.infra.service.codegen.inner;
2 2  
3   -import cn.hutool.core.io.FileUtil;
4   -import cn.hutool.core.io.IoUtil;
5   -import cn.hutool.core.io.resource.ResourceUtil;
6   -import cn.hutool.core.map.MapUtil;
7   -import cn.hutool.core.util.StrUtil;
8   -import cn.hutool.core.util.ZipUtil;
9   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
10   -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
11 3 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
12 4 import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
13   -import cn.iocoder.yudao.module.infra.enums.codegen.*;
14   -import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
15   -import org.apache.ibatis.type.JdbcType;
16   -import org.junit.jupiter.api.BeforeEach;
  5 +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
  6 +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
17 7 import org.junit.jupiter.api.Test;
18   -import org.mockito.InjectMocks;
19   -import org.mockito.Spy;
20 8  
21   -import java.io.ByteArrayInputStream;
22   -import java.io.ByteArrayOutputStream;
23   -import java.util.*;
24   -
25   -import static org.junit.jupiter.api.Assertions.assertEquals;
26   -import static org.junit.jupiter.api.Assertions.assertTrue;
  9 +import java.util.Arrays;
  10 +import java.util.List;
  11 +import java.util.Map;
27 12  
28 13 /**
29   - * {@link CodegenEngine} 的单元测试
  14 + * {@link CodegenEngine} 的 Vue2 + Element Plus 单元测试
30 15 *
31 16 * @author 芋道源码
32 17 */
33   -public class CodegenEngineTest extends BaseMockitoUnitTest {
34   -
35   - @InjectMocks
36   - private CodegenEngine codegenEngine;
37   -
38   - @Spy
39   - private CodegenProperties codegenProperties = new CodegenProperties()
40   - .setBasePackage("cn.iocoder.yudao");
41   -
42   - @BeforeEach
43   - public void setUp() {
44   - codegenEngine.initGlobalBindingMap();
45   - }
  18 +public class CodegenEngineVue3Test extends CodegenEngineAbstractTest {
46 19  
47 20 @Test
48 21 public void testExecute_vue3_one() {
... ... @@ -119,85 +92,4 @@ public class CodegenEngineTest extends BaseMockitoUnitTest {
119 92 // writeFile(result, "/Users/yunai/test/demo11.zip");
120 93 }
121 94  
122   - private static CodegenTableDO getTable(String name) {
123   - String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
124   - return JsonUtils.parseObject(content, "table", CodegenTableDO.class);
125   - }
126   -
127   - private static List<CodegenColumnDO> getColumnList(String name) {
128   - String content = ResourceUtil.readUtf8Str("codegen/table/" + name + ".json");
129   - List<CodegenColumnDO> list = JsonUtils.parseArray(content, "columns", CodegenColumnDO.class);
130   - list.forEach(column -> {
131   - if (column.getNullable() == null) {
132   - column.setNullable(false);
133   - }
134   - if (column.getCreateOperation() == null) {
135   - column.setCreateOperation(false);
136   - }
137   - if (column.getUpdateOperation() == null) {
138   - column.setUpdateOperation(false);
139   - }
140   - if (column.getListOperation() == null) {
141   - column.setListOperation(false);
142   - }
143   - if (column.getListOperationResult() == null) {
144   - column.setListOperationResult(false);
145   - }
146   - });
147   - return list;
148   - }
149   -
150   - @SuppressWarnings("rawtypes")
151   - private static void assertResult(Map<String, String> result, String path) {
152   - String assertContent = ResourceUtil.readUtf8Str(path + "/assert.json");
153   - List<HashMap> asserts = JsonUtils.parseArray(assertContent, HashMap.class);
154   - assertEquals(asserts.size(), result.size());
155   - // 校验每个文件
156   - asserts.forEach(assertMap -> {
157   - String contentPath = (String) assertMap.get("contentPath");
158   - String filePath = (String) assertMap.get("filePath");
159   - String content = ResourceUtil.readUtf8Str(path + "/" + contentPath);
160   - assertEquals(content, result.get(filePath), filePath + ":不匹配");
161   - });
162   - }
163   -
164   - // ==================== 调试专用 ====================
165   -
166   - /**
167   - * 【调试使用】将生成的代码,写入到文件
168   - *
169   - * @param result 生成的代码
170   - * @param path 写入文件的路径
171   - */
172   - private void writeFile(Map<String, String> result, String path) {
173   - // 生成压缩包
174   - String[] paths = result.keySet().toArray(new String[0]);
175   - ByteArrayInputStream[] ins = result.values().stream().map(IoUtil::toUtf8Stream).toArray(ByteArrayInputStream[]::new);
176   - ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
177   - ZipUtil.zip(outputStream, paths, ins);
178   - // 写入文件
179   - FileUtil.writeBytes(outputStream.toByteArray(), path);
180   - }
181   -
182   - /**
183   - * 【调试使用】将生成的结果,写入到文件
184   - *
185   - * @param result 生成的代码
186   - * @param basePath 写入文件的路径(绝对路径)
187   - */
188   - private void writeResult(Map<String, String> result, String basePath) {
189   - // 写入文件内容
190   - List<Map<String, String>> asserts = new ArrayList<>();
191   - result.forEach((filePath, fileContent) -> {
192   - String lastFilePath = StrUtil.subAfter(filePath, '/', true);
193   - String contentPath = StrUtil.subAfter(lastFilePath, '.', true)
194   - + '/' + StrUtil.subBefore(lastFilePath, '.', true);
195   - asserts.add(MapUtil.<String, String>builder().put("filePath", filePath)
196   - .put("contentPath", contentPath).build());
197   - FileUtil.writeUtf8String(fileContent, basePath + "/" + contentPath);
198   - });
199   - // 写入 assert.json 文件
200   - FileUtil.writeUtf8String(JsonUtils.toJsonPrettyString(asserts), basePath +"/assert.json");
201   - }
202   -
203 95 }
... ...