first commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
- [x] moments.astro 页面使用 `momentFinder.list(1, 50)` 替代 `momentFinder.list()`
|
||||
- [x] moments.astro 页面使用 `moment.spec.content.medium` 替代 `moment.spec.media`
|
||||
- [x] MomentsSection.astro 组件使用 `momentFinder.list(1, limit)` 替代 `momentFinder.list()`
|
||||
- [x] photos.astro 页面使用 `photoFinder.groupBy()` 替代 `photoFinder.listGroups()` + `listByGroupName()`
|
||||
- [x] PhotosSection.astro 组件使用 `photoFinder.groupBy()` 替代 `photoFinder.listGroups()` + `listByGroupName()`
|
||||
- [x] TimelineSection.astro 不使用 Groovy 闭包语法 `.groupBy { ... }`
|
||||
- [x] Navbar.astro 使用 `menuItem.spec.target` 替代 `menuItem.spec.target?.value`
|
||||
- [x] Header.astro 使用 `menuItem.spec.target` 替代 `menuItem.spec.target?.value`
|
||||
- [x] 构建成功(pnpm build 无错误)
|
||||
- [x] 部署后访问 / 首页无白屏
|
||||
- [x] 部署后访问 /photos 无白屏
|
||||
- [x] 部署后访问 /moments 无白屏
|
||||
- [x] 控制台无 ERR_INCOMPLETE_CHUNKED_ENCODING 错误
|
||||
@@ -0,0 +1,63 @@
|
||||
# WarmIsland 主题白屏及 API 错误彻底修复 Spec
|
||||
|
||||
## Why
|
||||
主题中使用了 Halo 2.24.2 不存在的 Finder API 方法(`momentFinder.list()`、`photoFinder.listGroups()`、`photoFinder.listByGroupName()`),以及 Thymeleaf 不支持的 Groovy 闭包语法(`.groupBy { ... }`),导致模板渲染时抛出 `SpelEvaluationException`,HTTP 响应流中断,产生 `ERR_INCOMPLETE_CHUNKED_ENCODING 200` 白屏错误。同时 `MomentSpec` 中不存在 `media` 字段,媒体数据实际在 `content.medium` 中。
|
||||
|
||||
## What Changes
|
||||
- **修复 `momentFinder.list()` 调用**:改为 `momentFinder.list(1, 50)`(返回 `Mono<ListResult<MomentVo>>`),需通过 `.items` 获取列表
|
||||
- **修复 `photoFinder.listGroups()` 调用**:改为 `photoFinder.groupBy()`(返回 `Flux<PhotoGroupVo>`),`PhotoGroupVo` 已包含 `photos` 列表
|
||||
- **修复 `photoFinder.listByGroupName()` 调用**:改为 `photoFinder.listBy(groupName)`(返回 `Flux<PhotoVo>`),或直接使用 `groupBy()` 返回的 `PhotoGroupVo.photos`
|
||||
- **修复 `moment.spec.media` 引用**:改为 `moment.spec.content.medium`(`MomentContent.medium` 是 `List<MomentMedia>`)
|
||||
- **修复 `TimelineSection.astro` 中的 Groovy 闭包语法**:`.groupBy { it.spec.publishTime?.getYear() }` 在 Thymeleaf 中不可用,需改用 `postFinder.list({page: 1, size: 50})` 获取文章后手动按年分组
|
||||
- **修复 `Navbar.astro` 和 `Header.astro` 中的 `menuItem.spec.target?.value`**:改为 `menuItem.spec.target`(`target` 是字符串而非对象)
|
||||
|
||||
## Impact
|
||||
- Affected code:
|
||||
- `src/pages/moments.astro` - 瞬间页面(白屏根因)
|
||||
- `src/pages/photos.astro` - 图库页面(白屏根因)
|
||||
- `src/components/MomentsSection.astro` - 首页瞬间区块(首页白屏根因)
|
||||
- `src/components/PhotosSection.astro` - 首页图库区块
|
||||
- `src/components/TimelineSection.astro` - 首页时间线区块
|
||||
- `src/components/Navbar.astro` - 导航栏 target 属性
|
||||
- `src/components/Header.astro` - 头部导航 target 属性
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 正确使用 momentFinder API
|
||||
系统 SHALL 使用 `momentFinder.list(page, size)` 替代不存在的 `momentFinder.list()`,返回 `ListResult` 对象需通过 `.items` 获取列表数据。
|
||||
|
||||
#### Scenario: 瞬间页面正常渲染
|
||||
- **WHEN** 用户访问 `/moments`
|
||||
- **THEN** 页面正常显示瞬间列表,无 `ERR_INCOMPLETE_CHUNKED_ENCODING` 错误
|
||||
|
||||
#### Scenario: 首页瞬间区块正常渲染
|
||||
- **WHEN** 用户访问首页且启用了瞬间区块
|
||||
- **THEN** 首页正常显示,瞬间区块展示最近的瞬间
|
||||
|
||||
### Requirement: 正确使用 photoFinder API
|
||||
系统 SHALL 使用 `photoFinder.groupBy()` 替代不存在的 `photoFinder.listGroups()`,`PhotoGroupVo` 已包含 `photos` 列表,无需额外调用 `listByGroupName`。
|
||||
|
||||
#### Scenario: 图库页面正常渲染
|
||||
- **WHEN** 用户访问 `/photos`
|
||||
- **THEN** 页面正常显示图库分组和照片,无白屏错误
|
||||
|
||||
### Requirement: 正确引用 Moment 媒体数据
|
||||
系统 SHALL 使用 `moment.spec.content.medium` 替代不存在的 `moment.spec.media`,`MomentMedia` 对象包含 `type`、`url`、`originType` 字段。
|
||||
|
||||
#### Scenario: 瞬间包含媒体时正常显示
|
||||
- **WHEN** 瞬间包含图片媒体
|
||||
- **THEN** 图片正常显示在瞬间卡片中
|
||||
|
||||
### Requirement: 不使用 Thymeleaf 不支持的语法
|
||||
系统 SHALL 不在 Thymeleaf 表达式中使用 Groovy 闭包语法(如 `.groupBy { ... }`),TimelineSection 需改用 `postFinder.list({...})` 获取文章列表。
|
||||
|
||||
#### Scenario: 首页时间线区块正常渲染
|
||||
- **WHEN** 用户访问首页且启用了时间线区块
|
||||
- **THEN** 首页正常显示,时间线区块按年展示文章
|
||||
|
||||
### Requirement: 正确引用菜单项 target 属性
|
||||
系统 SHALL 使用 `menuItem.spec.target` 替代 `menuItem.spec.target?.value`,`target` 是字符串类型。
|
||||
|
||||
#### Scenario: 导航链接在新标签页打开
|
||||
- **WHEN** 菜单项配置了在新标签页打开
|
||||
- **THEN** 链接正确设置 target 属性
|
||||
@@ -0,0 +1,51 @@
|
||||
# Tasks
|
||||
|
||||
- [x] Task 1: 修复 moments.astro 页面 - 替换 `momentFinder.list()` 为 `momentFinder.list(1, 50)`,修复 `moment.spec.media` 为 `moment.spec.content.medium`
|
||||
- [x] 将 `th:with="moments = ${momentFinder.list()}"` 改为 `th:with="momentsResult = ${momentFinder.list(1, 50)}"`
|
||||
- [x] 将 `th:each="moment : ${moments}"` 改为 `th:each="moment : ${momentsResult.items}"`
|
||||
- [x] 将 `th:if="${moments != null and not #lists.isEmpty(moments)}"` 改为 `th:if="${momentsResult != null and not #lists.isEmpty(momentsResult.items)}"`
|
||||
- [x] 将 `moment.spec?.media` 改为 `moment.spec.content.medium`
|
||||
- [x] 将 `moment.spec.media` 改为 `moment.spec.content.medium`
|
||||
- [x] 将 `media.type == 'PHOTO'` 保持不变(MomentMediaType.PHOTO 对应字符串 'PHOTO')
|
||||
- [x] 将 `media.url` 保持不变
|
||||
- [x] 将 `media.displayName ?: ''` 改为 `''`(MomentMedia 没有 displayName 字段)
|
||||
|
||||
- [x] Task 2: 修复 MomentsSection.astro 组件 - 替换 `momentFinder.list()` 为 `momentFinder.list(1, limit)`
|
||||
- [x] 将 `th:with="moments = ${momentFinder != null ? momentFinder.list() : null}, limit = ..."` 改为 `th:with="momentsResult = ${momentFinder.list(1, limit)}"`
|
||||
- [x] 将 `th:each="moment, stat : ${moments}"` 改为 `th:each="moment : ${momentsResult.items}"`
|
||||
- [x] 移除 `th:if="${stat.index < limit}"` 限制(已通过 list 的 size 参数限制)
|
||||
- [x] 修复 `moment.spec?.content?.html ?: moment.spec?.content?.raw ?: moment.spec?.content` 保持不变(正确)
|
||||
- [x] 修复 `moment.spec?.releaseTime` 保持不变(正确)
|
||||
|
||||
- [x] Task 3: 修复 photos.astro 页面 - 替换 `photoFinder.listGroups()` + `listByGroupName()` 为 `photoFinder.groupBy()`
|
||||
- [x] 将 `th:with="groups = ${photoFinder.listGroups()}"` 改为使用 `photoFinder.groupBy()`
|
||||
- [x] 使用 `th:each="group : ${photoFinder.groupBy()}"` 遍历分组
|
||||
- [x] `group` 是 `PhotoGroupVo`,包含 `metadata`、`spec`、`status`、`photos` 字段
|
||||
- [x] 移除 `th:with="photos = ${photoFinder.listByGroupName(group.metadata?.name)}"` 内部调用
|
||||
- [x] 直接使用 `group.photos` 遍历照片
|
||||
- [x] 照片字段:`photo.spec.url`、`photo.spec.displayName`、`photo.spec.description`
|
||||
|
||||
- [x] Task 4: 修复 PhotosSection.astro 组件 - 替换 `photoFinder.listGroups()` + `listByGroupName()` 为 `photoFinder.groupBy()`
|
||||
- [x] 将 `th:with="groups = ${photoFinder != null ? photoFinder.listGroups() : null}"` 改为使用 `photoFinder.groupBy()`
|
||||
- [x] 使用 `th:each="group : ${photoFinder.groupBy()}"` 获取第一个分组
|
||||
- [x] 使用 `group.photos` 获取照片列表
|
||||
- [x] 限制显示数量使用 `th:each="photo, stat : ${group.photos}" th:if="${stat.index < limit}"`
|
||||
|
||||
- [x] Task 5: 修复 TimelineSection.astro - 移除 Groovy 闭包语法
|
||||
- [x] 将 `${postFinder.listAll().groupBy { it.spec.publishTime?.getYear() }}` 改为 `${postFinder.list({page: 1, size: 50})}`
|
||||
- [x] 使用 `th:each="post : ${posts.items}"` 遍历文章
|
||||
- [x] 按年份分组改用 Thymeleaf 的方式:先获取所有文章,再在模板中按年分组展示
|
||||
|
||||
- [x] Task 6: 修复 Navbar.astro 和 Header.astro 中的 `menuItem.spec.target?.value`
|
||||
- [x] 将 `th:target="${menuItem.spec.target?.value}"` 改为 `th:target="${menuItem.spec.target}"`
|
||||
|
||||
- [x] Task 7: 构建并部署验证
|
||||
- [x] 执行 `pnpm build`
|
||||
- [x] 部署到 Docker 容器
|
||||
- [x] 重启 Halo 容器
|
||||
- [x] 通过浏览器访问所有页面验证无白屏
|
||||
|
||||
# Task Dependencies
|
||||
- [Task 7] depends on [Task 1, Task 2, Task 3, Task 4, Task 5, Task 6]
|
||||
- [Task 1] and [Task 2] can be parallelized
|
||||
- [Task 3] and [Task 4] can be parallelized
|
||||
Reference in New Issue
Block a user