当前位置: 首页 > news >正文

虚拟试衣间-云尚衣橱小程序-衣橱管理实现

衣橱管理实现

目标 (Goal):

  • 用户 (User): 能通过 UniApp 小程序上传衣服图片。

  • 后端 (Backend): 接收图片,存到云存储,并将图片信息(URL、用户ID等)存入数据库。

  • 用户 (User): 能在小程序里看到自己上传的所有衣服图片列表。

技术栈细化 (Refined Tech Stack for this Phase):

  • 前端 (Frontend): UniApp (Vue 语法)

  • 后端 (Backend): Node.js, Express.js

  • 数据库 (Database): MongoDB (使用 Mongoose ODM 操作会更方便)

  • 图片存储 (Image Storage): 腾讯云 COS / 阿里云 OSS (必须使用云存储)

  • HTTP 请求库 (Frontend): UniApp 内置的 uni.request 或 uni.uploadFile

  • 文件上传处理 (Backend): multer 中间件

  • 云存储 SDK (Backend): tcb-admin-node (如果用腾讯云开发) 或 cos-nodejs-sdk-v5 (腾讯云 COS) 或 ali-oss (阿里云 OSS)

  • 认证 (Authentication): JWT (JSON Web Tokens)

1. 后端 (Node.js / Express) 实现

项目结构 (示例):

wardrobe-backend/
├── node_modules/
├── config/
│   ├── db.js         # 数据库连接
│   └── cloudStorage.js # 云存储配置 (密钥等) - 不要硬编码!用环境变量
├── controllers/
│   ├── authController.js
│   └── wardrobeController.js
├── middleware/
│   ├── authMiddleware.js  # JWT 验证
│   └── uploadMiddleware.js # Multer 配置
├── models/
│   ├── User.js         # Mongoose User Schema
│   └── Clothes.js      # Mongoose Clothes Schema
├── routes/
│   ├── authRoutes.js
│   └── wardrobeRoutes.js
├── .env              # 环境变量 (数据库URI, 云存储密钥, JWT Secret) - 加入 .gitignore
├── .gitignore
├── package.json
└── server.js         # Express 应用入口

关键代码实现点:

(a) server.js (入口文件)

require('dotenv').config(); // Load environment variables
const express = require('express');
const cors = require('cors');
const connectDB = require('./config/db');
const authRoutes = require('./routes/authRoutes');
const wardrobeRoutes = require('./routes/wardrobeRoutes');

// Connect to Database
connectDB();

const app = express();

// Middleware
app.use(cors()); // 允许跨域请求 (小程序需要)
app.use(express.json()); // 解析 JSON body
app.use(express.urlencoded({ extended: false })); // 解析 URL-encoded body

// Routes
app.use('/api/auth', authRoutes);
app.use('/api/wardrobe', wardrobeRoutes); // 衣橱相关路由

// Basic Error Handling (can be improved)
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send({ message: 'Something broke!', error: err.message });
});


const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

(b) models/User.js & models/Clothes.js (Mongoose Schemas)

// models/User.js
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
    openid: { type: String, required: true, unique: true },
    // session_key: { type: String, required: true }, // 按需存储,注意安全
    nickname: { type: String },
    avatarUrl: { type: String },
    // ... other fields
}, { timestamps: true });
module.exports = mongoose.model('User', UserSchema);

// models/Clothes.js
const mongoose = require('mongoose');
const ClothesSchema = new mongoose.Schema({
    userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true, index: true },
    imageUrl: { type: String, required: true }, // 图片在云存储的URL
    tags: { type: [String], default: [] },      // AI识别标签 (暂时为空或默认值)
    notes: { type: String, default: '' },      // 用户备注
    // ... 其他未来可能添加的字段 (颜色、类型等)
}, { timestamps: true });
module.exports = mongoose.model('Clothes', ClothesSchema);

(c) middleware/authMiddleware.js (JWT 验证)

