feat(generator): 优化模板生成逻辑并添加新功能

- 改进 index.tsx 模板,增加智能字段检测和条件性功能生成
- 修复字段注释为空时模板渲染失败的问题
- 添加自动更新 app.config.ts 页面路径的功能
- 新增 ShopArticle相关的实体、Mapper、Service 等代码
- 优化 add.tsx 和 add.config.ts模板,提高用户体验
This commit is contained in:
2025-08-13 00:31:51 +08:00
parent 6caf434c3d
commit eac1102eb1
18 changed files with 1356 additions and 21 deletions

View File

@@ -13,6 +13,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* CMS模块-代码生成工具
@@ -56,7 +61,7 @@ public class CmsGenerator {
// "cms_docs_book",
// "cms_docs_content",
// "cms_ad",
"cms_ad_record",
// "cms_ad_record",
// "cms_navigation",
// "cms_design",
// "cms_design_record",
@@ -315,6 +320,87 @@ public class CmsGenerator {
mpg.setCfg(cfg);
mpg.execute();
// 自动更新 app.config.ts
updateAppConfig(TABLE_NAMES, MODULE_NAME);
}
/**
* 自动更新 app.config.ts 文件,添加新生成的页面路径
*/
private static void updateAppConfig(String[] tableNames, String moduleName) {
String appConfigPath = OUTPUT_LOCATION_UNIAPP + OUTPUT_DIR_VUE + "/app.config.ts";
try {
// 读取原文件内容
String content = new String(Files.readAllBytes(Paths.get(appConfigPath)));
// 为每个表生成页面路径
StringBuilder newPages = new StringBuilder();
for (String tableName : tableNames) {
String entityPath = tableName.replaceAll("_", "");
// 转换为驼峰命名
String[] parts = tableName.split("_");
StringBuilder camelCase = new StringBuilder(parts[0]);
for (int i = 1; i < parts.length; i++) {
camelCase.append(parts[i].substring(0, 1).toUpperCase()).append(parts[i].substring(1));
}
entityPath = camelCase.toString();
newPages.append(" '").append(entityPath).append("/index',\n");
newPages.append(" '").append(entityPath).append("/add',\n");
}
// 查找对应模块的子包配置
String modulePattern = "\"root\":\\s*\"" + moduleName + "\",\\s*\"pages\":\\s*\\[([^\\]]*)]";
Pattern pattern = Pattern.compile(modulePattern, Pattern.DOTALL);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String existingPages = matcher.group(1);
// 检查页面是否已存在,避免重复添加
boolean needUpdate = false;
String[] newPageArray = newPages.toString().split("\n");
for (String newPage : newPageArray) {
if (!newPage.trim().isEmpty() && !existingPages.contains(newPage.trim().replace(" ", "").replace(",", ""))) {
needUpdate = true;
break;
}
}
if (needUpdate) {
// 备份原文件
String backupPath = appConfigPath + ".backup." + System.currentTimeMillis();
Files.copy(Paths.get(appConfigPath), Paths.get(backupPath));
System.out.println("已备份原文件到: " + backupPath);
// 在现有页面列表末尾添加新页面
String updatedPages = existingPages.trim();
if (!updatedPages.endsWith(",")) {
updatedPages += ",";
}
updatedPages += "\n" + newPages.toString().trim();
// 替换内容
String updatedContent = content.replace(matcher.group(1), updatedPages);
// 写入更新后的内容
Files.write(Paths.get(appConfigPath), updatedContent.getBytes());
System.out.println("✅ 已自动更新 app.config.ts添加了以下页面路径:");
System.out.println(newPages.toString());
} else {
System.out.println(" app.config.ts 中已包含所有页面路径,无需更新");
}
} else {
System.out.println("⚠️ 未找到 " + moduleName + " 模块的子包配置,请手动添加页面路径");
}
} catch (Exception e) {
System.err.println("❌ 更新 app.config.ts 失败: " + e.getMessage());
e.printStackTrace();
}
}
}

View File

