Quellcode durchsuchen

feat(mall): 添加底部导航菜单配置功能并实现购物车操作

- 移除登录参数校验注解,固定授权类型为密码模式
- 新增底部导航菜单项相关实体、业务对象、视图对象及映射器
- 实现底部导航菜单项服务接口及业务逻辑处理
- 新增全局导航配置相关实体、业务对象、视图对象及映射器
- 实现导航配置服务接口,包含查询、保存、创建默认配置等功能
- 添加导航配置控制器,提供获取当前配置、详情信息和保存接口
- 在商品模块中新增购物车相关操作接口
- 实现购物车商品添加、更新、删除和查询功能
- 添加协议供货商品列表查询接口
hurx vor 1 Monat
Ursprung
Commit
0f4bad8446
16 geänderte Dateien mit 830 neuen und 8 gelöschten Zeilen
  1. 2 2
      ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java
  2. 0 2
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java
  3. 59 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/NavigationConfigController.java
  4. 60 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MBottomNavItems.java
  5. 63 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MNavigationConfig.java
  6. 60 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MBottomNavItemsBo.java
  7. 72 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MNavigationConfigBo.java
  8. 57 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MBottomNavItemsVo.java
  9. 65 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MNavigationConfigVo.java
  10. 14 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MBottomNavItemsMapper.java
  11. 14 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MNavigationConfigMapper.java
  12. 34 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMBottomNavItemsService.java
  13. 38 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMNavigationConfigService.java
  14. 75 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MBottomNavItemsServiceImpl.java
  15. 128 0
      ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MNavigationConfigServiceImpl.java
  16. 89 4
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/mini/MiniProductController.java

+ 2 - 2
ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java

@@ -238,8 +238,8 @@ public class TokenController {
         LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
         ValidatorUtils.validate(loginBody);
         // 授权类型和客户端id
-        String clientId = loginBody.getClientId();
-        String grantType = loginBody.getGrantType();
+        String clientId = "e5cd7e4891bf95d1d19206ce24a7b32e";
+        String grantType = "password";
         RemoteClientVo clientVo = remoteClientService.queryByClientId(clientId);
 
         // 查询不到 client 或 client 内不包含 grantType

+ 0 - 2
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java

@@ -16,13 +16,11 @@ public class LoginBody {
     /**
      * 客户端id
      */
-    @NotBlank(message = "{auth.clientid.not.blank}")
     private String clientId;
 
     /**
      * 授权类型
      */
-    @NotBlank(message = "{auth.grant.type.not.blank}")
     private String grantType;
 
     /**

+ 59 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/controller/NavigationConfigController.java

@@ -0,0 +1,59 @@
+package org.dromara.mall.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.mall.domain.bo.MNavigationConfigBo;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+import org.dromara.mall.service.IMNavigationConfigService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 底部菜单导航配置
+ * 前端访问路由地址为:/mall/navigationConfig
+ *
+ * @author LionLi
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/navigationConfig")
+public class NavigationConfigController extends BaseController {
+
+    private final IMNavigationConfigService navigationConfigService;
+
+    /**
+     * 获取当前导航配置
+     */
+    @GetMapping("/current")
+    public R<MNavigationConfigVo> getCurrent() {
+        return R.ok(navigationConfigService.getCurrentConfig());
+    }
+
+    /**
+     * 获取导航配置详细信息
+     *
+     * @param id 主键
+     */
+    @GetMapping("/{id}")
+    public R<MNavigationConfigVo> getInfo(@NotNull(message = "主键不能为空")
+                                          @PathVariable("id") Long id) {
+        return R.ok(navigationConfigService.queryById(id));
+    }
+
+    /**
+     * 保存导航配置
+     */
+    @Log(title = "保存导航配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/save")
+    public R<Void> save(@Validated @RequestBody MNavigationConfigBo bo) {
+        return toAjax(navigationConfigService.saveConfig(bo));
+    }
+
+}
+

+ 60 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MBottomNavItems.java

@@ -0,0 +1,60 @@
+package org.dromara.mall.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.tenant.core.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 底部菜单-底部导航菜单项对象 m_bottom_nav_items
+ *
+ * @author
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("m_bottom_nav_items")
+public class MBottomNavItems extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 外键,关联 m_navigation_config.id
+     */
+    private Long configId;
+
+    /**
+     * 排序序号
+     */
+    private Integer orderIndex;
+
+    /**
+     * 正常状态图标路径
+     */
+    private String iconNormal;
+
+    /**
+     * 选中状态图标路径
+     */
+    private String iconSelected;
+
+    /**
+     * 显示文字
+     */
+    private String text;
+
+    /**
+     * 跳转链接
+     */
+    private String linkUrl;
+
+}

