71 lines
2.9 KiB
JavaScript
71 lines
2.9 KiB
JavaScript
import { getStoreBenefitAPI, getStoreVipListAPI } from "@/apis";
|
|
import useStore from "@/store";
|
|
|
|
// 按账号隔离最近选择,刷新登录令牌后仍可恢复同一门店。
|
|
const selectionKey = () => {
|
|
const version = uni.getAccountInfoSync().miniProgram.envVersion;
|
|
return `${version}_experience_store_${useStore().user.id || "guest"}`;
|
|
};
|
|
|
|
export const getSelectedExperienceStore = () => {
|
|
const value = uni.getStorageSync(selectionKey());
|
|
return value && /^\d+$/.test(String(value.id)) && Number(value.id) > 0
|
|
? { id: String(value.id), name: String(value.name || "") }
|
|
: null;
|
|
};
|
|
|
|
export const rememberExperienceStore = (id, name) => {
|
|
uni.setStorageSync(selectionKey(), { id: String(id), name });
|
|
};
|
|
|
|
// 入口汇总所有门店;找到有效会员即可结束,未开通须查询完整列表。
|
|
export const hasAnyStoreVip = async () => {
|
|
const pageSize = 20;
|
|
let received = 0;
|
|
for (let page = 1; ; page += 1) {
|
|
const result = await getStoreVipListAPI({ page, pageSize });
|
|
const list = result?.list;
|
|
if (!Array.isArray(list) || !Number.isSafeInteger(result.total) || result.total < 0) {
|
|
throw new Error("门店会员列表响应格式异常");
|
|
}
|
|
if (list.some((item) => item?.isVip === true)) return true;
|
|
if (list.some((item) => typeof item?.isVip !== "boolean")) {
|
|
throw new Error("门店会员状态缺失");
|
|
}
|
|
received += list.length;
|
|
if (received >= result.total) return false;
|
|
// 列表尚未读完却返回空页时,不把不完整结果判为未开通。
|
|
if (!list.length) throw new Error("门店会员列表分页异常");
|
|
}
|
|
};
|
|
|
|
// 只接受非负整数,缺失或异常值不能转换成“已用完”的 0 次。
|
|
const normalizeRemaining = (benefit) => {
|
|
const remain = benefit?.remain;
|
|
return Number.isSafeInteger(remain) && remain >= 0 ? remain : "--";
|
|
};
|
|
|
|
export const normalizeStoreMembership = (store) => {
|
|
if (typeof store?.isVip !== "boolean") throw new Error("门店会员状态缺失");
|
|
const active = store.isVip === true;
|
|
return {
|
|
active,
|
|
cardImage: `https://static.shelingxingqiu.com/shootmini/static/coin/store-vip-card-${active ? "active" : "inactive"}.png`,
|
|
expiresAt: active ? String(store.vipExpireAt || "").slice(0, 10).replace(/-/g, "/") || "--" : "",
|
|
// 未开通或已过期统一为 0;有效会员逐项读取后端剩余次数。
|
|
remaining: {
|
|
trial: active ? normalizeRemaining(store.freeTrial) : 0,
|
|
discount: active ? normalizeRemaining(store.discountPurchase) : 0,
|
|
drink: active ? normalizeRemaining(store.drink) : 0,
|
|
},
|
|
};
|
|
};
|
|
|
|
export const loadStoreMembership = async (storeId) => {
|
|
const result = await getStoreBenefitAPI(storeId);
|
|
if (String(result?.storeId) !== String(storeId)) {
|
|
throw new Error("门店权益响应与当前门店不匹配");
|
|
}
|
|
return { name: result.storeName || "", ...normalizeStoreMembership(result) };
|
|
};
|