375 lines
10 KiB
JavaScript
375 lines
10 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';
|
|
import { createPage } from '../../utils/base-page.js';
|
|
import { fetchGonggaoLunbo, isGonggaoCacheValid } from '../../utils/display-config';
|
|
|
|
// 扫码场景参数名
|
|
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 (isGonggaoCacheValid(app)) {
|
|
this.setData({
|
|
shangpingonggao: app.globalData.shangpingonggao,
|
|
lunboList: this.processImageUrls(app.globalData.shangpinlunbo)
|
|
});
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
fetchGonggaoLunbo(app, 'order_pool')
|
|
.then((data) => {
|
|
this.setData({
|
|
shangpingonggao: data.shangpingonggao || '',
|
|
lunboList: this.processImageUrls(data.shangpinlunbo || [])
|
|
});
|
|
resolve();
|
|
})
|
|
.catch(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 });
|
|
}
|
|
}))
|