@@ -13,6 +13,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* CMS模块-代码生成工具
@@ -100,6 +105,7 @@ public class ShopGenerator {
// "shop_express_template",
// "shop_express_template_detail",
// "shop_gift"
"shop_article"
};
// 需要去除的表前缀
private static final String[] TABLE_PREFIX = new String[]{
@@ -343,6 +349,87 @@ public class ShopGenerator {
mpg.setCfg(cfg);
mpg.execute();
// 自动更新 app.config.ts
updateAppConfig(TABLE_NAMES, MODULE_NAME);
}
/**
* 自动更新 app.config.ts 文件,添加新生成的页面路径
*/
private static void updateAppConfig(String[] tableNames, String moduleName) {
String appConfigPath = OUTPUT_LOCATION_UNIAPP + OUTPUT_DIR_VUE + "/app.config.ts";
try {
// 读取原文件内容
String content = new String(Files.readAllBytes(Paths.get(appConfigPath)));
// 为每个表生成页面路径
StringBuilder newPages = new StringBuilder();
for (String tableName : tableNames) {
String entityPath = tableName.replaceAll("_", "");
// 转换为驼峰命名
String[] parts = tableName.split("_");
StringBuilder camelCase = new StringBuilder(parts[0]);
for (int i = 1; i < parts.length; i++) {
camelCase.append(parts[i].substring(0, 1).toUpperCase()).append(parts[i].substring(1));
}
entityPath = camelCase.toString();
newPages.append(" '").append(entityPath).append("/index',\n");
newPages.append(" '").append(entityPath).append("/add',\n");
}
// 查找对应模块的子包配置
String modulePattern = "\"root\":\\s*\"" + moduleName + "\",\\s*\"pages\":\\s*\\[([^\\]]*)]";
Pattern pattern = Pattern.compile(modulePattern, Pattern.DOTALL);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String existingPages = matcher.group(1);
// 检查页面是否已存在,避免重复添加
boolean needUpdate = false;
String[] newPageArray = newPages.toString().split("\n");
for (String newPage : newPageArray) {
if (!newPage.trim().isEmpty() && !existingPages.contains(newPage.trim().replace(" ", "").replace(",", ""))) {
needUpdate = true;
break;
}
}
if (needUpdate) {
// 备份原文件
String backupPath = appConfigPath + ".backup." + System.currentTimeMillis();
Files.copy(Paths.get(appConfigPath), Paths.get(backupPath));
System.out.println("已备份原文件到: " + backupPath);
// 在现有页面列表末尾添加新页面
String updatedPages = existingPages.trim();
if (!updatedPages.endsWith(",")) {
updatedPages += ",";
}
updatedPages += "\n" + newPages.toString().trim();
// 替换内容
String updatedContent = content.replace(matcher.group(1), updatedPages);
// 写入更新后的内容
Files.write(Paths.get(appConfigPath), updatedContent.getBytes());
System.out.println("✅ 已自动更新 app.config.ts添加了以下页面路径:");
System.out.println(newPages.toString());
} else {
System.out.println(" app.config.ts 中已包含所有页面路径,无需更新");
}
} else {
System.out.println("⚠️ 未找到 " + moduleName + " 模块的子包配置,请手动添加页面路径");
}
} catch (Exception e) {
System.err.println("❌ 更新 app.config.ts 失败: " + e.getMessage());
e.printStackTrace();
}
}
}

View File

@@ -1,4 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '新增${table.comment!}',
navigationBarTitleText: '新增${table.comment!'数据'}',
navigationBarTextStyle: 'black'
})

View File

