基于Vue与Spring Boot的在线商品体验平台 - 源码深度解析

JavaJavaScriptMavenHTMLCSSSSM框架MySQL使用Vue
2026-02-102 浏览

文章摘要

本项目是一款基于Vue与Spring Boot技术栈构建的在线商品体验平台,其核心业务价值在于彻底改变了传统的线上商品浏览模式,解决了用户无法在购买前直观、互动地了解商品实际效果的行业痛点。该平台不仅提供静态的商品展示,更关键的是集成了沉浸式的在线体验功能,允许用户通过模拟操作、参数调整等方式深度感...

在当今电子商务高度发达的时代,线上购物已成为主流消费方式。然而,传统电商平台普遍存在一个核心痛点:用户无法在购买前获得真实的产品体验感。面对这一行业挑战,我们开发了一款创新的沉浸式商品体验平台,通过Vue与Spring Boot技术栈的深度整合,重新定义了线上商品交互的标准。

系统架构与技术栈

该平台采用前后端分离的微服务架构设计,前端基于Vue.js生态体系构建,后端依托Spring Boot框架提供稳定的API服务。这种架构选择不仅保证了系统的高可维护性,还实现了技术栈的现代化升级。

前端技术栈

  • Vue 3.0 + Vue Router + Vuex状态管理
  • Element Plus UI组件库
  • Axios HTTP客户端
  • ECharts数据可视化

后端技术栈

  • Spring Boot 2.7 + Spring MVC + MyBatis Plus
  • MySQL 8.0关系型数据库
  • Redis缓存服务器
  • Maven项目管理工具
  • Hutool工具库

项目配置文件展示了完整的技术集成方案:

# 数据库连接配置
spring.datasource.url=jdbc:mysql://192.168.99.4:3306/vue_productexp?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
spring.datasource.username=vue_productexp
spring.datasource.password=vue_productexp

# MyBatis Plus配置
mybatis-plus.global-config.db-config.table-prefix=t_
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# Redis缓存配置
spring.redis.port=6379
spring.redis.host=java.envdown.site
spring.redis.password=1234

# 文件上传配置
spring.servlet.multipart.max-file-size=1000MB
spring.servlet.multipart.max-request-size=1000MB
server.servlet.context-path=/vue_productexp

数据库设计亮点

平台数据库设计包含28个核心表,体现了高度规范化的设计理念。以下重点分析几个关键表的结构设计:

地址管理表(t_address)

CREATE TABLE `t_address` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(1000) DEFAULT NULL COMMENT '姓名',
  `phone` varchar(1000) DEFAULT NULL COMMENT '联系电话',
  `address` varchar(1000) DEFAULT NULL COMMENT '具体位置',
  `keyong` tinyint(1) DEFAULT NULL COMMENT '是否可用',
  `moren` tinyint(1) DEFAULT NULL COMMENT '是否默认',
  `bz` varchar(1000) DEFAULT NULL COMMENT '备注',
  `user_id` int(11) DEFAULT NULL COMMENT '所属用户',
  `add_time` datetime DEFAULT NULL COMMENT '插入数据库时间',
  PRIMARY KEY (`id`),
  KEY `FK5220625006534175546` (`user_id`),
  CONSTRAINT `FK5220625006534175546` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='地址管理'

设计亮点分析

  • 使用utf8mb4_unicode_ci字符集,完美支持emoji和生僻字存储
  • tinyint(1)字段优化布尔值存储,相比varchar节省75%空间
  • 外键约束确保数据引用完整性,防止孤儿记录产生
  • 复合索引设计支持高效的用户地址查询

订单管理表(t_orders)

