修正了 pages 名为拼音的问题
This commit is contained in:
@@ -1,400 +1,391 @@
|
||||
// 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 });
|
||||
}
|
||||
// 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';
|
||||
|
||||
// 扫码场景参数名
|
||||
const SCENE_PARAM = 'scene';
|
||||
|
||||
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) {
|
||||
// 解析二维码参数
|
||||
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();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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. 扫码进入时绑定店铺
|
||||
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,
|
||||
gonggaoAnim: false,
|
||||
currentTime: this.getCurrentTime()
|
||||
});
|
||||
},
|
||||
|
||||
hideGonggaoDetail() {
|
||||
this.setData({
|
||||
showGonggaoModal: false,
|
||||
gonggaoAnim: true
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 刷新所有数据
|
||||
* 只刷新商品数据
|
||||
*/
|
||||
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 });
|
||||
}
|
||||
});
|
||||
@@ -113,7 +113,6 @@
|
||||
class="shangpin-image"
|
||||
lazy-load="{{true}}"
|
||||
/>
|
||||
<!-- 移除已售标签 -->
|
||||
</view>
|
||||
|
||||
<!-- 商品标题 -->
|
||||
|
||||
@@ -1,571 +1,413 @@
|
||||
/* ===== 1. 全局样式 ===== */
|
||||
.shangpin-page {
|
||||
min-height: 100vh;
|
||||
padding-top: 3px;
|
||||
background: linear-gradient(180deg, #f5faff 0%, #f0f8ff 100%);
|
||||
}
|
||||
|
||||
min-height: 100vh;
|
||||
padding-top: 3px;
|
||||
background: linear-gradient(180deg, #f5faff 0%, #f0f8ff 100%);
|
||||
}
|
||||
|
||||
/* ===== 2. 公告栏样式 ===== */
|
||||
.gonggao-box {
|
||||
margin: 20rpx 30rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(220, 255, 220, 0.85) 0%,
|
||||
rgba(255, 255, 200, 0.85) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 25rpx;
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 100, 0, 0.08);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
margin: 20rpx 30rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(220, 255, 220, 0.85) 0%,
|
||||
rgba(255, 255, 200, 0.85) 100%);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 25rpx;
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 100, 0, 0.08);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.gonggao-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.gonggao-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gonggao-icon image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.gonggao-icon image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.gonggao-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
margin-top: 2.5px; /* 视觉上的微小修正 */
|
||||
}
|
||||
.gonggao-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-top: 4px; /* 视觉上微微下调,不要删*/
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.gonggao-text {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
padding-right: 50rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
.gonggao-text {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
padding-right: 50rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.gonggao-anim {
|
||||
animation: marquee 10s linear infinite;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
.gonggao-anim {
|
||||
animation: marquee 10s linear infinite;
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 3. 轮播图样式 ===== */
|
||||
.lunbo-container {
|
||||
margin: 0 30rpx 30rpx;
|
||||
height: 350rpx;
|
||||
border-radius: 25rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.lunbo-swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.lunbo-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.lunbo-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lunbo-placeholder image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 刷新按钮 */
|
||||
.refresh-btn {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.refresh-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
transition: transform 0.3s;
|
||||
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
.refreshing {
|
||||
animation: rotate360 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate360 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.refresh-dot {
|
||||
position: absolute;
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #ffcc00;
|
||||
border-radius: 50%;
|
||||
top: 15rpx;
|
||||
right: 15rpx;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 0.8;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 4. 商品展示区域 ===== */
|
||||
.shangpin-container {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
margin-top: -20rpx;
|
||||
padding: 40rpx 30rpx 100rpx;
|
||||
min-height: 800rpx;
|
||||
box-shadow: 0 -10rpx 30rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 商品类型选择 - 完全重新设计,确保左对齐且间距协调 */
|
||||
.leixing-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.leixing-list {
|
||||
display: inline-flex;
|
||||
padding-left: 0; /* 完全去掉左内边距,100%左对齐 */
|
||||
padding-right: 30rpx; /* 只保留右内边距给最后一个元素一点空间 */
|
||||
padding-top: 10rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
/* 关键:完全协调的间距 */
|
||||
.leixing-item {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 30rpx; /* 合适的间距,不会太大也不会太小 */
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 130rpx; /* 固定宽度,确保四个看起来协调 */
|
||||
}
|
||||
|
||||
.leixing-item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.leixing-image-box {
|
||||
width: 110rpx; /* 稍微减小,让整体更紧凑 */
|
||||
height: 110rpx;
|
||||
border-radius: 25rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-bottom: 12rpx;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.leixing-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.leixing-glow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: 25rpx;
|
||||
border: 4rpx solid transparent;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.leixing-active .leixing-glow {
|
||||
border-color: #ffcc00;
|
||||
box-shadow: 0 0 20rpx rgba(255, 204, 0, 0.5);
|
||||
}
|
||||
|
||||
.leixing-active .leixing-image-box {
|
||||
transform: translateY(-8rpx);
|
||||
}
|
||||
|
||||
.leixing-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.leixing-active .leixing-text {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* 专区标题 */
|
||||
.zhuanqu-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 40rpx 0 15rpx;
|
||||
padding-left: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-icon-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* ===== 3. 轮播图样式 ===== */
|
||||
.lunbo-container {
|
||||
margin: 0 30rpx 30rpx;
|
||||
height: 350rpx;
|
||||
border-radius: 25rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.lunbo-swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.lunbo-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.lunbo-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lunbo-placeholder image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 刷新按钮 */
|
||||
.refresh-btn {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 20rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.refresh-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
transition: transform 0.3s;
|
||||
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.2));
|
||||
}
|
||||
|
||||
.refreshing {
|
||||
animation: rotate360 1s linear infinite;
|
||||
}
|
||||
|
||||
.refresh-dot {
|
||||
position: absolute;
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #ffcc00;
|
||||
border-radius: 50%;
|
||||
top: 15rpx;
|
||||
right: 15rpx;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
/* ===== 4. 商品展示区域 ===== */
|
||||
.shangpin-container {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 40rpx 40rpx 0 0;
|
||||
margin-top: -20rpx;
|
||||
padding: 40rpx 30rpx 100rpx;
|
||||
min-height: 800rpx;
|
||||
box-shadow: 0 -10rpx 30rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* 商品类型选择 */
|
||||
.leixing-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.leixing-list {
|
||||
display: inline-flex;
|
||||
padding-left: 0;
|
||||
padding-right: 30rpx;
|
||||
padding-top: 10rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.leixing-item {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 30rpx;
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 130rpx;
|
||||
}
|
||||
|
||||
.leixing-item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.leixing-image-box {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
border-radius: 25rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-bottom: 12rpx;
|
||||
transition: all 0.3s;
|
||||
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.leixing-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.leixing-glow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: 25rpx;
|
||||
border: 4rpx solid transparent;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.leixing-active .leixing-glow {
|
||||
border-color: #ffcc00;
|
||||
box-shadow: 0 0 20rpx rgba(255, 204, 0, 0.5);
|
||||
}
|
||||
|
||||
.leixing-active .leixing-image-box {
|
||||
transform: translateY(-8rpx);
|
||||
}
|
||||
|
||||
.leixing-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.leixing-active .leixing-text {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* 专区标题 */
|
||||
.zhuanqu-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 40rpx 0 15rpx;
|
||||
padding-left: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-icon-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: drop-shadow(0 2rpx 4rpx rgba(255, 204, 0, 0.3));
|
||||
}
|
||||
|
||||
.zhuanqu-sparkle {
|
||||
animation: sparkle 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes sparkle {
|
||||
0%, 100% {
|
||||
transform: scale(1) rotate(0deg);
|
||||
filter: drop-shadow(0 2rpx 4rpx rgba(255, 204, 0, 0.3));
|
||||
}
|
||||
|
||||
.zhuanqu-sparkle {
|
||||
animation: sparkle 2s infinite;
|
||||
50% {
|
||||
transform: scale(1.1) rotate(10deg);
|
||||
filter: drop-shadow(0 4rpx 8rpx rgba(255, 204, 0, 0.6));
|
||||
}
|
||||
|
||||
@keyframes sparkle {
|
||||
0%, 100% {
|
||||
transform: scale(1) rotate(0deg);
|
||||
filter: drop-shadow(0 2rpx 4rpx rgba(255, 204, 0, 0.3));
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1) rotate(10deg);
|
||||
filter: drop-shadow(0 4rpx 8rpx rgba(255, 204, 0, 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
.zhuanqu-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-text::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -8rpx;
|
||||
width: 60rpx;
|
||||
height: 4rpx;
|
||||
background: linear-gradient(90deg, #ffcc00, transparent);
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
|
||||
/* 商品网格 */
|
||||
.shangpin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 25rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.shangpin-card {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.shangpin-card:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.shangpin-image-box {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.shangpin-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
||||
/* 商品标题区域 - 协调紧凑 */
|
||||
.shangpin-title {
|
||||
height: 75rpx;
|
||||
padding: 6rpx 12rpx 2rpx 12rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 26rpx;
|
||||
color: #000;
|
||||
line-height: 34rpx;
|
||||
font-weight: 450; /* 微调粗细,更加协调 */
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 价格和购买按钮 - 协调紧凑 */
|
||||
.shangpin-footer {
|
||||
height: 50rpx;
|
||||
padding: 0 12rpx 8rpx 12rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.price-icon {
|
||||
font-size: 24rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
margin-right: 2rpx;
|
||||
}
|
||||
|
||||
.price-integer {
|
||||
font-size: 32rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.price-decimal {
|
||||
font-size: 24rpx;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #ff4444, #ff6666);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 68, 68, 0.3);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.buy-btn:active {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.buy-icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* ===== 5. 空状态 ===== */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 40rpx;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
color: #999;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.empty-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx 60rpx;
|
||||
border-radius: 50rpx;
|
||||
box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
/* ===== 6. 弹窗样式 ===== */
|
||||
.gonggao-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 600rpx;
|
||||
background: white;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.2);
|
||||
z-index: 1001;
|
||||
animation: modalShow 0.3s;
|
||||
}
|
||||
|
||||
@keyframes modalShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 40rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
font-size: 40rpx;
|
||||
color: #999;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.modal-close:active {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: 600rpx;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.modal-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* ===== 7. 加载提示 ===== */
|
||||
.loading-toast {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 30rpx 50rpx;
|
||||
border-radius: 25rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border: 6rpx solid rgba(255, 255, 255, 0.3);
|
||||
border-top-color: white;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 26rpx;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.zhuanqu-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.zhuanqu-text::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -8rpx;
|
||||
width: 60rpx;
|
||||
height: 4rpx;
|
||||
background: linear-gradient(90deg, #ffcc00, transparent);
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
|
||||
/* 商品网格 */
|
||||
.shangpin-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 25rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.shangpin-card {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.shangpin-card:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.shangpin-image-box {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.shangpin-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
||||
/* 商品标题区域 */
|
||||
.shangpin-title {
|
||||
height: 75rpx;
|
||||
padding: 6rpx 12rpx 2rpx 12rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 26rpx;
|
||||
color: #000;
|
||||
line-height: 34rpx;
|
||||
font-weight: 450;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 价格和购买按钮 */
|
||||
.shangpin-footer {
|
||||
height: 50rpx;
|
||||
padding: 0 12rpx 8rpx 12rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.price-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #ff4444, #ff6666);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 68, 68, 0.3);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.buy-btn:active {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.buy-icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* ===== 5. 空状态 ===== */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 40rpx;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
color: #999;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.empty-btn {
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
color: white;
|
||||
font-size: 28rpx;
|
||||
padding: 20rpx 60rpx;
|
||||
border-radius: 50rpx;
|
||||
box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
/* ===== 6. 弹窗样式 ===== */
|
||||
.gonggao-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user