feat: 项目结构重构优化

This commit is contained in:
Ray.Hao
2025-12-26 12:35:37 +08:00
parent 65ad4fe59f
commit aa374dd2ba
164 changed files with 11305 additions and 3103 deletions

View File

@@ -0,0 +1,141 @@
import { describe, it, expect, beforeEach } from "vitest";
import { setActivePinia, createPinia } from "pinia";
import { useAppStore } from "@/store/modules/app";
import { DeviceEnum, SidebarStatus } from "@/enums";
describe("useAppStore", () => {
beforeEach(() => {
setActivePinia(createPinia());
localStorage.clear();
});
describe("侧边栏状态", () => {
it("应该切换侧边栏状态", () => {
const store = useAppStore();
const initialState = store.sidebar.opened;
store.toggleSidebar();
expect(store.sidebar.opened).toBe(!initialState);
store.toggleSidebar();
expect(store.sidebar.opened).toBe(initialState);
});
it("应该关闭侧边栏", () => {
const store = useAppStore();
store.openSideBar();
expect(store.sidebar.opened).toBe(true);
store.closeSideBar();
expect(store.sidebar.opened).toBe(false);
});
it("应该打开侧边栏", () => {
const store = useAppStore();
store.closeSideBar();
expect(store.sidebar.opened).toBe(false);
store.openSideBar();
expect(store.sidebar.opened).toBe(true);
});
it("应该持久化侧边栏状态", () => {
const store = useAppStore();
store.openSideBar();
// 创建新的 store 实例模拟页面刷新
const newStore = useAppStore();
expect(newStore.sidebar.opened).toBe(true);
});
});
describe("设备类型", () => {
it("应该切换设备类型", () => {
const store = useAppStore();
store.toggleDevice(DeviceEnum.MOBILE);
expect(store.device).toBe(DeviceEnum.MOBILE);
store.toggleDevice(DeviceEnum.DESKTOP);
expect(store.device).toBe(DeviceEnum.DESKTOP);
});
it("应该持久化设备类型", () => {
const store = useAppStore();
store.toggleDevice(DeviceEnum.MOBILE);
const newStore = useAppStore();
expect(newStore.device).toBe(DeviceEnum.MOBILE);
});
});
describe("组件尺寸", () => {
it("应该修改组件尺寸", () => {
const store = useAppStore();
store.changeSize("large");
expect(store.size).toBe("large");
store.changeSize("small");
expect(store.size).toBe("small");
});
it("应该持久化组件尺寸", () => {
const store = useAppStore();
store.changeSize("large");
const newStore = useAppStore();
expect(newStore.size).toBe("large");
});
});
describe("语言设置", () => {
it("应该修改语言", () => {
const store = useAppStore();
store.changeLanguage("en");
expect(store.language).toBe("en");
store.changeLanguage("zh-cn");
expect(store.language).toBe("zh-cn");
});
it("应该根据语言返回正确的 locale", () => {
const store = useAppStore();
store.changeLanguage("en");
expect(store.locale).toBeDefined();
store.changeLanguage("zh-cn");
expect(store.locale).toBeDefined();
});
it("应该持久化语言设置", () => {
const store = useAppStore();
store.changeLanguage("en");
const newStore = useAppStore();
expect(newStore.language).toBe("en");
});
});
describe("顶部菜单", () => {
it("应该激活顶部菜单", () => {
const store = useAppStore();
store.activeTopMenu("/dashboard");
expect(store.activeTopMenuPath).toBe("/dashboard");
store.activeTopMenu("/system");
expect(store.activeTopMenuPath).toBe("/system");
});
it("应该持久化顶部菜单路径", () => {
const store = useAppStore();
store.activeTopMenu("/dashboard");
const newStore = useAppStore();
expect(newStore.activeTopMenuPath).toBe("/dashboard");
});
});
});

View File

