docs: 回填草原指南 TEST 验收结果
这个提交包含在:
父节点
8f2f40c670
当前提交
6e96521aa7
@ -69,31 +69,13 @@
|
||||
|
||||
## 3. 视频上传流程
|
||||
|
||||
### 3.1 前端先读取本地视频时长
|
||||
### 3.1 视频时长由后端自动提取
|
||||
|
||||
选择 MP4 后,在请求上传凭证前读取浏览器本地元数据:
|
||||
前端申请上传凭证和确认上传时均不提交 `durationSeconds`,管理端也不提供可编辑时长输入框。
|
||||
|
||||
```ts
|
||||
export async function readVideoDurationSeconds(file: File): Promise<number> {
|
||||
const url = URL.createObjectURL(file)
|
||||
try {
|
||||
const video = document.createElement('video')
|
||||
video.preload = 'metadata'
|
||||
video.src = url
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
video.onloadedmetadata = () => resolve()
|
||||
video.onerror = () => reject(new Error('无法读取视频元数据'))
|
||||
})
|
||||
return Math.ceil(video.duration)
|
||||
} finally {
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
}
|
||||
```
|
||||
上传确认阶段由后端通过 OSS Range 读取 MP4 的 `moov` 元数据,自动计算并保存向上取整后的秒数;不下载体积最大的 `mdat` 视频内容。确认成功后,前端只读展示素材或草原指南详情返回的 `durationSeconds`。
|
||||
|
||||
草原指南视频的 `durationSeconds` 必填且必须大于 0。后端不会下载完整视频计算时长。
|
||||
|
||||
该值由前端代码自动读取并提交,不能提供手工输入框。素材确认后,编辑页只读展示后端返回的时长。
|
||||
视频上传校验的最新完整契约见独立 changelog:[`13_fix_grassland_guide_mp4_progressive_gate.md`](./13_fix_grassland_guide_mp4_progressive_gate.md)。
|
||||
|
||||
### 3.2 获取素材上传凭证
|
||||
|
||||
@ -108,8 +90,7 @@ export async function readVideoDurationSeconds(file: File): Promise<number> {
|
||||
"filename": "hulunbuir-wind.mp4",
|
||||
"fileSize": 12925261,
|
||||
"md5": "32位文件MD5",
|
||||
"contentType": "video/mp4",
|
||||
"durationSeconds": 61
|
||||
"contentType": "video/mp4"
|
||||
}
|
||||
```
|
||||
|
||||
@ -118,7 +99,7 @@ export async function readVideoDurationSeconds(file: File): Promise<number> {
|
||||
- `categoryCode` 必须是 `grassland_guide`。
|
||||
- 文件扩展名必须是 `.mp4`。
|
||||
- `contentType` 必须以 `video/mp4` 开头。
|
||||
- `durationSeconds` 必须大于 0。
|
||||
- 不提交 `durationSeconds`;服务端不采信客户端时长。
|
||||
- 单个视频最大 `2147483648` 字节(2 GiB),大于 `10485760` 字节(10 MiB)时使用 OSS 分片上传。
|
||||
|
||||
响应中的 `uploadMode` 有两种:
|
||||
@ -142,17 +123,19 @@ export async function readVideoDurationSeconds(file: File): Promise<number> {
|
||||
}
|
||||
```
|
||||
|
||||
确认接口会通过 OSS `HeadObject` 读取实际对象元数据,并校验:
|
||||
确认接口会通过 OSS `HeadObject` 和 Range 读取实际对象元数据及 MP4 `moov`,并校验:
|
||||
|
||||
- OSS 对象必须真实存在。
|
||||
- 实际 `Content-Length` 必须等于申请上传凭证时声明的 `fileSize`。
|
||||
- MP4 的实际 `Content-Type` 必须是 `video/mp4`(允许携带参数)。
|
||||
- MP4 满足 `ftyp < moov < mdat`,且包含一条 H.264 视频轨和一条 AAC-LC 音频轨。
|
||||
- 服务端自动计算 `durationSeconds`,成功状态为 `OSS_MP4_READY_V1`。
|
||||
|
||||
任一校验失败时素材不会进入 `ACTIVE`。确认成功后保存返回的 `materialId`,创建草原指南内容时作为 `videoMaterialId` 提交。
|
||||
任一校验失败时素材不会进入可用状态。确认成功后保存返回的 `materialId`,创建草原指南内容时作为 `videoMaterialId` 提交。
|
||||
|
||||
### 3.4 文件夹上传
|
||||
|
||||
如素材库继续支持文件夹批量上传,`POST /admin/material/upload/folder` 的每个 `files[]` 项也必须为草原指南视频提交 `durationSeconds`。
|
||||
如素材库继续支持文件夹批量上传,草原指南视频同样不提交 `durationSeconds`;每个视频仍必须完成上传确认并取得 `OSS_MP4_READY_V1` 后才能用于新建或替换草原指南内容。
|
||||
|
||||
## 4. 视频封面
|
||||
|
||||
@ -361,7 +344,8 @@ OSS 自动封面格式:
|
||||
- 2026-07-13 已从管理端和小程序端完整删除 `showProducedBadge`:Resource/MP OpenAPI 均无该字段,首页、列表、详情、推荐 4 个实际接口均返回 `200` 且无该字段;Resource Flyway `20260713.001` 执行成功,遗留数据库列已删除。
|
||||
- 2026-07-13 PR #4953 已合入 `dev-v3`,并按 `hl-gateway` → `hl-mp-service` → `hl-resource-service` 部署测试环境;三项服务均完成双实例滚动升级。该 PR 补齐产品绑定字段、单条内容登录鉴权并移除前端 `version` 契约。
|
||||
- 2026-07-13 PR #4958 已将 `dev@73e25cf61` 的完整交付链同步回 `dev-v3@6b7775ab`。该 PR 文件差异为 0,合并前后代码树一致;随后仅在测试环境按 `hl-mp-service` → `hl-gateway` → `hl-resource-service` 再次串行滚动发布,任务分别为 `f9159fab`、`655b9b6e`、`40bacc94`,三项服务 Nacos 均为 `2/2` 健康。
|
||||
- 本轮真实接口复验确认管理端列表/详情与小程序列表/详情/推荐均成功;管理端和草原指南小程序契约均无前端 `version`,推荐分页排除自身且不重复。测试库 4 条已发布内容目前均为 `loginRequired=false`,因此受保护内容的匿名 `401` 与有效小程序 JWT `200` 双路径仍待具备测试数据后补验,不影响公开内容联调。
|
||||
- 本轮真实接口复验确认管理端列表/详情与小程序列表/详情/推荐均成功;管理端和草原指南小程序契约均无前端 `version`,推荐分页排除自身且不重复。
|
||||
- 2026-07-13 已补充受保护真实 4K 测试内容:匿名详情返回 `401`,伪造 `X-User-Id` 仍返回 `401`,有效小程序 USER token 返回 `200`;关闭 `loginRequired` 后匿名详情恢复 `200`。测试 token 仅在 TEST 宿主机本地 Redis 通过 `SCAN` 读取并在内存中使用,未输出、未落盘。
|
||||
- 音画同步不能仅凭 OSS `HEAD` 或 `Range 206` 判定通过。当前仍为 OSS 4K 原片直出,目标机型真机播放验收须单独记录;未经真机验证不得标记“音画同步已修复”。
|
||||
|
||||
## 8. 2026-07-14 正式环境 Nacos 部署清单
|
||||
@ -409,7 +393,7 @@ PR #4953 不新增 Nacos 配置。正式发布最终版本时按以下顺序滚
|
||||
|
||||
- [ ] 新增“草原指南管理”列表、编辑和发布页面。
|
||||
- [ ] 素材库展示顶级分类“草原指南”,隐藏系统分类删除/停用/改码操作。
|
||||
- [ ] 选择 MP4 后通过 `loadedmetadata` 获取时长并 `Math.ceil`,界面只读展示,不允许手填。
|
||||
- [ ] 不提交视频 `durationSeconds`;上传确认后只读展示后端自动提取的时长,不允许手填。
|
||||
- [ ] 使用素材库通用上传接口处理 `PRESIGNED_URL` 和 `STS_MULTIPART`。
|
||||
- [ ] 支持单独上传/选择图片作为自定义封面,并允许清空后恢复自动封面。
|
||||
- [ ] 草原指南内容保存 `videoMaterialId`,不保存 VOD 字段。
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
>
|
||||
> 后端 Issue:[HL #4959](https://git.1814.love:8443/wx/HL/issues/4959)
|
||||
>
|
||||
> 后端 PR:[HL #4960](https://git.1814.love:8443/wx/HL/pulls/4960),已合入 `dev`
|
||||
> 后端 PR:[HL #4960](https://git.1814.love:8443/wx/HL/pulls/4960),已合入 `dev`;随后通过 [HL #4963](https://git.1814.love:8443/wx/HL/pulls/4963) 由 `dev` 合入 `dev-v3`
|
||||
>
|
||||
> 当前状态:已合入 `dev`,本地编译及目标单测通过;待部署 TEST,暂未合入 `dev-v3`
|
||||
> 当前状态:已合入 `dev` 和 `dev-v3`,TEST 双实例部署及真实接口验收通过;尚未合入 `main`、尚未部署正式环境
|
||||
|
||||
## 1. 变更范围
|
||||
|
||||
@ -64,11 +64,14 @@ grassland-guide:delete
|
||||
|
||||
## 7. 联调清单
|
||||
|
||||
后端在 `origin/dev` 基线上已完成 15 模块编译和 24 项目标单测;以下仍需管理端/测试环境联调确认:
|
||||
后端在 `origin/dev` 基线上已完成 15 模块编译和 24 项目标单测;TEST 已完成接口验收,管理端 UI 仍需前端联调:
|
||||
|
||||
- [ ] `OFFLINE` 视频删除成功,列表和详情均不再返回。
|
||||
- [ ] `DRAFT`、`PUBLISHED` 视频没有删除入口,直接调用接口返回 `371008`。
|
||||
- [ ] 删除请求没有 body,也没有 `version`。
|
||||
- [ ] 重复删除返回 `371001`。
|
||||
- [x] `OFFLINE` 视频删除成功,管理端详情和小程序详情、列表均不再返回。
|
||||
- [x] `DRAFT`、`PUBLISHED` 直接调用删除接口均返回 `371008`。
|
||||
- [x] 删除请求没有 body,也没有 `version`。
|
||||
- [x] 重复删除返回 `371001`。
|
||||
- [ ] 无 `grassland-guide:delete` 权限时不展示入口。
|
||||
- [ ] 删除内容后,素材库中的原视频和封面仍然存在。
|
||||
- [ ] 管理端仅在 `OFFLINE` 状态展示删除入口,并完成二次确认交互。
|
||||
- [x] 删除内容后,素材库中的原视频和封面仍然存在。
|
||||
|
||||
TEST 证据:验收内容 ID `2076674584685240321` 已完成 `DRAFT → PUBLISHED → OFFLINE → 删除` 全状态流转;删除前尝试删除被引用素材返回 `371009`,删除内容后素材 `2076658080942116865` 仍保留且状态为 `OSS_MP4_READY_V1`。
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
# 草原指南视频上传校验与服务端时长
|
||||
|
||||
> 日期:2026-07-13
|
||||
>
|
||||
> 后端 Issue:[HL #4949](https://git.1814.love:8443/wx/HL/issues/4949)
|
||||
> 后端 PR:[HL #4961](https://git.1814.love:8443/wx/HL/pulls/4961)
|
||||
> 当前状态:已合入 `dev`;尚未部署 TEST,尚未合入 `dev-v3`
|
||||
>
|
||||
> 后端 PR:[HL #4961](https://git.1814.love:8443/wx/HL/pulls/4961)、[HL #4962](https://git.1814.love:8443/wx/HL/pulls/4962)、[HL #4964](https://git.1814.love:8443/wx/HL/pulls/4964)
|
||||
>
|
||||
> 测试合并:[HL #4963](https://git.1814.love:8443/wx/HL/pulls/4963)、[HL #4965](https://git.1814.love:8443/wx/HL/pulls/4965),均按 `dev` → `dev-v3` 进入 TEST
|
||||
>
|
||||
> 当前状态:TEST 已部署并通过真实 4K 上传确认;尚未合入 `main`、尚未部署正式环境
|
||||
|
||||
## 1. 本文件只说明视频上传链路
|
||||
|
||||
@ -94,11 +99,19 @@
|
||||
|
||||
## 7. 前端联调清单
|
||||
|
||||
- [ ] 上传凭证请求不提交草原指南视频 `durationSeconds`。
|
||||
- [ ] 大文件使用 `STS_MULTIPART` 直传 OSS。
|
||||
- [x] 后端 OpenAPI 与真实请求确认:上传凭证不需要草原指南视频 `durationSeconds`。
|
||||
- [x] 412400073 字节真实 4K 文件使用 `STS_MULTIPART` 直传 OSS。
|
||||
- [ ] 管理端时长只读展示确认接口返回值。
|
||||
- [ ] 原始 `moov` 位于文件尾部的视频确认返回 `250016`。
|
||||
- [ ] 无损 faststart 重排后的真实 4K 原片确认成功并返回 `OSS_MP4_READY_V1`。
|
||||
- [ ] `250015` 使用同一个 `materialId` 重试确认。
|
||||
- [ ] 新建/替换内容只能选择 `OSS_MP4_READY_V1` 视频;历史原素材不变时仍可维护。
|
||||
- [x] 无损 faststart 重排后的真实 4K 原片确认成功并返回 `OSS_MP4_READY_V1`、`durationSeconds=83` 和自动封面。
|
||||
- [x] 首次确认因 fat JAR 类加载问题失败后,使用同一个 `materialId=2076658080942116865` 重试成功,未重复上传 412 MB 文件。
|
||||
- [x] 新建草原指南已实测只接受 `OSS_MP4_READY_V1` 视频;历史原素材不变时仍可维护。
|
||||
- [ ] 微信 Android/iOS 真机完成原片与重排文件的 A/B 验收。
|
||||
|
||||
## 8. TEST 真实验证记录
|
||||
|
||||
- User 部署任务:`1a2a42da`,`dev-v3`,8081/8181 双实例滚动成功;Nacos `test` 命名空间两实例均为 `healthy=true`、`enabled=true`。
|
||||
- 素材:`2076658080942116865`,文件大小 `412400073`,存储方 `OSS`,媒体状态 `OSS_MP4_READY_V1`,服务端时长 `83` 秒,自动封面存在。
|
||||
- fat JAR 回归:通过 Spring Boot `PropertiesLauncher` 直接加载最终候选 JAR,并解析同一真实 4K `moov`,返回 `durationSeconds=83 / OSS_MP4_READY_V1`。
|
||||
- OSS Range:请求 `bytes=0-1023` 返回 HTTP `206`、1024 字节和 `Content-Range`。
|
||||
- 仍未据此宣称真机音画同步通过;默认 Bucket 域名的微信 Android/iOS 真机播放、拖动、暂停恢复与音画同步必须由前端单独验收。
|
||||
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户