新增:管理后台前端页面,以及openspec内容。

This commit is contained in:
2025-12-24 20:15:28 +08:00
parent 6d7ed38105
commit 845f1c6618
64 changed files with 9017 additions and 6 deletions

View File

@@ -0,0 +1,202 @@
# 后端 APIWxCheckMvc规范
## Purpose
本能力描述 `WxCheckMvc` 暴露给微信小程序与管理侧的 HTTP API登录/注册、会话记录的增删改查、文件上传、地址补全,以及 Redis Stream 的消息读取。
路由约定:统一为 `/api/{Controller}/{Action}`
## Requirements
### Requirement: 小程序登录(基于微信 code
系统 SHALL 提供登录接口,用 `wx.login()` 获取的 `code` 向微信换取 `openid`,并以 `openid` 作为系统内部 `UserKey`
接口:`POST /api/Login/Login`
请求:
- `Code: string`
响应(成功):
- `success: true`
- `data`: 用户对象(包含 `UserKey/openid``Token`
行为:
-`xcx_users` 不存在该 `UserKey`,系统 SHALL 自动插入一条用户记录(资料可为空)。
- 若用户 `IsDisabled = 1`,系统 SHALL 返回 `success: false`
#### Scenario: 首次登录自动建档
- **WHEN** 提交的 `code` 能换取有效 `openid`
- **AND** 数据库中不存在该 `openid`
- **THEN** 系统创建用户记录并返回 `Token`
#### Scenario: 禁用用户登录
- **WHEN** 用户 `IsDisabled = 1`
- **THEN** 系统返回 `success: false` 且提示用户已禁用
### Requirement: 小程序注册/完善资料
系统 SHALL 提供接口用于完善用户资料(用户名、微信名、手机号、头像链接)。
接口:`POST /api/Login/Register`
请求:
- `UserKey: string`openid
- `UserName: string`
- `WeChatName: string`
- `PhoneNumber: string`
- `AvatarUrl: string`
校验:
- `UserKey` 必填
- `PhoneNumber` SHALL 清洗为纯数字后满足 `^1\d{10}$`
- `UserName` SHALL 去除标点/符号/空白后仍非空
响应(成功):
- `success: true`
- `data`: 更新后的用户对象(包含 `Token`
#### Scenario: 正常完善资料
- **WHEN** 提交合法的用户名与手机号
- **AND** `UserKey` 对应用户存在
- **THEN** 系统更新用户资料并返回新 `Token`
#### Scenario: 用户不存在
- **WHEN** `UserKey` 对应用户不存在
- **THEN** 系统返回 404
### Requirement: 上传文件并可更新头像
系统 SHALL 提供文件上传接口,保存到后端 `wwwroot/{rootPathType}` 下,并返回可访问 URL。
接口:`POST /api/Check/UploadFile``multipart/form-data`
表单字段:
- `file`: 上传文件
- `rootPathType: string`(可选;默认 `Avatar`,仅允许字母/数字/下划线)
- `userKey: string`(可选;若提供则更新 `xcx_users.AvatarUrl`
响应:
- `success: true/false`
- `url`: 公开访问 URL
- `path`: 相对路径
#### Scenario: 上传头像并更新用户表
- **WHEN** 上传文件并提供 `userKey`
- **THEN** 系统保存文件并更新该用户 `AvatarUrl`
### Requirement: 新增会话记录
系统 SHALL 提供接口新增会话记录(软实时写入数据库),并尝试将消息投递到 Redis Stream。
接口:`POST /api/Check/AddConversation`
请求(核心字段):
- `UserKey: string`
- `ConversationContent: string`
- `SendMethod: string`
- `UserLocation: string`(当前实现中会尝试解析 `lat,lng`
- `MessageType: int`(默认 1
- `Guid?: string`(可选;缺省则服务端生成)
- `SpeakingTime?: int`
行为:
- 系统 SHALL 写入 `xcx_conversation`,并生成/使用 `Guid`
- 系统 MAY 将会话与用户信息写入 Redis Streamkey: `xcx_msg`group: `xcx_group`)。
#### Scenario: 新增会话并返回 guid
- **WHEN** 提交包含 `UserKey``ConversationContent` 的请求
- **THEN** 系统创建会话记录并返回 `conversationGuid`
### Requirement: 查询会话记录(按用户)
系统 SHALL 提供按 `UserKey` 查询会话记录的接口,默认只返回未删除记录。
接口:`POST /api/Check/GetConversations`
请求:
- `UserKey: string`
- `MessageType: int`0 不过滤1 公有2 私有;当前实现仅在 `MessageType == 1` 时追加过滤)
#### Scenario: 查询用户所有未删除会话
- **WHEN** 提交 `UserKey`
- **THEN** 系统返回该用户 `IsDeleted = 0` 的会话记录
### Requirement: 分页查询会话记录
系统 SHALL 提供分页接口。
接口:`POST /api/Check/GetConversationsByPage`
请求:
- `UserKey: string`
- `Page: int`<1 视为 1
- `PageSize: int`1..100,否则默认 10
- `MessageType: int`(当前实现仅在 `MessageType == 1` 时追加过滤)
响应:
- `data.conversations`
- `data.totalCount / page / pageSize / totalPages`
#### Scenario: PageSize 超限
- **WHEN** `PageSize > 100`
- **THEN** 系统按默认值 10 处理
### Requirement: 更新会话记录
系统 SHALL 提供接口按 `Guid + UserKey` 更新会话内容与发送方式。
接口:`POST /api/Check/UpdateConversation`
请求:
- `Guid: string`
- `UserKey: string`
- `ConversationContent: string`
- `SendMethod: string`
- `MessageType: int`
#### Scenario: 非本人更新
- **WHEN** `Guid` 存在但 `UserKey` 不匹配
- **THEN** 系统返回 404记录不存在或无权限修改
### Requirement: 删除会话记录(软删除)
系统 SHALL 提供接口按 `Guid + UserKey` 软删除会话。
接口:`POST /api/Check/DeleteConversation`
请求:
- `Guid: string`
- `UserKey: string`
#### Scenario: 删除已删除记录
- **WHEN** 记录已被删除
- **THEN** 系统返回 404
### Requirement: 按 Guid 查询会话(不受软删除影响)
系统 SHALL 提供接口按 `Guid` 查询单条会话记录,不过滤 `IsDeleted`
接口:`POST /api/Check/GetConversationByGuid`
#### Scenario: 查询已删除会话
- **WHEN** `Guid` 对应记录存在但 `IsDeleted = 1`
- **THEN** 系统仍返回该记录
### Requirement: 地址补全(经纬度→地址)
系统 SHALL 提供接口按 `Guid` 查找会话记录经纬度,并使用高德逆地理编码生成地址写回 `UserLocation`
接口:`POST /api/Check/CheckAddress`
#### Scenario: 记录不存在
- **WHEN** `Guid` 对应记录不存在或已删除
- **THEN** 系统返回 404
### Requirement: Redis Stream 读取消息
系统 SHALL 提供接口从 Redis Stream 读取消息。
接口:`POST /api/Check/ReadMessageFromRedis`
请求:
- `GroupName?: string`(默认 `xcx_group`
- `ConsumerName?: string`(默认 `consumer_{ticks}`
- `Count?: int`(默认 1
#### Scenario: 无新消息
- **WHEN** Stream 中无可读消息
- **THEN** 返回 `success: true` 且数据为空
## Known Limitations
- 当前 JWT 配置存在,但认证中间件与授权标注未启用;接口默认可匿名访问。
- `MessageType` 的过滤条件存在实现差异:部分接口仅在 `MessageType == 1` 时追加过滤(不覆盖 2
- 文件上传未实现内容类型/大小的强制限制。