refactor: ♻️ 字典调整按需加载,api、store和枚举文件命名优化

This commit is contained in:
Ray.Hao
2025-03-24 08:17:31 +08:00
parent 6204deb7cb
commit 3c9cf67961
84 changed files with 989 additions and 1108 deletions

View File

@@ -417,18 +417,18 @@ import Codemirror from "codemirror-editor-vue3";
import type { CmComponentRef } from "codemirror-editor-vue3";
import type { EditorConfiguration } from "codemirror";
import { FormTypeEnum } from "@/enums/FormTypeEnum";
import { QueryTypeEnum } from "@/enums/QueryTypeEnum";
import { FormTypeEnum } from "@/enums/codegen/form.enum";
import { QueryTypeEnum } from "@/enums/codegen/query.enum";
import GeneratorAPI, {
TablePageVO,
GenConfigForm,
TablePageQuery,
FieldConfig,
} from "@/api/codegen";
} from "@/api/codegen.api";
import DictAPI from "@/api/system/dict";
import MenuAPI from "@/api/system/menu";
import DictAPI from "@/api/system/dict.api";
import MenuAPI from "@/api/system/menu.api";
interface TreeNode {
label: string;

View File

@@ -285,8 +285,8 @@ defineOptions({
});
import { dayjs } from "element-plus";
import LogAPI, { VisitStatsVO, VisitTrendVO } from "@/api/system/log";
import { useUserStore } from "@/store/modules/user";
import LogAPI, { VisitStatsVO, VisitTrendVO } from "@/api/system/log.api";
import { useUserStore } from "@/store/modules/user.store";
import { formatGrowthRate } from "@/utils";
interface VersionItem {

View File

@@ -1,4 +1,4 @@
import UserAPI, { type UserForm } from "@/api/system/user";
import UserAPI, { type UserForm } from "@/api/system/user.api";
import type { IModalConfig } from "@/components/CURD/types";
const modalConfig: IModalConfig<UserForm> = {
@@ -11,7 +11,7 @@ const modalConfig: IModalConfig<UserForm> = {
form: {
labelWidth: 100,
},
formAction: UserAPI.add,
formAction: UserAPI.create,
beforeSubmit(data) {
console.log("提交之前处理", data);
},

View File

@@ -1,6 +1,6 @@
import UserAPI from "@/api/system/user";
import RoleAPI from "@/api/system/role";
import type { UserPageQuery } from "@/api/system/user";
import UserAPI from "@/api/system/user.api";
import RoleAPI from "@/api/system/role.api";
import type { UserPageQuery } from "@/api/system/user.api";
import type { IContentConfig } from "@/components/CURD/types";
const contentConfig: IContentConfig<UserPageQuery> = {

View File

@@ -1,6 +1,6 @@
import UserAPI, { type UserForm } from "@/api/system/user";
import UserAPI, { type UserForm } from "@/api/system/user.api";
import type { IModalConfig } from "@/components/CURD/types";
import { DeviceEnum } from "@/enums/DeviceEnum";
import { DeviceEnum } from "@/enums/settings/device.enum";
import { useAppStore } from "@/store";
const modalConfig: IModalConfig<UserForm> = {

View File

@@ -1,4 +1,4 @@
import DeptAPI from "@/api/system/dept";
import DeptAPI from "@/api/system/dept.api";
import type { ISearchConfig } from "@/components/CURD/types";
const searchConfig: ISearchConfig = {

View File

@@ -90,9 +90,9 @@
</template>
<script setup lang="ts">
import UserAPI from "@/api/system/user";
import DeptAPI from "@/api/system/dept";
import RoleAPI from "@/api/system/role";
import UserAPI from "@/api/system/user.api";
import DeptAPI from "@/api/system/dept.api";
import RoleAPI from "@/api/system/role.api";
import type { IObject, IOperatData } from "@/components/CURD/types";
import usePage from "@/components/CURD/usePage";
import addModalConfig from "./config/add";

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import FileAPI from "@/api/file";
import FileAPI from "@/api/file.api";
const imgUrl = ref("");
const canvas = ref();

View File

@@ -1,4 +1,4 @@
import UserAPI from "@/api/system/user";
import UserAPI from "@/api/system/user.api";
import type { ISelectConfig } from "@/components/TableSelect/index.vue";
const selectConfig: ISelectConfig = {

View File

@@ -98,7 +98,7 @@
<script setup lang="ts">
import { useStomp } from "@/hooks/useStomp";
import { useUserStoreHook } from "@/store/modules/user";
import { useUserStoreHook } from "@/store/modules/user.store";
const userStore = useUserStoreHook();
// 用于手动调整 WebSocket 地址

View File

@@ -146,28 +146,27 @@
</template>
<script setup lang="ts">
import { LocationQuery, useRoute } from "vue-router";
import { LocationQuery, RouteLocationRaw, useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import AuthAPI, { type LoginFormData } from "@/api/auth";
import AuthAPI, { type LoginFormData } from "@/api/auth.api";
import router from "@/router";
import type { FormInstance } from "element-plus";
import defaultSettings from "@/settings";
import { ThemeEnum } from "@/enums/ThemeEnum";
import { ThemeMode } from "@/enums/settings/theme.enum";
import { useSettingsStore, useUserStore, useDictStore } from "@/store";
import { useSettingsStore, useUserStore } from "@/store";
const userStore = useUserStore();
const settingsStore = useSettingsStore();
const dictStore = useDictStore();
const route = useRoute();
const { t } = useI18n();
const loginFormRef = ref<FormInstance>();
const isDark = ref(settingsStore.theme === ThemeEnum.DARK); // 是否暗黑模式
const isDark = ref(settingsStore.theme === ThemeMode.DARK); // 是否暗黑模式
const loading = ref(false); // 按钮 loading 状态
const isCapslock = ref(false); // 是否大写锁定
const captchaBase64 = ref(); // 验证码图片Base64字符串
@@ -218,57 +217,60 @@ function getCaptcha() {
});
}
// 登录
// 登录提交处理
async function handleLoginSubmit() {
loginFormRef.value?.validate((valid: boolean) => {
if (valid) {
loading.value = true;
userStore
.login(loginFormData.value)
.then(async () => {
await userStore.getUserInfo();
// 需要在路由跳转前加载字典数据,否则会出现字典数据未加载完成导致页面渲染异常
await dictStore.loadDictionaries();
// 跳转到登录前的页面
const { path, queryParams } = parseRedirect();
router.push({ path: path, query: queryParams });
})
.catch(() => {
getCaptcha();
})
.finally(() => {
loading.value = false;
});
}
});
// 1. 表单验证
const valid = await loginFormRef.value?.validate();
if (!valid) return;
loading.value = true;
try {
// 2. 执行登录
await userStore.login(loginFormData.value);
// 3. 获取用户信息
await userStore.getUserInfo();
// 4. 解析并跳转目标地址
const redirect = resolveRedirectTarget(route.query);
await router.push(redirect);
} catch (error) {
// 5. 统一错误处理
getCaptcha(); // 刷新验证码
console.error("登录失败:", error);
} finally {
loading.value = false;
}
}
/**
* 解析 redirect 字符串 为 path 和 queryParams
*
* @returns { path: string, queryParams: Record<string, string> } 解析后的 path 和 queryParams
* 解析重定向目标
* @param query 路由查询参数
* @returns 标准化后的路由地址对象
*/
function parseRedirect(): {
path: string;
queryParams: Record<string, string>;
} {
const query: LocationQuery = route.query;
const redirect = (query.redirect as string) ?? "/";
function resolveRedirectTarget(query: LocationQuery): RouteLocationRaw {
// 默认跳转路径
const defaultPath = "/";
const url = new URL(redirect, window.location.origin);
const path = url.pathname;
const queryParams: Record<string, string> = {};
// 获取原始重定向路径
const rawRedirect = (query.redirect as string) || defaultPath;
url.searchParams.forEach((value, key) => {
queryParams[key] = value;
});
return { path, queryParams };
try {
// 6. 使用Vue Router解析路径
const resolved = router.resolve(rawRedirect);
return {
path: resolved.path,
query: resolved.query,
};
} catch {
// 7. 异常处理:返回安全路径
return { path: defaultPath };
}
}
// 主题切换
const toggleTheme = () => {
const newTheme = settingsStore.theme === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
const newTheme = settingsStore.theme === ThemeMode.DARK ? ThemeMode.LIGHT : ThemeMode.DARK;
settingsStore.changeTheme(newTheme);
};

View File

@@ -260,9 +260,9 @@ import UserAPI, {
MobileUpdateForm,
EmailUpdateForm,
UserProfileForm,
} from "@/api/system/user";
} from "@/api/system/user.api";
import FileAPI from "@/api/file";
import FileAPI from "@/api/file.api";
import { Camera } from "@element-plus/icons-vue";

View File

@@ -135,7 +135,7 @@ defineOptions({
inheritAttrs: false,
});
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config";
import ConfigAPI, { ConfigPageVO, ConfigForm, ConfigPageQuery } from "@/api/system/config.api";
const queryFormRef = ref();
const dataFormRef = ref();
@@ -233,7 +233,7 @@ function handleSubmit() {
})
.finally(() => (loading.value = false));
} else {
ConfigAPI.add(formData)
ConfigAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();

View File

@@ -158,7 +158,7 @@ defineOptions({
inheritAttrs: false,
});
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/system/dept";
import DeptAPI, { DeptVO, DeptForm, DeptQuery } from "@/api/system/dept.api";
const queryFormRef = ref();
const deptFormRef = ref();
@@ -251,7 +251,7 @@ function handleSubmit() {
})
.finally(() => (loading.value = false));
} else {
DeptAPI.add(formData)
DeptAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();

View File

@@ -1,4 +1,4 @@
<!-- 字典数据 -->
<!-- 字典 -->
<template>
<div class="app-container">
<div class="search-bar mt-5">
@@ -34,8 +34,8 @@
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典标签" prop="label" />
<el-table-column label="字典值" prop="value" />
<el-table-column label="字典标签" prop="label" />
<el-table-column label="字典值" prop="value" />
<el-table-column label="排序" prop="sort" />
<el-table-column label="状态">
<template #default="scope">
@@ -78,7 +78,7 @@
/>
</el-card>
<!--字典弹窗-->
<!--字典弹窗-->
<el-dialog
v-model="dialog.visible"
:title="dialog.title"
@@ -87,10 +87,10 @@
>
<el-form ref="dataFormRef" :model="formData" :rules="computedRules" label-width="100px">
<el-card shadow="never">
<el-form-item label="字典标签" prop="label">
<el-form-item label="字典标签" prop="label">
<el-input v-model="formData.label" placeholder="请输入字典标签" />
</el-form-item>
<el-form-item label="字典值" prop="value">
<el-form-item label="字典值" prop="value">
<el-input v-model="formData.value" placeholder="请输入字典值" />
</el-form-item>
<el-form-item label="状态">
@@ -130,15 +130,11 @@
<script setup lang="ts">
defineOptions({
name: "DictData",
name: "DictItem",
inherititems: false,
});
import DictDataAPI, {
DictDataPageQuery,
DictDataPageVO,
DictDataForm,
} from "@/api/system/dict-data";
import DictAPI, { DictItemPageQuery, DictItemPageVO, DictItemForm } from "@/api/system/dict.api";
const route = useRoute();
@@ -151,20 +147,19 @@ const loading = ref(false);
const ids = ref<number[]>([]);
const total = ref(0);
const queryParams = reactive<DictDataPageQuery>({
const queryParams = reactive<DictItemPageQuery>({
pageNum: 1,
pageSize: 10,
dictCode: dictCode.value,
});
const tableData = ref<DictDataPageVO[]>();
const tableData = ref<DictItemPageVO[]>();
const dialog = reactive({
title: "",
visible: false,
});
const formData = reactive<DictDataForm>({});
const formData = reactive<DictItemForm>({});
const computedRules = computed(() => {
const rules: Partial<Record<string, any>> = {
@@ -177,7 +172,7 @@ const computedRules = computed(() => {
//
function handleQuery() {
loading.value = true;
DictDataAPI.getPage(queryParams)
DictAPI.getDictItemPage(dictCode.value, queryParams)
.then((data) => {
tableData.value = data.list;
total.value = data.total;
@@ -200,12 +195,12 @@ function handleSelectionChange(selection: any) {
}
//
function handleOpenDialog(row?: DictDataPageVO) {
function handleOpenDialog(row?: DictItemPageVO) {
dialog.visible = true;
dialog.title = row ? "编辑字典数据" : "新增字典数据";
dialog.title = row ? "编辑字典" : "新增字典";
if (row?.id) {
DictDataAPI.getFormData(row.id).then((data) => {
DictAPI.getDictItemFormData(dictCode.value, row.id).then((data) => {
Object.assign(formData, data);
});
}
@@ -219,7 +214,7 @@ function handleSubmitClick() {
const id = formData.id;
formData.dictCode = dictCode.value;
if (id) {
DictDataAPI.update(id, formData)
DictAPI.updateDictItem(dictCode.value, id, formData)
.then(() => {
ElMessage.success("修改成功");
handleCloseDialog();
@@ -227,7 +222,7 @@ function handleSubmitClick() {
})
.finally(() => (loading.value = false));
} else {
DictDataAPI.add(formData)
DictAPI.createDictItem(dictCode.value, formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();
@@ -256,8 +251,8 @@ function handleCloseDialog() {
* @param id 字典ID
*/
function handleDelete(id?: number) {
const attrGroupIds = [id || ids.value].join(",");
if (!attrGroupIds) {
const itemIds = [id || ids.value].join(",");
if (!itemIds) {
ElMessage.warning("请勾选删除项");
return;
}
@@ -267,7 +262,7 @@ function handleDelete(id?: number) {
type: "warning",
}).then(
() => {
DictDataAPI.deleteByIds(attrGroupIds).then(() => {
DictAPI.deleteDictItems(dictCode.value, itemIds).then(() => {
ElMessage.success("删除成功");
handleResetQuery();
});

View File

@@ -129,7 +129,7 @@ defineOptions({
inherititems: false,
});
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict";
import DictAPI, { DictPageQuery, DictPageVO, DictForm } from "@/api/system/dict.api";
import router from "@/router";
@@ -221,7 +221,7 @@ function handleSubmitClick() {
})
.finally(() => (loading.value = false));
} else {
DictAPI.add(formData)
DictAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();
@@ -270,17 +270,12 @@ function handleDelete(id?: number) {
);
}
// 打开字典数据
// 打开字典
function handleOpenDictData(row: DictPageVO) {
router.push({
path: "/system/dict-data",
path: "/system/dict-item",
query: { dictCode: row.dictCode, title: "【" + row.name + "】字典数据" },
});
/* router.push({
name: "DictData",
params: { dictCode: row.dictCode, title: "【" + row.name + "】字典数据" },
}); */
}
onMounted(() => {

View File

@@ -60,7 +60,7 @@ defineOptions({
inheritAttrs: false,
});
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log";
import LogAPI, { LogPageVO, LogPageQuery } from "@/api/system/log.api";
const queryFormRef = ref();

View File

@@ -335,8 +335,8 @@ defineOptions({
inheritAttrs: false,
});
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/system/menu";
import { MenuTypeEnum } from "@/enums/MenuTypeEnum";
import MenuAPI, { MenuQuery, MenuForm, MenuVO } from "@/api/system/menu.api";
import { MenuTypeEnum } from "@/enums/system/menu.enum";
const queryFormRef = ref();
const menuFormRef = ref();
@@ -465,7 +465,7 @@ function handleSubmit() {
handleQuery();
});
} else {
MenuAPI.add(formData.value).then(() => {
MenuAPI.create(formData.value).then(() => {
ElMessage.success("新增成功");
handleCloseDialog();
handleQuery();

View File

@@ -107,7 +107,7 @@ defineOptions({
inheritAttrs: false,
});
import NoticeAPI, { NoticePageVO, NoticePageQuery, NoticeDetailVO } from "@/api/system/notice";
import NoticeAPI, { NoticePageVO, NoticePageQuery, NoticeDetailVO } from "@/api/system/notice.api";
const queryFormRef = ref();
const pageData = ref<NoticePageVO[]>([]);

View File

@@ -259,8 +259,8 @@ import NoticeAPI, {
NoticeForm,
NoticePageQuery,
NoticeDetailVO,
} from "@/api/system/notice";
import UserAPI from "@/api/system/user";
} from "@/api/system/notice.api";
import UserAPI from "@/api/system/user.api";
const queryFormRef = ref();
const dataFormRef = ref();
@@ -389,7 +389,7 @@ function handleSubmit() {
})
.finally(() => (loading.value = false));
} else {
NoticeAPI.add(formData)
NoticeAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();

View File

@@ -208,8 +208,8 @@ defineOptions({
inheritAttrs: false,
});
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role";
import MenuAPI from "@/api/system/menu";
import RoleAPI, { RolePageVO, RoleForm, RolePageQuery } from "@/api/system/role.api";
import MenuAPI from "@/api/system/menu.api";
const queryFormRef = ref();
const roleFormRef = ref();
@@ -313,7 +313,7 @@ function handleSubmit() {
})
.finally(() => (loading.value = false));
} else {
RoleAPI.add(formData)
RoleAPI.create(formData)
.then(() => {
ElMessage.success("新增成功");
handleCloseDialog();

View File

@@ -21,7 +21,7 @@
</template>
<script setup lang="ts">
import DeptAPI from "@/api/system/dept";
import DeptAPI from "@/api/system/dept.api";
const props = defineProps({
modelValue: {
type: [Number],

View File

@@ -90,8 +90,8 @@
<script lang="ts" setup>
import { ElMessage, type UploadUserFile } from "element-plus";
import UserAPI from "@/api/system/user";
import { ResultEnum } from "@/enums/ResultEnum";
import UserAPI from "@/api/system/user.api";
import { ResultEnum } from "@/enums/api/result.enum";
const emit = defineEmits(["import-success"]);
const visible = defineModel("modelValue", {

View File

@@ -237,10 +237,10 @@
</template>
<script setup lang="ts">
import UserAPI, { UserForm, UserPageQuery, UserPageVO } from "@/api/system/user";
import UserAPI, { UserForm, UserPageQuery, UserPageVO } from "@/api/system/user.api";
import DeptAPI from "@/api/system/dept";
import RoleAPI from "@/api/system/role";
import DeptAPI from "@/api/system/dept.api";
import RoleAPI from "@/api/system/role.api";
import DeptTree from "./components/DeptTree.vue";
import UserImport from "./components/UserImport.vue";
@@ -301,7 +301,7 @@ const roleOptions = ref<OptionType[]>();
const importDialogVisible = ref(false);
// 查询
function handleQuery() {
async function handleQuery() {
loading.value = true;
UserAPI.getPage(queryParams)
.then((data) => {
@@ -395,7 +395,7 @@ const handleSubmit = useDebounceFn(() => {
})
.finally(() => (loading.value = false));
} else {
UserAPI.add(formData)
UserAPI.create(formData)
.then(() => {
ElMessage.success("新增用户成功");
handleCloseDialog();