feat(admin-portal): 完成参考项目差距闭环 - 4 批次补齐 + Vitest 测试
差距分析闭环(workline §7-§8): - P0:审计子模块 3 页 + 学校组织 7 页 - P1:系统设置 4 Card + 公告管理 + 邀请码管理 - P2:文件管理 + AI 配置 - P6:5 测试文件 / 69 用例全过 共享基础设施: - permissions +11 权限点 +14 路由 - view-models +20 接口 - i18n +100 key - graphql-client +25 operation - fixtures/handlers +15 mock +20 handler 质量:typecheck + lint 零错误,vitest 69/69 通过,arch.db 已更新
This commit is contained in:
@@ -17,6 +17,25 @@ import type {
|
||||
AdminDashboardViewModel,
|
||||
SystemSettingsViewModel,
|
||||
CurrentUser,
|
||||
SchoolViewModel,
|
||||
GradeViewModel,
|
||||
GradeInsightsViewModel,
|
||||
DepartmentViewModel,
|
||||
AcademicYearViewModel,
|
||||
AuditOverviewStats,
|
||||
AuditTrendPoint,
|
||||
DataChangeLogViewModel,
|
||||
LoginLogViewModel,
|
||||
AnnouncementViewModel,
|
||||
InvitationCodeViewModel,
|
||||
FileViewModel,
|
||||
FileStats,
|
||||
AiProviderViewModel,
|
||||
AiUsageViewModel,
|
||||
SecurityPolicy,
|
||||
FileUploadConfig,
|
||||
NotificationConfig,
|
||||
BrandConfig,
|
||||
} from "@/types/view-models";
|
||||
|
||||
export const mockCurrentUser: CurrentUser = {
|
||||
@@ -904,3 +923,712 @@ export const mockSystemSettings: SystemSettingsViewModel = {
|
||||
export function genId(prefix: string): string {
|
||||
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
||||
}
|
||||
|
||||
// ─── 学校组织管理细化 ──────────────────────────────────────────────
|
||||
|
||||
export const mockSchools: SchoolViewModel[] = [
|
||||
{
|
||||
id: "sch-001",
|
||||
name: "Edu 实验学校",
|
||||
code: "EDU-001",
|
||||
address: "北京市海淀区中关村大街 1 号",
|
||||
contactPhone: "010-88888888",
|
||||
contactEmail: "contact@edu.test",
|
||||
principalName: "张校长",
|
||||
gradeCount: 6,
|
||||
classCount: 24,
|
||||
studentCount: 1200,
|
||||
teacherCount: 80,
|
||||
createdAt: Date.now() - 86400000 * 365,
|
||||
},
|
||||
{
|
||||
id: "sch-002",
|
||||
name: "Edu 附属中学",
|
||||
code: "EDU-002",
|
||||
address: "北京市西城区西长安街 2 号",
|
||||
contactPhone: "010-66666666",
|
||||
contactEmail: "fz@edu.test",
|
||||
principalName: "李校长",
|
||||
gradeCount: 3,
|
||||
classCount: 18,
|
||||
studentCount: 900,
|
||||
teacherCount: 60,
|
||||
createdAt: Date.now() - 86400000 * 300,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockGrades: GradeViewModel[] = [
|
||||
{
|
||||
id: "grd-001",
|
||||
name: "一年级",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
directorName: "王主任",
|
||||
classCount: 4,
|
||||
studentCount: 200,
|
||||
sortOrder: 1,
|
||||
createdAt: Date.now() - 86400000 * 300,
|
||||
},
|
||||
{
|
||||
id: "grd-002",
|
||||
name: "二年级",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
directorName: "刘主任",
|
||||
classCount: 4,
|
||||
studentCount: 210,
|
||||
sortOrder: 2,
|
||||
createdAt: Date.now() - 86400000 * 300,
|
||||
},
|
||||
{
|
||||
id: "grd-003",
|
||||
name: "三年级",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
directorName: "陈主任",
|
||||
classCount: 4,
|
||||
studentCount: 195,
|
||||
sortOrder: 3,
|
||||
createdAt: Date.now() - 86400000 * 300,
|
||||
},
|
||||
{
|
||||
id: "grd-004",
|
||||
name: "初一",
|
||||
schoolId: "sch-002",
|
||||
schoolName: "Edu 附属中学",
|
||||
directorName: "赵主任",
|
||||
classCount: 6,
|
||||
studentCount: 300,
|
||||
sortOrder: 1,
|
||||
createdAt: Date.now() - 86400000 * 250,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockGradeInsights: GradeInsightsViewModel = {
|
||||
gradeId: "grd-001",
|
||||
gradeName: "一年级",
|
||||
schoolWideSummary: {
|
||||
totalStudents: 1200,
|
||||
totalClasses: 24,
|
||||
avgScore: 82.5,
|
||||
passingRate: 0.95,
|
||||
},
|
||||
homeworkTimeline: [
|
||||
{
|
||||
homeworkId: "hw-001",
|
||||
title: "数学练习一",
|
||||
className: "一班",
|
||||
avgScore: 85,
|
||||
submittedCount: 48,
|
||||
totalCount: 50,
|
||||
dueDate: "2026-07-10",
|
||||
},
|
||||
{
|
||||
homeworkId: "hw-002",
|
||||
title: "语文阅读",
|
||||
className: "二班",
|
||||
avgScore: 78,
|
||||
submittedCount: 45,
|
||||
totalCount: 50,
|
||||
dueDate: "2026-07-11",
|
||||
},
|
||||
{
|
||||
homeworkId: "hw-003",
|
||||
title: "英语听力",
|
||||
className: "三班",
|
||||
avgScore: 82,
|
||||
submittedCount: 50,
|
||||
totalCount: 50,
|
||||
dueDate: "2026-07-12",
|
||||
},
|
||||
{
|
||||
homeworkId: "hw-004",
|
||||
title: "数学练习二",
|
||||
className: "四班",
|
||||
avgScore: 88,
|
||||
submittedCount: 47,
|
||||
totalCount: 50,
|
||||
dueDate: "2026-07-13",
|
||||
},
|
||||
],
|
||||
classRankings: [
|
||||
{
|
||||
classId: "cls-001",
|
||||
className: "一班",
|
||||
avgScore: 85.2,
|
||||
rank: 1,
|
||||
delta: 2.1,
|
||||
},
|
||||
{
|
||||
classId: "cls-002",
|
||||
className: "四班",
|
||||
avgScore: 83.8,
|
||||
rank: 2,
|
||||
delta: -0.5,
|
||||
},
|
||||
{
|
||||
classId: "cls-003",
|
||||
className: "二班",
|
||||
avgScore: 81.5,
|
||||
rank: 3,
|
||||
delta: 1.3,
|
||||
},
|
||||
{
|
||||
classId: "cls-004",
|
||||
className: "三班",
|
||||
avgScore: 79.6,
|
||||
rank: 4,
|
||||
delta: -1.2,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const mockDepartments: DepartmentViewModel[] = [
|
||||
{
|
||||
id: "dept-001",
|
||||
name: "数学教研组",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
leaderName: "王老师",
|
||||
memberCount: 12,
|
||||
subject: "数学",
|
||||
createdAt: Date.now() - 86400000 * 200,
|
||||
},
|
||||
{
|
||||
id: "dept-002",
|
||||
name: "语文教研组",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
leaderName: "李老师",
|
||||
memberCount: 10,
|
||||
subject: "语文",
|
||||
createdAt: Date.now() - 86400000 * 200,
|
||||
},
|
||||
{
|
||||
id: "dept-003",
|
||||
name: "英语教研组",
|
||||
schoolId: "sch-001",
|
||||
schoolName: "Edu 实验学校",
|
||||
leaderName: "张老师",
|
||||
memberCount: 8,
|
||||
subject: "英语",
|
||||
createdAt: Date.now() - 86400000 * 200,
|
||||
},
|
||||
{
|
||||
id: "dept-004",
|
||||
name: "理科教研组",
|
||||
schoolId: "sch-002",
|
||||
schoolName: "Edu 附属中学",
|
||||
leaderName: "赵老师",
|
||||
memberCount: 15,
|
||||
subject: "物理",
|
||||
createdAt: Date.now() - 86400000 * 180,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockAcademicYears: AcademicYearViewModel[] = [
|
||||
{
|
||||
id: "ay-001",
|
||||
name: "2025-2026学年",
|
||||
startDate: "2025-09-01",
|
||||
endDate: "2026-07-15",
|
||||
firstSemesterStart: "2025-09-01",
|
||||
firstSemesterEnd: "2026-01-15",
|
||||
secondSemesterStart: "2026-02-15",
|
||||
secondSemesterEnd: "2026-07-15",
|
||||
isCurrent: true,
|
||||
createdAt: Date.now() - 86400000 * 300,
|
||||
},
|
||||
{
|
||||
id: "ay-002",
|
||||
name: "2024-2025学年",
|
||||
startDate: "2024-09-01",
|
||||
endDate: "2025-07-15",
|
||||
firstSemesterStart: "2024-09-01",
|
||||
firstSemesterEnd: "2025-01-15",
|
||||
secondSemesterStart: "2025-02-15",
|
||||
secondSemesterEnd: "2025-07-15",
|
||||
isCurrent: false,
|
||||
createdAt: Date.now() - 86400000 * 665,
|
||||
},
|
||||
];
|
||||
|
||||
// ─── 审计日志子模块 ─────────────────────────────────────────────────
|
||||
|
||||
export const mockAuditOverviewStats: AuditOverviewStats = {
|
||||
totalEvents: 15420,
|
||||
todayEvents: 86,
|
||||
uniqueActors: 142,
|
||||
failedActions: 23,
|
||||
topActions: [
|
||||
{ action: "USER_LOGIN", count: 3200 },
|
||||
{ action: "USER_CREATE", count: 156 },
|
||||
{ action: "USER_UPDATE", count: 892 },
|
||||
{ action: "ROLE_UPDATE", count: 45 },
|
||||
{ action: "SYSTEM_SETTINGS_UPDATE", count: 12 },
|
||||
],
|
||||
topResources: [
|
||||
{ resource: "user", count: 4200 },
|
||||
{ resource: "role", count: 380 },
|
||||
{ resource: "viewport", count: 120 },
|
||||
{ resource: "system_settings", count: 45 },
|
||||
],
|
||||
};
|
||||
|
||||
export const mockAuditTrend: AuditTrendPoint[] = Array.from(
|
||||
{ length: 7 },
|
||||
(_, i) => {
|
||||
const d = new Date();
|
||||
d.setDate(d.getDate() - (6 - i));
|
||||
return {
|
||||
date: d.toISOString().slice(0, 10),
|
||||
count: Math.floor(50 + Math.random() * 50),
|
||||
action: "USER_LOGIN",
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export const mockDataChangeLogs: DataChangeLogViewModel[] = [
|
||||
{
|
||||
id: "dcl-001",
|
||||
occurredAt: Date.now() - 3600000,
|
||||
actorUserId: "u-admin-001",
|
||||
actorName: "系统管理员",
|
||||
tableName: "users",
|
||||
action: "create",
|
||||
recordId: "u-006",
|
||||
beforeState: null,
|
||||
afterState: '{"email":"new@edu.test","name":"新用户"}',
|
||||
ip: "192.168.1.1",
|
||||
},
|
||||
{
|
||||
id: "dcl-002",
|
||||
occurredAt: Date.now() - 7200000,
|
||||
actorUserId: "u-admin-001",
|
||||
actorName: "系统管理员",
|
||||
tableName: "roles",
|
||||
action: "update",
|
||||
recordId: "r-002",
|
||||
beforeState: '{"name":"教师"}',
|
||||
afterState: '{"name":"教师","permissions":["READ","WRITE"]}',
|
||||
ip: "192.168.1.1",
|
||||
},
|
||||
{
|
||||
id: "dcl-003",
|
||||
occurredAt: Date.now() - 10800000,
|
||||
actorUserId: "u-admin-001",
|
||||
actorName: "系统管理员",
|
||||
tableName: "users",
|
||||
action: "delete",
|
||||
recordId: "u-005",
|
||||
beforeState: '{"email":"old@edu.test"}',
|
||||
afterState: null,
|
||||
ip: "192.168.1.1",
|
||||
},
|
||||
{
|
||||
id: "dcl-004",
|
||||
occurredAt: Date.now() - 14400000,
|
||||
actorUserId: "u-admin-001",
|
||||
actorName: "系统管理员",
|
||||
tableName: "viewports",
|
||||
action: "update",
|
||||
recordId: "v-001",
|
||||
beforeState: '{"sortOrder":1}',
|
||||
afterState: '{"sortOrder":2}',
|
||||
ip: "192.168.1.1",
|
||||
},
|
||||
{
|
||||
id: "dcl-005",
|
||||
occurredAt: Date.now() - 18000000,
|
||||
actorUserId: "u-admin-001",
|
||||
actorName: "系统管理员",
|
||||
tableName: "system_settings",
|
||||
action: "update",
|
||||
recordId: "settings",
|
||||
beforeState: '{"schoolName":"旧名称"}',
|
||||
afterState: '{"schoolName":"Edu 实验学校"}',
|
||||
ip: "192.168.1.1",
|
||||
},
|
||||
];
|
||||
|
||||
export const mockLoginLogs: LoginLogViewModel[] = [
|
||||
{
|
||||
id: "ll-001",
|
||||
occurredAt: Date.now() - 1800000,
|
||||
userId: "u-admin-001",
|
||||
userName: "系统管理员",
|
||||
action: "signin",
|
||||
status: "success",
|
||||
ip: "192.168.1.1",
|
||||
userAgent: "Chrome/126.0",
|
||||
failureReason: null,
|
||||
},
|
||||
{
|
||||
id: "ll-002",
|
||||
occurredAt: Date.now() - 3600000,
|
||||
userId: "u-002",
|
||||
userName: "王老师",
|
||||
action: "signin",
|
||||
status: "success",
|
||||
ip: "10.0.0.5",
|
||||
userAgent: "Firefox/127.0",
|
||||
failureReason: null,
|
||||
},
|
||||
{
|
||||
id: "ll-003",
|
||||
occurredAt: Date.now() - 5400000,
|
||||
userId: "unknown",
|
||||
userName: "unknown",
|
||||
action: "signin",
|
||||
status: "failure",
|
||||
ip: "203.0.113.5",
|
||||
userAgent: "curl/8.0",
|
||||
failureReason: "密码错误",
|
||||
},
|
||||
{
|
||||
id: "ll-004",
|
||||
occurredAt: Date.now() - 7200000,
|
||||
userId: "u-003",
|
||||
userName: "李老师",
|
||||
action: "signout",
|
||||
status: "success",
|
||||
ip: "10.0.0.8",
|
||||
userAgent: "Chrome/126.0",
|
||||
failureReason: null,
|
||||
},
|
||||
{
|
||||
id: "ll-005",
|
||||
occurredAt: Date.now() - 9000000,
|
||||
userId: "u-006",
|
||||
userName: "新用户",
|
||||
action: "signup",
|
||||
status: "success",
|
||||
ip: "10.0.0.12",
|
||||
userAgent: "Safari/17.0",
|
||||
failureReason: null,
|
||||
},
|
||||
{
|
||||
id: "ll-006",
|
||||
occurredAt: Date.now() - 10800000,
|
||||
userId: "unknown",
|
||||
userName: "unknown",
|
||||
action: "signin",
|
||||
status: "failure",
|
||||
ip: "198.51.100.1",
|
||||
userAgent: "bot/1.0",
|
||||
failureReason: "账户锁定",
|
||||
},
|
||||
];
|
||||
|
||||
// ─── 公告管理 ───────────────────────────────────────────────────────
|
||||
|
||||
export const mockAnnouncements: AnnouncementViewModel[] = [
|
||||
{
|
||||
id: "ann-001",
|
||||
title: "2026年春季学期开学通知",
|
||||
content:
|
||||
"各位师生:2026年春季学期将于2月15日正式开学,请提前做好准备工作。",
|
||||
status: "published",
|
||||
audience: ["all"],
|
||||
authorName: "系统管理员",
|
||||
isPinned: true,
|
||||
readCount: 1150,
|
||||
totalCount: 1200,
|
||||
publishedAt: Date.now() - 86400000 * 3,
|
||||
createdAt: Date.now() - 86400000 * 5,
|
||||
updatedAt: Date.now() - 86400000 * 3,
|
||||
},
|
||||
{
|
||||
id: "ann-002",
|
||||
title: "期中考试安排",
|
||||
content: "期中考试将于第10周进行,具体安排另行通知。",
|
||||
status: "published",
|
||||
audience: ["teachers", "students"],
|
||||
authorName: "系统管理员",
|
||||
isPinned: false,
|
||||
readCount: 800,
|
||||
totalCount: 1280,
|
||||
publishedAt: Date.now() - 86400000 * 2,
|
||||
createdAt: Date.now() - 86400000 * 4,
|
||||
updatedAt: Date.now() - 86400000 * 2,
|
||||
},
|
||||
{
|
||||
id: "ann-003",
|
||||
title: "家长会通知(草稿)",
|
||||
content: "定于下周六召开家长会,具体时间待定。",
|
||||
status: "draft",
|
||||
audience: ["parents"],
|
||||
authorName: "系统管理员",
|
||||
isPinned: false,
|
||||
readCount: 0,
|
||||
totalCount: 0,
|
||||
publishedAt: null,
|
||||
createdAt: Date.now() - 86400000,
|
||||
updatedAt: Date.now() - 86400000,
|
||||
},
|
||||
{
|
||||
id: "ann-004",
|
||||
title: "寒假放假通知",
|
||||
content: "寒假时间为1月16日至2月14日。",
|
||||
status: "archived",
|
||||
audience: ["all"],
|
||||
authorName: "系统管理员",
|
||||
isPinned: false,
|
||||
readCount: 1190,
|
||||
totalCount: 1200,
|
||||
publishedAt: Date.now() - 86400000 * 30,
|
||||
createdAt: Date.now() - 86400000 * 32,
|
||||
updatedAt: Date.now() - 86400000 * 25,
|
||||
},
|
||||
];
|
||||
|
||||
// ─── 邀请码管理 ─────────────────────────────────────────────────────
|
||||
|
||||
export const mockInvitationCodes: InvitationCodeViewModel[] = [
|
||||
{
|
||||
id: "ic-001",
|
||||
code: "AB3D7F9H",
|
||||
status: "unused",
|
||||
roleId: "r-001",
|
||||
roleName: "教师",
|
||||
classId: null,
|
||||
className: null,
|
||||
email: null,
|
||||
batchId: "bat-001",
|
||||
usedBy: null,
|
||||
usedByName: null,
|
||||
usedAt: null,
|
||||
createdAt: Date.now() - 86400000,
|
||||
expiresAt: Date.now() + 86400000 * 30,
|
||||
},
|
||||
{
|
||||
id: "ic-002",
|
||||
code: "JC5K8M2P",
|
||||
status: "unused",
|
||||
roleId: "r-002",
|
||||
roleName: "学生",
|
||||
classId: "cls-001",
|
||||
className: "一年级一班",
|
||||
email: null,
|
||||
batchId: "bat-001",
|
||||
usedBy: null,
|
||||
usedByName: null,
|
||||
usedAt: null,
|
||||
createdAt: Date.now() - 86400000,
|
||||
expiresAt: Date.now() + 86400000 * 30,
|
||||
},
|
||||
{
|
||||
id: "ic-003",
|
||||
code: "QR7S4T6V",
|
||||
status: "used",
|
||||
roleId: "r-003",
|
||||
roleName: "家长",
|
||||
classId: null,
|
||||
className: null,
|
||||
email: "parent@edu.test",
|
||||
batchId: "bat-001",
|
||||
usedBy: "u-007",
|
||||
usedByName: "张家长",
|
||||
usedAt: Date.now() - 3600000,
|
||||
createdAt: Date.now() - 86400000,
|
||||
expiresAt: Date.now() + 86400000 * 30,
|
||||
},
|
||||
{
|
||||
id: "ic-004",
|
||||
code: "WX9Y2Z4B",
|
||||
status: "expired",
|
||||
roleId: null,
|
||||
roleName: null,
|
||||
classId: null,
|
||||
className: null,
|
||||
email: null,
|
||||
batchId: "bat-000",
|
||||
usedBy: null,
|
||||
usedByName: null,
|
||||
usedAt: null,
|
||||
createdAt: Date.now() - 86400000 * 60,
|
||||
expiresAt: Date.now() - 86400000 * 30,
|
||||
},
|
||||
];
|
||||
|
||||
// ─── 文件管理 ───────────────────────────────────────────────────────
|
||||
|
||||
export const mockFiles: FileViewModel[] = [
|
||||
{
|
||||
id: "file-001",
|
||||
filename: "期中考试试卷.pdf",
|
||||
mimeType: "application/pdf",
|
||||
size: 1024000,
|
||||
url: "/files/exam-mid.pdf",
|
||||
entityType: "exam",
|
||||
entityId: "exam-001",
|
||||
uploadedByName: "王老师",
|
||||
createdAt: Date.now() - 86400000 * 3,
|
||||
},
|
||||
{
|
||||
id: "file-002",
|
||||
filename: "数学课件.pptx",
|
||||
mimeType:
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
size: 5120000,
|
||||
url: "/files/math.pptx",
|
||||
entityType: "lesson_plan",
|
||||
entityId: "lp-001",
|
||||
uploadedByName: "李老师",
|
||||
createdAt: Date.now() - 86400000 * 2,
|
||||
},
|
||||
{
|
||||
id: "file-003",
|
||||
filename: "学生头像.jpg",
|
||||
mimeType: "image/jpeg",
|
||||
size: 256000,
|
||||
url: "/files/avatar.jpg",
|
||||
entityType: "user_avatar",
|
||||
entityId: "u-005",
|
||||
uploadedByName: "系统管理员",
|
||||
createdAt: Date.now() - 86400000,
|
||||
},
|
||||
{
|
||||
id: "file-004",
|
||||
filename: "开学通知.docx",
|
||||
mimeType:
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
size: 89000,
|
||||
url: "/files/notice.docx",
|
||||
entityType: "announcement",
|
||||
entityId: "ann-001",
|
||||
uploadedByName: "系统管理员",
|
||||
createdAt: Date.now() - 86400000 * 5,
|
||||
},
|
||||
{
|
||||
id: "file-005",
|
||||
filename: "成绩统计.xlsx",
|
||||
mimeType:
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
size: 348000,
|
||||
url: "/files/grades.xlsx",
|
||||
entityType: "homework",
|
||||
entityId: "hw-001",
|
||||
uploadedByName: "王老师",
|
||||
createdAt: Date.now() - 86400000 * 7,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockFileStats: FileStats = {
|
||||
totalFiles: 348,
|
||||
totalSize: 2840000000,
|
||||
byMimeType: [
|
||||
{ mimeType: "application/pdf", count: 85, size: 95000000 },
|
||||
{ mimeType: "image/jpeg", count: 120, size: 340000000 },
|
||||
{
|
||||
mimeType:
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
count: 45,
|
||||
size: 12000000,
|
||||
},
|
||||
{
|
||||
mimeType:
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
count: 30,
|
||||
size: 8900000,
|
||||
},
|
||||
{ mimeType: "video/mp4", count: 12, size: 2300000000 },
|
||||
],
|
||||
byEntityType: [
|
||||
{ entityType: "exam", count: 85 },
|
||||
{ entityType: "lesson_plan", count: 60 },
|
||||
{ entityType: "user_avatar", count: 120 },
|
||||
{ entityType: "announcement", count: 25 },
|
||||
{ entityType: "homework", count: 58 },
|
||||
],
|
||||
};
|
||||
|
||||
// ─── AI 配置 ─────────────────────────────────────────────────────────
|
||||
|
||||
export const mockAiProviders: AiProviderViewModel[] = [
|
||||
{
|
||||
id: "aip-001",
|
||||
name: "OpenAI",
|
||||
type: "openai",
|
||||
isPublic: true,
|
||||
isActive: true,
|
||||
model: "gpt-4o",
|
||||
apiBase: "https://api.openai.com/v1",
|
||||
createdBy: "系统管理员",
|
||||
createdAt: Date.now() - 86400000 * 30,
|
||||
},
|
||||
{
|
||||
id: "aip-002",
|
||||
name: "通义千问",
|
||||
type: "qwen",
|
||||
isPublic: true,
|
||||
isActive: true,
|
||||
model: "qwen-max",
|
||||
apiBase: "https://dashscope.aliyuncs.com/api/v1",
|
||||
createdBy: "系统管理员",
|
||||
createdAt: Date.now() - 86400000 * 20,
|
||||
},
|
||||
{
|
||||
id: "aip-003",
|
||||
name: "个人 DeepSeek",
|
||||
type: "deepseek",
|
||||
isPublic: false,
|
||||
isActive: false,
|
||||
model: "deepseek-chat",
|
||||
apiBase: "https://api.deepseek.com/v1",
|
||||
createdBy: "王老师",
|
||||
createdAt: Date.now() - 86400000 * 10,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockAiUsage: AiUsageViewModel = {
|
||||
totalRequests: 12580,
|
||||
totalTokens: 4520000,
|
||||
totalCost: 68.5,
|
||||
byProvider: [
|
||||
{ providerName: "OpenAI", requests: 8200, tokens: 3200000, cost: 52.3 },
|
||||
{ providerName: "通义千问", requests: 3380, tokens: 1100000, cost: 12.8 },
|
||||
{
|
||||
providerName: "个人 DeepSeek",
|
||||
requests: 1000,
|
||||
tokens: 220000,
|
||||
cost: 3.4,
|
||||
},
|
||||
],
|
||||
byDay: Array.from({ length: 7 }, (_, i) => {
|
||||
const d = new Date();
|
||||
d.setDate(d.getDate() - (6 - i));
|
||||
return {
|
||||
date: d.toISOString().slice(0, 10),
|
||||
requests: Math.floor(800 + Math.random() * 400),
|
||||
tokens: Math.floor(300000 + Math.random() * 200000),
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
// ─── 增强系统设置 ───────────────────────────────────────────────────
|
||||
|
||||
export const mockSecurityPolicy: SecurityPolicy = {
|
||||
passwordMinLength: 8,
|
||||
passwordRequireSpecial: true,
|
||||
passwordRequireUppercase: true,
|
||||
sessionTimeoutMinutes: 30,
|
||||
forcePasswordChange: false,
|
||||
};
|
||||
|
||||
export const mockFileUploadConfig: FileUploadConfig = {
|
||||
maxFileSize: 50,
|
||||
allowedTypes: ["pdf", "jpg", "jpeg", "png", "docx", "xlsx", "pptx", "mp4"],
|
||||
};
|
||||
|
||||
export const mockNotificationConfig: NotificationConfig = {
|
||||
notifyNewUser: true,
|
||||
notifyScheduleChange: true,
|
||||
notifyAnnouncement: false,
|
||||
};
|
||||
|
||||
export const mockBrandConfig: BrandConfig = {
|
||||
logoUrl: "/logo.png",
|
||||
primaryColor: "#1a56db",
|
||||
schoolMotto: "博学笃行,求实创新",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user