日期:2026-10-24
核验范围:cfc-frontend/pages/activity/index.vue+ 活动模块相关前后端代码
loadData() 修复核验将 loadData()(约 462-488 行)改为:先重置当前 tab 的页码为 1、清空对应数组、再调用 loadXxxActivities() 加载第一页。
loadData: function() {
if (this.currentTab === 'mine') {
this.minePage = 1
this.myActivities = []
this.hasMore = true
this.loadMyActivities()
} else if (this.currentTab === 'discover') {
this.discoverPage = 1
this.discoverActivities = []
this.hasMore = true
this.loadDiscoverActivities()
} else if (this.currentTab === 'history') {
this.historyPage = 1
this.historyActivities = []
this.hasMore = true
this.loadHistoryActivities()
} else if (this.currentTab === 'manage') {
if (this.canManageActivity) {
this.loadManageData()
}
}
}
证据(index.vue 第 391-398 行):
onShow: function() {
if (this._onLoadFired) {
this._onLoadFired = false // 首次进入:onLoad 已加载,跳过避免双发
} else {
this.resolveManagePermission()
this.loadData() // ← 切 Tab/从子页返回时走这里
}
},
详情页跳转用 uni.navigateTo(非 tab 页面),返回时触发 onShow;首次进入时 onLoad 已设 _onLoadFired = true,onShow 跳过。后续返回时标志已被重置为 false,会真正调用 loadData()。✅
关键:loadXxxActivities 在非 refresh 分支会 concat,但 loadData 先清空了数组,所以 concat 后不会叠加。
loadDiscoverActivities 非 refresh 分支(第 754-755 行):
self.discoverActivities = self.discoverActivities.concat(list)
此时 discoverActivities 已被 loadData() 初始化为 [],concat 结果 = list,不会翻倍。✅
| 路径 | 实际行为 | 是否正确 |
|---|---|---|
下拉刷新 onRefresh() (659-677 行) |
调用 loadXxxActivities(true) → refresh=true 分支清空数组 + page=1 |
✅ 正确 |
加载更多 onLoadMore() (646-658 行) |
递增 page++ → 调用 loadXxxActivities() 无 refresh → concat 追加 |
✅ 正确 |
Tab 切换 onTabChange() (447-460 行) |
先清空数组+page=1,再调 loadData() → loadData 内部不再重复清空(不影响) |
✅ 正确(轻微冗余但无害) |
维度筛选切换 onDimensionChange() (639-644 行) |
先清空 discover 数组+page=1,再调 loadDiscoverActivities() 无 refresh,concat 到空数组 |
✅ 正确 |
mine 筛选切换 onMineFilterChange() (628-638 行) |
同维度筛选逻辑,直接调 loadXxxActivities() |
✅ 正确 |
| 发布成功后 switchToDiscover (831-837 行) | 先清空数组+page=1,再调 loadDiscoverActivities() 无 refresh |
✅ 正确 |
manage 权限解析后回落 onPermissionResolved() (434-438 行) |
切换 tab 后调 loadData(),mine 分支会清空并加载 |
✅ 正确 |
运行 node scripts/verify-vue-compile.js pages/activity/index.vue:
校验文件数: 1
模板通过: 1 样式通过: 1 脚本通过: 1
PASS
无语法错误、无未定义变量、this 指向正确(全用 var self = this 或箭头函数)。✅
原始需求三点:
| 位置 | 状态 | 证据 |
|---|---|---|
| 后端 Entity | ✅ 已有 | Activity.java 第 23 行:private String intro; |
| 后端 DTO | ✅ 已有 | ActivityDTO.java 第 13 行:private String intro; |
| 数据库 Schema | ✅ 已有 | schema.sql 第 2134 行:intro VARCHAR(200) DEFAULT NULL COMMENT '活动简介(列表卡片展示)' |
| Web 管理端表单 | ✅ 已有 | ActivityEdit.vue 第 84-86 行:<el-form-item label="活动简介"> + v-model="form.intro" + maxlength=200 |
| Web 管理端保存 | ✅ 已有 | ActivityEdit.vue 第 496 行:payload 含 intro: this.form.intro |
| 小程序活动列表 | ✅ 展示 | index.vue 第 140 行:`<text class="card-desc" v-if="act.intro |
| 小程序创建活动页 | ❌ 没有 | create.vue 无 intro 输入框,仅有 description(第 108-112 行) |
| 小程序详情页海报 | ⚠️ 传的是 description 而非 intro | activity-detail.vue 第 300 行:`:intro="(activity && activity.description) |
小结:后端字段、Web 管理端录入、列表展示均已实现。小程序创建页缺录入入口,详情页海报传了 description 而非 intro。
| 位置 | 状态 | 证据 |
|---|---|---|
| 小程序详情页「生成海报」按钮 | ✅ 有 | activity-detail.vue 第 132 行:<button class="share-btn" @click="generatePoster">生成海报</button> |
| 海报组件 | ✅ 已重设计 | ActivityPoster.vue(755 行):Canvas 绘制,三套模板引擎(gradient/minimal/card),支持模板选择、背景色切换、二维码 CTA |
| 模板选择行 | ✅ 有 | ActivityPoster.vue 第 18-32 行:tplOptions 渲染管理端模板列表 |
| 背景色板 | ✅ 有 | ActivityPoster.vue 第 34-46 行:渐变模板下可切换背景色 |
| 保存功能 | ✅ 有 | ActivityPoster.vue 第 49 行:「保存到相册」按钮 |
小结:海报预览已重设计为独立的 ActivityPoster.vue Canvas 组件,支持模板选择与配色定制。已完成 ✅。
| 位置 | 状态 | 证据 |
|---|---|---|
| 后端 Entity | ✅ 已有 | ActivityPosterTemplate.java(53 行):name/templateKey/mainColor/darkColor/lightColor/bgColors/qrSize/sortOrder/status |
| 后端 Service | ✅ 已有 | ActivityPosterTemplateService.java:listAll/listEnabled/save/delete |
| 后端 Admin Controller | ✅ 已有 | AdminPosterTemplateController.java:`POST /api/admin/poster-template/list |
| 后端公开 Controller | ✅ 已有 | PosterTemplateController.java:POST /api/poster-template/list(小程序端调用) |
| 数据库表 | ✅ 已有 | schema.sql 第 5409 行:CREATE TABLE activity_poster_templates |
| 迁移脚本 | ✅ 已有 | DatabaseInitializer.java 第 3106-3107 行:迁移 381 建表 + 初始化 3 套种子模板;第 3139-3141 行:迁移 388 给 activities 加 poster_template_id 列 |
| Web 管理端页面 | ✅ 已有 | PosterTemplateManage.vue(360 行):列表+新增/编辑/删除弹窗,支持颜色选择器、QR 尺寸、排序、启用/停用 |
| 路由注册 | ✅ 已有 | router/index.js 第 723 行:path: 'poster-template-manage',菜单入口在 Layout.vue 第 246 行 |
| 小程序端接入 | ✅ 已有 | activity-detail.vue 第 808 行:getPosterTemplates() 拉取模板列表传给 <ActivityPoster :templates="posterTemplates"> |
小结:后台海报模板定义功能(CRUD + 启用/停用 + 颜色/尺寸配置)已完整实现 ✅。
| 子需求 | 完成度 | 说明 |
|---|---|---|
| ① 活动支持添加「活动简介」 | 部分完成 ⚠️ | 后端字段/DB/Web 管理端/列表展示均已完成;小程序创建页缺少 intro 输入框;详情页海报传的是 description 而非 intro(activity-detail.vue:300) |
| ② 详情页海报预览重新设计 | 已完成 ✅ | ActivityPoster.vue 是全新 Canvas 组件,支持三套模板引擎、模板选择、背景色切换 |
| ③ 后台自定义海报模板 | 已完成 ✅ | 后端 CRUD + 管理端 PosterTemplateManage.vue + 小程序端接入均已到位 |