2023版全新高质量商业级小程序全栈项目实战

44 阅读3分钟

090cbb463dabf5018a5f65744cc4e2b3.jpeg

2023版全新高质量商业级小程序全栈项目实战

项目概述:智能电商小程序

项目特点

  • 采用最新技术栈(Taro + React + Node.js + MongoDB)
  • 模块化架构设计
  • 高性能优化策略
  • 完整的用户体系和支付流程

前端小程序界面设计

jsx

复制下载

// 首页 - 使用Taro + React实现
import { useState, useEffect } from 'react'
import { View, Text, Image, ScrollView } from '@tarojs/components'
import { AtSearchBar, AtGrid, AtCard } from 'taro-ui'
import Taro from '@tarojs/taro'
import './index.scss'

const HomePage = () => {
  const [searchValue, setSearchValue] = useState('')
  const [banners, setBanners] = useState([])
  const [products, setProducts] = useState([])
  const [categories, setCategories] = useState([])

  useEffect(() => {
    fetchHomeData()
  }, [])

  const fetchHomeData = async () => {
    try {
      // 模拟API调用
      const bannerData = [
        { id: 1, image: 'https://example.com/banner1.jpg', link: '/pages/product/detail' },
        { id: 2, image: 'https://example.com/banner2.jpg', link: '/pages/promotion/list' }
      ]
      const categoryData = [
        { image: 'https://example.com/category1.png', value: '电子产品' },
        { image: 'https://example.com/category2.png', value: '服装配饰' },
        { image: 'https://example.com/category3.png', value: '家居生活' }
      ]
      const productData = [
        {
          id: 1,
          title: '高端智能手机',
          price: 5999,
          originalPrice: 6999,
          sales: 1234,
          image: 'https://example.com/product1.jpg'
        }
      ]

      setBanners(bannerData)
      setCategories(categoryData)
      setProducts(productData)
    } catch (error) {
      console.error('获取首页数据失败:', error)
    }
  }

  const handleSearch = (value) => {
    Taro.navigateTo({
      url: `/pages/search/result?keyword=${value}`
    })
  }

  const navigateToCategory = (category) => {
    Taro.navigateTo({
      url: `/pages/category/list?type=${category.value}`
    })
  }

  const navigateToProduct = (productId) => {
    Taro.navigateTo({
      url: `/pages/product/detail?id=${productId}`
    })
  }

  return (
    <View className='home-page'>
      {/* 搜索栏 */}
      <View className='search-section'>
        <AtSearchBar
          value={searchValue}
          onChange={setSearchValue}
          onActionClick={() => handleSearch(searchValue)}
          placeholder='搜索商品...'
        />
      </View>

      <ScrollView scrollY className='content-scroll'>
        {/* 轮播图 */}
        <View className='banner-section'>
          <ScrollView scrollX className='banner-scroll'>
            {banners.map(banner => (
              <Image
                key={banner.id}
                src={banner.image}
                className='banner-image'
                mode='aspectFill'
                onClick={() => Taro.navigateTo({ url: banner.link })}
              />
            ))}
          </ScrollView>
        </View>

        {/* 分类网格 */}
        <View className='category-section'>
          <AtGrid
            data={categories}
            onClick={navigateToCategory}
            columnNum={5}
          />
        </View>

        {/* 推荐商品 */}
        <View className='product-section'>
          <View className='section-header'>
            <Text className='section-title'>热门推荐</Text>
            <Text 
              className='section-more'
              onClick={() => Taro.navigateTo({ url: '/pages/product/list' })}
            >
              查看更多
            </Text>
          </View>
          <View className='product-grid'>
            {products.map(product => (
              <View 
                key={product.id} 
                className='product-card'
                onClick={() => navigateToProduct(product.id)}
              >
                <Image src={product.image} className='product-image' />
                <View className='product-info'>
                  <Text className='product-title'>{product.title}</Text>
                  <View className='price-section'>
                    <Text className='current-price'>¥{product.price}</Text>
                    <Text className='original-price'>¥{product.originalPrice}</Text>
                  </View>
                  <Text className='sales'>已售{product.sales}件</Text>
                </View>
              </View>
            ))}
          </View>
        </View>
      </ScrollView>
    </View>
  )
}

export default HomePage

后端API架构设计

javascript

复制下载

// app.js - Express服务器入口
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const helmet = require('helmet')
const rateLimit = require('express-rate-limit')
const compression = require('compression')

const app = express()

// 中间件配置
app.use(helmet())
app.use(compression())
app.use(cors())
app.use(express.json({ limit: '10mb' }))
app.use(express.urlencoded({ extended: true }))

// 速率限制
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 100 // 限制每个IP每15分钟最多100次请求
})
app.use(limiter)

// 数据库连接
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/miniprogram', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})

// 路由配置
app.use('/api/auth', require('./routes/auth'))
app.use('/api/products', require('./routes/products'))
app.use('/api/orders', require('./routes/orders'))
app.use('/api/users', require('./routes/users'))
app.use('/api/upload', require('./routes/upload'))

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).json({
    code: 500,
    message: '服务器内部错误',
    data: null
  })
})

// 404处理
app.use('*', (req, res) => {
  res.status(404).json({
    code: 404,
    message: '接口不存在',
    data: null
  })
})

const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
  console.log(`服务器运行在端口 ${PORT}`)
})

module.exports = app

数据库模型设计

javascript

复制下载

// models/User.js - 用户模型
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')

