diff --git a/MULTI_PROJECT_DEPLOYMENT.md b/MULTI_PROJECT_DEPLOYMENT.md deleted file mode 100644 index c42ba2e..0000000 --- a/MULTI_PROJECT_DEPLOYMENT.md +++ /dev/null @@ -1,254 +0,0 @@ -# 多项目统一部署方案 - -## 目录结构设计 - -在云服务器上创建以下目录结构: - -``` -/projects/ -├── project1/ -│ ├── source/ # 项目源代码 -│ ├── logs/ # 项目日志 -│ ├── docker/ # Docker相关文件 -│ └── docker-compose.yml -├── project2/ -│ ├── source/ -│ ├── logs/ -│ ├── docker/ -│ └── docker-compose.yml -├── project3/ -│ ├── source/ -│ ├── logs/ -│ ├── docker/ -│ └── docker-compose.yml -├── project4/ -│ ├── source/ -│ ├── logs/ -│ ├── docker/ -│ └── docker-compose.yml -└── scripts/ # 统一管理脚本 - ├── deploy-all.sh # 一键部署所有项目 - ├── update-all.sh # 一键更新所有项目 - ├── restart-all.sh # 一键重启所有项目 - └── status-all.sh # 查看所有项目状态 -``` - -## 部署脚本 - -### 1. 创建目录结构脚本 - -```bash -#!/bin/bash -# create-project-structure.sh - -echo "创建多项目统一部署目录结构..." - -# 创建主目录 -mkdir -p /projects/{project1,project2,project3,project4}/{source,logs,docker} -mkdir -p /projects/scripts - -echo "目录结构创建完成!" -echo "目录结构:" -find /projects -type d | sort -``` - -### 2. 统一部署脚本 - -```bash -#!/bin/bash -# /projects/scripts/deploy-all.sh - -echo "开始部署所有项目..." - -# 项目列表 -projects=("project1" "project2" "project3" "project4") - -for project in "${projects[@]}"; do - echo "\n=== 部署 $project ===" - cd /projects/$project - - # 拉取最新代码 - echo "拉取最新代码..." - cd source - git pull origin BOSS - cd .. - - # 构建并启动容器 - echo "构建并启动容器..." - docker-compose down - docker-compose up -d --build - - echo "$project 部署完成!" -done - -echo "\n所有项目部署完成!" -``` - -### 3. 统一更新脚本 - -```bash -#!/bin/bash -# /projects/scripts/update-all.sh - -echo "开始更新所有项目..." - -# 项目列表 -projects=("project1" "project2" "project3" "project4") - -for project in "${projects[@]}"; do - echo "\n=== 更新 $project ===" - cd /projects/$project - - # 拉取最新代码 - echo "拉取最新代码..." - cd source - git pull origin BOSS - cd .. - - # 重新构建并启动容器 - echo "重新构建并启动容器..." - docker-compose down - docker-compose up -d --build - - echo "$project 更新完成!" -done - -echo "\n所有项目更新完成!" -``` - -### 4. 统一状态查看脚本 - -```bash -#!/bin/bash -# /projects/scripts/status-all.sh - -echo "查看所有项目状态..." - -# 项目列表 -projects=("project1" "project2" "project3" "project4") - -for project in "${projects[@]}"; do - echo "\n=== $project 状态 ===" - cd /projects/$project - docker-compose ps - - echo "\n$project 日志(最近10行):" - docker-compose logs --tail=10 -done - -echo "\n所有项目状态查看完成!" -``` - -### 5. 统一重启脚本 - -```bash -#!/bin/bash -# /projects/scripts/restart-all.sh - -echo "开始重启所有项目..." - -# 项目列表 -projects=("project1" "project2" "project3" "project4") - -for project in "${projects[@]}"; do - echo "\n=== 重启 $project ===" - cd /projects/$project - docker-compose restart - echo "$project 重启完成!" -done - -echo "\n所有项目重启完成!" -``` - -## 项目配置示例 - -### 以当前项目为例,创建docker-compose.yml - -```yaml -# /projects/project1/docker-compose.yml -version: '3.8' - -services: - app: - build: ./source/server-example - container_name: project1-server - restart: always - ports: - - "3000:3000" - environment: - - NODE_ENV=production - volumes: - - ./logs:/app/logs - - ./source/server-example/uploads:/app/uploads - depends_on: - - db - - db: - image: mysql:8.0 - container_name: project1-db - restart: always - ports: - - "3306:3306" - environment: - - MYSQL_ROOT_PASSWORD=rootpassword - - MYSQL_DATABASE=wechat_miniprogram - - MYSQL_USER=wechat_user - - MYSQL_PASSWORD=wechat_password - volumes: - - db_data:/var/lib/mysql - -volumes: - db_data: -``` - -## 使用说明 - -1. **创建目录结构**: - ```bash - chmod +x create-project-structure.sh - ./create-project-structure.sh - ``` - -2. **部署项目**: - - 将每个项目的源代码克隆到对应的`/projects/{projectN}/source/`目录 - - 为每个项目创建docker-compose.yml文件 - - 执行统一部署脚本: - ```bash - chmod +x /projects/scripts/*.sh - /projects/scripts/deploy-all.sh - ``` - -3. **管理项目**: - - 更新所有项目:`/projects/scripts/update-all.sh` - - 查看所有项目状态:`/projects/scripts/status-all.sh` - - 重启所有项目:`/projects/scripts/restart-all.sh` - -## 运维最佳实践 - -1. **日志管理**: - - 所有项目的日志统一存储在`/projects/{projectN}/logs/`目录 - - 可以使用ELK等工具进行统一日志收集和分析 - -2. **备份策略**: - - 定期备份数据库: - ```bash - docker exec -t project1-db mysqldump -u wechat_user -p wechat_miniprogram > /projects/backups/project1_db_$(date +%Y%m%d_%H%M%S).sql - ``` - - 定期备份源代码和配置文件 - -3. **监控告警**: - - 使用Prometheus和Grafana监控容器和应用状态 - - 设置告警规则,及时发现问题 - -4. **安全措施**: - - 定期更新容器镜像和依赖 - - 配置防火墙,只开放必要的端口 - - 定期检查系统安全漏洞 - -## 注意事项 - -1. 确保每个项目使用不同的端口,避免端口冲突 -2. 为每个项目的数据库设置强密码 -3. 定期清理无用的容器和镜像:`docker system prune -f` -4. 监控磁盘空间使用情况,及时清理日志文件 -5. 考虑使用CI/CD工具(如Jenkins、GitLab CI)实现自动化部署 diff --git a/TEST_PLAN.md b/TEST_PLAN.md deleted file mode 100644 index 86f9e55..0000000 --- a/TEST_PLAN.md +++ /dev/null @@ -1,103 +0,0 @@ -# 修复功能测试计划 - -## 1. 测试默认排序规则 - -**测试目的**:验证商品是否按照要求的默认排序规则显示 - -**测试步骤**: -1. 打开小程序首页 -2. 观察商品列表顺序 -3. 确认排序规则: - - 已发布商品(published)在已售罄商品(sold_out)之前 - - 同一状态内,预订数量(reservedCount)高的在前 - - 预订数量相同时,价格低的在前 - - 价格相同时,创建时间晚的在前 - -**预期结果**:商品按照上述规则正确排序 - -## 2. 测试sold_out商品加载逻辑 - -**测试目的**:验证只有当数据库中找不到published商品时才加载sold_out商品 - -**测试步骤**: -1. 打开小程序首页 -2. 检查初始加载的商品是否都是published状态 -3. 向下滑动页面,直到加载更多商品 -4. 确认在所有published商品加载完毕后,才开始加载sold_out商品 - -**预期结果**: -- 初始加载的商品都是published状态 -- 当published商品加载完毕后,自动开始加载sold_out商品 - -## 3. 测试sold_out商品加载功能 - -**测试目的**:验证sold_out商品能够正常加载 - -**测试步骤**: -1. 打开小程序首页 -2. 向下滑动页面,直到加载sold_out商品 -3. 检查是否有sold_out状态的商品显示 - -**预期结果**:sold_out商品能够正常显示在列表中 - -## 4. 测试下滑到底部加载功能 - -**测试目的**:验证下滑到底部能够加载更多商品,包括sold_out商品 - -**测试步骤**: -1. 打开小程序首页 -2. 连续向下滑动页面,直到到达列表底部 -3. 观察是否自动加载更多商品 -4. 继续滑动,直到加载sold_out商品 - -**预期结果**: -- 下滑到底部时自动加载更多商品 -- published商品加载完毕后,自动加载sold_out商品 - -## 5. 测试下拉刷新功能 - -**测试目的**:验证下拉刷新不会改变已加载商品的顺序 - -**测试步骤**: -1. 打开小程序首页 -2. 观察初始商品顺序,记住前几个商品 -3. 下拉页面进行刷新 -4. 刷新完成后,观察商品顺序是否变化 - -**预期结果**:下拉刷新后,已加载商品的顺序保持不变,新商品添加在列表底部 - -## 6. 测试分类和搜索功能 - -**测试目的**:验证分类和搜索功能下,排序和加载逻辑依然正常 - -**测试步骤**: -1. 选择一个分类(如"粉壳") -2. 观察商品排序是否正确 -3. 向下滑动加载更多商品,验证是否正常加载sold_out商品 -4. 进行搜索,重复步骤2和3 - -**预期结果**:分类和搜索功能下,所有排序和加载逻辑都正常工作 - -## 7. 测试缓存功能 - -**测试目的**:验证缓存机制不会影响排序和加载逻辑 - -**测试步骤**: -1. 打开小程序首页,加载商品 -2. 关闭小程序 -3. 重新打开小程序 -4. 观察商品是否从缓存加载,排序是否正确 - -**预期结果**:缓存加载的商品保持正确的排序顺序 - -## 测试环境要求 - -- WeChat Developer Tools最新版本 -- 测试用手机(推荐)或模拟器 -- 稳定的网络连接 - -## 测试注意事项 - -1. 记录测试过程中的任何异常情况 -2. 如果发现问题,尝试重现并记录详细步骤 -3. 测试完成后,汇总测试结果 diff --git a/pages/evaluate2/one.js b/pages/evaluate2/one.js index 50c28d1..ed850e5 100644 --- a/pages/evaluate2/one.js +++ b/pages/evaluate2/one.js @@ -22,6 +22,15 @@ Page({ } } + // 增加用户估价点击次数(进入页面时自动增加) + const API = require('../../utils/api'); + API.incrementAppraisalNum().then(res => { + console.log('增加估价次数成功:', res); + }).catch(err => { + console.error('增加估价次数失败:', err); + // 即使失败也不影响主流程 + }); + if (productName) { this.setData({ productName: productName }); this.loadSpecifications(productName); @@ -447,6 +456,16 @@ Page({ const specItem = e.currentTarget.dataset.spec; console.log('点击的规格项:', specItem); console.log('传递的价格:', specItem.finalPriceText); + + // 增加用户估价点击次数 + const API = require('../../utils/api'); + API.incrementAppraisalNum().then(res => { + console.log('增加估价次数成功:', res); + }).catch(err => { + console.error('增加估价次数失败:', err); + // 即使失败也不影响主流程 + }); + wx.navigateTo({ url: `/pages/evaluate1/spec-detail?productName=${encodeURIComponent(this.data.productName)}&specification=${encodeURIComponent(specItem.name)}&price=${encodeURIComponent(specItem.finalPriceText)}` }); diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js index 68a9fd3..d81c209 100644 --- a/pages/goods-detail/goods-detail.js +++ b/pages/goods-detail/goods-detail.js @@ -3063,6 +3063,14 @@ Page({ // 即使记录失败,也不影响主流程 }); + // 增加用户对比价格点击次数 + API.incrementCompareNum().then(res => { + console.log('增加对比价格次数成功:', res); + }).catch(err => { + console.error('增加对比价格次数失败:', err); + // 即使失败也不影响主流程 + }); + // 检查用户身份证认证状态 let idcardstatus = 0; const users = wx.getStorageSync('users') || {}; diff --git a/server-example/server-mysql.js b/server-example/server-mysql.js index 4123481..47309bb 100644 --- a/server-example/server-mysql.js +++ b/server-example/server-mysql.js @@ -1548,7 +1548,7 @@ User.init({ // 身份证认证状态字段 idcardstatus: { type: DataTypes.INTEGER, // 0: 待审核, 1: 审核通过, 2: 审核失败 - defaultValue: 0, // 默认值为待审核 + defaultValue: null, // 默认值为null comment: '身份证认证状态' }, // 授权区域字段 - 用于存储用户位置信息 @@ -1576,6 +1576,18 @@ User.init({ notice: { type: DataTypes.STRING(255) // 通知提醒 }, + // 新增字段:点击估价次数 + appraisalnum: { + type: DataTypes.INTEGER, + defaultValue: 0, + comment: '点击估价次数' + }, + // 新增字段:点击对比价格次数 + comparenum: { + type: DataTypes.INTEGER, + defaultValue: 0, + comment: '点击对比价格次数' + }, idcard1: { type: DataTypes.TEXT, // 身份证正面 comment: '身份证正面' @@ -11110,6 +11122,82 @@ app.get('/api/orders', async (req, res) => { } }); +// 新增:增加用户估价点击次数接口 +app.post('/api/user/increment-appraisal', async (req, res) => { + try { + const { openid, userId } = req.body; + console.log('增加估价次数请求:', { openid, userId }); + + if (!openid || !userId) { + return res.status(400).json({ + success: false, + code: 400, + message: '缺少必要参数' + }); + } + + // 更新用户的估价点击次数(使用 COALESCE 处理 NULL 值) + const [result] = await sequelize.query( + 'UPDATE users SET appraisalnum = COALESCE(appraisalnum, 0) + 1 WHERE openid = ? OR userId = ?', + { replacements: [openid, userId] } + ); + + console.log('增加估价次数结果:', result, '影响行数:', result.affectedRows); + + res.json({ + success: true, + code: 200, + message: '增加估价次数成功', + affectedRows: result.affectedRows + }); + } catch (error) { + console.error('增加估价次数失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '增加估价次数失败: ' + error.message + }); + } +}); + +// 新增:增加用户对比价格点击次数接口 +app.post('/api/user/increment-compare', async (req, res) => { + try { + const { openid, userId } = req.body; + console.log('增加对比价格次数请求:', { openid, userId }); + + if (!openid || !userId) { + return res.status(400).json({ + success: false, + code: 400, + message: '缺少必要参数' + }); + } + + // 更新用户的对比价格点击次数(使用 COALESCE 处理 NULL 值) + const [result] = await sequelize.query( + 'UPDATE users SET comparenum = COALESCE(comparenum, 0) + 1 WHERE openid = ? OR userId = ?', + { replacements: [openid, userId] } + ); + + console.log('增加对比价格次数结果:', result, '影响行数:', result.affectedRows); + + res.json({ + success: true, + code: 200, + message: '增加对比价格次数成功', + affectedRows: result.affectedRows + }); + } catch (error) { + console.error('增加对比价格次数失败:', error); + res.status(500).json({ + success: false, + code: 500, + message: '增加对比价格次数失败: ' + error.message + }); + } +}); + // 在服务器启动前执行商品联系人更新 updateProductContacts().then(() => { console.log('\n📦 商品联系人信息更新完成!'); diff --git a/utils/api.js b/utils/api.js index 8b72cc2..229bc00 100644 --- a/utils/api.js +++ b/utils/api.js @@ -3584,6 +3584,44 @@ module.exports = { openid: openid }); }, + + // 增加用户估价点击次数 + incrementAppraisalNum: function () { + const openid = wx.getStorageSync('openid'); + const userId = wx.getStorageSync('userId'); + console.log('API.incrementAppraisalNum - openid:', openid, 'userId:', userId); + if (!openid || !userId) { + return Promise.reject(new Error('用户未登录')); + } + + return request('/api/user/increment-appraisal', 'POST', { + openid: openid, + userId: userId + }).catch(err => { + console.error('增加估价次数失败:', err); + // 即使失败也返回成功,不影响主流程 + return { success: true }; + }); + }, + + // 增加用户对比价格点击次数 + incrementCompareNum: function () { + const openid = wx.getStorageSync('openid'); + const userId = wx.getStorageSync('userId'); + console.log('API.incrementCompareNum - openid:', openid, 'userId:', userId); + if (!openid || !userId) { + return Promise.reject(new Error('用户未登录')); + } + + return request('/api/user/increment-compare', 'POST', { + openid: openid, + userId: userId + }).catch(err => { + console.error('增加对比价格次数失败:', err); + // 即使失败也返回成功,不影响主流程 + return { success: true }; + }); + }, // 编辑商品方法 - 修复版 editProduct: function (productId, productData) { const openid = wx.getStorageSync('openid');