+ 63 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/MNavigationConfig.java

@@ -0,0 +1,63 @@
+package org.dromara.mall.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.tenant.core.TenantEntity;
+
+import java.io.Serial;
+
+/**
+ * 底部菜单-全局导航配置对象 m_navigation_config
+ *
+ * @author
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("m_navigation_config")
+public class MNavigationConfig extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 顶部文字颜色
+     */
+    private String topNavTextColor;
+
+    /**
+     * 顶部背景颜色
+     */
+    private String topNavBgColor;
+
+    /**
+     * 底部背景颜色
+     */
+    private String bottomNavBgColor;
+
+    /**
+     * 底部文字颜色
+     */
+    private String bottomNavTextColor;
+
+    /**
+     * 底部选中项颜色
+     */
+    private String bottomNavSelectedColor;
+
+    /**
+     * 导航样式:仅图标 / 仅文字 / 图标+文字
+     */
+    private String navStyle;
+
+    private String status;
+
+
+}

+ 60 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MBottomNavItemsBo.java

@@ -0,0 +1,60 @@
+package org.dromara.mall.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.mall.domain.MBottomNavItems;
+
+/**
+ * 底部菜单-底部导航菜单项业务对象 m_bottom_nav_items
+ *
+ * @author LionLi
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MBottomNavItems.class, reverseConvertGenerate = false)
+public class MBottomNavItemsBo extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 外键,关联 m_navigation_config.id
+     */
+    // @NotNull(message = "外键不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long configId;
+
+    /**
+     * 排序序号
+     */
+    // @NotNull(message = "排序序号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer orderIndex;
+
+    /**
+     * 正常状态图标路径
+     */
+    // @NotBlank(message = "正常状态图标路径不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String iconNormal;
+
+    /**
+     * 选中状态图标路径
+     */
+    // @NotBlank(message = "选中状态图标路径不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String iconSelected;
+
+    /**
+     * 显示文字
+     */
+    // @NotBlank(message = "显示文字不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String text;
+
+    /**
+     * 跳转链接
+     */
+    // @NotBlank(message = "跳转链接不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String linkUrl;
+
+}

+ 72 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/bo/MNavigationConfigBo.java

