# LuckyDollars Season6 创建记录

本文记录按《快速建立活动页方案》创建 `LuckyDollars Season6` 新活动页的实际步骤。Season6 被当作一个新页面处理：有独立页面目录、独立图片目录、独立页面配置、独立路由和权限配置。为了先验证页面效果，接口参数暂时沿用 Season5。

## 1. 确认页面类型和模块

Season6 属于复杂活动页，包含以下模块：

```text
reward
ranking
lottery
task
withdraw
history
rule
```

页面功能目标：先做出与 Season5 行为一致的活动页，后续再替换 Season6 的真实图片和活动接口参数。

## 2. 创建页面目录

创建新页面目录：

```text
src/views/Activities/LuckyDollars/Season6/
src/views/Activities/LuckyDollars/Season6/components/
```

创建后包含：

```text
src/views/Activities/LuckyDollars/Season6/index.vue
src/views/Activities/LuckyDollars/Season6/page.config.js
src/views/Activities/LuckyDollars/Season6/components/Barrage.vue
src/views/Activities/LuckyDollars/Season6/components/topUser.vue
```

说明：当前 UI 结构参考 Season5 的实现，但 Season6 已抽出自己的页面配置，不直接依赖 Season5 的图片路径和路由。

## 3. 创建页面配置

新增：

```text
src/views/Activities/LuckyDollars/Season6/page.config.js
```

配置内容包括：

```js
export const pageConfig = {
  name: 'LuckyDollars Season6',
  routePath: '/activities/lucky-dollars-season6',
  assetPath: 'Activities/LuckyDollars/Season6/',

  activity: {
    activityId: '2007771533999124198',
    activityCode: '24198',
    rewardActivityType: 'CONSUMPTION_ACTIVITY',
    rankingActivityType: 'USER_RECHARGE_DRAW',
  },

  modules: ['reward', 'ranking', 'lottery', 'task', 'withdraw', 'history', 'rule'],
}
```

当前 `activityId` 和 `activityCode` 沿用 Season5，仅用于验证 Season6 页面是否完整可用。后续接真实 Season6 活动时，只改这里。

## 4. 配置图片路径

页面中不写死路径，统一从 `pageConfig.assetPath` 获取：

```js
const imageUrl = (filename) => getPngUrl(pageConfig.assetPath, filename)
const webpUrl = (filename) => getWebpUrl(pageConfig.assetPath, filename)
```

Season6 的图片路径为：

```text
Activities/LuckyDollars/Season6/
```

开发环境会解析为：

```text
/oss/h5/Azizi/Activities/LuckyDollars/Season6/xxx.png
```

## 5. 创建本地 OSS 图片目录

创建：

```text
public/oss/h5/Azizi/Activities/LuckyDollars/Season6/
```

这个目录用于开发阶段模拟真实 OSS。你已把 Season6 图片补充到该目录。

注意：`vite.config.js` 中 `/oss` 开发代理已调整为“本地 public 文件优先，本地不存在再代理 CDN”。这样本地 Season6 图片可以直接被 dev server 读取。

## 6. 按图片清单配置多语言

Season6 使用图片清单中的支持语言生成多语言图片回退。

在 `page.config.js` 中声明哪些图片支持语言后缀：

```js
images: {
  localized: {
    helpInfo: ['ar'],
    historyBg: ['ar'],
    historyBt: ['ar'],
    lotteryBt: ['ar'],
    lotteryBtActive: ['ar'],
    rankBt: ['ar'],
    rankBtActive: ['ar'],
    rewardReceive: ['ar'],
    rewardReceived: ['ar'],
    rewardReceiveNot: ['ar'],
    rulesBt: ['ar'],
    ruleInfo: ['ar'],
  },
}
```

页面中使用：

```js
const getImgName = (filename) => {
  return getLocalizedImageName(filename, currentLangType.value)
}
```

如果当前语言没有对应图片，自动回退原图，避免请求不存在的图片。

## 7. 配置排行榜模式

Season6 的排行榜沿用 Season5 接口，属于服务端分页模式：

```js
ranking: {
  loadMode: 'remote',
  pageSize: 20,
  topCount: 3,
}
```

数据流：

```text
首次请求 pageNo = 1
上拉触底后请求 pageNo + 1
把新数据追加到 rankingAdd
rankingTotal = ranking + rankingAdd
```

## 8. 配置抽奖模式

Season6 当前奖品已经画在抽奖背景图上，因此抽奖格子属于 `track-only` 模式：

