6cefa620e4
重新设计权限系统所有 UI 组件的视觉风格,统一配色、圆角、阴影和交互动效: - 实时概览:统计卡片加图标和渐变色条,健康评分改为环形进度,告警改为卡片式 - 趋势分析:图表卡片加彩色图标标识,ECharts 配色升级为渐变面积填充 - 访问日志:指标卡片带图标,日志审计改为卡片式入口,IP排行前三高亮 - IP属地:工具栏重设计,排行列表前三渐变高亮,指标卡片统一新风格 - 系统级权限:从 el-table 改为自定义卡片列表,模块块独立圆角卡片 - 项目权限配置:空状态引导优化,成员表格加头像,工具栏加背景容器 - 角色概览卡片:加进度条可视化,hover 微动效 - 接口权限矩阵:工具栏分离布局,表格圆角包裹 - 角色管理抽屉:侧边栏选中态渐变,操作行 hover 高亮 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
84 lines
2.9 KiB
TypeScript
84 lines
2.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const readView = (relativePath: string) =>
|
|
readFileSync(resolve(__dirname, relativePath), "utf8");
|
|
|
|
const normalizeWhitespace = (source: string) => source.replace(/\s+/g, " ").trim();
|
|
|
|
describe("route view overlays are mounted only when visible", () => {
|
|
it("gates high-risk admin and subject overlays behind visible flags", () => {
|
|
const checks = [
|
|
{
|
|
file: "./admin/ProjectMembers.vue",
|
|
snippets: ['<el-dialog v-if="addVisible"', 'v-model="addVisible"'],
|
|
},
|
|
{
|
|
file: "./admin/Sites.vue",
|
|
snippets: ['<SiteForm', 'v-if="projectId && formVisible"'],
|
|
},
|
|
{
|
|
file: "./admin/SiteForm.vue",
|
|
snippets: ['<el-dialog v-if="visibleProxy"', 'v-model="visibleProxy"'],
|
|
},
|
|
{
|
|
file: "./admin/SiteCraBinding.vue",
|
|
snippets: ['<el-dialog v-if="visibleProxy"', 'v-model="visibleProxy"'],
|
|
},
|
|
{
|
|
file: "./subjects/SubjectDetail.vue",
|
|
snippets: [
|
|
'<el-dialog v-if="historyDialogVisible"',
|
|
'<el-dialog v-if="visitDialogVisible"',
|
|
'<el-dialog v-if="aeDialogVisible"',
|
|
'<el-dialog v-if="pdDialogVisible"',
|
|
],
|
|
},
|
|
{
|
|
file: "./ia/ProjectMilestones.vue",
|
|
snippets: ['<el-drawer v-if="editorVisible"', 'v-model="editorVisible"'],
|
|
},
|
|
{
|
|
file: "./ia/MaterialEquipment.vue",
|
|
snippets: ['<el-drawer v-if="drawerVisible"', 'v-model="drawerVisible"'],
|
|
},
|
|
{
|
|
file: "./ia/RiskIssueMonitoringVisits.vue",
|
|
snippets: [
|
|
'<el-drawer v-if="formDialogVisible"',
|
|
'v-model="formDialogVisible"',
|
|
'<el-dialog v-if="viewDialogVisible"',
|
|
'v-model="viewDialogVisible"',
|
|
],
|
|
},
|
|
{
|
|
file: "../components/attachments/AttachmentList.vue",
|
|
snippets: ['<el-dialog v-if="previewVisible"', 'append-to-body', 'v-model="previewVisible"'],
|
|
},
|
|
{
|
|
file: "./admin/ProjectDetail.vue",
|
|
snippets: [
|
|
'<el-dialog v-if="publishConfirmVisible"',
|
|
'v-model="publishConfirmVisible"',
|
|
'v-if="rollbackDialogVisible"',
|
|
'v-model="rollbackDialogVisible"',
|
|
'<el-drawer v-if="projectMilestoneEditorVisible"',
|
|
'<el-drawer v-if="siteMilestoneEditorVisible"',
|
|
'<el-drawer v-if="siteEnrollmentEditorVisible"',
|
|
'const getRollbackAxisLeftStyle = (axisX?: number | null) => ({',
|
|
':style="getRollbackAxisLeftStyle(lane.x)"',
|
|
':style="getRollbackAxisLeftStyle(row.axisX)"',
|
|
],
|
|
},
|
|
];
|
|
|
|
for (const check of checks) {
|
|
const source = normalizeWhitespace(readView(check.file));
|
|
for (const snippet of check.snippets) {
|
|
expect(source, `${check.file} should include ${snippet}`).toContain(normalizeWhitespace(snippet));
|
|
}
|
|
}
|
|
});
|
|
});
|