# Conflicts:
#	yudao-module-mall/yudao-module-promotion-server/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
#	yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java
This commit is contained in:
YunaiV
2025-12-28 10:22:38 +08:00
41 changed files with 2853 additions and 1396 deletions

View File

@@ -23,6 +23,8 @@ public enum CodegenFrontTypeEnum {
VUE3_VBEN5_EP_SCHEMA(50), // Vue3 VBEN5 + EP + schema 模版
VUE3_VBEN5_EP_GENERAL(51), // Vue3 VBEN5 + EP 标准模版
VUE3_ADMIN_UNIAPP_WOT(60), // Vue3 Admin + Uniapp + WOT 标准模版
;
/**

View File

@@ -72,6 +72,14 @@ public class FileController {
return success(fileService.createFile(createReqVO));
}
@GetMapping("/get")
@Operation(summary = "获得文件")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('infra:file:query')")
public CommonResult<FileRespVO> getFile(@RequestParam("id") Long id) {
return success(BeanUtils.toBean(fileService.getFile(id), FileRespVO.class));
}
@DeleteMapping("/delete")
@Operation(summary = "删除文件")
@Parameter(name = "id", description = "编号", required = true)

View File

@@ -4,12 +4,14 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenCreateListReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.CodegenUpdateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTablePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
@@ -17,7 +19,9 @@ import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.google.common.annotations.VisibleForTesting;
@@ -45,6 +49,8 @@ public class CodegenServiceImpl implements CodegenService {
@Resource
private DatabaseTableService databaseTableService;
@Resource
private DataSourceConfigService dataSourceConfigService;
@Resource
private CodegenTableMapper codegenTableMapper;
@@ -284,8 +290,11 @@ public class CodegenServiceImpl implements CodegenService {
}
}
// 获取数据源对应的数据库类型
DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(table.getDataSourceConfigId());
DbType dbType = JdbcUtils.getDbType(dataSourceConfig.getUrl());
// 执行生成
return codegenEngine.execute(table, columns, subTables, subColumnsList);
return codegenEngine.execute(dbType, table, columns, subTables, subColumnsList);
}
@Override

View File

@@ -33,6 +33,7 @@ import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenVOTypeEnum;
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
import com.baomidou.mybatisplus.annotation.DbType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Maps;
@@ -96,7 +97,7 @@ public class CodegenEngine {
.build();
/**
* 端的配置模版
* 端的配置模版
*
* key1UI 模版的类型 {@link CodegenFrontTypeEnum#getType()}
* key2模板在 resources 的地址
@@ -137,6 +138,16 @@ public class CodegenEngine {
vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue"))
.put(CodegenFrontTypeEnum.VUE3_ELEMENT_PLUS.getType(), vue3TemplatePath("api/api.ts"),
vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("api/api.ts"),
vue3UniappFilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/index.vue"),
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/index.vue"))
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("components/search-form.vue"),
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/components/search-form.vue"))
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/form/index.vue"),
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/form/index.vue"))
.put(CodegenFrontTypeEnum.VUE3_ADMIN_UNIAPP_WOT.getType(), vue3AdminUniappTemplatePath("views/detail/index.vue"),
vue3UniappFilePath("pages-${table.moduleName}/${table.businessName}/detail/index.vue"))
// VUE3_VBEN2_ANTD_SCHEMA
.put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"),
vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts"))
@@ -300,16 +311,17 @@ public class CodegenEngine {
/**
* 生成代码
*
* @param dbType 数据库类型
* @param table 表定义
* @param columns table 的字段定义数组
* @param subTables 子表数组,当且仅当主子表时使用
* @param subColumnsList subTables 的字段定义数组
* @return 生成的代码key 是路径value 是对应代码
*/
public Map<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns,
public Map<String, String> execute(DbType dbType, CodegenTableDO table, List<CodegenColumnDO> columns,
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
// 1.1 初始化 bindMap 上下文
Map<String, Object> bindingMap = initBindingMap(table, columns, subTables, subColumnsList);
Map<String, Object> bindingMap = initBindingMap(dbType, table, columns, subTables, subColumnsList);
// 1.2 获得模版
Map<String, String> templates = getTemplates(table.getFrontType());
@@ -387,8 +399,8 @@ public class CodegenEngine {
* @return 格式化后的代码
*/
private String prettyCode(String content, String vmPath) {
// Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5
if (!StrUtil.contains(vmPath, "vben5")) {
// Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错(需要排除 vben5、vue3_admin_uniapp
if (!StrUtil.containsAny(vmPath, "vben5", "vue3_admin_uniapp")) {
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }");
}
// Vue 界面:去除多的 dateFormatter只有一个的情况下说明没使用到
@@ -415,10 +427,11 @@ public class CodegenEngine {
return content;
}
private Map<String, Object> initBindingMap(CodegenTableDO table, List<CodegenColumnDO> columns,
private Map<String, Object> initBindingMap(DbType dbType, CodegenTableDO table, List<CodegenColumnDO> columns,
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
// 创建 bindingMap
Map<String, Object> bindingMap = new HashMap<>(globalBindingMap);
bindingMap.put("dbType", dbType);
bindingMap.put("table", table);
bindingMap.put("columns", columns);
bindingMap.put("primaryColumn", CollectionUtils.findFirst(columns, CodegenColumnDO::getPrimaryKey)); // 主键字段
@@ -617,6 +630,15 @@ public class CodegenEngine {
"src/" + path;
}
private static String vue3AdminUniappTemplatePath(String path) {
return "codegen/vue3_admin_uniapp/" + path + ".vm";
}
private static String vue3UniappFilePath(String path) {
return "yudao-ui-${sceneEnum.basePackage}-uniapp/" + // 顶级目录
"src/" + path;
}
private static String vue3VbenFilePath(String path) {
return "yudao-ui-${sceneEnum.basePackage}-vben/" + // 顶级目录
"src/" + path;

View File

@@ -62,6 +62,7 @@ public interface FileService {
* @return 编号
*/
Long createFile(FileCreateReqVO createReqVO);
FileDO getFile(Long id);
/**
* 删除文件

View File

@@ -152,6 +152,11 @@ public class FileServiceImpl implements FileService {
return file.getId();
}
@Override
public FileDO getFile(Long id) {
return validateFileExists(id);
}
@Override
public void deleteFile(Long id) throws Exception {
// 校验存在

View File

@@ -1,3 +1,24 @@
## 通用变量定义
#set ($functionNames = ['查询', '创建', '更新', '删除', '导出'])
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
##
## 宏定义:生成按钮 SQL通用部分
#macro(insertButtonSql $parentIdVar)
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, ${parentIdVar},
'', '', '', 0
);
#end
#end
##
## ======================= MySQL / OceanBase =======================
#if ($dbType.name() == 'MYSQL' || $dbType.name() == 'OCEAN_BASE')
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
@@ -9,12 +30,9 @@ VALUES (
);
-- 按钮父菜单ID
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
#set ($functionNames = ['查询', '创建', '更新', '删除', '导出'])
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
@@ -25,4 +43,139 @@ VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
'', '', '', 0
);
#end
#end
##
## ======================= Oracle / 达梦 DM =======================
#elseif ($dbType.name() == 'ORACLE' || $dbType.name() == 'DM')
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
);
-- 按钮父菜单ID
-- 说明Oracle/达梦 使用序列获取上一个插入的 ID
DECLARE
v_parent_id NUMBER;
BEGIN
SELECT system_menu_seq.CURRVAL INTO v_parent_id FROM DUAL;
-- 按钮 SQL
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, v_parent_id,
'', '', '', 0
);
#end
END;
/
##
## ======================= PostgreSQL / 人大金仓 KingbaseES =======================
#elseif ($dbType.name() == 'POSTGRE_SQL' || $dbType.name() == 'KINGBASE_ES')
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
);
-- 按钮父菜单ID
-- 说明PostgreSQL/KingbaseES 使用 lastval() 获取上一个插入的序列值
DO $$
DECLARE
v_parent_id BIGINT;
BEGIN
v_parent_id := lastval();
-- 按钮 SQL
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, v_parent_id,
'', '', '', 0
);
#end
END $$;
##
## ======================= SQL Server =======================
#elseif ($dbType.name() == 'SQL_SERVER' || $dbType.name() == 'SQL_SERVER2005')
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
);
-- 按钮父菜单ID
-- 说明SQL Server 使用 SCOPE_IDENTITY() 获取上一个插入的自增 ID
DECLARE @parentId BIGINT;
SET @parentId = SCOPE_IDENTITY();
-- 按钮 SQL
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
'', '', '', 0
);
#end
##
## ======================= 不支持的数据库类型 =======================
#else
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- 注意:当前数据库类型 ${dbType.name()} 暂不支持自动生成菜单 SQL
-- 请参考以下 MySQL 语法,手动修改为您的数据库对应的语法
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- 菜单 SQL
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status, component_name
)
VALUES (
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}'
);
-- 按钮父菜单ID
-- TODO: 请根据您的数据库类型,修改获取上一个插入 ID 的方式
-- MySQL: SELECT @parentId := LAST_INSERT_ID();
-- Oracle: SELECT system_menu_seq.CURRVAL INTO v_parent_id FROM DUAL;
-- PostgreSQL: SELECT lastval() INTO v_parent_id;
-- SQL Server: SET @parentId = SCOPE_IDENTITY();
SELECT @parentId := LAST_INSERT_ID();
-- 按钮 SQL
#foreach ($functionName in $functionNames)
#set ($index = $foreach.count - 1)
INSERT INTO system_menu(
name, permission, type, sort, parent_id,
path, icon, component, status
)
VALUES (
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
'', '', '', 0
);
#end
#end

View File

@@ -0,0 +1,297 @@
<template>
<!-- 搜索框入口 -->
<view @click="visible = true">
<wd-search :placeholder="placeholder" hide-cancel disabled />
</view>
<!-- 搜索弹窗 -->
<wd-popup v-model="visible" position="top" @close="visible = false">
<view class="yd-search-form-container" :style="{ paddingTop: `#[[${]]#getNavbarHeight()#[[}]]#px` }">
#set ($hasDict = 0)
#foreach ($column in $columns)
#if ($hasDict == 0 && $column.listOperation && $column.dictType && "" != $column.dictType)
#set ($hasDict = 1)
#end
#end
#foreach($column in $columns)
#if ($column.listOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($listOperationCondition = $column.listOperationCondition)
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ($column.htmlType == "input")
<view class="yd-search-form-item">
<view class="yd-search-form-label">
${comment}
</view>
<wd-input
v-model="formData.${javaField}"
placeholder="请输入${comment}"
clearable
/>
</view>
#elseif ($column.htmlType == "datetime" && $listOperationCondition == "BETWEEN")
#set ($AttrName = $javaField.substring(0,1).toUpperCase() + ${javaField.substring(1)})
<view class="yd-search-form-item">
<view class="yd-search-form-label">
${comment}
</view>
<view class="yd-search-form-date-range-container">
<view @click="visible${AttrName}[0] = true">
<view class="yd-search-form-date-range-picker">
{{ formatDate(formData.${javaField}?.[0]) || '开始日期' }}
</view>
</view>
-
<view @click="visible${AttrName}[1] = true">
<view class="yd-search-form-date-range-picker">
{{ formatDate(formData.${javaField}?.[1]) || '结束日期' }}
</view>
</view>
</view>
<wd-datetime-picker-view v-if="visible${AttrName}[0]" v-model="temp${AttrName}[0]" type="date" />
<view v-if="visible${AttrName}[0]" class="yd-search-form-date-range-actions">
<wd-button size="small" plain @click="visible${AttrName}[0] = false">
取消
</wd-button>
<wd-button size="small" type="primary" @click="handle${AttrName}0Confirm">
确定
</wd-button>
</view>
<wd-datetime-picker-view v-if="visible${AttrName}[1]" v-model="temp${AttrName}[1]" type="date" />
<view v-if="visible${AttrName}[1]" class="yd-search-form-date-range-actions">
<wd-button size="small" plain @click="visible${AttrName}[1] = false">
取消
</wd-button>
<wd-button size="small" type="primary" @click="handle${AttrName}1Confirm">
确定
</wd-button>
</view>
</view>
#elseif (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType)
<view class="yd-search-form-item">
<view class="yd-search-form-label">
${comment}
</view>
<wd-radio-group v-model="formData.${javaField}" shape="button">
<wd-radio :value="-1">
全部
</wd-radio>
<wd-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</wd-radio>
</wd-radio-group>
</view>
#else
<view class="yd-search-form-item">
<view class="yd-search-form-label">
${comment}
</view>
<wd-input
v-model="formData.${javaField}"
placeholder="请输入${comment}"
clearable
/>
</view>
#end
#end
#end
<view class="yd-search-form-actions">
<wd-button class="flex-1" plain @click="handleReset">
重置
</wd-button>
<wd-button class="flex-1" type="primary" @click="handleSearch">
搜索
</wd-button>
</view>
</view>
</wd-popup>
</template>
<script lang="ts" setup>
#set ($hasDict = 0)
#set ($hasGetDictOptions = 0)
#set ($hasGetIntDictOptions = 0)
#set ($hasGetStrDictOptions = 0)
#set ($hasGetBoolDictOptions = 0)
#set ($hasDateTimeBetween = 0)
#foreach($column in $columns)
#if ($column.listOperation && $column.dictType && "" != $column.dictType)
#set ($hasDict = 1)
#if ($column.htmlType == "select" || $column.htmlType == "radio")
#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")
#set ($hasGetIntDictOptions = 1)
#elseif ($column.javaType == "String")
#set ($hasGetStrDictOptions = 1)
#elseif ($column.javaType == "Boolean")
#set ($hasGetBoolDictOptions = 1)
#else
#set ($hasGetDictOptions = 1)
#end
#end
#end
#if ($hasDateTimeBetween == 0 && $column.listOperation && $column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($hasDateTimeBetween = 1)
#end
#end
import { computed, reactive, ref } from 'vue'
import { getNavbarHeight } from '@/utils'
#if ($hasDateTimeBetween == 1)
import { formatDate, formatDateRange } from '@/utils/date'
#end
#if ($hasDict == 1)
#set ($dictImportNames = "getDictLabel, ")
#if ($hasGetDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getDictOptions, ")
#end
#if ($hasGetIntDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getIntDictOptions, ")
#end
#if ($hasGetStrDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getStrDictOptions, ")
#end
#if ($hasGetBoolDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ")
#end
#set ($dictImportNames = $dictImportNames.trim())
#set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1))
import { $dictImportNames } from '@/hooks/useDict'
import { DICT_TYPE } from '@/utils/constants'
#end
const emit = defineEmits<{
search: [data: Record<string, any>]
reset: []
}>()
const visible = ref(false)
const formData = reactive({
#foreach($column in $columns)
#if ($column.listOperation)
#set ($javaType = $column.javaType.toLowerCase())
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
${column.javaField}: [undefined, undefined] as [number | undefined, number | undefined],
#elseif ($column.dictType && "" != $column.dictType)
#if(${javaType} == "string")
${column.javaField}: -1 as -1 | string, // -1 表示全部
#elseif(${javaType} == "boolean")
${column.javaField}: -1 as -1 | boolean, // -1 表示全部
#else
${column.javaField}: -1, // -1 表示全部
#end
#elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte")
${column.javaField}: undefined as number | undefined,
#elseif(${javaType} == "boolean")
${column.javaField}: undefined as boolean | undefined,
#else
${column.javaField}: undefined as string | undefined,
#end
#end
#end
})
/** 搜索条件 placeholder 拼接 */
const placeholder = computed(() => {
const conditions: string[] = []
#foreach($column in $columns)
#if ($column.listOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType.toLowerCase())
#set ($comment = $column.columnComment)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
if (formData.${javaField}?.[0] && formData.${javaField}?.[1]) {
conditions.push(`${comment}:#[[${]]#formatDate(formData.${javaField}[0])#[[}]]#~#[[${]]#formatDate(formData.${javaField}[1])#[[}]]#`)
}
#elseif ($dictType && "" != $dictType)
if (formData.${javaField} !== -1) {
conditions.push(`${comment}:#[[${]]#getDictLabel(DICT_TYPE.${dictType.toUpperCase()}, formData.${javaField})#[[}]]#`)
}
#else
#if(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte" || ${javaType} == "boolean")
if (formData.${javaField} !== undefined) {
conditions.push(`${comment}:#[[${]]#formData.${javaField}#[[}]]#`)
}
#else
if (formData.${javaField}) {
conditions.push(`${comment}:#[[${]]#formData.${javaField}#[[}]]#`)
}
#end
#end
#end
#end
return conditions.length > 0 ? conditions.join(' | ') : '搜索${table.classComment}'
})
#if ($hasDateTimeBetween == 1)
// 时间范围选择器状态
#foreach($column in $columns)
#if ($column.listOperation && $column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
#set ($javaField = $column.javaField)
#set ($AttrName = $javaField.substring(0,1).toUpperCase() + ${javaField.substring(1)})
const visible${AttrName} = ref<[boolean, boolean]>([false, false])
const temp${AttrName} = ref<[number, number]>([Date.now(), Date.now()])
/** ${column.columnComment}[0]确认 */
function handle${AttrName}0Confirm() {
formData.${javaField} = [temp${AttrName}.value[0], formData.${javaField}?.[1]]
visible${AttrName}.value[0] = false
}
/** ${column.columnComment}[1]确认 */
function handle${AttrName}1Confirm() {
formData.${javaField} = [formData.${javaField}?.[0], temp${AttrName}.value[1]]
visible${AttrName}.value[1] = false
}
#end
#end
#end
/** 搜索 */
function handleSearch() {
visible.value = false
emit('search', {
...formData,
#foreach($column in $columns)
#if ($column.listOperation)
#if ($column.dictType && "" != $column.dictType)
${column.javaField}: formData.${column.javaField} === -1 ? undefined : formData.${column.javaField},
#elseif ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
${column.javaField}: formatDateRange(formData.${column.javaField}),
#end
#end
#end
})
}
/** 重置 */
function handleReset() {
#foreach($column in $columns)
#if ($column.listOperation)
#if ($column.htmlType == "datetime" && $column.listOperationCondition == "BETWEEN")
formData.${column.javaField} = [undefined, undefined]
#elseif ($column.dictType && "" != $column.dictType)
formData.${column.javaField} = -1
#else
formData.${column.javaField} = undefined
#end
#end
#end
visible.value = false
emit('reset')
}
</script>

View File

@@ -0,0 +1,151 @@
<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="${table.classComment}详情"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 详情内容 -->
<view>
<wd-cell-group border>
#foreach($column in $columns)
#if ($column.primaryKey || $column.listOperationResult || $column.createOperation || $column.updateOperation)
#set ($javaField = $column.javaField)
#set ($comment = $column.columnComment)
#if ($column.dictType && "" != $column.dictType)
<wd-cell title="${comment}">
<dict-tag :type="DICT_TYPE.${column.dictType.toUpperCase()}" :value="formData?.${javaField}" />
</wd-cell>
#elseif ($column.javaType == "LocalDateTime")
<wd-cell title="${comment}" :value="formatDateTime(formData?.${javaField}) || '-'" />
#else
<wd-cell title="${comment}" :value="formData?.${javaField} ?? '-'" />
#end
#end
#end
</wd-cell-group>
</view>
<!-- 底部操作按钮 -->
<view class="yd-detail-footer">
<view class="yd-detail-footer-actions">
<wd-button
v-if="hasAccessByCodes(['${permissionPrefix}:update'])"
class="flex-1" type="warning" @click="handleEdit"
>
编辑
</wd-button>
<wd-button
v-if="hasAccessByCodes(['${permissionPrefix}:delete'])"
class="flex-1" type="error" :loading="deleting" @click="handleDelete"
>
删除
</wd-button>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
#set ($hasDict = 0)
#foreach($column in $columns)
#if ($hasDict == 0 && $column.dictType && "" != $column.dictType)
#set ($hasDict = 1)
#end
#end
#set ($hasDateTime = 0)
#foreach($column in $columns)
#if ($hasDateTime == 0 && $column.javaType == "LocalDateTime")
#set ($hasDateTime = 1)
#end
#end
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
import { onMounted, ref } from 'vue'
import { useToast } from 'wot-design-uni'
import { delete${simpleClassName}, get${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
import { useAccess } from '@/hooks/useAccess'
import { navigateBackPlus } from '@/utils'
#if ($hasDict == 1)
import { DICT_TYPE } from '@/utils/constants'
#end
#if ($hasDateTime == 1)
import { formatDateTime } from '@/utils/date'
#end
const props = defineProps<{
id?: number | any
}>()
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const { hasAccessByCodes } = useAccess()
const toast = useToast()
const formData = ref<${simpleClassName}>()
const deleting = ref(false)
/** 返回上一页 */
function handleBack() {
navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index')
}
/** 加载${table.classComment}详情 */
async function getDetail() {
if (!props.id) {
return
}
try {
toast.loading('加载中...')
formData.value = await get${simpleClassName}(props.id)
} finally {
toast.close()
}
}
/** 编辑${table.classComment} */
function handleEdit() {
uni.navigateTo({
url: `/pages-${table.moduleName}/${table.businessName}/form/index?id=#[[${]]#props.id#[[}]]#`,
})
}
/** 删除${table.classComment} */
function handleDelete() {
if (!props.id) {
return
}
uni.showModal({
title: '提示',
content: '确定要删除该${table.classComment}吗?',
success: async (res) => {
if (!res.confirm) {
return
}
deleting.value = true
try {
await delete${simpleClassName}(props.id)
toast.success('删除成功')
setTimeout(() => {
handleBack()
}, 500)
} finally {
deleting.value = false
}
},
})
}
/** 初始化 */
onMounted(() => {
getDetail()
})
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,253 @@
<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
:title="getTitle"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 表单区域 -->
<view>
<wd-form ref="formRef" :model="formData" :rules="formRules">
<wd-cell-group border>
#foreach($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
## 优先判断是否有字典,有字典则使用 radio-group
#if (($column.htmlType == "select" || $column.htmlType == "radio") && $dictType && "" != $dictType)
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
<wd-radio-group v-model="formData.${javaField}" shape="button">
<wd-radio
v-for="dict in $dictMethod(DICT_TYPE.${dictType.toUpperCase()})"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</wd-radio>
</wd-radio-group>
</wd-cell>
## 数字类型(无字典)
#elseif (${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer" || ${javaType.toLowerCase()} == "short" || ${javaType.toLowerCase()} == "double" || ${javaType.toLowerCase()} == "bigdecimal" || ${javaType.toLowerCase()} == "byte")
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
<wd-input-number
v-model="formData.${javaField}"
:min="0"
/>
</wd-cell>
## 布尔类型
#elseif (${javaType.toLowerCase()} == "boolean")
<wd-cell title="${comment}" title-width="180rpx" prop="${javaField}" center>
<wd-switch v-model="formData.${javaField}" />
</wd-cell>
## 日期时间类型
#elseif (${javaType.toLowerCase()} == "date" || ${javaType.toLowerCase()} == "localdate" || ${javaType.toLowerCase()} == "localdatetime")
#set ($pickerType = "date")
#if (${javaType.toLowerCase()} == "localdatetime")
#set ($pickerType = "datetime")
#end
<wd-datetime-picker
v-model="formData.${javaField}"
type="${pickerType}"
label="${comment}"
label-width="180rpx"
prop="${javaField}"
/>
## 文本域
#elseif ($column.htmlType == "textarea")
<wd-textarea
v-model="formData.${javaField}"
label="${comment}"
label-width="180rpx"
placeholder="请输入${comment}"
:maxlength="200"
show-word-limit
clearable
/>
## 默认:文本输入
#else
<wd-input
v-model="formData.${javaField}"
label="${comment}"
label-width="180rpx"
prop="${javaField}"
clearable
placeholder="请输入${comment}"
/>
#end
#end
#end
</wd-cell-group>
</wd-form>
</view>
<!-- 底部保存按钮 -->
<view class="yd-detail-footer">
<wd-button
type="primary"
block
:loading="formLoading"
@click="handleSubmit"
>
保存
</wd-button>
</view>
</view>
</template>
<script lang="ts" setup>
#set ($primaryJavaType = $primaryColumn.javaType.toLowerCase())
#if(${primaryJavaType} == "long" || ${primaryJavaType} == "integer" || ${primaryJavaType} == "short" || ${primaryJavaType} == "double" || ${primaryJavaType} == "bigdecimal" || ${primaryJavaType} == "byte")
#set ($primaryTsType = "number")
#else
#set ($primaryTsType = "string")
#end
#set ($hasDict = 0)
#set ($hasGetDictOptions = 0)
#set ($hasGetIntDictOptions = 0)
#set ($hasGetStrDictOptions = 0)
#set ($hasGetBoolDictOptions = 0)
#foreach ($column in $columns)
#if (($column.createOperation || $column.updateOperation) && !$column.primaryKey
&& ($column.htmlType == "select" || $column.htmlType == "radio")
&& $column.dictType && "" != $column.dictType)
#set ($hasDict = 1)
#if ($column.javaType == "Integer" || $column.javaType == "Long" || $column.javaType == "Byte" || $column.javaType == "Short")
#set ($hasGetIntDictOptions = 1)
#elseif ($column.javaType == "String")
#set ($hasGetStrDictOptions = 1)
#elseif ($column.javaType == "Boolean")
#set ($hasGetBoolDictOptions = 1)
#else
#set ($hasGetDictOptions = 1)
#end
#end
#end
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
import { computed, onMounted, ref } from 'vue'
import { useToast } from 'wot-design-uni'
import { create${simpleClassName}, get${simpleClassName}, update${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
#if ($hasDict == 1)
#set ($dictImportNames = "")
#if ($hasGetDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getDictOptions, ")
#end
#if ($hasGetIntDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getIntDictOptions, ")
#end
#if ($hasGetStrDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getStrDictOptions, ")
#end
#if ($hasGetBoolDictOptions == 1)
#set ($dictImportNames = "${dictImportNames}getBoolDictOptions, ")
#end
#set ($dictImportNames = $dictImportNames.trim())
#set ($dictImportNames = $dictImportNames.substring(0, $dictImportNames.length() - 1))
import { $dictImportNames } from '@/hooks/useDict'
#end
import { navigateBackPlus } from '@/utils'
#if ($hasDict == 1)
import { DICT_TYPE } from '@/utils/constants'
#end
const props = defineProps<{
id?: ${primaryTsType} | any
}>()
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const toast = useToast()
const getTitle = computed(() => props.id ? '编辑${table.classComment}' : '新增${table.classComment}')
const formLoading = ref(false)
const formData = ref<${simpleClassName}>({
#foreach($column in $columns)
#if (($column.createOperation || $column.updateOperation) || $column.primaryKey)
#set ($javaType = $column.javaType.toLowerCase())
#set ($javaFieldLower = $column.javaField.toLowerCase())
#set ($optional = $column.nullable || $column.primaryKey || $javaFieldLower == "createtime" || $javaFieldLower == "updatetime")
#if ($column.primaryKey)
${column.javaField}: undefined,
#elseif(${javaType} == "long" || ${javaType} == "integer" || ${javaType} == "short" || ${javaType} == "double" || ${javaType} == "bigdecimal" || ${javaType} == "byte")
${column.javaField}: 0,
#elseif(${javaType} == "boolean")
${column.javaField}: false,
#elseif(${javaType} == "date" || ${javaType} == "localdate" || ${javaType} == "localdatetime")
${column.javaField}: undefined,
#else
${column.javaField}: '',
#end
#end
#end
})
const formRules = {
#foreach($column in $columns)
#set ($javaFieldLower = $column.javaField.toLowerCase())
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !$column.primaryKey
&& $javaFieldLower != "createtime" && $javaFieldLower != "updatetime")
${column.javaField}: [{ required: true, message: '${column.columnComment}不能为空' }],
#end
#end
}
const formRef = ref()
/** 返回上一页 */
function handleBack() {
navigateBackPlus('/pages-${table.moduleName}/${table.businessName}/index')
}
/** 加载${table.classComment}详情 */
async function getDetail() {
if (!props.id) {
return
}
formData.value = await get${simpleClassName}(props.id)
}
/** 提交表单 */
async function handleSubmit() {
const { valid } = await formRef.value.validate()
if (!valid) {
return
}
formLoading.value = true
try {
if (props.id) {
await update${simpleClassName}(formData.value)
toast.success('修改成功')
} else {
await create${simpleClassName}(formData.value)
toast.success('新增成功')
}
setTimeout(() => {
handleBack()
}, 500)
} finally {
formLoading.value = false
}
}
/** 初始化 */
onMounted(() => {
getDetail()
})
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,211 @@
<template>
<view class="yd-page-container">
<!-- 顶部导航栏 -->
<wd-navbar
title="${table.classComment}管理"
left-arrow placeholder safe-area-inset-top fixed
@click-left="handleBack"
/>
<!-- 搜索组件 -->
<SearchForm @search="handleQuery" @reset="handleReset" />
<!-- ${table.classComment}列表 -->
<view class="p-24rpx">
<view
v-for="item in list"
:key="item.${primaryColumn.javaField}"
class="mb-24rpx overflow-hidden rounded-12rpx bg-white shadow-sm"
@click="handleDetail(item)"
>
<view class="p-24rpx">
#set ($titleField = "")
#set ($statusField = "")
#set ($statusDictType = "")
#foreach($column in $columns)
#if ($titleField == "" && !$column.primaryKey && $column.listOperationResult)
#set ($titleField = $column.javaField)
#set ($titleComment = $column.columnComment)
#end
#if ($statusField == "" && $column.listOperationResult && $column.dictType && "" != $column.dictType)
#set ($statusField = $column.javaField)
#set ($statusDictType = $column.dictType)
#end
#end
#if ($titleField == "")
#set ($titleField = $primaryColumn.javaField)
#end
<view class="mb-16rpx flex items-center justify-between">
<view class="text-32rpx text-[#333] font-semibold">
{{ item.${titleField} }}
</view>
#if($statusField != "")
<dict-tag :type="DICT_TYPE.${statusDictType.toUpperCase()}" :value="item.${statusField}" />
#end
</view>
#foreach($column in $columns)
#if ($column.listOperationResult && !$column.primaryKey && $column.javaField != $titleField && $column.javaField != $statusField)
#set ($javaField = $column.javaField)
#set ($comment = $column.columnComment)
#set ($dictType = $column.dictType)
#set ($javaType = $column.javaType)
#if ($dictType && "" != $dictType)
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
<text class="mr-8rpx text-[#999]">${comment}</text>
<dict-tag :type="DICT_TYPE.${dictType.toUpperCase()}" :value="item.${javaField}" />
</view>
#elseif ($javaType == "LocalDateTime")
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
<text class="mr-8rpx text-[#999]">${comment}</text>
<text class="line-clamp-1">{{ formatDateTime(item.${javaField}) || '-' }}</text>
</view>
#else
<view class="mb-12rpx flex items-center text-28rpx text-[#666]">
<text class="mr-8rpx text-[#999]">${comment}</text>
<text class="line-clamp-1">{{ item.${javaField} }}</text>
</view>
#end
#end
#end
</view>
</view>
<!-- 加载更多 -->
<view v-if="loadMoreState !== 'loading' && list.length === 0" class="py-100rpx text-center">
<wd-status-tip image="content" tip="暂无${table.classComment}数据" />
</view>
<wd-loadmore
v-if="list.length > 0"
:state="loadMoreState"
@reload="loadMore"
/>
</view>
<!-- 新增按钮 -->
<wd-fab
v-if="hasAccessByCodes(['${permissionPrefix}:create'])"
position="right-bottom"
type="primary"
:expandable="false"
@click="handleAdd"
/>
</view>
</template>
<script lang="ts" setup>
#set ($hasDict = 0)
#foreach($column in $columns)
#if ($hasDict == 0 && $column.listOperationResult && $column.dictType && "" != $column.dictType)
#set ($hasDict = 1)
#end
#end
#set ($hasDateTime = 0)
#foreach($column in $columns)
#if ($column.listOperationResult)
#if ($hasDateTime == 0 && $column.javaType == "LocalDateTime")
#set ($hasDateTime = 1)
#end
#end
#end
import type { ${simpleClassName} } from '@/api/${table.moduleName}/${table.businessName}'
import type { LoadMoreState } from '@/http/types'
import { onReachBottom } from '@dcloudio/uni-app'
import { onMounted, ref } from 'vue'
import { get${simpleClassName}Page } from '@/api/${table.moduleName}/${table.businessName}'
import { useAccess } from '@/hooks/useAccess'
import { navigateBackPlus } from '@/utils'
#if ($hasDict == 1)
import { DICT_TYPE } from '@/utils/constants'
#end
#if ($hasDateTime == 1)
import { formatDateTime } from '@/utils/date'
#end
import SearchForm from './components/search-form.vue'
definePage({
style: {
navigationBarTitleText: '',
navigationStyle: 'custom',
},
})
const { hasAccessByCodes } = useAccess()
const total = ref(0)
const list = ref<${simpleClassName}[]>([])
const loadMoreState = ref<LoadMoreState>('loading')
const queryParams = ref({
pageNo: 1,
pageSize: 10,
})
/** 返回上一页 */
function handleBack() {
navigateBackPlus()
}
/** 查询${table.classComment}列表 */
async function getList() {
loadMoreState.value = 'loading'
try {
const data = await get${simpleClassName}Page(queryParams.value)
list.value = [...list.value, ...data.list]
total.value = data.total
loadMoreState.value = list.value.length >= total.value ? 'finished' : 'loading'
} catch {
queryParams.value.pageNo = queryParams.value.pageNo > 1 ? queryParams.value.pageNo - 1 : 1
loadMoreState.value = 'error'
}
}
/** 搜索按钮操作 */
function handleQuery(data?: Record<string, any>) {
queryParams.value = {
...data,
pageNo: 1,
pageSize: queryParams.value.pageSize,
}
list.value = []
getList()
}
/** 重置按钮操作 */
function handleReset() {
handleQuery()
}
/** 加载更多 */
function loadMore() {
if (loadMoreState.value === 'finished') {
return
}
queryParams.value.pageNo++
getList()
}
/** 新增${table.classComment} */
function handleAdd() {
uni.navigateTo({
url: '/pages-${table.moduleName}/${table.businessName}/form/index',
})
}
/** 查看详情 */
function handleDetail(item: ${simpleClassName}) {
uni.navigateTo({
url: `/pages-${table.moduleName}/${table.businessName}/detail/index?id=#[[${]]#item.${primaryColumn.javaField}#[[}]]#`,
})
}
/** 触底加载更多 */
onReachBottom(() => {
loadMore()
})
/** 初始化 */
onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped>
</style>

View File

@@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTa
import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.DatabaseTableRespVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
@@ -19,7 +20,9 @@ import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine;
import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService;
import cn.iocoder.yudao.module.infra.service.db.DatabaseTableService;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import org.junit.jupiter.api.Test;
@@ -62,6 +65,8 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
@MockBean
private DatabaseTableService databaseTableService;
@MockitoBean
private DataSourceConfigService dataSourceConfigService;
@MockBean
private CodegenBuilder codegenBuilder;
@@ -453,9 +458,12 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
CodegenColumnDO column02 = randomPojo(CodegenColumnDO.class, o -> o.setTableId(table.getId())
.setOrdinalPosition(2));
codegenColumnMapper.insert(column02);
// mock 数据DataSourceConfigDO
when(dataSourceConfigService.getDataSourceConfig(eq(table.getDataSourceConfigId())))
.thenReturn(randomPojo(DataSourceConfigDO.class, o -> o.setUrl("jdbc:mysql://")));
// mock 执行生成
Map<String, String> codes = MapUtil.of(randomString(), randomString());
when(codegenEngine.execute(eq(table), argThat(columns -> {
when(codegenEngine.execute(eq(DbType.MYSQL), eq(table), argThat(columns -> {
assertEquals(2, columns.size());
assertEquals(column01, columns.get(0));
assertEquals(column02, columns.get(1));
@@ -494,9 +502,12 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
// mock 数据sub CodegenColumnDO
CodegenColumnDO subColumn01 = randomPojo(CodegenColumnDO.class, o -> o.setId(1024L).setTableId(subTable.getId()));
codegenColumnMapper.insert(subColumn01);
// mock 数据DataSourceConfigDO
when(dataSourceConfigService.getDataSourceConfig(eq(table.getDataSourceConfigId())))
.thenReturn(randomPojo(DataSourceConfigDO.class, o -> o.setUrl("jdbc:mysql://")));
// mock 执行生成
Map<String, String> codes = MapUtil.of(randomString(), randomString());
when(codegenEngine.execute(eq(table), argThat(columns -> {
when(codegenEngine.execute(eq(DbType.MYSQL), eq(table), argThat(columns -> {
assertEquals(2, columns.size());
assertEquals(column01, columns.get(0));
assertEquals(column02, columns.get(1));

View File

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.baomidou.mybatisplus.annotation.DbType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -28,7 +29,7 @@ public class CodegenEngineVue2Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> columns = getColumnList("student");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null);
// 生成测试文件
//writeResult(result, resourcesPath + "/vue2_one");
// 断言
@@ -44,7 +45,7 @@ public class CodegenEngineVue2Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> columns = getColumnList("category");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null);
// 生成测试文件
//writeResult(result, resourcesPath + "/vue2_tree");
// 断言
@@ -88,7 +89,7 @@ public class CodegenEngineVue2Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> teacherColumns = getColumnList("teacher");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns,
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns,
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
// 生成测试文件
//writeResult(result, resourcesPath + path);

View File

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO;
import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum;
import com.baomidou.mybatisplus.annotation.DbType;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -28,7 +29,7 @@ public class CodegenEngineVue3Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> columns = getColumnList("student");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null);
// 生成测试文件
//writeResult(result, resourcesPath + "/vue3_one");
// 断言
@@ -44,7 +45,7 @@ public class CodegenEngineVue3Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> columns = getColumnList("category");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns, null, null);
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns, null, null);
// 生成测试文件
//writeResult(result, resourcesPath + "/vue3_tree");
// 断言
@@ -88,7 +89,7 @@ public class CodegenEngineVue3Test extends CodegenEngineAbstractTest {
List<CodegenColumnDO> teacherColumns = getColumnList("teacher");
// 调用
Map<String, String> result = codegenEngine.execute(table, columns,
Map<String, String> result = codegenEngine.execute(DbType.MYSQL, table, columns,
Arrays.asList(contactTable, teacherTable), Arrays.asList(contactColumns, teacherColumns));
// 生成测试文件
//writeResult(result, resourcesPath + path);