@@ -0,0 +1,134 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import { setActivePinia, createPinia } from "pinia";
import { useDictStore } from "@/store/modules/dict";
import DictAPI from "@/api/system/dict";
import type { DictItemOption } from "@/types/api";
// Mock DictAPI
vi.mock("@/api/system/dict", () => ({
default: {
getDictItems: vi.fn(),
},
}));
describe("useDictStore", () => {
beforeEach(() => {
// 创建新的 Pinia 实例
setActivePinia(createPinia());
// 清理 localStorage
localStorage.clear();
// 重置所有 mock
vi.clearAllMocks();
});
describe("字典缓存", () => {
it("应该缓存字典数据", async () => {
const store = useDictStore();
const mockData: DictItemOption[] = [
{ value: "1", label: "选项1" },
{ value: "2", label: "选项2" },
];
vi.mocked(DictAPI.getDictItems).mockResolvedValue(mockData);
await store.loadDictItems("test_dict");
expect(store.getDictItems("test_dict")).toEqual(mockData);
expect(DictAPI.getDictItems).toHaveBeenCalledWith("test_dict");
expect(DictAPI.getDictItems).toHaveBeenCalledTimes(1);
});
it("应该从缓存中获取字典数据,不重复请求", async () => {
const store = useDictStore();
const mockData: DictItemOption[] = [{ value: "1", label: "选项1" }];
vi.mocked(DictAPI.getDictItems).mockResolvedValue(mockData);
// 第一次加载
await store.loadDictItems("test_dict");
// 第二次加载(应该从缓存获取)
await store.loadDictItems("test_dict");
expect(DictAPI.getDictItems).toHaveBeenCalledTimes(1);
expect(store.getDictItems("test_dict")).toEqual(mockData);
});
it("应该防止并发重复请求", async () => {
const store = useDictStore();
const mockData: DictItemOption[] = [{ value: "1", label: "选项1" }];
vi.mocked(DictAPI.getDictItems).mockResolvedValue(mockData);
// 同时发起多个请求
const promises = [
store.loadDictItems("test_dict"),
store.loadDictItems("test_dict"),
store.loadDictItems("test_dict"),
];
await Promise.all(promises);
// 应该只请求一次
expect(DictAPI.getDictItems).toHaveBeenCalledTimes(1);
});
});
describe("字典操作", () => {
it("应该返回空数组当字典不存在时", () => {
const store = useDictStore();
expect(store.getDictItems("non_exist")).toEqual([]);
});
it("应该移除指定字典项", async () => {
const store = useDictStore();
const mockData: DictItemOption[] = [{ value: "1", label: "选项1" }];
vi.mocked(DictAPI.getDictItems).mockResolvedValue(mockData);
await store.loadDictItems("test_dict");
expect(store.getDictItems("test_dict")).toEqual(mockData);
store.removeDictItem("test_dict");
expect(store.getDictItems("test_dict")).toEqual([]);
});
it("应该清空所有字典缓存", async () => {
const store = useDictStore();
const mockData1: DictItemOption[] = [{ value: "1", label: "选项1" }];
const mockData2: DictItemOption[] = [{ value: "2", label: "选项2" }];
vi.mocked(DictAPI.getDictItems)
.mockResolvedValueOnce(mockData1)
.mockResolvedValueOnce(mockData2);
await store.loadDictItems("dict1");
await store.loadDictItems("dict2");
expect(store.getDictItems("dict1")).toEqual(mockData1);
expect(store.getDictItems("dict2")).toEqual(mockData2);
store.clearDictCache();
expect(store.getDictItems("dict1")).toEqual([]);
expect(store.getDictItems("dict2")).toEqual([]);
});
});
describe("错误处理", () => {
it("应该处理请求失败的情况", async () => {
const store = useDictStore();
const error = new Error("Network error");
vi.mocked(DictAPI.getDictItems).mockRejectedValue(error);
await expect(store.loadDictItems("test_dict")).rejects.toThrow("Network error");
// 失败后应该允许重试
const mockData: DictItemOption[] = [{ value: "1", label: "选项1" }];
vi.mocked(DictAPI.getDictItems).mockResolvedValue(mockData);
await store.loadDictItems("test_dict");
expect(store.getDictItems("test_dict")).toEqual(mockData);
});
});
});

View File

