feat: 完善学生生命周期管理与权限范围并发布 1.4.2
This commit is contained in:
1 parent
6347d1e5aa
commit
24e8dd902b
92 files changed
+6801
-2255
No files matched your search
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@classhelper/shared",
|
||||
"version": "1.4.1",
|
||||
"version": "1.4.2",
|
||||
"private": true,
|
||||
"description": "ClassHelper - 三端共享的类型、常量与工具函数",
|
||||
"type": "module",
|
||||
|
||||
@@ -10,3 +10,4 @@ export * from './class-plan.js';
|
||||
export * from './island-layout.js';
|
||||
export type * from './types.js';
|
||||
export * from './courseware.js';
|
||||
export * from './lifecycle.js';
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { PermissionScope } from './class-plan.js';
|
||||
|
||||
/** 范围解析供保存、查询与展示共用;旧库空岗位范围会由调用方拒绝访问。 */
|
||||
export function parsePermissionScope(scope: PermissionScope, value = '', knownGrades?: readonly string[]) {
|
||||
if (scope === 'ALL') return { scope, scopeValue: '', grades: [], scopeLabel: '全校' };
|
||||
if (scope === 'SELF_CLASS') {
|
||||
if (value !== '' && value !== 'HEAD') throw new Error('关联班级范围只允许全部关联班级或仅班主任班');
|
||||
return {
|
||||
scope,
|
||||
scopeValue: value,
|
||||
grades: [],
|
||||
scopeLabel: value === 'HEAD' ? '仅班主任班' : '班主任与任课班级',
|
||||
};
|
||||
}
|
||||
if (scope !== 'GRADE' && scope !== 'DIVISION') throw new Error('未知的数据范围');
|
||||
const grades = [...new Set(value.split(/[,,、\s]+/u).filter(Boolean))].sort();
|
||||
if (!grades.length) throw new Error('请选择范围中的年级');
|
||||
if (scope === 'GRADE' && grades.length !== 1) throw new Error('年级范围只能选择一个年级');
|
||||
if (knownGrades && grades.some((grade) => !knownGrades.includes(grade)))
|
||||
throw new Error('范围包含未知年级,请刷新选项');
|
||||
return {
|
||||
scope,
|
||||
scopeValue: grades.join(','),
|
||||
grades,
|
||||
scopeLabel: `${scope === 'GRADE' ? '年级' : '部'}:${grades.join('、')}`,
|
||||
};
|
||||
}
|
||||
|
||||
export interface PromotionPlan {
|
||||
tracks: {
|
||||
id: string;
|
||||
name: string;
|
||||
entryClassCount: number;
|
||||
stages: { grade: string; terminal?: boolean }[];
|
||||
}[];
|
||||
termStartDate: string | null;
|
||||
resetTermWeeks: boolean;
|
||||
}
|
||||
export function defaultPromotionPlan(classCount = 1): PromotionPlan {
|
||||
return {
|
||||
tracks: [
|
||||
{
|
||||
id: 'high',
|
||||
name: '高中',
|
||||
entryClassCount: classCount,
|
||||
stages: [{ grade: '高一' }, { grade: '高二' }, { grade: '高三', terminal: true }],
|
||||
},
|
||||
],
|
||||
termStartDate: null,
|
||||
resetTermWeeks: true,
|
||||
};
|
||||
}
|
||||
@@ -200,6 +200,7 @@ export const PERMISSION_KEYS = [
|
||||
// 学期与归档
|
||||
'term:read',
|
||||
'term:write',
|
||||
'promotion:manage',
|
||||
'archive:manage',
|
||||
'dashboard:read',
|
||||
// 系统与安全
|
||||
@@ -258,7 +259,7 @@ export const PERMISSION_LABELS: Record<PermissionKey, string> = {
|
||||
'class:read': '查看班级与班级列表',
|
||||
'class:manage': '创建 / 修改 / 删除班级(含班级账号密码)',
|
||||
'roster:read': '查看学生名单',
|
||||
'roster:manage': '学生名单管理(增删 / 调班 / 导入)',
|
||||
'roster:manage': '学生名单管理(资料 / 调班 / 转入转出 / 停用)',
|
||||
'teacher:read': '查看教师名单',
|
||||
'teacher:manage': '教师账号管理(新建 / 导入 / 重置密码 / 删除)',
|
||||
'schedule:read': '查看课表',
|
||||
@@ -285,6 +286,7 @@ export const PERMISSION_LABELS: Record<PermissionKey, string> = {
|
||||
'remote:control': '远控客户端电脑(关机 / 重启 / 注销 / 锁屏)',
|
||||
'term:read': '查看学期周次',
|
||||
'term:write': '修改学期周次与开学日期',
|
||||
'promotion:manage': '配置、预览与执行学年升级',
|
||||
'archive:manage': '毕业归档',
|
||||
'dashboard:read': '查看统计看板',
|
||||
'database:manage': '数据库快照 / 导出 / 切库',
|
||||
@@ -342,7 +344,10 @@ export const PERMISSION_CATEGORIES: readonly { title: string; keys: readonly Per
|
||||
title: '客户端设备',
|
||||
keys: ['client:read', 'client:manage', 'client:update', 'client:update-push', 'remote:control'],
|
||||
},
|
||||
{ title: '学期与统计', keys: ['term:read', 'term:write', 'archive:manage', 'dashboard:read'] },
|
||||
{
|
||||
title: '学期与统计',
|
||||
keys: ['term:read', 'term:write', 'promotion:manage', 'archive:manage', 'dashboard:read'],
|
||||
},
|
||||
{
|
||||
title: '系统与安全',
|
||||
keys: [
|
||||
@@ -399,6 +404,7 @@ export const PERMISSION_DEFAULT_ROLES: Record<PermissionKey, readonly UserRole[]
|
||||
'remote:control': ['ADMIN'],
|
||||
'term:read': ['ADMIN', 'TEACHER'],
|
||||
'term:write': ['ADMIN'],
|
||||
'promotion:manage': ['ADMIN'],
|
||||
'archive:manage': ['ADMIN'],
|
||||
'dashboard:read': ['ADMIN', 'TEACHER'],
|
||||
'database:manage': ['ADMIN'],
|
||||
@@ -454,6 +460,7 @@ export const PERMISSION_MATRIX: readonly {
|
||||
subject: boolean;
|
||||
classDevice?: boolean;
|
||||
}[] = [
|
||||
{ action: '学年升级(默认管理员,可按权限组授权)', admin: true, head: false, subject: false },
|
||||
{ action: '班级创建 / 修改 / 删除', admin: true, head: false, subject: false },
|
||||
{ action: '分配班主任与各科科任老师', admin: true, head: false, subject: false },
|
||||
{ action: '学生名单管理(增删 / 导入 / 调班)', admin: true, head: true, subject: false },
|
||||
|
||||
@@ -186,16 +186,14 @@ export interface CreateStudentRequest {
|
||||
classId?: string | null;
|
||||
gender?: StudentGender;
|
||||
guardianPhone?: string;
|
||||
status?: StudentStatus;
|
||||
status?: 'active' | 'inactive';
|
||||
}
|
||||
|
||||
export interface UpdateStudentRequest {
|
||||
studentNo?: string;
|
||||
name?: string;
|
||||
classId?: string | null;
|
||||
gender?: StudentGender;
|
||||
guardianPhone?: string;
|
||||
status?: StudentStatus;
|
||||
}
|
||||
|
||||
/** 学生是否属于某个班的判定范围(列表查询用) */
|
||||
@@ -207,10 +205,19 @@ export interface StudentQueryParams {
|
||||
/* ------------------------------------------------------------------ 调班 */
|
||||
|
||||
/** 调班 / 转出的方式 */
|
||||
export type StudentTransferMode = 'single' | 'batch' | 'transfer-out';
|
||||
export type StudentTransferMode = 'single' | 'batch' | 'transfer-out' | 'restore-transfer';
|
||||
export type StudentLifecycleKind =
|
||||
'class-change' | 'transfer-in' | 'transfer-out' | 'restore' | 'unassign' | 'deactivate';
|
||||
|
||||
/** 一次调班 / 转出的历史记录(原班级 / 新班级 / 操作人 / 时间) */
|
||||
export interface StudentTransferDto {
|
||||
kind: StudentLifecycleKind;
|
||||
batchId: string;
|
||||
academicYear: number | null;
|
||||
fromGrade: string;
|
||||
toGrade: string;
|
||||
fromSchool: string;
|
||||
toSchool: string;
|
||||
id: string;
|
||||
studentId: string;
|
||||
/** 学号快照:学生被删除后历史仍可读 */
|
||||
@@ -234,6 +241,7 @@ export interface StudentTransferDto {
|
||||
* **学号不变**,只改学生当前的班级归属;历史作业与成绩保留原归属。
|
||||
*/
|
||||
export interface TransferStudentsRequest {
|
||||
allowGradeChange?: boolean;
|
||||
studentIds: string[];
|
||||
toClassId: string | null;
|
||||
note?: string;
|
||||
@@ -244,6 +252,7 @@ export interface TransferStudentsRequest {
|
||||
* 单个与批量共用 —— 传一个 id 就是单个。
|
||||
*/
|
||||
export interface TransferOutStudentsRequest {
|
||||
toSchool?: string;
|
||||
studentIds: string[];
|
||||
/** 转出去向 / 原因备注 */
|
||||
note?: string;
|
||||
@@ -272,6 +281,7 @@ export interface ArchivedYearDto {
|
||||
classCount: number;
|
||||
studentCount: number;
|
||||
transferredCount: number;
|
||||
inactiveCount: number;
|
||||
homeworkCount: number;
|
||||
notificationCount: number;
|
||||
archivedAt: string;
|
||||
@@ -292,11 +302,14 @@ export interface ArchivedClassDto {
|
||||
}
|
||||
|
||||
export interface ArchivedYearDetailDto extends ArchivedYearDto {
|
||||
/** 本届保留名单中有转入记录的学生数,按学生去重 */
|
||||
transferInCount: number;
|
||||
classes: ArchivedClassDto[];
|
||||
/** 本届毕业生 */
|
||||
graduates: StudentDto[];
|
||||
/** 本届在读期间转出的学生 */
|
||||
transferred: StudentDto[];
|
||||
inactive: StudentDto[];
|
||||
}
|
||||
|
||||
/** 归档班级的作业与通知(只读) */
|
||||
@@ -488,8 +501,6 @@ export interface UpdateClassRequest {
|
||||
enrollmentYear?: number;
|
||||
/** 班号(同上) */
|
||||
classIndex?: number;
|
||||
/** 当前年级(高一 / 高二 / 高三;学年升级时改它,**不归档**) */
|
||||
grade?: string;
|
||||
/** 本学期教学周数(1~30,仅管理员可调) */
|
||||
termWeeks?: number;
|
||||
}
|
||||
@@ -1456,6 +1467,7 @@ export interface UpdateInfo {
|
||||
export interface PermissionGroupDto {
|
||||
scope?: ContractPermissionScope;
|
||||
scopeValue?: string;
|
||||
scopeLabel: string;
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
@@ -1476,10 +1488,10 @@ export interface PermissionMemberDto {
|
||||
role: UserRole;
|
||||
/** 所属权限组;空数组 = 走角色默认模板 */
|
||||
groupIds: string[];
|
||||
/** 生效权限数量(ADMIN 恒为全集;班级端账号恒为 0,见权限页的说明) */
|
||||
/** 生效权限数量;管理员在分组并集之外始终保留两个管理入口 */
|
||||
permissionCount: number;
|
||||
/** 该账号固定拥有全部权限,不接受分配(管理员) */
|
||||
fixed: boolean;
|
||||
permissions: PermissionKey[];
|
||||
scopeLabels: string[];
|
||||
}
|
||||
|
||||
/** `GET /api/permissions/catalog`:权限键目录(与 shared 的常量一一对应,供权限页渲染) */
|
||||
|
||||
Reference in new issue
Block a user