Files
familyactivity-front/src/types/activity.ts
T
2026-09-20 18:00:18 +08:00

569 lines
16 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.
/**
* 武校家校信息发布 · 活动信息发布模块 前端类型契约
*
* 与后端 VO/DTO 一一对齐(Jackson 默认驼峰序列化,详情 VO 保留旧字段名):
* - ActivityVo → 活动列表项
* - ActivityDetailVo → 活动详情(@JsonProperty 保留 Contents / DeptName 等旧字段名)
* - SignupsResultVo → 某活动的报名回执情况
* - ActivityStatisticsVo → 活动统计
* - ActivityRequest → 发布/编辑入参
* - ActivityQuery → 列表查询入参
*
* 业务要点(武校家校场景):
* 1. 发布对象到「班级」一级:receiveList = "ALL" 或 班级 id 逗号串;
* 应收人数、已读人数按班级学生数累加(家长即挂在学生档案上的联系人)。
* 2. 回执方式 receiptMode:
* - none 仅通知(无需回执,只统计已读;家长端「阅读即知悉」)
* - signup 需报名(家长填报参加人数,可带随行)
* - confirm 需确认(家长端**打开活动即自动确认**,无需点击)
* 3. 活动流程状态 status:draft 草稿 → signup 报名中 → closed 已截止 → finished 已结束。
*/
// ============================ 分页外壳 ============================
/** 统一分页响应外壳 */
export interface BasePageResult<T> {
total: number;
content: T[];
pageIndex: number;
pageSize: number;
totalPages: number;
hasNext: boolean;
}
/** 活动分页结果(扩展当前视角未读数) */
export interface ActivityPageResult<T> extends BasePageResult<T> {
/** 当前用户未读活动总数 */
unreadCount: number;
}
// ============================ 枚举 ============================
/** 活动流程状态 */
export type ActivityStatus = "draft" | "signup" | "closed" | "finished";
/** 回执方式:none 仅通知(阅读即知悉)/ signup 需报名 / confirm 需确认(打开即自动确认) */
export type ReceiptMode = "none" | "signup" | "confirm";
/** 单条回执(报名)状态 */
export type SignupStatus = "none" | "signed" | "confirmed" | "canceled";
/** 当前视角角色(家长端以学生身份登录,不单列) */
export type ViewerRole = "teacher" | "parent";
// ============================ 回执进度 ============================
/** 活动回执/报名进度(草稿或仅通知为 null) */
export interface ActivityProgress {
/** 应收人数 */
should: number;
/** 已报名人数 */
signed: number;
/** 已确认人数 */
confirmed: number;
/** 已取消/请假人数 */
canceled: number;
/** 未回执人数 */
unsigned: number;
/** 回执率(%) */
signupRate: number;
/** 名额上限,0 表示不限 */
quota: number;
/** 已用名额(按随行人数合计) */
usedQuota: number;
/** 是否名额已满 */
full: boolean;
}
// ============================ 活动列表项 ============================
/** 活动视图对象(列表用) */
export interface ActivityVo {
id: number;
title: string;
content: string;
/** 活动分类(存分类名称,选项来自「应用设置-活动分类」字典,存 sys_dict dict_type=category) */
category: string;
/** 活动地点 */
venue: string;
/** 活动开始时间 yyyy-MM-dd HH:mm:ss */
startTime: string | null;
/** 活动结束时间 */
endTime: string | null;
/** 报名截止时间 */
signupDeadline: string | null;
/** 回执方式 */
receiptMode: ReceiptMode;
receiptModeDesc: string;
/** 名额上限(0 不限) */
quota: number;
/** 是否允许家长随行 */
allowAccompany: number;
/** 活动费用(元) */
cost: number;
/** 发布人ID(平台用户ID;家长端=学生ID) */
publisherId: number;
publisherName: string;
/** 主办部门 */
deptId: string;
deptName: string;
status: number;
statusDesc: string;
/** 活动流程状态 */
actStatus: ActivityStatus;
actStatusDesc: string;
topmost: number;
/** 已读人数 */
readCount: number;
/** 应读人数 */
allowCount: number;
/** 当前用户是否已读 */
read: boolean;
/** 是否撤回:0 否 / 1 是 */
isPulled: number;
/** 定时发送时间 */
timingSendTime: string | null;
/** 短信发送标记 */
smsFlag: number;
/** 接收对象类型:class=班级 */
receiveType?: string;
/** 接收列表:"all" 或 班级 id 逗号串 */
receiveList: string | null;
/** 接收对象可读文本 */
receiveText?: string;
/** 覆盖班级数 */
classCount?: number;
/** 回执/报名进度(草稿或仅通知为 null) */
progress?: ActivityProgress | null;
createBy: string | null;
createTime: string | null;
updateBy: string | null;
updateTime: string | null;
}
// ============================ 活动详情 ============================
/** 活动详情视图对象(保留旧字段名,便于复用既有详情排版) */
export interface ActivityDetailVo {
serid: number;
title: string;
/** 活动内容(旧字段名 Contents) */
Contents: string;
/** 主办部门ID(旧字段名 DeptID) */
DeptID: string;
/** 主办部门名称(旧字段名 DeptName) */
DeptName: string;
/** 发布人姓名(旧字段名 TeaName) */
TeaName: string;
/** 发布时间(旧字段名 EditDate,已格式化为字符串) */
EditDate: string;
/** 应读人数 */
numcount: number;
/** 已读人数 */
readnumcount: number;
/** 接收人列表 */
ReceiveList: string | null;
/** 定时发送时间(旧字段名 DsfsTime) */
DsfsTime: string | null;
/** 是否定时发送 */
isDsfs: boolean;
/** 活动分类 */
category: string;
/** 活动地点 */
venue: string;
startTime: string | null;
endTime: string | null;
signupDeadline: string | null;
receiptMode: ReceiptMode;
receiptModeDesc: string;
quota: number;
allowAccompany: number;
cost: number;
actStatus: ActivityStatus;
actStatusDesc: string;
progress: ActivityProgress | null;
/** 附件列表(旧字段名 ChaoSend) */
ChaoSend: ActivityDetailFileItem[];
/** 接收对象列表:"all" 或 班级 id 数组 */
tlist: string | string[];
receiveType?: string;
/** 接收对象可读文本 */
receiveText?: string;
}
/** 活动详情附件项 */
export interface ActivityDetailFileItem {
id: number;
name: string;
size: number;
fileid: number;
filename: string;
}
// ============================ 文件上传 ============================
/** 文件上传结果 */
export interface UpFileResultVo {
fileid: number;
name: string;
fileurl: string;
host: string;
type: string;
size: number;
}
/** 附件视图对象 */
export interface UpFileVo {
id: number;
fileTrueName: string;
fileName: string;
fileSize: number;
fileType: string;
topicId: number;
topicType: string;
}
// ============================ 一键已读 ============================
/** 一键已读结果 */
export interface InitializeRedVo {
count: number;
}
// ============================ 上一篇/下一篇 ============================
/** 上一篇/下一篇活动ID */
export interface NextPrevVo {
prevId: number;
nextId: number;
}
// ============================ 阅读情况 ============================
/** 阅读情况分组项(字段名固定) */
export interface ReadGroup {
GroupName: string;
teaslist: ReadGroupUser[];
}
/** 阅读情况用户项(id 为班级ID,读/未读按班级粒度) */
export interface ReadGroupUser {
id: string;
teaname: string;
states: "read" | "unread";
}
// ============================ 回执 / 报名 ============================
/** 回执名单项(Signups 接口返回,精简) */
export interface SignupBrief {
signupId: number;
studentId: number;
studentName: string;
className: string;
/** 家长姓名 */
guardianName: string;
/** 联系电话 */
guardianPhone: string;
/** 参加人数(含学生本人) */
joinCount: number;
status: SignupStatus;
statusDesc: string;
signedAt: string | null;
/** 是否已回执/已报名 */
hasReceipt: boolean;
/** 备注(如过敏史、随行人数说明) */
remark: string;
}
/** 回执名单按班级分组 */
export interface SignupGroup {
className: string;
students: SignupBrief[];
}
/** 某活动的回执/报名结果 */
export interface SignupsResultVo {
activityId: number;
title: string;
category: string;
venue: string;
startTime: string | null;
signupDeadline: string | null;
actStatus: ActivityStatus;
actStatusDesc: string;
receiptMode: ReceiptMode;
receiptModeDesc: string;
summary: ActivityProgress;
groups: SignupGroup[];
}
/** 单条回执详情(回执详情弹窗用) */
export interface SignupDetailVo {
signupId: number;
activityId: number;
activityTitle: string;
category: string;
studentId: number;
studentName: string;
classId: string;
className: string;
guardianName: string;
guardianPhone: string;
joinCount: number;
status: SignupStatus;
statusDesc: string;
signedAt: string | null;
read: boolean;
readAt: string | null;
remark: string;
}
/** 回执审核/处理入参 */
export interface ReviewRequest {
signupId: number;
/** confirm 确认参加 / cancel 取消或请假 / waitlist 转待定 */
action: "confirm" | "cancel" | "waitlist";
remark?: string;
}
// ============================ 统计 ============================
/** 活动统计视图 */
export interface ActivityStatisticsVo {
/** 活动总数 */
total: number;
/** 已发布(含报名中/已截止/已结束) */
publishedCount: number;
/** 我发布的活动数 */
myActivityCount: number;
/** 累计回执/报名人次 */
totalSignups: number;
/** 平均回执率(%) */
avgSignupRate: number;
/** 待处理回执(名额超额或需人工确认) */
pendingReview: number;
/** 按主办部门 */
byPublisher: { publisherName: string; count: number }[];
/** 按月份 */
byMonth: { year: number; month: number; count: number }[];
/** 按活动分类分布 */
byCategory: { label: string; key: string; count: number }[];
/** 我发布的活动·回执与已读 */
byActivity: ({
id: number;
title: string;
category: string;
venue: string;
actStatus: ActivityStatus;
actStatusDesc: string;
} & ActivityProgress)[];
}
// ============================ 请求入参 ============================
/** 活动发布/编辑入参 */
export interface ActivityRequest {
title: string;
content?: string;
/** 活动分类 */
category?: string;
/** 活动地点 */
venue?: string;
/** 活动开始时间 yyyy-MM-dd HH:mm:ss */
startTime?: string;
/** 活动结束时间 */
endTime?: string;
/** 报名截止时间 */
signupDeadline?: string;
/** 回执方式 */
receiptMode?: ReceiptMode;
/** 名额上限(0 不限) */
quota?: number;
/** 是否允许家长随行 */
allowAccompany?: number;
/** 活动费用(元) */
cost?: number;
/** 主办部门ID */
deptId?: string;
deptName?: string;
/** 存草稿:true 则不发布 */
draft?: boolean;
topmost?: number;
/** 接收对象:"all" 或 班级 id 逗号串(receiveType=class) */
receiveList?: string;
/** 接收对象类型:class=班级 */
receiveType?: string;
/** 附件文件ID列表(逗号分隔串) */
fileIds?: string;
/** 定时发送时间 */
timingSendTime?: string;
/** 短信发送标记 */
smsFlag?: number;
/** 转发/复用的源活动ID */
sourceId?: number;
}
/** 活动列表查询参数 */
export interface ActivityQuery {
pageIndex?: number;
pageSize?: number;
keyword?: string;
/** 列表范围(管理端):"user" 只看自己发布的,不传=全部 */
scope?: string;
deptId?: string;
/** 活动分类筛选 */
category?: string;
/** 流程状态筛选:draft/signup/closed/finished,缺省或 all=全部 */
actStatus?: string;
/** 发布人ID */
publisherId?: number;
/** 开始时间(yyyy-MM-dd 短日期) */
startTime?: string;
/** 结束时间(yyyy-MM-dd 短日期) */
endTime?: string;
/** 阅读状态过滤(仅家长端):0 全部 / 1 未读 / 2 已读 */
readType?: number;
/** 排序:1 时间倒序 / 2 时间正序 */
orderByTime?: string;
}
/** 家长端报名入参 */
export interface SignupRequest {
serid: number;
/** 参加人数(含学生本人) */
joinCount?: number | string;
guardianName?: string;
guardianPhone?: string;
remark?: string;
}
// ============================ 字典/联系组 ============================
/** 系统字典下拉项 */
export interface DictOption {
k: number | string;
v: string | null;
[key: string]: any;
}
/** 主办部门管理列表项 */
export interface DeptManageItem {
SerID: number;
CodeID: string;
Name: string;
Enable: number;
}
/** 联系组列表项 */
export interface ContactGroupItem {
serid: number;
GroupName: string;
}
/** 联系组分页结果 */
export interface ContactGroupPage {
list: ContactGroupItem[];
total: number;
}
/** 联系组用户项(id=平台用户ID,不保存账号) */
export interface ContactUser {
id: number;
name: string;
}
/** 联系组用户分页结果 */
export interface ContactUserPage {
list: ContactUser[];
total: number;
}
/** 组织树节点(基础平台返回) */
export interface SchoolTreeNode {
[key: string]: any;
}
// ============================ 班级 ============================
/** 年级→班级树节点(叶子=班级,id 为数字班级 id,附学生数) */
export interface ClassTreeNode {
id: number;
name: string;
isParent: boolean;
studentCount?: number;
children?: ClassTreeNode[];
[key: string]: any;
}
// ============================ 家长端 ============================
/** 家长/学生视角的报名态 */
export interface MySignupInfo {
signupId: number;
status: SignupStatus;
statusDesc: string;
joinCount: number;
guardianName: string;
guardianPhone: string;
remark: string;
signedAt: string | null;
}
/** 家长端活动项 */
export interface ParentActivityVo {
id: number;
title: string;
category: string;
venue: string;
startTime: string | null;
endTime: string | null;
signupDeadline: string | null;
receiptMode: ReceiptMode;
receiptModeDesc: string;
quota: number;
allowAccompany: number;
cost: number;
content: string;
publisherName: string;
deptName: string;
createTime: string | null;
actStatus: ActivityStatus;
actStatusDesc: string;
/** 无需报名(仅通知) */
viewOnly: boolean;
/** 是否还能报名 */
canSignup: boolean;
my: MySignupInfo | null;
}
/** 家长端活动列表(含分桶计数) */
export interface MyActivitiesVo {
buckets: { todo: number; signed: number; finished: number; all: number };
list: ParentActivityVo[];
}
/** 家长端某活动详情(活动信息 + 我的报名) */
export interface MyActivityVo {
activity: {
id: number;
title: string;
category: string;
venue: string;
content: string;
startTime: string | null;
endTime: string | null;
signupDeadline: string | null;
receiptMode: ReceiptMode;
receiptModeDesc: string;
quota: number;
allowAccompany: number;
cost: number;
publisherName: string;
deptName: string;
actStatus: ActivityStatus;
actStatusDesc: string;
};
my: MySignupInfo | null;
}