const jwt = require('jsonwebtoken');
const User = require('../models/User');

const protect = async (req, res, next) => {
    let token;
    if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
        try {
            // Get token from header
            token = req.headers.authorization.split(' ')[1];

            // Verify token
            const decoded = jwt.verify(token, process.env.JWT_SECRET); // 使用环境变量中的密钥

            // Get user from the token (select -password if you store passwords)
            req.user = await User.findById(decoded.id).select('-session_key'); // 附加用户信息到 req

            if (!req.user) {
                 return res.status(401).json({ message: 'Not authorized, user not found' });
            }

            next();
        } catch (error) {
            console.error(error);
            res.status(401).json({ message: 'Not authorized, token failed' });
        }
    }

    if (!token) {
        res.status(401).json({ message: 'Not authorized, no token' });
    }
};

module.exports = { protect };

(d) routes/authRoutes.js & controllers/authController.js (登录逻辑)

// routes/authRoutes.js
const express = require('express');
const { loginUser } = require('../controllers/authController');
const router = express.Router();
router.post('/login', loginUser);
module.exports = router;

// controllers/authController.js
const axios = require('axios');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

const WX_APPID = process.env.WX_APPID;       // 小程序 AppID
const WX_SECRET = process.env.WX_SECRET;   // 小程序 Secret

// Generate JWT
const generateToken = (id) => {
    return jwt.sign({ id }, process.env.JWT_SECRET, {
        expiresIn: '30d', // Token 有效期
    });
};

const loginUser = async (req, res) => {
    const { code, userInfo } = req.body; // 前端发送 wx.login 的 code 和用户信息

    if (!code) {
        return res.status(400).json({ message: 'Code is required' });
    }

    try {
        // 1. 用 code 换取 openid 和 session_key
        const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${WX_APPID}&secret=${WX_SECRET}&js_code=${code}&grant_type=authorization_code`;
        const response = await axios.get(url);
        const { openid, session_key } = response.data;

        if (!openid) {
            return res.status(400).json({ message: 'Failed to get openid', error: response.data });
        }

        // 2. 查找或创建用户
        let user = await User.findOne({ openid });
        if (!user) {
            // 如果需要用户信息&
http://www.dtcms.com/a/108475.html

相关文章:

  • 算法:二进制求和
  • 从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.3.3低代码开发:快速构建行业应用(电商推荐与金融风控案例)
  • Python 驱动周立功200U收发报文
  • 国产系统服务器识别不到SATA盘
  • STM32学习笔记之RCC模块(实操篇)
  • 横扫SQL面试——中位数问题
  • git tag
  • Linux 中CIFS和NFS使用说明
  • MCP学习总结
  • 基于RapidIO接口的DSP+GPU工业AI实时计算解决方案
  • ‘conda‘ 不是内部或外部命令,也不是可运行的程序或批处理文件
  • 【YOLOv8】YOLOv8改进系列(12)----替换主干网络之StarNet
  • 系统安全——文件监控-FileMonitor
  • 数据在内存中存储(C语言)
  • 杂篇-行业分类一二-2(通、专用设备制造,汽车制造)
  • (done) MIT6.824 Lecture 02 - RPC and Threads
  • stm32:sg90 和 mg90s舵机学习
  • Python----计算机视觉处理(Opencv:道路检测之提取车道线)
  • 好玩有趣的github开源项目分享(持续更新)
  • 【MySQL基础】 JSON函数入门
  • 代码随想录-动态规划18
  • 如何学习C++以及C++的宏观认知
  • AI:机器学习模型-线性回归
  • 清华大学:网络大模型NetGPT研究进展(2025)
  • 深入解析JavaScript混淆加密与Python逆向调用实战-题八
  • 蓝桥杯-算法基础-For循环
  • [CISSP] [5] 保护资产安全
  • Mybatis 如何自定义缓存?
  • UML 关系探秘:理论与实践双维度剖析
  • Cesium for Unreal 源码编译