feat: 提交家校活动前端工程源码(Vue3 + Vite + view-ui-plus)
build / build (push) Successful in 5m24s

This commit is contained in:
lijing
2026-09-20 18:00:18 +08:00
parent 267ba04af2
commit 66ad7fc6c3
333 changed files with 33141 additions and 2 deletions
@@ -0,0 +1,124 @@
# 活动信息发布模块 · 功能与接口说明 v1
> 武校家校信息发布 —— 活动信息发布子模块。本文档面向后端联调与前端维护,与代码同步维护。
> 前端契约:`src/types/activity.ts`、`src/api/module/activity.ts`;本地 mock:`src/assets/mock/activityapi.ts`。
## 一、页面与路由
| 页面 | 路由 | 组件 | 关键交互 |
| --- | --- | --- | --- |
| 我发布的 | `/list` | `ActivityList.vue` | 状态标签(全部/报名中/已截止/已结束/草稿)、时间范围 + 分类 + 关键字筛选、发布活动入口 |
| 全部活动 | `/activitylist` | `ActivityList.vue` | 同组件;不传 `scope=user`,展示全量 |
| 发布活动 | `/list/new` | `NewActivity.vue` | `?serid=` 编辑、`?fid=` 复用;立即发布 / 存草稿 / 定时发布 |
| 活动详情 | `/list/detail`、`/activitylist/detail` | `ActivityDetails.vue` | `type=0` 管理视角(阅读 + 回执进度、报名情况、编辑、复用、打印);`type=1` 查看视角(标读) |
| 报名情况 | `/signups` | `Signups.vue` | 活动下拉切换、回执状态筛选、汇总卡、按班级分组名单、回执详情、代为确认/取消、催报名、导出 CSV |
| 活动统计 | `/stats` | `ActivityStats.vue` | 总量卡、分类分布、月度趋势、发布人分布、我发布活动的回执表 |
| 应用设置 | `/setting` | `ActivitySetting.vue` | 主办部门(拖拽排序 / 启停 / 内联改名)+ 自定义组(组成员设置) |
| 活动广场 | `/par/activities` | `ParentActivities.vue` | 家长端;标签(全部/待回执/已报名/已结束)+ 关键字;右侧详情 + 报名回执弹窗 |
| 我的报名 | `/par/mine` | `ParentActivities.vue` | 同组件,`meta.initTab=signed` |
菜单 ↔ 路由通过 `meta.modId` 契约绑定(`src/router/routes.ts` 头部注释为唯一口径来源):
```
2 我发布的 /list
3 全部活动 /activitylist
4 活动统计 /stats
21 应用设置 /setting
25 报名情况 /signups
31 活动广场 /par/activities
32 我的报名 /par/mine
22 发布活动 /list/new (深层子页,parentId=2,不在菜单)
23 活动详情 /list/detail (parentId=2)
24 活动详情 /activitylist/detail (parentId=3)
```
## 二、枚举口径
| 字段 | 取值 | 含义 |
| --- | --- | --- |
| `actStatus` | `draft` / `signup` / `closed` / `finished` | 草稿 / 报名中 / 已截止 / 已结束 |
| `receiptMode` | `none` / `signup` / `confirm` | 仅通知 / 需报名 / 需确认(打开即自动确认) |
| `status`(回执记录) | `none` / `signed` / `confirmed` / `canceled` | 未回执 / 已报名 / 已确认 / 已取消(请假) |
派生量(`ActivityProgress`):`should` 应收、`signed` 已报名、`confirmed` 已确认、`canceled` 已取消、
`unsigned` 未回执、`signupRate` 回执率(%)、`quota` 名额上限、`usedQuota` 已占名额、`full` 是否满额。
`receiptMode = none` 或 `actStatus = draft` 时 `progress` 为 `null`(不产生回执记录,只统计已读)。
## 三、接口清单
统一响应 `{ code, msg, data }`,`code` 为 0 表示成功,由 `utils/alova/alova-core.ts` 解包为 `data`。
### 基础 / 布局(`/api/base`)
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/api/base/GetUserInfo` | 当前登录用户 |
| GET | `/api/base/GetUserMod` | 已授权模块(左侧菜单) |
| POST | `/api/base/SetRole` | 切换视角 `{ as: "teacher" \| "parent" }`,需在拉取用户信息前调用 |
| GET | `/api/base/GetSchoolAll` | 教师组织树(选择用户) |
| GET | `/api/base/GetClassTree` | 年级 → 班级树(发布对象到班级一级,叶子带 `studentCount`) |
| POST | `/api/base/FileUpload` | 附件上传 |
### 活动域(`/api/activity`)
| 方法 | 路径 | 入参 | 说明 |
| --- | --- | --- | --- |
| GET | `/List` | `ActivityQuery` | 家长端收件箱(已发布 + 面向本班) |
| GET | `/SendList` | `ActivityQuery`(`scope=user` 只看自己) | 我发布的 / 全部活动 |
| GET | `/Detail` | `serid, type` | `type=1` 标读;`type=0` 不标读(管理视角) |
| GET | `/GetDetail` | `serid` | 编辑/复用回显,不标读 |
| GET | `/GetNextPrev` | `serid, type` | 上一篇/下一篇 id |
| GET | `/ReadDetail` | `serid` | 阅读情况:按年级分组的班级读/未读 |
| POST | `/Create` | `ActivityRequest` | 新建,返回活动 id |
| POST | `/Edit` | `ActivityRequest`(含 `sourceId`) | 编辑 |
| POST | `/Delete` | `number[]` | 批量删除(级联清回执记录) |
| POST | `/InitializeRed` | —— | 一键全部已读 |
| POST | `/UserPull` | `serid` | 撤回(家长端不可见) |
| POST | `/SetTopmost` | `serid, topmost` | 置顶 / 取消置顶 |
| POST | `/Expedite` | `serid` | 催办未读,返回 `{ reminded }` |
| POST | `/ReceiveClasses` | `serid, classes` | 追加接收班级(补发,自动补回执记录) |
| GET | `/Statis` | `startTime?, endTime?` | 活动统计 |
| GET | `/Signups` | `serid, signupStatus` | 报名回执名单(按班级分组 + 汇总) |
| GET | `/SignupDetail` | `signupId` | 单条回执详情 |
| POST | `/Review` | `{ signupId, action: "confirm"\|"cancel"\|"waitlist", remark? }` | 处理回执 |
| POST | `/Remind` | `serid` | 催报名,返回 `{ reminded }` |
| GET | `/ExportSignups` | `serid` | 导出回执名单(JSON 包装 `{ csv }`,csv 为带 BOM 的 CSV 文本,前端取 csv 字段生成文件下载) |
| GET | `/MyActivities` | `ActivityQuery` | 家长端活动广场(含分桶计数 `buckets`) |
| GET | `/MySignup` | `serid` | 家长端活动详情 + 我的回执(同时标读) |
| POST | `/Signup` | `{ serid, joinCount, guardianName, guardianPhone, remark }` | 家长报名 / 修改回执 |
| POST | `/CancelSignup` | `serid` | 取消报名 |
### 字典 / 联系组
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| GET | `/api/dict/List?type=1` | 主办部门下拉(仅启用) |
| GET | `/api/dict/ManageList?type=dept` | 主办部门管理列表 |
| POST | `/api/dict/Add` / `Update` / `Delete` / `Sort` | 主办部门增删改与排序 |
| GET | `/api/contacts/GetGroup` | 自定义组分页 |
| POST | `/api/contacts/AddGroup` / `EditGroup` / `DelGroup` | 自定义组增删改 |
| GET | `/api/contacts/GetContactsTea` | 组内成员(`page=0&count=0` 取全部) |
| POST | `/api/contacts/SetContactsTea` | 设置组内成员 |
| GET | `/api/contacts/GetGroupTree` | 组 → 成员树(选人弹窗 tab) |
### 文件
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| POST | `/api/file/UploadImage` | 富文本内嵌图片上传 |
| GET | `/api/file/Preview` | 文件预览 |
| GET | `/api/file/Down` | 附件下载 |
| GET | `/api/activity/AllFileDown` | 全部附件打包下载 |
## 四、关键实现约定
1. **表单参数传递**:`postForm` 会把参数同时拼进 URL query。后端 `@RequestParam` 都能接收;本地 `vite-plugin-mock`
不解析 `application/x-www-form-urlencoded` body,靠 query 才能取到参数(不影响线上)。
2. **`@RequestBody` 接口**(`Create` / `Edit` / `Delete` / `Signup` / `Review`)走 `postJSON`,mock 侧用 `bodyOf(body, query)` 合并取参。
3. **接收班级**:`receiveList = "ALL"` 或班级 id 逗号串;`targetClassIds()` 统一解析。
4. **已读判定**:以班级为粒度(`classRead: string[]`);应收 / 已读人数按班级 `studentCount` 累加。
5. **端分离**:`App.vue` 依据路由前缀(`/par` → 家长端)调用 `SetRole` 切换视角并重新拉取 `GetUserMod`,
菜单与用户信息随视角变化;家长端菜单提供「发布端(教师)」入口便于返回。
6. **表格高度**:`Utils.useTableHeight({ isSearch, isTabs, isPage, isOperat })`,头部 112(自身 header 56 + 面包屑 56)。
7. **操作列图标**:`Utils.operatingHandle(h, 提示, iconClass, cb)`,图标取自 `src/assets/styles/icons.css` 的 bsch-icons 字体。