569 lines
16 KiB
TypeScript
569 lines
16 KiB
TypeScript
/**
|
||
* 武校家校信息发布 · 活动信息发布模块 前端类型契约
|
||
*
|
||
* 与后端 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;
|
||
}
|