mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-23 05:10:57 +00:00
refactor: 重构工具模块导入与项目代码结构
1. 统一所有API文件的request导入路径,从@utils/http改为@utils 2. 合并工具类导出,将分散的工具模块整合到@utils统一出口 3. 重构状态管理导入路径,统一从@utils导入相关工具与store 4. 整理组件导入与样式引用,优化项目内组件与样式的引用路径 5. 新增部分基础组件与工具方法,完善项目基础能力 6. 修复部分样式类名的书写规范,统一类名格式
This commit is contained in:
+9
-9
@@ -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
|
||||
+14
-13
@@ -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 }
|
||||
);
|
||||
+7
-6
@@ -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[];
|
||||
+7
-7
@@ -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();
|
||||
}
|
||||
+1
-2
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user