Skip to content

shop.ts — 商店 Store

文件: web/src/stores/shop.ts

职责

  • 积分兑换管理
  • 自定义奖励项 CRUD(全部通过 API 调用)
  • 密码验证与设置
  • 兑换历史记录
  • 10 种预设奖励图标

依赖

Store用途
useUserStore读取 shopPointsshopPasswordshopLockUntilshopAttempts;兑换后刷新用户数据

数据加载

  • load(): 通过 2 个 API 并行加载:
    • api.get<ShopReward[]>("/shop/rewards") — 奖励列表
    • api.get<ShopHistory[]>("/shop/history") — 兑换历史
  • 初始化时自动调用。

数据持久化

全部 CRUD 操作均通过 API 调用,不在 Store 内直接操作数据。

方法API 端点方式
load()GET /shop/rewards + GET /shop/history读取
addReward()POST /shop/rewards创建 → 重新 load
updateReward()PUT /shop/rewards/:id更新 → 重新 load
deleteReward()DELETE /shop/rewards/:id删除 → 重新 load
toggleReward()PUT /shop/rewards/:id/toggle切换启用/禁用 → 重新 load
redeemReward()POST /shop/rewards/:id/redeem兑换 → 重新 load + 刷新 userStore
verifyPassword()POST /shop/password/verify验证密码
setPassword()PUT /shop/password设置/修改密码

所有 CRUD 操作后均调用 load() 刷新数据,redeemReward 额外调用 user.load() 同步积分余额。

核心数据结构

typescript
interface ShopReward {
  id: string
  name: string
  cost: number
  icon: string          // 图标名称(对应 presetIcons 中的 value)
  enabled: boolean      // 是否启用
  createdAt: string     // 创建时间
}

interface ShopHistory {
  id: string
  rewardId: string
  rewardName: string
  cost: number
  redeemedAt: string
  pointsBefore: number
  pointsAfter: number
}

Reactive State

属性类型说明
rewardsRef<ShopReward[]>奖励列表
shopHistoryRef<ShopHistory[]>兑换历史
loadingRef<boolean>加载状态
shopPointsComputedRef<number>当前积分(来自 userStore)
availablePointsComputedRef<number>可用积分(同 shopPoints)
hasPasswordComputedRef<boolean>是否已设置密码
lockUntilComputedRef<number>密码锁定截止时间戳
presetIconsconst10 种预设图标:star, gift, game, book, music, sport, art, food, toy, travel

方法

奖励管理

方法签名返回值说明
addReward(data: { name, cost, icon }) => Promise<void>添加奖励,POST /shop/rewards → 重新 load
updateReward(id: string, data: Partial<{ name, cost, icon }>) => Promise<void>更新奖励,PUT /shop/rewards/:id → 重新 load
deleteReward(id: string) => Promise<void>删除奖励,DELETE /shop/rewards/:id → 重新 load
toggleReward(id: string) => Promise<void>启用/禁用奖励,PUT /shop/rewards/:id/toggle → 重新 load

兑换

方法签名返回值说明
redeemReward(rewardId: string) => Promise<boolean>是否成功兑换奖励,成功后重新 load 奖励和用户数据

密码

方法签名返回值说明
verifyPassword(pwd: string) => Promise<boolean>是否匹配验证密码,POST /shop/password/verify
setPassword(newPwd: string, oldPwd?: string) => Promise<boolean>是否成功设置/修改密码,PUT /shop/password

工具

方法签名返回值说明
getIconSvg(icon: string) => stringSVG 路径根据图标名称返回 SVG 文件路径