Files
Edu/apps/portal-shell/src/features/admin/lesson-plans/transformations.ts
SpecialX f991bf0446 feat(portal-shell): 管理域全模块功能补齐与差异修复
按 ARCHITECTURE.md 与 admin-NeedTodo.md 要求补齐所有管理页面缺失功能:
- users/roles/permissions:权限矩阵搜索/折叠、zod 校验、value 字段
- audit-logs:行内详情对话框、分页页码、ChartCardShell
- school:CRUD 对话框、GradeOverviewCards、academic-year 侧栏
- announcements/invitation-codes/ai-settings:发布按钮、分页、zod 校验
- course-plans/elective:Select 导入、undefined 处理
- error-book/scheduling/questions/lesson-plans/attendance:统计卡片

验证:typecheck 0 错误、arch:scan 已更新
2026-07-30 17:49:49 +08:00

126 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Admin Lesson Plans 数据变换工具ARCHITECTURE.md §11.3 DoD - 纯函数单测)
*
* 所有格式化/映射函数均为纯函数,便于 vitest 单测。
* 关联ARCHITECTURE.md §11.3 DoD "数据变换/权限判断等纯函数有 vitest 单测"
*/
import type { AdminLessonPlanListItem } from "@/lib/api/admin-p5";
/** 教案状态中文标签映射 */
export const LESSON_PLAN_STATUS_LABEL: Record<string, string> = {
DRAFT: "草稿",
PUBLISHED: "已发布",
ARCHIVED: "已归档",
SUBMITTED: "已提交",
};
/**
* 将教案状态枚举值映射为中文标签。
* 未知状态回退为原始值。
*/
export function formatLessonPlanStatus(status: string): string {
return LESSON_PLAN_STATUS_LABEL[status] ?? status;
}
/**
* 格式化 ISO 日期字符串为本地化展示zh-CN含年月日时分
* 输入无效null/undefined/空/非法)时返回占位符 "--"。
*/
export function formatLessonPlanDate(
isoDate: string | null | undefined,
): string {
if (!isoDate) return "--";
const d = new Date(isoDate);
if (Number.isNaN(d.getTime())) return "--";
return d.toLocaleString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
});
}
/**
* 判断教案是否可编辑(草稿与已发布状态允许编辑,归档后不可编辑)。
*/
export function isLessonPlanEditable(status: string): boolean {
return status === "DRAFT" || status === "PUBLISHED";
}
/**
* 判断教案是否已发布PUBLISHED
*/
export function isLessonPlanPublished(status: string): boolean {
return status === "PUBLISHED";
}
/**
* 判断教案是否已归档ARCHIVED
*/
export function isLessonPlanArchived(status: string): boolean {
return status === "ARCHIVED";
}
/**
* 从教案详情中提取列表项视图模型(裁剪字段)。
*
* 用于详情→列表裁剪场景详情字段textbookId/chapterId/content 等)被剥离。
*/
export function toAdminLessonPlanListItem(detail: {
id: string;
title: string;
subjectId: string;
subjectName: string;
teacherId: string;
teacherName: string;
classId: string;
className: string;
status: string;
createdAt: string;
updatedAt: string;
}): AdminLessonPlanListItem {
return {
id: detail.id,
title: detail.title,
subjectId: detail.subjectId,
subjectName: detail.subjectName,
teacherId: detail.teacherId,
teacherName: detail.teacherName,
classId: detail.classId,
className: detail.className,
status: detail.status,
createdAt: detail.createdAt,
updatedAt: detail.updatedAt,
};
}
/**
* 格式化数量为展示字符串。
* 输入无效null/undefined/NaN/负数)返回 "0"。
*/
export function formatCount(count: number | null | undefined): string {
if (count === null || count === undefined) return "0";
if (!Number.isFinite(count) || count < 0) return "0";
return `${count}`;
}
/**
* 根据教案状态返回 Tailwind 徽章语义类名。
*/
export function lessonPlanStatusToBadgeClass(status: string): string {
switch (status) {
case "DRAFT":
return "bg-muted text-muted-foreground";
case "PUBLISHED":
return "bg-primary/10 text-primary";
case "ARCHIVED":
return "bg-muted text-muted-foreground";
case "SUBMITTED":
return "bg-amber-500/10 text-amber-600 dark:text-amber-400";
default:
return "bg-muted text-muted-foreground";
}
}