@@ -0,0 +1,186 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import { setActivePinia, createPinia } from "pinia";
import { useSettingsStore } from "@/store/modules/settings";
import { ThemeMode, SidebarColor } from "@/enums";
// Mock theme utils
vi.mock("@/utils/theme", () => ({
applyTheme: vi.fn(),
generateThemeColors: vi.fn(() => ({})),
toggleDarkMode: vi.fn(),
toggleSidebarColor: vi.fn(),
}));
describe("useSettingsStore", () => {
beforeEach(() => {
setActivePinia(createPinia());
localStorage.clear();
vi.clearAllMocks();
});
describe("界面显示设置", () => {
it("应该切换标签页显示", () => {
const store = useSettingsStore();
const initial = store.showTagsView;
store.showTagsView = !initial;
expect(store.showTagsView).toBe(!initial);
});
it("应该切换 Logo 显示", () => {
const store = useSettingsStore();
const initial = store.showAppLogo;
store.showAppLogo = !initial;
expect(store.showAppLogo).toBe(!initial);
});
it("应该切换水印显示", () => {
const store = useSettingsStore();
const initial = store.showWatermark;
store.showWatermark = !initial;
expect(store.showWatermark).toBe(!initial);
});
it("应该持久化界面显示设置", () => {
const store = useSettingsStore();
store.showTagsView = false;
store.showAppLogo = false;
store.showWatermark = true;
const newStore = useSettingsStore();
expect(newStore.showTagsView).toBe(false);
expect(newStore.showAppLogo).toBe(false);
expect(newStore.showWatermark).toBe(true);
});
});
describe("主题设置", () => {
it("应该切换主题模式", () => {
const store = useSettingsStore();
store.theme = ThemeMode.DARK;
expect(store.theme).toBe(ThemeMode.DARK);
store.theme = ThemeMode.LIGHT;
expect(store.theme).toBe(ThemeMode.LIGHT);
});
it("应该修改主题颜色", () => {
const store = useSettingsStore();
store.themeColor = "#409EFF";
expect(store.themeColor).toBe("#409EFF");
store.themeColor = "#67C23A";
expect(store.themeColor).toBe("#67C23A");
});
it("应该持久化主题设置", () => {
const store = useSettingsStore();
store.theme = ThemeMode.DARK;
store.themeColor = "#409EFF";
const newStore = useSettingsStore();
expect(newStore.theme).toBe(ThemeMode.DARK);
expect(newStore.themeColor).toBe("#409EFF");
});
});
describe("侧边栏配色", () => {
it("应该切换侧边栏配色方案", () => {
const store = useSettingsStore();
store.sidebarColorScheme = SidebarColor.CLASSIC_BLUE;
expect(store.sidebarColorScheme).toBe(SidebarColor.CLASSIC_BLUE);
store.sidebarColorScheme = SidebarColor.THEME_COLOR;
expect(store.sidebarColorScheme).toBe(SidebarColor.THEME_COLOR);
});
it("应该持久化侧边栏配色", () => {
const store = useSettingsStore();
store.sidebarColorScheme = SidebarColor.CLASSIC_BLUE;
const newStore = useSettingsStore();
expect(newStore.sidebarColorScheme).toBe(SidebarColor.CLASSIC_BLUE);
});
});
describe("特殊模式", () => {
it("应该切换灰色模式", () => {
const store = useSettingsStore();
store.grayMode = true;
expect(store.grayMode).toBe(true);
store.grayMode = false;
expect(store.grayMode).toBe(false);
});
it("应该切换色弱模式", () => {
const store = useSettingsStore();
store.colorWeak = true;
expect(store.colorWeak).toBe(true);
store.colorWeak = false;
expect(store.colorWeak).toBe(false);
});
it("应该持久化特殊模式", () => {
const store = useSettingsStore();
store.grayMode = true;
store.colorWeak = true;
const newStore = useSettingsStore();
expect(newStore.grayMode).toBe(true);
expect(newStore.colorWeak).toBe(true);
});
});
describe("AI 助手", () => {
it("应该切换 AI 助手", () => {
const store = useSettingsStore();
store.userEnableAi = true;
expect(store.userEnableAi).toBe(true);
store.userEnableAi = false;
expect(store.userEnableAi).toBe(false);
});
it("应该持久化 AI 助手设置", () => {
const store = useSettingsStore();
store.userEnableAi = true;
const newStore = useSettingsStore();
expect(newStore.userEnableAi).toBe(true);
});
});
describe("重置设置", () => {
it("应该重置所有设置为默认值", () => {
const store = useSettingsStore();
// 修改所有设置
store.showTagsView = false;
store.showAppLogo = false;
store.showWatermark = false;
store.userEnableAi = true;
store.grayMode = true;
store.colorWeak = true;
store.theme = ThemeMode.DARK;
store.themeColor = "#409EFF";
// 重置
store.resetSettings();
// 验证已重置(具体值取决于 defaults
expect(store.userEnableAi).toBe(false);
expect(store.grayMode).toBe(false);
expect(store.colorWeak).toBe(false);
});
});
});