refactor: 重构工具模块导入与项目代码结构

1.  统一所有API文件的request导入路径,从@utils/http改为@utils
2.  合并工具类导出,将分散的工具模块整合到@utils统一出口
3.  重构状态管理导入路径,统一从@utils导入相关工具与store
4.  整理组件导入与样式引用,优化项目内组件与样式的引用路径
5.  新增部分基础组件与工具方法,完善项目基础能力
6.  修复部分样式类名的书写规范,统一类名格式
This commit is contained in:
zhangtao
2026-05-17 06:56:31 +08:00
parent bb768d1a34
commit 8725be6d7d
210 changed files with 1277 additions and 1393 deletions
@@ -7,7 +7,7 @@
dialog-class="create-table-dialog"
@opened="onDialogOpened"
>
<ElAlert type="info" :closable="false" show-icon class="mb-3 !items-start">
<ElAlert type="info" :closable="false" show-icon class="mb-3 items-start!">
<template #title>
<span class="text-sm leading-relaxed">
<template v-if="editMode === 'visual'">
@@ -19,7 +19,7 @@
</ElAlert>
<div class="create-table-toolbar mb-3 flex flex-wrap items-center gap-2">
<span class="text-sm text-[var(--el-text-color-regular)] shrink-0">方式</span>
<span class="text-sm text-(--el-text-color-regular) shrink-0">方式</span>
<ElRadioGroup v-model="editMode" size="small">
<ElRadioButton value="visual">表结构推荐</ElRadioButton>
<ElRadioButton value="sql"> SQL</ElRadioButton>
@@ -42,7 +42,7 @@
</ElDropdownMenu>
</template>
</ElDropdown>
<span class="text-xs text-[var(--el-text-color-secondary)]">从模板开始比自己写更省事</span>
<span class="text-xs text-(--el-text-color-secondary)">从模板开始比自己写更省事</span>
</div>
<ElScrollbar max-height="min(52vh, 420px)" class="sql-editor-scroll">
<div class="absolute z-36 right-5 top-2">
@@ -67,7 +67,7 @@
<div class="visual-structure max-w-3xl">
<FaDescriptions :column="1" size="small" class="visual-desc" :scrollbar="false">
<template #title>
<span class="text-sm font-medium text-[var(--el-text-color-primary)]">选项</span>
<span class="text-sm font-medium text-(--el-text-color-primary)">选项</span>
</template>
<ElDescriptionsItem label="数据库" label-class-name="visual-desc-label">
<ElRadioGroup v-model="visual.dialect" size="small">
@@ -85,11 +85,11 @@
<FaDescriptions :column="1" size="small" class="visual-desc mt-3" :scrollbar="false">
<template #title>
<span class="text-sm font-medium text-[var(--el-text-color-primary)]">主表</span>
<span class="text-sm font-medium text-(--el-text-color-primary)">主表</span>
</template>
<ElDescriptionsItem label-class-name="visual-desc-label">
<template #label>
<span class="text-[var(--el-color-danger)]">*</span>
<span class="text-(--el-color-danger)">*</span>
表名
</template>
<ElInput
@@ -111,11 +111,11 @@
:scrollbar="false"
>
<template #title>
<span class="text-sm font-medium text-[var(--el-text-color-primary)]">子表</span>
<span class="text-sm font-medium text-(--el-text-color-primary)">子表</span>
</template>
<ElDescriptionsItem label-class-name="visual-desc-label">
<template #label>
<span class="text-[var(--el-color-danger)]">*</span>
<span class="text-(--el-color-danger)">*</span>
表名
</template>
<ElInput
@@ -145,7 +145,7 @@
</ElLink>
</div>
</div>
<p class="mb-1 mt-2 text-xs text-[var(--el-text-color-secondary)]">
<p class="mb-1 mt-2 text-xs text-(--el-text-color-secondary)">
将要执行的 SQL随上面表格自动更新
</p>
<ElInput
@@ -229,8 +229,9 @@ import { GENCODE_BASIC_FORM_KEY } from "../gencodeInjectionKeys";
defineOptions({ name: "GenBasicStep" });
const info = defineModel<GenTableSchema>("info", { required: true });
const props = defineProps<{
info: GenTableSchema;
rules: FormRules;
menuOptions: OptionType[];
}>();
@@ -247,7 +248,7 @@ function findOptionByValue(options: OptionType[], value: number | string): any |
}
function inferPackageNameFromParentMenu(): string | null {
const pid = props.info.parent_menu_id;
const pid = info.value.parent_menu_id;
if (pid == null) return null;
const node = findOptionByValue(props.menuOptions || [], pid);
const routePath = (node?.route_path ?? "").toString().trim();
@@ -258,12 +259,12 @@ function inferPackageNameFromParentMenu(): string | null {
}
const effectivePackageName = computed(() => {
return inferPackageNameFromParentMenu() || (props.info.package_name || "").trim();
return inferPackageNameFromParentMenu() || (info.value.package_name || "").trim();
});
const permissionPreview = computed(() => {
const pkg = effectivePackageName.value;
const mod = (props.info.module_name || "").trim();
const mod = (info.value.module_name || "").trim();
if (!pkg || !mod) return "<module_xxx>:<module>:<操作>";
// permission_prefix + query
return `${pkg}:${mod}:query`;
@@ -271,21 +272,21 @@ const permissionPreview = computed(() => {
const backendModuleDirPreview = computed(() => {
const pkg = effectivePackageName.value;
const mod = (props.info.module_name || "").trim();
const mod = (info.value.module_name || "").trim();
if (!pkg || !mod) return "backend/app/plugin/<module_xxx>/<module>/";
return `backend/app/plugin/${pkg}/${mod}/`;
});
const frontendViewDirPreview = computed(() => {
const pkg = effectivePackageName.value;
const mod = (props.info.module_name || "").trim();
const mod = (info.value.module_name || "").trim();
if (!pkg || !mod) return "frontend/src/views/<module_xxx>/<module>/";
return `frontend/src/views/${pkg}/${mod}/`;
});
const frontendApiFilePreview = computed(() => {
const pkg = effectivePackageName.value;
const mod = (props.info.module_name || "").trim();
const mod = (info.value.module_name || "").trim();
if (!pkg || !mod) return "frontend/src/api/<module_xxx>/<module>.ts";
return `frontend/src/api/${pkg}/${mod}.ts`;
});
@@ -312,13 +313,13 @@ function slugFromTableName(table: string): string {
}
watch(
() => [props.info.parent_menu_id, props.info.module_name, props.info.table_name] as const,
() => [info.value.parent_menu_id, info.value.module_name, info.value.table_name] as const,
() => {
if (props.info.parent_menu_id != null) return;
const current = (props.info.package_name || "").trim();
if (info.value.parent_menu_id != null) return;
const current = (info.value.package_name || "").trim();
if (current && current !== "gencode" && current !== "module_gencode") return;
const mod = (props.info.module_name || "").trim();
const tn = (props.info.table_name || "").trim();
const mod = (info.value.module_name || "").trim();
const tn = (info.value.table_name || "").trim();
const slug = tn ? slugFromTableName(tn) : "";
const next = mod
? mod.startsWith("module_")
@@ -327,7 +328,7 @@ watch(
: slug
? `module_${slug}`
: "";
if (next) props.info.package_name = next;
if (next) info.value.package_name = next;
},
{ immediate: true }
);
@@ -16,7 +16,7 @@
<div class="gencode-drawer-step-wrap mt-4">
<div v-show="activeStep === 0">
<GenBasicStep
:info="info"
v-model:info="info"
:rules="rules"
:menu-options="menuOptions"
@clear-master-sub="emit('clear-master-sub')"
@@ -26,7 +26,7 @@
<div v-show="activeStep === 1">
<GenColumnsStep
:info="info"
v-model:info="info"
:dict-options="dictOptions"
:loading="loading"
:bulk-set="bulkSet"
@@ -101,14 +101,15 @@ import type { GenTableSchema } from "@/api/module_generator/gencode";
import type { DictTable } from "@/api/module_system/dict";
import FaDrawer from "@/components/modal/fa-drawer/index.vue";
import type { TreeNode } from "../types";
import GenBasicStep from "./GenBasicStep.vue";
import GenColumnsStep from "./GenColumnsStep.vue";
import GenPreviewStep from "./GenPreviewStep.vue";
import GenBasicStep from "./FaGenBasicStep.vue";
import GenColumnsStep from "./FaGenColumnsStep.vue";
import GenPreviewStep from "./FaGenPreviewStep.vue";
defineOptions({ name: "GenCodeDrawer" });
const info = defineModel<GenTableSchema>("info", { required: true });
const props = defineProps<{
info: GenTableSchema;
rules: FormRules;
activeStep: number;
menuOptions: OptionType[];
@@ -254,8 +254,9 @@ import type { DictTable } from "@/api/module_system/dict";
defineOptions({ name: "GenColumnsStep" });
const props = defineProps<{
info: GenTableSchema;
const info = defineModel<GenTableSchema>("info", { required: true });
defineProps<{
dictOptions: DictTable[];
loading: boolean;
bulkSet: (field: string | string[], value: unknown) => void;
@@ -273,15 +274,14 @@ const tableHeight = computed(() => {
});
const columnsModel = computed({
get: () => props.info.columns || [],
get: () => info.value.columns || [],
set: (v) => {
// props.info reactive
props.info.columns = v as GenTableColumnSchema[];
info.value.columns = v as GenTableColumnSchema[];
},
});
const displayColumns = computed(() => {
const cols = props.info.columns || [];
const cols = info.value.columns || [];
const q = columnKeyword.value.trim().toLowerCase();
if (!q) return cols;
return cols.filter((c) => {
@@ -330,7 +330,7 @@ onMounted(() => {
});
watch(
() => [columnKeyword.value, (props.info.columns || []).length],
() => [columnKeyword.value, (info.value.columns || []).length],
async () => {
await setupRowDraggable();
}
@@ -92,8 +92,7 @@ import Codemirror from "codemirror-editor-vue3";
import type { EditorConfiguration } from "codemirror";
import type { CmComponentRef } from "codemirror-editor-vue3";
import FaSvgIcon from "@/components/base/fa-svg-icon/index.vue";
import { resolveLocalIconUrl } from "@utils/icons";
import { resolveIconForFaSvgIcon } from "@utils/menuIcon/index";
import { resolveLocalIconUrl, resolveIconForFaSvgIcon } from "@utils";
import { CopyDocument } from "@element-plus/icons-vue";
import { GENCODE_CM_KEY } from "../gencodeInjectionKeys";
import type { TreeNode } from "../types";
@@ -84,14 +84,14 @@
/>
</ElCard>
<CreateTableDialog
<FaCreateTableDialog
v-model="createTableVisible"
:loading="loading"
:link-from-gen="createTableLinkFromGen"
@submit="handleCreateTableSubmit"
/>
<ImportDbTableDialog
<FaImportDbTableDialog
ref="importDbDialogRef"
v-model="importVisible"
v-model:query="formData"
@@ -105,12 +105,12 @@
@selection-change="handleImportTableSelectionChange"
/>
<GenCodeDrawer
<FaGenCodeDrawer
v-model="editVisible"
v-model:preview-scope="previewScope"
v-model:preview-types="previewTypes"
v-model:code="code"
:info="info"
v-model:info="info"
:rules="rules"
:active-step="activeStep"
:menu-options="menuOptions"
@@ -164,13 +164,14 @@ import FaTable from "@/components/tables/fa-table/index.vue";
import FaTableHeader from "@/components/tables/fa-table-header/index.vue";
import FaSearchBar from "@/components/forms/fa-search-bar/index.vue";
import type { SearchFormItem } from "@/components/forms/fa-search-bar/index.vue";
import FaGenCodeDrawer from "./components/FaGenCodeDrawer.vue";
import FaImportDbTableDialog from "./components/FaImportDbTableDialog.vue";
import { CreateTableSubmitMeta } from "./components/FaCreateTableDialog.vue";
import FaCreateTableDialog from "./components/FaCreateTableDialog.vue";
import { GENCODE_BASIC_FORM_KEY, GENCODE_CM_KEY } from "./gencodeInjectionKeys";
import type { ColumnOption } from "@/types/component";
import { useAuth } from "@/hooks/core/useAuth";
import { renderTableOperationCell, type TableOperationAction } from "@utils/table";
import CreateTableDialog, { type CreateTableSubmitMeta } from "./components/CreateTableDialog.vue";
import GenCodeDrawer from "./components/GenCodeDrawer.vue";
import ImportDbTableDialog from "./components/ImportDbTableDialog.vue";
import { GENCODE_BASIC_FORM_KEY, GENCODE_CM_KEY } from "./gencodeInjectionKeys";
import { renderTableOperationCell, type TableOperationAction } from "@utils";
import type { TreeNode } from "./types";
// 文件数据接口
@@ -184,7 +185,7 @@ interface FileData {
// 组件引用(与子组件 inject 同步,供校验 / CodeMirror 主题)
const cmRef = ref<CmComponentRef>();
const basicInfo = ref<FormInstance>();
const importDbDialogRef = ref<InstanceType<typeof ImportDbTableDialog>>();
const importDbDialogRef = ref<InstanceType<typeof FaImportDbTableDialog>>();
/** FaTable:勾选清空(删除后) */
const faTableRef = ref<{ elTableRef?: { clearSelection: () => void } } | null>(null);
@@ -1038,7 +1039,7 @@ async function handleImportReset(): Promise<void> {
}
// 表单数据(后端返回字段可能含 null,这里做更宽松的承载,避免 TS 因类型收窄报错)
const info = reactive<
let info = reactive<
GenTableSchema & {
sub_table_name?: string | null;
sub_table_fk_name?: string | null;