diff --git a/commitlint.config.cjs b/commitlint.config.cjs index 89f188eb..f30d2852 100644 --- a/commitlint.config.cjs +++ b/commitlint.config.cjs @@ -51,9 +51,10 @@ module.exports = { { value: "perf", name: "性能: 🚀 性能优化", emoji: ":zap:" }, { value: "test", name: "测试: 🧪 添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"}, { value: "build", name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"}, - { value: "ci", name: "集成: ⚙️ 修改 CI 配置、脚本", emoji: ":ferris_wheel:"}, - { value: "revert", name: "回退: ↩️ 回滚 commit",emoji: ":rewind:"}, - { value: "chore", name: "其他: 🛠️ 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"}, + { value: "ci", name: "集成: ⚙️ 修改 CI 配置、脚本", emoji: ":ferris_wheel:"}, + { value: "revert", name: "回退: ↩️ 回滚 commit",emoji: ":rewind:"}, + { value: "chore", name: "其他: 🛠️ 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"}, + { value: "wip", name: "开发中: 🚧 开发阶段临时提交", emoji: ":construction:"}, ], useEmoji: true, emojiAlign: "center", diff --git a/package.json b/package.json index 4a758394..b2445f9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue3-element-admin", - "version": "2.12.0", + "version": "2.13.0", "private": true, "type": "module", "scripts": { diff --git a/src/api/generator.ts b/src/api/generator.ts index a0d1c0b5..8620d15b 100644 --- a/src/api/generator.ts +++ b/src/api/generator.ts @@ -1,35 +1,46 @@ import request from "@/utils/request"; +import { FormTypeEnum } from "@/enums/FormTypeEnum"; +import { QueryTypeEnum } from "@/enums/QueryTypeEnum"; -const DATABASE_BASE_URL = "/api/v1/generator"; +const GENERATOR_BASE_URL = "/api/v1/generator"; -class DatabaseAPI { +class GeneratorAPI { /** 获取数据表分页列表 */ static getTablePage(params: TablePageQuery) { return request>({ - url: `${DATABASE_BASE_URL}/table/page`, + url: `${GENERATOR_BASE_URL}/table/page`, method: "get", params: params, }); } - /** 获取代码生成预览数据 */ - static getTableColumns(tableName: string) { - return request({ - url: `${DATABASE_BASE_URL}/table/${tableName}/columns`, + /** 获取代码生成配置 */ + static getGenConfig(tableName: string) { + return request({ + url: `${GENERATOR_BASE_URL}/${tableName}/config`, method: "get", }); } + /** 获取代码生成配置 */ + static saveGenConfig(tableName: string, data: GenConfigForm) { + return request({ + url: `${GENERATOR_BASE_URL}/${tableName}/config`, + method: "post", + data: data, + }); + } + /** 获取代码生成预览数据 */ static getPreviewData(tableName: string) { return request({ - url: `${DATABASE_BASE_URL}/table/${tableName}/preview`, + url: `${GENERATOR_BASE_URL}/${tableName}/preview`, method: "get", }); } } -export default DatabaseAPI; +export default GeneratorAPI; /** 代码生成预览对象 */ export interface GeneratorPreviewVO { @@ -65,49 +76,68 @@ export interface TablePageVO { createTime: string; } -/** 数据表字段VO */ -export interface TableColumnVO { - /** 字段名称 */ - columnName: string; +/** 代码生成配置表单 */ +export interface GenConfigForm { + /** 主键 */ + id?: number; + + /** 表名 */ + tableName?: string; + + /** 业务名 */ + businessName?: string; + + /** 模块名 */ + moduleName?: string; + + /** 包名 */ + packageName?: string; + + /** 实体名 */ + entityName?: string; + + /** 作者 */ + author?: string; + + /** 字段配置列表 */ + fieldConfigs?: FieldConfig[]; +} + +/** 字段配置 */ +interface FieldConfig { + /** 主键 */ + id?: number; + + /** 列名 */ + columnName?: string; + + /** 列类型 */ + columnType?: string; + + /** 字段名 */ + fieldName?: string; /** 字段类型 */ - dataType: string; + fieldType?: string; /** 字段描述 */ - columnComment: string; + fieldComment?: string; - /** 字段长度 */ - characterMaximumLength: number; + /** 是否在列表显示 */ + isShowInList?: number; - /** 是否主键(1-是 0-否) */ - isPrimaryKey: number; + /** 是否在表单显示 */ + isShowInForm?: number; - /** 是否可为空(1-是 0-否) */ - isNullable: string; + /** 是否在查询条件显示 */ + isShowInQuery?: number; - /** 字符集 */ - characterSetName: string; + /** 是否必填 */ + isRequired?: number; - /** 字符集排序规则 */ - collationName: string; -} - -interface GeneratorConfigForm { - tableName: string; - entityName: string; - packageName: string; - moduleName: string; - author: string; - fieldConfigs: FieldConfig[]; -} - -interface FieldConfig { - name: string; - type: string; - description: string; - showInList: boolean; - showInForm: boolean; - showInQuery: boolean; - formType: string; - queryMethod: string; + /** 表单类型 */ + formType?: number; + + /** 查询类型 */ + queryType?: number; } diff --git a/src/enums/FormTypeEnum.ts b/src/enums/FormTypeEnum.ts new file mode 100644 index 00000000..32cb9608 --- /dev/null +++ b/src/enums/FormTypeEnum.ts @@ -0,0 +1,14 @@ +/** + * 表单类型枚举 + */ +export const FormTypeEnum: Record = { + INPUT: { value: 1, label: "输入框" }, + SELECT: { value: 2, label: "下拉框" }, + RADIO: { value: 3, label: "单选框" }, + CHECK_BOX: { value: 4, label: "复选框" }, + INPUT_NUMBER: { value: 5, label: "数字输入框" }, + SWITCH: { value: 6, label: "开关" }, + TEXT_AREA: { value: 7, label: "文本域" }, + DATE_TIME: { value: 8, label: "日期时间框" }, + DATE: { value: 9, label: "日期框" }, +}; diff --git a/src/enums/MenuTypeEnum.ts b/src/enums/MenuTypeEnum.ts index b69942fd..b4571f4f 100644 --- a/src/enums/MenuTypeEnum.ts +++ b/src/enums/MenuTypeEnum.ts @@ -5,18 +5,18 @@ export const enum MenuTypeEnum { /** * 目录 */ - CATALOG = "CATALOG", + CATALOG, /** * 菜单 */ - MENU = "MENU", + MENU, /** * 按钮 */ - BUTTON = "BUTTON", + BUTTON, /** * 外链 */ - EXTLINK = "EXTLINK", + EXTLINK, } diff --git a/src/enums/QueryTypeEnum.ts b/src/enums/QueryTypeEnum.ts new file mode 100644 index 00000000..253efc0d --- /dev/null +++ b/src/enums/QueryTypeEnum.ts @@ -0,0 +1,37 @@ +/** + * 查询类型枚举 + */ +export const QueryTypeEnum: Record = { + /** 等于 */ + EQ: { value: 1, label: "=" }, + + /** 模糊匹配 */ + LIKE: { value: 2, label: "LIKE '%s%'" }, + + /** 包含 */ + IN: { value: 3, label: "IN" }, + + /** 范围 */ + BETWEEN: { value: 4, label: "BETWEEN" }, + + /** 大于 */ + GT: { value: 5, label: ">" }, + + /** 大于等于 */ + GE: { value: 6, label: ">=" }, + + /** 小于 */ + LT: { value: 7, label: "<" }, + + /** 小于等于 */ + LE: { value: 8, label: "<=" }, + + /** 不等于 */ + NE: { value: 9, label: "!=" }, + + /** 左模糊匹配 */ + LIKE_LEFT: { value: 10, label: "LIKE '%s'" }, + + /** 右模糊匹配 */ + LIKE_RIGHT: { value: 11, label: "LIKE 's%'" }, +}; diff --git a/src/views/generator/index.vue b/src/views/generator/index.vue index 4611c6d2..ae0ad75b 100644 --- a/src/views/generator/index.vue +++ b/src/views/generator/index.vue @@ -51,7 +51,7 @@ type="primary" size="small" link - @click="handleOpenDialog('config', scope.row.tableName)" + @click="handleOpenDialog(scope.row.tableName)" > 生成 @@ -75,10 +75,187 @@ @close="handleCloseDialog" size="80%" > -
- + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - +
- 复制 + 一键复制
@@ -114,140 +291,17 @@
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -263,23 +317,19 @@ import Codemirror from "codemirror-editor-vue3"; import type { CmComponentRef } from "codemirror-editor-vue3"; import type { Editor, EditorConfiguration } from "codemirror"; const { copy, copied } = useClipboard(); - -const code = ref(); -const cmRef = ref(); -const cmOptions: EditorConfiguration = { - mode: "text/javascript", -}; +import { FormTypeEnum } from "@/enums/FormTypeEnum"; +import { QueryTypeEnum } from "@/enums/QueryTypeEnum"; import GeneratorAPI, { TablePageVO, - TableColumnVO, + GenConfigForm, TablePageQuery, - GeneratorPreviewVO, } from "@/api/generator"; const queryFormRef = ref(ElForm); const loading = ref(false); +const loadingText = ref("loading..."); const total = ref(0); const queryParams = reactive({ @@ -289,14 +339,68 @@ const queryParams = reactive({ const pageData = ref([]); -const tableColumns = ref([]); +const formData = ref({}); + +const formTypeOptions: Record = FormTypeEnum; +const queryTypeOptions: Record = QueryTypeEnum; const dialog = reactive({ - type: "", visible: false, title: "", }); +const code = ref(); +const cmRef = ref(); +const cmOptions: EditorConfiguration = { + mode: "text/javascript", +}; + +const prevBtnText = ref(""); +const nextBtnText = ref("下一步,字段配置"); +const active = ref(1); + +function handlePrevClick() { + if (active.value-- <= 1) active.value = 1; +} + +function handleNextClick() { + if (active.value === 2) { + // 保存生成配置 + const tableName = formData.value.tableName; + if (!tableName) { + ElMessage.error("表名不能为空"); + return; + } + loading.value = true; + loadingText.value = "代码生成中,请稍后..."; + GeneratorAPI.saveGenConfig(tableName, formData.value) + .then(() => { + handlePreview(tableName); + }) + .then(() => { + if (active.value++ >= 3) active.value = 3; + }) + .finally(() => { + loading.value = false; + loadingText.value = "loading..."; + }); + } else { + if (active.value++ >= 3) active.value = 3; + } +} + +watch(active, (val) => { + if (val === 1) { + nextBtnText.value = "下一步,字段配置"; + } else if (val === 2) { + prevBtnText.value = "上一步,基础配置"; + nextBtnText.value = "下一步,确认生成"; + } else if (val === 3) { + prevBtnText.value = "上一步,字段配置"; + nextBtnText.value = "下载代码"; + } +}); + /** 查询 */ function handleQuery() { loading.value = true; @@ -329,34 +433,41 @@ interface TreeNode { const treeData = ref([]); /** 打开弹窗 */ -function handleOpenDialog(type: string, tableName: string) { +function handleOpenDialog(tableName: string) { dialog.visible = true; - dialog.type = type; - if (type === "config") { - GeneratorAPI.getTableColumns(tableName).then((data) => { - dialog.title = `配置 ${tableName}`; - tableColumns.value = data; - }); - } else if (type === "preview") { - treeData.value = []; - GeneratorAPI.getPreviewData(tableName).then((data) => { - dialog.title = `预览 ${tableName}`; + GeneratorAPI.getGenConfig(tableName).then((data) => { + dialog.title = `${tableName} 代码生成`; + formData.value = data; + if (formData.value.id) { + active.value = 3; + handlePreview(tableName); + } else { + active.value = 1; + } + }); +} - // 组装树形结构完善代码 - const tree = buildTree(data); - treeData.value = [tree]; +/** 获取生成预览 */ +function handlePreview(tableName: string) { + treeData.value = []; + GeneratorAPI.getPreviewData(tableName).then((data) => { + dialog.title = `预览 ${tableName}`; - // 默认选中第一个叶子节点并设置 code 值 - const firstLeafNode = findFirstLeafNode(tree); - if (firstLeafNode) { - code.value = firstLeafNode.content || ""; - } - }); - } + // 组装树形结构完善代码 + const tree = buildTree(data); + treeData.value = [tree]; + + // 默认选中第一个叶子节点并设置 code 值 + const firstLeafNode = findFirstLeafNode(tree); + if (firstLeafNode) { + code.value = firstLeafNode.content || ""; + } + }); } /** * 递归构建树形结构 + * * @param data - 数据数组 * @returns 树形结构根节点 */ @@ -372,24 +483,22 @@ function buildTree( const parts = item.path.split(separator); // 定义特殊路径 + // TODO: 如果菜单有多个节点,需要将此菜单作为独立一级的节点,而不是合并到上一级。 按照此规则, com.youlai.system 则是三个节点,而不是合并到一起,但是这里需要将 com.youlai.system 合并到一起,所以需要特殊处理 const specialPaths = [ + "com\\youlai\\system", "src\\main", + "java", "youlai-boot", "vue3-element-admin", - "java", - "com\\youlai\\system", ]; // 检查路径中的特殊部分并合并它们 const mergedParts: string[] = []; let buffer: string[] = []; - console.log("parts", parts); - parts.forEach((part) => { buffer.push(part); const currentPath = buffer.join(separator); - console.log("currentPath", currentPath); if (specialPaths.includes(currentPath)) { mergedParts.push(currentPath); buffer = []; @@ -483,8 +592,6 @@ watch(copied, () => { } }); -function handleSubmit() {} - onMounted(() => { handleQuery(); cmRef.value?.destroy();