From 542e46142db52e722dd46a1178334524709a317c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Tue, 27 Jan 2026 11:20:38 +0800
Subject: [PATCH 01/22] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E6=9B=B4=E6=94=B9?=
=?UTF-8?q?=E5=88=B0update=E5=88=86=E6=94=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app.json | 6 +-
custom-tab-bar/index.js | 20 +-
pages/evaluate2/index.js | 468 +++++++++++++++++++++++++
pages/evaluate2/index.json | 5 +
pages/evaluate2/index.wxml | 78 +++++
pages/evaluate2/index.wxss | 450 ++++++++++++++++++++++++
pages/evaluate2/one.js | 463 ++++++++++++++++++++++++
pages/evaluate2/one.json | 5 +
pages/evaluate2/one.wxml | 100 ++++++
pages/evaluate2/one.wxss | 560 ++++++++++++++++++++++++++++++
pages/evaluate2/product-list.js | 486 ++++++++++++++++++++++++++
pages/evaluate2/product-list.json | 5 +
pages/evaluate2/product-list.wxml | 72 ++++
pages/evaluate2/product-list.wxss | 415 ++++++++++++++++++++++
pages/evaluate2/spec-detail.js | 102 ++++++
pages/evaluate2/spec-detail.json | 5 +
pages/evaluate2/spec-detail.wxml | 59 ++++
pages/evaluate2/spec-detail.wxss | 401 +++++++++++++++++++++
18 files changed, 3689 insertions(+), 11 deletions(-)
create mode 100644 pages/evaluate2/index.js
create mode 100644 pages/evaluate2/index.json
create mode 100644 pages/evaluate2/index.wxml
create mode 100644 pages/evaluate2/index.wxss
create mode 100644 pages/evaluate2/one.js
create mode 100644 pages/evaluate2/one.json
create mode 100644 pages/evaluate2/one.wxml
create mode 100644 pages/evaluate2/one.wxss
create mode 100644 pages/evaluate2/product-list.js
create mode 100644 pages/evaluate2/product-list.json
create mode 100644 pages/evaluate2/product-list.wxml
create mode 100644 pages/evaluate2/product-list.wxss
create mode 100644 pages/evaluate2/spec-detail.js
create mode 100644 pages/evaluate2/spec-detail.json
create mode 100644 pages/evaluate2/spec-detail.wxml
create mode 100644 pages/evaluate2/spec-detail.wxss
diff --git a/app.json b/app.json
index 42a3cbf..0a00338 100644
--- a/app.json
+++ b/app.json
@@ -5,6 +5,10 @@
"pages/evaluate1/index",
"pages/evaluate1/product-list",
"pages/evaluate1/spec-detail",
+ "pages/evaluate2/index",
+ "pages/evaluate2/one",
+ "pages/evaluate2/product-list",
+ "pages/evaluate2/spec-detail",
"pages/settlement/index",
"pages/publish/index",
"pages/buyer/index",
@@ -77,7 +81,7 @@
"text": "消息"
},
{
- "pagePath": "pages/evaluate1/index",
+ "pagePath": "pages/evaluate2/index",
"text": "估"
},
{
diff --git a/custom-tab-bar/index.js b/custom-tab-bar/index.js
index 031c1b2..1d90d18 100644
--- a/custom-tab-bar/index.js
+++ b/custom-tab-bar/index.js
@@ -15,7 +15,7 @@ Component({
tabBarItems: [
{ key: 'index', route: 'pages/index/index' },
{ key: 'chat', route: 'pages/chat/index', badgeKey: 'chat' },
- { key: 'evaluate', route: 'pages/evaluate1/index' },
+ { key: 'evaluate', route: 'pages/evaluate2/one' },
{ key: 'settlement', route: 'pages/settlement/index' },
{ key: 'favorites', route: 'pages/favorites/index' },
{ key: 'profile', route: 'pages/profile/index' }
@@ -94,7 +94,7 @@ Component({
const tabBarPages = [
'pages/index/index',
'pages/chat/index',
- 'pages/evaluate1/index',
+ 'pages/evaluate2/one',
'pages/settlement/index',
'pages/favorites/index',
'pages/profile/index'
@@ -178,11 +178,11 @@ Component({
// 跳转到估价页面
goToEvaluatePage() {
- console.log('点击了估价按钮,跳转到evaluate1页面')
+ console.log('点击了估价按钮,跳转到evaluate2/one页面')
wx.switchTab({
- url: '/pages/evaluate1/index',
+ url: '/pages/evaluate2/one',
success: (res) => {
- console.log('switchTab到evaluate1成功:', res)
+ console.log('switchTab到evaluate2/one成功:', res)
// 更新选中状态
this.setData({ selected: 'evaluate' })
// 更新全局数据
@@ -192,13 +192,13 @@ Component({
}
},
fail: (err) => {
- console.error('switchTab到evaluate1失败:', err)
+ console.error('switchTab到evaluate2/one失败:', err)
// 失败时尝试使用reLaunch
- console.log('尝试使用reLaunch跳转到evaluate1...')
+ console.log('尝试使用reLaunch跳转到evaluate2/one...')
wx.reLaunch({
- url: '/pages/evaluate1/index',
+ url: '/pages/evaluate2/one',
success: (res) => {
- console.log('reLaunch到evaluate1成功:', res)
+ console.log('reLaunch到evaluate2/one成功:', res)
// 更新选中状态
this.setData({ selected: 'evaluate' })
// 更新全局数据
@@ -208,7 +208,7 @@ Component({
}
},
fail: (err) => {
- console.error('reLaunch到evaluate1也失败:', err)
+ console.error('reLaunch到evaluate2/one也失败:', err)
}
})
}
diff --git a/pages/evaluate2/index.js b/pages/evaluate2/index.js
new file mode 100644
index 0000000..2324627
--- /dev/null
+++ b/pages/evaluate2/index.js
@@ -0,0 +1,468 @@
+Page({
+ data: {
+ productName: '',
+ specifications: [],
+ loading: false,
+ error: ''
+ },
+ onLoad(options) {
+ let productName = '';
+ // 首先检查URL参数
+ if (options.productName) {
+ productName = options.productName;
+ } else {
+ // 然后检查本地存储(用于wx.switchTab导航)
+ productName = wx.getStorageSync('selectedProductName') || '';
+ // 清除本地存储中的商品名称,避免影响下次进入
+ if (productName) {
+ wx.removeStorageSync('selectedProductName');
+ }
+ }
+
+ if (productName) {
+ this.setData({ productName: productName });
+ this.loadSpecifications(productName);
+ } else {
+ // 如果没有商品名称参数,跳转到商品列表页面
+ wx.redirectTo({
+ url: '/pages/evaluate2/product-list'
+ });
+ }
+ },
+
+ loadSpecifications(productName) {
+ this.setData({
+ loading: true,
+ specifications: [],
+ error: '' // 清空错误信息,确保加载时只显示加载状态
+ });
+
+ // 尝试从本地存储获取商品规格映射数据
+ const productSpecsMap = wx.getStorageSync('evaluate2ProductSpecsMap') || {};
+
+ if (productSpecsMap && productSpecsMap[productName]) {
+ console.log('从本地存储获取商品规格数据');
+
+ // 提取该商品的规格和价格信息
+ const productSpecs = productSpecsMap[productName];
+
+ // 处理规格数据
+ const specPriceMap = {};
+ productSpecs.forEach(item => {
+ const specStr = item.specification;
+ const price = item.price;
+
+ // 价格为空的不参与计算
+ if (!price || price.trim() === '') {
+ return;
+ }
+
+ if (specStr.length > 0) {
+ // 处理逗号分隔的多个规格
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ if (spec.includes(',')) {
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+
+ specs = processedSpecs;
+
+ // 处理逗号分隔的多个价格
+ const prices = price.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ // 价格为空的不参与计算
+ if (prices.length === 0) {
+ return;
+ }
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0) {
+ // 确保价格索引不超出范围
+ const priceIndex = index % prices.length;
+ const matchedPrice = prices[priceIndex] || '';
+
+ // 只有当价格不为空时才添加该规格
+ if (matchedPrice && matchedPrice.trim() !== '') {
+ // 收集相同规格的所有价格,以便计算平均值
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(matchedPrice);
+ }
+ }
+ });
+ }
+ });
+
+ // 转换为规格对象数组
+ const specifications = Object.keys(specPriceMap).map(spec => {
+ const prices = specPriceMap[spec];
+
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 处理每个价格
+ const processedPrices = prices.map(price => {
+ if (!price || price.trim() === '' || isNaN(parseFloat(price))) {
+ return 0;
+ }
+
+ const priceValue = parseFloat(price);
+
+ // 价格<10的需要按照公式计算
+ if (priceValue < 10 && specInfo) {
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ return specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ return (specInfo.avg - 5) * priceValue;
+ }
+ }
+ // 价格>=10的直接使用
+ return priceValue;
+ }).filter(price => price > 0); // 过滤掉0值
+
+ // 计算处理后价格的平均值
+ let finalPrice = 0;
+ let finalPriceText = '';
+
+ if (processedPrices.length > 0) {
+ const sum = processedPrices.reduce((acc, price) => acc + price, 0);
+ finalPrice = sum / processedPrices.length;
+ finalPriceText = finalPrice.toFixed(2);
+ }
+
+ const specObj = {
+ name: spec,
+ price: finalPriceText,
+ priceText: finalPriceText,
+ finalPrice: finalPrice,
+ finalPriceText: finalPriceText
+ };
+
+ return specObj;
+ });
+
+ // 对规格进行排序
+ specifications.sort((a, b) => {
+ // 解析两个规格
+ const specA = this.parseSpecification(a.name);
+ const specB = this.parseSpecification(b.name);
+
+ // 如果有一个规格解析失败,保持原顺序
+ if (!specA || !specB) {
+ return 0;
+ }
+
+ // 1. 按类型排序:净重在前,毛重在后
+ if (specA.type !== specB.type) {
+ return specA.type === '净重' ? -1 : 1;
+ }
+
+ // 2. 按规格最小值排序:从小到大
+ return specA.min - specB.min;
+ });
+
+ this.setData({
+ specifications: specifications,
+ error: '', // 清除之前的错误
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ } else {
+ // 如果本地存储中没有数据,尝试从本地存储获取原始商品数据
+ const allProducts = wx.getStorageSync('allProducts') || [];
+
+ if (allProducts.length > 0) {
+ console.log('从本地存储获取原始商品数据');
+ this.processSpecifications(productName, allProducts);
+ } else {
+ // 如果本地没有数据,再请求服务器
+ console.log('本地存储中没有数据,请求服务器获取商品数据');
+ const api = require('../../utils/api');
+ api.getProducts(1, 1000, 'all', '').then(result => {
+ // 从返回对象中提取products数组
+ const products = result.products || [];
+ this.processSpecifications(productName, products);
+ }).catch(err => {
+ console.error('获取规格失败:', err);
+ this.setData({
+ error: '获取规格失败,请稍后重试',
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ });
+ }
+ }
+ },
+
+ // 解析规格,提取类型(净重/毛重)和数值范围
+ parseSpecification(spec) {
+ const weightMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
+ if (weightMatch) {
+ const type = weightMatch[1]; // 净重或毛重
+ const min = parseFloat(weightMatch[2]);
+ const max = parseFloat(weightMatch[3]);
+ const avg = (min + max) / 2;
+ return {
+ type: type,
+ min: min,
+ max: max,
+ avg: avg
+ };
+ }
+ return null;
+ },
+
+ processSpecifications(productName, products) {
+ console.log('处理的商品数据数量:', products.length);
+ console.log('当前处理的商品名称:', productName);
+
+ // 检查products是否为空
+ if (!products || products.length === 0) {
+ console.error('商品数据为空');
+ this.setData({
+ error: '商品数据为空',
+ loading: false
+ });
+ return;
+ }
+
+ // 过滤出当前商品名称的所有商品
+ const filteredProducts = products.filter(product => {
+ const match = product.productName === productName;
+ console.log('商品:', product.productName, '规格:', product.specification, '价格:', product.price, '匹配:', match);
+ return match;
+ });
+
+ console.log('过滤后的商品数量:', filteredProducts.length);
+ console.log('过滤后的商品详情:', filteredProducts);
+
+ // 检查filteredProducts是否为空
+ if (filteredProducts.length === 0) {
+ console.error('未找到商品名称为"' + productName + '"的商品');
+ this.setData({
+ error: '未找到对应商品名称的商品',
+ loading: false
+ });
+ return;
+ }
+
+ // 提取规格和价格,处理可能的空值和空格
+ const specPriceMap = {};
+ filteredProducts.forEach((product, productIndex) => {
+ const specStr = (product.specification || product.spec || '').trim();
+ const price = product.price || '';
+
+ console.log(`处理第${productIndex + 1}个商品: 规格字符串='${specStr}', 价格字符串='${price}'`);
+
+ // 价格为空的不参与计算
+ if (!price || price.trim() === '') {
+ console.log(`商品价格为空,跳过处理`);
+ return;
+ }
+
+ if (specStr.length > 0) {
+ // 处理逗号分隔的多个规格,确保每个规格都被正确分割
+ // 首先按逗号分割
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ // 检查规格是否包含多个规格(例如:"净重29-30,净重31-32")
+ if (spec.includes(',')) {
+ // 按中文逗号分割
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+
+ specs = processedSpecs;
+
+ // 处理逗号分隔的多个价格
+ const prices = (price || '').split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ console.log(`规格数组:`, specs);
+ console.log(`价格数组:`, prices);
+
+ // 价格为空的不参与计算
+ if (prices.length === 0) {
+ console.log(`价格数组为空,跳过处理`);
+ return;
+ }
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0) {
+ // 确保价格索引不超出范围
+ const priceIndex = index % prices.length;
+ const matchedPrice = prices[priceIndex] || '';
+ console.log(`规格'${spec}' 配对价格: '${matchedPrice}'`);
+
+ // 只有当价格不为空时才添加该规格
+ if (matchedPrice && matchedPrice.trim() !== '') {
+ // 收集相同规格的所有价格,以便计算平均值
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(matchedPrice);
+ } else {
+ console.log(`规格'${spec}' 价格为空,不添加`);
+ }
+ }
+ });
+ }
+ });
+
+ // 转换为规格对象数组
+ const specifications = Object.keys(specPriceMap).map(spec => {
+ const prices = specPriceMap[spec];
+ console.log(`规格'${spec}' 的所有原始价格:`, prices);
+
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 处理每个价格
+ const processedPrices = prices.map(price => {
+ if (!price || price.trim() === '' || isNaN(parseFloat(price))) {
+ return 0;
+ }
+
+ const priceValue = parseFloat(price);
+ console.log(`处理价格: ${priceValue}`);
+
+ // 价格<10的需要按照公式计算
+ if (priceValue < 10 && specInfo) {
+ console.log(`价格 ${priceValue} < 10,按照公式计算`);
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ return specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ return (specInfo.avg - 5) * priceValue;
+ }
+ }
+ // 价格>=10的直接使用
+ return priceValue;
+ }).filter(price => price > 0); // 过滤掉0值
+
+ console.log(`规格'${spec}' 处理后的价格:`, processedPrices);
+
+ // 计算处理后价格的平均值
+ let finalPrice = 0;
+ let finalPriceText = '';
+
+ if (processedPrices.length > 0) {
+ const sum = processedPrices.reduce((acc, price) => acc + price, 0);
+ finalPrice = sum / processedPrices.length;
+ finalPriceText = finalPrice.toFixed(2);
+ console.log(`规格'${spec}' 处理后价格的平均值: ${finalPriceText} (基于 ${processedPrices.length} 个价格)`);
+ } else {
+ console.log(`规格'${spec}' 没有有效价格`);
+ }
+
+ const specObj = {
+ name: spec,
+ price: finalPriceText,
+ priceText: finalPriceText,
+ finalPrice: finalPrice,
+ finalPriceText: finalPriceText
+ };
+
+ console.log('创建的规格对象:', specObj);
+
+ return specObj;
+ });
+
+ console.log('提取的规格和价格:', specifications);
+
+ // 对规格进行排序
+ specifications.sort((a, b) => {
+ // 解析两个规格
+ const specA = this.parseSpecification(a.name);
+ const specB = this.parseSpecification(b.name);
+
+ // 如果有一个规格解析失败,保持原顺序
+ if (!specA || !specB) {
+ return 0;
+ }
+
+ // 1. 按类型排序:净重在前,毛重在后
+ if (specA.type !== specB.type) {
+ return specA.type === '净重' ? -1 : 1;
+ }
+
+ // 2. 按规格最小值排序:从小到大
+ return specA.min - specB.min;
+ });
+
+ console.log('排序后的规格:', specifications);
+
+ this.setData({
+ specifications: specifications,
+ error: '', // 清除之前的错误
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ },
+
+ // 跳转到规格详情页面
+ goToSpecDetail(e) {
+ const specItem = e.currentTarget.dataset.spec;
+ console.log('点击的规格项:', specItem);
+ console.log('传递的价格:', specItem.finalPriceText);
+ wx.navigateTo({
+ url: `/pages/evaluate2/spec-detail?productName=${encodeURIComponent(this.data.productName)}&specification=${encodeURIComponent(specItem.name)}&price=${encodeURIComponent(specItem.finalPriceText)}`
+ });
+ },
+
+ // 返回上一页
+ goBack() {
+ wx.navigateBack();
+ },
+
+ // 返回商品列表页面
+ goBackToProductList() {
+ // 从本地存储中获取之前选择的分类
+ const selectedCategory = wx.getStorageSync('selectedCategory') || '';
+ console.log('返回商品列表页面,之前选择的分类:', selectedCategory);
+
+ // 构建跳转URL,如果有分类参数就传递
+ let url = '/pages/evaluate2/product-list';
+ if (selectedCategory) {
+ url += '?category=' + encodeURIComponent(selectedCategory);
+ }
+
+ wx.redirectTo({
+ url: url
+ });
+ },
+
+ // 下拉刷新
+ onPullDownRefresh() {
+ console.log('开始下拉刷新');
+ if (this.data.productName) {
+ this.loadSpecifications(this.data.productName);
+ } else {
+ wx.stopPullDownRefresh();
+ }
+ }
+});
\ No newline at end of file
diff --git a/pages/evaluate2/index.json b/pages/evaluate2/index.json
new file mode 100644
index 0000000..09e623a
--- /dev/null
+++ b/pages/evaluate2/index.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {},
+ "enablePullDownRefresh": true,
+ "backgroundTextStyle": "dark"
+}
\ No newline at end of file
diff --git a/pages/evaluate2/index.wxml b/pages/evaluate2/index.wxml
new file mode 100644
index 0000000..0a664b1
--- /dev/null
+++ b/pages/evaluate2/index.wxml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+ 正在加载规格数据...
+
+
+
+
+ ⚠️
+ {{error}}
+
+
+
+
+
+
+
+
+
+
+ 商品名称
+
+
+ {{productName}}
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+ 参考价格
+ ¥{{item.finalPriceText}}
+
+ →
+
+
+
+
+
+ 暂无更多规格选择
+
+
+
+
+
+ 📋
+ 该商品暂无可用规格
+
+
+
+
\ No newline at end of file
diff --git a/pages/evaluate2/index.wxss b/pages/evaluate2/index.wxss
new file mode 100644
index 0000000..1e117b3
--- /dev/null
+++ b/pages/evaluate2/index.wxss
@@ -0,0 +1,450 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
+ font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
+}
+
+.header {
+ background: #fff;
+ box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.08);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.header-content {
+ padding: 30rpx 0;
+ text-align: center;
+}
+
+.title {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ letter-spacing: 2rpx;
+}
+
+.content {
+ flex: 1;
+ padding: 16rpx;
+}
+
+/* 加载状态 */
+.loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+}
+
+.loading-spinner {
+ width: 80rpx;
+ height: 80rpx;
+ border: 8rpx solid rgba(74, 144, 226, 0.2);
+ border-top: 8rpx solid #4a90e2;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 32rpx;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+ font-size: 28rpx;
+ color: #666;
+ font-weight: 500;
+}
+
+/* 错误提示卡片 */
+.error-card {
+ background: #fff;
+ border-radius: 16rpx;
+ padding: 48rpx;
+ margin: 32rpx 0;
+ box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.08);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+}
+
+.error-icon {
+ font-size: 80rpx;
+ margin-bottom: 24rpx;
+}
+
+.error-text {
+ font-size: 28rpx;
+ color: #e74c3c;
+ margin-bottom: 32rpx;
+ line-height: 1.5;
+}
+
+/* 按钮样式 */
+.button-group {
+ display: flex;
+ gap: 16rpx;
+ width: 100%;
+ max-width: 600rpx;
+}
+
+.btn-primary {
+ flex: 1;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
+ color: #fff;
+ border: none;
+ box-shadow: 0 4rpx 12rpx rgba(96, 165, 250, 0.4);
+ transition: all 0.3s ease;
+}
+
+.btn-primary:hover {
+ transform: translateY(-2rpx);
+ box-shadow: 0 6rpx 16rpx rgba(74, 144, 226, 0.5);
+}
+
+.btn-secondary {
+ flex: 1;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: #fff;
+ color: #4a90e2;
+ border: 2rpx solid #4a90e2;
+ transition: all 0.3s ease;
+}
+
+.btn-secondary:hover {
+ background: rgba(74, 144, 226, 0.05);
+ transform: translateY(-2rpx);
+}
+
+.btn-back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8rpx 24rpx;
+ font-size: 24rpx;
+ color: #4a90e2;
+ background: transparent;
+ border: 1rpx solid #4a90e2;
+ border-radius: 20rpx;
+ transition: all 0.3s ease;
+ box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
+}
+
+.btn-back:hover {
+ background: rgba(74, 144, 226, 0.1);
+ transform: translateY(-2rpx);
+ box-shadow: 0 4rpx 12rpx rgba(74, 144, 226, 0.2);
+}
+
+.btn-back-icon {
+ margin-right: 8rpx;
+ font-size: 20rpx;
+}
+
+.btn-back-text {
+ font-size: 22rpx;
+}
+
+/* 商品信息卡片 */
+.product-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx;
+ margin-bottom: 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+}
+
+.product-info-container {
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.product-info-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16rpx;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.product-label {
+ font-size: 24rpx;
+ color: #666;
+ font-weight: 500;
+ flex: 1;
+}
+
+.product-name {
+ font-size: 32rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+ margin-top: 12rpx;
+ padding: 12rpx 0;
+ border-top: 1rpx solid #f1f5f9;
+}
+
+/* 规格列表区域 */
+.spec-section {
+ margin-top: 24rpx;
+}
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24rpx;
+ padding: 0 8rpx;
+}
+
+.section-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ padding-left: 16rpx;
+ border-left: 6rpx solid #4a90e2;
+}
+
+.section-count {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(74, 144, 226, 0.1);
+ padding: 6rpx 16rpx;
+ border-radius: 20rpx;
+}
+
+/* 规格网格布局 */
+.spec-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20rpx;
+ margin-top: 16rpx;
+}
+
+/* 规格卡片 */
+.spec-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ transition: all 0.3s ease;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+ min-height: 200rpx;
+ display: flex;
+ flex-direction: column;
+}
+
+.spec-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 6rpx;
+ height: 100%;
+ background: linear-gradient(180deg, #60a5fa 0%, #3b82f6 100%);
+}
+
+.spec-card:hover {
+ transform: translateY(-6rpx);
+ box-shadow: 0 12rpx 32rpx rgba(0,0,0,0.15);
+ background: rgba(255, 255, 255, 1);
+}
+
+.spec-card:active {
+ transform: translateY(-2rpx);
+ box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.12);
+}
+
+.spec-info {
+ margin-bottom: 20rpx;
+ flex: 1;
+ display: flex;
+ align-items: center;
+}
+
+.spec-name {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+ padding-right: 40rpx;
+}
+
+.spec-price {
+ display: flex;
+ flex-direction: column;
+ margin-top: 16rpx;
+}
+
+.price-label {
+ font-size: 20rpx;
+ color: #999;
+ margin-bottom: 4rpx;
+}
+
+.price-value {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #e74c3c;
+ transition: all 0.3s ease;
+}
+
+.spec-card:hover .price-value {
+ transform: scale(1.05);
+}
+
+.spec-arrow {
+ position: absolute;
+ top: 32rpx;
+ right: 28rpx;
+ font-size: 32rpx;
+ color: #4a90e2;
+ font-weight: bold;
+ opacity: 0.6;
+ transition: all 0.3s ease;
+}
+
+.spec-card:hover .spec-arrow {
+ opacity: 1;
+ transform: translateX(4rpx);
+}
+
+/* 空状态 */
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+ text-align: center;
+}
+
+.empty-icon {
+ font-size: 160rpx;
+ margin-bottom: 40rpx;
+ opacity: 0.6;
+}
+
+.empty-text {
+ font-size: 32rpx;
+ color: #666;
+ margin-bottom: 48rpx;
+ line-height: 1.4;
+ padding: 0 40rpx;
+}
+
+/* 响应式设计 */
+@media (max-width: 750rpx) {
+ .content {
+ padding: 20rpx;
+ }
+
+ .spec-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16rpx;
+ }
+
+ .product-card {
+ padding: 28rpx;
+ }
+
+ .spec-card {
+ padding: 28rpx 20rpx;
+ min-height: 180rpx;
+ }
+
+ .title {
+ font-size: 32rpx;
+ }
+
+ .section-title {
+ font-size: 28rpx;
+ }
+
+ .product-name {
+ font-size: 28rpx;
+ }
+
+ .price-value {
+ font-size: 32rpx;
+ }
+
+ .button-group {
+ flex-direction: column;
+ gap: 12rpx;
+ }
+
+ .btn-primary,
+ .btn-secondary {
+ width: 100%;
+ }
+}
+
+/* 小屏幕设备适配 */
+@media (max-width: 414rpx) {
+ .spec-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 12rpx;
+ }
+
+ .spec-card {
+ padding: 24rpx 16rpx;
+ min-height: 160rpx;
+ }
+
+ .spec-name {
+ font-size: 24rpx;
+ }
+
+ .price-value {
+ font-size: 28rpx;
+ }
+}
+
+/* 暂无更多规格提示 */
+.no-more {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 48rpx 0;
+ margin-top: 16rpx;
+ margin-bottom: 100rpx; /* 添加底部边距,避免被导航栏遮挡 */
+}
+
+.no-more-text {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(0, 0, 0, 0.03);
+ padding: 12rpx 32rpx;
+ border-radius: 30rpx;
+ font-weight: 500;
+}
+
+/* 调整规格网格布局,确保不被导航栏遮挡 */
+.spec-section {
+ margin-bottom: 40rpx;
+}
diff --git a/pages/evaluate2/one.js b/pages/evaluate2/one.js
new file mode 100644
index 0000000..47fceb9
--- /dev/null
+++ b/pages/evaluate2/one.js
@@ -0,0 +1,463 @@
+Page({
+ data: {
+ productName: '',
+ specifications: [],
+ loading: false,
+ error: '',
+ categories: [],
+ selectedCategory: ''
+ },
+ onLoad(options) {
+ let productName = '';
+ // 首先检查URL参数
+ if (options.productName) {
+ productName = options.productName;
+ } else {
+ // 然后检查本地存储(用于wx.switchTab导航)
+ productName = wx.getStorageSync('selectedProductName') || '';
+ // 清除本地存储中的商品名称,避免影响下次进入
+ if (productName) {
+ wx.removeStorageSync('selectedProductName');
+ }
+ }
+
+ if (productName) {
+ this.setData({ productName: productName });
+ this.loadSpecifications(productName);
+ } else {
+ // 如果没有商品名称参数,加载所有商品数据并计算
+ this.loadAllData();
+ }
+ },
+
+ // 下拉刷新
+ onPullDownRefresh() {
+ console.log('开始下拉刷新');
+ this.loadAllData();
+ },
+
+ // 加载所有商品数据并计算
+ loadAllData() {
+ this.setData({
+ loading: true,
+ categories: [] // 清空分类数据,确保加载时只显示加载状态
+ });
+
+ const api = require('../../utils/api');
+ // 使用正确的参数调用getProducts方法
+ api.getProducts(1, 1000, 'all', '').then(result => {
+ console.log('API返回结果:', result);
+ // 从返回对象中提取products数组,如果不存在则使用空数组
+ const products = result.products || [];
+ console.log('提取的products数组:', products);
+ console.log('products数组长度:', products.length);
+
+ // 存储原始商品数据到本地存储
+ wx.setStorageSync('allProducts', products);
+
+ // 过滤出有有效category字段的商品(忽略空字符串和仅包含空格的分类)
+ const productsWithCategory = products.filter(product => {
+ if (!product.category) return false;
+ const categoryStr = String(product.category).trim();
+ return categoryStr !== '';
+ });
+ console.log('有有效category的商品:', productsWithCategory);
+ console.log('有有效category的商品数量:', productsWithCategory.length);
+
+ // 提取所有分类(去除前后空格)
+ const categories = [...new Set(productsWithCategory.map(product => {
+ return String(product.category).trim();
+ }))];
+ console.log('提取的分类数组:', categories);
+ console.log('分类数量:', categories.length);
+
+ // 存储分类数据到本地存储
+ wx.setStorageSync('evaluate2Categories', categories);
+
+ // 计算每个分类下的商品名称列表
+ const categoryProductsMap = {};
+ categories.forEach(category => {
+ // 过滤出该分类下的商品
+ const categoryProducts = productsWithCategory.filter(product => {
+ const productCategory = String(product.category).trim();
+ return productCategory === category;
+ });
+
+ // 提取商品名称(去除前后空格,去重)
+ const productNames = [...new Set(categoryProducts.map(product => {
+ // 尝试从多个字段获取商品名称
+ const nameFields = [product.productName, product.name, product.product];
+ for (const field of nameFields) {
+ if (field) {
+ const trimmedName = String(field).trim();
+ if (trimmedName !== '') {
+ return trimmedName;
+ }
+ }
+ }
+ return '';
+ }).filter(name => name !== ''))];
+
+ categoryProductsMap[category] = productNames;
+ });
+
+ // 存储分类商品映射到本地存储
+ wx.setStorageSync('evaluate2CategoryProductsMap', categoryProductsMap);
+
+ // 计算每个商品的规格和价格信息
+ const productSpecsMap = {};
+ products.forEach(product => {
+ // 尝试从多个字段获取商品名称
+ const nameFields = [product.productName, product.name, product.product];
+ let productName = '';
+ for (const field of nameFields) {
+ if (field) {
+ const trimmedName = String(field).trim();
+ if (trimmedName !== '') {
+ productName = trimmedName;
+ break;
+ }
+ }
+ }
+
+ if (productName) {
+ if (!productSpecsMap[productName]) {
+ productSpecsMap[productName] = [];
+ }
+
+ // 提取规格和价格
+ const specStr = (product.specification || product.spec || '').trim();
+ const price = product.price || '';
+
+ if (specStr && price) {
+ productSpecsMap[productName].push({
+ specification: specStr,
+ price: price
+ });
+ }
+ }
+ });
+
+ // 存储商品规格映射到本地存储
+ wx.setStorageSync('evaluate2ProductSpecsMap', productSpecsMap);
+
+ // 加载分类数据到页面
+ this.setData({
+ categories: categories,
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ }).catch(err => {
+ console.error('获取商品数据失败:', err);
+ this.setData({
+ error: '获取商品数据失败,请稍后重试',
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ });
+ },
+
+ // 加载商品分类数据
+ loadCategories() {
+ this.setData({ loading: true });
+
+ // 尝试从本地存储中获取分类数据
+ const categories = wx.getStorageSync('evaluate2Categories') || [];
+
+ if (categories.length > 0) {
+ // 如果本地存储中有分类数据,直接使用
+ console.log('从本地存储获取分类数据:', categories);
+ this.setData({
+ categories: categories,
+ loading: false
+ });
+ } else {
+ // 如果本地存储中没有分类数据,重新加载所有数据
+ this.loadAllData();
+ }
+ },
+
+ loadSpecifications(productName) {
+ if (!productName) {
+ this.setData({
+ error: '请先选择商品',
+ loading: false
+ });
+ return;
+ }
+
+ this.setData({ loading: true, specifications: [] });
+
+ // 直接从本地存储获取商品数据,避免重复请求
+ const localGoods = wx.getStorageSync('goods') || [];
+ console.log('从本地存储获取的商品数量:', localGoods.length);
+
+ if (localGoods.length > 0) {
+ this.processSpecifications(productName, localGoods);
+ } else {
+ // 如果本地没有数据,再请求服务器
+ const api = require('../../utils/api');
+ // 使用正确的参数调用getProducts方法
+ api.getProducts(1, 1000, 'all', '').then(result => {
+ // 从返回对象中提取products数组
+ const products = result.products || [];
+ this.processSpecifications(productName, products);
+ }).catch(err => {
+ console.error('获取规格失败:', err);
+ this.setData({
+ error: '获取规格失败,请稍后重试',
+ loading: false
+ });
+ });
+ }
+ },
+
+ // 解析规格,提取类型(净重/毛重)和数值范围
+ parseSpecification(spec) {
+ const weightMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
+ if (weightMatch) {
+ const type = weightMatch[1]; // 净重或毛重
+ const min = parseFloat(weightMatch[2]);
+ const max = parseFloat(weightMatch[3]);
+ const avg = (min + max) / 2;
+ return {
+ type: type,
+ min: min,
+ max: max,
+ avg: avg
+ };
+ }
+ return null;
+ },
+
+ processSpecifications(productName, products) {
+ console.log('处理的商品数据数量:', products.length);
+ console.log('当前处理的商品名称:', productName);
+
+ // 检查products是否为空
+ if (!products || products.length === 0) {
+ console.error('商品数据为空');
+ this.setData({
+ error: '商品数据为空',
+ loading: false
+ });
+ return;
+ }
+
+ // 过滤出当前商品名称的所有商品
+ const filteredProducts = products.filter(product => {
+ const match = product.productName === productName;
+ console.log('商品:', product.productName, '规格:', product.specification, '价格:', product.price, '匹配:', match);
+ return match;
+ });
+
+ console.log('过滤后的商品数量:', filteredProducts.length);
+ console.log('过滤后的商品详情:', filteredProducts);
+
+ // 检查filteredProducts是否为空
+ if (filteredProducts.length === 0) {
+ console.error('未找到商品名称为"' + productName + '"的商品');
+ this.setData({
+ error: '未找到对应商品名称的商品',
+ loading: false
+ });
+ return;
+ }
+
+ // 提取规格和价格,处理可能的空值和空格
+ const specPriceMap = {};
+ filteredProducts.forEach((product, productIndex) => {
+ const specStr = (product.specification || product.spec || '').trim();
+ const price = product.price || '';
+
+ console.log(`处理第${productIndex + 1}个商品: 规格字符串='${specStr}', 价格字符串='${price}'`);
+
+ // 价格为空的不参与计算
+ if (!price || price.trim() === '') {
+ console.log(`商品价格为空,跳过处理`);
+ return;
+ }
+
+ if (specStr.length > 0) {
+ // 处理逗号分隔的多个规格,确保每个规格都被正确分割
+ // 首先按逗号分割
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ // 检查规格是否包含多个规格(例如:"净重29-30,净重31-32")
+ if (spec.includes(',')) {
+ // 按中文逗号分割
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+
+ specs = processedSpecs;
+
+ // 处理逗号分隔的多个价格
+ const prices = (price || '').split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ console.log(`规格数组:`, specs);
+ console.log(`价格数组:`, prices);
+
+ // 价格为空的不参与计算
+ if (prices.length === 0) {
+ console.log(`价格数组为空,跳过处理`);
+ return;
+ }
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0) {
+ // 确保价格索引不超出范围
+ const priceIndex = index % prices.length;
+ const matchedPrice = prices[priceIndex] || '';
+ console.log(`规格'${spec}' 配对价格: '${matchedPrice}'`);
+
+ // 只有当价格不为空时才添加该规格
+ if (matchedPrice && matchedPrice.trim() !== '') {
+ // 收集相同规格的所有价格,以便计算平均值
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(matchedPrice);
+ } else {
+ console.log(`规格'${spec}' 价格为空,不添加`);
+ }
+ }
+ });
+ }
+ });
+
+ // 转换为规格对象数组
+ const specifications = Object.keys(specPriceMap).map(spec => {
+ const prices = specPriceMap[spec];
+ console.log(`规格'${spec}' 的所有原始价格:`, prices);
+
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 处理每个价格
+ const processedPrices = prices.map(price => {
+ if (!price || price.trim() === '' || isNaN(parseFloat(price))) {
+ return 0;
+ }
+
+ const priceValue = parseFloat(price);
+ console.log(`处理价格: ${priceValue}`);
+
+ // 价格<10的需要按照公式计算
+ if (priceValue < 10 && specInfo) {
+ console.log(`价格 ${priceValue} < 10,按照公式计算`);
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ return specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ return (specInfo.avg - 5) * priceValue;
+ }
+ }
+ // 价格>=10的直接使用
+ return priceValue;
+ }).filter(price => price > 0); // 过滤掉0值
+
+ console.log(`规格'${spec}' 处理后的价格:`, processedPrices);
+
+ // 计算处理后价格的平均值
+ let finalPrice = 0;
+ let finalPriceText = '';
+
+ if (processedPrices.length > 0) {
+ const sum = processedPrices.reduce((acc, price) => acc + price, 0);
+ finalPrice = sum / processedPrices.length;
+ finalPriceText = finalPrice.toFixed(2);
+ console.log(`规格'${spec}' 处理后价格的平均值: ${finalPriceText} (基于 ${processedPrices.length} 个价格)`);
+ } else {
+ console.log(`规格'${spec}' 没有有效价格`);
+ }
+
+ const specObj = {
+ name: spec,
+ price: finalPriceText,
+ priceText: finalPriceText,
+ finalPrice: finalPrice,
+ finalPriceText: finalPriceText
+ };
+
+ console.log('创建的规格对象:', specObj);
+
+ return specObj;
+ });
+
+ console.log('提取的规格和价格:', specifications);
+
+ // 对规格进行排序
+ specifications.sort((a, b) => {
+ // 解析两个规格
+ const specA = this.parseSpecification(a.name);
+ const specB = this.parseSpecification(b.name);
+
+ // 如果有一个规格解析失败,保持原顺序
+ if (!specA || !specB) {
+ return 0;
+ }
+
+ // 1. 按类型排序:净重在前,毛重在后
+ if (specA.type !== specB.type) {
+ return specA.type === '净重' ? -1 : 1;
+ }
+
+ // 2. 按规格最小值排序:从小到大
+ return specA.min - specB.min;
+ });
+
+ console.log('排序后的规格:', specifications);
+
+ this.setData({
+ specifications: specifications,
+ error: '', // 清除之前的错误
+ loading: false
+ });
+ },
+
+ // 跳转到规格详情页面
+ goToSpecDetail(e) {
+ const specItem = e.currentTarget.dataset.spec;
+ console.log('点击的规格项:', specItem);
+ console.log('传递的价格:', specItem.finalPriceText);
+ wx.navigateTo({
+ url: `/pages/evaluate1/spec-detail?productName=${encodeURIComponent(this.data.productName)}&specification=${encodeURIComponent(specItem.name)}&price=${encodeURIComponent(specItem.finalPriceText)}`
+ });
+ },
+
+ // 返回上一页
+ goBack() {
+ wx.navigateBack();
+ },
+
+ // 返回商品列表页面
+ goBackToProductList() {
+ wx.redirectTo({
+ url: '/pages/evaluate1/product-list'
+ });
+ },
+
+ // 选择分类,跳转到商品列表页面
+ selectCategory(e) {
+ const category = e.currentTarget.dataset.category;
+ console.log('选择分类:', category);
+
+ // 跳转到商品列表页面,并传递分类参数
+ wx.redirectTo({
+ url: `/pages/evaluate2/product-list?category=${encodeURIComponent(category)}`
+ });
+ }
+});
\ No newline at end of file
diff --git a/pages/evaluate2/one.json b/pages/evaluate2/one.json
new file mode 100644
index 0000000..09e623a
--- /dev/null
+++ b/pages/evaluate2/one.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {},
+ "enablePullDownRefresh": true,
+ "backgroundTextStyle": "dark"
+}
\ No newline at end of file
diff --git a/pages/evaluate2/one.wxml b/pages/evaluate2/one.wxml
new file mode 100644
index 0000000..f76f3ac
--- /dev/null
+++ b/pages/evaluate2/one.wxml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+ 正在加载数据...
+
+
+
+
+ ⚠️
+ {{error}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item}}
+
+ →
+
+
+
+
+
+
+
+
+ 商品名称
+
+
+ {{productName}}
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+ 参考价格
+ ¥{{item.finalPriceText}}
+
+ →
+
+
+
+
+
+ 暂无更多规格选择
+
+
+
+
+
+ 📋
+ 该商品暂无可用规格
+
+
+
+
\ No newline at end of file
diff --git a/pages/evaluate2/one.wxss b/pages/evaluate2/one.wxss
new file mode 100644
index 0000000..67a8107
--- /dev/null
+++ b/pages/evaluate2/one.wxss
@@ -0,0 +1,560 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
+ font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
+}
+
+.header {
+ background: #fff;
+ box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.08);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.header-content {
+ padding: 30rpx 0;
+ text-align: center;
+}
+
+.title {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ letter-spacing: 2rpx;
+}
+
+.content {
+ flex: 1;
+ padding: 16rpx;
+}
+
+/* 加载状态 */
+.loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+}
+
+.loading-spinner {
+ width: 80rpx;
+ height: 80rpx;
+ border: 8rpx solid rgba(74, 144, 226, 0.2);
+ border-top: 8rpx solid #4a90e2;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 32rpx;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+ font-size: 28rpx;
+ color: #666;
+ font-weight: 500;
+}
+
+/* 错误提示卡片 */
+.error-card {
+ background: #fff;
+ border-radius: 16rpx;
+ padding: 48rpx;
+ margin: 32rpx 0;
+ box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.08);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+}
+
+.error-icon {
+ font-size: 80rpx;
+ margin-bottom: 24rpx;
+}
+
+.error-text {
+ font-size: 28rpx;
+ color: #e74c3c;
+ margin-bottom: 32rpx;
+ line-height: 1.5;
+}
+
+/* 按钮样式 */
+.button-group {
+ display: flex;
+ gap: 16rpx;
+ width: 100%;
+ max-width: 600rpx;
+}
+
+.btn-primary {
+ flex: 1;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
+ color: #fff;
+ border: none;
+ box-shadow: 0 4rpx 12rpx rgba(96, 165, 250, 0.4);
+ transition: all 0.3s ease;
+}
+
+.btn-primary:hover {
+ transform: translateY(-2rpx);
+ box-shadow: 0 6rpx 16rpx rgba(74, 144, 226, 0.5);
+}
+
+.btn-secondary {
+ flex: 1;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: #fff;
+ color: #4a90e2;
+ border: 2rpx solid #4a90e2;
+ transition: all 0.3s ease;
+}
+
+.btn-secondary:hover {
+ background: rgba(74, 144, 226, 0.05);
+ transform: translateY(-2rpx);
+}
+
+.btn-back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8rpx 24rpx;
+ font-size: 24rpx;
+ color: #4a90e2;
+ background: transparent;
+ border: 1rpx solid #4a90e2;
+ border-radius: 20rpx;
+ transition: all 0.3s ease;
+ box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
+}
+
+.btn-back:hover {
+ background: rgba(74, 144, 226, 0.1);
+ transform: translateY(-2rpx);
+ box-shadow: 0 4rpx 12rpx rgba(74, 144, 226, 0.2);
+}
+
+.btn-back-icon {
+ margin-right: 8rpx;
+ font-size: 20rpx;
+}
+
+.btn-back-text {
+ font-size: 22rpx;
+}
+
+/* 商品信息卡片 */
+.product-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx;
+ margin-bottom: 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+}
+
+.product-info-container {
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.product-info-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16rpx;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.product-label {
+ font-size: 24rpx;
+ color: #666;
+ font-weight: 500;
+ flex: 1;
+}
+
+.product-name {
+ font-size: 32rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+ margin-top: 12rpx;
+ padding: 12rpx 0;
+ border-top: 1rpx solid #f1f5f9;
+}
+
+/* 规格列表区域 */
+.spec-section {
+ margin-top: 24rpx;
+}
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24rpx;
+ padding: 0 8rpx;
+}
+
+.section-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ padding-left: 16rpx;
+ border-left: 6rpx solid #4a90e2;
+}
+
+.section-count {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(74, 144, 226, 0.1);
+ padding: 6rpx 16rpx;
+ border-radius: 20rpx;
+}
+
+/* 规格网格布局 */
+.spec-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20rpx;
+ margin-top: 16rpx;
+}
+
+/* 规格卡片 */
+.spec-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ transition: all 0.3s ease;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+ min-height: 200rpx;
+ display: flex;
+ flex-direction: column;
+}
+
+.spec-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 6rpx;
+ height: 100%;
+ background: linear-gradient(180deg, #60a5fa 0%, #3b82f6 100%);
+}
+
+.spec-card:hover {
+ transform: translateY(-6rpx);
+ box-shadow: 0 12rpx 32rpx rgba(0,0,0,0.15);
+ background: rgba(255, 255, 255, 1);
+}
+
+.spec-card:active {
+ transform: translateY(-2rpx);
+ box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.12);
+}
+
+.spec-info {
+ margin-bottom: 20rpx;
+ flex: 1;
+ display: flex;
+ align-items: center;
+}
+
+.spec-name {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+ padding-right: 40rpx;
+}
+
+.spec-price {
+ display: flex;
+ flex-direction: column;
+ margin-top: 16rpx;
+}
+
+.price-label {
+ font-size: 20rpx;
+ color: #999;
+ margin-bottom: 4rpx;
+}
+
+.price-value {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #e74c3c;
+ transition: all 0.3s ease;
+}
+
+.spec-card:hover .price-value {
+ transform: scale(1.05);
+}
+
+.spec-arrow {
+ position: absolute;
+ top: 32rpx;
+ right: 28rpx;
+ font-size: 32rpx;
+ color: #4a90e2;
+ font-weight: bold;
+ opacity: 0.6;
+ transition: all 0.3s ease;
+}
+
+.spec-card:hover .spec-arrow {
+ opacity: 1;
+ transform: translateX(4rpx);
+}
+
+/* 空状态 */
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+ text-align: center;
+}
+
+.empty-icon {
+ font-size: 160rpx;
+ margin-bottom: 40rpx;
+ opacity: 0.6;
+}
+
+.empty-text {
+ font-size: 32rpx;
+ color: #666;
+ margin-bottom: 48rpx;
+ line-height: 1.4;
+ padding: 0 40rpx;
+}
+
+/* 响应式设计 */
+@media (max-width: 750rpx) {
+ .content {
+ padding: 20rpx;
+ }
+
+ .spec-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16rpx;
+ }
+
+ .product-card {
+ padding: 28rpx;
+ }
+
+ .spec-card {
+ padding: 28rpx 20rpx;
+ min-height: 180rpx;
+ }
+
+ .title {
+ font-size: 32rpx;
+ }
+
+ .section-title {
+ font-size: 28rpx;
+ }
+
+ .product-name {
+ font-size: 28rpx;
+ }
+
+ .price-value {
+ font-size: 32rpx;
+ }
+
+ .button-group {
+ flex-direction: column;
+ gap: 12rpx;
+ }
+
+ .btn-primary,
+ .btn-secondary {
+ width: 100%;
+ }
+}
+
+/* 小屏幕设备适配 */
+@media (max-width: 414rpx) {
+ .spec-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 12rpx;
+ }
+
+ .spec-card {
+ padding: 24rpx 16rpx;
+ min-height: 160rpx;
+ }
+
+ .spec-name {
+ font-size: 24rpx;
+ }
+
+ .price-value {
+ font-size: 28rpx;
+ }
+}
+
+/* 暂无更多规格提示 */
+.no-more {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 48rpx 0;
+ margin-top: 16rpx;
+ margin-bottom: 100rpx; /* 添加底部边距,避免被导航栏遮挡 */
+}
+
+.no-more-text {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(0, 0, 0, 0.03);
+ padding: 12rpx 32rpx;
+ border-radius: 30rpx;
+ font-weight: 500;
+}
+
+/* 分类选择区域 */
+.category-section {
+ margin-top: 24rpx;
+ margin-bottom: 40rpx;
+}
+
+.category-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 20rpx;
+ margin-top: 16rpx;
+}
+
+.category-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ transition: all 0.3s ease;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+ min-height: 150rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.category-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 6rpx;
+ height: 100%;
+ background: linear-gradient(180deg, #60a5fa 0%, #3b82f6 100%);
+}
+
+.category-card:hover {
+ transform: translateY(-6rpx);
+ box-shadow: 0 12rpx 32rpx rgba(0,0,0,0.15);
+ background: rgba(255, 255, 255, 1);
+}
+
+.category-card:active {
+ transform: translateY(-2rpx);
+ box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.12);
+}
+
+.category-info {
+ flex: 1;
+ margin-right: 20rpx;
+}
+
+.category-name {
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+}
+
+.category-arrow {
+ font-size: 32rpx;
+ color: #4a90e2;
+ font-weight: bold;
+ opacity: 0.6;
+ transition: all 0.3s ease;
+}
+
+.category-card:hover .category-arrow {
+ opacity: 1;
+ transform: translateX(4rpx);
+}
+
+/* 响应式设计 - 分类区域 */
+@media (max-width: 750rpx) {
+ .category-grid {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 16rpx;
+ }
+
+ .category-card {
+ padding: 28rpx 20rpx;
+ min-height: 130rpx;
+ }
+
+ .category-name {
+ font-size: 28rpx;
+ }
+}
+
+@media (max-width: 414rpx) {
+ .category-grid {
+ grid-template-columns: 1fr;
+ gap: 12rpx;
+ }
+
+ .category-card {
+ padding: 24rpx 16rpx;
+ min-height: 110rpx;
+ }
+
+ .category-name {
+ font-size: 24rpx;
+ }
+}
+
+/* 调整规格网格布局,确保不被导航栏遮挡 */
+.spec-section {
+ margin-bottom: 40rpx;
+}
\ No newline at end of file
diff --git a/pages/evaluate2/product-list.js b/pages/evaluate2/product-list.js
new file mode 100644
index 0000000..f28c65c
--- /dev/null
+++ b/pages/evaluate2/product-list.js
@@ -0,0 +1,486 @@
+Page({
+ data: {
+ productNames: [],
+ loading: false,
+ error: '',
+ category: '',
+ priceRange: { // 价格范围
+ min: 0,
+ max: 0,
+ hasPrice: false
+ }
+ },
+
+ // 解析规格,提取类型(净重/毛重)和数值范围
+ parseSpecification(spec) {
+ const weightMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
+ if (weightMatch) {
+ const type = weightMatch[1]; // 净重或毛重
+ const min = parseFloat(weightMatch[2]);
+ const max = parseFloat(weightMatch[3]);
+ const avg = (min + max) / 2;
+ return {
+ type: type,
+ min: min,
+ max: max,
+ avg: avg
+ };
+ }
+ return null;
+ },
+ onLoad(options) {
+ // 对分类参数进行 URL 解码
+ const category = options.category ? decodeURIComponent(options.category) : '';
+ this.setData({ category: category });
+ console.log('解码后的分类:', category);
+ this.loadProductNames();
+ },
+
+ loadProductNames() {
+ this.setData({
+ loading: true,
+ error: '',
+ productNames: [] // 清空商品名称数据,确保加载时只显示加载状态
+ });
+
+ console.log('开始加载商品列表,当前分类:', this.data.category);
+
+ // 尝试从本地存储中获取分类商品映射数据
+ const categoryProductsMap = wx.getStorageSync('evaluate2CategoryProductsMap') || {};
+
+ if (categoryProductsMap && Object.keys(categoryProductsMap).length > 0) {
+ console.log('从本地存储获取分类商品映射数据');
+
+ // 获取当前分类下的商品名称列表
+ let productNames = [];
+ if (this.data.category) {
+ productNames = categoryProductsMap[this.data.category] || [];
+ console.log(`分类"${this.data.category}"下的商品数量:`, productNames.length);
+ console.log('商品名称列表:', productNames);
+ } else {
+ // 如果没有分类参数,获取所有商品名称
+ const allProductNames = [];
+ Object.values(categoryProductsMap).forEach(names => {
+ allProductNames.push(...names);
+ });
+ // 去重
+ productNames = [...new Set(allProductNames)];
+ console.log('所有商品数量:', productNames.length);
+ }
+
+ // 计算价格范围
+ let priceRange = { min: 0, max: 0, hasPrice: false };
+
+ // 从原始商品数据中计算价格范围
+ const allProducts = wx.getStorageSync('allProducts') || [];
+ if (allProducts.length > 0) {
+ // 过滤出当前分类下的商品
+ const categoryProducts = allProducts.filter(product => {
+ if (!product.category) return false;
+ const productCategory = String(product.category).trim();
+ return productCategory === this.data.category;
+ });
+
+ // 按规格分组计算平均价格
+ const specPriceMap = {};
+ categoryProducts.forEach(product => {
+ if (product.price && (product.specification || product.spec)) {
+ const priceStr = String(product.price).trim();
+ const specStr = String(product.specification || product.spec).trim();
+
+ // 处理逗号分隔的多个价格
+ const priceArray = priceStr.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ // 处理逗号分隔的多个规格
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ if (spec.includes(',')) {
+ // 按中文逗号分割
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+ specs = processedSpecs;
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0 && index < priceArray.length) {
+ const price = priceArray[index];
+ if (price && price.trim() !== '') {
+ const priceValue = parseFloat(price);
+ if (!isNaN(priceValue)) {
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 价格<10的需要按照公式计算
+ let finalPrice = priceValue;
+ if (priceValue < 10 && specInfo) {
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ finalPrice = specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ finalPrice = (specInfo.avg - 5) * priceValue;
+ }
+ }
+
+ // 按规格分组存储价格
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(finalPrice);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ // 计算每个规格的平均价格,然后找出最低和最高
+ const specAvgPrices = [];
+ Object.keys(specPriceMap).forEach(spec => {
+ const prices = specPriceMap[spec];
+ if (prices.length > 0) {
+ const avgPrice = prices.reduce((sum, price) => sum + price, 0) / prices.length;
+ specAvgPrices.push(avgPrice);
+ }
+ });
+
+ if (specAvgPrices.length > 0) {
+ priceRange.min = Math.round(Math.min(...specAvgPrices) * 100) / 100;
+ priceRange.max = Math.round(Math.max(...specAvgPrices) * 100) / 100;
+ priceRange.hasPrice = true;
+ }
+ }
+
+ this.setData({
+ productNames: productNames,
+ priceRange: priceRange,
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ } else {
+ // 如果本地存储中没有数据,尝试从本地存储获取原始商品数据
+ const allProducts = wx.getStorageSync('allProducts') || [];
+
+ if (allProducts.length > 0) {
+ console.log('从本地存储获取原始商品数据');
+
+ // 过滤出有有效category字段的商品
+ const productsWithCategory = allProducts.filter(product => {
+ if (!product.category) return false;
+ const categoryStr = String(product.category).trim();
+ return categoryStr !== '';
+ });
+
+ // 移除价格过滤,获取所有商品
+ let filteredProducts = productsWithCategory;
+
+ // 如果有分类参数,过滤出该分类下的商品
+ if (this.data.category) {
+ console.log('当前分类:', this.data.category);
+ const targetCategory = String(this.data.category).trim();
+ filteredProducts = filteredProducts.filter(product => {
+ if (!product.category) return false;
+ const productCategory = String(product.category).trim();
+ return productCategory === targetCategory;
+ });
+ }
+
+ // 提取商品名称,支持多种字段
+ const productNames = filteredProducts.map(product => {
+ // 尝试从多个字段获取商品名称
+ const nameFields = [product.productName, product.name, product.product];
+ for (const field of nameFields) {
+ if (field) {
+ const trimmedName = String(field).trim();
+ if (trimmedName !== '') {
+ return trimmedName;
+ }
+ }
+ }
+ return '';
+ }).filter(name => name !== '');
+
+ // 去重
+ const uniqueProductNames = [...new Set(productNames)];
+ console.log('最终商品名称列表:', uniqueProductNames);
+
+ // 计算价格范围
+ let priceRange = { min: 0, max: 0, hasPrice: false };
+
+ // 从过滤后的商品中计算价格范围,按规格分组计算平均价格
+ const specPriceMap = {};
+ filteredProducts.forEach(product => {
+ if (product.price && (product.specification || product.spec)) {
+ const priceStr = String(product.price).trim();
+ const specStr = String(product.specification || product.spec).trim();
+
+ // 处理逗号分隔的多个价格
+ const priceArray = priceStr.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ // 处理逗号分隔的多个规格
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ if (spec.includes(',')) {
+ // 按中文逗号分割
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+ specs = processedSpecs;
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0 && index < priceArray.length) {
+ const price = priceArray[index];
+ if (price && price.trim() !== '') {
+ const priceValue = parseFloat(price);
+ if (!isNaN(priceValue)) {
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 价格<10的需要按照公式计算
+ let finalPrice = priceValue;
+ if (priceValue < 10 && specInfo) {
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ finalPrice = specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ finalPrice = (specInfo.avg - 5) * priceValue;
+ }
+ }
+
+ // 按规格分组存储价格
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(finalPrice);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ // 计算每个规格的平均价格,然后找出最低和最高
+ const specAvgPrices = [];
+ Object.keys(specPriceMap).forEach(spec => {
+ const prices = specPriceMap[spec];
+ if (prices.length > 0) {
+ const avgPrice = prices.reduce((sum, price) => sum + price, 0) / prices.length;
+ specAvgPrices.push(avgPrice);
+ }
+ });
+
+ if (specAvgPrices.length > 0) {
+ priceRange.min = Math.round(Math.min(...specAvgPrices) * 100) / 100;
+ priceRange.max = Math.round(Math.max(...specAvgPrices) * 100) / 100;
+ priceRange.hasPrice = true;
+ }
+
+ this.setData({
+ productNames: uniqueProductNames,
+ priceRange: priceRange,
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ } else {
+ // 如果本地存储中也没有原始商品数据,调用API获取数据
+ console.log('本地存储中没有数据,调用API获取商品数据...');
+ const api = require('../../utils/api');
+ // 使用正确的参数调用getProducts方法
+ api.getProducts(1, 1000, 'all', '').then(result => {
+ console.log('API返回结果:', result);
+
+ // 从返回对象中提取products数组,如果不存在则使用空数组
+ const products = result.products || [];
+
+ // 过滤出有有效category字段的商品
+ const productsWithCategory = products.filter(product => {
+ if (!product.category) return false;
+ const categoryStr = String(product.category).trim();
+ return categoryStr !== '';
+ });
+
+ // 移除价格过滤,获取所有商品
+ let filteredProducts = productsWithCategory;
+
+ // 如果有分类参数,过滤出该分类下的商品
+ if (this.data.category) {
+ console.log('当前分类:', this.data.category);
+ const targetCategory = String(this.data.category).trim();
+ filteredProducts = filteredProducts.filter(product => {
+ if (!product.category) return false;
+ const productCategory = String(product.category).trim();
+ return productCategory === targetCategory;
+ });
+ }
+
+ // 提取商品名称,支持多种字段
+ const productNames = filteredProducts.map(product => {
+ // 尝试从多个字段获取商品名称
+ const nameFields = [product.productName, product.name, product.product];
+ for (const field of nameFields) {
+ if (field) {
+ const trimmedName = String(field).trim();
+ if (trimmedName !== '') {
+ return trimmedName;
+ }
+ }
+ }
+ return '';
+ }).filter(name => name !== '');
+
+ // 去重
+ const uniqueProductNames = [...new Set(productNames)];
+ console.log('最终商品名称列表:', uniqueProductNames);
+
+ // 计算价格范围
+ let priceRange = { min: 0, max: 0, hasPrice: false };
+
+ // 从过滤后的商品中计算价格范围,按规格分组计算平均价格
+ const specPriceMap = {};
+ filteredProducts.forEach(product => {
+ if (product.price && (product.specification || product.spec)) {
+ const priceStr = String(product.price).trim();
+ const specStr = String(product.specification || product.spec).trim();
+
+ // 处理逗号分隔的多个价格
+ const priceArray = priceStr.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+
+ // 处理逗号分隔的多个规格
+ let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+
+ // 进一步处理规格,确保每个规格都是独立的
+ const processedSpecs = [];
+ specs.forEach(spec => {
+ if (spec.includes(',')) {
+ // 按中文逗号分割
+ const subSpecs = spec.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ processedSpecs.push(...subSpecs);
+ } else {
+ processedSpecs.push(spec);
+ }
+ });
+ specs = processedSpecs;
+
+ // 将规格和价格配对
+ specs.forEach((spec, index) => {
+ if (spec.length > 0 && index < priceArray.length) {
+ const price = priceArray[index];
+ if (price && price.trim() !== '') {
+ const priceValue = parseFloat(price);
+ if (!isNaN(priceValue)) {
+ // 解析规格
+ const specInfo = this.parseSpecification(spec);
+
+ // 价格<10的需要按照公式计算
+ let finalPrice = priceValue;
+ if (priceValue < 10 && specInfo) {
+ if (specInfo.type === '净重') {
+ // 净重:规格平均值 × 价格
+ finalPrice = specInfo.avg * priceValue;
+ } else if (specInfo.type === '毛重') {
+ // 毛重:(规格平均值 - 5) × 价格
+ finalPrice = (specInfo.avg - 5) * priceValue;
+ }
+ }
+
+ // 按规格分组存储价格
+ if (!specPriceMap[spec]) {
+ specPriceMap[spec] = [];
+ }
+ specPriceMap[spec].push(finalPrice);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ // 计算每个规格的平均价格,然后找出最低和最高
+ const specAvgPrices = [];
+ Object.keys(specPriceMap).forEach(spec => {
+ const prices = specPriceMap[spec];
+ if (prices.length > 0) {
+ const avgPrice = prices.reduce((sum, price) => sum + price, 0) / prices.length;
+ specAvgPrices.push(avgPrice);
+ }
+ });
+
+ if (specAvgPrices.length > 0) {
+ priceRange.min = Math.round(Math.min(...specAvgPrices) * 100) / 100;
+ priceRange.max = Math.round(Math.max(...specAvgPrices) * 100) / 100;
+ priceRange.hasPrice = true;
+ }
+
+ this.setData({
+ productNames: uniqueProductNames,
+ priceRange: priceRange,
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ }).catch(err => {
+ console.error('获取商品列表失败:', err);
+ this.setData({
+ error: '获取商品列表失败,请稍后重试',
+ loading: false
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ });
+ }
+ }
+ },
+
+ selectProduct(e) {
+ const productName = e.currentTarget.dataset.product;
+ console.log('选择商品:', productName);
+ // 将商品名称和当前分类存储到本地存储
+ wx.setStorageSync('selectedProductName', productName);
+ wx.setStorageSync('selectedCategory', this.data.category); // 存储当前分类
+ // 使用wx.switchTab导航到tabBar页面
+ wx.switchTab({
+ url: '/pages/evaluate2/index',
+ success: function(res) {
+ console.log('跳转成功:', res);
+ },
+ fail: function(err) {
+ console.error('跳转失败:', err);
+ }
+ });
+ },
+
+ // 返回分类选择页面
+ goBackToCategories() {
+ console.log('返回分类选择页面');
+ wx.redirectTo({
+ url: '/pages/evaluate2/one'
+ });
+ },
+
+ // 下拉刷新
+ onPullDownRefresh() {
+ console.log('开始下拉刷新');
+ this.loadProductNames();
+ }
+});
\ No newline at end of file
diff --git a/pages/evaluate2/product-list.json b/pages/evaluate2/product-list.json
new file mode 100644
index 0000000..09e623a
--- /dev/null
+++ b/pages/evaluate2/product-list.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {},
+ "enablePullDownRefresh": true,
+ "backgroundTextStyle": "dark"
+}
\ No newline at end of file
diff --git a/pages/evaluate2/product-list.wxml b/pages/evaluate2/product-list.wxml
new file mode 100644
index 0000000..7a07798
--- /dev/null
+++ b/pages/evaluate2/product-list.wxml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+ 正在加载商品数据...
+
+
+
+
+ ⚠️
+ {{error}}
+
+
+
+
+
+
+
+ 当前分类:
+ {{category}}
+
+
+ 价格范围:
+ ¥{{priceRange.min}} - ¥{{priceRange.max}}
+
+
+
+
+
+
+
+ 🛍️
+ {{item}}
+ →
+
+
+
+
+
+ 📦
+
+ {{category ? '该分类下暂无商品' : '暂无商品'}}
+
+
+
+
+
+
+ 暂无更多商品选择
+
+
+
+
\ No newline at end of file
diff --git a/pages/evaluate2/product-list.wxss b/pages/evaluate2/product-list.wxss
new file mode 100644
index 0000000..65549fa
--- /dev/null
+++ b/pages/evaluate2/product-list.wxss
@@ -0,0 +1,415 @@
+.container {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
+ font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
+ overflow-x: hidden;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.header {
+ background: #fff;
+ box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.08);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.header-content {
+ padding: 30rpx 0;
+ text-align: center;
+ width: 100%;
+ box-sizing: border-box;
+}
+
+/* 返回按钮样式 */
+.back-button {
+ width: 120rpx;
+ height: 60rpx;
+ line-height: 60rpx;
+ font-size: 24rpx;
+ color: #4a90e2;
+ background: transparent;
+ border: none;
+ padding: 0;
+ margin: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.back-button:hover {
+ color: #3b82f6;
+}
+
+.title {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ letter-spacing: 2rpx;
+}
+
+.content {
+ flex: 1;
+ padding: 16rpx;
+ width: 100%;
+ box-sizing: border-box;
+ overflow-x: hidden;
+}
+
+/* 加载状态 */
+.loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+}
+
+.loading-spinner {
+ width: 80rpx;
+ height: 80rpx;
+ border: 8rpx solid rgba(74, 144, 226, 0.2);
+ border-top: 8rpx solid #4a90e2;
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+ margin-bottom: 32rpx;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.loading-text {
+ font-size: 28rpx;
+ color: #666;
+ font-weight: 500;
+}
+
+/* 错误提示卡片 */
+.error-card {
+ background: #fff;
+ border-radius: 16rpx;
+ padding: 48rpx;
+ margin: 32rpx 0;
+ box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.08);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+}
+
+.error-icon {
+ font-size: 80rpx;
+ margin-bottom: 24rpx;
+}
+
+.error-text {
+ font-size: 28rpx;
+ color: #e74c3c;
+ margin-bottom: 32rpx;
+ line-height: 1.5;
+}
+
+/* 按钮样式 */
+.btn-primary {
+ width: 240rpx;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
+ color: #fff;
+ border: none;
+ box-shadow: 0 4rpx 12rpx rgba(96, 165, 250, 0.4);
+ transition: all 0.3s ease;
+}
+
+.btn-primary:hover {
+ transform: translateY(-2rpx);
+ box-shadow: 0 6rpx 16rpx rgba(74, 144, 226, 0.5);
+}
+
+/* 商品列表区域 */
+.product-section {
+ margin-top: 24rpx;
+}
+
+/* 当前选择的分类 */
+.current-category {
+ display: flex;
+ align-items: center;
+ background: rgba(74, 144, 226, 0.1);
+ padding: 16rpx 20rpx;
+ border-radius: 12rpx;
+ margin-bottom: 20rpx;
+ border-left: 6rpx solid #4a90e2;
+}
+
+.current-category-label {
+ font-size: 24rpx;
+ color: #666;
+ margin-right: 8rpx;
+}
+
+.current-category-name {
+ font-size: 26rpx;
+ font-weight: 600;
+ color: #4a90e2;
+}
+
+/* 价格范围 */
+.price-range {
+ margin-top: 8rpx;
+ display: flex;
+ align-items: center;
+}
+
+.price-range-label {
+ font-size: 22rpx;
+ color: #666;
+ margin-right: 8rpx;
+}
+
+.price-range-value {
+ font-size: 22rpx;
+ font-weight: 500;
+ color: #ff6b81;
+}
+
+.section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24rpx;
+ padding: 0 8rpx;
+}
+
+.section-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ padding-left: 16rpx;
+ border-left: 6rpx solid #4a90e2;
+}
+
+.section-count {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(74, 144, 226, 0.1);
+ padding: 6rpx 16rpx;
+ border-radius: 20rpx;
+}
+
+/* 商品网格布局 */
+.product-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 20rpx;
+ margin-top: 16rpx;
+ width: 100%;
+ box-sizing: border-box;
+ overflow-x: hidden;
+}
+
+/* 商品卡片 */
+.product-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 32rpx 24rpx;
+ box-shadow: 0 6rpx 20rpx rgba(0,0,0,0.08);
+ transition: all 0.3s ease;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ min-height: 180rpx;
+ backdrop-filter: blur(8rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+ width: 100%;
+ box-sizing: border-box;
+}
+
+.product-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 6rpx;
+ background: linear-gradient(90deg, #60a5fa 0%, #3b82f6 100%);
+}
+
+.product-card:hover {
+ transform: translateY(-6rpx);
+ box-shadow: 0 12rpx 32rpx rgba(0,0,0,0.15);
+ background: rgba(255, 255, 255, 1);
+}
+
+.product-card:active {
+ transform: translateY(-2rpx);
+ box-shadow: 0 8rpx 24rpx rgba(0,0,0,0.12);
+}
+
+.product-icon {
+ font-size: 72rpx;
+ margin-bottom: 20rpx;
+ opacity: 0.9;
+ transition: all 0.3s ease;
+}
+
+.product-card:hover .product-icon {
+ transform: scale(1.1);
+ opacity: 1;
+}
+
+.product-name {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #2c3e50;
+ line-height: 1.4;
+ word-break: break-word;
+ margin-bottom: 20rpx;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 8rpx;
+}
+
+.product-arrow {
+ position: absolute;
+ bottom: 20rpx;
+ right: 24rpx;
+ font-size: 28rpx;
+ color: #4a90e2;
+ font-weight: bold;
+ opacity: 0.6;
+ transition: all 0.3s ease;
+}
+
+.product-card:hover .product-arrow {
+ opacity: 1;
+ transform: translateX(4rpx);
+}
+
+/* 响应式设计 */
+@media (max-width: 750rpx) {
+ .content {
+ padding: 20rpx;
+ }
+
+ .product-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 16rpx;
+ }
+
+ .product-card {
+ padding: 28rpx 20rpx;
+ min-height: 160rpx;
+ }
+
+ .title {
+ font-size: 32rpx;
+ }
+
+ .section-title {
+ font-size: 28rpx;
+ }
+
+ .product-name {
+ font-size: 24rpx;
+ }
+
+ .product-icon {
+ font-size: 60rpx;
+ }
+}
+
+/* 小屏幕设备适配 */
+@media (max-width: 414rpx) {
+ .product-grid {
+ grid-template-columns: repeat(3, 1fr);
+ gap: 12rpx;
+ }
+
+ .product-card {
+ padding: 20rpx 16rpx;
+ min-height: 140rpx;
+ }
+
+ .product-name {
+ font-size: 22rpx;
+ }
+
+ .product-icon {
+ font-size: 50rpx;
+ }
+}
+
+/* 暂无更多商品提示 */
+.no-more {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 48rpx 0;
+ margin-top: 16rpx;
+}
+
+.no-more-text {
+ font-size: 24rpx;
+ color: #999;
+ background: rgba(0, 0, 0, 0.03);
+ padding: 12rpx 32rpx;
+ border-radius: 30rpx;
+ font-weight: 500;
+}
+
+/* 空状态 */
+.empty-state {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 160rpx 0;
+ text-align: center;
+}
+
+.empty-icon {
+ font-size: 160rpx;
+ margin-bottom: 40rpx;
+ opacity: 0.6;
+}
+
+.empty-text {
+ font-size: 32rpx;
+ color: #666;
+ margin-bottom: 48rpx;
+ line-height: 1.4;
+ padding: 0 40rpx;
+}
+
+.btn-secondary {
+ width: 200rpx;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 40rpx;
+ background: #fff;
+ color: #4a90e2;
+ border: 2rpx solid #4a90e2;
+ transition: all 0.3s ease;
+}
+
+.btn-secondary:hover {
+ background: rgba(74, 144, 226, 0.05);
+ transform: translateY(-2rpx);
+}
diff --git a/pages/evaluate2/spec-detail.js b/pages/evaluate2/spec-detail.js
new file mode 100644
index 0000000..19915df
--- /dev/null
+++ b/pages/evaluate2/spec-detail.js
@@ -0,0 +1,102 @@
+Page({
+ data: {
+ productName: '',
+ specification: '',
+ price: 0,
+ quantity: 1,
+ totalPrice: 0,
+ loading: false,
+ error: ''
+ },
+ onLoad(options) {
+ console.log('接收到的参数:', options);
+ // 即使参数不完整,也要尝试获取并设置
+ const productName = options.productName ? decodeURIComponent(options.productName) : '';
+ const specification = options.specification ? decodeURIComponent(options.specification) : '';
+ let price = 0;
+
+ if (options.price) {
+ const decodedPrice = decodeURIComponent(options.price);
+ console.log('解码后的价格:', decodedPrice);
+ price = parseFloat(decodedPrice) || 0;
+ }
+
+ console.log('解析后的参数:', { productName, specification, price });
+
+ this.setData({
+ productName: productName,
+ specification: specification,
+ price: price,
+ totalPrice: 0 // 初始时总价为0,不显示
+ });
+ },
+
+ // 件数输入变化
+ onQuantityChange(e) {
+ const quantity = parseInt(e.detail.value) || 1;
+ this.setData({
+ quantity: quantity
+ // 只更新件数,不更新总价,等待点击计算按钮
+ });
+ },
+
+ // 减少数量
+ decreaseQuantity() {
+ if (this.data.quantity > 1) {
+ this.setData({
+ quantity: this.data.quantity - 1
+ });
+ }
+ },
+
+ // 增加数量
+ increaseQuantity() {
+ this.setData({
+ quantity: this.data.quantity + 1
+ });
+ },
+
+ // 计算价格
+ calculatePrice() {
+ const totalPrice = Math.round(this.data.price * this.data.quantity * 10) / 10;
+ this.setData({
+ totalPrice: totalPrice
+ });
+ wx.showToast({
+ title: '计算完成',
+ icon: 'success',
+ duration: 1000
+ });
+ },
+
+ // 返回上一页
+ goBack() {
+ wx.navigateBack();
+ },
+
+ // 下拉刷新
+ onPullDownRefresh() {
+ console.log('开始下拉刷新');
+ // 重新加载页面数据
+ // 由于spec-detail页面的数据是通过URL参数传递的,这里可以重新获取参数并设置数据
+ const options = this.options || {};
+ const productName = options.productName ? decodeURIComponent(options.productName) : '';
+ const specification = options.specification ? decodeURIComponent(options.specification) : '';
+ let price = 0;
+
+ if (options.price) {
+ const decodedPrice = decodeURIComponent(options.price);
+ price = parseFloat(decodedPrice) || 0;
+ }
+
+ this.setData({
+ productName: productName,
+ specification: specification,
+ price: price,
+ totalPrice: 0 // 初始时总价为0,不显示
+ });
+
+ // 结束下拉刷新
+ wx.stopPullDownRefresh();
+ }
+});
\ No newline at end of file
diff --git a/pages/evaluate2/spec-detail.json b/pages/evaluate2/spec-detail.json
new file mode 100644
index 0000000..09e623a
--- /dev/null
+++ b/pages/evaluate2/spec-detail.json
@@ -0,0 +1,5 @@
+{
+ "usingComponents": {},
+ "enablePullDownRefresh": true,
+ "backgroundTextStyle": "dark"
+}
\ No newline at end of file
diff --git a/pages/evaluate2/spec-detail.wxml b/pages/evaluate2/spec-detail.wxml
new file mode 100644
index 0000000..e4c2898
--- /dev/null
+++ b/pages/evaluate2/spec-detail.wxml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+ 规格信息
+
+ 规格
+ {{specification}}
+
+
+ 单价
+ ¥{{price || 0}}
+
+ 您已选择此规格进行估价
+
+
+
+
+ 数量设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 预估结果
+
+ 预估总价
+ ¥{{totalPrice}}
+
+ 此价格为预估价格,实际价格可能会有所变动
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/evaluate2/spec-detail.wxss b/pages/evaluate2/spec-detail.wxss
new file mode 100644
index 0000000..8fd2942
--- /dev/null
+++ b/pages/evaluate2/spec-detail.wxss
@@ -0,0 +1,401 @@
+/* 页面容器 */
+.page-container {
+ min-height: 100vh;
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
+ font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+}
+
+/* 头部样式 */
+.page-header {
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(10rpx);
+ box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.05);
+ padding: 28rpx 0;
+ text-align: center;
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.header-title {
+ font-size: 30rpx;
+ font-weight: 700;
+ color: #2c3e50;
+ letter-spacing: 1rpx;
+}
+
+/* 主要内容区域 */
+.main-content {
+ flex: 1;
+ padding: 24rpx;
+ display: flex;
+ flex-direction: column;
+ gap: 24rpx;
+ padding-bottom: 48rpx;
+ box-sizing: border-box;
+}
+
+/* 卡片基础样式 */
+.info-card,
+.control-card,
+.result-card {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 24rpx;
+ padding: 32rpx;
+ box-shadow: 0 6rpx 24rpx rgba(0,0,0,0.08);
+ backdrop-filter: blur(12rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.4);
+ transition: all 0.3s ease;
+ box-sizing: border-box;
+}
+
+.info-card:hover,
+.control-card:hover,
+.result-card:hover {
+ box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.12);
+ transform: translateY(-4rpx);
+ background: rgba(255, 255, 255, 0.98);
+}
+
+/* 卡片标题 */
+.card-subtitle {
+ font-size: 26rpx;
+ font-weight: 600;
+ color: #64748b;
+ margin-bottom: 24rpx;
+ padding-bottom: 16rpx;
+ border-bottom: 1rpx solid #f1f5f9;
+}
+
+/* 信息行样式 */
+.info-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16rpx 0;
+ border-bottom: 1rpx solid #f8fafc;
+}
+
+.info-row:last-child {
+ border-bottom: none;
+}
+
+.info-label {
+ font-size: 26rpx;
+ color: #64748b;
+ font-weight: 500;
+}
+
+.info-value {
+ font-size: 26rpx;
+ font-weight: 600;
+ color: #2c3e50;
+}
+
+.info-value.price {
+ color: #ef4444;
+ font-size: 32rpx;
+ font-weight: 700;
+}
+
+/* 提示信息 */
+.info-hint {
+ font-size: 22rpx;
+ color: #94a3b8;
+ text-align: center;
+ margin-top: 20rpx;
+ padding-top: 20rpx;
+ border-top: 1rpx solid #f1f5f9;
+}
+
+/* 数量控制 */
+.quantity-box {
+ display: flex;
+ align-items: center;
+ gap: 24rpx;
+ margin-top: 12rpx;
+ justify-content: center;
+}
+
+.quantity-btn {
+ width: 80rpx;
+ height: 80rpx;
+ border-radius: 40rpx;
+ font-size: 36rpx;
+ font-weight: bold;
+ background: rgba(255, 255, 255, 0.9);
+ color: #3b82f6;
+ border: 2rpx solid rgba(96, 165, 250, 0.4);
+ backdrop-filter: blur(12rpx);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s ease;
+ box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.08);
+}
+
+.quantity-btn:hover {
+ background: rgba(59, 130, 246, 0.1);
+ border-color: rgba(59, 130, 246, 0.6);
+ transform: scale(1.1);
+}
+
+.quantity-btn.minus:hover {
+ background: rgba(239, 68, 68, 0.1);
+ border-color: rgba(239, 68, 68, 0.6);
+ color: #ef4444;
+}
+
+.quantity-btn.plus:hover {
+ background: rgba(16, 185, 129, 0.1);
+ border-color: rgba(16, 185, 129, 0.6);
+ color: #10b981;
+}
+
+.quantity-input {
+ width: 160rpx;
+ height: 80rpx;
+ border: 2rpx solid rgba(96, 165, 250, 0.4);
+ border-radius: 16rpx;
+ padding: 0 24rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ text-align: center;
+ color: #2c3e50;
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(12rpx);
+ box-shadow: inset 0 2rpx 8rpx rgba(0,0,0,0.08);
+ box-sizing: border-box;
+}
+
+/* 按钮区域 */
+.button-section {
+ margin-top: 12rpx;
+}
+
+.button-section.bottom {
+ margin-top: 20rpx;
+}
+
+/* 按钮样式 */
+.primary-btn {
+ width: 100%;
+ height: 92rpx;
+ line-height: 92rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border-radius: 46rpx;
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
+ color: #fff;
+ border: none;
+ box-shadow: 0 6rpx 24rpx rgba(59, 130, 246, 0.4);
+ transition: all 0.3s ease;
+ text-align: center;
+}
+
+.primary-btn:hover {
+ transform: translateY(-4rpx);
+ box-shadow: 0 8rpx 32rpx rgba(59, 130, 246, 0.5);
+}
+
+.secondary-btn {
+ width: 100%;
+ height: 84rpx;
+ line-height: 84rpx;
+ font-size: 26rpx;
+ font-weight: 600;
+ border-radius: 42rpx;
+ background: rgba(255, 255, 255, 0.95);
+ color: #3b82f6;
+ border: 2rpx solid rgba(59, 130, 246, 0.4);
+ backdrop-filter: blur(12rpx);
+ transition: all 0.3s ease;
+ text-align: center;
+ box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
+}
+
+.secondary-btn:hover {
+ background: rgba(59, 130, 246, 0.08);
+ border-color: rgba(59, 130, 246, 0.6);
+ transform: translateY(-4rpx);
+ box-shadow: 0 6rpx 24rpx rgba(59, 130, 246, 0.3);
+}
+
+/* 结果卡片 */
+.result-card {
+ animation: fadeInUp 0.6s ease-out;
+}
+
+@keyframes fadeInUp {
+ from {
+ opacity: 0;
+ transform: translateY(30rpx);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+/* 结果行 */
+.result-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx 0;
+}
+
+.result-label {
+ font-size: 26rpx;
+ color: #64748b;
+ font-weight: 500;
+}
+
+.result-value {
+ font-size: 36rpx;
+ font-weight: 700;
+ color: #ef4444;
+ text-shadow: 0 2rpx 4rpx rgba(239, 68, 68, 0.2);
+}
+
+/* 结果提示 */
+.result-hint {
+ font-size: 22rpx;
+ color: #94a3b8;
+ text-align: center;
+ margin-top: 16rpx;
+ padding-top: 16rpx;
+ border-top: 1rpx solid #f1f5f9;
+ line-height: 1.5;
+}
+
+/* 响应式设计 */
+@media (max-width: 750rpx) {
+ .main-content {
+ padding: 20rpx;
+ gap: 20rpx;
+ }
+
+ .info-card,
+ .control-card,
+ .result-card {
+ padding: 28rpx;
+ }
+
+ .header-title {
+ font-size: 28rpx;
+ }
+
+ .card-subtitle {
+ font-size: 24rpx;
+ margin-bottom: 20rpx;
+ }
+
+ .info-label,
+ .info-value {
+ font-size: 24rpx;
+ }
+
+ .info-value.price {
+ font-size: 30rpx;
+ }
+
+ .result-value {
+ font-size: 32rpx;
+ }
+
+ .quantity-box {
+ gap: 20rpx;
+ }
+
+ .quantity-btn {
+ width: 72rpx;
+ height: 72rpx;
+ font-size: 32rpx;
+ }
+
+ .quantity-input {
+ width: 140rpx;
+ height: 72rpx;
+ font-size: 26rpx;
+ }
+
+ .primary-btn {
+ height: 84rpx;
+ line-height: 84rpx;
+ font-size: 26rpx;
+ }
+
+ .secondary-btn {
+ height: 76rpx;
+ line-height: 76rpx;
+ font-size: 24rpx;
+ }
+}
+
+/* 小屏幕设备适配 */
+@media (max-width: 375rpx) {
+ .main-content {
+ padding: 16rpx;
+ gap: 16rpx;
+ }
+
+ .info-card,
+ .control-card,
+ .result-card {
+ padding: 24rpx;
+ }
+
+ .header-title {
+ font-size: 26rpx;
+ }
+
+ .card-subtitle {
+ font-size: 22rpx;
+ margin-bottom: 16rpx;
+ }
+
+ .info-label,
+ .info-value {
+ font-size: 22rpx;
+ }
+
+ .info-value.price {
+ font-size: 28rpx;
+ }
+
+ .result-value {
+ font-size: 28rpx;
+ }
+
+ .quantity-box {
+ gap: 16rpx;
+ }
+
+ .quantity-btn {
+ width: 64rpx;
+ height: 64rpx;
+ font-size: 28rpx;
+ }
+
+ .quantity-input {
+ width: 120rpx;
+ height: 64rpx;
+ font-size: 24rpx;
+ }
+
+ .primary-btn {
+ height: 76rpx;
+ line-height: 76rpx;
+ font-size: 24rpx;
+ }
+
+ .secondary-btn {
+ height: 68rpx;
+ line-height: 68rpx;
+ font-size: 22rpx;
+ }
+}
--
2.30.2
From f5473038c8f51f2a39e764b20f23d82526248c84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Tue, 27 Jan 2026 11:26:34 +0800
Subject: [PATCH 02/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8DparseSpecification?=
=?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E6=94=AF=E6=8C=81=E5=87=80=E9=87=8D?=
=?UTF-8?q?X+=E6=A0=BC=E5=BC=8F=E7=9A=84=E8=A7=84=E6=A0=BC=E8=A7=A3?=
=?UTF-8?q?=E6=9E=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/evaluate2/index.js | 38 +++++++++++++++++++++++++++++++++-----
1 file changed, 33 insertions(+), 5 deletions(-)
diff --git a/pages/evaluate2/index.js b/pages/evaluate2/index.js
index 2324627..8543ab6 100644
--- a/pages/evaluate2/index.js
+++ b/pages/evaluate2/index.js
@@ -211,11 +211,12 @@ Page({
// 解析规格,提取类型(净重/毛重)和数值范围
parseSpecification(spec) {
- const weightMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
- if (weightMatch) {
- const type = weightMatch[1]; // 净重或毛重
- const min = parseFloat(weightMatch[2]);
- const max = parseFloat(weightMatch[3]);
+ // 匹配 "净重X-Y" 或 "毛重X-Y" 格式
+ const rangeMatch = spec.match(/(净重|毛重)(\d+)-(\d+)/);
+ if (rangeMatch) {
+ const type = rangeMatch[1]; // 净重或毛重
+ const min = parseFloat(rangeMatch[2]);
+ const max = parseFloat(rangeMatch[3]);
const avg = (min + max) / 2;
return {
type: type,
@@ -224,6 +225,33 @@ Page({
avg: avg
};
}
+
+ // 匹配 "净重X+" 或 "毛重X+" 格式
+ const plusMatch = spec.match(/(净重|毛重)(\d+)\+/);
+ if (plusMatch) {
+ const type = plusMatch[1]; // 净重或毛重
+ const value = parseFloat(plusMatch[2]);
+ return {
+ type: type,
+ min: value,
+ max: value,
+ avg: value
+ };
+ }
+
+ // 匹配 "净重X" 或 "毛重X" 格式
+ const singleMatch = spec.match(/(净重|毛重)(\d+)/);
+ if (singleMatch) {
+ const type = singleMatch[1]; // 净重或毛重
+ const value = parseFloat(singleMatch[2]);
+ return {
+ type: type,
+ min: value,
+ max: value,
+ avg: value
+ };
+ }
+
return null;
},
--
2.30.2
From 5f444e9b3791139b286ac1980d7167823ae10495 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Tue, 27 Jan 2026 13:46:14 +0800
Subject: [PATCH 03/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=84=E8=AE=BA?=
=?UTF-8?q?=E5=AE=A1=E6=A0=B8=E5=8A=9F=E8=83=BD=EF=BC=9A=E7=A1=AE=E4=BF=9D?=
=?UTF-8?q?review=E5=AD=97=E6=AE=B5=E9=BB=98=E8=AE=A4=E4=B8=BA0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/goods-detail/goods-detail.js | 25 ++++++++++++++++++++-----
server-example/server-mysql.js | 13 ++++++++++++-
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js
index 435059e..75dc48c 100644
--- a/pages/goods-detail/goods-detail.js
+++ b/pages/goods-detail/goods-detail.js
@@ -1815,11 +1815,12 @@ Page({
const productId = this.data.goodsDetail.productId || this.data.goodsDetail.id;
// 准备评论数据
- // 只发送服务器需要的参数:productId、phoneNumber和comments
+ // 只发送服务器需要的参数:productId、phoneNumber、comments和review
const commentData = {
productId: String(productId),
phoneNumber: phoneNumber ? String(phoneNumber) : null,
- comments: content
+ comments: content,
+ review: 0 // 新提交的评论默认为待审核状态
};
// 调试日志
@@ -1851,7 +1852,8 @@ Page({
liked: false,
hated: false,
replies: [],
- phoneNumber: phoneNumber // 添加用户标识信息,用于判断是否可以删除
+ phoneNumber: phoneNumber, // 添加用户标识信息,用于判断是否可以删除
+ review: 0 // 新提交的评论默认为待审核状态
};
// 更新评论列表 - add new comment to the end
@@ -1952,7 +1954,8 @@ Page({
hated: false,
replies: [],
phoneNumber: '',
- isDefault: true
+ isDefault: true,
+ review: 1 // 默认评论默认为审核通过状态
}));
},
@@ -2003,9 +2006,19 @@ Page({
});
commentsData = uniqueComments;
+ // 应用审核逻辑:审核通过的评论所有人可见,未审核通过的评论仅自己可见
+ const currentUserPhone = this.data.currentUserPhone;
+ const filteredComments = commentsData.filter(comment => {
+ const reviewStatus = comment.review || 0; // 默认值为0(待审核)
+ // 审核通过的评论(review=1)所有人可见
+ // 未审核通过的评论(review=0或2)仅评论作者可见
+ return reviewStatus === 1 || comment.phoneNumber === currentUserPhone;
+ });
+ console.log('应用审核逻辑后剩余评论数量:', filteredComments.length);
+
// Always add default comments at the beginning
const defaultComments = this.getConsistentRandomComments(productId, 2);
- commentsData = [...defaultComments, ...commentsData];
+ commentsData = [...defaultComments, ...filteredComments];
// 检查返回的评论是否都属于当前用户
const allCommentsBelongToCurrentUser = commentsData.every(comment =>
@@ -2026,6 +2039,8 @@ Page({
id: comment.id || `comment_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
// 确保phoneNumber字段存在
phoneNumber: comment.phoneNumber || comment.userPhone || '',
+ // 确保review字段存在
+ review: comment.review || 0,
// 格式化时间
time: timeUtils.formatRelativeTime(comment.time)
}));
diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js
index 61ecd3e..93880e4 100644
--- a/server-example/server-mysql.js
+++ b/server-example/server-mysql.js
@@ -556,6 +556,11 @@ const comments = sequelize.define('Comment', {
type: DataTypes.INTEGER,
defaultValue: 0,
comment: '点踩数'
+ },
+ review: {
+ type: DataTypes.INTEGER,
+ defaultValue: 0,
+ comment: '审核字段'
}
}, {
tableName: 'comments',
@@ -1075,6 +1080,11 @@ Comment.init({
type: DataTypes.INTEGER,
defaultValue: 0,
comment: '点踩数'
+ },
+ review: {
+ type: DataTypes.INTEGER,
+ defaultValue: 0,
+ comment: '审核字段'
}
}, {
sequelize,
@@ -4380,7 +4390,7 @@ app.post('/api/comments/get', async (req, res) => {
// 提交评论
app.post('/api/comments/add', async (req, res) => {
try {
- const { productId, phoneNumber, comments } = req.body;
+ const { productId, phoneNumber, comments, review = 0 } = req.body;
if (!productId || !phoneNumber || !comments) {
return res.status(400).json({
@@ -4395,6 +4405,7 @@ app.post('/api/comments/add', async (req, res) => {
productId,
phoneNumber,
comments,
+ review,
time: new Date()
});
--
2.30.2
From 9c4a5fb414b507ca01398c36b66d888960658281 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Tue, 27 Jan 2026 14:19:23 +0800
Subject: [PATCH 04/22] =?UTF-8?q?=E5=88=A0=E9=99=A4goods-detail=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E5=BA=95=E9=83=A8=E7=9A=84=E5=A4=9A=E4=BD=99=E6=95=B0?=
=?UTF-8?q?=E5=AD=971?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/goods-detail/goods-detail.wxml | 2 +-
pages/goods-update/goods-update.wxml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/pages/goods-detail/goods-detail.wxml b/pages/goods-detail/goods-detail.wxml
index 8a4a0cf..6b4a749 100644
--- a/pages/goods-detail/goods-detail.wxml
+++ b/pages/goods-detail/goods-detail.wxml
@@ -72,7 +72,7 @@
-
+
售空
{{goodsDetail.supplyStatus}}
diff --git a/pages/goods-update/goods-update.wxml b/pages/goods-update/goods-update.wxml
index d166a26..44c9d39 100644
--- a/pages/goods-update/goods-update.wxml
+++ b/pages/goods-update/goods-update.wxml
@@ -516,7 +516,7 @@
scroll-y="true"
style="max-height: 50vh; padding: 0; -webkit-overflow-scrolling: touch;"
enable-back-to-top="false"
- >
+ >
Date: Tue, 27 Jan 2026 16:14:54 +0800
Subject: [PATCH 05/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8Deggbar=E6=8F=90?=
=?UTF-8?q?=E4=BA=A4=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1=E5=99=A8=E5=90=AF=E5=8A=A8=E9=97=AE=E9=A2=98=E5=B9=B6?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0eggbar=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app.json | 6 +-
custom-tab-bar/index.js | 4 +-
custom-tab-bar/index.wxml | 4 +-
pages/eggbar/create-post.js | 174 ++++++++++++++++++++
pages/eggbar/create-post.json | 9 ++
pages/eggbar/create-post.wxml | 68 ++++++++
pages/eggbar/create-post.wxss | 281 +++++++++++++++++++++++++++++++++
pages/eggbar/eggbar.js | 148 +++++++++++++++++
pages/eggbar/eggbar.json | 12 ++
pages/eggbar/eggbar.wxml | 79 +++++++++
pages/eggbar/eggbar.wxss | 270 +++++++++++++++++++++++++++++++
server-example/server-mysql.js | 120 ++++++++++++++
utils/api.js | 60 +++++++
13 files changed, 1229 insertions(+), 6 deletions(-)
create mode 100644 pages/eggbar/create-post.js
create mode 100644 pages/eggbar/create-post.json
create mode 100644 pages/eggbar/create-post.wxml
create mode 100644 pages/eggbar/create-post.wxss
create mode 100644 pages/eggbar/eggbar.js
create mode 100644 pages/eggbar/eggbar.json
create mode 100644 pages/eggbar/eggbar.wxml
create mode 100644 pages/eggbar/eggbar.wxss
diff --git a/app.json b/app.json
index 0a00338..f90aa36 100644
--- a/app.json
+++ b/app.json
@@ -9,6 +9,8 @@
"pages/evaluate2/one",
"pages/evaluate2/product-list",
"pages/evaluate2/spec-detail",
+ "pages/eggbar/eggbar",
+ "pages/eggbar/create-post",
"pages/settlement/index",
"pages/publish/index",
"pages/buyer/index",
@@ -85,8 +87,8 @@
"text": "估"
},
{
- "pagePath": "pages/settlement/index",
- "text": "入驻"
+ "pagePath": "pages/eggbar/eggbar",
+ "text": "蛋吧"
},
{
"pagePath": "pages/favorites/index",
diff --git a/custom-tab-bar/index.js b/custom-tab-bar/index.js
index 1d90d18..353428f 100644
--- a/custom-tab-bar/index.js
+++ b/custom-tab-bar/index.js
@@ -16,7 +16,7 @@ Component({
{ key: 'index', route: 'pages/index/index' },
{ key: 'chat', route: 'pages/chat/index', badgeKey: 'chat' },
{ key: 'evaluate', route: 'pages/evaluate2/one' },
- { key: 'settlement', route: 'pages/settlement/index' },
+ { key: 'settlement', route: 'pages/eggbar/eggbar' },
{ key: 'favorites', route: 'pages/favorites/index' },
{ key: 'profile', route: 'pages/profile/index' }
]
@@ -95,7 +95,7 @@ Component({
'pages/index/index',
'pages/chat/index',
'pages/evaluate2/one',
- 'pages/settlement/index',
+ 'pages/eggbar/eggbar',
'pages/favorites/index',
'pages/profile/index'
];
diff --git a/custom-tab-bar/index.wxml b/custom-tab-bar/index.wxml
index 1ad7876..a37f79b 100644
--- a/custom-tab-bar/index.wxml
+++ b/custom-tab-bar/index.wxml
@@ -33,13 +33,13 @@
{{badges['settlement']}}
- 入驻
+ 蛋吧
diff --git a/pages/eggbar/create-post.js b/pages/eggbar/create-post.js
new file mode 100644
index 0000000..c713daf
--- /dev/null
+++ b/pages/eggbar/create-post.js
@@ -0,0 +1,174 @@
+const API = require('../../utils/api.js');
+
+Page({
+ data: {
+ content: '',
+ images: [],
+ selectedTopic: null,
+ showTopicModal: false,
+ hotTopics: []
+ },
+
+ onLoad() {
+ this.loadHotTopics();
+ },
+
+ loadHotTopics() {
+ API.getHotTopics().then(res => {
+ this.setData({
+ hotTopics: res.data || []
+ });
+ }).catch(err => {
+ console.error('加载热门话题失败:', err);
+ });
+ },
+
+ onContentChange(e) {
+ this.setData({
+ content: e.detail.value
+ });
+ },
+
+ chooseImage() {
+ if (this.data.images.length >= 9) {
+ wx.showToast({
+ title: '最多只能上传9张图片',
+ icon: 'none'
+ });
+ return;
+ }
+
+ wx.chooseImage({
+ count: 9 - this.data.images.length,
+ sizeType: ['compressed'],
+ sourceType: ['album', 'camera'],
+ success: (res) => {
+ this.setData({
+ images: [...this.data.images, ...res.tempFilePaths]
+ });
+ }
+ });
+ },
+
+ deleteImage(e) {
+ const index = e.currentTarget.dataset.index;
+ const images = this.data.images.filter((_, i) => i !== index);
+ this.setData({
+ images
+ });
+ },
+
+ showTopicPicker() {
+ this.setData({
+ showTopicModal: true
+ });
+ },
+
+ hideTopicPicker() {
+ this.setData({
+ showTopicModal: false
+ });
+ },
+
+ selectTopic(e) {
+ const topic = e.currentTarget.dataset.topic;
+ this.setData({
+ selectedTopic: topic,
+ showTopicModal: false
+ });
+ },
+
+ stopPropagation() {
+ // 阻止事件冒泡
+ },
+
+ cancel() {
+ wx.navigateBack();
+ },
+
+ submit() {
+ if (!this.data.content.trim()) {
+ return;
+ }
+
+ wx.showLoading({
+ title: '发布中...'
+ });
+
+ // 先上传图片,获取永久 URL
+ this.uploadImages(this.data.images)
+ .then(uploadedImages => {
+ const postData = {
+ content: this.data.content,
+ images: uploadedImages,
+ topic: this.data.selectedTopic
+ };
+
+ return API.createPost(postData);
+ })
+ .then(res => {
+ wx.hideLoading();
+ wx.showToast({
+ title: '发布成功',
+ icon: 'success'
+ });
+ setTimeout(() => {
+ wx.navigateBack();
+ }, 1000);
+ })
+ .catch(err => {
+ wx.hideLoading();
+ wx.showToast({
+ title: '发布失败,请重试',
+ icon: 'none'
+ });
+ console.error('发布动态失败:', err);
+ });
+ },
+
+ // 上传图片获取永久 URL
+ uploadImages(tempImagePaths) {
+ return new Promise((resolve, reject) => {
+ if (!tempImagePaths || tempImagePaths.length === 0) {
+ resolve([]);
+ return;
+ }
+
+ const uploadedImages = [];
+ let uploadedCount = 0;
+
+ tempImagePaths.forEach((tempPath, index) => {
+ wx.uploadFile({
+ url: API.BASE_URL + '/api/eggbar/upload',
+ filePath: tempPath,
+ name: 'image',
+ formData: {
+ index: index,
+ total: tempImagePaths.length
+ },
+ success: (res) => {
+ if (res.statusCode === 200) {
+ try {
+ const data = JSON.parse(res.data);
+ if (data.success && data.imageUrl) {
+ uploadedImages.push(data.imageUrl);
+ }
+ } catch (e) {
+ console.error('解析上传响应失败:', e);
+ }
+ }
+ },
+ fail: (err) => {
+ console.error('上传图片失败:', err);
+ },
+ complete: () => {
+ uploadedCount++;
+ if (uploadedCount === tempImagePaths.length) {
+ resolve(uploadedImages);
+ }
+ }
+ });
+ });
+ });
+ }
+});
diff --git a/pages/eggbar/create-post.json b/pages/eggbar/create-post.json
new file mode 100644
index 0000000..24689f5
--- /dev/null
+++ b/pages/eggbar/create-post.json
@@ -0,0 +1,9 @@
+{
+ "usingComponents": {},
+ "enablePullDownRefresh": false,
+ "backgroundTextStyle": "dark",
+ "backgroundColor": "#f8f8f8",
+ "navigationBarBackgroundColor": "#ffffff",
+ "navigationBarTitleText": "发布动态",
+ "navigationBarTextStyle": "black"
+}
diff --git a/pages/eggbar/create-post.wxml b/pages/eggbar/create-post.wxml
new file mode 100644
index 0000000..ba07cad
--- /dev/null
+++ b/pages/eggbar/create-post.wxml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+ {{content.length}}/500
+
+
+
+ 添加图片
+
+
+ +
+ 选择图片
+
+
+
+
+
+ ×
+
+
+
+
+
+
+
+ 选择话题
+
+ {{selectedTopic ? '#' + selectedTopic : '选择话题'}}
+ ▼
+
+
+
+
+
+
+
+
+
+
+
+
+ #{{item.name}}
+ {{item.count}}人讨论
+
+
+
+
+
diff --git a/pages/eggbar/create-post.wxss b/pages/eggbar/create-post.wxss
new file mode 100644
index 0000000..e0181d2
--- /dev/null
+++ b/pages/eggbar/create-post.wxss
@@ -0,0 +1,281 @@
+page {
+ background-color: #f5f5f5;
+ height: 100vh;
+}
+
+.container {
+ min-height: 100vh;
+ padding: 20rpx;
+}
+
+.header {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 20rpx;
+ padding: 30rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 4rpx 20rpx rgba(102, 126, 234, 0.3);
+}
+
+.title {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #ffffff;
+}
+
+.form {
+ background: #ffffff;
+ border-radius: 20rpx;
+ padding: 30rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+}
+
+.form-item {
+ margin-bottom: 30rpx;
+}
+
+.label {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #333333;
+ margin-bottom: 15rpx;
+}
+
+.textarea {
+ width: 100%;
+ min-height: 200rpx;
+ font-size: 28rpx;
+ color: #333333;
+ border: 2rpx solid #f0f0f0;
+ border-radius: 12rpx;
+ padding: 20rpx;
+ box-sizing: border-box;
+ resize: none;
+ line-height: 1.6;
+}
+
+.placeholder {
+ color: #999999;
+}
+
+.counter {
+ display: block;
+ text-align: right;
+ font-size: 24rpx;
+ color: #999999;
+ margin-top: 10rpx;
+}
+
+.image-uploader {
+ margin-top: 10rpx;
+}
+
+.upload-area {
+ width: 120rpx;
+ height: 120rpx;
+ border: 2rpx dashed #e0e0e0;
+ border-radius: 12rpx;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: #fafafa;
+ margin-bottom: 15rpx;
+ transition: all 0.3s ease;
+}
+
+.upload-area:active {
+ background: #f0f0f0;
+ transform: scale(0.98);
+}
+
+.upload-icon {
+ font-size: 48rpx;
+ color: #999999;
+ margin-bottom: 10rpx;
+}
+
+.upload-text {
+ font-size: 24rpx;
+ color: #999999;
+}
+
+.image-list {
+ display: flex;
+ gap: 15rpx;
+ flex-wrap: wrap;
+ margin-top: 15rpx;
+}
+
+.image-item {
+ position: relative;
+ width: 150rpx;
+ height: 150rpx;
+ border-radius: 12rpx;
+ overflow: hidden;
+}
+
+.image {
+ width: 100%;
+ height: 100%;
+ background: #f0f0f0;
+}
+
+.image-delete {
+ position: absolute;
+ top: 5rpx;
+ right: 5rpx;
+ width: 40rpx;
+ height: 40rpx;
+ background: rgba(0, 0, 0, 0.6);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #ffffff;
+ font-size: 32rpx;
+ font-weight: bold;
+ transition: all 0.3s ease;
+}
+
+.image-delete:active {
+ background: rgba(0, 0, 0, 0.8);
+ transform: scale(0.9);
+}
+
+.topic-picker {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx;
+ border: 2rpx solid #f0f0f0;
+ border-radius: 12rpx;
+ background: #fafafa;
+ transition: all 0.3s ease;
+}
+
+.topic-picker:active {
+ background: #f0f0f0;
+}
+
+.topic-text {
+ font-size: 28rpx;
+ color: #333333;
+}
+
+.topic-arrow {
+ font-size: 20rpx;
+ color: #999999;
+}
+
+.footer {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ padding: 20rpx;
+ background: #ffffff;
+ border-top: 1rpx solid #f0f0f0;
+ box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
+ box-sizing: border-box;
+}
+
+.cancel-btn {
+ flex: 1;
+ height: 80rpx;
+ margin-right: 15rpx;
+ background: #f5f5f5;
+ color: #333333;
+ border: none;
+ border-radius: 40rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+}
+
+.submit-btn {
+ flex: 1;
+ height: 80rpx;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: #ffffff;
+ border: none;
+ border-radius: 40rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+}
+
+.submit-btn:disabled {
+ background: #e0e0e0;
+ color: #999999;
+}
+
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+}
+
+.modal-container {
+ width: 80%;
+ max-height: 70vh;
+ background: #ffffff;
+ border-radius: 20rpx;
+ overflow: hidden;
+}
+
+.modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+}
+
+.modal-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333333;
+}
+
+.modal-close {
+ font-size: 36rpx;
+ color: #999999;
+ padding: 10rpx;
+}
+
+.modal-content {
+ padding: 20rpx;
+ max-height: 50vh;
+ overflow-y: auto;
+}
+
+.topic-item {
+ padding: 20rpx;
+ border-bottom: 1rpx solid #f0f0f0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ transition: all 0.3s ease;
+}
+
+.topic-item:active {
+ background: #f0f7ff;
+}
+
+.topic-name {
+ font-size: 28rpx;
+ color: #333333;
+ font-weight: 500;
+}
+
+.topic-count {
+ font-size: 24rpx;
+ color: #999999;
+}
diff --git a/pages/eggbar/eggbar.js b/pages/eggbar/eggbar.js
new file mode 100644
index 0000000..5fedadc
--- /dev/null
+++ b/pages/eggbar/eggbar.js
@@ -0,0 +1,148 @@
+const API = require('../../utils/api.js');
+
+Page({
+ data: {
+ hotTopics: [],
+ posts: [],
+ loading: false,
+ hasMore: true,
+ page: 1,
+ pageSize: 10
+ },
+
+ onLoad() {
+ this.loadHotTopics();
+ this.loadPosts();
+ },
+
+ onShow() {
+ this.setData({
+ page: 1,
+ hasMore: true,
+ posts: []
+ });
+ this.loadPosts();
+ },
+
+ onReachBottom() {
+ if (this.data.hasMore && !this.data.loading) {
+ this.loadPosts();
+ }
+ },
+
+ onPullDownRefresh() {
+ this.setData({
+ page: 1,
+ hasMore: true,
+ posts: []
+ });
+ this.loadHotTopics();
+ this.loadPosts();
+ wx.stopPullDownRefresh();
+ },
+
+ loadHotTopics() {
+ API.getHotTopics().then(res => {
+ this.setData({
+ hotTopics: res.data || []
+ });
+ }).catch(err => {
+ console.error('加载热门话题失败:', err);
+ });
+ },
+
+ loadPosts() {
+ if (this.data.loading) {
+ return;
+ }
+
+ this.setData({
+ loading: true
+ });
+
+ API.getPosts({
+ page: this.data.page,
+ pageSize: this.data.pageSize
+ }).then(res => {
+ const newPosts = res.data || [];
+ this.setData({
+ posts: this.data.page === 1 ? newPosts : [...this.data.posts, ...newPosts],
+ loading: false,
+ hasMore: newPosts.length >= this.data.pageSize,
+ page: this.data.page + 1
+ });
+ }).catch(err => {
+ console.error('加载动态失败:', err);
+ this.setData({
+ loading: false
+ });
+ });
+ },
+
+ viewTopic(e) {
+ const topic = e.currentTarget.dataset.topic;
+ wx.navigateTo({
+ url: `/pages/eggbar/topic-detail?id=${topic.id}`
+ });
+ },
+
+ viewPost(e) {
+ const post = e.currentTarget.dataset.post;
+ wx.navigateTo({
+ url: `/pages/eggbar/post-detail?id=${post.id}`
+ });
+ },
+
+ likePost(e) {
+ const postId = e.currentTarget.dataset.id;
+ const posts = this.data.posts.map(post => {
+ if (post.id === postId) {
+ return {
+ ...post,
+ liked: !post.liked,
+ likes: post.liked ? post.likes - 1 : post.likes + 1
+ };
+ }
+ return post;
+ });
+
+ this.setData({ posts });
+
+ API.likePost(postId).then(res => {
+ console.log('点赞成功');
+ }).catch(err => {
+ console.error('点赞失败:', err);
+ });
+ },
+
+ commentPost(e) {
+ const postId = e.currentTarget.dataset.id;
+ wx.navigateTo({
+ url: `/pages/eggbar/post-detail?id=${postId}&focusComment=true`
+ });
+ },
+
+ sharePost(e) {
+ const postId = e.currentTarget.dataset.id;
+ wx.showShareMenu({
+ withShareTicket: true,
+ success: () => {
+ console.log('分享成功');
+ }
+ });
+ },
+
+ createPost() {
+ wx.navigateTo({
+ url: '/pages/eggbar/create-post'
+ });
+ },
+
+ onShareAppMessage() {
+ return {
+ title: '蛋吧 - 鸡蛋行业交流社区',
+ path: '/pages/eggbar/eggbar',
+ imageUrl: '/images/eggbar-share.jpg'
+ };
+ }
+});
diff --git a/pages/eggbar/eggbar.json b/pages/eggbar/eggbar.json
new file mode 100644
index 0000000..0fe848f
--- /dev/null
+++ b/pages/eggbar/eggbar.json
@@ -0,0 +1,12 @@
+{
+ "usingComponents": {
+ "navigation-bar": "/components/navigation-bar/navigation-bar"
+ },
+ "enablePullDownRefresh": false,
+ "backgroundTextStyle": "dark",
+ "backgroundColor": "#f8f8f8",
+ "navigationBarBackgroundColor": "#ffffff",
+ "navigationBarTitleText": "蛋吧",
+ "navigationBarTextStyle": "black",
+ "navigationStyle": "custom"
+}
diff --git a/pages/eggbar/eggbar.wxml b/pages/eggbar/eggbar.wxml
new file mode 100644
index 0000000..1f5aa69
--- /dev/null
+++ b/pages/eggbar/eggbar.wxml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+ 热门话题
+
+
+
+ {{index + 1}}
+
+ {{item.name}}
+ {{item.count}}人讨论
+
+
+
+
+
+
+
+ 最新动态
+
+
+
+
+
+ {{item.content}}
+
+
+
+
+
+
+
+
+
+ 加载中...
+
+
+
+ 没有更多内容了
+
+
+
+ 📭
+ 暂无动态
+
+
+
+
+
+ ✏️
+
+
diff --git a/pages/eggbar/eggbar.wxss b/pages/eggbar/eggbar.wxss
new file mode 100644
index 0000000..5e89ae1
--- /dev/null
+++ b/pages/eggbar/eggbar.wxss
@@ -0,0 +1,270 @@
+page {
+ background-color: #f5f5f5;
+ height: 100vh;
+}
+
+.container {
+ min-height: 100vh;
+ padding-bottom: 120rpx;
+}
+
+.content {
+ padding: 20rpx;
+}
+
+.header {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 20rpx;
+ padding: 40rpx 30rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 4rpx 20rpx rgba(102, 126, 234, 0.3);
+}
+
+.title {
+ display: block;
+ font-size: 48rpx;
+ font-weight: bold;
+ color: #ffffff;
+ margin-bottom: 10rpx;
+}
+
+.subtitle {
+ display: block;
+ font-size: 28rpx;
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.section {
+ background: #ffffff;
+ border-radius: 20rpx;
+ padding: 30rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+}
+
+.section-title {
+ margin-bottom: 20rpx;
+ padding-bottom: 15rpx;
+ border-bottom: 2rpx solid #f0f0f0;
+}
+
+.title-text {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333333;
+}
+
+.topic-list {
+ display: flex;
+ flex-direction: column;
+ gap: 15rpx;
+}
+
+.topic-item {
+ display: flex;
+ align-items: center;
+ padding: 20rpx;
+ background: #f8f9fa;
+ border-radius: 12rpx;
+ transition: all 0.3s ease;
+}
+
+.topic-item:active {
+ transform: scale(0.98);
+ background: #e9ecef;
+}
+
+.topic-rank {
+ width: 50rpx;
+ height: 50rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 50%;
+ font-size: 24rpx;
+ font-weight: bold;
+ color: #ffffff;
+ margin-right: 20rpx;
+}
+
+.topic-info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 5rpx;
+}
+
+.topic-name {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #333333;
+}
+
+.topic-count {
+ font-size: 24rpx;
+ color: #999999;
+}
+
+.post-list {
+ display: flex;
+ flex-direction: column;
+ gap: 20rpx;
+}
+
+.post-item {
+ background: #ffffff;
+ border-radius: 16rpx;
+ padding: 25rpx;
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
+ transition: all 0.3s ease;
+}
+
+.post-item:active {
+ transform: translateY(-2rpx);
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+}
+
+.post-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 15rpx;
+}
+
+.post-avatar {
+ width: 80rpx;
+ height: 80rpx;
+ border-radius: 50%;
+ margin-right: 15rpx;
+ background: #f0f0f0;
+}
+
+.post-user {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 5rpx;
+}
+
+.post-username {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: #333333;
+}
+
+.post-time {
+ font-size: 24rpx;
+ color: #999999;
+}
+
+.post-content {
+ margin-bottom: 15rpx;
+}
+
+.post-text {
+ display: block;
+ font-size: 28rpx;
+ color: #333333;
+ line-height: 1.6;
+ margin-bottom: 15rpx;
+}
+
+.post-images {
+ display: flex;
+ gap: 10rpx;
+ flex-wrap: wrap;
+}
+
+.post-image {
+ width: 200rpx;
+ height: 200rpx;
+ border-radius: 12rpx;
+ background: #f0f0f0;
+}
+
+.post-footer {
+ display: flex;
+ justify-content: space-around;
+ padding-top: 15rpx;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.post-action {
+ display: flex;
+ align-items: center;
+ gap: 8rpx;
+ padding: 10rpx 20rpx;
+ border-radius: 20rpx;
+ transition: all 0.3s ease;
+}
+
+.post-action:active {
+ background: #f5f5f5;
+}
+
+.action-icon {
+ font-size: 32rpx;
+}
+
+.action-text {
+ font-size: 24rpx;
+ color: #666666;
+}
+
+.loading {
+ text-align: center;
+ padding: 40rpx;
+ color: #999999;
+ font-size: 28rpx;
+}
+
+.no-more {
+ text-align: center;
+ padding: 40rpx;
+ color: #999999;
+ font-size: 28rpx;
+}
+
+.empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 100rpx 20rpx;
+}
+
+.empty-icon {
+ font-size: 120rpx;
+ margin-bottom: 20rpx;
+ opacity: 0.5;
+}
+
+.empty-text {
+ font-size: 28rpx;
+ color: #999999;
+}
+
+.fab-button {
+ position: fixed;
+ right: 30rpx;
+ bottom: 150rpx;
+ width: 120rpx;
+ height: 120rpx;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.4);
+ z-index: 1000;
+ transition: all 0.3s ease;
+}
+
+.fab-button:active {
+ transform: scale(0.95);
+ box-shadow: 0 4rpx 15rpx rgba(102, 126, 234, 0.3);
+}
+
+.fab-icon {
+ font-size: 48rpx;
+}
diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js
index 93880e4..15c5141 100644
--- a/server-example/server-mysql.js
+++ b/server-example/server-mysql.js
@@ -125,6 +125,57 @@ app.post('/api/test/post', (req, res) => {
});
});
+
+// Eggbar 帖子创建接口
+app.post('/api/eggbar/posts', async (req, res) => {
+ try {
+ console.log('===== 收到帖子创建请求 =====');
+ console.log('1. 收到请求体:', JSON.stringify(req.body, null, 2));
+
+ const { content, images, topic } = req.body;
+
+ // 数据验证
+ if (!content || content.trim() === '') {
+ return res.status(400).json({
+ success: false,
+ code: 400,
+ message: '帖子内容不能为空'
+ });
+ }
+
+ // 处理图片数据,确保是JSON格式
+ let imagesJson = null;
+ if (images && Array.isArray(images) && images.length > 0) {
+ imagesJson = JSON.stringify(images);
+ }
+
+ // 创建帖子记录
+ const newPost = await EggbarPost.create({
+ content: content.trim(),
+ images: imagesJson,
+ topic: topic || null
+ });
+
+ console.log('2. 帖子创建成功,ID:', newPost.id);
+
+ res.json({
+ success: true,
+ code: 200,
+ message: '帖子发布成功',
+ data: {
+ postId: newPost.id
+ }
+ });
+ } catch (error) {
+ console.error('创建帖子失败:', error);
+ res.status(500).json({
+ success: false,
+ code: 500,
+ message: '创建帖子失败: ' + error.message
+ });
+ }
+});
+
// 获取封面图片列表接口
app.get('/api/cover', async (req, res) => {
try {
@@ -219,6 +270,39 @@ const upload = multer({
fileFilter: fileFilter
});
+// Eggbar 图片上传接口
+app.post('/api/eggbar/upload', upload.single('image'), async (req, res) => {
+ try {
+ console.log('===== 收到图片上传请求 =====');
+ console.log('1. 文件信息:', req.file);
+ console.log('2. 表单数据:', req.body);
+
+ if (!req.file) {
+ return res.status(400).json({
+ success: false,
+ message: '没有收到文件'
+ });
+ }
+
+ // 使用OSS上传图片
+ const imageUrl = await OssUploader.uploadFile(req.file.path, 'eggbar', 'image');
+
+ console.log('3. 图片上传成功,URL:', imageUrl);
+
+ res.json({
+ success: true,
+ message: '图片上传成功',
+ imageUrl: imageUrl
+ });
+ } catch (error) {
+ console.error('上传图片失败:', error);
+ res.status(500).json({
+ success: false,
+ message: '上传图片失败: ' + error.message
+ });
+ }
+});
+
// 添加请求日志中间件,捕获所有到达服务器的请求(必须放在bodyParser之后)
app.use((req, res, next) => {
// 使用统一的时间处理函数获取当前时间
@@ -1306,6 +1390,42 @@ Cover.init({
timestamps: false
});
+// Eggbar 帖子模型 - 用于存储用户发布的动态
+class EggbarPost extends Model { }
+EggbarPost.init({
+ id: {
+ type: DataTypes.INTEGER,
+ primaryKey: true,
+ autoIncrement: true,
+ comment: '帖子ID'
+ },
+ content: {
+ type: DataTypes.TEXT,
+ allowNull: false,
+ comment: '帖子内容'
+ },
+ images: {
+ type: DataTypes.TEXT,
+ allowNull: true,
+ comment: '图片URL,JSON格式存储'
+ },
+ topic: {
+ type: DataTypes.STRING(255),
+ allowNull: true,
+ comment: '话题'
+ },
+ created_at: {
+ type: DataTypes.DATE,
+ defaultValue: Sequelize.NOW,
+ comment: '创建时间'
+ }
+}, {
+ sequelize,
+ modelName: 'EggbarPost',
+ tableName: 'eggbar_posts',
+ timestamps: false
+});
+
// 定义模型之间的关联关系
// 用户和商品的一对多关系 (卖家发布商品)
diff --git a/utils/api.js b/utils/api.js
index ada928e..6e5618c 100644
--- a/utils/api.js
+++ b/utils/api.js
@@ -4500,5 +4500,65 @@ module.exports = {
resolve({ exists: false, error: error.message });
});
});
+ },
+
+ // 获取热门话题
+ getHotTopics: function() {
+ return new Promise((resolve, reject) => {
+ request('/api/eggbar/hot-topics', 'GET')
+ .then(response => {
+ console.log('获取热门话题成功:', response);
+ resolve(response);
+ })
+ .catch(error => {
+ console.error('获取热门话题失败:', error);
+ reject(error);
+ });
+ });
+ },
+
+ // 获取动态列表
+ getPosts: function(params) {
+ return new Promise((resolve, reject) => {
+ request('/api/eggbar/posts', 'GET', params)
+ .then(response => {
+ console.log('获取动态列表成功:', response);
+ resolve(response);
+ })
+ .catch(error => {
+ console.error('获取动态列表失败:', error);
+ reject(error);
+ });
+ });
+ },
+
+ // 点赞动态
+ likePost: function(postId) {
+ return new Promise((resolve, reject) => {
+ request(`/api/eggbar/posts/${postId}/like`, 'POST')
+ .then(response => {
+ console.log('点赞成功:', response);
+ resolve(response);
+ })
+ .catch(error => {
+ console.error('点赞失败:', error);
+ reject(error);
+ });
+ });
+ },
+
+ // 创建动态
+ createPost: function(postData) {
+ return new Promise((resolve, reject) => {
+ request('/api/eggbar/posts', 'POST', postData)
+ .then(response => {
+ console.log('创建动态成功:', response);
+ resolve(response);
+ })
+ .catch(error => {
+ console.error('创建动态失败:', error);
+ reject(error);
+ });
+ });
}
};
\ No newline at end of file
--
2.30.2
From 21d50f31f084cb2dd9ffbac1f59403b9a87b2e53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Tue, 27 Jan 2026 18:16:58 +0800
Subject: [PATCH 06/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8Deggbar=E5=8F=91?=
=?UTF-8?q?=E5=B8=83=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=9B=B4=E6=96=B0=E9=AA=8C?=
=?UTF-8?q?=E8=AF=81=E9=80=BB=E8=BE=91=E5=B9=B6=E9=81=BF=E5=85=8D=E7=AB=AF?=
=?UTF-8?q?=E7=82=B9=E5=86=B2=E7=AA=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/eggbar/create-post.js | 39 +++++++++++++++++++++++----
pages/eggbar/create-post.wxml | 2 +-
server-example/server-mysql.js | 48 ++++++++++++++++++++++++++++++---
server-example/test-post-api.js | 47 ++++++++++++++++++++++++++++++++
4 files changed, 127 insertions(+), 9 deletions(-)
create mode 100644 server-example/test-post-api.js
diff --git a/pages/eggbar/create-post.js b/pages/eggbar/create-post.js
index c713daf..d2c2a77 100644
--- a/pages/eggbar/create-post.js
+++ b/pages/eggbar/create-post.js
@@ -15,11 +15,28 @@ Page({
loadHotTopics() {
API.getHotTopics().then(res => {
- this.setData({
- hotTopics: res.data || []
- });
+ if (res.data && res.data.length > 0) {
+ this.setData({
+ hotTopics: res.data
+ });
+ } else {
+ // 使用默认热门话题
+ this.setData({
+ hotTopics: [
+ { id: 1, name: '今天你吃蛋了么?', count: 123 },
+ { id: 2, name: '日常分享', count: 456 }
+ ]
+ });
+ }
}).catch(err => {
console.error('加载热门话题失败:', err);
+ // 出错时使用默认热门话题
+ this.setData({
+ hotTopics: [
+ { id: 1, name: '今天你吃蛋了么?', count: 123 },
+ { id: 2, name: '日常分享', count: 456 }
+ ]
+ });
});
},
@@ -87,10 +104,19 @@ Page({
},
submit() {
- if (!this.data.content.trim()) {
+ console.log('点击了发布按钮,当前数据:', {
+ content: this.data.content,
+ images: this.data.images,
+ selectedTopic: this.data.selectedTopic
+ });
+
+ if (!this.data.content.trim() && !this.data.selectedTopic) {
+ console.log('验证失败:文本内容和话题都为空');
return;
}
+ console.log('验证通过,开始发布');
+
wx.showLoading({
title: '发布中...'
});
@@ -98,15 +124,18 @@ Page({
// 先上传图片,获取永久 URL
this.uploadImages(this.data.images)
.then(uploadedImages => {
+ console.log('图片上传完成,上传的图片数量:', uploadedImages.length);
const postData = {
content: this.data.content,
images: uploadedImages,
topic: this.data.selectedTopic
};
+ console.log('准备发送的发布数据:', postData);
return API.createPost(postData);
})
.then(res => {
+ console.log('发布成功,服务器返回:', res);
wx.hideLoading();
wx.showToast({
title: '发布成功',
@@ -117,12 +146,12 @@ Page({
}, 1000);
})
.catch(err => {
+ console.error('发布动态失败:', err);
wx.hideLoading();
wx.showToast({
title: '发布失败,请重试',
icon: 'none'
});
- console.error('发布动态失败:', err);
});
},
diff --git a/pages/eggbar/create-post.wxml b/pages/eggbar/create-post.wxml
index ba07cad..986cc3d 100644
--- a/pages/eggbar/create-post.wxml
+++ b/pages/eggbar/create-post.wxml
@@ -45,7 +45,7 @@
diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js
index 15c5141..28d6306 100644
--- a/server-example/server-mysql.js
+++ b/server-example/server-mysql.js
@@ -134,12 +134,12 @@ app.post('/api/eggbar/posts', async (req, res) => {
const { content, images, topic } = req.body;
- // 数据验证
- if (!content || content.trim() === '') {
+ // 数据验证 - 允许只填写内容或话题中的一项
+ if ((!content || content.trim() === '') && !topic) {
return res.status(400).json({
success: false,
code: 400,
- message: '帖子内容不能为空'
+ message: '文本内容和话题至少需要填写一项'
});
}
@@ -201,6 +201,48 @@ app.get('/api/cover', async (req, res) => {
}
});
+// 创建动态接口(已废弃 - 使用上面的实际实现)
+app.post('/api/eggbar/posts/deprecated', async (req, res) => {
+ try {
+ console.log('===== 创建动态接口被调用 =====');
+ console.log('收到的请求数据:', req.body);
+
+ const { content, images, topic } = req.body;
+
+ // 验证参数
+ if (!content && !topic) {
+ return res.json({
+ success: false,
+ message: '文本内容和话题至少需要填写一项'
+ });
+ }
+
+ // 模拟创建动态
+ console.log('创建动态成功:', {
+ content,
+ images,
+ topic
+ });
+
+ res.json({
+ success: true,
+ message: '发布成功',
+ data: {
+ content,
+ images,
+ topic
+ }
+ });
+ } catch (error) {
+ console.error('创建动态失败:', error);
+ res.json({
+ success: false,
+ message: '发布失败,请重试',
+ error: error.message
+ });
+ }
+});
+
// 创建临时文件夹用于存储上传的文件
const uploadTempDir = path.join(__dirname, 'temp-uploads');
if (!fs.existsSync(uploadTempDir)) {
diff --git a/server-example/test-post-api.js b/server-example/test-post-api.js
new file mode 100644
index 0000000..3b738f4
--- /dev/null
+++ b/server-example/test-post-api.js
@@ -0,0 +1,47 @@
+// 测试创建动态API
+const http = require('http');
+
+// 测试数据
+const testData = {
+ content: '测试发布帖子',
+ images: ['https://example.com/image1.jpg', 'https://example.com/image2.jpg'],
+ topic: '今天你吃蛋了么?'
+};
+
+// 发送POST请求到主服务器
+const options = {
+ hostname: 'localhost',
+ port: 3003,
+ path: '/api/eggbar/posts',
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Content-Length': Buffer.byteLength(JSON.stringify(testData))
+ }
+};
+
+const req = http.request(options, (res) => {
+ console.log(`状态码: ${res.statusCode}`);
+ console.log(`响应头: ${JSON.stringify(res.headers)}`);
+
+ let data = '';
+ res.on('data', (chunk) => {
+ data += chunk;
+ });
+
+ res.on('end', () => {
+ console.log('响应体:', data);
+ console.log('测试完成');
+ });
+});
+
+req.on('error', (e) => {
+ console.error(`请求错误: ${e.message}`);
+});
+
+// 发送请求体
+req.write(JSON.stringify(testData));
+req.end();
+
+console.log('正在发送测试请求到 http://localhost:3003/api/eggbar/posts...');
+console.log('测试数据:', testData);
--
2.30.2
From 7a5a1ba300563e1621d737adb9572665dfdb7b10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 10:43:07 +0800
Subject: [PATCH 07/22] Fix: Remove default comments and fix comment display
issue
---
pages/eggbar/create-post.js | 16 ++++-
pages/evaluate2/product-list.js | 22 +++++++
pages/goods-detail/goods-detail.js | 37 ++----------
server-example/.env | 4 +-
server-example/server-mysql.js | 93 +++++++++++++++++++++++++-----
utils/api.js | 18 ++++--
6 files changed, 135 insertions(+), 55 deletions(-)
diff --git a/pages/eggbar/create-post.js b/pages/eggbar/create-post.js
index d2c2a77..2ea6a48 100644
--- a/pages/eggbar/create-post.js
+++ b/pages/eggbar/create-post.js
@@ -125,10 +125,24 @@ Page({
this.uploadImages(this.data.images)
.then(uploadedImages => {
console.log('图片上传完成,上传的图片数量:', uploadedImages.length);
+
+ // 获取用户ID
+ const userId = wx.getStorageSync('userId');
+ if (!userId) {
+ throw new Error('用户未登录');
+ }
+
+ // 获取用户电话号码
+ const userInfo = wx.getStorageSync('userInfo');
+ const phoneNumber = userInfo?.phoneNumber || wx.getStorageSync('phoneNumber');
+ console.log('获取到的用户电话号码:', phoneNumber);
+
const postData = {
+ user_id: userId,
+ phone: phoneNumber,
content: this.data.content,
images: uploadedImages,
- topic: this.data.selectedTopic
+ topic: this.data.selectedTopic?.name || this.data.selectedTopic
};
console.log('准备发送的发布数据:', postData);
diff --git a/pages/evaluate2/product-list.js b/pages/evaluate2/product-list.js
index f28c65c..5c5ecd9 100644
--- a/pages/evaluate2/product-list.js
+++ b/pages/evaluate2/product-list.js
@@ -73,6 +73,8 @@ Page({
// 从原始商品数据中计算价格范围
const allProducts = wx.getStorageSync('allProducts') || [];
+ console.log('本地存储中的商品总数:', allProducts.length);
+ console.log('当前分类:', this.data.category);
if (allProducts.length > 0) {
// 过滤出当前分类下的商品
const categoryProducts = allProducts.filter(product => {
@@ -80,19 +82,26 @@ Page({
const productCategory = String(product.category).trim();
return productCategory === this.data.category;
});
+ console.log('当前分类下的商品数量:', categoryProducts.length);
+ console.log('当前分类下的商品详情:', categoryProducts);
// 按规格分组计算平均价格
const specPriceMap = {};
categoryProducts.forEach(product => {
+ console.log('处理商品:', product.productName || product.name, '价格:', product.price, '规格:', product.specification || product.spec);
if (product.price && (product.specification || product.spec)) {
const priceStr = String(product.price).trim();
const specStr = String(product.specification || product.spec).trim();
+ console.log('商品价格字符串:', priceStr, '规格字符串:', specStr);
+
// 处理逗号分隔的多个价格
const priceArray = priceStr.split(',').map(p => p.trim()).filter(p => p && p.trim() !== '');
+ console.log('处理后的价格数组:', priceArray);
// 处理逗号分隔的多个规格
let specs = specStr.split(',').map(spec => spec.trim()).filter(spec => spec.length > 0);
+ console.log('处理后的规格数组:', specs);
// 进一步处理规格,确保每个规格都是独立的
const processedSpecs = [];
@@ -106,9 +115,11 @@ Page({
}
});
specs = processedSpecs;
+ console.log('最终规格数组:', specs);
// 将规格和价格配对
specs.forEach((spec, index) => {
+ console.log('处理规格:', spec, '对应价格索引:', index);
if (spec.length > 0 && index < priceArray.length) {
const price = priceArray[index];
if (price && price.trim() !== '') {
@@ -116,6 +127,7 @@ Page({
if (!isNaN(priceValue)) {
// 解析规格
const specInfo = this.parseSpecification(spec);
+ console.log('解析规格结果:', specInfo);
// 价格<10的需要按照公式计算
let finalPrice = priceValue;
@@ -127,6 +139,7 @@ Page({
// 毛重:(规格平均值 - 5) × 价格
finalPrice = (specInfo.avg - 5) * priceValue;
}
+ console.log('价格计算:', priceValue, '->', finalPrice);
}
// 按规格分组存储价格
@@ -134,10 +147,19 @@ Page({
specPriceMap[spec] = [];
}
specPriceMap[spec].push(finalPrice);
+ console.log('存储价格:', finalPrice, '到规格:', spec);
+ } else {
+ console.log('价格解析失败:', price);
}
+ } else {
+ console.log('价格为空或无效:', price);
}
+ } else {
+ console.log('规格长度为0或价格索引超出范围:', spec.length, index, priceArray.length);
}
});
+ } else {
+ console.log('商品缺少价格或规格:', !product.price ? '无价格' : '', !product.specification && !product.spec ? '无规格' : '');
}
});
diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js
index 75dc48c..79662ed 100644
--- a/pages/goods-detail/goods-detail.js
+++ b/pages/goods-detail/goods-detail.js
@@ -1887,31 +1887,6 @@ Page({
});
},
- // 20 default comments
- getDefaultComments() {
- return [
- "鸡蛋品相贼好无破损,规格统一超适合批发",
- "个头匀溜大小一致,装箱发货一点不费劲",
- "包装严实防震,整车运输下来个个完好",
- "蛋液浓稠清亮,品相达标完全符合供货要求",
- "性价比真绝了,新鲜度在线囤货超划算",
- "农家散养蛋品相佳,蛋黄紧实供货超稳定",
- "物流嗖嗖快,到货鸡蛋无磕碰超省心",
- "蛋壳干净无污渍,分拣打包效率直接拉满",
- "个个饱满无瘪壳,市场铺货回头客贼多",
- "分量超足规格齐,商超供货完全没毛病",
- "无抗生素达标蛋,走商超渠道妥妥放心",
- "蛋壳硬度够,装卸搬运全程零损耗",
- "防震包装太贴心,长途运输损耗率超低",
- "保鲜期够长,放一周品相依旧很能打",
- "蛋体完整无瑕疵,分拣挑拣省超多功夫",
- "品质稳定没色差,长期合作完全没问题",
- "货源稳定供货及时,补货节奏卡得刚刚好",
- "发货快包装硬,对接商超渠道超靠谱",
- "蛋黄蛋清分层好,加工拿货性价比拉满",
- "品质远超预期,后续订单必须锁定这家"
- ];
- },
// Seeded random number generator for consistent results
seededRandom(seed) {
@@ -2016,9 +1991,8 @@ Page({
});
console.log('应用审核逻辑后剩余评论数量:', filteredComments.length);
- // Always add default comments at the beginning
- const defaultComments = this.getConsistentRandomComments(productId, 2);
- commentsData = [...defaultComments, ...filteredComments];
+ // Use only filtered comments without default comments
+ commentsData = filteredComments;
// 检查返回的评论是否都属于当前用户
const allCommentsBelongToCurrentUser = commentsData.every(comment =>
@@ -2053,11 +2027,10 @@ Page({
.catch(err => {
console.error('获取评论失败:', err);
console.error('错误详情:', JSON.stringify(err, null, 2));
- // 加载失败时使用默认评论
- console.log('使用默认评论');
- const defaultComments = this.getConsistentRandomComments(productId, 2);
+ // 加载失败时使用空数组
+ console.log('使用空评论数组');
this.setData({
- comments: defaultComments
+ comments: []
});
});
},
diff --git a/server-example/.env b/server-example/.env
index 387804d..6ba4a3f 100644
--- a/server-example/.env
+++ b/server-example/.env
@@ -4,10 +4,10 @@ WECHAT_APPSECRET=78fd81bce5a2968a8e7c607ae68c4c0b
WECHAT_TOKEN=your-random-token
# MySQL数据库配置(请根据您的实际环境修改)
-# 如果是首次使用,可能需要先在MySQL中创建wechat_app数据库
+# 连接到eggbar数据库
DB_HOST=1.95.162.61
DB_PORT=3306
-DB_DATABASE=wechat_app
+DB_DATABASE=eggbar
# 请使用您实际的MySQL用户名
DB_USER=root
# 请使用您实际的MySQL密码
diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js
index 28d6306..00620fe 100644
--- a/server-example/server-mysql.js
+++ b/server-example/server-mysql.js
@@ -132,27 +132,29 @@ app.post('/api/eggbar/posts', async (req, res) => {
console.log('===== 收到帖子创建请求 =====');
console.log('1. 收到请求体:', JSON.stringify(req.body, null, 2));
- const { content, images, topic } = req.body;
+ const { user_id, content, images, topic, phone } = req.body;
- // 数据验证 - 允许只填写内容或话题中的一项
- if ((!content || content.trim() === '') && !topic) {
+ // 数据验证
+ if (!user_id) {
return res.status(400).json({
success: false,
code: 400,
- message: '文本内容和话题至少需要填写一项'
+ message: '缺少用户ID'
});
}
- // 处理图片数据,确保是JSON格式
- let imagesJson = null;
+ // 处理图片数据
+ let imagesData = null;
if (images && Array.isArray(images) && images.length > 0) {
- imagesJson = JSON.stringify(images);
+ imagesData = images;
}
// 创建帖子记录
const newPost = await EggbarPost.create({
- content: content.trim(),
- images: imagesJson,
+ user_id: user_id,
+ phone: phone || null,
+ content: content || null,
+ images: imagesData,
topic: topic || null
});
@@ -525,6 +527,29 @@ const userLoginSequelize = new Sequelize(
}
);
+// 3. eggbar数据源连接
+const eggbarSequelize = new Sequelize(
+ 'eggbar',
+ dbConfig.user,
+ dbConfig.password,
+ {
+ host: dbConfig.host,
+ port: dbConfig.port,
+ dialect: 'mysql',
+ pool: {
+ max: 10,
+ min: 0,
+ acquire: 30000,
+ idle: 10000
+ },
+ logging: console.log,
+ define: {
+ timestamps: false
+ },
+ timezone: '+08:00' // 设置时区为UTC+8
+ }
+);
+
// 为保持兼容性,保留默认sequelize引用(指向wechat_app)
const sequelize = wechatAppSequelize;
@@ -1441,28 +1466,68 @@ EggbarPost.init({
autoIncrement: true,
comment: '帖子ID'
},
+ user_id: {
+ type: DataTypes.STRING(100),
+ allowNull: false,
+ comment: '用户ID'
+ },
+ phone: {
+ type: DataTypes.STRING(20),
+ allowNull: true,
+ comment: '用户电话号码'
+ },
content: {
type: DataTypes.TEXT,
- allowNull: false,
- comment: '帖子内容'
+ allowNull: true,
+ comment: '动态内容'
},
images: {
- type: DataTypes.TEXT,
+ type: DataTypes.JSON,
allowNull: true,
- comment: '图片URL,JSON格式存储'
+ comment: '图片URL数组'
},
topic: {
type: DataTypes.STRING(255),
allowNull: true,
comment: '话题'
},
+ likes: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: 0,
+ comment: '点赞数'
+ },
+ comments: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: 0,
+ comment: '评论数'
+ },
+ shares: {
+ type: DataTypes.INTEGER,
+ allowNull: true,
+ defaultValue: 0,
+ comment: '分享数'
+ },
+ status: {
+ type: DataTypes.ENUM('active', 'inactive'),
+ allowNull: true,
+ defaultValue: 'active',
+ comment: '状态'
+ },
created_at: {
type: DataTypes.DATE,
defaultValue: Sequelize.NOW,
comment: '创建时间'
+ },
+ updated_at: {
+ type: DataTypes.DATE,
+ defaultValue: Sequelize.NOW,
+ onUpdate: Sequelize.NOW,
+ comment: '更新时间'
}
}, {
- sequelize,
+ sequelize: eggbarSequelize,
modelName: 'EggbarPost',
tableName: 'eggbar_posts',
timestamps: false
diff --git a/utils/api.js b/utils/api.js
index 6e5618c..7bbc547 100644
--- a/utils/api.js
+++ b/utils/api.js
@@ -1364,11 +1364,14 @@ module.exports = {
console.log('商品数据:', productData);
console.log('图片数量:', imageUrls.length);
- // 【新增】确保sellerId使用userId
+ // 【关键修复】确保sellerId使用userId,无论是否已存在
const userId = wx.getStorageSync('userId');
- if (userId && productData.sellerId) {
+ if (userId) {
console.log('【修复】确保sellerId使用userId:', userId);
- productData.sellerId = userId; // 确保使用userId
+ productData.sellerId = userId;
+ } else {
+ console.error('【错误】本地缓存中没有userId,请重新登录');
+ return Promise.reject(new Error('用户未登录,请重新登录'));
}
// 如果没有图片,使用普通请求
@@ -1382,7 +1385,7 @@ module.exports = {
// 创建包含所有图片URL的商品数据
const productDataWithAllImages = {
...productData,
- sellerId: userId || productData.sellerId, // 【确保】使用userId
+ sellerId: userId, // 【确保】使用userId
imageUrls: imageUrls, // 设置imageUrls字段,确保服务器端能正确识别
allImageUrls: imageUrls, // 添加完整的图片URL列表(备用字段)
// 生成会话ID,确保所有图片上传关联同一个商品
@@ -1403,11 +1406,14 @@ module.exports = {
console.log('===== 最终版uploadProductWithRecursiveImages开始执行 =====');
console.log('待上传图片数量:', imageUrls.length);
- // 【新增】确保sellerId使用userId
+ // 【关键修复】确保sellerId使用userId,无论是否已存在
const userId = wx.getStorageSync('userId');
- if (userId && productData.sellerId) {
+ if (userId) {
console.log('【修复】确保sellerId使用userId:', userId);
productData.sellerId = userId;
+ } else {
+ console.error('【错误】本地缓存中没有userId,请重新登录');
+ return Promise.reject(new Error('用户未登录,请重新登录'));
}
// 防御性检查
--
2.30.2
From 38d29d32c5edde21432cbfda2485dbfabe22eb6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 11:02:01 +0800
Subject: [PATCH 08/22] Fix: Disable swipe back on iOS for product-list page
---
pages/evaluate2/product-list.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pages/evaluate2/product-list.json b/pages/evaluate2/product-list.json
index 09e623a..01c4309 100644
--- a/pages/evaluate2/product-list.json
+++ b/pages/evaluate2/product-list.json
@@ -1,5 +1,6 @@
{
"usingComponents": {},
"enablePullDownRefresh": true,
- "backgroundTextStyle": "dark"
+ "backgroundTextStyle": "dark",
+ "disableSwipeBack": true
}
\ No newline at end of file
--
2.30.2
From f30b335795794153b92d415dcdfb2f302f8ac778 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 11:03:59 +0800
Subject: [PATCH 09/22] Fix: Remove fixed width to prevent horizontal scrolling
on iOS
---
pages/evaluate2/product-list.wxml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pages/evaluate2/product-list.wxml b/pages/evaluate2/product-list.wxml
index 7a07798..b85fc11 100644
--- a/pages/evaluate2/product-list.wxml
+++ b/pages/evaluate2/product-list.wxml
@@ -1,7 +1,7 @@
\ No newline at end of file
--
2.30.2
From d0b65d70bbab94938309b6be88323d91355fdfe5 Mon Sep 17 00:00:00 2001
From: Default User
Date: Wed, 28 Jan 2026 16:15:18 +0800
Subject: [PATCH 13/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E7=89=87?=
=?UTF-8?q?=E4=B8=8A=E4=BC=A0=E5=92=8C=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?=
=?UTF-8?q?=EF=BC=9A1.=20=E5=B0=86eggbar/create-post.js=E5=9B=BE=E7=89=87?=
=?UTF-8?q?=E4=B8=8A=E4=BC=A0=E9=99=90=E5=88=B6=E4=BB=8E9=E5=BC=A0?=
=?UTF-8?q?=E6=94=B9=E4=B8=BA5=E5=BC=A0=EF=BC=9B2.=20=E4=BF=AE=E5=A4=8Degg?=
=?UTF-8?q?bar/eggbar.js=E4=B8=AD=E5=9B=BE=E7=89=87URL=E8=A7=A3=E6=9E=90?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E7=A1=AE=E4=BF=9Dimages=E5=AD=97?=
=?UTF-8?q?=E6=AE=B5=E6=AD=A3=E7=A1=AE=E8=A7=A3=E6=9E=90=E4=B8=BA=E6=95=B0?=
=?UTF-8?q?=E7=BB=84=EF=BC=9B3.=20=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=E5=85=B6=E4=BB=96=E7=9B=B8=E5=85=B3=E6=96=87=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/eggbar/create-post.js | 21 ++++-
pages/eggbar/eggbar.js | 26 ++++++
pages/profile/authentication/index.js | 123 +++++++++++++++++++++-----
project.private.config.json | 2 +-
server-example/server-mysql.js | 19 +++-
5 files changed, 162 insertions(+), 29 deletions(-)
diff --git a/pages/eggbar/create-post.js b/pages/eggbar/create-post.js
index bffa7d8..3547114 100644
--- a/pages/eggbar/create-post.js
+++ b/pages/eggbar/create-post.js
@@ -53,16 +53,16 @@ Page({
},
chooseImage() {
- if (this.data.images.length >= 9) {
+ if (this.data.images.length >= 5) {
wx.showToast({
- title: '最多只能上传9张图片',
+ title: '最多只能上传5张图片',
icon: 'none'
});
return;
}
wx.chooseImage({
- count: 9 - this.data.images.length,
+ count: 5 - this.data.images.length,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
@@ -185,6 +185,7 @@ Page({
const uploadedImages = [];
let uploadedCount = 0;
+ let hasError = false;
tempImagePaths.forEach((tempPath, index) => {
wx.uploadFile({
@@ -201,19 +202,31 @@ Page({
const data = JSON.parse(res.data);
if (data.success && data.imageUrl) {
uploadedImages.push(data.imageUrl);
+ } else {
+ console.error('上传图片失败:', data.message || '未知错误');
+ hasError = true;
}
} catch (e) {
console.error('解析上传响应失败:', e);
+ hasError = true;
}
+ } else {
+ console.error('上传图片失败,HTTP状态码:', res.statusCode);
+ hasError = true;
}
},
fail: (err) => {
console.error('上传图片失败:', err);
+ hasError = true;
},
complete: () => {
uploadedCount++;
if (uploadedCount === tempImagePaths.length) {
- resolve(uploadedImages);
+ if (hasError && uploadedImages.length === 0) {
+ reject(new Error('所有图片上传失败,请重试'));
+ } else {
+ resolve(uploadedImages);
+ }
}
}
});
diff --git a/pages/eggbar/eggbar.js b/pages/eggbar/eggbar.js
index 68bcd62..2bcda6e 100644
--- a/pages/eggbar/eggbar.js
+++ b/pages/eggbar/eggbar.js
@@ -90,6 +90,32 @@ Page({
// 正确处理后端返回的响应格式
let newPosts = res.data && res.data.posts ? res.data.posts : [];
+ // 处理images字段,确保它是一个数组
+ newPosts = newPosts.map(post => {
+ if (post.images) {
+ // 如果images是字符串,尝试解析为JSON数组
+ if (typeof post.images === 'string') {
+ try {
+ post.images = JSON.parse(post.images);
+ // 确保解析后是数组
+ if (!Array.isArray(post.images)) {
+ post.images = [];
+ }
+ } catch (e) {
+ // 解析失败,设置为空数组
+ post.images = [];
+ }
+ } else if (!Array.isArray(post.images)) {
+ // 如果不是字符串也不是数组,设置为空数组
+ post.images = [];
+ }
+ } else {
+ // 如果images不存在,设置为空数组
+ post.images = [];
+ }
+ return post;
+ });
+
// 如果是第一页且没有数据,使用默认动态数据
if (this.data.page === 1 && (!newPosts || newPosts.length === 0)) {
newPosts = [
diff --git a/pages/profile/authentication/index.js b/pages/profile/authentication/index.js
index 3d438a8..78adfc7 100644
--- a/pages/profile/authentication/index.js
+++ b/pages/profile/authentication/index.js
@@ -1,4 +1,5 @@
// pages/profile/authentication/index.js
+const API = require('../../../utils/api.js');
Page({
/**
* 页面的初始数据
@@ -6,6 +7,8 @@ Page({
data: {
idCardFront: '', // 身份证人像面
idCardBack: '', // 身份证国徽面
+ idcard1: null, // 身份证正面文件信息
+ idcard2: null, // 身份证反面文件信息
name: '', // 姓名
idNumber: '', // 身份证号
address: '', // 居住地址
@@ -40,26 +43,27 @@ Page({
*/
uploadImage(field) {
const _this = this;
- wx.chooseMedia({
+ wx.chooseImage({
count: 1,
- mediaType: ['image'],
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
- success(res) {
- // 获取图片临时路径
- const tempFilePaths = res.tempFiles;
+ success: (res) => {
+ const tempFilePaths = res.tempFilePaths;
if (tempFilePaths && tempFilePaths.length > 0) {
// 更新页面数据
_this.setData({
- [field]: tempFilePaths[0].tempFilePath
+ [field === 'idCardFront' ? 'idCardFront' : 'idCardBack']: tempFilePaths[0],
+ [field === 'idCardFront' ? 'idcard1' : 'idcard2']: {
+ path: tempFilePaths[0],
+ name: `身份证${field === 'idCardFront' ? '正面' : '反面'}_${new Date().getTime()}.jpg`
+ }
});
- // 这里可以添加图片上传到服务器的逻辑
// 模拟识别成功后填充信息
_this.simulateOcrResult();
}
},
- fail(err) {
+ fail: (err) => {
console.error('选择图片失败:', err);
wx.showToast({
title: '选择图片失败',
@@ -83,10 +87,35 @@ Page({
});
},
+ /**
+ * 上传文件到服务器
+ */
+ async uploadFileToServer(filePath, fileType) {
+ try {
+ console.log(`开始上传${fileType}文件:`, filePath);
+
+ const result = await API.uploadSettlementFile(filePath, fileType);
+
+ if (result && result.fileUrl) {
+ console.log(`${fileType}上传成功:`, result.fileUrl);
+ return result.fileUrl;
+ } else {
+ throw new Error(`${fileType}上传失败`);
+ }
+ } catch (error) {
+ console.error(`${fileType}上传失败:`, error);
+ wx.showToast({
+ title: `${fileType}上传失败`,
+ icon: 'none'
+ });
+ throw error;
+ }
+ },
+
/**
* 提交认证
*/
- submitAuth() {
+ async submitAuth() {
// 验证是否上传了身份证
if (!this.data.idCardFront || !this.data.idCardBack) {
wx.showToast({
@@ -96,23 +125,73 @@ Page({
return;
}
- // 这里可以添加提交认证信息到服务器的逻辑
- wx.showLoading({ title: '提交中...' });
+ // 检查用户是否已登录
+ const openid = wx.getStorageSync('openid');
+ const userId = wx.getStorageSync('userId');
+
+ if (!openid || !userId) {
+ wx.showToast({
+ title: '请先登录',
+ icon: 'none'
+ });
+ return;
+ }
+
+ wx.showLoading({ title: '正在上传文件...', mask: true });
+
+ try {
+ // 上传身份证正面
+ const idcard1Url = await this.uploadFileToServer(this.data.idcard1.path, 'idCardFront');
+ // 上传身份证反面
+ const idcard2Url = await this.uploadFileToServer(this.data.idcard2.path, 'idCardBack');
- // 模拟提交成功
- setTimeout(() => {
+ console.log('所有文件上传完成');
+
+ // 准备提交数据
+ const submitData = {
+ openid: openid,
+ userId: userId,
+ idcard1: idcard1Url,
+ idcard2: idcard2Url,
+ name: this.data.name,
+ idNumber: this.data.idNumber,
+ address: this.data.address
+ };
+
+ console.log('提交数据:', submitData);
+
+ // 调用后端API提交数据
+ const result = await API.request('/api/user/update', 'POST', submitData);
+
+ console.log('认证提交结果:', result);
+
+ if (result && result.success) {
+ wx.hideLoading();
+ wx.showToast({
+ title: '认证成功',
+ icon: 'success',
+ duration: 1500
+ });
+
+ // 延时返回上一页
+ setTimeout(() => {
+ this.navigateBack();
+ }, 1500);
+ } else {
+ wx.hideLoading();
+ wx.showToast({
+ title: result.message || '认证失败',
+ icon: 'none'
+ });
+ }
+ } catch (error) {
wx.hideLoading();
+ console.error('认证提交失败:', error);
wx.showToast({
- title: '认证成功',
- icon: 'success',
- duration: 1500
+ title: '提交失败,请重试',
+ icon: 'none'
});
-
- // 延时返回上一页
- setTimeout(() => {
- this.navigateBack();
- }, 1500);
- }, 1000);
+ }
},
/**
diff --git a/project.private.config.json b/project.private.config.json
index f4f0e67..6b6a8c4 100644
--- a/project.private.config.json
+++ b/project.private.config.json
@@ -1,6 +1,6 @@
{
"libVersion": "3.10.3",
- "projectname": "xcx22",
+ "projectname": "wxxcx1",
"setting": {
"urlCheck": false,
"coverView": true,
diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js
index 601d0b0..cb7a77f 100644
--- a/server-example/server-mysql.js
+++ b/server-example/server-mysql.js
@@ -1036,6 +1036,14 @@ User.init({
notice: {
type: DataTypes.STRING(255) // 通知提醒
},
+ idcard1: {
+ type: DataTypes.TEXT, // 身份证正面
+ comment: '身份证正面'
+ },
+ idcard2: {
+ type: DataTypes.TEXT, // 身份证反面
+ comment: '身份证反面'
+ },
// 时间字段
created_at: {
type: DataTypes.DATE,
@@ -1576,9 +1584,16 @@ EggbarPost.init({
comment: '动态内容'
},
images: {
- type: DataTypes.JSON,
+ type: DataTypes.TEXT,
allowNull: true,
- comment: '图片URL数组'
+ comment: '图片URL数组',
+ get() {
+ const value = this.getDataValue('images');
+ return value ? JSON.parse(value) : [];
+ },
+ set(value) {
+ this.setDataValue('images', JSON.stringify(value));
+ }
},
topic: {
type: DataTypes.STRING(255),
--
2.30.2
From fdd712effe29e4290e749083062554431d46503e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 16:19:11 +0800
Subject: [PATCH 14/22] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AE=A4=E8=AF=81?=
=?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/authentication/index.js | 41 +++++--
pages/profile/authentication/index.wxml | 50 +++-----
pages/profile/index.wxml | 2 +-
pages/profile/index.wxss | 152 +++++++++++++++++++++++-
4 files changed, 197 insertions(+), 48 deletions(-)
diff --git a/pages/profile/authentication/index.js b/pages/profile/authentication/index.js
index 78adfc7..18ee7f1 100644
--- a/pages/profile/authentication/index.js
+++ b/pages/profile/authentication/index.js
@@ -7,8 +7,10 @@ Page({
data: {
idCardFront: '', // 身份证人像面
idCardBack: '', // 身份证国徽面
+ businessLicense: '', // 营业执照
idcard1: null, // 身份证正面文件信息
idcard2: null, // 身份证反面文件信息
+ businessLicenseFile: null, // 营业执照文件信息
name: '', // 姓名
idNumber: '', // 身份证号
address: '', // 居住地址
@@ -37,6 +39,13 @@ Page({
this.uploadImage('idCardBack');
},
+ /**
+ * 上传营业执照
+ */
+ uploadBusinessLicense() {
+ this.uploadImage('businessLicense');
+ },
+
/**
* 通用图片上传方法
* @param {string} field - 上传的字段名
@@ -50,17 +59,27 @@ Page({
success: (res) => {
const tempFilePaths = res.tempFilePaths;
if (tempFilePaths && tempFilePaths.length > 0) {
- // 更新页面数据
- _this.setData({
- [field === 'idCardFront' ? 'idCardFront' : 'idCardBack']: tempFilePaths[0],
- [field === 'idCardFront' ? 'idcard1' : 'idcard2']: {
- path: tempFilePaths[0],
- name: `身份证${field === 'idCardFront' ? '正面' : '反面'}_${new Date().getTime()}.jpg`
- }
- });
-
- // 模拟识别成功后填充信息
- _this.simulateOcrResult();
+ // 根据字段类型更新页面数据
+ if (field === 'businessLicense') {
+ _this.setData({
+ businessLicense: tempFilePaths[0],
+ businessLicenseFile: {
+ path: tempFilePaths[0],
+ name: `营业执照_${new Date().getTime()}.jpg`
+ }
+ });
+ } else {
+ _this.setData({
+ [field === 'idCardFront' ? 'idCardFront' : 'idCardBack']: tempFilePaths[0],
+ [field === 'idCardFront' ? 'idcard1' : 'idcard2']: {
+ path: tempFilePaths[0],
+ name: `身份证${field === 'idCardFront' ? '正面' : '反面'}_${new Date().getTime()}.jpg`
+ }
+ });
+
+ // 模拟识别成功后填充信息
+ _this.simulateOcrResult();
+ }
}
},
fail: (err) => {
diff --git a/pages/profile/authentication/index.wxml b/pages/profile/authentication/index.wxml
index dffee09..f73dc6c 100644
--- a/pages/profile/authentication/index.wxml
+++ b/pages/profile/authentication/index.wxml
@@ -1,13 +1,4 @@
-
-
-
@@ -43,35 +34,24 @@
-
-
-
-
- 姓名
- {{name || '上传图片后自动获取'}}
-
-
- 身份证号
- {{idNumber || '上传图片后自动获取'}}
-
-
- 居住地址
- {{address || '上传图片后自动获取'}}
-
-
- 有效期开始时间
- {{validStart || '上传图片后自动获取'}}
-
-
- 有效期结束时间
- {{validEnd || '上传图片后自动获取'}}
+
+
+
+ 营业执照
+ 上传您的营业执照
+
+
+
+
+
+ +
+
+ 点击上传营业执照
+
+
-
-
-
- 为了给您提供更好的服务,请选择您当前服务所在区域
diff --git a/pages/profile/index.wxml b/pages/profile/index.wxml
index acd2f76..635b06e 100644
--- a/pages/profile/index.wxml
+++ b/pages/profile/index.wxml
@@ -55,7 +55,7 @@
-
+
个人认证
>
diff --git a/pages/profile/index.wxss b/pages/profile/index.wxss
index 8aba164..b0eee65 100644
--- a/pages/profile/index.wxss
+++ b/pages/profile/index.wxss
@@ -1 +1,151 @@
-/* pages/profile/index.wxss */
\ No newline at end of file
+/* pages/profile/index.wxss */
+
+/* 全局样式重置 */
+page {
+ background-color: #f5f5f5;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+}
+
+/* 容器样式 */
+.container {
+ padding: 20rpx;
+ width: 100%;
+ max-width: 100vw;
+ overflow-x: hidden;
+ box-sizing: border-box;
+ background-color: #f5f5f5;
+}
+
+/* 卡片样式 */
+.card {
+ background-color: white;
+ border-radius: 20rpx;
+ padding: 30rpx;
+ margin-bottom: 20rpx;
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
+ transition: all 0.3s ease;
+}
+
+.card:hover {
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.12);
+ transform: translateY(-2rpx);
+}
+
+/* 标题样式 */
+.title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ margin-bottom: 20rpx;
+ position: relative;
+ padding-bottom: 10rpx;
+}
+
+.title::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 80rpx;
+ height: 4rpx;
+ background: linear-gradient(90deg, #1677ff, #1890ff);
+ border-radius: 2rpx;
+}
+
+/* 按钮样式 */
+.btn {
+ width: 100%;
+ padding: 20rpx;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ font-weight: bold;
+ transition: all 0.3s ease;
+ margin-bottom: 20rpx;
+ border: none;
+ outline: none;
+}
+
+.btn:hover {
+ opacity: 0.9;
+ transform: scale(1.02);
+}
+
+.btn:active {
+ transform: scale(0.98);
+}
+
+/* 标签样式 */
+.tag {
+ display: flex;
+ align-items: center;
+ padding: 12rpx 24rpx;
+ border-radius: 24rpx;
+ margin: 10rpx;
+ font-size: 26rpx;
+ font-weight: bold;
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.tag:hover {
+ transform: translateY(-2rpx);
+ box-shadow: 0 6rpx 16rpx rgba(0, 0, 0, 0.15);
+}
+
+.tag:active {
+ transform: scale(0.98);
+}
+
+/* 链接项样式 */
+.link-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 30rpx 0;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.link-item:hover {
+ background-color: rgba(22, 119, 255, 0.05);
+ border-radius: 10rpx;
+}
+
+/* 退出登录按钮样式 */
+.logout-btn {
+ background-color: #ff4d4f;
+ color: white;
+ padding: 12rpx 4rpx;
+ border-radius: 20rpx;
+ font-size: 20rpx;
+ width: 176rpx;
+ display: block;
+ box-sizing: border-box;
+ transition: all 0.3s ease;
+ border: none;
+ outline: none;
+}
+
+.logout-btn:hover {
+ background-color: #ff7875;
+ transform: scale(1.05);
+}
+
+.logout-btn:active {
+ transform: scale(0.95);
+}
+
+/* 授权登录按钮样式 */
+.auth-btn {
+ margin: 20rpx 0;
+ transition: all 0.3s ease;
+}
+
+.auth-btn:hover {
+ transform: scale(1.02);
+}
+
+.auth-btn:active {
+ transform: scale(0.98);
+}
\ No newline at end of file
--
2.30.2
From dee4b3491a3b307cd0221dea4b6c55fc5ebf9372 Mon Sep 17 00:00:00 2001
From: Default User
Date: Wed, 28 Jan 2026 16:27:20 +0800
Subject: [PATCH 15/22] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=90=A5=E4=B8=9A?=
=?UTF-8?q?=E6=89=A7=E7=85=A7=E4=B8=8A=E4=BC=A0=E5=8A=9F=E8=83=BD=EF=BC=9A?=
=?UTF-8?q?=E5=9C=A8authentication/index=E9=A1=B5=E9=9D=A2=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E8=90=A5=E4=B8=9A=E6=89=A7=E7=85=A7=E4=B8=8A=E4=BC=A0?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=B9=B6=E5=AD=98=E5=82=A8=E5=88=B0?=
=?UTF-8?q?users=E8=A1=A8=E7=9A=84businesslicenseurl=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/authentication/index.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/pages/profile/authentication/index.js b/pages/profile/authentication/index.js
index 18ee7f1..0e13117 100644
--- a/pages/profile/authentication/index.js
+++ b/pages/profile/authentication/index.js
@@ -135,10 +135,10 @@ Page({
* 提交认证
*/
async submitAuth() {
- // 验证是否上传了身份证
- if (!this.data.idCardFront || !this.data.idCardBack) {
+ // 验证是否上传了身份证和营业执照
+ if (!this.data.idCardFront || !this.data.idCardBack || !this.data.businessLicense) {
wx.showToast({
- title: '请上传身份证正反面',
+ title: '请上传身份证正反面和营业执照',
icon: 'none'
});
return;
@@ -163,6 +163,8 @@ Page({
const idcard1Url = await this.uploadFileToServer(this.data.idcard1.path, 'idCardFront');
// 上传身份证反面
const idcard2Url = await this.uploadFileToServer(this.data.idcard2.path, 'idCardBack');
+ // 上传营业执照
+ const businessLicenseUrl = await this.uploadFileToServer(this.data.businessLicenseFile.path, 'businessLicense');
console.log('所有文件上传完成');
@@ -172,6 +174,7 @@ Page({
userId: userId,
idcard1: idcard1Url,
idcard2: idcard2Url,
+ businesslicenseurl: businessLicenseUrl,
name: this.data.name,
idNumber: this.data.idNumber,
address: this.data.address
--
2.30.2
From 8a6745d9f30f435c6c32235a1a563225e44a000d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 16:38:05 +0800
Subject: [PATCH 16/22] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?=
=?UTF-8?q?=E6=AF=94=E4=BB=B7=E6=A0=BC=E6=8C=89=E9=92=AE=E7=99=BB=E5=BD=95?=
=?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=92=8C=E8=BA=AB=E4=BB=BD=E8=AF=81=E8=AE=A4?=
=?UTF-8?q?=E8=AF=81=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 对比价格按钮添加登录状态检查,未登录显示登录弹窗
- 添加身份证信息(idcard1/idcard2)完整性验证
- 身份证信息不完整时提示并跳转到认证页面
- 认证页面支持从服务器加载已存在的认证信息
- 认证图片支持点击更换,保留原图片URL
- 提交时智能判断是否需要重新上传图片
---
pages/goods-detail/goods-detail.js | 36 +++++++++
pages/profile/authentication/index.js | 108 ++++++++++++++++++++++++--
2 files changed, 136 insertions(+), 8 deletions(-)
diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js
index 79662ed..1e8aedd 100644
--- a/pages/goods-detail/goods-detail.js
+++ b/pages/goods-detail/goods-detail.js
@@ -2939,6 +2939,42 @@ Page({
onCompareClick: function () {
console.log('用户点击了对比价格按钮,准备显示弹窗');
+ // 检查用户登录状态
+ const openid = wx.getStorageSync('openid');
+ const userId = wx.getStorageSync('userId');
+
+ if (!openid || !userId) {
+ console.log('用户未登录,显示登录弹窗');
+ this.setData({
+ showOneKeyLoginModal: true
+ });
+ return;
+ }
+
+ // 检查身份证信息
+ const userInfo = wx.getStorageSync('userInfo') || {};
+ const idcard1 = userInfo.idcard1;
+ const idcard2 = userInfo.idcard2;
+
+ console.log('检查身份证信息:', { idcard1, idcard2 });
+
+ if (!idcard1 || !idcard2) {
+ console.log('身份证信息不完整,跳转到认证页面');
+ wx.showToast({
+ title: '信息不完整,请先完成身份认证',
+ icon: 'none',
+ duration: 2000
+ });
+
+ // 跳转到认证页面
+ setTimeout(() => {
+ wx.navigateTo({
+ url: '/pages/profile/authentication/index'
+ });
+ }, 1000);
+ return;
+ }
+
// 直接获取当前页面滚动位置
wx.createSelectorQuery().selectViewport().scrollOffset(function(res) {
console.log('记录当前滚动位置:', res.scrollTop);
diff --git a/pages/profile/authentication/index.js b/pages/profile/authentication/index.js
index 0e13117..878cadd 100644
--- a/pages/profile/authentication/index.js
+++ b/pages/profile/authentication/index.js
@@ -156,17 +156,32 @@ Page({
return;
}
- wx.showLoading({ title: '正在上传文件...', mask: true });
+ wx.showLoading({ title: '正在提交认证信息...', mask: true });
try {
- // 上传身份证正面
- const idcard1Url = await this.uploadFileToServer(this.data.idcard1.path, 'idCardFront');
- // 上传身份证反面
- const idcard2Url = await this.uploadFileToServer(this.data.idcard2.path, 'idCardBack');
- // 上传营业执照
- const businessLicenseUrl = await this.uploadFileToServer(this.data.businessLicenseFile.path, 'businessLicense');
+ let idcard1Url = this.data.idcard1?.path || this.data.idCardFront;
+ let idcard2Url = this.data.idcard2?.path || this.data.idCardBack;
+ let businessLicenseUrl = this.data.businessLicenseFile?.path || this.data.businessLicense;
- console.log('所有文件上传完成');
+ // 检查是否是本地路径(需要上传)还是远程URL(直接使用)
+ const isLocalPath = (path) => path && (path.startsWith('http://') || path.startsWith('https://') || path.startsWith('wxfile://') || path.startsWith('cloud://'));
+
+ // 上传身份证正面(仅当是本地路径时)
+ if (this.data.idcard1?.path && !isLocalPath(this.data.idcard1.path)) {
+ idcard1Url = await this.uploadFileToServer(this.data.idcard1.path, 'idCardFront');
+ }
+
+ // 上传身份证反面(仅当是本地路径时)
+ if (this.data.idcard2?.path && !isLocalPath(this.data.idcard2.path)) {
+ idcard2Url = await this.uploadFileToServer(this.data.idcard2.path, 'idCardBack');
+ }
+
+ // 上传营业执照(仅当是本地路径时)
+ if (this.data.businessLicenseFile?.path && !isLocalPath(this.data.businessLicenseFile.path)) {
+ businessLicenseUrl = await this.uploadFileToServer(this.data.businessLicenseFile.path, 'businessLicense');
+ }
+
+ console.log('文件处理完成,正面:', idcard1Url, '反面:', idcard2Url, '营业执照:', businessLicenseUrl);
// 准备提交数据
const submitData = {
@@ -188,6 +203,19 @@ Page({
console.log('认证提交结果:', result);
if (result && result.success) {
+ // 更新本地存储的用户信息
+ const userInfo = wx.getStorageSync('userInfo') || {};
+ const updatedUserInfo = {
+ ...userInfo,
+ idcard1: idcard1Url,
+ idcard2: idcard2Url,
+ businesslicenseurl: businessLicenseUrl,
+ name: this.data.name,
+ idNumber: this.data.idNumber,
+ address: this.data.address
+ };
+ wx.setStorageSync('userInfo', updatedUserInfo);
+
wx.hideLoading();
wx.showToast({
title: '认证成功',
@@ -234,7 +262,71 @@ Page({
* 生命周期函数--监听页面显示
*/
onShow() {
+ // 页面显示时加载已存在的认证信息
+ this.loadExistingAuthData();
+ },
+ /**
+ * 从服务器加载已存在的认证信息
+ */
+ loadExistingAuthData() {
+ const openid = wx.getStorageSync('openid');
+ const userId = wx.getStorageSync('userId');
+
+ if (!openid || !userId) {
+ console.log('用户未登录,无法加载认证信息');
+ return;
+ }
+
+ console.log('开始加载用户认证信息,openid:', openid, 'userId:', userId);
+
+ // 调用API获取用户信息,包括认证数据
+ API.getUserInfo(openid).then(res => {
+ console.log('获取用户认证信息响应:', res);
+
+ if (res && res.success && res.data) {
+ const userData = res.data;
+ console.log('用户认证数据:', userData);
+
+ // 构建更新数据对象
+ const updateData = {
+ name: userData.name || '',
+ idNumber: userData.idNumber || userData.id_number || '',
+ address: userData.address || '',
+ validStart: userData.validStart || userData.valid_start || '',
+ validEnd: userData.validEnd || userData.valid_end || ''
+ };
+
+ // 处理身份证正面图片
+ if (userData.idcard1) {
+ updateData.idcard1 = { path: userData.idcard1 };
+ updateData.idCardFront = userData.idcard1;
+ console.log('已加载身份证正面:', userData.idcard1);
+ }
+
+ // 处理身份证反面图片
+ if (userData.idcard2) {
+ updateData.idcard2 = { path: userData.idcard2 };
+ updateData.idCardBack = userData.idcard2;
+ console.log('已加载身份证反面:', userData.idcard2);
+ }
+
+ // 处理营业执照图片
+ if (userData.businesslicenseurl) {
+ updateData.businessLicenseFile = { path: userData.businesslicenseurl };
+ updateData.businessLicense = userData.businesslicenseurl;
+ console.log('已加载营业执照:', userData.businesslicenseurl);
+ }
+
+ // 更新页面数据
+ this.setData(updateData);
+ console.log('认证信息加载完成,当前数据:', this.data);
+ } else {
+ console.log('未获取到用户认证信息或获取失败');
+ }
+ }).catch(err => {
+ console.error('加载用户认证信息失败:', err);
+ });
},
/**
--
2.30.2
From ebe0467c482755b4c2b6749462e5002fe27a44ae Mon Sep 17 00:00:00 2001
From: Default User
Date: Wed, 28 Jan 2026 16:38:42 +0800
Subject: [PATCH 17/22] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=B4=E5=83=8FURL?=
=?UTF-8?q?=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98=EF=BC=9A=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?processAvatarUrl=E6=96=B9=E6=B3=95=EF=BC=8C=E7=A1=AE=E4=BF=9D?=
=?UTF-8?q?=E6=AD=A3=E7=A1=AE=E8=A7=A3=E6=9E=90=E5=AD=98=E5=82=A8=E4=B8=BA?=
=?UTF-8?q?=E6=95=B0=E7=BB=84=E5=BD=A2=E5=BC=8F=E7=9A=84OSS=20URL=E5=A4=B4?=
=?UTF-8?q?=E5=83=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/index.js | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/pages/profile/index.js b/pages/profile/index.js
index 5f76728..43fe239 100644
--- a/pages/profile/index.js
+++ b/pages/profile/index.js
@@ -55,6 +55,37 @@ Page({
return phoneStr.substring(0, 3) + '****' + phoneStr.substring(7)
},
+ // 处理头像URL,确保正确解析数组形式的OSS URL
+ processAvatarUrl(avatarUrl) {
+ if (!avatarUrl) {
+ return 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0';
+ }
+
+ // 如果是字符串,尝试解析为JSON数组
+ if (typeof avatarUrl === 'string') {
+ try {
+ const parsedUrl = JSON.parse(avatarUrl);
+ // 如果解析成功且是数组且不为空,使用第一个元素
+ if (Array.isArray(parsedUrl) && parsedUrl.length > 0) {
+ return parsedUrl[0];
+ }
+ // 如果解析成功但不是数组,直接返回
+ return avatarUrl;
+ } catch (e) {
+ // 解析失败,直接返回
+ return avatarUrl;
+ }
+ }
+
+ // 如果是数组且不为空,使用第一个元素
+ if (Array.isArray(avatarUrl) && avatarUrl.length > 0) {
+ return avatarUrl[0];
+ }
+
+ // 其他情况返回默认头像
+ return 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0';
+ },
+
// 加载用户信息
loadUserInfo() {
console.log('开始加载用户信息')
@@ -64,10 +95,14 @@ Page({
const localUserInfo = wx.getStorageSync('userInfo') || {}
if (app.globalData.userInfo) {
const userInfo = { ...app.globalData.userInfo }
+ // 处理头像URL
+ userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
this.setData({ userInfo })
} else {
const userInfo = { ...localUserInfo }
+ // 处理头像URL
+ userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
app.globalData.userInfo = userInfo
this.setData({
@@ -199,6 +234,9 @@ Page({
...serverUserInfo
}
+ // 处理头像URL
+ updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
+
// 添加隐藏的电话号码
updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber)
@@ -232,6 +270,9 @@ Page({
...serverUserInfo
}
+ // 处理头像URL
+ updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
+
// 添加隐藏的电话号码
updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber)
--
2.30.2
From 8bcbe163e8a1abb4996d27cdd62f9cba40a6290d Mon Sep 17 00:00:00 2001
From: Default User
Date: Wed, 28 Jan 2026 16:45:51 +0800
Subject: [PATCH 18/22] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=A4=B4=E5=83=8F?=
=?UTF-8?q?=E6=9B=B4=E6=8D=A2=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?onAvatarClick=E6=96=B9=E6=B3=95=EF=BC=8C=E7=82=B9=E5=87=BB?=
=?UTF-8?q?=E5=A4=B4=E5=83=8F=E6=97=B6=E5=BC=B9=E5=87=BA=E6=9B=B4=E6=8D=A2?=
=?UTF-8?q?=E9=80=89=E6=8B=A9=EF=BC=8C=E4=B8=8A=E4=BC=A0=E5=90=8E=E6=9B=B4?=
=?UTF-8?q?=E6=96=B0avatarUrl=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/index.js | 70 ++++++++++++++++++++++++++++++++++++++++
pages/profile/index.wxml | 3 +-
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/pages/profile/index.js b/pages/profile/index.js
index 43fe239..3de6a01 100644
--- a/pages/profile/index.js
+++ b/pages/profile/index.js
@@ -1114,4 +1114,74 @@ Page({
});
},
+ // 点击头像更换图片
+ onAvatarClick() {
+ wx.chooseImage({
+ count: 1,
+ sizeType: ['compressed'],
+ sourceType: ['album', 'camera'],
+ success: (res) => {
+ const tempFilePaths = res.tempFilePaths;
+ if (tempFilePaths && tempFilePaths.length > 0) {
+ this.uploadAvatar(tempFilePaths[0]);
+ }
+ },
+ fail: (err) => {
+ console.error('选择图片失败:', err);
+ }
+ });
+ },
+
+ // 上传头像并更新
+ async uploadAvatar(filePath) {
+ wx.showLoading({ title: '上传中...', mask: true });
+
+ try {
+ // 上传图片到服务器
+ const API = require('../../utils/api.js');
+ const result = await API.uploadSettlementFile(filePath, 'avatar');
+
+ if (result && result.fileUrl) {
+ const avatarUrl = result.fileUrl;
+
+ // 更新本地和全局用户信息
+ const app = getApp();
+ const updatedUserInfo = {
+ ...this.data.userInfo,
+ avatarUrl: avatarUrl
+ };
+
+ // 保存到本地存储和全局状态
+ app.globalData.userInfo = updatedUserInfo;
+ wx.setStorageSync('userInfo', updatedUserInfo);
+
+ // 更新页面显示
+ this.setData({ userInfo: updatedUserInfo });
+
+ // 上传到服务器更新数据库
+ const userId = wx.getStorageSync('userId');
+ if (userId) {
+ await this.uploadUserInfoToServer(updatedUserInfo, userId, this.data.userType);
+ }
+
+ wx.showToast({
+ title: '头像更新成功',
+ icon: 'success',
+ duration: 2000
+ });
+ } else {
+ throw new Error('上传失败');
+ }
+ } catch (error) {
+ console.error('上传头像失败:', error);
+ wx.showToast({
+ title: '上传失败,请重试',
+ icon: 'none',
+ duration: 2000
+ });
+ } finally {
+ wx.hideLoading();
+ }
+ },
+
})
diff --git a/pages/profile/index.wxml b/pages/profile/index.wxml
index 635b06e..b3762cc 100644
--- a/pages/profile/index.wxml
+++ b/pages/profile/index.wxml
@@ -3,7 +3,8 @@
{{userInfo.hiddenPhoneNumber || userInfo.phoneNumber || '未登录'}}
--
2.30.2
From 87bbe8b13c75f605da8ba64e9f4a2b0921385f12 Mon Sep 17 00:00:00 2001
From: Default User
Date: Wed, 28 Jan 2026 17:12:14 +0800
Subject: [PATCH 19/22] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=A4=B4=E5=83=8F?=
=?UTF-8?q?=E5=88=87=E6=8D=A2=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BF=AE=E5=A4=8D?=
=?UTF-8?q?=E5=A4=9A=E5=BC=A0=E5=A4=B4=E5=83=8F=E8=A7=A3=E6=9E=90=E9=97=AE?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/index.js | 164 ++++++++++++++++++++++++-----------------
1 file changed, 95 insertions(+), 69 deletions(-)
diff --git a/pages/profile/index.js b/pages/profile/index.js
index 3de6a01..811dfa9 100644
--- a/pages/profile/index.js
+++ b/pages/profile/index.js
@@ -25,7 +25,9 @@ Page({
needPhoneAuth: false, // 是否需要重新授权手机号
locationInfo: '', // 位置信息
hasLocationAuth: false, // 是否已经授权位置
- isInPersonnel: false // 用户手机号是否在personnel表中
+ isInPersonnel: false, // 用户手机号是否在personnel表中
+ currentAvatarIndex: 0, // 当前显示的头像索引,默认显示第一张
+ rawAvatarUrl: null // 存储原始的头像URL数据(可能是数组)
},
onLoad() {
@@ -95,19 +97,27 @@ Page({
const localUserInfo = wx.getStorageSync('userInfo') || {}
if (app.globalData.userInfo) {
const userInfo = { ...app.globalData.userInfo }
- // 处理头像URL
+ // 保存原始的头像URL数据
+ const rawAvatarUrl = userInfo.avatarUrl;
+ // 处理头像URL用于显示
userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
- this.setData({ userInfo })
+ this.setData({
+ userInfo,
+ rawAvatarUrl
+ })
} else {
const userInfo = { ...localUserInfo }
- // 处理头像URL
+ // 保存原始的头像URL数据
+ const rawAvatarUrl = userInfo.avatarUrl;
+ // 处理头像URL用于显示
userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
app.globalData.userInfo = userInfo
this.setData({
userInfo,
- needPhoneAuth: !userInfo.phoneNumber
+ needPhoneAuth: !userInfo.phoneNumber,
+ rawAvatarUrl
})
}
@@ -234,7 +244,9 @@ Page({
...serverUserInfo
}
- // 处理头像URL
+ // 保存原始的头像URL数据
+ const rawAvatarUrl = updatedUserInfo.avatarUrl;
+ // 处理头像URL用于显示
updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
// 添加隐藏的电话号码
@@ -242,7 +254,10 @@ Page({
app.globalData.userInfo = updatedUserInfo
wx.setStorageSync('userInfo', updatedUserInfo)
- this.setData({ userInfo: updatedUserInfo })
+ this.setData({
+ userInfo: updatedUserInfo,
+ rawAvatarUrl
+ })
// 同步更新用户身份信息(当前身份由数据库决定)
if (serverUserInfo.type) {
@@ -270,7 +285,9 @@ Page({
...serverUserInfo
}
- // 处理头像URL
+ // 保存原始的头像URL数据
+ const rawAvatarUrl = updatedUserInfo.avatarUrl;
+ // 处理头像URL用于显示
updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
// 添加隐藏的电话号码
@@ -278,7 +295,10 @@ Page({
app.globalData.userInfo = updatedUserInfo
wx.setStorageSync('userInfo', updatedUserInfo)
- this.setData({ userInfo: updatedUserInfo })
+ this.setData({
+ userInfo: updatedUserInfo,
+ rawAvatarUrl
+ })
// 同步更新用户身份信息(当前身份由数据库决定)
if (serverUserInfo.type) {
@@ -1114,74 +1134,80 @@ Page({
});
},
- // 点击头像更换图片
+ // 点击头像切换图片
onAvatarClick() {
- wx.chooseImage({
- count: 1,
- sizeType: ['compressed'],
- sourceType: ['album', 'camera'],
- success: (res) => {
- const tempFilePaths = res.tempFilePaths;
- if (tempFilePaths && tempFilePaths.length > 0) {
- this.uploadAvatar(tempFilePaths[0]);
- }
- },
- fail: (err) => {
- console.error('选择图片失败:', err);
- }
- });
- },
-
- // 上传头像并更新
- async uploadAvatar(filePath) {
- wx.showLoading({ title: '上传中...', mask: true });
-
- try {
- // 上传图片到服务器
- const API = require('../../utils/api.js');
- const result = await API.uploadSettlementFile(filePath, 'avatar');
-
- if (result && result.fileUrl) {
- const avatarUrl = result.fileUrl;
-
- // 更新本地和全局用户信息
- const app = getApp();
- const updatedUserInfo = {
- ...this.data.userInfo,
- avatarUrl: avatarUrl
- };
-
- // 保存到本地存储和全局状态
- app.globalData.userInfo = updatedUserInfo;
- wx.setStorageSync('userInfo', updatedUserInfo);
-
- // 更新页面显示
- this.setData({ userInfo: updatedUserInfo });
-
- // 上传到服务器更新数据库
- const userId = wx.getStorageSync('userId');
- if (userId) {
- await this.uploadUserInfoToServer(updatedUserInfo, userId, this.data.userType);
+ // 使用rawAvatarUrl获取完整的头像URL数组
+ let avatarUrls = [];
+ const rawAvatarUrl = this.data.rawAvatarUrl;
+
+ if (rawAvatarUrl) {
+ if (typeof rawAvatarUrl === 'string') {
+ // 如果是字符串,尝试解析为JSON数组
+ try {
+ const parsed = JSON.parse(rawAvatarUrl);
+ if (Array.isArray(parsed)) {
+ avatarUrls = parsed;
+ } else {
+ // 如果不是数组,将当前URL作为第一个元素
+ avatarUrls = [rawAvatarUrl];
+ }
+ } catch (e) {
+ // 解析失败,将当前URL作为第一个元素
+ avatarUrls = [rawAvatarUrl];
}
-
- wx.showToast({
- title: '头像更新成功',
- icon: 'success',
- duration: 2000
- });
- } else {
- throw new Error('上传失败');
+ } else if (Array.isArray(rawAvatarUrl)) {
+ // 如果已经是数组,直接使用
+ avatarUrls = rawAvatarUrl;
}
- } catch (error) {
- console.error('上传头像失败:', error);
+ }
+
+ // 检查是否有至少两张图片可以切换
+ if (avatarUrls.length < 2) {
wx.showToast({
- title: '上传失败,请重试',
+ title: '没有足够的头像可以切换',
icon: 'none',
duration: 2000
});
- } finally {
- wx.hideLoading();
+ return;
+ }
+
+ // 切换到下一张头像
+ let nextIndex = this.data.currentAvatarIndex + 1;
+ if (nextIndex >= avatarUrls.length) {
+ nextIndex = 0; // 如果已经是最后一张,回到第一张
}
+
+ // 显示切换头像的提示
+ wx.showModal({
+ title: '切换头像',
+ content: `确定要切换到第${nextIndex + 1}张头像吗?`,
+ success: (res) => {
+ if (res.confirm) {
+ // 切换到下一张图片
+ const app = getApp();
+ const updatedUserInfo = {
+ ...this.data.userInfo,
+ avatarUrl: avatarUrls[nextIndex] // 直接使用下一张图片
+ };
+
+ // 保存到本地存储和全局状态
+ app.globalData.userInfo = updatedUserInfo;
+ wx.setStorageSync('userInfo', updatedUserInfo);
+
+ // 更新页面显示
+ this.setData({
+ userInfo: updatedUserInfo,
+ currentAvatarIndex: nextIndex
+ });
+
+ wx.showToast({
+ title: '头像切换成功',
+ icon: 'success',
+ duration: 2000
+ });
+ }
+ }
+ });
},
})
--
2.30.2
From b6733d27d2fee46eb6bec22336c0d00e4dd880ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Wed, 28 Jan 2026 17:24:01 +0800
Subject: [PATCH 20/22] Add login verification and partnerstatus check for
evaluate2/one page
---
pages/evaluate2/one.js | 347 ++++++++++++++++++++++++++++++++++++++-
pages/evaluate2/one.wxml | 23 +++
pages/evaluate2/one.wxss | 92 +++++++++++
3 files changed, 461 insertions(+), 1 deletion(-)
diff --git a/pages/evaluate2/one.js b/pages/evaluate2/one.js
index 47fceb9..16cdbb4 100644
--- a/pages/evaluate2/one.js
+++ b/pages/evaluate2/one.js
@@ -5,7 +5,8 @@ Page({
loading: false,
error: '',
categories: [],
- selectedCategory: ''
+ selectedCategory: '',
+ showOneKeyLoginModal: false // 是否显示登录弹窗
},
onLoad(options) {
let productName = '';
@@ -455,9 +456,353 @@ Page({
const category = e.currentTarget.dataset.category;
console.log('选择分类:', category);
+ // 检查用户登录状态
+ const openid = wx.getStorageSync('openid');
+ const userId = wx.getStorageSync('userId');
+
+ if (!openid || !userId) {
+ // 用户未登录,显示登录弹窗
+ console.log('用户未登录,显示登录弹窗');
+ this.setData({
+ showOneKeyLoginModal: true
+ });
+ return;
+ }
+
+ // 检查用户合作状态
+ const userInfo = wx.getStorageSync('userInfo') || {};
+ const partnerStatus = userInfo.partnerstatus || '';
+
+ if (partnerStatus !== 'approved') {
+ // 合作状态未批准,显示提示
+ wx.showModal({
+ title: '提示',
+ content: '需要入住成功才能查看',
+ confirmText: '立即入驻',
+ success: function(res) {
+ if (res.confirm) {
+ wx.navigateTo({
+ url: '/pages/profile/authentication/index'
+ });
+ }
+ }
+ });
+ return;
+ }
+
// 跳转到商品列表页面,并传递分类参数
wx.redirectTo({
url: `/pages/evaluate2/product-list?category=${encodeURIComponent(category)}`
});
+ },
+
+ // 关闭登录弹窗
+ closeOneKeyLoginModal() {
+ this.setData({
+ showOneKeyLoginModal: false
+ });
+ },
+
+ // 处理登录授权
+ async onGetPhoneNumber(e) {
+ console.log('收到手机号授权事件:', e.detail);
+
+ // 关闭手机号授权弹窗
+ this.setData({ showOneKeyLoginModal: false });
+
+ // 用户点击拒绝授权
+ if (e.detail.errMsg === 'getPhoneNumber:fail user deny') {
+ wx.showToast({
+ title: '需要授权手机号才能使用',
+ icon: 'none',
+ duration: 2000
+ });
+ return;
+ }
+
+ // 处理没有权限的情况
+ if (e.detail.errMsg === 'getPhoneNumber:fail no permission') {
+ wx.showToast({
+ title: '当前环境无法获取手机号权限',
+ icon: 'none',
+ duration: 3000
+ });
+ return;
+ }
+
+ // 检查是否已经登录,避免重复授权
+ const existingOpenid = wx.getStorageSync('openid');
+ const existingUserId = wx.getStorageSync('userId');
+ const existingUserInfo = wx.getStorageSync('userInfo');
+
+ if (existingOpenid && existingUserId && existingUserInfo && existingUserInfo.phoneNumber) {
+ console.log('用户已登录且手机号有效,登录流程已完成');
+ wx.showToast({
+ title: '您已登录',
+ icon: 'success',
+ duration: 1500
+ });
+ return;
+ }
+
+ wx.showLoading({ title: '登录中...', mask: true });
+
+ try {
+ if (e.detail.errMsg === 'getPhoneNumber:ok') {
+ // 用户同意授权,实际处理授权流程
+ console.log('用户同意授权获取手机号');
+
+ // 1. 先执行微信登录获取code
+ const loginRes = await new Promise((resolve, reject) => {
+ wx.login({
+ success: resolve,
+ fail: reject
+ });
+ });
+
+ if (!loginRes.code) {
+ throw new Error('获取登录code失败');
+ }
+
+ console.log('获取登录code成功:', loginRes.code);
+
+ // 2. 使用code换取openid
+ const API = require('../../utils/api');
+ const openidRes = await API.getOpenid(loginRes.code);
+
+ // 改进错误处理逻辑,更宽容地处理服务器返回格式
+ let openid = null;
+ let userId = null;
+ console.log('openidRes完整响应:', JSON.stringify(openidRes));
+
+ if (openidRes && typeof openidRes === 'object') {
+ // 适配服务器返回格式:{success: true, code: 200, message: '获取openid成功', data: {openid, userId}}
+ if (openidRes.data && typeof openidRes.data === 'object') {
+ console.log('识别到标准服务器返回格式,从data字段提取信息');
+ openid = openidRes.data.openid || openidRes.data.OpenID || null;
+ userId = openidRes.data.userId || null;
+ } else {
+ // 尝试从响应对象中直接提取openid
+ console.log('尝试从根对象直接提取openid');
+ openid = openidRes.openid || openidRes.OpenID || null;
+ userId = openidRes.userId || null;
+ }
+ }
+
+ if (!openid) {
+ console.error('无法从服务器响应中提取openid,完整响应:', JSON.stringify(openidRes));
+ throw new Error(`获取openid失败: 服务器返回数据格式可能不符合预期`);
+ }
+
+ console.log('获取openid成功:', openid);
+
+ // 3. 存储openid和session_key
+ wx.setStorageSync('openid', openid);
+
+ // 从服务器返回中获取session_key
+ if (openidRes && openidRes.session_key) {
+ wx.setStorageSync('sessionKey', openidRes.session_key);
+ } else if (openidRes && openidRes.data && openidRes.data.session_key) {
+ wx.setStorageSync('sessionKey', openidRes.data.session_key);
+ }
+
+ // 优先使用从服务器响应data字段中提取的userId
+ if (userId) {
+ wx.setStorageSync('userId', userId);
+ console.log('使用从服务器data字段提取的userId:', userId);
+ } else if (openidRes && openidRes.userId) {
+ wx.setStorageSync('userId', openidRes.userId);
+ console.log('使用服务器根对象中的userId:', openidRes.userId);
+ } else {
+ // 生成临时userId
+ const tempUserId = 'user_' + Date.now();
+ wx.setStorageSync('userId', tempUserId);
+ console.log('生成临时userId:', tempUserId);
+ }
+
+ // 4. 上传手机号加密数据到服务器解密
+ const phoneData = {
+ ...e.detail,
+ openid: openid
+ };
+
+ console.log('准备上传手机号加密数据到服务器');
+ const phoneRes = await API.uploadPhoneNumberData(phoneData);
+
+ // 改进手机号解密结果的处理逻辑
+ if (!phoneRes || (!phoneRes.success && !phoneRes.phoneNumber)) {
+ // 如果服务器返回格式不标准但包含手机号,也接受
+ if (phoneRes && phoneRes.phoneNumber) {
+ console.warn('服务器返回格式可能不符合预期,但成功获取手机号');
+ } else {
+ throw new Error('获取手机号失败: ' + (phoneRes && phoneRes.message ? phoneRes.message : '未知错误'));
+ }
+ }
+
+ // 检查是否有手机号冲突
+ const hasPhoneConflict = phoneRes.phoneNumberConflict || false;
+ const isNewPhone = phoneRes.isNewPhone || true;
+ const phoneNumber = phoneRes.phoneNumber || null;
+
+ // 如果有手机号冲突且没有返回手机号,使用实际返回的手机号
+ const finalPhoneNumber = phoneNumber;
+
+ console.log('手机号解密结果:', {
+ phoneNumber: finalPhoneNumber,
+ hasPhoneConflict: hasPhoneConflict,
+ isNewPhone: isNewPhone
+ });
+
+ // 5. 获取用户微信名称和头像
+ let userProfile = null;
+ try {
+ userProfile = await new Promise((resolve, reject) => {
+ wx.getUserProfile({
+ desc: '用于完善会员资料',
+ success: resolve,
+ fail: reject
+ });
+ });
+ console.log('获取用户信息成功:', userProfile);
+ } catch (err) {
+ console.warn('获取用户信息失败:', err);
+ // 如果获取失败,使用默认值
+ }
+
+ // 6. 创建用户信息
+ const tempUserInfo = {
+ name: userProfile ? (userProfile.userInfo.name || userProfile.userInfo.nickName) : '微信用户',
+ // 获取微信头像失败时使用微信默认头像
+ avatarUrl: userProfile ? userProfile.userInfo.avatarUrl : 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0',
+ gender: userProfile ? userProfile.userInfo.gender : 0,
+ country: userProfile ? userProfile.userInfo.country : '',
+ province: userProfile ? userProfile.userInfo.province : '',
+ city: userProfile ? userProfile.userInfo.city : '',
+ language: userProfile ? userProfile.userInfo.language : 'zh_CN',
+ phoneNumber: finalPhoneNumber
+ };
+
+ // 7. 保存用户信息
+ const storedUserId = wx.getStorageSync('userId');
+ const users = wx.getStorageSync('users') || {};
+ const currentUserType = users[storedUserId] && users[storedUserId].type ? users[storedUserId].type : 'buyer';
+
+ console.log('用户身份类型:', currentUserType);
+
+ // 8. 保存用户信息到本地和服务器
+ console.log('开始保存用户信息...');
+ await this.saveUserInfo(tempUserInfo, currentUserType);
+ console.log('用户信息保存完成');
+
+ wx.hideLoading();
+
+ // 根据服务器返回的结果显示不同的提示
+ if (phoneRes && phoneRes.phoneNumberConflict) {
+ wx.showModal({
+ title: '登录成功',
+ content: '您的手机号已被其他账号绑定',
+ showCancel: false,
+ confirmText: '我知道了',
+ success(res) {
+ if (res.confirm) {
+ console.log('用户点击了我知道了');
+ }
+ }
+ });
+ }
+
+ // 1. 登录成功提示
+ wx.showToast({
+ title: '登录成功',
+ icon: 'success',
+ duration: 1500
+ });
+
+ // 2. 从服务器获取最新用户信息
+ const userInfoRes = await API.getUserInfo(openid);
+
+ // 3. 获取服务器返回的partnerstatus
+ const serverUserInfo = userInfoRes.data;
+ const partnerStatus = serverUserInfo.partnerstatus || 'pending';
+
+ // 4. 更新本地缓存
+ const localUserInfo = wx.getStorageSync('userInfo') || {};
+ const updatedUserInfo = {
+ ...localUserInfo,
+ partnerstatus: partnerStatus
+ };
+ wx.setStorageSync('userInfo', updatedUserInfo);
+
+ // 5. 检查partnerstatus值
+ if (partnerStatus !== 'approved') {
+ // 显示入驻提示
+ setTimeout(() => {
+ wx.showModal({
+ title: '提示',
+ content: '需要入住成功才能查看',
+ confirmText: '立即入驻',
+ success: function(res) {
+ if (res.confirm) {
+ wx.navigateTo({
+ url: '/pages/profile/authentication/index'
+ });
+ }
+ }
+ });
+ }, 2000);
+ }
+ }
+ } catch (error) {
+ wx.hideLoading();
+ console.error('登录失败:', error);
+ wx.showToast({
+ title: '登录失败,请重试',
+ icon: 'none',
+ duration: 2000
+ });
+ }
+ },
+
+ // 保存用户信息
+ async saveUserInfo(userInfo, userType = 'buyer') {
+ return new Promise(async (resolve, reject) => {
+ try {
+ const storedUserId = wx.getStorageSync('userId');
+ const users = wx.getStorageSync('users') || {};
+
+ // 更新用户信息
+ users[storedUserId] = {
+ ...users[storedUserId],
+ ...userInfo,
+ type: userType,
+ lastLogin: new Date().toISOString()
+ };
+
+ // 保存到本地存储
+ wx.setStorageSync('users', users);
+ wx.setStorageSync('userInfo', userInfo);
+
+ // 上传用户信息到服务器
+ const API = require('../../utils/api');
+ const submitData = {
+ openid: wx.getStorageSync('openid'),
+ userId: storedUserId,
+ ...userInfo,
+ type: userType
+ };
+
+ await API.request('/api/user/update', 'POST', submitData).then(res => {
+ console.log('用户信息上传成功:', res);
+ resolve({ success: true, message: '用户信息保存成功' });
+ }).catch(err => {
+ console.error('用户信息上传失败:', err);
+ // 即使服务器上传失败,也继续流程,只在本地保存
+ resolve({ success: false, message: '本地保存成功,服务器同步失败' });
+ });
+ } catch (error) {
+ console.error('保存用户信息失败:', error);
+ reject(error);
+ }
+ });
}
});
\ No newline at end of file
diff --git a/pages/evaluate2/one.wxml b/pages/evaluate2/one.wxml
index 4180588..6eaf083 100644
--- a/pages/evaluate2/one.wxml
+++ b/pages/evaluate2/one.wxml
@@ -6,6 +6,29 @@
+
+
+
+ 授权登录
+ 授权您的手机号后才能使用完整功能
+
+
+
+
+
+
+
diff --git a/pages/evaluate2/one.wxss b/pages/evaluate2/one.wxss
index 67a8107..d8e7fad 100644
--- a/pages/evaluate2/one.wxss
+++ b/pages/evaluate2/one.wxss
@@ -557,4 +557,96 @@
/* 调整规格网格布局,确保不被导航栏遮挡 */
.spec-section {
margin-bottom: 40rpx;
+}
+
+/* 登录弹窗样式 */
+.auth-modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 9999;
+}
+
+.auth-modal-container {
+ background: rgba(255, 255, 255, 0.95);
+ border-radius: 20rpx;
+ padding: 48rpx;
+ width: 80%;
+ max-width: 500rpx;
+ box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2);
+ backdrop-filter: blur(12rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.3);
+}
+
+.auth-modal-title {
+ font-size: 36rpx;
+ font-weight: 700;
+ text-align: center;
+ margin-bottom: 24rpx;
+ color: #2c3e50;
+ letter-spacing: 2rpx;
+}
+
+.auth-modal-content {
+ font-size: 28rpx;
+ text-align: center;
+ margin-bottom: 48rpx;
+ color: #666;
+ line-height: 1.5;
+ padding: 0 20rpx;
+}
+
+.auth-modal-buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 24rpx;
+}
+
+.auth-primary-button {
+ background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);
+ color: white;
+ border: none;
+ border-radius: 12rpx;
+ padding: 24rpx;
+ font-size: 30rpx;
+ font-weight: 700;
+ min-height: 88rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 4rpx 16rpx rgba(96, 165, 250, 0.4);
+ transition: all 0.3s ease;
+}
+
+.auth-primary-button:hover {
+ transform: translateY(-2rpx);
+ box-shadow: 0 8rpx 24rpx rgba(96, 165, 250, 0.6);
+}
+
+.auth-cancel-button {
+ background: rgba(255, 255, 255, 0.9);
+ color: #2c3e50;
+ border: 2rpx solid #e2e8f0;
+ border-radius: 12rpx;
+ padding: 24rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ min-height: 88rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s ease;
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
+}
+
+.auth-cancel-button:hover {
+ background: rgba(236, 240, 241, 0.8);
+ transform: translateY(-2rpx);
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
\ No newline at end of file
--
2.30.2
From f80397f9881deed5a2eaa15f3d453c784613e8d2 Mon Sep 17 00:00:00 2001
From: Default User
Date: Thu, 29 Jan 2026 10:02:27 +0800
Subject: [PATCH 21/22] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=B4=E5=83=8F?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=9B=BA=E5=AE=9A?=
=?UTF-8?q?=E7=9A=84=E5=A4=B4=E5=83=8FURL=E6=95=B0=E7=BB=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/profile/index.js | 124 ++++++++++++++++++++++-------------------
1 file changed, 67 insertions(+), 57 deletions(-)
diff --git a/pages/profile/index.js b/pages/profile/index.js
index 811dfa9..d07059a 100644
--- a/pages/profile/index.js
+++ b/pages/profile/index.js
@@ -27,7 +27,12 @@ Page({
hasLocationAuth: false, // 是否已经授权位置
isInPersonnel: false, // 用户手机号是否在personnel表中
currentAvatarIndex: 0, // 当前显示的头像索引,默认显示第一张
- rawAvatarUrl: null // 存储原始的头像URL数据(可能是数组)
+ rawAvatarUrl: null, // 存储原始的头像URL数据(可能是数组)
+ // 固定的头像URL数组
+ avatarUrls: [
+ "https://my-supplier-photos.oss-cn-chengdu.aliyuncs.com/products/%E6%B5%B7%E8%93%9D%E7%81%B0/image/7a2a8a17a83ba4d3d4270828531e2041.jpeg",
+ "https://my-supplier-photos.oss-cn-chengdu.aliyuncs.com/products/%E4%BC%8A%E8%8E%8E%E7%B2%89/image/1b2a0ba28eaa17c16c3674985ccee05c.jpeg"
+ ]
},
onLoad() {
@@ -65,23 +70,49 @@ Page({
// 如果是字符串,尝试解析为JSON数组
if (typeof avatarUrl === 'string') {
+ // 去除字符串两端的空格和引号
+ let cleanedUrl = avatarUrl.trim();
+ // 去除可能存在的前后引号
+ if ((cleanedUrl.startsWith('"') && cleanedUrl.endsWith('"')) ||
+ (cleanedUrl.startsWith('`') && cleanedUrl.endsWith('`'))) {
+ cleanedUrl = cleanedUrl.substring(1, cleanedUrl.length - 1);
+ }
+
try {
- const parsedUrl = JSON.parse(avatarUrl);
+ const parsedUrl = JSON.parse(cleanedUrl);
// 如果解析成功且是数组且不为空,使用第一个元素
if (Array.isArray(parsedUrl) && parsedUrl.length > 0) {
- return parsedUrl[0];
+ // 清理第一个元素中的空格和引号
+ let firstUrl = parsedUrl[0];
+ if (typeof firstUrl === 'string') {
+ firstUrl = firstUrl.trim();
+ if ((firstUrl.startsWith('"') && firstUrl.endsWith('"')) ||
+ (firstUrl.startsWith('`') && firstUrl.endsWith('`'))) {
+ firstUrl = firstUrl.substring(1, firstUrl.length - 1);
+ }
+ }
+ return firstUrl;
}
- // 如果解析成功但不是数组,直接返回
- return avatarUrl;
+ // 如果解析成功但不是数组,直接返回清理后的URL
+ return cleanedUrl;
} catch (e) {
- // 解析失败,直接返回
- return avatarUrl;
+ // 解析失败,返回清理后的URL
+ return cleanedUrl;
}
}
// 如果是数组且不为空,使用第一个元素
if (Array.isArray(avatarUrl) && avatarUrl.length > 0) {
- return avatarUrl[0];
+ let firstUrl = avatarUrl[0];
+ if (typeof firstUrl === 'string') {
+ // 清理第一个元素中的空格和引号
+ firstUrl = firstUrl.trim();
+ if ((firstUrl.startsWith('"') && firstUrl.endsWith('"')) ||
+ (firstUrl.startsWith('`') && firstUrl.endsWith('`'))) {
+ firstUrl = firstUrl.substring(1, firstUrl.length - 1);
+ }
+ }
+ return firstUrl;
}
// 其他情况返回默认头像
@@ -97,27 +128,31 @@ Page({
const localUserInfo = wx.getStorageSync('userInfo') || {}
if (app.globalData.userInfo) {
const userInfo = { ...app.globalData.userInfo }
- // 保存原始的头像URL数据
- const rawAvatarUrl = userInfo.avatarUrl;
- // 处理头像URL用于显示
- userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
+ // 使用固定的头像URL数组
+ const avatarUrls = this.data.avatarUrls;
+ // 使用第一张头像作为默认显示
+ userInfo.avatarUrl = avatarUrls[0];
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
this.setData({
userInfo,
- rawAvatarUrl
+ rawAvatarUrl: avatarUrls
})
+ // 更新全局状态中的头像URL,确保下次加载时使用固定的头像
+ app.globalData.userInfo = userInfo;
+ wx.setStorageSync('userInfo', userInfo);
} else {
const userInfo = { ...localUserInfo }
- // 保存原始的头像URL数据
- const rawAvatarUrl = userInfo.avatarUrl;
- // 处理头像URL用于显示
- userInfo.avatarUrl = this.processAvatarUrl(userInfo.avatarUrl);
+ // 使用固定的头像URL数组
+ const avatarUrls = this.data.avatarUrls;
+ // 使用第一张头像作为默认显示
+ userInfo.avatarUrl = avatarUrls[0];
userInfo.hiddenPhoneNumber = this.hidePhoneNumber(userInfo.phoneNumber)
app.globalData.userInfo = userInfo
+ wx.setStorageSync('userInfo', userInfo);
this.setData({
userInfo,
needPhoneAuth: !userInfo.phoneNumber,
- rawAvatarUrl
+ rawAvatarUrl: avatarUrls
})
}
@@ -244,10 +279,10 @@ Page({
...serverUserInfo
}
- // 保存原始的头像URL数据
- const rawAvatarUrl = updatedUserInfo.avatarUrl;
- // 处理头像URL用于显示
- updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
+ // 使用固定的头像URL数组
+ const avatarUrls = this.data.avatarUrls;
+ // 使用第一张头像作为默认显示
+ updatedUserInfo.avatarUrl = avatarUrls[0];
// 添加隐藏的电话号码
updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber)
@@ -256,7 +291,7 @@ Page({
wx.setStorageSync('userInfo', updatedUserInfo)
this.setData({
userInfo: updatedUserInfo,
- rawAvatarUrl
+ rawAvatarUrl: avatarUrls
})
// 同步更新用户身份信息(当前身份由数据库决定)
@@ -285,10 +320,10 @@ Page({
...serverUserInfo
}
- // 保存原始的头像URL数据
- const rawAvatarUrl = updatedUserInfo.avatarUrl;
- // 处理头像URL用于显示
- updatedUserInfo.avatarUrl = this.processAvatarUrl(updatedUserInfo.avatarUrl);
+ // 使用固定的头像URL数组
+ const avatarUrls = this.data.avatarUrls;
+ // 使用第一张头像作为默认显示
+ updatedUserInfo.avatarUrl = avatarUrls[0];
// 添加隐藏的电话号码
updatedUserInfo.hiddenPhoneNumber = this.hidePhoneNumber(updatedUserInfo.phoneNumber)
@@ -297,7 +332,7 @@ Page({
wx.setStorageSync('userInfo', updatedUserInfo)
this.setData({
userInfo: updatedUserInfo,
- rawAvatarUrl
+ rawAvatarUrl: avatarUrls
})
// 同步更新用户身份信息(当前身份由数据库决定)
@@ -1136,30 +1171,8 @@ Page({
// 点击头像切换图片
onAvatarClick() {
- // 使用rawAvatarUrl获取完整的头像URL数组
- let avatarUrls = [];
- const rawAvatarUrl = this.data.rawAvatarUrl;
-
- if (rawAvatarUrl) {
- if (typeof rawAvatarUrl === 'string') {
- // 如果是字符串,尝试解析为JSON数组
- try {
- const parsed = JSON.parse(rawAvatarUrl);
- if (Array.isArray(parsed)) {
- avatarUrls = parsed;
- } else {
- // 如果不是数组,将当前URL作为第一个元素
- avatarUrls = [rawAvatarUrl];
- }
- } catch (e) {
- // 解析失败,将当前URL作为第一个元素
- avatarUrls = [rawAvatarUrl];
- }
- } else if (Array.isArray(rawAvatarUrl)) {
- // 如果已经是数组,直接使用
- avatarUrls = rawAvatarUrl;
- }
- }
+ // 使用固定的头像URL数组
+ const avatarUrls = this.data.avatarUrls;
// 检查是否有至少两张图片可以切换
if (avatarUrls.length < 2) {
@@ -1185,15 +1198,12 @@ Page({
if (res.confirm) {
// 切换到下一张图片
const app = getApp();
+ // 只更新显示用的avatarUrl
const updatedUserInfo = {
...this.data.userInfo,
- avatarUrl: avatarUrls[nextIndex] // 直接使用下一张图片
+ avatarUrl: avatarUrls[nextIndex] // 直接使用下一张图片用于显示
};
- // 保存到本地存储和全局状态
- app.globalData.userInfo = updatedUserInfo;
- wx.setStorageSync('userInfo', updatedUserInfo);
-
// 更新页面显示
this.setData({
userInfo: updatedUserInfo,
--
2.30.2
From 91c872a1a0c0be663776f60c53fcd0e117fe75de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BE=90=E9=A3=9E=E6=B4=8B?=
<15778543+xufeiyang6017@user.noreply.gitee.com>
Date: Thu, 29 Jan 2026 10:19:36 +0800
Subject: [PATCH 22/22] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=AE=8C?=
=?UTF-8?q?=E6=95=B4=E7=9A=84=E7=82=B9=E8=B5=9E=E5=8A=9F=E8=83=BD=E5=92=8C?=
=?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8A=A8=E6=80=81=E6=98=BE=E7=A4=BA=E9=97=AE?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/eggbar/eggbar.js | 59 ++++++-
pages/eggbar/eggbar.wxml | 6 +-
server-example/server-mysql.js | 291 +++++++++++++++++++++++++++++----
utils/api.js | 4 +-
4 files changed, 321 insertions(+), 39 deletions(-)
diff --git a/pages/eggbar/eggbar.js b/pages/eggbar/eggbar.js
index 2bcda6e..ee665ad 100644
--- a/pages/eggbar/eggbar.js
+++ b/pages/eggbar/eggbar.js
@@ -83,12 +83,25 @@ Page({
loading: true
});
- API.getPosts({
+ // 获取用户电话号码
+ const userInfo = wx.getStorageSync('userInfo');
+ const phoneNumber = userInfo?.phoneNumber || wx.getStorageSync('phoneNumber');
+
+ // 只有当电话号码存在时才传递,避免传递空值
+ const params = {
page: this.data.page,
pageSize: this.data.pageSize
- }).then(res => {
+ };
+ if (phoneNumber) {
+ params.phone = phoneNumber;
+ }
+
+ API.getPosts(params).then(res => {
+ console.log('后端返回的完整响应:', res);
// 正确处理后端返回的响应格式
let newPosts = res.data && res.data.posts ? res.data.posts : [];
+ console.log('后端返回的动态数量:', newPosts.length);
+ console.log('后端返回的动态数据:', newPosts);
// 处理images字段,确保它是一个数组
newPosts = newPosts.map(post => {
@@ -243,6 +256,20 @@ Page({
likePost(e) {
const postId = e.currentTarget.dataset.id;
+
+ // 获取用户电话号码
+ const userInfo = wx.getStorageSync('userInfo');
+ const phoneNumber = userInfo?.phoneNumber || wx.getStorageSync('phoneNumber');
+
+ if (!phoneNumber) {
+ wx.showToast({
+ title: '请先登录获取电话号码',
+ icon: 'none'
+ });
+ return;
+ }
+
+ // 前端临时更新状态
const posts = this.data.posts.map(post => {
if (post.id === postId) {
return {
@@ -256,10 +283,34 @@ Page({
this.setData({ posts });
- API.likePost(postId).then(res => {
- console.log('点赞成功');
+ // 调用API
+ API.likePost(postId, phoneNumber).then(res => {
+ console.log('点赞成功:', res);
+ wx.showToast({
+ title: res.message || '操作成功',
+ icon: 'success'
+ });
}).catch(err => {
console.error('点赞失败:', err);
+
+ // 恢复原始状态
+ const originalPosts = this.data.posts.map(post => {
+ if (post.id === postId) {
+ return {
+ ...post,
+ liked: !post.liked,
+ likes: post.liked ? post.likes + 1 : post.likes - 1
+ };
+ }
+ return post;
+ });
+
+ this.setData({ posts: originalPosts });
+
+ wx.showToast({
+ title: '操作失败,请重试',
+ icon: 'none'
+ });
});
},
diff --git a/pages/eggbar/eggbar.wxml b/pages/eggbar/eggbar.wxml
index 5bdeceb..a75559c 100644
--- a/pages/eggbar/eggbar.wxml
+++ b/pages/eggbar/eggbar.wxml
@@ -42,15 +42,15 @@