const userSchema = new mongoose.Schema({
  // 基础信息
  openid: {
    type: String,
    required: true,
    unique: true
  },
  unionid: String,
  
  // 用户资料
  nickname: {
    type: String,
    default: ''
  },
  avatar: {
    type: String,
    default: ''
  },
  gender: {
    type: Number,
    enum: [0, 1, 2], // 0:未知 1:男 2:女
    default: 0
  },
  phone: {
    type: String,
    default: ''
  },
  
  // 账户信息
  balance: {
    type: Number,
    default: 0
  },
  points: {
    type: Number,
    default: 0
  },
  
  // 状态
  status: {
    type: String,
    enum: ['active', 'inactive', 'banned'],
    default: 'active'
  },
  
  // 时间戳
  lastLoginAt: Date,
  createdAt: {
    type: Date,
    default: Date.now
  },
  updatedAt: {
    type: Date,
    default: Date.now
  }
})

// 索引优化
userSchema.index({ openid: 1 })
userSchema.index({ unionid: 1 })
userSchema.index({ createdAt: -1 })

// 更新时间的中间件
userSchema.pre('save', function(next) {
  this.updatedAt = Date.now()
  next()
})

module.exports = mongoose.model('User', userSchema)

javascript

复制下载

// models/Product.js - 商品模型
const mongoose = require('mongoose')

const productSchema = new mongoose.Schema({
  // 基础信息
  name: {
    type: String,
    required: true,
    trim: true
  },
  description: {
    type: String,
    default: ''
  },
  
  // 分类和标签
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
    required: true
  },
  tags: [String],
  
  // 价格信息
  price: {
    type: Number,
    required: true,
    min: 0
  },
  originalPrice: {
    type: Number,
    min: 0
  },
  
  // 库存信息
  stock: {
    type: Number,
    default: 0,
    min: 0
  },
  sales: {
    type: Number,
    default: 0,
    min: 0
  },
  
  // 图片和媒体
  images: [{
    url: String,
    isMain: {
      type: Boolean,
      default: false
    }
  }],
  
  // 商品属性
  attributes: [{
    name: String,
    value: String
  }],
  
  // SKU信息
  skus: [{
    attributes: [{
      name: String,
      value: String
    }],
    price: Number,
    stock: Number,
    image: String
  }],
  
  // 状态
  status: {
    type: String,
    enum: ['draft', 'published', 'out_of_stock', 'discontinued'],
    default: 'draft'
  },
  
  // 时间戳
  createdAt: {
    type: Date,
    default: Date.now
  },
  updatedAt: {
    type: Date,
    default: Date.now
  }
})

// 索引优化
productSchema.index({ category: 1, status: 1 })
productSchema.index({ price: 1 })
productSchema.index({ sales: -1 })
productSchema.index({ createdAt: -1 })

productSchema.pre('save', function(next) {
  this.updatedAt = Date.now()
  next()
})

module.exports = mongoose.model('Product', productSchema)

核心业务逻辑实现

javascript

复制下载

// services/OrderService.js - 订单服务
class OrderService {
  /**
   * 创建订单
   */
  async createOrder(orderData, userId) {
    try {
      // 1. 验证商品库存
      const stockValidation = await this.validateStock(orderData.items)
      if (!stockValidation.valid) {
        throw new Error(`商品 ${stockValidation.productName} 库存不足`)
      }

      // 2. 计算订单金额
      const amount = await this.calculateOrderAmount(orderData.items)

      // 3. 创建订单记录
      const order = new Order({
        ...orderData,
        userId,
        orderNo: this.generateOrderNo(),
        amount,
        status: 'pending'
      })

      // 4. 扣减库存
      await this.deductStock(orderData.items)

      // 5. 保存订单
      await order.save()

      return {
        success: true,
        data: order,
        message: '订单创建成功'
      }
    } catch (error) {
      console.error('创建订单失败:', error)
      return {
        success: false,
        message: error.message
      }
    }
  }

  /**
   * 验证库存
   */
  async validateStock(items) {
    for (const item of items) {
      const product = await Product.findById(item.productId)
      if (!product || product.stock < item.quantity) {
        return {
          valid: false,
          productName: product ? product.name : '未知商品'
        }
      }
    }
    return { valid: true }
  }

  /**
   * 计算订单金额
   */
  async calculateOrderAmount(items) {
    let total = 0
    for (const item of items) {
      const product = await Product.findById(item.productId)
      total += product.price * item.quantity
    }
    return total
  }

  /**
   * 生成订单号
   */
  generateOrderNo() {
    const timestamp = new Date().getTime()
    const random = Math.random().toString().slice(2, 8)
    return `ORDER${timestamp}${random}`
  }
}

module.exports = new OrderService()

项目架构优势

1. 技术栈优势

  • 前端: Taro 3.x + React + TypeScript
  • 后端: Node.js + Express + MongoDB
  • 部署: Docker + Nginx + PM2

2. 性能优化

  • 图片懒加载和WebP格式支持
  • 接口响应缓存
  • 数据库查询优化
  • CDN静态资源加速

3. 安全措施

  • JWT Token认证
  • 接口签名验证
  • SQL注入防护
  • XSS攻击防范

4. 可扩展性

  • 微服务架构准备
  • 消息队列集成
  • 分布式缓存支持
  • 负载均衡配置

这个全栈项目方案涵盖了现代商业级小程序的核心需求,包括用户系统、商品管理、订单处理、支付集成等完整功能。代码结构清晰,易于维护和扩展,适合作为商业项目的基础架构。