Commit 47f3c560fad2b8f98dea8784445592cf51cde565

Authored by xingyu4j
1 parent ddc42c2a

feat: vue3 codegen

yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
@@ -91,8 +91,6 @@ public class CodegenEngine { @@ -91,8 +91,6 @@ public class CodegenEngine {
91 vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) 91 vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts"))
92 .put(vue3TemplatePath("api/api.ts"), 92 .put(vue3TemplatePath("api/api.ts"),
93 vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) 93 vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts"))
94 - .put(vue3TemplatePath("api/types.ts"),  
95 - vue3FilePath("api/${table.moduleName}/${classNameVar}/types.ts"))  
96 // SQL 94 // SQL
97 .put("codegen/sql/sql.vm", "sql/sql.sql") 95 .put("codegen/sql/sql.vm", "sql/sql.sql")
98 .put("codegen/sql/h2.vm", "sql/h2.sql") 96 .put("codegen/sql/h2.vm", "sql/h2.sql")
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
1 import request from '@/config/axios' 1 import request from '@/config/axios'
2 -import { ${simpleClassName}VO, ${simpleClassName}PageReqVO, ${simpleClassName}ExcelReqVO } from './types'  
3 2
  3 +export interface ${simpleClassName}VO {
  4 +#foreach ($column in $columns)
  5 +#if ($column.createOperation || $column.updateOperation)
  6 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
  7 + ${column.javaField}?: number
  8 +#elseif(${column.javaType.toLowerCase()} == "date")
  9 + ${column.javaField}?: string
  10 +#else
  11 + ${column.javaField}?: ${column.javaType.toLowerCase()}
  12 +#end
  13 +#end
  14 +#end
  15 +}
  16 +
  17 +export interface ${simpleClassName}PageReqVO extends PageParam {
  18 +#foreach ($column in $columns)
  19 +#if (${column.listOperation})##查询操作
  20 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
  21 + ${column.javaField}?: number
  22 +#elseif(${column.javaType.toLowerCase()} == "date")
  23 + ${column.javaField}?: string
  24 +#else
  25 + ${column.javaField}?: ${column.javaType.toLowerCase()}
  26 +#end
  27 +#end
  28 +#end
  29 +}
  30 +
  31 +export interface ${simpleClassName}ExcelReqVO {
  32 + #foreach ($column in $columns)
  33 + #if (${column.listOperation})##查询操作
  34 + #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
  35 + ${column.javaField}: number
  36 + #elseif(${column.javaType.toLowerCase()} == "date")
  37 + ${column.javaField}: string
  38 + #else
  39 + ${column.javaField}: ${column.javaType.toLowerCase()}
  40 + #end
  41 + #end
  42 + #end
  43 +}
4 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") 44 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
  45 +
5 // 查询${table.classComment}列表 46 // 查询${table.classComment}列表
6 export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => { 47 export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => {
7 return await request.get({ url: '${baseURL}/page', params }) 48 return await request.get({ url: '${baseURL}/page', params })
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm deleted
1 -export type ${simpleClassName}VO = {  
2 -#foreach ($column in $columns)  
3 -#if ($column.createOperation || $column.updateOperation)  
4 -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")  
5 - ${column.javaField}: number  
6 -#elseif(${column.javaType.toLowerCase()} == "date")  
7 - ${column.javaField}: string  
8 -#else  
9 - ${column.javaField}: ${column.javaType.toLowerCase()}  
10 -#end  
11 -#end  
12 -#end  
13 -}  
14 -  
15 -export type ${simpleClassName}PageReqVO = {  
16 -#foreach ($column in $columns)  
17 -#if (${column.listOperation})##查询操作  
18 -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")  
19 - ${column.javaField}: number  
20 -#elseif(${column.javaType.toLowerCase()} == "date")  
21 - ${column.javaField}: string  
22 -#else  
23 - ${column.javaField}: ${column.javaType.toLowerCase()}  
24 -#end  
25 -#end  
26 -#end  
27 -}  
28 -  
29 -export type ${simpleClassName}ExcelReqVO = {  
30 -#foreach ($column in $columns)  
31 -#if (${column.listOperation})##查询操作  
32 -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")  
33 - ${column.javaField}: number  
34 -#elseif(${column.javaType.toLowerCase()} == "date")  
35 - ${column.javaField}: string  
36 -#else  
37 - ${column.javaField}: ${column.javaType.toLowerCase()}  
38 -#end  
39 -#end  
40 -#end  
41 -}  
42 \ No newline at end of file 0 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
1 import { reactive } from 'vue' 1 import { reactive } from 'vue'
2 import { useI18n } from '@/hooks/web/useI18n' 2 import { useI18n } from '@/hooks/web/useI18n'
3 -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'  
4 import { DICT_TYPE } from '@/utils/dict' 3 import { DICT_TYPE } from '@/utils/dict'
  4 +import { required } from '@/utils/formRules'
  5 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
5 const { t } = useI18n() // 国际化 6 const { t } = useI18n() // 国际化
6 // 表单校验 7 // 表单校验
7 export const rules = reactive({ 8 export const rules = reactive({
8 #foreach ($column in $columns) 9 #foreach ($column in $columns)
9 #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 10 #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
10 #set($comment=$column.columnComment) 11 #set($comment=$column.columnComment)
11 - $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == "select")'change'#else'blur'#end }], 12 + $column.javaField: [required],
12 #end 13 #end
13 #end 14 #end
14 }) 15 })
15 // CrudSchema 16 // CrudSchema
16 -const crudSchemas = reactive<CrudSchema[]>([ 17 +const crudSchemas = reactive<VxeCrudSchema>({
  18 + primaryKey: 'id', // 默认的主键ID
  19 + primaryTitle: t('common.index'), // 默认显示的值
  20 + primaryType: 'seq', // 默认为seq,序号模式
  21 + action: true,
  22 + actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可
  23 + columns: [
17 #foreach($column in $columns) 24 #foreach($column in $columns)
18 #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation) 25 #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation)
19 #set ($dictType = $column.dictType) 26 #set ($dictType = $column.dictType)
  27 + #if(!$column.primaryKey)
20 { 28 {
21 - label: '${column.columnComment}', 29 + title: '${column.columnComment}',
22 field: '${column.javaField}', 30 field: '${column.javaField}',
23 #if ("" != $dictType)## 有数据字典 31 #if ("" != $dictType)## 有数据字典
24 dictType: DICT_TYPE.$dictType.toUpperCase(), 32 dictType: DICT_TYPE.$dictType.toUpperCase(),
25 #end 33 #end
26 - #if($column.primaryKey)  
27 - type: 'index',  
28 - form: {  
29 - show: false  
30 - },  
31 - detail: {  
32 - show: false  
33 - }  
34 - #else  
35 #if (!$column.createOperation && !$column.updateOperation) 34 #if (!$column.createOperation && !$column.updateOperation)
36 - form: {  
37 - show: false  
38 - }, 35 + isForm: false
39 #elseif(!("" != $column.dictType)) 36 #elseif(!("" != $column.dictType))
  37 + #if ($column.htmlType == "datetime")## 时间框
40 form: { 38 form: {
41 show: true, 39 show: true,
42 - #if ($column.htmlType == "datetime")## 时间框  
43 component: 'DatePicker', 40 component: 'DatePicker',
44 componentProps: { 41 componentProps: {
45 type: 'datetime', 42 type: 'datetime',
46 valueFormat: 'YYYY-MM-DD HH:mm:ss' 43 valueFormat: 'YYYY-MM-DD HH:mm:ss'
47 } 44 }
48 - #elseif($column.htmlType == "editor")## 文本编辑器 45 + }
  46 + #elseif($column.htmlType == "editor")## 文本编辑器
  47 + form: {
  48 + show: true,
49 component: 'Editor', 49 component: 'Editor',
50 colProps: { 50 colProps: {
51 span: 24 51 span: 24
@@ -53,7 +53,10 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([ @@ -53,7 +53,10 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([
53 componentProps: { 53 componentProps: {
54 valueHtml: '' 54 valueHtml: ''
55 } 55 }
56 - #elseif($column.htmlType == "textarea")## 文本框 56 + }
  57 + #elseif($column.htmlType == "textarea")## 文本框
  58 + form: {
  59 + show: true,
57 component: 'Input', 60 component: 'Input',
58 componentProps: { 61 componentProps: {
59 type: 'textarea', 62 type: 'textarea',
@@ -62,50 +65,27 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([ @@ -62,50 +65,27 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([
62 colProps: { 65 colProps: {
63 span: 24 66 span: 24
64 } 67 }
65 - #end  
66 - }, 68 + }
  69 + #end
67 #end 70 #end
68 #if ($column.listOperationResult) 71 #if ($column.listOperationResult)
  72 + #if($column.htmlType == "input")
  73 + isSearch: true
  74 + #elseif("" != $dictType)
  75 + isSearch: true
  76 + #elseif($column.htmlType == "datetime")
69 search: { 77 search: {
70 - #if($column.htmlType == "input")  
71 - show: true  
72 - #else  
73 - #if($column.htmlType == "datetime")  
74 show: true, 78 show: true,
75 - component: 'DatePicker',  
76 - componentProps: {  
77 - type: 'datetimerange',  
78 - valueFormat: 'YYYY-MM-DD HH:mm:ss'  
79 - }  
80 - #elseif($column.htmlType == "select" || $column.htmlType == "radio")  
81 - #if ("" == $dictType)## 没有数据字典  
82 - show: true,  
83 - component: 'Select',  
84 - componentProps: {  
85 - option: [{'','请选择字典生成'}] 79 + itemRender: {
  80 + name: 'XDataTimePicker'
86 } 81 }
87 - #else  
88 - show: true  
89 - #end  
90 - #end  
91 - #end  
92 } 82 }
93 #end 83 #end
94 #end 84 #end
  85 + #end
95 }, 86 },
96 #end 87 #end
97 #end 88 #end
98 - {  
99 - label: t('table.action'),  
100 - field: 'action',  
101 - width: '240px',  
102 - form: {  
103 - show: false  
104 - },  
105 - detail: {  
106 - show: false  
107 - }  
108 - }  
109 -])  
110 -  
111 -export const { allSchemas } = useCrudSchemas(crudSchemas)  
112 \ No newline at end of file 89 \ No newline at end of file
  90 + ]
  91 +})
  92 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
113 \ No newline at end of file 93 \ No newline at end of file
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
  1 +<template>
  2 + <ContentWrap>
  3 + <!-- 列表 -->
  4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
  5 + <template #toolbar_buttons>
  6 + <!-- 操作:新增 -->
  7 + <XButton
  8 + type="primary"
  9 + preIcon="ep:zoom-in"
  10 + :title="t('action.add')"
  11 + v-hasPermi="['${permissionPrefix}:create']"
  12 + @click="handleCreate()"
  13 + />
  14 + <!-- 操作:导出 -->
  15 + <XButton
  16 + type="warning"
  17 + preIcon="ep:download"
  18 + :title="t('action.export')"
  19 + v-hasPermi="['${permissionPrefix}:export']"
  20 + @click="handleExport()"
  21 + />
  22 + </template>
  23 + <template #actionbtns_default="{ row }">
  24 + <!-- 操作:修改 -->
  25 + <XTextButton
  26 + preIcon="ep:edit"
  27 + :title="t('action.edit')"
  28 + v-hasPermi="['${permissionPrefix}:update']"
  29 + @click="handleUpdate(row.id)"
  30 + />
  31 + <!-- 操作:详情 -->
  32 + <XTextButton
  33 + preIcon="ep:view"
  34 + :title="t('action.detail')"
  35 + v-hasPermi="['${permissionPrefix}:query']"
  36 + @click="handleDetail(row.id)"
  37 + />
  38 + <!-- 操作:删除 -->
  39 + <XTextButton
  40 + preIcon="ep:delete"
  41 + :title="t('action.del')"
  42 + v-hasPermi="['${permissionPrefix}:delete']"
  43 + @click="handleDelete(row.id)"
  44 + />
  45 + </template>
  46 + </vxe-grid>
  47 + </ContentWrap>
  48 + <!-- 弹窗 -->
  49 + <XModal id="${classNameVar}Model" :loading="modelLoading" v-model="modelVisible" :title="modelTitle">
  50 + <!-- 表单:添加/修改 -->
  51 + <Form
  52 + ref="formRef"
  53 + v-if="['create', 'update'].includes(actionType)"
  54 + :schema="allSchemas.formSchema"
  55 + :rules="rules"
  56 + />
  57 + <!-- 表单:详情 -->
  58 + <Descriptions
  59 + v-if="actionType === 'detail'"
  60 + :schema="allSchemas.detailSchema"
  61 + :data="detailData"
  62 + />
  63 + <template #footer>
  64 + <!-- 按钮:保存 -->
  65 + <XButton
  66 + v-if="['create', 'update'].includes(actionType)"
  67 + type="primary"
  68 + :title="t('action.save')"
  69 + :loading="actionLoading"
  70 + @click="submitForm()"
  71 + />
  72 + <!-- 按钮:关闭 -->
  73 + <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" />
  74 + </template>
  75 + </XModal>
  76 +</template>
1 <script setup lang="ts"> 77 <script setup lang="ts">
  78 +// 全局相关的 import
2 import { ref, unref } from 'vue' 79 import { ref, unref } from 'vue'
3 -import dayjs from 'dayjs'  
4 -import { ElMessage } from 'element-plus'  
5 -import { DICT_TYPE } from '@/utils/dict'  
6 -import { useTable } from '@/hooks/web/useTable'  
7 import { useI18n } from '@/hooks/web/useI18n' 80 import { useI18n } from '@/hooks/web/useI18n'
  81 +import { useMessage } from '@/hooks/web/useMessage'
  82 +import { useVxeGrid } from '@/hooks/web/useVxeGrid'
  83 +import { VxeGridInstance } from 'vxe-table'
8 import { FormExpose } from '@/components/Form' 84 import { FormExpose } from '@/components/Form'
9 -import type { ${simpleClassName}VO } from '@/api/${table.moduleName}/${classNameVar}/types' 85 +// 业务相关的 import
10 import { rules, allSchemas } from './${classNameVar}.data' 86 import { rules, allSchemas } from './${classNameVar}.data'
11 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}' 87 import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${classNameVar}'
  88 +
12 const { t } = useI18n() // 国际化 89 const { t } = useI18n() // 国际化
  90 +const message = useMessage() // 消息弹窗
13 91
14 -// ========== 列表相关 ==========  
15 -const { register, tableObject, methods } = useTable<${simpleClassName}VO>({ 92 +// 列表相关的变量
  93 +const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
  94 +const { gridOptions, reloadList, deleteData, exportList } = useVxeGrid<${simpleClassName}Api.${simpleClassName}VO>({
  95 + allSchemas: allSchemas,
16 getListApi: ${simpleClassName}Api.get${simpleClassName}PageApi, 96 getListApi: ${simpleClassName}Api.get${simpleClassName}PageApi,
17 - delListApi: ${simpleClassName}Api.delete${simpleClassName}Api, 97 + deleteApi: ${simpleClassName}Api.delete${simpleClassName}Api,
18 exportListApi: ${simpleClassName}Api.export${simpleClassName}Api 98 exportListApi: ${simpleClassName}Api.export${simpleClassName}Api
19 }) 99 })
20 -const { getList, setSearchParams, delList, exportList } = methods  
21 100
22 -// ========== CRUD 相关 ==========  
23 -const actionLoading = ref(false) // 遮罩层 101 +// 弹窗相关的变量
  102 +const modelVisible = ref(false) // 是否显示弹出层
  103 +const modelTitle = ref('edit') // 弹出层标题
  104 +const modelLoading = ref(false) // 弹出层loading
24 const actionType = ref('') // 操作按钮的类型 105 const actionType = ref('') // 操作按钮的类型
25 -const dialogVisible = ref(false) // 是否显示弹出层  
26 -const dialogTitle = ref('edit') // 弹出层标题 106 +const actionLoading = ref(false) // 按钮 Loading
27 const formRef = ref<FormExpose>() // 表单 Ref 107 const formRef = ref<FormExpose>() // 表单 Ref
  108 +const detailData = ref() // 详情 Ref
28 109
29 // 设置标题 110 // 设置标题
30 const setDialogTile = (type: string) => { 111 const setDialogTile = (type: string) => {
31 - dialogTitle.value = t('action.' + type) 112 + modelLoading.value = true
  113 + modelTitle.value = t('action.' + type)
32 actionType.value = type 114 actionType.value = type
33 - dialogVisible.value = true 115 + modelVisible.value = true
34 } 116 }
35 117
36 // 新增操作 118 // 新增操作
37 const handleCreate = () => { 119 const handleCreate = () => {
38 setDialogTile('create') 120 setDialogTile('create')
39 - // 重置表单  
40 - unref(formRef)?.getElFormRef()?.resetFields() 121 + modelLoading.value = false
  122 +}
  123 +
  124 +// 导出操作
  125 +const handleExport = async () => {
  126 + await exportList(xGrid, '导出.xls')
41 } 127 }
42 128
43 // 修改操作 129 // 修改操作
44 -const handleUpdate = async (row: ${simpleClassName}VO) => { 130 +const handleUpdate = async (rowId: number) => {
45 setDialogTile('update') 131 setDialogTile('update')
46 // 设置数据 132 // 设置数据
47 - const res = await ${simpleClassName}Api.get${simpleClassName}Api(row.id) 133 + const res = await ${simpleClassName}Api.get${simpleClassName}Api(rowId)
48 unref(formRef)?.setValues(res) 134 unref(formRef)?.setValues(res)
  135 + modelLoading.value = false
  136 +}
  137 +
  138 +// 详情操作
  139 +const handleDetail = async (rowId: number) => {
  140 + setDialogTile('detail')
  141 + const res = await ${simpleClassName}Api.get${simpleClassName}Api(rowId)
  142 + detailData.value = res
  143 + modelLoading.value = false
  144 +}
  145 +
  146 +// 删除操作
  147 +const handleDelete = async (rowId: number) => {
  148 + await deleteData(xGrid, rowId)
49 } 149 }
50 150
51 // 提交按钮 151 // 提交按钮
@@ -57,156 +157,23 @@ const submitForm = async () =&gt; { @@ -57,156 +157,23 @@ const submitForm = async () =&gt; {
57 actionLoading.value = true 157 actionLoading.value = true
58 // 提交请求 158 // 提交请求
59 try { 159 try {
60 - const data = unref(formRef)?.formModel as ${simpleClassName}VO 160 + const data = unref(formRef)?.formModel as ${simpleClassName}Api.${simpleClassName}VO
61 if (actionType.value === 'create') { 161 if (actionType.value === 'create') {
62 await ${simpleClassName}Api.create${simpleClassName}Api(data) 162 await ${simpleClassName}Api.create${simpleClassName}Api(data)
63 - ElMessage.success(t('common.createSuccess')) 163 + message.success(t('common.createSuccess'))
64 } else { 164 } else {
65 await ${simpleClassName}Api.update${simpleClassName}Api(data) 165 await ${simpleClassName}Api.update${simpleClassName}Api(data)
66 - ElMessage.success(t('common.updateSuccess')) 166 + message.success(t('common.updateSuccess'))
67 } 167 }
68 - // 操作成功,重新加载列表  
69 dialogVisible.value = false 168 dialogVisible.value = false
70 - await getList()  
71 } finally { 169 } finally {
72 actionLoading.value = false 170 actionLoading.value = false
  171 + // 刷新列表
  172 + await reloadList(xGrid)
73 } 173 }
74 } 174 }
75 }) 175 })
76 } 176 }
77 177
78 -// ========== 详情相关 ==========  
79 -const detailRef = ref() // 详情 Ref  
80 -  
81 -// 详情操作  
82 -const handleDetail = async (row: ${simpleClassName}VO) => {  
83 - // 设置数据  
84 - detailRef.value = row  
85 - setDialogTile('detail')  
86 -}  
87 -  
88 -// ========== 初始化 ==========  
89 -getList()  
90 </script> 178 </script>
91 179
92 -<template>  
93 - <!-- 搜索工作区 -->  
94 - <ContentWrap>  
95 - <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />  
96 - </ContentWrap>  
97 - <ContentWrap>  
98 - <!-- 操作工具栏 -->  
99 - <div class="mb-10px">  
100 - <XButton  
101 - type="primary"  
102 - preIcon="ep:zoom-in"  
103 - :title="t('action.add')"  
104 - v-hasPermi="['${permissionPrefix}:create']"  
105 - @click="handleCreate()"  
106 - />  
107 - <XButton  
108 - type="warning"  
109 - preIcon="ep:download"  
110 - :title="t('action.export')"  
111 - v-hasPermi="['${permissionPrefix}:export']"  
112 - @click="exportList('数据.xls')"  
113 - />  
114 - </div>  
115 - <!-- 列表 -->  
116 - <Table  
117 - :columns="allSchemas.tableColumns"  
118 - :selection="false"  
119 - :data="tableObject.tableList"  
120 - :loading="tableObject.loading"  
121 - :pagination="{  
122 - total: tableObject.total  
123 - }"  
124 - v-model:pageSize="tableObject.pageSize"  
125 - v-model:currentPage="tableObject.currentPage"  
126 - @register="register"  
127 - >  
128 -#foreach($column in $columns)  
129 -#if ($column.listOperationResult)  
130 - #set ($dictType=$column.dictType)  
131 - #if ($column.javaType == "LocalDateTime")## 时间类型  
132 - <template #${column.javaField}="{ row }">  
133 - <span>{{ dayjs(row.${column.javaField}).format('YYYY-MM-DD HH:mm:ss') }}</span>  
134 - </template>  
135 - #elseif("" != $column.dictType)## 数据字典  
136 - <template #${column.javaField}="{ row }">  
137 - <DictTag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${column.javaField}" />  
138 - </template>  
139 - #end  
140 -#end  
141 -#end  
142 - <template #action="{ row }">  
143 - <XButton  
144 - link  
145 - type="primary"  
146 - preIcon="ep:edit"  
147 - :title="t('action.edit')"  
148 - v-hasPermi="['${permissionPrefix}:update']"  
149 - @click="handleUpdate(row.id)"  
150 - />  
151 - <XButton  
152 - link  
153 - type="primary"  
154 - preIcon="ep:view"  
155 - :title="t('action.detail')"  
156 - v-hasPermi="['${permissionPrefix}:update']"  
157 - @click="handleDetail(row)"  
158 - />  
159 - <XButton  
160 - link  
161 - type="primary"  
162 - preIcon="ep:delete"  
163 - :title="t('action.del')"  
164 - v-hasPermi="['${permissionPrefix}:delete']"  
165 - @click="handleDelete(row.id)"  
166 - />  
167 - </template>  
168 - </Table>  
169 - </ContentWrap>  
170 -  
171 - <Dialog v-model="dialogVisible" :title="dialogTitle">  
172 - <!-- 对话框(添加 / 修改) -->  
173 - <Form  
174 - v-if="['create', 'update'].includes(actionType)"  
175 - :schema="allSchemas.formSchema"  
176 - :rules="rules"  
177 - ref="formRef"  
178 - />  
179 - <!-- 对话框(详情) -->  
180 - <Descriptions  
181 - v-if="actionType === 'detail'"  
182 - :schema="allSchemas.detailSchema"  
183 - :data="detailRef"  
184 - >  
185 -#foreach($column in $columns)  
186 - #if ($column.listOperationResult)  
187 - #set ($dictType=$column.dictType)  
188 - #if ($column.javaType == "LocalDateTime")## 时间类型  
189 - <template #${column.javaField}="{ row }">  
190 - <span>{{ dayjs(row.${column.javaField}).format('YYYY-MM-DD HH:mm:ss') }}</span>  
191 - </template>  
192 - #elseif("" != $column.dictType)## 数据字典  
193 - <template #${column.javaField}="{ row }">  
194 - <DictTag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${column.javaField}" />  
195 - </template>  
196 - #end  
197 - #end  
198 -#end  
199 - </Descriptions>  
200 - <!-- 操作按钮 -->  
201 - <template #footer>  
202 - <XButton  
203 - v-if="['create', 'update'].includes(actionType)"  
204 - :loading="actionLoading"  
205 - :title="t('action.save')"  
206 - type="primary"  
207 - @click="submitForm"  
208 - />  
209 - <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />  
210 - </template>  
211 - </Dialog>  
212 -</template>  
yudao-ui-admin-vue3/src/views/infra/codegen/components/Preview.vue
@@ -117,15 +117,17 @@ defineExpose({ @@ -117,15 +117,17 @@ defineExpose({
117 <XModal title="预览" v-model="preview.open"> 117 <XModal title="预览" v-model="preview.open">
118 <div class="flex"> 118 <div class="flex">
119 <el-card class="w-1/4" :gutter="12" shadow="hover"> 119 <el-card class="w-1/4" :gutter="12" shadow="hover">
120 - <el-tree  
121 - ref="treeRef"  
122 - node-key="id"  
123 - :data="preview.fileTree"  
124 - :expand-on-click-node="false"  
125 - default-expand-all  
126 - highlight-current  
127 - @node-click="handleNodeClick"  
128 - /> 120 + <el-scrollbar height="calc(100vh - 88px - 40px - 50px)">
  121 + <el-tree
  122 + ref="treeRef"
  123 + node-key="id"
  124 + :data="preview.fileTree"
  125 + :expand-on-click-node="false"
  126 + default-expand-all
  127 + highlight-current
  128 + @node-click="handleNodeClick"
  129 + />
  130 + </el-scrollbar>
129 </el-card> 131 </el-card>
130 <el-card class="w-3/4" style="margin-left: 10px" :gutter="12" shadow="hover"> 132 <el-card class="w-3/4" style="margin-left: 10px" :gutter="12" shadow="hover">
131 <el-tabs v-model="preview.activeName"> 133 <el-tabs v-model="preview.activeName">
yudao-ui-admin-vue3/src/views/system/post/index.vue
1 <template> 1 <template>
2 <ContentWrap> 2 <ContentWrap>
3 <!-- 列表 --> 3 <!-- 列表 -->
4 - <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar" :class="isDark"> 4 + <vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
5 <template #toolbar_buttons> 5 <template #toolbar_buttons>
6 <!-- 操作:新增 --> 6 <!-- 操作:新增 -->
7 <XButton 7 <XButton
@@ -86,8 +86,6 @@ import { FormExpose } from &#39;@/components/Form&#39; @@ -86,8 +86,6 @@ import { FormExpose } from &#39;@/components/Form&#39;
86 import * as PostApi from '@/api/system/post' 86 import * as PostApi from '@/api/system/post'
87 import { rules, allSchemas } from './post.data' 87 import { rules, allSchemas } from './post.data'
88 88
89 -import { useDark } from '@vueuse/core'  
90 -const isDark = useDark()  
91 const { t } = useI18n() // 国际化 89 const { t } = useI18n() // 国际化
92 const message = useMessage() // 消息弹窗 90 const message = useMessage() // 消息弹窗
93 // 列表相关的变量 91 // 列表相关的变量
@@ -125,6 +123,7 @@ const handleCreate = () =&gt; { @@ -125,6 +123,7 @@ const handleCreate = () =&gt; {
125 const handleExport = async () => { 123 const handleExport = async () => {
126 await exportList(xGrid, '岗位列表.xls') 124 await exportList(xGrid, '岗位列表.xls')
127 } 125 }
  126 +
128 // 修改操作 127 // 修改操作
129 const handleUpdate = async (rowId: number) => { 128 const handleUpdate = async (rowId: number) => {
130 setDialogTile('update') 129 setDialogTile('update')
yudao-ui-admin-vue3/use.md
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 - 一个页面(以post为例)由4部分组成 15 - 一个页面(以post为例)由4部分组成
16 16
17 ```bash 17 ```bash
18 -/src/api/system/post/ [index.ts | types.ts] 18 +/src/api/system/post/index.ts
19 /src/views/system/post/ [index.vue | post.data.ts] 19 /src/views/system/post/ [index.vue | post.data.ts]
20 ``` 20 ```
21 21