更新部分功能实现逻辑

This commit is contained in:
焦龙言
2026-06-22 13:23:04 +08:00
parent 1e6230d412
commit faa09101a1
31 changed files with 4859 additions and 307 deletions
+36
View File
@@ -0,0 +1,36 @@
import {
DEFAULT_THEME_SETTINGS,
isLegacyDefaultAppearance,
themeOptions,
} from "../src/stores/theme";
assertEqual(DEFAULT_THEME_SETTINGS.theme, "enterprise");
assertEqual(DEFAULT_THEME_SETTINGS.mode, "light");
assertEqual(DEFAULT_THEME_SETTINGS.font, "sans");
assertEqual(DEFAULT_THEME_SETTINGS.radius, "0.3");
assertEqual(DEFAULT_THEME_SETTINGS.density, "compact");
assertEqual(DEFAULT_THEME_SETTINGS.sidebar, "embedded");
const enterprise = themeOptions.find((item) => item.name === "enterprise");
if (!enterprise) {
throw new Error("缺少企业清爽主题");
}
assertEqual(enterprise.label, "企业清爽");
assertEqual(enterprise.tokens.light.surface, "#f5f7fa");
assertEqual(enterprise.tokens.light.sidebarBg, "#ffffff");
assertEqual(enterprise.tokens.light.navActiveBg, "#e8f0ff");
assertTruthy(isLegacyDefaultAppearance("anthropic", "dark", "serif", "1", "floating"));
assertTruthy(isLegacyDefaultAppearance("navy", "dark", "serif", "1", "floating"));
function assertEqual(actual: string, expected: string): void {
if (actual !== expected) {
throw new Error(`期望 ${expected},实际 ${actual}`);
}
}
function assertTruthy(actual: boolean): void {
if (!actual) {
throw new Error("期望结果为 true");
}
}
@@ -0,0 +1,41 @@
declare const process: { cwd(): string };
declare function require(name: string): {
readFileSync?: (path: string, encoding: string) => string;
join?: (...parts: string[]) => string;
};
const { readFileSync } = require("node:fs");
const { join } = require("node:path");
if (!readFileSync || !join) {
throw new Error("测试运行环境缺少文件读取能力");
}
const view = readFileSync(join(process.cwd(), "src/views/OrganizationView.vue"), "utf-8");
const css = readFileSync(join(process.cwd(), "src/assets/styles.css"), "utf-8");
assertIncludes(view, "organization-tree-layout");
assertIncludes(view, "organization-tree");
assertIncludes(view, "tree-node");
assertIncludes(view, "selectedNode");
assertIncludes(view, "部门详情");
assertIncludes(view, "岗位详情");
assertNotIncludes(view, "<h2>部门列表</h2>");
assertNotIncludes(view, "<h2>岗位列表</h2>");
assertIncludes(css, ".organization-tree-layout");
assertIncludes(css, ".organization-tree-panel");
assertIncludes(css, ".organization-detail-panel");
assertIncludes(css, ".tree-node");
function assertIncludes(content: string, expected: string): void {
if (!content.includes(expected)) {
throw new Error(`期望包含 ${expected}`);
}
}
function assertNotIncludes(content: string, unexpected: string): void {
if (content.includes(unexpected)) {
throw new Error(`不应包含 ${unexpected}`);
}
}
+56
View File
@@ -0,0 +1,56 @@
declare const process: { cwd(): string };
declare function require(name: string): {
existsSync?: (path: string) => boolean;
readFileSync?: (path: string, encoding: string) => string;
join?: (...parts: string[]) => string;
};
const { existsSync, readFileSync } = require("node:fs");
const { join } = require("node:path");
if (!existsSync || !readFileSync || !join) {
throw new Error("测试运行环境缺少文件读取能力");
}
const root = process.cwd();
const realtimeApiPath = join(root, "src/api/realtimeAttendance.ts");
const monthlyApiPath = join(root, "src/api/monthlyPayroll.ts");
const realtimeViewPath = join(root, "src/views/RealtimeAttendanceView.vue");
const monthlyViewPath = join(root, "src/views/MonthlyPayrollView.vue");
assertTruthy(existsSync(realtimeApiPath), "缺少实时考勤 API 客户端");
assertTruthy(existsSync(monthlyApiPath), "缺少月度核算 API 客户端");
const realtimeApi = readFileSync(realtimeApiPath, "utf-8");
assertIncludes(realtimeApi, "/api/attendance/realtime/today");
assertIncludes(realtimeApi, "/api/attendance/realtime/sync");
const monthlyApi = readFileSync(monthlyApiPath, "utf-8");
assertIncludes(monthlyApi, "/api/payroll/monthly/runs");
const realtimeView = readFileSync(realtimeViewPath, "utf-8");
assertNotIncludes(realtimeView, "待接入菜单");
assertNotIncludes(realtimeView, "待接入钉钉同步");
assertIncludes(realtimeView, "预估金额,最终以月度核算锁定结果为准");
const monthlyView = readFileSync(monthlyViewPath, "utf-8");
assertNotIncludes(monthlyView, "下一阶段接入");
assertIncludes(monthlyView, "锁定后本月工资不能重新计算");
function assertIncludes(content: string, expected: string): void {
if (!content.includes(expected)) {
throw new Error(`期望包含 ${expected}`);
}
}
function assertNotIncludes(content: string, unexpected: string): void {
if (content.includes(unexpected)) {
throw new Error(`不应包含 ${unexpected}`);
}
}
function assertTruthy(value: boolean, message: string): void {
if (!value) {
throw new Error(message);
}
}
+51
View File
@@ -0,0 +1,51 @@
declare const process: { cwd(): string };
declare function require(name: string): {
readFileSync?: (path: string, encoding: string) => string;
join?: (...parts: string[]) => string;
};
const { readFileSync } = require("node:fs");
const { join } = require("node:path");
if (!readFileSync || !join) {
throw new Error("测试运行环境缺少文件读取能力");
}
const css = readFileSync(join(process.cwd(), "src/assets/styles.css"), "utf-8");
const loginVisual = cssBlock(".login-visual");
assertIncludes(loginVisual, "background: var(--surface-soft);");
assertIncludes(loginVisual, "color: var(--text);");
assertNotIncludes(loginVisual, "rgba(var(--primary-rgb), 0.94)");
const ledgerVisual = cssBlock(".ledger-visual");
assertIncludes(ledgerVisual, "background: var(--card);");
assertIncludes(ledgerVisual, "padding: 32px;");
const appearancePanel = cssBlock(".appearance-panel");
assertIncludes(appearancePanel, "width: min(480px, calc(100vw - 20px));");
function cssBlock(selector: string): string {
const pattern = new RegExp(`${escapeRegExp(selector)}\\s*\\{([\\s\\S]*?)\\n\\}`, "m");
const match = css.match(pattern);
if (!match) {
throw new Error(`缺少样式块 ${selector}`);
}
return match[1];
}
function assertIncludes(content: string, expected: string): void {
if (!content.includes(expected)) {
throw new Error(`期望包含 ${expected}`);
}
}
function assertNotIncludes(content: string, unexpected: string): void {
if (content.includes(unexpected)) {
throw new Error(`不应包含 ${unexpected}`);
}
}
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}