@@ -0,0 +1,72 @@
+package org.dromara.mall.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.mall.domain.MNavigationConfig;
+
+import java.util.List;
+
+/**
+ * 底部菜单-全局导航配置业务对象 m_navigation_config
+ *
+ * @author LionLi
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MNavigationConfig.class, reverseConvertGenerate = false)
+public class MNavigationConfigBo extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 顶部文字颜色
+     */
+    @NotBlank(message = "顶部文字颜色不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String topNavTextColor;
+
+    /**
+     * 顶部背景颜色
+     */
+    @NotBlank(message = "顶部背景颜色不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String topNavBgColor;
+
+    /**
+     * 底部背景颜色
+     */
+    @NotBlank(message = "底部背景颜色不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String bottomNavBgColor;
+
+    /**
+     * 底部文字颜色
+     */
+    @NotBlank(message = "底部文字颜色不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String bottomNavTextColor;
+
+    /**
+     * 底部选中项颜色
+     */
+    @NotBlank(message = "底部选中项颜色不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String bottomNavSelectedColor;
+
+    /**
+     * 导航样式:仅图标 / 仅文字 / 图标+文字
+     */
+    @NotBlank(message = "导航样式不能为空", groups = {AddGroup.class, EditGroup.class})
+    private String navStyle;
+
+    private String status;
+
+    /**
+     * 导航菜单项列表
+     */
+    private List<MBottomNavItemsBo> navItems;
+
+}

+ 57 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MBottomNavItemsVo.java

@@ -0,0 +1,57 @@
+package org.dromara.mall.domain.vo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.mall.domain.MBottomNavItems;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 底部菜单-底部导航菜单项视图对象 m_bottom_nav_items
+ *
+ * @author LionLi
+ */
+@Data
+@AutoMapper(target = MBottomNavItems.class)
+public class MBottomNavItemsVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 外键,关联 m_navigation_config.id
+     */
+    private Long configId;
+
+    /**
+     * 排序序号
+     */
+    private Integer orderIndex;
+
+    /**
+     * 正常状态图标路径
+     */
+    private String iconNormal;
+
+    /**
+     * 选中状态图标路径
+     */
+    private String iconSelected;
+
+    /**
+     * 显示文字
+     */
+    private String text;
+
+    /**
+     * 跳转链接
+     */
+    private String linkUrl;
+
+}

+ 65 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/domain/vo/MNavigationConfigVo.java

@@ -0,0 +1,65 @@
+package org.dromara.mall.domain.vo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.mall.domain.MNavigationConfig;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 底部菜单-全局导航配置视图对象 m_navigation_config
+ *
+ * @author
+ */
+@Data
+@AutoMapper(target = MNavigationConfig.class)
+public class MNavigationConfigVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 顶部文字颜色
+     */
+    private String topNavTextColor;
+
+    /**
+     * 顶部背景颜色
+     */
+    private String topNavBgColor;
+
+    /**
+     * 底部背景颜色
+     */
+    private String bottomNavBgColor;
+
+    /**
+     * 底部文字颜色
+     */
+    private String bottomNavTextColor;
+
+    /**
+     * 底部选中项颜色
+     */
+    private String bottomNavSelectedColor;
+
+    /**
+     * 导航样式:仅图标 / 仅文字 / 图标+文字
+     */
+    private String navStyle;
+
+    private String status;
+
+    /**
+     * 导航菜单项列表
+     */
+    private List<MBottomNavItemsVo> navItems;
+
+}

+ 14 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MBottomNavItemsMapper.java

@@ -0,0 +1,14 @@
+package org.dromara.mall.mapper;
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.mall.domain.MBottomNavItems;
+import org.dromara.mall.domain.vo.MBottomNavItemsVo;
+
+/**
+ * 底部菜单-底部导航菜单项Mapper接口
+ *
+ * @author LionLi
+ */
+public interface MBottomNavItemsMapper extends BaseMapperPlus<MBottomNavItems, MBottomNavItemsVo> {
+
+}

+ 14 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/mapper/MNavigationConfigMapper.java

@@ -0,0 +1,14 @@
+package org.dromara.mall.mapper;
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.mall.domain.MNavigationConfig;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+
+/**
+ * 底部菜单-全局导航配置Mapper接口
+ *
+ * @author LionLi
+ */
+public interface MNavigationConfigMapper extends BaseMapperPlus<MNavigationConfig, MNavigationConfigVo> {
+
+}

+ 34 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMBottomNavItemsService.java

@@ -0,0 +1,34 @@
+package org.dromara.mall.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.mall.domain.MBottomNavItems;
+import org.dromara.mall.domain.bo.MBottomNavItemsBo;
+import org.dromara.mall.domain.vo.MBottomNavItemsVo;
+
+import java.util.List;
+
+/**
+ * 底部菜单-底部导航菜单项Service接口
+ *
+ * @author LionLi
+ */
+public interface IMBottomNavItemsService extends IService<MBottomNavItems> {
+
+    /**
+     * 根据配置ID查询导航菜单项列表
+     *
+     * @param configId 配置ID
+     * @return 导航菜单项列表
+     */
+    List<MBottomNavItemsVo> queryListByConfigId(Long configId);
+
+    /**
+     * 批量保存菜单项
+     *
+     * @param configId 配置ID
+     * @param items    菜单项列表
+     * @return 是否保存成功
+     */
+    Boolean saveBatchByConfigId(Long configId, List<MBottomNavItemsBo> items);
+
+}

+ 38 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/IMNavigationConfigService.java

@@ -0,0 +1,38 @@
+package org.dromara.mall.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.mall.domain.MNavigationConfig;
+import org.dromara.mall.domain.bo.MNavigationConfigBo;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+
+/**
+ * 底部菜单-全局导航配置Service接口
+ *
+ * @author LionLi
+ */
+public interface IMNavigationConfigService extends IService<MNavigationConfig> {
+
+    /**
+     * 查询导航配置详细信息(包含菜单项)
+     *
+     * @param id 主键
+     * @return 导航配置详细信息
+     */
+    MNavigationConfigVo queryById(Long id);
+
+    /**
+     * 获取当前导航配置(如果没有则创建默认配置)
+     *
+     * @return 导航配置详细信息
+     */
+    MNavigationConfigVo getCurrentConfig();
+
+    /**
+     * 保存导航配置(包括配置和菜单项)
+     *
+     * @param bo 导航配置业务对象
+     * @return 是否保存成功
+     */
+    Boolean saveConfig(MNavigationConfigBo bo);
+
+}

+ 75 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MBottomNavItemsServiceImpl.java

@@ -0,0 +1,75 @@
+package org.dromara.mall.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.mall.domain.MBottomNavItems;
+import org.dromara.mall.domain.bo.MBottomNavItemsBo;
+import org.dromara.mall.domain.vo.MBottomNavItemsVo;
+import org.dromara.mall.mapper.MBottomNavItemsMapper;
+import org.dromara.mall.service.IMBottomNavItemsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 底部菜单-底部导航菜单项Service业务层处理
+ *
+ * @author LionLi
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MBottomNavItemsServiceImpl extends ServiceImpl<MBottomNavItemsMapper, MBottomNavItems> implements IMBottomNavItemsService {
+
+    private final MBottomNavItemsMapper baseMapper;
+
+    /**
+     * 根据配置ID查询导航菜单项列表
+     *
+     * @param configId 配置ID
+     * @return 导航菜单项列表
+     */
+    @Override
+    public List<MBottomNavItemsVo> queryListByConfigId(Long configId) {
+        LambdaQueryWrapper<MBottomNavItems> lqw = Wrappers.lambdaQuery();
+        lqw.eq(MBottomNavItems::getConfigId, configId);
+        lqw.orderByAsc(MBottomNavItems::getOrderIndex);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    /**
+     * 批量保存菜单项
+     *
+     * @param configId 配置ID
+     * @param items    菜单项列表
+     * @return 是否保存成功
+     */
+    @Override
+    public Boolean saveBatchByConfigId(Long configId, List<MBottomNavItemsBo> items) {
+        // 先删除旧的菜单项
+        LambdaQueryWrapper<MBottomNavItems> lqw = Wrappers.lambdaQuery();
+        lqw.eq(MBottomNavItems::getConfigId, configId);
+        baseMapper.delete(lqw);
+
+        // 保存新的菜单项
+        if (items != null && !items.isEmpty()) {
+            List<MBottomNavItems> navItems = items.stream()
+                .map(item -> {
+                    MBottomNavItems navItem = MapstructUtils.convert(item, MBottomNavItems.class);
+                    navItem.setConfigId(configId);
+                    return navItem;
+                })
+                .collect(Collectors.toList());
+
+            return this.saveBatch(navItems);
+        }
+
+        return true;
+    }
+
+}

+ 128 - 0
ruoyi-modules/ruoyi-mall/src/main/java/org/dromara/mall/service/impl/MNavigationConfigServiceImpl.java

@@ -0,0 +1,128 @@
+package org.dromara.mall.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.mall.domain.MNavigationConfig;
+import org.dromara.mall.domain.bo.MNavigationConfigBo;
+import org.dromara.mall.domain.vo.MNavigationConfigVo;
+import org.dromara.mall.mapper.MNavigationConfigMapper;
+import org.dromara.mall.service.IMBottomNavItemsService;
+import org.dromara.mall.service.IMNavigationConfigService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 底部菜单-全局导航配置Service业务层处理
+ *
+ * @author LionLi
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MNavigationConfigServiceImpl extends ServiceImpl<MNavigationConfigMapper, MNavigationConfig> implements IMNavigationConfigService {
+
+    private final MNavigationConfigMapper baseMapper;
+    private final IMBottomNavItemsService bottomNavItemsService;
+
+    /**
+     * 查询导航配置详细信息(包含菜单项)
+     *
+     * @param id 主键
+     * @return 导航配置详细信息
+     */
+    @Override
+    public MNavigationConfigVo queryById(Long id) {
+        MNavigationConfigVo vo = baseMapper.selectVoById(id);
+        if (vo != null) {
+            // 查询关联的菜单项
+            vo.setNavItems(bottomNavItemsService.queryListByConfigId(id));
+        }
+        return vo;
+    }
+
+    /**
+     * 获取当前导航配置(如果没有则创建默认配置)
+     *
+     * @return 导航配置详细信息
+     */
+    @Override
+    public MNavigationConfigVo getCurrentConfig() {
+        // 查询是否有配置
+        LambdaQueryWrapper<MNavigationConfig> lqw = Wrappers.lambdaQuery();
+        lqw.last("LIMIT 1");
+        MNavigationConfig config = baseMapper.selectOne(lqw);
+
+        if (config == null) {
+            // 如果没有配置,创建默认配置
+            config = createDefaultConfig();
+        }
+
+        MNavigationConfigVo vo = baseMapper.selectVoById(config.getId());
+        if (vo != null) {
+            // 查询关联的菜单项
+            vo.setNavItems(bottomNavItemsService.queryListByConfigId(vo.getId()));
+        }
+
+        return vo;
+    }
+
+    /**
+     * 保存导航配置(包括配置和菜单项)
+     *
+     * @param bo 导航配置业务对象
+     * @return 是否保存成功
+     */
+    @Override
+    public Boolean saveConfig(MNavigationConfigBo bo) {
+        MNavigationConfig update = MapstructUtils.convert(bo, MNavigationConfig.class);
+        validEntityBeforeSave(update);
+
+        boolean flag;
+        if (update.getId() != null) {
+            // 更新
+            flag = baseMapper.updateById(update) > 0;
+        } else {
+            // 新增
+            flag = baseMapper.insert(update) > 0;
+            if (flag) {
+                bo.setId(update.getId());
+            }
+        }
+
+        // 保存菜单项
+        if (flag && bo.getNavItems() != null && !bo.getNavItems().isEmpty()) {
+            // 转换navItems从Bo到Vo再到普通的item进行保存
+            // 这里需要将List<MBottomNavItemsBo>转换为List<MBottomNavItemsBo>
+            bottomNavItemsService.saveBatchByConfigId(update.getId() != null ? update.getId() : bo.getId(), bo.getNavItems());
+        }
+
+        return flag;
+    }
+
+    /**
+     * 创建默认配置
+     */
+    private MNavigationConfig createDefaultConfig() {
+        MNavigationConfig config = new MNavigationConfig();
+        config.setTopNavTextColor("black");
+        config.setTopNavBgColor("#FFFFFF");
+        config.setBottomNavBgColor("#FFFFFF");
+        config.setBottomNavTextColor("#666666");
+        config.setBottomNavSelectedColor("#00CC00");
+        config.setNavStyle("icon_text");
+
+        baseMapper.insert(config);
+        return config;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(MNavigationConfig entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+}

+ 89 - 4
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/mini/MiniProductController.java

@@ -1,19 +1,24 @@
 package org.dromara.product.controller.mini;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.product.domain.ProductShoppingCart;
 import org.dromara.product.domain.bo.PcProductBo;
 import org.dromara.product.domain.bo.ProductBaseBo;
+import org.dromara.product.domain.bo.ProductShoppingCartBo;
 import org.dromara.product.domain.vo.PcProductVo;
 import org.dromara.product.domain.vo.ProductBaseVo;
 import org.dromara.product.service.IProductBaseService;
+import org.dromara.product.service.IProductShoppingCartService;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * 首页
@@ -30,6 +35,9 @@ public class MiniProductController {
     //商品
     private final IProductBaseService productBaseService;
 
+    //购物车
+    private final IProductShoppingCartService productShoppingCartService;
+
     /**
      * 获取客户商品池的商品
      */
@@ -57,4 +65,81 @@ public class MiniProductController {
     public R<ProductBaseVo> getProductDetail(@PathVariable Long productId) {
         return R.ok(productBaseService.queryById(productId));
     }
+
+    /**
+     * mini将商品添加到购物车
+     */
+    @PostMapping("/addProductShoppingCart")
+    public R addProductShoppingCart(@RequestBody ProductShoppingCartBo bo) {
+        Long userId = LoginHelper.getUserId();
+        //校验是否存在库存和商品是否上架
+        ProductBaseVo productBaseVo = productBaseService.queryById(bo.getProductId());
+        if (!Objects.equals(productBaseVo.getProductStatus(), 1)) {
+            return R.fail("商品已下架");
+        }
+        if (productBaseVo.getTotalInventory() - bo.getProductNum() < 0) {
+            return R.fail("商品库存不足");
+        }
+        //查看是否存在同一个商品
+        ProductShoppingCart one = productShoppingCartService.getOne(Wrappers.lambdaQuery(ProductShoppingCart.class)
+            .eq(ProductShoppingCart::getUserId, userId)
+            .eq(ProductShoppingCart::getProductId, bo.getProductId())
+        );
+        if (one != null) {
+            one.setProductNum(one.getProductNum() + bo.getProductNum());
+            productShoppingCartService.updateById(one);
+            return R.ok();
+        } else {
+            bo.setUserId(userId);
+            productShoppingCartService.insertByBo(bo);
+        }
+        return R.ok();
+    }
+
+    /**
+     * mini更新购物车商品数量
+     * */
+    @PostMapping("/updateProductShoppingCart")
+    public R updateProductShoppingCart(@RequestBody ProductShoppingCartBo bo) {
+        productShoppingCartService.update(Wrappers.lambdaUpdate(ProductShoppingCart.class)
+            .eq(ProductShoppingCart::getUserId, LoginHelper.getUserId())
+            .eq(ProductShoppingCart::getProductId, bo.getProductId())
+            .set(ProductShoppingCart::getProductNum, bo.getProductNum())
+        );
+        return R.ok();
+    }
+
+    /**
+     * mini删除购物车商品
+     */
+    @DeleteMapping("/deleteProductShoppingCart/{ids}")
+    public R deleteProductShoppingCart(@PathVariable Long[] ids) {
+        productShoppingCartService.removeByIds(Arrays.asList(ids));
+        return R.ok();
+    }
+
+    /**
+     * mini查询购物车的商品
+     */
+    @GetMapping("/getProductShoppingCartPage")
+    public TableDataInfo<PcProductVo> getProductShoppingCartPage(String id, PageQuery pageQuery) {
+        return productBaseService.getProductShoppingCartPage(id, LoginHelper.getUserId(), pageQuery);
+    }
+
+    /**
+     * mini获取购物车商品未失效的商品数量
+     */
+    @GetMapping("/getProductShoppingCartCount")
+    public R getProductShoppingCartCount() {
+        return R.ok(productBaseService.getProductShoppingCartCount(LoginHelper.getUserId(), 0));
+    }
+
+    /**
+     *mini 协议供货商品列表
+     */
+    @GetMapping("/getAgreementSupplyProductPage")
+    public TableDataInfo<PcProductVo> getProtocolProductsPage(PcProductBo bo, PageQuery pageQuery) {
+        bo.setCustomerId(LoginHelper.getLoginUser().getCustomerId());
+        return productBaseService.getProtocolProductsPage(bo, pageQuery);
+    }
 }