From 4b26fa67fb8bb170d8977eba5fa9714b2e1d866c Mon Sep 17 00:00:00 2001 From: zhanglei Date: Fri, 3 Apr 2026 13:23:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9B=BE=E6=A0=87=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- generator.py | 372 ------------------------------------- main.py | 377 ++++++++++++++++++++++++++++++++++++++ utils.py | 6 + frontend_vue.py => vue.py | 29 +-- 4 files changed, 385 insertions(+), 399 deletions(-) delete mode 100644 generator.py create mode 100644 main.py rename frontend_vue.py => vue.py (73%) diff --git a/generator.py b/generator.py deleted file mode 100644 index 29d4622..0000000 --- a/generator.py +++ /dev/null @@ -1,372 +0,0 @@ -import logging -import os -from datetime import datetime -from jinja2 import Environment, FileSystemLoader,TemplateNotFound -# from config import * -from db import get_table, get_columns -from utils import * -import argparse -import yaml -import re - -env = Environment(loader=FileSystemLoader("templates/java")) - -def build_fields(table_name): - columns = get_columns(table_name) - fields = [] - for c in columns: - fields.append({ - "java_name": to_camel(c["column_name"]), - "tab_name": c["column_name"], - "tab_type": c["data_type"], - "java_get_name": to_class(c["column_name"]), - "java_type": mysql_to_java(c["data_type"]), - "comment": c["column_comment"] - }) - return fields - -def render(template_name, out_path, context, java_version, overwrite=False): - """ - :param template_name: 模板文件名 - :param out_path: 输出文件路径 - :param context: 渲染上下文 - :param overwrite: 是否覆盖已存在文件,默认 False - """ - - # 文件存在且不允许覆盖 → 跳过 - if os.path.exists(out_path) and not overwrite: - logging.info("Skip exists file: %s", out_path) - return - - if java_version != "": - template_name = java_version+"."+template_name - - real_template = template_name - - print(">>>>template_name:", template_name) - - # 1️⃣ 尝试原模板 - try: - env.loader.get_source(env, real_template) - except TemplateNotFound: - # 2️⃣ 去掉数字前缀,如 21.controller.java.j2 → controller.java.j2 - fallback = re.sub(r"^\d+\.", "", template_name) - - if fallback != template_name: - try: - env.loader.get_source(env, fallback) - logging.warning( - "Template not found: %s, fallback to %s", - template_name, fallback - ) - real_template = fallback - except TemplateNotFound: - raise FileNotFoundError( - f"Template not found: {template_name} and fallback {fallback}" - ) - else: - raise FileNotFoundError(f"Template not found: {template_name}") - - # 3️⃣ 正式渲染 - tpl = env.get_template(real_template) - content = tpl.render(**context) - - os.makedirs(os.path.dirname(out_path), exist_ok=True) - with open(out_path, "w", encoding="utf-8") as f: - f.write(content) - - logging.info("Generated file: %s (template: %s)", out_path, real_template) - - -def generate(table_names: list[str], model_names: list[str], conf_name: str, over_write: bool, java_version: str): - - with open(conf_name, "r", encoding="utf-8") as f: - cfg = yaml.safe_load(f) - cfg = resolve_config(cfg) - - context = { - "mainModule": cfg["mainModule"], - "moduleName": cfg["moduleName"], - "groupId": cfg["groupId"], - "author": cfg["author"], - "wechat": cfg["wechat"], - "date": datetime.now().strftime("%Y-%m-%d"), - "entityLombokModel": cfg["entityLombokModel"], - "package": cfg["package"], - "db": cfg["db"], - "application": cfg["application"], - "restControllerStyle": cfg["restControllerStyle"] - } - # MAIN_BASE_PACKAGE_DIR = f"{OUTPUT_DIR}/java/{to_path(BASE_PACKAGE)}" - # MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{DEFAULT_PREFIX_URL}" - - BASE_DIR = cfg["baseDir"] - BASE_PACKAGE = cfg["package"]["Base"] - OUTPUT_DIR = cfg["outputDir"] - MAIN_MODULE = cfg["mainModule"] - MODULE_NAME = cfg["moduleName"] - MAIN_BASE_PACKAGE_DIR = f"{cfg['outputDir']}/java/{to_path(BASE_PACKAGE)}" - MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{cfg['package']['Models']}" - - - # ========= 按表循环 ========= - for table_name in table_names: - table = get_table(table_name) - entity = to_class(table_name) - - context = dict(context) - context.update({ - "fields": build_fields(table_name), - "table": { - "tabToPath": tab_to_path(table_name), - "entity": entity, - "lowerEntity": lower_first(entity), - "name": table_name, - "comment": table["table_comment"] - } - }) - - # ========= 需要循环生成的模板 ========= - render( - "entity.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/{entity}.java", - context, - java_version, - over_write - ) - - render( - "controller.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/{entity}Controller.java", - context, - java_version, - over_write - ) - - render( - "service.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/{entity}Service.java", - context, - java_version, - over_write - ) - - render( - "serviceImpl.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/impl/{entity}MPJBaseServiceImpl.java", - context, - java_version, - over_write - ) - - render( - "mapper.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/mapper/{entity}Mapper.java", - context, - java_version, - over_write - ) - - render( - "mapper.xml.j2", - f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/mappers/{entity}Mapper.xml", - context, - java_version, - over_write - ) - - # ========= 生成固定模板 ========= - # BaseEntity - render( - "baseEntity.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/BaseEntity.java", - context, - java_version - ) - - # common MybatisPlusConfig - render( - "mybatisPlusConfig.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MybatisPlusConfig.java", - context, - java_version - ) - - # common MybatisPlusConfig - render( - "webLogAspect.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/WebLogAspect.java", - context, - java_version - ) - - # common 基础输出result - render( - "result.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/vo/Result.java", - context, - java_version - ) - - #Util 公共功能 - for file in ["Md5HashUtil.java.j2","FilesUtil.java.j2"]: - render( - file, - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/{file.replace('.j2', '')}", - context, - java_version - ) - - # application 启动的方法 - render( - "application.java.j2", - f"{BASE_DIR}{MAIN_BASE_PACKAGE_DIR}/Application.java", - context, - java_version - ) - - # test 测试类 - render( - "applicationTests.java.j2", - f"{BASE_DIR}{OUTPUT_DIR}/test/{to_path(BASE_PACKAGE)}/ApplicationTests.java", - context, - java_version - ) - - # 主pom文件 - render( - "main.pom.xml.j2", - f"{BASE_DIR}{MAIN_MODULE}/pom.xml", - context, - java_version - ) - - # 子项目pom文件 - render( - "project.pom.xml.j2", - f"{BASE_DIR}{MAIN_MODULE}/{MODULE_NAME}/pom.xml", - context, - java_version - ) - - #项目的yml配置文件 resources 生成环境配置为了最低限度能将项目跑起来 - render( - "application.yml.j2", - f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application.yml", - context, - java_version - ) - - #项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 - render( - "application-dev.yml.j2", - f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application-dev.yml", - context, - java_version - ) - - #项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 - render( - "logback.xml.j2", - f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/logback.xml", - context, - java_version - ) - - # ========= 功能模块 ========= - for model_name in model_names: - match model_name: - case "swagger": - # common Swagger2 - render( - "SwaggerConfig.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/Swagger2.java", - context, - java_version - ) - case "saToken": - # common GlobalException soToken 报错自定义 - render( - "globalException.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/GlobalException.java", - context, - java_version - ) - render( - "SaTokenConfig.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/SaTokenConfig.java", - context, - java_version - ) - case "minio": - #MinioConfig - render( - "MinioConfig.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MinioConfig.java", - context, - java_version - ) - render( - "MinioUpController.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/MinioUpController.java", - context, - java_version - ) - render( - "MinioUpComponent.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/MinioUpComponent.java", - context, - java_version - ) - case "xxlJob": - # common XxlJobConfig - render( - "xxlJobConfig.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/XxlJobConfig.java", - context, - java_version - ) - # common xxjob的测试类 - render( - "testJob.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/job/TestJob.java", - context, - java_version - ) - case "vue": - # 如果生成vue,则一定要有table_names - if table_names is None or len(table_names) == 0: - print("生成vue相关公共,需要生成相对应的表") - else : - render( - "CommonController.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/CommonController.java", - context, - java_version, - over_write - ) - - render( - "CommonVueEnumsEntity.java.j2", - f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/CommonVueEnumsEntity.java", - context, - java_version, - over_write - ) - -if __name__ == "__main__": - args = parse_args() - - tables = [t.strip() for t in args.tab.split(",") if t.strip()] - models = [m.strip() for m in args.model.split(",") if m.strip()] - conf = args.conf - version = args.jdk - rew = args.rew - - generate( - table_names=tables, - model_names=models, - conf_name=conf, - java_version=version, - over_write=rew - ) \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..4cba234 --- /dev/null +++ b/main.py @@ -0,0 +1,377 @@ +import logging +import os +from datetime import datetime +from jinja2 import Environment, FileSystemLoader,TemplateNotFound +# from config import * +from db import get_table, get_columns +from utils import * +import argparse +import yaml +import re +from vue import generate_vue # ✅ 核心:引入前端模块 + +env = Environment(loader=FileSystemLoader("templates/java")) + +def build_fields(table_name): + columns = get_columns(table_name) + fields = [] + for c in columns: + fields.append({ + "java_name": to_camel(c["column_name"]), + "tab_name": c["column_name"], + "tab_type": c["data_type"], + "java_get_name": to_class(c["column_name"]), + "java_type": mysql_to_java(c["data_type"]), + "comment": c["column_comment"] + }) + return fields + +def render(template_name, out_path, context, java_version, overwrite=False): + """ + :param template_name: 模板文件名 + :param out_path: 输出文件路径 + :param context: 渲染上下文 + :param overwrite: 是否覆盖已存在文件,默认 False + """ + + # 文件存在且不允许覆盖 → 跳过 + if os.path.exists(out_path) and not overwrite: + logging.info("Skip exists file: %s", out_path) + return + + if java_version != "": + template_name = java_version+"."+template_name + + real_template = template_name + + print(">>>>template_name:", template_name) + + # 1️⃣ 尝试原模板 + try: + env.loader.get_source(env, real_template) + except TemplateNotFound: + # 2️⃣ 去掉数字前缀,如 21.controller.java.j2 → controller.java.j2 + fallback = re.sub(r"^\d+\.", "", template_name) + + if fallback != template_name: + try: + env.loader.get_source(env, fallback) + logging.warning( + "Template not found: %s, fallback to %s", + template_name, fallback + ) + real_template = fallback + except TemplateNotFound: + raise FileNotFoundError( + f"Template not found: {template_name} and fallback {fallback}" + ) + else: + raise FileNotFoundError(f"Template not found: {template_name}") + + # 3️⃣ 正式渲染 + tpl = env.get_template(real_template) + content = tpl.render(**context) + + os.makedirs(os.path.dirname(out_path), exist_ok=True) + with open(out_path, "w", encoding="utf-8") as f: + f.write(content) + + logging.info("Generated file: %s (template: %s)", out_path, real_template) + + +def generate(table_names: list[str], model_names: list[str], conf_name: str, over_write: bool, java_version: str, vue: str): + + with open(conf_name, "r", encoding="utf-8") as f: + cfg = yaml.safe_load(f) + cfg = resolve_config(cfg) + if(vue!=""): + generate_vue(vue, cfg) + else : + context = { + "mainModule": cfg["mainModule"], + "moduleName": cfg["moduleName"], + "groupId": cfg["groupId"], + "author": cfg["author"], + "wechat": cfg["wechat"], + "date": datetime.now().strftime("%Y-%m-%d"), + "entityLombokModel": cfg["entityLombokModel"], + "package": cfg["package"], + "db": cfg["db"], + "application": cfg["application"], + "restControllerStyle": cfg["restControllerStyle"] + } + # MAIN_BASE_PACKAGE_DIR = f"{OUTPUT_DIR}/java/{to_path(BASE_PACKAGE)}" + # MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{DEFAULT_PREFIX_URL}" + + BASE_DIR = cfg["baseDir"] + BASE_PACKAGE = cfg["package"]["Base"] + OUTPUT_DIR = cfg["outputDir"] + MAIN_MODULE = cfg["mainModule"] + MODULE_NAME = cfg["moduleName"] + MAIN_BASE_PACKAGE_DIR = f"{cfg['outputDir']}/java/{to_path(BASE_PACKAGE)}" + MAIN_OUTPUT_DIR = f"{MAIN_BASE_PACKAGE_DIR}/{cfg['package']['Models']}" + + + # ========= 按表循环 ========= + for table_name in table_names: + table = get_table(table_name) + entity = to_class(table_name) + + context = dict(context) + context.update({ + "fields": build_fields(table_name), + "table": { + "tabToPath": tab_to_path(table_name), + "entity": entity, + "lowerEntity": lower_first(entity), + "name": table_name, + "comment": table["table_comment"] + } + }) + + # ========= 需要循环生成的模板 ========= + render( + "entity.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/{entity}.java", + context, + java_version, + over_write + ) + + render( + "controller.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/{entity}Controller.java", + context, + java_version, + over_write + ) + + render( + "service.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/{entity}Service.java", + context, + java_version, + over_write + ) + + render( + "serviceImpl.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/service/impl/{entity}MPJBaseServiceImpl.java", + context, + java_version, + over_write + ) + + render( + "mapper.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/mapper/{entity}Mapper.java", + context, + java_version, + over_write + ) + + render( + "mapper.xml.j2", + f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/mappers/{entity}Mapper.xml", + context, + java_version, + over_write + ) + + # ========= 生成固定模板 ========= + # BaseEntity + render( + "baseEntity.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/BaseEntity.java", + context, + java_version + ) + + # common MybatisPlusConfig + render( + "mybatisPlusConfig.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MybatisPlusConfig.java", + context, + java_version + ) + + # common MybatisPlusConfig + render( + "webLogAspect.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/WebLogAspect.java", + context, + java_version + ) + + # common 基础输出result + render( + "result.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/vo/Result.java", + context, + java_version + ) + + #Util 公共功能 + for file in ["Md5HashUtil.java.j2","FilesUtil.java.j2"]: + render( + file, + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/{file.replace('.j2', '')}", + context, + java_version + ) + + # application 启动的方法 + render( + "application.java.j2", + f"{BASE_DIR}{MAIN_BASE_PACKAGE_DIR}/Application.java", + context, + java_version + ) + + # test 测试类 + render( + "applicationTests.java.j2", + f"{BASE_DIR}{OUTPUT_DIR}/test/{to_path(BASE_PACKAGE)}/ApplicationTests.java", + context, + java_version + ) + + # 主pom文件 + render( + "main.pom.xml.j2", + f"{BASE_DIR}{MAIN_MODULE}/pom.xml", + context, + java_version + ) + + # 子项目pom文件 + render( + "project.pom.xml.j2", + f"{BASE_DIR}{MAIN_MODULE}/{MODULE_NAME}/pom.xml", + context, + java_version + ) + + #项目的yml配置文件 resources 生成环境配置为了最低限度能将项目跑起来 + render( + "application.yml.j2", + f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application.yml", + context, + java_version + ) + + #项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 + render( + "application-dev.yml.j2", + f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/application-dev.yml", + context, + java_version + ) + + #项目开发环境的yml配置文件 resources yml 只生成dev环境配置为了最低限度能将项目跑起来 + render( + "logback.xml.j2", + f"{MAIN_MODULE}/{MODULE_NAME}/src/main/resources/logback.xml", + context, + java_version + ) + + # ========= 功能模块 ========= + for model_name in model_names: + match model_name: + case "swagger": + # common Swagger2 + render( + "SwaggerConfig.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/Swagger2.java", + context, + java_version + ) + case "saToken": + # common GlobalException soToken 报错自定义 + render( + "globalException.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/GlobalException.java", + context, + java_version + ) + render( + "SaTokenConfig.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/SaTokenConfig.java", + context, + java_version + ) + case "minio": + #MinioConfig + render( + "MinioConfig.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/MinioConfig.java", + context, + java_version + ) + render( + "MinioUpController.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/MinioUpController.java", + context, + java_version + ) + render( + "MinioUpComponent.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/unit/MinioUpComponent.java", + context, + java_version + ) + case "xxlJob": + # common XxlJobConfig + render( + "xxlJobConfig.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/config/XxlJobConfig.java", + context, + java_version + ) + # common xxjob的测试类 + render( + "testJob.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/common/job/TestJob.java", + context, + java_version + ) + case "vue": + # 如果生成vue,则一定要有table_names + if table_names is None or len(table_names) == 0: + print("生成vue相关公共,需要生成相对应的表") + else : + render( + "CommonController.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/controller/CommonController.java", + context, + java_version, + over_write + ) + + render( + "CommonVueEnumsEntity.java.j2", + f"{BASE_DIR}{MAIN_OUTPUT_DIR}/entity/CommonVueEnumsEntity.java", + context, + java_version, + over_write + ) + + +if __name__ == "__main__": + args = parse_args() + + tables = [t.strip() for t in args.tab.split(",") if t.strip()] + models = [m.strip() for m in args.model.split(",") if m.strip()] + conf = args.conf + version = args.jdk + rew = args.rew + + generate( + table_names=tables, + model_names=models, + conf_name=conf, + java_version=version, + over_write=rew, + vue=args.vue + ) \ No newline at end of file diff --git a/utils.py b/utils.py index 1499431..6acb403 100644 --- a/utils.py +++ b/utils.py @@ -89,6 +89,12 @@ def parse_args(): help="Java版本号,默认Java 8, JAVA21直接输入21" ) + parser.add_argument( + "--vue", + default="", + help="vue对应的表名" + ) + return parser.parse_args() diff --git a/frontend_vue.py b/vue.py similarity index 73% rename from frontend_vue.py rename to vue.py index dc99123..88b785b 100644 --- a/frontend_vue.py +++ b/vue.py @@ -32,11 +32,7 @@ def build_fields(table): return fields -def generate(table): - - with open("./config.yml", "r", encoding="utf-8") as f: - cfg = yaml.safe_load(f) - cfg = resolve_config(cfg) +def generate_vue(table, cfg): API_DIR = cfg["frontend"]["root"]+"/"+cfg["frontend"]["api"] VIEW_DIR = cfg["frontend"]["root"]+"/"+cfg["frontend"]["views"] @@ -85,29 +81,8 @@ def generate(table): ctx ) - render( "mock.ts.j2", f"{MOCK_DIR}/{entity}.ts", ctx - ) - - -# ... existing code ... - -if __name__ == "__main__": - import sys - - # 从命令行参数获取表名 - if len(sys.argv) > 1: - table_name = sys.argv[1] - print(f"=== 生成前端代码1:{table_name} ===") - generate(table_name) - else: - # 如果没有提供参数,提示用户输入 - table_name = input("请输入表名 (例如 health_user): ").strip() - if table_name: - print(f"=== 生成前端代码2:{table_name} ===") - generate(table_name) - else: - print("❌ 未输入表名,退出程序") \ No newline at end of file + ) \ No newline at end of file