# intelligence-mall **Repository Path**: wu-jingyu-666/intelligence-mail ## Basic Information - **Project Name**: intelligence-mall - **Description**: 智能商城管理 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-10 - **Last Updated**: 2025-09-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 智能商城管理系统 ## 一,系统介绍 ### 1.1项目背景 由于商城管理系统覆盖范围广,而且用的技术比较多,可以更全面的学习java相关知识,以及如何处理遇到的问题,恰逢现在ai的爆火,所以我决定使用java+ai的方式来从0到1设计一个智能商城管理系统 ### 1.2 系统架构 该系统分为管理端和用户端,由于体量比较小,管理端和用户端都是网页版,适合新手学习的一款项目,本系统分成3个部分更好管理,小程序端还暂未开放 Vue请看我的仓库,后续主要模块我都会列出来 ### 1.3 技术选型 后端:spring boot,mybatis plus,mysql,maven,jwt,spring secrety,阿里云oss 前端:vue3,vue Router,Pinia ,Element Plus 开发工具: idea,VScode,git ## 二,项目结构 ### 2.1 intelligence-common(通用模块) constant包,常量包,用于设置一些常量不用重复定义 context包,线程包,用于获取当前线程的用户id exception包,异常包,用于抛出自定义异常,返回给前端 result包,结果包,用于返回结果给前端 ### 2.2 intelligence-domain(领域模型模块) Product包,关于商品的一系列实体类(entity),前端返回类(dto),返回前端类(vo) User包,关于员工,用户的一系列实体类(entity),前端返回类(dto),返回前端类(vo) ### 2.3 intelligence-system(主应用模块) config包,一些基础配置,里面存放基础配置类 controller包,控制层,用于控制用户的一系列行为 handle包,处理包,用于处理一些异常 filter包,过滤器,用于筛选满足条件的接口 mapper包,用于处理后端和数据库端的数据关系 properities包,用于配置一些不想对外人开放的类 service包,服务层,实现具体的逻辑 utils包,工具包,一些需要用到的工具的设计 ## 三,数据库结构 ### 3.1 `用户表 (users)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :----------- | :-------------------- | :--------- | | `userId` | varchar(20) | 用户唯一标识 | 主键 | | `userName` | varchar(30) | 用户姓名 | 非空 | | `sex` | char(1) | 性别(0男,1女,2保密) | 非空 | | `password` | varchar(200) | 加密后的密码 | 非空 | | `phone` | varchar(11) | 手机号码 | 唯一,非空 | | `isEnable` | char(1) | 是否启用(1启用,0禁用) | 默认'1' | | `isCustomer` | char(1) | 是否客户(1是,0否) | 默认'0' | | `addUserId` | varchar(20) | 创建此用户的用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者的用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.2 `角色表 (roles)` | 字段名 | 类型 | 说明 | 约束 | | :---------------- | :----------- | :-------------------- | :--------- | | `roleId` | varchar(20) | 角色唯一标识 | 主键 | | `roleName` | varchar(50) | 角色名称 | 唯一,非空 | | `roleDescription` | varchar(200) | 角色描述 | 可空 | | `isEnable` | char(1) | 是否启用(1启用,0禁用) | 默认'1' | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.3 `权限表 (permissions)` | 字段名 | 类型 | 说明 | 约束 | | :---------------------- | :----------- | :---------------------- | :--------- | | `permissionId` | varchar(20) | 权限唯一标识 | 主键 | | `permissionName` | varchar(50) | 权限名称 | 非空 | | `permissionCode` | varchar(50) | 权限代码(如:view,add等) | 唯一,非空 | | `permissionDescription` | varchar(200) | 权限描述 | 可空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.4 `模块表 (module)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--------- | | `moduleID` | varchar(20) | 模块唯一标识 | 主键 | | `moduleName` | varchar(50) | 模块名称 | 唯一,非空 | | `order` | int | 显示排序顺序 | 非空 | | `addUserId` | varchar(20) | 创建者用户ID | 可空 | | `addDate` | datetime | 创建时间 | 可空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.5 `菜单表 (menu)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :----------- | :--------------- | :--------- | | `menuId` | varchar(20) | 菜单唯一标识 | 主键 | | `moduleId` | varchar(20) | 所属模块ID | 外键,非空 | | `menuName` | varchar(50) | 菜单名称 | 唯一,非空 | | `order` | int | 菜单显示顺序 | 非空 | | `path` | varchar(100) | 菜单路由路径 | 非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.6 `角色表 roles)` | 字段名 | 类型 | 说明 | 约束 | | :---------------- | :----------- | :-------------------- | :--------- | | `roleId` | varchar(20) | 角色唯一标识 | 主键 | | `roleName` | varchar(50) | 角色名称 | 唯一,非空 | | `roleDescription` | varchar(200) | 角色描述 | 可空 | | `isEnable` | char(1) | 是否启用(1启用,0禁用) | 默认'1' | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.7 `用户-角色关联表 (user_roles)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--------- | | `id` | int | 关联记录唯一标识 | 主键,自增 | | `userId` | varchar(20) | 用户ID | 外键,非空 | | `roleId` | varchar(20) | 角色ID | 外键,非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.8 `角色-权限关联表 (role_permissions)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--------- | | `id` | int | 关联记录唯一标识 | 主键,自增 | | `roleId` | varchar(20) | 角色ID | 外键,非空 | | `menuId` | varchar(20) | 菜单ID | 外键,非空 | | `permissionId` | varchar(20) | 权限ID | 外键,非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.9 `商品表 (products)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :------------ | :-------------------- | :--------- | | `productId` | varchar(20) | 商品唯一标识 | 主键 | | `productName` | varchar(100) | 商品名称 | 非空 | | `image` | varchar(200) | 商品图片URL | 非空 | | `categoryId` | varchar(20) | 分类ID | 外键,非空 | | `description` | text | 商品描述 | 可空 | | `brandId` | varchar(20) | 品牌ID | 外键,可空 | | `price` | decimal(10,2) | 商品价格 | 非空 | | `stock` | int | 库存数量 | 非空 | | `isOnSale` | char(1) | 是否上架(1上架,0下架) | 默认'1' | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.10 `商品分类表 (product_categories)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--- | | `categoryId` | varchar(20) | 分类唯一标识 | 主键 | | `categoryName` | varchar(50) | 分类名称 | 非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.11 `品牌表 (brands)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--------- | | `brandId` | varchar(20) | 品牌唯一标识 | 主键 | | `brandName` | varchar(50) | 品牌名称 | 唯一,非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.12 `品牌-分类关联表 (brand_categories)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :--------------- | :--------- | | `id` | int | 关联记录唯一标识 | 主键,自增 | | `brandId` | varchar(20) | 品牌ID | 外键,非空 | | `categoryId` | varchar(20) | 分类ID | 外键,非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ### 3.13 `购物车表 (shopping_cart)` | 字段名 | 类型 | 说明 | 约束 | | :------------- | :---------- | :----------------- | :--------- | | `cartId` | varchar(20) | 购物车记录唯一标识 | 主键 | | `userId` | varchar(20) | 用户ID | 外键,非空 | | `productId` | varchar(20) | 商品ID | 外键,非空 | | `quantity` | int | 购买数量 | 非空 | | `addUserId` | varchar(20) | 创建者用户ID | 非空 | | `addDate` | datetime | 创建时间 | 非空 | | `updateUserId` | varchar(20) | 最后更新者用户ID | 可空 | | `updateDate` | datetime | 最后更新时间 | 可空 | ## 四,接口设计 ### 1.管理端 #### 1.1 用户相关接口 #### 1.2 商品管理接口 #### 1.3 品牌管理接口 #### 1.4 分类管理接口 #### 1.5 权限管理接口 #### 1.6 路由管理接口 ### 2.用户端 ## 五,详细配置 ### 5.1 jwt相关配置 在配置之前应该知道jwt是什么:它是用于验证用户是否非法直接进入到他没有登录的时候就看到的他不应该看到的界面,此时就会强制要求用户必须登录才能看到该界面,防止发出非法请求导致数据库有脏数据 如果要配置jwt,首先需要在父类maven还有需要用到的子类中导入jwt,然后创建生成jwt和解析jwt的工具类`JWTUtils` ``` xml 0.12.3 io.jsonwebtoken jjwt ${jjwt.version} ``` ``` java public class JWTUtils { /** * 生成JWT * 使用HS256算法 * * @param secretKey jwt秘钥(至少256位/32字节) * @param ttlMillis jwt过期时间(毫秒) * @param claims 设置的自定义claims * @return JWT字符串 */ public static String createJWT(String secretKey, long ttlMillis, Map claims) { // 1. 创建安全的签名密钥 Key key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); // 2. 计算过期时间 Date now = new Date(); Date expiryDate = new Date(now.getTime() + ttlMillis); // 3. 构建JWT return Jwts.builder() .claims(claims) // 设置自定义claims .issuedAt(now) // 签发时间 .expiration(expiryDate) // 过期时间 .signWith(key) // 签名 .compact(); } /** * Token解析 * * @param secretKey jwt秘钥(必须与生成时使用的相同) * @param token 要解析的JWT字符串 * @return Claims对象 * @throws io.jsonwebtoken.JwtException 如果token无效或过期 */ public static Claims parseJWT(String secretKey, String token) { // 1. 创建安全的签名密钥 SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); // 2. 解析JWT return Jwts.parser() .verifyWith(key) // 设置验证密钥 .build() .parseSignedClaims(token) // 解析已签名的claims .getPayload(); // 获取claims主体 } } ``` 然后就是一些秘钥相关变量不便于展示在页面就需要配置在yaml文件中或者系统环境变量中,创建一个配置类`JwtProperties` ``` java @Component @ConfigurationProperties(prefix = "mall.jwt") //在yaml文件中自定义配置 @Data public class JwtProperties { /** * 管理端员工生成jwt令牌相关配置 */ private String adminSecretKey; private long adminTtl; private String adminTokenName; /** * 用户端微信用户生成jwt令牌相关配置 */ private String userSecretKey; private long userTtl; private String userTokenName; } ``` ``` yaml mall: jwt: # 设置jwt签名加密时使用的秘钥 admin-secret-key: adminadminadminadminadminadminadminadmin # 设置jwt过期时间 admin-ttl: 86400000 #设置前端传递过来的令牌名称 admin-token-name: Authorization user-secret-key: useruseruseruseruseruseruseruseruseruser user-ttl: 3600000 user-token-name: Authorization ``` 这是最主要的2个配置,然后就是在用户登录的时候生成jwt使用 ``` java /** * 员工登录 * */ public UserLoginVo login(UserLoginDto userLoginDto) throws Exception { UserDetail userDetail = getUserDetail(userLoginDto); Map claims = new HashMap<>(); //把userId存进claims中 claims.put("userId", userDetail.getUsername()); //用刚刚的工具类生成jwt String token = JWTUtils.createJWT( jwtProperties.getAdminSecretKey(), jwtProperties.getAdminTtl(), claims ); return UserLoginVo.builder() .userId(userDetail.getUsername()) .userName(userDetail.getUserName()) .token(token) //传递token .build(); } ``` 那怎么让传递的token起作用呢,其实只需要设置一个过滤器或者拦截器在每次前端发送请求的时候解析验证一下,判断是否为空或者过期就行了,由于后面有spring secrity需要结合的一起使用我在后面展示 ### 5.2 阿里oss相关配置 同样在配置之前应该知道它是什么:它是用于保存一些图片或者其他的静态资源,可以存在阿里云oss中,不需要存在本地占用内存,而且配置繁琐较为复杂,而阿里oss只需要一个配置类就可以在想要上传图片或者其他静态资源时调用就可以了 首先在子类maven中导入阿里oss ``` xml com.aliyun.oss aliyun-sdk-oss 3.17.4 ``` ### 5.3 spring secrity配置