// 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'; import { createPage } from '../../utils/base-page.js'; // 扫码场景参数名 const SCENE_PARAM = 'scene'; Page(createPage({ 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) { // 解析二维码参数 if (options[SCENE_PARAM]) { try { const scene = decodeURIComponent(options[SCENE_PARAM]); this.shopId = scene; } catch (e) { console.error('scene解码失败', e); } } // 等待全局配置加载完成 this.waitForConfigAndInit(); // 已登录时才检查弹窗 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(); } } }, 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. 扫码进入时绑定店铺 if (this.shopId) { await bindShop(this.shopId); } // 3. 并行加载公告轮播图和商品数据 const [gonggaoResult, shopData] = await Promise.all([ this.loadGonggaoAndLunbo(), fetchShopGoods() ]); // 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 }); } }, /** * 加载公告和轮播图 */ 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, _modalLeaving: false, gonggaoAnim: false, currentTime: this.getCurrentTime() }); }, hideGonggaoDetail() { this.setData({ showGonggaoModal: false, _modalLeaving: true, gonggaoAnim: true }); setTimeout(() => this.setData({ _modalLeaving: false }), 300); }, /** * 刷新所有数据 * 只刷新商品数据 */ async refreshAllData() { if (this.data.isRefreshing) return; this.setData({ isRefreshing: true }); wx.showLoading({ title: '刷新中...', mask: true }); try { // 重新获取商品数据 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/product-detail/product-detail?id=${shangpinId}` }); }, onReachBottom() {}, onShareAppMessage() { return { title: '阿龙电竞', path: '/pages/shangpin/shangpin' }; }, onUnload() { this.setData({ gonggaoAnim: false }); } }))