/** * 权益状态:权益中心 / 我的权益 / 领取 / 使用 */ import { defineStore } from "pinia"; import { BENEFIT_STATUS } from "@/constant"; import * as benefitApi from "@/api/benefit"; export const useBenefitStore = defineStore("benefit", { state: () => ({ /** 权益中心列表 */ centerList: [], /** 我的权益列表(全部,筛选在 getter 完成) */ myList: [], /** 页头数据行文案 */ headline: "", /** 权益中心筛选类型 all | scenic | stay | food | specialty */ filterType: "all", /** 我的权益子分段 all | usable | invalid */ subTab: "all", loading: false, /** 缓存标记:分别标记两个列表是否已从服务端拉过(onShow 重复进入不再打接口) */ centerLoaded: false, mineLoaded: false, }), getters: { /** 权益中心:按类别筛选后的列表 */ filteredCenter: (state) => state.filterType === "all" ? state.centerList : state.centerList.filter((b) => b.type === state.filterType), /** 我的权益:按状态子分段筛选后的列表 */ filteredMine: (state) => { if (state.subTab === "usable") return state.myList.filter((b) => b.status === BENEFIT_STATUS.CLAIMED); if (state.subTab === "invalid") return state.myList.filter((b) => b.status === BENEFIT_STATUS.EXPIRED); return state.myList; }, /** 我的权益数量角标(Tab3「我的权益」右栏数字) */ usableCount: (state) => state.myList.filter((b) => b.status === BENEFIT_STATUS.CLAIMED).length, counts: (state) => ({ all: state.myList.length, usable: state.myList.filter((b) => b.status === BENEFIT_STATUS.CLAIMED).length, invalid: state.myList.filter((b) => b.status === BENEFIT_STATUS.EXPIRED).length, }), }, actions: { async loadCenter(force = false) { if (this.centerLoaded && !force) return this.centerList; this.loading = true; try { const [list, headline] = await Promise.all([ benefitApi.getBenefitList(), benefitApi.getBenefitHeadline(), ]); this.centerList = list || []; this.headline = headline || ""; this.centerLoaded = true; } finally { this.loading = false; } return this.centerList; }, async loadMine(force = false) { if (this.mineLoaded && !force) return this.myList; const list = await benefitApi.getMyBenefitList(); this.myList = list || []; this.mineLoaded = true; return this.myList; }, async loadAll(force = false) { await Promise.all([this.loadCenter(force), this.loadMine(force)]); }, setFilterType(type) { this.filterType = type; }, setSubTab(tab) { this.subTab = tab; }, /** 领取权益 → 落本地,强制重拉两侧列表 */ async claim(id) { await benefitApi.claimBenefit(id); await Promise.all([this.loadCenter(true), this.loadMine(true)]); }, /** * 记录一次使用(可多次使用,不失效,无幂等约束) */ async use(id) { await benefitApi.useBenefit(id); await Promise.all([this.loadCenter(true), this.loadMine(true)]); }, reset() { this.centerList = []; this.myList = []; this.headline = ""; this.centerLoaded = false; this.mineLoaded = false; this.filterType = "all"; this.subTab = "all"; }, }, });