```js
lottery: {
  prizeRenderMode: 'track-only',
  slotCount: 9,
}
```

含义：

```text
接口奖品用于计算中奖位置
页面只渲染高亮框转圈
不在格子内额外渲染奖品图和文字
```

## 9. 增加路由

在 `src/router/index.js` 中增加：

```js
{
  path: '/activities/lucky-dollars-season6',
  name: 'lucky-dollars-season6',
  component: () => import('../views/Activities/LuckyDollars/Season6/index.vue'),
  meta: { requiresAuth: true },
}
```

访问地址：

```text
/activities/lucky-dollars-season6
```

## 10. 补充安全白名单

在 `src/config/security.js` 的 `PUBLIC_PATHS` 中加入：

```js
'/activities/lucky-dollars-season6'
```

否则页面可能被安全路径检查拦截。

## 11. 补充权限配置

在 `src/utils/permissionManager.js` 的 `ACTIVITIES` 中加入：

```js
'/activities/lucky-dollars-season6'
```

否则页面可能被权限管理拦截。

## 12. 修改页面内跳转来源

页面内跳转到提现页时，`from` 参数改为 Season6 自己的路由：

```js
query: { from: '/activities/lucky-dollars-season6', activeAction: 'incomeShow' }
```

## 13. 当前仍沿用的参考实现

为了快速验证视觉和功能，当前 Season6 的主体模板结构、样式细节、弹幕组件、顶部用户组件等仍参考 Season5 的实现。

本次已先接入以下通用能力，避免新页面只能整页复制：

```text
useLotteryDraw
ActivityLotteryGrid
useActivityAssets
```

已落地内容：

- `useActivityAssets`：Season6 的图片 URL、多语言图片名从 `pageConfig` 读取。
- `ActivityLotteryGrid`：Season6 的抽奖格子、高亮框、中心按钮区域从页面模板中抽离。
- `useLotteryDraw`：Season6 的抽奖转圈动画从页面脚本中抽离。
- `pageConfig.lottery`：抽奖背景内容布局、格子布局、历史按钮位置、奖品展示模式改为配置。

暂未强行改造：

```text
useActivityTabs
useActivityRanking
```

原因：Season6 当前标签页和排行榜与大量现有展示状态耦合，继续硬改收益不高。后续真正新建页面时，初始骨架应直接使用这两个 composable，避免一开始就写多个 `reward/rankShow/lotteryShow/incomeShow` 布尔值。

## 14. 后续给 Codex 建类似页面时的输入

以后建立同类页面时，不需要说“复制某页面”。建议先按 [建页操作模板.md](./建页操作模板.md) 让 Codex 创建专属页面信息 md，再把必要信息填进去，例如：

```text
页面类型：Activities
新页面目录：src/views/Activities/LuckyDollars/Season7
参考页面：src/views/Activities/LuckyDollars/Season6
路由 path：/activities/lucky-dollars-season7
OSS 图片路径：Activities/LuckyDollars/Season7/
模块：reward / ranking / lottery / task / withdraw / history / rule
排行榜分页方式：remote
抽奖奖品展示：track-only
多语言图片：按页面创建信息 md 的 3.1 图片清单处理
接口参数：先沿用 Season6 或填写真实 activityId/activityCode
```

Codex 应产出可运行初始版本，你再调整具体样式和图片对位。

## 15. 本地图片 404 处理记录

开发时曾出现：

```text
GET http://localhost:5173/oss/h5/Azizi/Activities/LuckyDollars/Season6/lotteryBtActive.png 404
```

原因：开发环境的 `/oss` 代理会转发到 CDN。如果本地 dev server 没有优先读取 `public/oss/...`，Season6 这种还没上传到服务端 OSS 的图片就会请求失败。

处理方式：调整 `vite.config.js` 的 `/oss` 代理，先判断请求文件是否存在于项目 `public` 目录，存在则直接返回本地 public 路径；不存在再代理到 CDN。

修改配置后需要重启 `npm run dev`，旧 dev server 不会自动吃到 `vite.config.js` 的变更。

## 16. 验证记录

已运行：

```bash
npm run build
```

结果：构建成功。

构建期间仍有既有警告：

```text
../assets/images/Azizi/secondBg.png referenced in ../assets/images/Azizi/secondBg.png didn't resolve at build time
```

该警告不是 Season6 新增代码引起的，构建仍正常完成。