@@ -36,7 +36,7 @@ const Add${entity} = () => {
}
Taro.showToast({
title: `${params.id ? '更新' : '保存'}成功`,
title: `操作成功`,
icon: 'success'
})
@@ -45,7 +45,7 @@ const Add${entity} = () => {
}, 1000)
} catch (error) {
Taro.showToast({
title: `${params.id ? '更新' : '保存'}失败`,
title: `操作失败`,
icon: 'error'
});
}
@@ -97,11 +97,11 @@ const Add${entity} = () => {
<CellGroup style={{padding: '4px 0'}}>
<% for(field in table.fields){ %>
<% if(field.propertyName != 'id' && field.propertyName != 'createTime' && field.propertyName != 'updateTime'){ %>
<Form.Item name="${field.propertyName}" label="${field.comment!}" initialValue={FormData.${field.propertyName}} required>
<% if(field.propertyType == 'String' && (field.comment?contains('描述') || field.comment?contains('备注') || field.comment?contains('内容'))){ %>
<TextArea maxLength={200} placeholder="请输入${field.comment!}"/>
<Form.Item name="${field.propertyName}" label="${field.comment!field.propertyName}" initialValue={FormData.${field.propertyName}} required>
<% if(field.propertyType == 'String' && field.comment?? && (field.comment?contains('描述') || field.comment?contains('备注') || field.comment?contains('内容'))){ %>
<TextArea maxLength={200} placeholder="请输入${field.comment!'内容'}"/>
<% } else { %>
<Input placeholder="请输入${field.comment!}" maxLength={50}/>
<Input placeholder="请输入${field.comment!'字段'}" maxLength={50}/>
<% } %>
</Form.Item>
<% } %>

View File

@@ -131,11 +131,19 @@ public class ${table.controllerName} {
<% } %>
@PostMapping()
public ApiResult<?> save(@RequestBody ${entity} ${table.entityPath}) {
<% var hasUserIdField = false; %>
<% for(field in table.fields){ %>
<% if(field.propertyName == 'userId'){ %>
<% hasUserIdField = true; %>
<% } %>
<% } %>
<% if(hasUserIdField){ %>
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
${table.entityPath}.setUserId(loginUser.getUserId());
}
<% } %>
if (${serviceIns}.save(${table.entityPath})) {
return success("添加成功");
}

View File

@@ -1,4 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '${table.comment!}管理',
navigationBarTitleText: '${table.comment!'数据'}管理',
navigationBarTextStyle: 'black'
})

View File

@@ -8,7 +8,15 @@ import {list${entity}, remove${entity}, update${entity}} from "@/api/${package.M
const ${entity}List = () => {
const [list, setList] = useState<${entity}[]>([])
<% var hasIsDefaultField = false; %>
<% for(field in table.fields){ %>
<% if(field.propertyName == 'isDefault'){ %>
<% hasIsDefaultField = true; %>
<% } %>
<% } %>
<% if(hasIsDefaultField){ %>
const [selectedItem, setSelectedItem] = useState<${entity}>()
<% } %>
const reload = () => {
list${entity}({
@@ -16,8 +24,10 @@ const ${entity}List = () => {
})
.then(data => {
setList(data || [])
<% if(hasIsDefaultField){ %>
// 设置默认选中项
setSelectedItem(data.find(item => item.isDefault))
<% } %>
})
.catch(() => {
Taro.showToast({
@@ -27,6 +37,7 @@ const ${entity}List = () => {
})
}
<% if(hasIsDefaultField){ %>
const onDefault = async (item: ${entity}) => {
if (selectedItem) {
await update${entity}({
@@ -45,15 +56,6 @@ const ${entity}List = () => {
reload();
}
const onDel = async (id?: number) => {
await remove${entity}(id)
Taro.showToast({
title: '删除成功',
icon: 'success'
});
reload();
}
const selectItem = async (item: ${entity}) => {
if (selectedItem) {
await update${entity}({
@@ -69,6 +71,18 @@ const ${entity}List = () => {
Taro.navigateBack()
},500)
}
<% } %>
const onDel = async (id?: number) => {
await remove${entity}(id)
Taro.showToast({
title: '删除成功',
icon: 'success'
});
reload();
}
useDidShow(() => {
reload()
@@ -98,22 +112,38 @@ const ${entity}List = () => {
<>
{list.map((item, _) => (
<Cell.Group key={item.id}>
<% if(hasIsDefaultField){ %>
<Cell className={'flex flex-col gap-1'} onClick={() => selectItem(item)}>
<% } else { %>
<Cell className={'flex flex-col gap-1'}>
<% } %>
<View>
<View className={'font-medium text-sm'}>{item.name}</View>
<% var displayFields = []; %>
<% for(field in table.fields){ %>
<% if(field.propertyName != 'id' && field.propertyName != 'createTime' && field.propertyName != 'updateTime' && field.propertyName != 'isDefault'){ %>
<% displayFields.add(field); %>
<% } %>
<% } %>
<% if(displayFields.size() > 0){ %>
<View className={'font-medium text-sm'}>{item.${displayFields[0].propertyName}}</View>
<% } %>
</View>
<% if(displayFields.size() > 1){ %>
<View className={'text-xs'}>
{item.description}
{item.${displayFields[1].propertyName}}
</View>
<% } %>
</Cell>
<Cell
align="center"
<% if(hasIsDefaultField){ %>
title={
<View className={'flex items-center gap-1'} onClick={() => onDefault(item)}>
{item.isDefault ? <Checked className={'text-green-600'} size={16}/> : <CheckNormal size={16}/>}
<View className={'text-gray-400'}>默认选项</View>
</View>
}
<% } %>
extra={
<>
<View className={'text-gray-400'} onClick={() => onDel(item.id)}>