# bindbox-mini 代码冗余分析

## 项目概述

bindbox-mini 是一个基于 uni-app 的微信小程序项目，主要实现盲盒/抽赏类活动功能。

### 技术栈
- 框架：uni-app (Vue 3 Composition API)
- 样式：SCSS
- 状态管理：Vue ref/computed

### 核心页面
| 页面 | 路径 | 行数 | 功能描述 |
|------|------|------|----------|
| 一番赏 | `pages/activity/yifanshang/index.vue` | 1229 | 格位选择抽奖 |
| 对对碰 | `pages/activity/duiduipeng/index.vue` | 2291 | 配对游戏 |
| 无限赏 | `pages/activity/wuxianshang/index.vue` | 1559 | 多次抽奖 |
| 扭蛋(啪嗒) | `pages/activity/pata/index.vue` | 399 | 入口页面 |

---

## 🔴 已识别的冗余问题

### 1. 模板结构重复

三个主要活动页面（yifanshang/duiduipeng/wuxianshang）共享**几乎相同的页面布局结构**：

```vue
<!-- 重复出现在每个页面 -->
<view class="page-wrapper">
  <view class="bg-decoration">
    <view class="orb orb-1"></view>
    <view class="orb orb-2"></view>
  </view>
  <view class="page-bg">
    <image class="bg-image" :src="coverUrl" mode="aspectFill" />
    <view class="bg-mask"></view>
  </view>
  <scroll-view class="main-scroll" scroll-y>
    <view class="header-card animate-enter"><!-- 相同的 header-card 结构 --></view>
    <view class="section-container"><!-- tabs/pool/records --></view>
  </scroll-view>
</view>
```

**冗余程度**：约100-150行相似模板代码 × 3个页面 = ~400行冗余

---

### 2. 工具函数重复

以下函数在多个页面中**完全重复定义**：

| 函数名 | 出现位置 | 功能 |
|--------|----------|------|
| `cleanUrl(u)` | yifanshang, duiduipeng, wuxianshang | 清理URL字符串 |
| `truthy(v)` | yifanshang, duiduipeng, wuxianshang | 判断真值 |
| `detectBoss(i)` | yifanshang, duiduipeng, wuxianshang | 检测BOSS奖 |
| `unwrap(list)` | yifanshang, duiduipeng, wuxianshang | 解包API返回 |
| `normalizeIssues(list)` | yifanshang, duiduipeng, wuxianshang | 标准化期数据 |
| `normalizeRewards(list)` | yifanshang, duiduipeng, wuxianshang | 标准化奖励数据 |
| `statusToText(s)` | yifanshang, duiduipeng, wuxianshang | 状态转文本 |
| `formatPercent(v)` | yifanshang, duiduipeng, wuxianshang | 格式化百分比 |
| `levelToAlpha(level)` | duiduipeng, wuxianshang | 等级数字转字母 |
| `isFresh(ts)` | yifanshang, duiduipeng, wuxianshang | 判断缓存新鲜度 |
| `getRewardCache()` | yifanshang, duiduipeng, wuxianshang | 获取奖励缓存 |
| `pickLatestIssueId(list)` | yifanshang, duiduipeng, wuxianshang | 查找最新期ID |
| `setSelectedById(id)` | yifanshang, duiduipeng, wuxianshang | 设置选中期 |
| `prevIssue()` / `nextIssue()` | yifanshang, duiduipeng, wuxianshang | 期数切换 |

**冗余程度**：约200-300行工具函数 × 3个页面 = ~700行冗余

---

### 3. API调用逻辑重复

以下API调用模式在多个页面中重复：

```javascript
// fetchDetail - 获取活动详情（3处重复）
async function fetchDetail(id) {
  const data = await getActivityDetail(id)
  detail.value = data || {}
  statusText.value = statusToText(detail.value.status)
  // ...
}

// fetchIssues - 获取期列表（3处重复）
async function fetchIssues(id) {
  const data = await getActivityIssues(id)
  issues.value = normalizeIssues(data)
  // ...
}

// fetchRewardsForIssues - 获取奖励（3处重复）
async function fetchRewardsForIssues(activityId) {
  // ~50行相似代码
}

// fetchWinRecords - 获取购买记录（3处重复）
async function fetchWinRecords(actId, issId) {
  // ~30行相似代码
}
```

**冗余程度**：约150-200行API调用代码 × 3个页面 = ~500行冗余

---

### 4. 样式代码重复

以下SCSS样式在三个页面中几乎**完全相同**：

```scss
// 基础布局（~80行）
.page-wrapper, .bg-decoration, .orb, @keyframes float
.page-bg, .bg-image, .bg-mask, .main-scroll

// 头部卡片（~100行）
.header-card, .header-cover, .header-info, .header-title
.header-price-row, .price-symbol, .price-num, .price-unit
.header-tags, .tag-item, .header-actions, .action-btn, .action-icon

// 板块容器（~50行）
.section-container, .section-header, .section-title, .section-more

// Tabs切换（~50行）
.modern-tabs, .tab-item, .active-dot

// 奖池预览（~80行）
.preview-scroll, .preview-item, .preview-img, .preview-name, .prize-tag

// 购买记录（~60行）
.records-list, .record-item, .record-img, .record-info

// 弹窗样式（~100行）
.rewards-overlay, .rewards-mask, .rewards-panel, .rewards-header, .rewards-list
```

**冗余程度**：约500-600行样式代码 × 3个页面 = ~1500行冗余

---

### 5. 状态管理重复

以下响应式状态在多个页面中重复定义：

```javascript
// 每个页面都有类似的状态定义
const detail = ref({})
const issues = ref([])
const rewardsMap = ref({})
const currentIssueId = ref('')
const selectedIssueIndex = ref(0)
const activityId = ref('')
const tabActive = ref('pool')
const winRecords = ref([])
const rewardsVisible = ref(false)
// ...
```

---

## 📊 冗余统计汇总

| 类别 | 估算冗余行数 | 占比 |
|------|-------------|------|
| 模板结构 | ~400行 | 13% |
| 工具函数 | ~700行 | 22% |
| API调用逻辑 | ~500行 | 16% |
| SCSS样式 | ~1500行 | 48% |
| **合计** | **~3100行** | **100%** |

当前三个主要活动页面总计约 **5079行**（1229+2291+1559），冗余代码约占 **61%**。

---

## ❓ 需要确认的问题

1. **重构方向**：是希望进行完整的组件化重构，还是仅提取共用工具函数？

2. **优先级**：
   - 先处理工具函数冗余？（影响最小，风险最低）
   - 先处理模板/组件冗余？（收益最大，但改动较大）
   - 先处理样式冗余？（提取公共样式文件）

3. **兼容性考虑**：是否需要保留现有的页面独立性（便于后续定制化）？

4. **测试策略**：目前项目有自动化测试吗？重构后如何验证功能正确性？

---

## 🎯 初步建议

### 方案A：渐进式重构（推荐）

1. **第一步**：提取共用工具函数到 `utils/activity.js`
2. **第二步**：提取共用样式到 `styles/activity-common.scss`
3. **第三步**：创建共用组件（ActivityHeader, ActivityTabs, RewardsPopup）
4. **第四步**：重构各活动页面使用共用组件

### 方案B：完全组件化

创建通用活动页面框架 `ActivityPageLayout.vue`，各玩法页面只需实现差异化部分。

---

*文档创建时间：2025-12-25*