CREATE TABLE `t_orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `pdetail` varchar(1000) DEFAULT NULL COMMENT '购买商品详情',
  `total` double DEFAULT NULL COMMENT '订单总金额',
  `address` varchar(1000) DEFAULT NULL COMMENT '收货地址',
  `keeper` varchar(1000) DEFAULT NULL COMMENT '收货人',
  `phone` varchar(1000) DEFAULT NULL COMMENT '联系电话',
  `ydanhao` varchar(1000) DEFAULT NULL COMMENT '运单号',
  `comment` varchar(1000) DEFAULT NULL COMMENT '评价',
  `comment_time` varchar(255) DEFAULT NULL COMMENT '评价时间',
  `stime` varchar(1000) DEFAULT NULL COMMENT '下单时间',
  `bz` varchar(1000) DEFAULT NULL COMMENT '备注',
  `user_id` int(11) DEFAULT NULL COMMENT '购买人',
  `orderStatus_id` int(11) DEFAULT NULL COMMENT '订单状态',
  `add_time` datetime DEFAULT NULL COMMENT '插入数据库时间',
  PRIMARY KEY (`id`),
  KEY `FK7581838138783766629` (`user_id`),
  KEY `FK2263803048440309603` (`orderStatus_id`),
  CONSTRAINT `FK2263803048440309603` FOREIGN KEY (`orderStatus_id`) REFERENCES `t_orderstatus` (`id`),
  CONSTRAINT `FK7581838138783766629` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单管理'

性能优化策略

  • 双外键索引设计支持高效的订单状态和用户查询
  • datetime类型精确记录时间戳,支持范围查询优化
  • 金额字段使用double类型,确保计算精度
  • 冗余字段设计减少联表查询,提升读取性能

角色权限表(t_role & t_user_role)

CREATE TABLE `t_role` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(50) DEFAULT NULL COMMENT '角色名字',
  `role_desc` varchar(100) DEFAULT NULL COMMENT '角色备注',
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色表'

CREATE TABLE `t_user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '关联ID',
  `user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  `role_id` int(11) DEFAULT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户角色表'

权限模型设计

  • 多对多关系表支持灵活的用户角色分配
  • 角色表独立设计,便于权限管理的扩展
  • 自增主键确保数据插入性能最优

角色管理界面

核心功能实现

1. 沉浸式商品体验模块

平台的核心创新在于商品体验功能。通过Vue.js的响应式特性,实现了实时交互的商品预览效果。

前端体验组件实现

<template>
  <div class="product-experience">
    <div class="product-viewer">
      <canvas ref="productCanvas" @mousemove="handleMouseMove"></canvas>
    </div>
    <div class="control-panel">
      <el-slider v-model="rotationX" :min="0" :max="360" @change="updateProductView" />
      <el-slider v-model="rotationY" :min="0" :max="360" @change="updateProductView" />
      <el-color-picker v-model="productColor" @change="updateProductColor" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      rotationX: 0,
      rotationY: 0,
      productColor: '#1890ff',
      productModel: null
    }
  },
  methods: {
    async loadProductModel(productId) {
      const response = await this.$api.get(`/product/model/${productId}`)
      this.productModel = response.data
      this.renderProduct()
    },
    updateProductView() {
      this.renderProduct()
    },
    renderProduct() {
      const canvas = this.$refs.productCanvas
      const ctx = canvas.getContext('2d')
      // 3D渲染逻辑实现
      this.render3DModel(ctx, this.productModel, {
        rotationX: this.rotationX,
        rotationY: this.rotationY,
        color: this.productColor
      })
    }
  }
}
</script>

后端商品模型接口

@RestController
@RequestMapping("/product")
public class ProductController {
    
    @Autowired
    private ProductService productService;
    
    @GetMapping("/model/{productId}")
    @RequireLoginWithToken
    public Result<ProductModelDTO> getProductModel(@PathVariable Integer productId) {
        try {
            ProductModelDTO model = productService.getProductModelById(productId);
            return Result.success(model);
        } catch (Exception e) {
            log.error("获取商品模型失败: {}", e.getMessage());
            return Result.error(ResultCode.PRODUCT_MODEL_NOT_FOUND);
        }
    }
    
    @PostMapping("/experience/record")
    @RequireLoginWithToken
    public Result recordUserExperience(@RequestBody ExperienceRecord record) {
        productService.recordUserExperience(record);
        return Result.success("体验记录保存成功");
    }
}

商品详情页面

2. 智能地址管理系统

地址管理模块采用层级化的设计理念,支持多地址管理和默认地址设置。

地址控制器核心实现

@Controller
@RequestMapping("/address")
public class AddressController {
    
    @Resource
    private AddressService addressService;
    
    @Resource
    private UserService userService;

    @RequestMapping("/list")
    @ResponseBody
    @RequireLoginWithToken
    public Result<List<Address>> getAddressList(HttpServletRequest request) {
        try {
            Integer userId = JwtUtil.getUserIdFromToken(request);
            List<Address> addresses = addressService.getUserAddresses(userId);
            return Result.success(addresses);
        } catch (Exception e) {
            log.error("获取地址列表失败: {}", e.getMessage());
            return Result.error(ResultCode.ADDRESS_QUERY_FAILED);
        }
    }

    @PostMapping("/setDefault")
    @ResponseBody
    @RequireLoginWithToken
    public Result setDefaultAddress(@RequestParam Integer addressId, 
                                   HttpServletRequest request) {
        try {
            Integer userId = JwtUtil.getUserIdFromToken(request);
            addressService.setDefaultAddress(userId, addressId);
            return Result.success("默认地址设置成功");
        } catch (DataIntegrityViolationException e) {
            log.error("地址数据完整性错误: {}", e.getMessage());
            return Result.error(ResultCode.DATA_INTEGRITY_ERROR);
        }
    }
}

地址服务层业务逻辑

@Service
public class AddressService {
    
    @Autowired
    private AddressMapper addressMapper;
    
    public List<Address> getUserAddresses(Integer userId) {
        MPJLambdaWrapper<Address> wrapper = new MPJLambdaWrapper<Address>()
            .eq(Address::getUserId, userId)
            .eq(Address::getKeyong, 1)
            .orderByDesc(Address::getMoren)
            .orderByDesc(Address::getAddTime);
        
        return addressMapper.selectList(wrapper);
    }
    
    @Transactional
    public void setDefaultAddress(Integer userId, Integer addressId) {
        // 取消当前所有默认地址
        addressMapper.cancelAllDefaultAddresses(userId);
        
        // 设置新的默认地址
        Address address = new Address();
        address.setId(addressId);
        address.setMoren(1);
        addressMapper.updateById(address);
    }
}

用户地址管理

3. 订单流程管理系统

订单系统采用状态机模式管理订单生命周期,确保业务流程的严谨性。

订单状态转换服务

@Service
public class OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private OrderStatusService statusService;
    
    @Transactional
    public void processOrderStatus(Integer orderId, OrderStatus newStatus) {
        Order order = orderMapper.selectById(orderId);
        OrderStatus currentStatus = statusService.getStatusById(order.getOrderStatusId());
        
        if (!canTransition(currentStatus, newStatus)) {
            throw new BusinessException("订单状态转换不合法");
        }
        
        // 更新订单状态
        order.setOrderStatusId(newStatus.getId());
        orderMapper.updateById(order);
        
        // 记录状态变更日志
        recordStatusChange(orderId, currentStatus, newStatus);
    }
    
    private boolean canTransition(OrderStatus from, OrderStatus to) {
        // 定义状态转换规则
        Map<OrderStatus, List<OrderStatus>> transitionRules = new HashMap<>();
        transitionRules.put(OrderStatus.PENDING, 
            Arrays.asList(OrderStatus.CONFIRMED, OrderStatus.CANCELLED));
        transitionRules.put(OrderStatus.CONFIRMED, 
            Arrays.asList(OrderStatus.SHIPPED, OrderStatus.CANCELLED));
        // ... 更多状态转换规则
        
        return transitionRules.getOrDefault(from, Collections.emptyList())
                            .contains(to);
    }
}

订单查询优化实现

public Page<OrderDTO> getUserOrders(Integer userId, PageModel pageModel) {
    MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<Order>()
        .selectAll(Order.class)
        .selectAs(OrderStatus::getStatusName, OrderDTO::getStatusName)
        .selectAs(User::getUsername, OrderDTO::getUsername)
        .leftJoin(OrderStatus.class, OrderStatus::getId, Order::getOrderStatusId)
        .leftJoin(User.class, User::getId, Order::getUserId)
        .eq(Order::getUserId, userId)
        .orderByDesc(Order::getAddTime);
    
    return orderMapper.selectJoinPage(new Page<>(pageModel.getPage(), pageModel.getSize()), 
                                     OrderDTO.class, wrapper);
}

全局订单管理

4. 权限控制系统

基于RBAC模型的权限控制系统,支持细粒度的访问控制。

权限拦截器实现

@Component
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Autowired
    private UserService userService;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, Object handler) throws Exception {
        
        String token = request.getHeader("Authorization");
        if (StringUtils.isBlank(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        
        Integer userId = JwtUtil.getUserIdFromToken(token);
        User user = userService.getUserWithRoles(userId);
        
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        if (!hasPermission(user, requestURI, method)) {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            return false;
        }
        
        return true;
    }
    
    private boolean hasPermission(User user, String uri, String method) {
        for (Role role : user.getRoles()) {
            for (Permission permission : role.getPermissions()) {
                if (permission.matches(uri, method)) {
                    return true;
                }
            }
        }
        return false;
    }
}

实体模型设计

系统采用领域驱动设计(DDD)理念,核心实体模型设计体现了业务领域的完整性。

用户聚合根设计

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
    private String phone;
    private Integer status;
    private Timestamp addTime;
    
    // 值对象集合
    private List<Address> addresses;
    private List<Order> orders;
    private Set<Role> roles;
    
    public boolean canPlaceOrder() {
        return status == 1 && hasValidAddress();
    }
    
    private boolean hasValidAddress() {
        return addresses.stream()
                       .anyMatch(addr -> addr.getKeyong() == 1);
    }
}

商品领域服务

@Service
public class ProductDomainService {
    
    public ProductExperience createProductExperience(Product product, User user) {
        ProductExperience experience = new ProductExperience();
        experience.setProductId(product.getId());
        experience.setUserId(user.getId());
        experience.setStartTime(new Timestamp(System.currentTimeMillis()));
        experience.setExperienceData(buildInitialExperienceData(product));
        
        // 验证用户体验权限
        if (!user.hasExperiencePermission(product.getCategory())) {
            throw new BusinessException("用户无体验权限");
        }
        
        return experience;
    }
}

功能展望与优化

基于当前系统架构,提出以下优化方向:

1. 微服务架构改造

将单体应用拆分为商品服务、订单服务、用户服务等独立微服务,提升系统可扩展性。

服务拆分方案

// 商品服务独立部署
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServiceApplication.class, args);
    }
}

// 使用Feign客户端进行服务间调用
@FeignClient(name = "order-service", path = "/api/orders")
public interface OrderServiceClient {
    @PostMapping("/create")
    OrderDTO createOrder(@RequestBody OrderCreateRequest request);
}

2. 引入Elasticsearch搜索引擎

提升商品搜索性能和相关性排序能力。

搜索服务集成

@Service
public class ProductSearchService {
    
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    
    public Page<ProductDocument> searchProducts(ProductSearchRequest request) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        
        // 构建复杂查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.matchQuery("name", request.getKeyword()));
        boolQuery.filter(QueryBuilders.rangeQuery("price")
                          .gte(request.getMinPrice()).lte(request.getMaxPrice()));
        
        queryBuilder.with
本文关键词
VueSpring Boot在线商品体验平台源码解析电商平台

上下篇

上一篇
没有更多文章
下一篇
没有更多文章