// pages/shangpin/shangpin.js const app = getApp(); import { ensureLogin } from '../../utils/login'; import { fetchShopGoods, bindShop } from '../../utils/shop'; import { backfillUserProfileCache, getSessionToken } from '../../utils/role-tab-bar'; import PopupService from '../../services/popupService.js'; // 🔥 固定参数:扫码时从 scene 中获取店铺ID的字段名(可在此处集中修改) const SCENE_PARAM = 'scene'; // 二维码参数统一使用 scene,解码后即为店铺ID Page({ data: { // 全局变量引用 ossImageUrl: '', lunbozhanwei: '', // 页面数据 shangpingonggao: '', lunboList: [], shangpinleixing: [], shangpinzhuanqu: [], shangpinliebiao: [], // 状态控制 selectedLeixingId: null, filteredData: [], showGonggaoModal: false, gonggaoAnim: true, isLoading: false, isRefreshing: false, hasInitialized: false, currentTime: '' }, // 从二维码解析出的店铺ID(仅在扫码时存在) shopId: null, onLoad(options) { // 🔥 解析二维码参数(scene) if (options[SCENE_PARAM]) { try { // 微信会对 scene 进行编码,需要解码 const scene = decodeURIComponent(options[SCENE_PARAM]); this.shopId = scene; // 例如:dianpu_123 } catch (e) { console.error('scene解码失败', e); } } // 等待全局配置加载完成 this.waitForConfigAndInit(); // 🆕 修改:仅在已登录时检查弹窗,避免未登录时发起请求导致 401 弹窗 const token = getSessionToken(app); if (token) { PopupService.checkAndShow(this, 'index'); } }, // 🆕 页面隐藏时清理弹窗视图 onHide: function () { const popupComp = this.selectComponent('#popupNotice'); if (popupComp && popupComp.cleanup) { popupComp.cleanup(); } }, waitForConfigAndInit() { if (app.globalData.ossImageUrl) { this.setData({ ossImageUrl: app.globalData.ossImageUrl, lunbozhanwei: app.globalData.lunbozhanwei, currentTime: this.getCurrentTime() }); this.initPageData(); } else { setTimeout(() => this.waitForConfigAndInit(), 100); } }, onShow() { backfillUserProfileCache(app); if (this.data.ossImageUrl) { this.setData({ gonggaoAnim: true, currentTime: this.getCurrentTime(), }); } this.registerNotificationComponent(); if (!getSessionToken(app)) { this.setData({ hasInitialized: false, filteredData: [], shangpinleixing: [], shangpinzhuanqu: [], shangpinliebiao: [], }); return; } // 已登录时加载/刷新商品;未登录不自动登录、不跳转 if (!this.data.isLoading) { const needLoad = !this.data.hasInitialized || !this.data.filteredData || this.data.filteredData.length === 0; if (needLoad) { this.initPageData(); } } }, registerNotificationComponent() { const notificationComp = this.selectComponent('#global-notification'); if (notificationComp && notificationComp.showNotification) { app.globalData.globalNotification = { show: (data) => notificationComp.showNotification(data), hide: () => notificationComp.hideNotification() }; } }, getCurrentTime() { const now = new Date(); const year = now.getFullYear(); const month = (now.getMonth() + 1).toString().padStart(2, '0'); const day = now.getDate().toString().padStart(2, '0'); const hour = now.getHours().toString().padStart(2, '0'); const minute = now.getMinutes().toString().padStart(2, '0'); return `${year}-${month}-${day} ${hour}:${minute}`; }, sortByPaixu(list) { if (!list || !Array.isArray(list)) return []; return [...list].sort((a, b) => { const paixuA = a.paixu || 0; const paixuB = b.paixu || 0; if (paixuB !== paixuA) return paixuB - paixuA; return a.id - b.id; }); }, /** * 初始化页面数据(重构后) * 流程:确保登录 → 如有扫码ID则绑定店铺 → 并行加载公告轮播图和商品数据 */ async initPageData() { this.setData({ isLoading: true }); try { // 1. 确保登录(静默,不跳转) await ensureLogin({ page: this }); // 2. 🔥 关键:仅当通过扫码进入且携带了有效的店铺ID时,才执行绑定 if (this.shopId) { await bindShop(this.shopId); } // 3. 并行加载公告轮播图(复用原接口,独立请求)和店铺商品(新接口) const [gonggaoResult, shopData] = await Promise.all([ this.loadGonggaoAndLunbo(), // 公告轮播图使用原有的 wx.request 方式,不受影响 fetchShopGoods() // 商品数据通过封装的 request 获取 ]); // 4. 处理商品数据 const sortedLeixing = this.sortByPaixu(shopData.shangpinleixing || []); const sortedZhuanqu = this.sortByPaixu(shopData.shangpinzhuanqu || []); const sortedShangpin = this.sortByPaixu(shopData.shangpinliebiao || []); // 更新全局缓存(可选,用于其他页面复用) app.globalData.shangpinleixing = sortedLeixing; app.globalData.shangpinzhuanqu = sortedZhuanqu; app.globalData.shangpinliebiao = sortedShangpin; this.setData({ shangpinleixing: sortedLeixing, shangpinzhuanqu: sortedZhuanqu, shangpinliebiao: sortedShangpin, selectedLeixingId: sortedLeixing[0]?.id || null, isLoading: false, hasInitialized: true, }, () => { this.filterShangpinData(); }); } catch (error) { console.error('初始化失败:', error); this.setData({ isLoading: false }); // 错误提示已在各函数内部处理,此处仅做兜底 } }, /** * 加载公告和轮播图(完全复用原逻辑,使用 wx.request,不使用封装 request) */ loadGonggaoAndLunbo() { return new Promise((resolve, reject) => { // 如果全局已有数据,直接使用 if (app.globalData.shangpingonggao && app.globalData.shangpinlunbo.length > 0) { this.setData({ shangpingonggao: app.globalData.shangpingonggao, lunboList: this.processImageUrls(app.globalData.shangpinlunbo) }); resolve(); return; } wx.request({ url: app.globalData.apiBaseUrl + '/peizhi/shangpingonggao/', method: 'POST', header: { 'content-type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data) { const data = res.data; app.globalData.shangpingonggao = data.shangpingonggao || ''; app.globalData.shangpinlunbo = data.shangpinlunbo || []; this.setData({ shangpingonggao: app.globalData.shangpingonggao, lunboList: this.processImageUrls(app.globalData.shangpinlunbo) }); resolve(); } else { reject(new Error('请求失败')); } }, fail: reject }); }); }, processImageUrls(urlList) { if (!urlList || !Array.isArray(urlList)) return []; return urlList.map(url => url.startsWith('http') ? url : this.data.ossImageUrl + url); }, /** * 筛选商品数据(完全复用原有逻辑,不做任何改动) */ filterShangpinData() { const { selectedLeixingId, shangpinzhuanqu, shangpinliebiao } = this.data; if (!selectedLeixingId || !shangpinzhuanqu || !shangpinliebiao) { this.setData({ filteredData: [] }); return; } const zhuanquByLeixing = new Map(); shangpinzhuanqu.forEach(zhuanqu => { if (zhuanqu.leixing_id === selectedLeixingId) { if (!zhuanquByLeixing.has(selectedLeixingId)) { zhuanquByLeixing.set(selectedLeixingId, []); } zhuanquByLeixing.get(selectedLeixingId).push(zhuanqu); } }); const shangpinByZhuanqu = new Map(); shangpinliebiao.forEach(shangpin => { if (shangpin.leixing_id === selectedLeixingId && shangpin.zhuanqu_id) { const zhuanquId = shangpin.zhuanqu_id; if (!shangpinByZhuanqu.has(zhuanquId)) { shangpinByZhuanqu.set(zhuanquId, []); } const jiage = parseFloat(shangpin.jiage) || 0; const priceInteger = Math.floor(jiage); let priceDecimal = '00'; const decimalPart = (jiage - priceInteger).toFixed(2); if (decimalPart > 0) { priceDecimal = decimalPart.toString().split('.')[1]; } shangpinByZhuanqu.get(zhuanquId).push({ id: shangpin.id, biaoqian: shangpin.biaoqian, jiage: jiage, priceInteger: priceInteger, priceDecimal: priceDecimal, tupian_url: shangpin.tupian_url, duiwai_xiaoliang: shangpin.duiwai_xiaoliang || 0, paixu: shangpin.paixu || 0 }); } }); const filteredData = []; const currentZhuanquList = zhuanquByLeixing.get(selectedLeixingId) || []; currentZhuanquList.forEach(zhuanqu => { const shangpinList = shangpinByZhuanqu.get(zhuanqu.id) || []; if (shangpinList.length > 0) { filteredData.push({ zhuanqu: { id: zhuanqu.id, mingzi: zhuanqu.mingzi, paixu: zhuanqu.paixu || 0 }, shangpinList: shangpinList }); } }); const sortedFilteredData = filteredData.sort((a, b) => { const paixuA = a.zhuanqu.paixu || 0; const paixuB = b.zhuanqu.paixu || 0; if (paixuB !== paixuA) return paixuB - paixuA; return a.zhuanqu.id - b.zhuanqu.id; }); this.setData({ filteredData: sortedFilteredData }); }, selectLeixing(e) { const leixingId = e.currentTarget.dataset.id; if (this.data.selectedLeixingId === leixingId) return; this.setData({ selectedLeixingId: leixingId }, () => { this.filterShangpinData(); }); }, showGonggaoDetail() { this.setData({ showGonggaoModal: true, gonggaoAnim: false, currentTime: this.getCurrentTime() }); }, hideGonggaoDetail() { this.setData({ showGonggaoModal: false, gonggaoAnim: true }); }, /** * 刷新所有数据(点击刷新按钮) * 只刷新商品数据,公告轮播图保持不变(若需刷新可清空全局缓存后调用 loadGonggaoAndLunbo) */ async refreshAllData() { if (this.data.isRefreshing) return; this.setData({ isRefreshing: true }); wx.showLoading({ title: '刷新中...', mask: true }); try { // 重新获取商品数据(登录状态由 fetchShopGoods 内部确保) const shopData = await fetchShopGoods(); // 公告轮播图通常不需要随刷新按钮更新,保持原样 const sortedLeixing = this.sortByPaixu(shopData.shangpinleixing || []); const sortedZhuanqu = this.sortByPaixu(shopData.shangpinzhuanqu || []); const sortedShangpin = this.sortByPaixu(shopData.shangpinliebiao || []); app.globalData.shangpinleixing = sortedLeixing; app.globalData.shangpinzhuanqu = sortedZhuanqu; app.globalData.shangpinliebiao = sortedShangpin; this.setData({ shangpinleixing: sortedLeixing, shangpinzhuanqu: sortedZhuanqu, shangpinliebiao: sortedShangpin, selectedLeixingId: sortedLeixing[0]?.id || null, isRefreshing: false }, () => { this.filterShangpinData(); }); wx.hideLoading(); wx.showToast({ title: '刷新成功', icon: 'success', duration: 1500 }); } catch (error) { wx.hideLoading(); this.setData({ isRefreshing: false }); } }, goToDetail(e) { const shangpinId = e.currentTarget.dataset.id; if (!shangpinId) return; wx.navigateTo({ url: `/pages/shangpinxiangqing/shangpinxiangqing?id=${shangpinId}` }); }, onReachBottom() {}, onShareAppMessage() { return { title: '阿龙电竞', path: '/pages/shangpin/shangpin' }; }, onUnload() { this.setData({ gonggaoAnim: false }); } });