400 lines
12 KiB
JavaScript
400 lines
12 KiB
JavaScript
// 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 });
|
||
}
|
||
}); |