refactor(module): 重构模块路径和数据库配置

- 将前端API路径从`system`和`monitor`重命名为`module_system`和`module_monitor`
- 移除MongoDB相关配置和依赖
- 统一数据库类型命名为`mysql`和`postgres`
- 修复代码生成模板中的字段命名问题
- 更新依赖项并移除不必要的包
- 优化数据库连接配置
- 添加新的文档和Redoc视图组件
- 修复SQL脚本中的字段注释
This commit is contained in:
zhangtao
2025-11-10 01:43:23 +08:00
parent bbde7b8c6e
commit 3df4f5a45a
89 changed files with 964 additions and 1531 deletions
+1 -1
View File
@@ -215,7 +215,7 @@
<script lang="ts" setup>
import type { FormInstance, UploadRequestOptions, UploadFile, ElUpload, ComponentSize } from 'element-plus'
import UserAPI, { type InfoFormState, type PasswordFormState } from '@/api/system/user';
import UserAPI, { type InfoFormState, type PasswordFormState } from '@/api/module_system/user';
import { useUserStore, useDictStore } from "@/store";
import { useUserStoreHook } from "@/store/modules/user.store";
import { Camera } from '@element-plus/icons-vue';
+1 -1
View File
@@ -186,7 +186,7 @@ defineOptions({
import { EChartsOption } from 'echarts'
import { useUserStore } from "@/store/index";
import { greetings } from '@/utils/common';
import NoticeAPI, { NoticeTable } from '@/api/system/notice';
import NoticeAPI, { NoticeTable } from '@/api/module_system/notice';
import { ref, onMounted, reactive } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@@ -172,7 +172,7 @@ const props = defineProps({
}
})
import JobAPI, { JobLogPageQuery, JobLogTable } from "@/api/application/job";
import JobAPI, { JobLogPageQuery, JobLogTable } from "@/api/module_application/job";
import { useAppStore } from "@/store/modules/app.store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import ExportModal from "@/components/CURD/ExportModal.vue";
@@ -594,9 +594,6 @@
:selection-data="selectionRows"
/>
</div>
</template>
<script lang="ts" setup>
@@ -605,12 +602,12 @@ defineOptions({
inheritAttrs: false,
});
import JobAPI, { JobTable, JobForm, JobPageQuery } from "@/api/application/job";
import JobAPI, { JobTable, JobForm, JobPageQuery } from "@/api/module_application/job";
import IntervalTab from "@/components/IntervalTab/index.vue";
import { useDictStore } from "@/store/index";
import { vue3CronPlus } from "vue3-cron-plus";
import "vue3-cron-plus/dist/index.css"; // 引入样式
import JobLogDrawer from "@/views/application/job/components/JobLogDrawer.vue"
import JobLogDrawer from "@/views/module_application/job/components/JobLogDrawer.vue"
import OperationColumn from "@/components/OperationColumn/index.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
@@ -232,7 +232,7 @@ import { useTagsViewStore } from "@/store";
import { useRouter } from "vue-router";
import { DeviceEnum } from "@/enums/settings/device.enum";
import { Monitor, User, Clock } from '@element-plus/icons-vue';
import ApplicationAPI, { type ApplicationForm, type ApplicationInfo, type ApplicationPageQuery } from "@/api/application/myapp";
import ApplicationAPI, { type ApplicationForm, type ApplicationInfo, type ApplicationPageQuery } from "@/api/module_application/myapp";
import { formatToDateTime } from "@/utils/dateUtil";
const appStore = useAppStore();
@@ -203,7 +203,7 @@ defineOptions({
});
import { ref, reactive, onMounted } from "vue";
import ExampleAPI, { ExampleTable, ExampleForm, ExamplePageQuery } from "@/api/generator/demo";
import ExampleAPI, { ExampleTable, ExampleForm, ExamplePageQuery } from "@/api/module_generator/demo";
import DatePicker from "@/components/DatePicker/index.vue";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -43,7 +43,7 @@
<el-button v-hasPerm="['generator:gencode:delete']" type="danger" plain icon="Delete" :disabled="ids.length === 0" @click="handleDelete()">批量删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPerm="['generator:gencode:code']" type="warning" plain icon="Download" :disabled="!canGenerate" @click="handleGenTable()">批量生成</el-button>
<el-button v-hasPerm="['generator:gencode:code']" type="warning" plain icon="Download" :disabled="!canGenerate" @click="handleGenTable('0')">批量生成</el-button>
</el-col>
</el-row>
</div>
@@ -116,13 +116,33 @@
</el-card>
<!-- 创建表 -->
<el-dialog v-model="createTableVisible" title="创建表" append-to-body>
<el-dialog v-model="createTableVisible" title="创建表" append-to-body >
<span>创建表语句(支持多个建表sql语句):</span>
<el-input v-model="createContent" type="textarea" :rows="10" placeholder="请输入创建表sql语句" clearable :rules="[{ required: true, message: '请输入创建表sql语句', trigger: 'blur' }]"></el-input>
<el-button type="warning" size="small" class="ml-1 mb-1" @click="loadExampleMysql">加载MySQL示例</el-button>
<el-button type="primary" size="small" class="ml-1 mb-1" @click="loadExamplePostgres">加载Postgres示例</el-button>
<el-scrollbar max-height="72vh">
<div class="absolute z-36 right-5 top-2">
<el-link type="primary" @click="handleCopyCode">
<el-icon>
<CopyDocument />
</el-icon>
复制代码
</el-link>
</div>
<Codemirror
ref="sqlRef"
v-model:value="createContent"
:options="sqlOptions"
border
:height="'300px'"
width="100%"
/>
</el-scrollbar>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="loading" @click="handleCreateTable(createContent)">确 定</el-button>
<el-button @click="createTableVisible = false">取 消</el-button>
<el-button @click="handleCreateTableCancel()">取 消</el-button>
</div>
</template>
</el-dialog>
@@ -154,12 +174,12 @@
</el-form-item>
</el-form>
<el-row>
<el-table ref="table" :data="dbTableList" height="300px" @row-click="clickRow" @selection-change="handleImportTableSelectionChange">
<el-table ref="table" :data="dbTableList" height="300px" border @row-click="clickRow" @selection-change="handleImportTableSelectionChange">
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="序号" type="index" min-width="55" align="center" fixed>
<el-table-column label="序号" type="index" min-width="30" align="center" fixed>
<template #default="scope">
<span>{{(importQueryFormData.page_no - 1) * importQueryFormData.page_size + scope.$index + 1}}</span>
</template>
@@ -185,12 +205,11 @@
</el-dialog>
<!-- 代码生成抽屉 -->
<el-drawer v-model="editVisible" :title="'【代码生成】' + info.table_name" size="80%" @close="handleClose">
<el-drawer v-model="editVisible" :title="'【代码生成】' + info.table_name" size="85%" @close="handleClose">
<el-steps :active="activeStep" finish-status="success" simple>
<el-step title="基础配置" />
<el-step title="字段配置" />
<el-step title="预览代码" />
<el-step title="代码生成" />
</el-steps>
<div class="mt-5">
@@ -212,6 +231,68 @@
<el-input v-model="info.class_name" placeholder="请输入"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="package_name">
<template #label>
包名
<el-tooltip content="生成在哪个python模块下,例如 module_gencode" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.package_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="module_name">
<template #label>
模块名
<el-tooltip content="可理解为子系统名,例如 system" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.module_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="business_name">
<template #label>
业务名
<el-tooltip content="可理解为功能英文名,例如 user" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.business_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="function_name">
<template #label>
功能名
<el-tooltip content="用作类描述,例如 用户" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.function_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
上级菜单
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-tree-select
v-model="info.parent_menu_id"
:data="menuOptions"
placeholder="请选择系统菜单"
check-strictly
filterable
:render-after-expand="false"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="description">
<el-input v-model="info.description" type="textarea" :rows="3"></el-input>
@@ -266,7 +347,7 @@
<el-table
ref="dragTable"
v-loading="loading"
:data="columns"
:data="info.columns"
row-key="id"
max-height="680"
highlight--currentrow
@@ -277,7 +358,7 @@
<template #empty>
<el-empty :image-size="80" description="暂无数据" />
</template>
<el-table-column label="序号" type="index" min-width="5%" fixed />
<el-table-column label="序号" type="index" min-width="7%" fixed />
<el-table-column label="列名" prop="column_name" min-width="10%" :show-overflow-tooltip="true"/>
<el-table-column label="类型" prop="column_type" min-width="10%" :show-overflow-tooltip="true"/>
<el-table-column label="长度" prop="column_length" min-width="8%" :show-overflow-tooltip="true">
@@ -355,9 +436,9 @@
<el-checkbox v-model="scope.row.is_increment" true-value="1" false-value="0" />
</template>
</el-table-column>
<el-table-column label="必填" min-width="10%">
<el-table-column label="允许空" min-width="10%">
<template #default="scope">
<el-checkbox v-model="scope.row.is_required" true-value="1" false-value="0"></el-checkbox>
<el-checkbox v-model="scope.row.is_nullable" true-value="0" false-value="1"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="唯一" min-width="10%">
@@ -365,6 +446,11 @@
<el-checkbox v-model="scope.row.is_unique" true-value="1" false-value="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="主键" min-width="10%">
<template #default="scope">
<el-checkbox v-model="scope.row.is_pk" true-value="1" false-value="0"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="表单类型" min-width="12%">
<template #default="scope">
<el-select v-model="scope.row.html_type">
@@ -454,120 +540,16 @@
</el-scrollbar>
</el-col>
</el-row>
<!-- 第四步:代码生成 -->
<el-form v-show="activeStep == 3" ref="genInfo" :model="info" :rules="rules" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item prop="package_name">
<template #label>
生成包路径
<el-tooltip content="生成在哪个python模块下,例如 module_gencode" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.package_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="module_name">
<template #label>
生成模块名
<el-tooltip content="可理解为子系统名,例如 system" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.module_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="business_name">
<template #label>
生成业务名
<el-tooltip content="可理解为功能英文名,例如 user" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.business_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="function_name">
<template #label>
生成功能名
<el-tooltip content="用作类描述,例如 用户" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-input v-model="info.function_name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="gen_type">
<template #label>
生成代码方式
<el-tooltip content="默认为zip压缩包下载,也可以自定义生成路径" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-radio v-model="info.gen_type" value="0">zip压缩包</el-radio>
<el-radio v-model="info.gen_type" value="1">项目目录</el-radio>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
上级菜单
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
<el-icon><QuestionFilled/></el-icon>
</el-tooltip>
</template>
<el-tree-select
v-model="info.parent_menu_id"
:data="menuOptions"
placeholder="请选择系统菜单"
check-strictly
filterable
:render-after-expand="false"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<template #footer>
<!-- 公共按钮:关闭 -->
<el-button :icon="Close" @click="close">关闭</el-button>
<!-- 第一步:只有“下一步” -->
<el-button v-if="activeStep === 0" type="primary" @click="nextStep">
下一步,字段配置<el-icon class="el-icon--right"><Right /></el-icon>
</el-button>
<!-- 第二步:有“上一步”和“下一步” -->
<el-button v-if="activeStep === 1" type="success" :icon="Back" @click="prevStep">上一步,基础配置</el-button>
<el-button v-if="activeStep === 1" v-hasPerm="['generator:gencode:update']" type="warning" :icon="Edit" @click="submitForm">保存字段配置</el-button>
<el-button v-if="activeStep === 1" type="primary" @click="nextStep">
下一步,预览代码<el-icon class="el-icon--right"><View /></el-icon>
</el-button>
<!-- 第三步:有“上一步”和“下载代码” -->
<el-button v-if="activeStep === 2" type="success" :icon="Back" @click="prevStep">上一步,字段配置</el-button>
<el-button v-if="activeStep === 2" type="primary" @click="nextStep">
下一步,生成代码<el-icon class="el-icon--right"><Right /></el-icon>
</el-button>
<!-- 第四步:有“上一步”和“写入本地” -->
<el-button v-if="activeStep === 3" type="success" :icon="View" @click="prevStep">上一步,预览代码</el-button>
<el-button v-if="activeStep === 3" :disabled="info.gen_type != '0'" type="warning" :icon="Download" :loading="loading" @click="handleGenTable(info)">下载代码</el-button>
<el-button v-if="activeStep === 3" :disabled="info.gen_type != '1'" type="primary" :icon="FolderOpened" :loading="loading" @click="handleGenTable(info)">写入本地</el-button>
<el-button v-if="activeStep != 0" type="success" :icon="Back" @click="prevStep">上一步</el-button>
<el-button v-if="activeStep != 2" v-hasPerm="['generator:gencode:update']" type="warning" :icon="Edit" :loading="loading" @click="submitForm">保存配置</el-button>
<el-button v-if="activeStep != 2" type="primary" @click="nextStep">下一步<el-icon class="el-icon--right"><Right /></el-icon></el-button>
<el-button v-if="activeStep === 2" type="warning" :icon="Download" :loading="loading" @click="handleGenTable('0', info)">下载代码</el-button>
<el-button v-if="activeStep === 2" type="primary" :icon="FolderOpened" :loading="loading" @click="handleGenTable('1', info)">写入本地</el-button>
</template>
</el-drawer>
</div>
@@ -580,6 +562,7 @@ defineOptions({
});
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/sql/sql.js";
import { ref, reactive, computed, onActivated, onMounted } from 'vue';
import { useClipboard } from '@vueuse/core';
import { useRoute } from 'vue-router';
@@ -587,10 +570,10 @@ import Codemirror from "codemirror-editor-vue3";
import type { EditorConfiguration } from "codemirror";
import type { CmComponentRef } from "codemirror-editor-vue3";
import { ElMessage, ElMessageBox, type FormInstance, type TableInstance } from 'element-plus';
import { QuestionFilled, MagicStick, View, CopyDocument, Close, Right, FolderOpened, Back, Download, Edit } from '@element-plus/icons-vue';
import GencodeAPI, { type GenTableOutVO, type DatabaseTable, type GenTableQueryParam, type GenTableColumnOutSchema, type GenTableSchema } from "@/api/generator/gencode";
import MenuAPI, { MenuTable } from "@/api/system/menu";
import DictAPI, { DictTable } from "@/api/system/dict";
import { QuestionFilled, MagicStick, CopyDocument, Close, Right, FolderOpened, Back, Download, Edit } from '@element-plus/icons-vue';
import GencodeAPI, { type GenTableSchema, type DBTableSchema, type GenTablePageQuery } from "@/api/module_generator/gencode";
import MenuAPI, { MenuTable } from "@/api/module_system/menu";
import DictAPI, { DictTable } from "@/api/module_system/dict";
import { formatTree } from "@/utils/common";
import { MenuTypeEnum } from "@/enums";
@@ -621,8 +604,8 @@ interface FileData {
const queryRef = ref<FormInstance>();
const table = ref<TableInstance>();
const cmRef = ref<CmComponentRef>();
const sqlRef = ref<CmComponentRef>();
const basicInfo = ref<FormInstance>();
const genInfo = ref<FormInstance>();
const dragTable = ref<TableInstance>();
// 状态管理
@@ -639,15 +622,15 @@ const importVisible = ref(false);
// 表单和列表数据
const createContent = ref("");
const dateRange = ref<[Date, Date] | []>([]);
const tableList = ref<GenTableOutVO[]>([]);
const dbTableList = ref<DatabaseTable[]>([]);
const tableList = ref<GenTableSchema[]>([]);
const dbTableList = ref<DBTableSchema[]>([]);
const ids = ref<number[]>([]);
const tableNames = ref<string[]>([]);
// 导入弹窗专用状态
const importLoading = ref(false);
const importTotal = ref<number>(0);
const importQueryFormData = reactive<GenTableQueryParam>({
const importQueryFormData = reactive<GenTablePageQuery>({
page_no: 1,
page_size: 10,
table_name: undefined,
@@ -664,7 +647,6 @@ type TableItem = {
table_comment: string;
};
const tables = ref<TableItem[]>([]);
const columns = ref<GenTableColumnOutSchema[]>([]);
// 导入按钮点击事件
async function handleImportClick() {
@@ -687,13 +669,11 @@ const code = ref<string>('');
const treeData = ref<TreeNode[]>([]);
// 分页查询参数
const queryFormData = reactive<GenTableQueryParam>({
const queryFormData = reactive<GenTablePageQuery>({
page_no: 1,
page_size: 10,
table_name: undefined,
table_comment: undefined,
start_time: undefined,
end_time: undefined,
});
// 表格列配置
@@ -718,6 +698,17 @@ const cmOptions: EditorConfiguration = {
readOnly: true
};
const sqlOptions: EditorConfiguration = {
mode: "text/x-sql",
lineNumbers: true,
smartIndent: true,
indentUnit: 2,
tabSize: 2,
readOnly: false,
theme: "default",
lineWrapping: true,
};
// 工具函数
const { copy } = useClipboard();
@@ -831,7 +822,7 @@ function buildTree(data: FileData[]): TreeNode {
}
/** 获取生成预览 */
async function handlePreview(row: GenTableOutVO): Promise<void> {
async function handlePreview(row: GenTableSchema): Promise<void> {
try {
if (!row.id) {
ElMessage.warning('无效的表ID');
@@ -906,14 +897,12 @@ async function loadingData(): Promise<void> {
}
/** 表格行内生成代码操作 */
async function handleGenTable(row?: GenTableOutVO): Promise<void> {
async function handleGenTable(targetGenType: string, row?: GenTableSchema): Promise<void> {
let tbNames: string | string[] = [];
let targetGenType = '0';
// 判断是单条还是批量操作
if (row) {
tbNames = [row.table_name || ''];
targetGenType = row.gen_type || '0';
} else if (tableNames.value.length > 0) {
tbNames = tableNames.value;
} else {
@@ -954,7 +943,7 @@ async function handleGenTable(row?: GenTableOutVO): Promise<void> {
}
/** 同步数据库操作 */
async function handleSynchDb(row: GenTableOutVO): Promise<void> {
async function handleSynchDb(row: GenTableSchema): Promise<void> {
const tableName = row.table_name || '';
if (!tableName) {
@@ -997,27 +986,19 @@ async function handleRefresh() {
}
/** 多选框选中数据 - 主表格 */
function handleTableSelectionChange(selection: GenTableOutVO[]): void {
function handleTableSelectionChange(selection: GenTableSchema[]): void {
ids.value = selection.map((item) => item.id!);
tableNames.value = selection.map((item) => item.table_name || '').filter(Boolean);
}
/** 多选框选中数据 - 导入表格 */
function handleImportTableSelectionChange(selection: DatabaseTable[]): void {
function handleImportTableSelectionChange(selection: DBTableSchema[]): void {
tables.value = selection.map(item => ({
table_name: item.table_name || '',
table_comment: item.table_comment || ''
}));
}
/** 表格行内修改按钮操作 */
/** 计算表格高度 */
function calculateTableHeight() {
// 为了确保表格有足够的高度显示,我们设置一个固定的合理值
// 这里使用400px作为表格高度,这是一个适合大多数屏幕的高度
}
// 修改菜单选项过滤逻辑,添加递归过滤函数
const filterMenuTypes = (nodes: MenuTable[]) => {
return nodes
@@ -1029,7 +1010,7 @@ const filterMenuTypes = (nodes: MenuTable[]) => {
};
/** 表格行内修改按钮操作 */
async function handlePreviewTable(row?: GenTableOutVO): Promise<void> {
async function handlePreviewTable(row?: GenTableSchema): Promise<void> {
const selectedTableId = row?.id || ids.value[0];
if (selectedTableId) {
// 设置编辑的表ID和名称
@@ -1043,17 +1024,13 @@ async function handlePreviewTable(row?: GenTableOutVO): Promise<void> {
const dict_response = await DictAPI.getDictTypeList({page_no: 1, page_size: 100});
dictOptions.value = dict_response.data.data.items;
// 延迟计算表格高度,确保DOM已经渲染完成
setTimeout(() => {
calculateTableHeight();
}, 100);
} else {
ElMessage.error('请选择要修改的数据');
}
}
/** 删除按钮操作 */
async function handleDelete(row?: GenTableOutVO): Promise<void> {
async function handleDelete(row?: GenTableSchema): Promise<void> {
const tableIds = row?.id ? [row.id] : ids.value;
if (tableIds.length === 0) {
@@ -1084,6 +1061,50 @@ async function handleDelete(row?: GenTableOutVO): Promise<void> {
}
}
/** 加载SQL示例 */
function loadExampleMysql(): void {
const exampleSql = `-- MySQL SQL案例
CREATE TABLE \`gen_demo01\` (
\`name\` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '名称',
\`status\` tinyint(1) NOT NULL COMMENT '是否启用(True:启用 False:禁用)',
\`creator_id\` int DEFAULT NULL COMMENT '创建人ID',
\`id\` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
\`description\` text COLLATE utf8mb4_unicode_ci COMMENT '备注/描述',
\`created_at\` datetime DEFAULT NULL COMMENT '创建时间',
\`updated_at\` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (\`id\`),
KEY \`ix_gen_demo01_creator_id\` (\`creator_id\`),
CONSTRAINT \`gen_demo01_ibfk_1\` FOREIGN KEY (\`creator_id\`) REFERENCES \`system_users\` (\`id\`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='示例表';`;
createContent.value = exampleSql;
}
function loadExamplePostgres(): void {
const exampleSql = `-- Psstgres SQL案例
CREATE TABLE gen_demo01(
name varchar(64),
status boolean NOT NULL,
creator_id integer,
id SERIAL NOT NULL,
description text,
created_at timestamp without time zone,
updated_at timestamp without time zone,
PRIMARY KEY(id),
CONSTRAINT gen_demo01_creator_id_fkey FOREIGN key(creator_id) REFERENCES system_users(id)
);
CREATE INDEX ix_gen_demo01_creator_id ON public.gen_demo01 USING btree (creator_id);
COMMENT ON TABLE gen_demo01 IS '示例表';
COMMENT ON COLUMN gen_demo01.name IS '名称';
COMMENT ON COLUMN gen_demo01.status IS '是否启用(True:启用 False:禁用)';
COMMENT ON COLUMN gen_demo01.creator_id IS '创建人ID';
COMMENT ON COLUMN gen_demo01.id IS '主键ID';
COMMENT ON COLUMN gen_demo01.description IS '备注/描述';
COMMENT ON COLUMN gen_demo01.created_at IS '创建时间';
COMMENT ON COLUMN gen_demo01.updated_at IS '更新时间';`;
createContent.value = exampleSql;
}
/** 创建表操作 */
async function handleCreateTable(sql: string): Promise<void> {
if (!sql || sql.trim() === '') {
@@ -1104,6 +1125,14 @@ async function handleCreateTable(sql: string): Promise<void> {
}
}
/** 取消创建表操作 */
function handleCreateTableCancel(): void {
createTableVisible.value = false;
createContent.value = '';
}
/** 导入表操作 */
async function handleImportTable(): Promise<void> {
if (tables.value.length === 0) {
@@ -1126,7 +1155,7 @@ async function handleImportTable(): Promise<void> {
}
/** 单击选择行 */
function clickRow(row: DatabaseTable): void {
function clickRow(row: DBTableSchema): void {
table.value?.toggleRowSelection(row);
}
@@ -1195,11 +1224,8 @@ const info = reactive<GenTableSchema>({
module_name: '',
business_name: '',
function_name: '',
gen_type: '0',
options: {parent_menu_id: undefined,},
description: '',
parent_menu_id: undefined,
parent_menu_name: '',
pk_column: undefined,
sub_table: undefined,
columns: [],
@@ -1263,7 +1289,7 @@ async function nextStep(): Promise<void> {
// 当从字段配置进入预览步骤时,自动加载预览数据
if (activeStep.value === 2 && info.id) {
await handlePreview({ id: info.id, table_name: info.table_name } as GenTableOutVO);
await handlePreview({ id: info.id, table_name: info.table_name } as GenTableSchema);
}
}
}
@@ -1297,7 +1323,6 @@ function close(): void {
// 清除表单验证状态
setTimeout(() => {
basicInfo.value?.resetFields();
genInfo.value?.resetFields();
}, 300);
}
@@ -1316,21 +1341,17 @@ async function loadTableDetail(id: number | string) {
const data = response.data.data;
// 填充表单数据
Object.assign(info, { ...data.info });
Object.assign(info, { ...data });
// 处理列数据
if (data.rows) {
// 深拷贝确保数据独立性
info.columns = JSON.parse(JSON.stringify(data.rows));
// 设置列的选中状态
if (info.columns) {
info.columns.forEach((item: any) => {
item.select = true;
});
// 创建新数组避免引用问题
columns.value = [...info.columns];
}
}
if (data && data.columns && Array.isArray(data.columns)) {
// 深拷贝确保数据独立性
info.columns = JSON.parse(JSON.stringify(data.columns));
// 设置列的选中状态
info.columns.forEach((item: any) => {
item.select = true;
});
}
// 重置当前步骤为第一步
activeStep.value = 0;
@@ -266,7 +266,7 @@ defineOptions({
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { ResultEnum } from "@/enums/api/result.enum";
import ExampleAPI, { ExampleTable, ExampleForm, ExamplePageQuery } from "@/api/generator/demo";
import ExampleAPI, { ExampleTable, ExampleForm, ExamplePageQuery } from "@/api/module_generator/demo";
import ImportModal from "@/components/CURD/ImportModal.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import DatePicker from "@/components/DatePicker/index.vue";
@@ -235,7 +235,7 @@
</template>
<script lang="ts" setup>
import CacheAPI, { type CacheInfo, type CacheForm, type CacheMonitor, type RedisInfo } from "@/api/monitor/cache";
import CacheAPI, { type CacheInfo, type CacheForm, type CacheMonitor, type RedisInfo } from "@/api/module_monitor/cache";
import * as echarts from 'echarts';
// 响应式状态定义
@@ -111,7 +111,7 @@ defineOptions({
inheritAttrs: false,
});
import OnlineAPI, { type OnlineUserPageQuery, type OnlineUserTable } from "@/api/monitor/online";
import OnlineAPI, { type OnlineUserPageQuery, type OnlineUserTable } from "@/api/module_monitor/online";
const queryFormRef = ref();
const total = ref(0);
@@ -287,7 +287,7 @@ import {
UploadFilled,
QuestionFilled
} from '@element-plus/icons-vue'
import { ResourceAPI, type ResourceItem, type ResourcePageQuery } from '@/api/monitor/resource'
import { ResourceAPI, type ResourceItem, type ResourcePageQuery } from '@/api/module_monitor/resource'
// 分页表单
const fileList = ref<ResourceItem[]>([])
@@ -231,7 +231,7 @@
</template>
<script lang="ts" setup>
import ServerAPI, {type ServerInfo } from '@/api/monitor/server'
import ServerAPI, {type ServerInfo } from '@/api/module_monitor/server'
const loading = ref(false);
@@ -104,7 +104,7 @@ import type { FormInstance } from "element-plus";
import { LocationQuery, RouteLocationRaw, useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { onActivated, onMounted, watch } from "vue";
import AuthAPI, {type LoginFormData, type CaptchaInfo } from "@/api/system/auth";
import AuthAPI, {type LoginFormData, type CaptchaInfo } from "@/api/module_system/auth";
import { useAppStore, useUserStore, useSettingsStore } from "@/store";
import CommonWrapper from "@/components/CommonWrapper/index.vue";
@@ -73,7 +73,7 @@
<script setup lang="ts">
import type { FormInstance } from "element-plus";
import { Lock } from "@element-plus/icons-vue";
import UserAPI, { type RegisterForm } from "@/api/system/user";
import UserAPI, { type RegisterForm } from "@/api/module_system/user";
import { useConfigStore } from "@/store";
import { useI18n } from "vue-i18n";
@@ -66,7 +66,7 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import type { FormInstance } from "element-plus";
import UserAPI, { type ForgetPasswordForm } from "@/api/system/user";
import UserAPI, { type ForgetPasswordForm } from "@/api/module_system/user";
const loading = ref(false); // 按钮 loading 状态
const isCapsLock = ref(false); // 是否大写锁定
@@ -199,7 +199,7 @@ defineOptions({
inheritAttrs: false,
});
import DeptAPI, { DeptTable, DeptForm, DeptPageQuery } from "@/api/system/dept";
import DeptAPI, { DeptTable, DeptForm, DeptPageQuery } from "@/api/module_system/dept";
import { useUserStore } from "@/store";
import { formatTree } from "@/utils/common";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -276,10 +276,10 @@ const props = defineProps({
})
const drawerVisible = defineModel<boolean>()
import DictAPI, { DictDataTable, DictDataForm, DictDataPageQuery } from "@/api/system/dict";
import DictAPI, { DictDataTable, DictDataForm, DictDataPageQuery } from "@/api/module_system/dict";
import { useAppStore } from "@/store/modules/app.store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -234,9 +234,9 @@ defineOptions({
inheritAttrs: false,
});
import DictAPI, { DictTable, DictForm, DictPageQuery } from "@/api/system/dict";
import DataDrawer from "@/views/system/dict/components/DataDrawer.vue"
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import DictAPI, { DictTable, DictForm, DictPageQuery } from "@/api/module_system/dict";
import DataDrawer from "@/views/module_system/dict/components/DataDrawer.vue"
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -216,8 +216,8 @@ defineOptions({
inheritAttrs: false,
});
import LogAPI, { LogTable, LogPageQuery } from "@/api/system/log";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import LogAPI, { LogTable, LogPageQuery } from "@/api/module_system/log";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import JsonPretty from "@/components/JsonPretty/index.vue";
import type { IContentConfig } from "@/components/CURD/types";
@@ -482,7 +482,7 @@ import { useAppStore } from "@/store/modules/app.store";
import { useUserStore } from "@/store/modules/user.store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import MenuAPI, { MenuPageQuery, MenuForm, MenuTable } from "@/api/system/menu";
import MenuAPI, { MenuPageQuery, MenuForm, MenuTable } from "@/api/module_system/menu";
import { MenuTypeEnum } from "@/enums/system/menu.enum";
import { formatTree } from "@/utils/common";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -267,7 +267,7 @@
<script setup lang="ts">
import { useDictStore } from "@/store/index";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -278,7 +278,7 @@ defineOptions({
inheritAttrs: false,
});
import NoticeAPI, { NoticeTable, NoticeForm, NoticePageQuery } from "@/api/system/notice";
import NoticeAPI, { NoticeTable, NoticeForm, NoticePageQuery } from "@/api/module_system/notice";
const queryFormRef = ref();
const dataFormRef = ref();
@@ -254,7 +254,7 @@
<script lang="ts" setup>
import { ref, reactive, onMounted, computed } from 'vue';
import ParamsAPI, { type ConfigTable } from '@/api/system/params';
import ParamsAPI, { type ConfigTable } from '@/api/module_system/params';
import { useConfigStore } from "@/store";
import { useI18n } from 'vue-i18n';
import { ElMessage, ElMessageBox } from 'element-plus';
@@ -210,8 +210,8 @@ defineOptions({
inheritAttrs: false,
});
import ParamsAPI, { ConfigTable, ConfigForm, ConfigPageQuery } from "@/api/system/params";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import ParamsAPI, { ConfigTable, ConfigForm, ConfigPageQuery } from "@/api/module_system/params";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -218,9 +218,9 @@ defineOptions({
inheritAttrs: false,
});
import PositionAPI, { PositionTable, PositionForm, PositionPageQuery } from "@/api/system/position";
import PositionAPI, { PositionTable, PositionForm, PositionPageQuery } from "@/api/module_system/position";
import { useUserStore } from "@/store";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { formatToDateTime } from "@/utils/dateUtil";
@@ -146,9 +146,9 @@ const props = defineProps({
})
import { listToTree, formatTree } from "@/utils/common";
import RoleAPI, { permissionDataType, permissionDeptType, permissionMenuType } from "@/api/system/role";
import DeptAPI from "@/api/system/dept";
import MenuAPI from "@/api/system/menu";
import RoleAPI, { permissionDataType, permissionDeptType, permissionMenuType } from "@/api/module_system/role";
import DeptAPI from "@/api/module_system/dept";
import MenuAPI from "@/api/module_system/menu";
import type { TreeInstance } from 'element-plus'
import { useAppStore } from "@/store/modules/app.store";
import { DeviceEnum } from "@/enums/settings/device.enum";
@@ -285,9 +285,9 @@ defineOptions({
});
import { ElMessage, ElMessageBox } from "element-plus";
import RoleAPI, { RoleTable, RoleForm, TablePageQuery } from "@/api/system/role";
import RoleAPI, { RoleTable, RoleForm, TablePageQuery } from "@/api/module_system/role";
import { useUserStore } from "@/store";
import UserTableSelect from "@/views/system/user/components/UserTableSelect.vue";
import UserTableSelect from "@/views/module_system/user/components/UserTableSelect.vue";
import ExportModal from "@/components/CURD/ExportModal.vue";
import type { IContentConfig } from "@/components/CURD/types";
import { QuestionFilled, ArrowUp, ArrowDown } from "@element-plus/icons-vue";
@@ -26,7 +26,7 @@
</template>
<script setup lang="ts">
import DeptAPI, { DeptPageQuery } from "@/api/system/dept";
import DeptAPI, { DeptPageQuery } from "@/api/module_system/dept";
import { formatTree } from "@/utils/common";
import type { FilterNodeMethodFunction, TreeInstance } from 'element-plus'
@@ -11,7 +11,7 @@
<script setup lang="ts">
import type { ISelectConfig } from "@/components/TableSelect/index.vue";
import UserAPI from "@/api/system/user";
import UserAPI from "@/api/module_system/user";
// 父组件双向绑定的值(选中用户ID)
const props = defineProps<{ modelValue?: number }>();
@@ -369,11 +369,11 @@ import { useAppStore } from "@/store/modules/app.store";
import { DeviceEnum } from "@/enums/settings/device.enum";
import { ResultEnum } from "@/enums/api/result.enum";
import UserAPI, { type UserForm, type UserInfo, type UserPageQuery } from "@/api/system/user";
import UserAPI, { type UserForm, type UserInfo, type UserPageQuery } from "@/api/module_system/user";
import { formatTree } from "@/utils/common";
import PositionAPI from "@/api/system/position";
import DeptAPI from "@/api/system/dept";
import RoleAPI from "@/api/system/role";
import PositionAPI from "@/api/module_system/position";
import DeptAPI from "@/api/module_system/dept";
import RoleAPI from "@/api/module_system/role";
import { formatToDateTime } from "@/utils/dateUtil";
import DeptTree from "./components/DeptTree.vue";