mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-18 17:38:48 +08:00
feat :组件分类
This commit is contained in:
parent
e0a44fd727
commit
83438b76dd
194
ruoyi-site/ruoyi-h5/README_COMPONENT.md
Normal file
194
ruoyi-site/ruoyi-h5/README_COMPONENT.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# H5 组件库系统开发完成
|
||||||
|
|
||||||
|
## 开发时间
|
||||||
|
2026-03-06
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
实现了一个完整的 H5 组件库系统,支持组件分类管理、标签检索、快速应用等功能。
|
||||||
|
|
||||||
|
## 已完成的功能
|
||||||
|
|
||||||
|
### 1. 数据库设计 (5 张表)
|
||||||
|
- **h5_component**: 组件表 - 存储组件基本信息和配置数据
|
||||||
|
- **h5_component_category**: 分类表 - 存储两级分类结构
|
||||||
|
- **h5_component_category_rel**: 组件分类关联表 - 组件与分类的多对多关系
|
||||||
|
- **h5_tag**: 标签表 - 存储标签信息
|
||||||
|
- **h5_component_tag_rel**: 组件标签关联表 - 组件与标签的多对多关系
|
||||||
|
|
||||||
|
### 2. 核心功能
|
||||||
|
|
||||||
|
#### 组件管理
|
||||||
|
- ✅ 组件 CRUD 操作
|
||||||
|
- ✅ 分页查询 (支持按类型、关键词、分类、标签筛选)
|
||||||
|
- ✅ 使用次数统计
|
||||||
|
- ✅ 点赞数统计
|
||||||
|
- ✅ 热门组件查询
|
||||||
|
- ✅ 批量删除
|
||||||
|
|
||||||
|
#### 分类管理
|
||||||
|
- ✅ 两级分类结构 (一级固定 5 大类:文字、图片、扩展、背景、音乐)
|
||||||
|
- ✅ 一级分类查询
|
||||||
|
- ✅ 二级分类查询 (按父 ID)
|
||||||
|
- ✅ 按类型查询分类
|
||||||
|
- ✅ 分类树形结构
|
||||||
|
- ✅ 分类 CRUD 操作
|
||||||
|
|
||||||
|
#### 标签管理
|
||||||
|
- ✅ 所有标签查询
|
||||||
|
- ✅ 热门标签查询
|
||||||
|
- ✅ 按类型查询标签
|
||||||
|
- ✅ 标签 CRUD 操作
|
||||||
|
- ✅ 标签使用次数统计
|
||||||
|
|
||||||
|
### 3. 技术实现
|
||||||
|
|
||||||
|
#### 分层架构
|
||||||
|
```
|
||||||
|
com.luban.api
|
||||||
|
├── controller # 控制器层
|
||||||
|
│ ├── H5ComponentController
|
||||||
|
│ ├── H5ComponentCategoryController
|
||||||
|
│ └── H5TagController
|
||||||
|
├── service # 服务层接口
|
||||||
|
│ ├── H5ComponentService
|
||||||
|
│ ├── H5ComponentCategoryService
|
||||||
|
│ └── H5TagService
|
||||||
|
├── service.impl # 服务层实现
|
||||||
|
│ ├── H5ComponentServiceImpl
|
||||||
|
│ ├── H5ComponentCategoryServiceImpl
|
||||||
|
│ └── H5TagServiceImpl
|
||||||
|
├── dao # 数据访问层
|
||||||
|
│ ├── H5ComponentDao
|
||||||
|
│ ├── H5ComponentCategoryDao
|
||||||
|
│ ├── H5TagDao
|
||||||
|
│ ├── H5ComponentCategoryRelDao
|
||||||
|
│ └── H5ComponentTagRelDao
|
||||||
|
├── entity # 实体类
|
||||||
|
│ ├── H5Component
|
||||||
|
│ ├── H5ComponentCategory
|
||||||
|
│ ├── H5Tag
|
||||||
|
│ ├── H5ComponentCategoryRel
|
||||||
|
│ └── H5ComponentTagRel
|
||||||
|
├── vo # 视图对象
|
||||||
|
│ ├── H5ComponentVO
|
||||||
|
│ └── Result
|
||||||
|
└── convert # 转换类
|
||||||
|
└── H5ComponentConvert
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 技术栈
|
||||||
|
- Spring Boot 3
|
||||||
|
- MyBatis-Plus (ORM 框架)
|
||||||
|
- Lombok (简化代码)
|
||||||
|
- MapStruct (对象转换)
|
||||||
|
- Swagger (API 文档)
|
||||||
|
|
||||||
|
#### 代码规范
|
||||||
|
- ✅ 使用 `@Data`、`@EqualsAndHashCode`、`@NoArgsConstructor`、`@AllArgsConstructor`进行 POJO 类定义
|
||||||
|
- ✅ MyBatis-Plus映射添加`@TableName`和`@TableId`注解
|
||||||
|
- ✅ 事务一致性保障 (`@Transactional` 注解)
|
||||||
|
- ✅ Controller 不直接调用 Repository
|
||||||
|
- ✅ Controller 返回值不使用 Map 类型
|
||||||
|
- ✅ ID 字段统一命名为 id
|
||||||
|
- ✅ 所有类和方法有适当的 Swagger 注解
|
||||||
|
- ✅ 时间字段使用 Unix 时间戳 (秒级)
|
||||||
|
|
||||||
|
### 4. API 接口列表
|
||||||
|
|
||||||
|
#### 组件接口
|
||||||
|
```
|
||||||
|
GET /h5/component/{id} # 根据 ID 查询组件
|
||||||
|
GET /h5/component/page # 分页查询组件列表
|
||||||
|
POST /h5/component # 创建组件
|
||||||
|
PUT /h5/component/{id} # 更新组件
|
||||||
|
DELETE /h5/component/{id} # 删除组件
|
||||||
|
DELETE /h5/component/batch # 批量删除组件
|
||||||
|
POST /h5/component/{id}/usage # 增加使用次数
|
||||||
|
POST /h5/component/{id}/like # 增加点赞数
|
||||||
|
GET /h5/component/hot # 获取热门组件
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 分类接口
|
||||||
|
```
|
||||||
|
GET /h5/category/top-level # 查询所有一级分类
|
||||||
|
GET /h5/category/children # 根据父分类 ID 查询子分类
|
||||||
|
GET /h5/category/by-type # 根据类型查询分类
|
||||||
|
GET /h5/category/tree # 获取分类树形结构
|
||||||
|
POST /h5/category # 创建分类
|
||||||
|
PUT /h5/category/{id} # 更新分类
|
||||||
|
DELETE /h5/category/{id} # 删除分类
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 标签接口
|
||||||
|
```
|
||||||
|
GET /h5/tag # 查询所有标签
|
||||||
|
GET /h5/tag/hot # 查询热门标签
|
||||||
|
GET /h5/tag/by-type # 根据类型查询标签
|
||||||
|
POST /h5/tag # 创建标签
|
||||||
|
PUT /h5/tag/{id} # 更新标签
|
||||||
|
DELETE /h5/tag/{id} # 删除标签
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 数据库初始化脚本
|
||||||
|
位置:`ruoyi-site/ruoyi-h5/doc/dml/h5_component.sql`
|
||||||
|
|
||||||
|
包含:
|
||||||
|
- 5 张表的建表语句
|
||||||
|
- 一级分类初始化数据 (固定 5 大类)
|
||||||
|
- 二级分类示例数据
|
||||||
|
- 标签示例数据
|
||||||
|
|
||||||
|
### 6. 组件类型说明
|
||||||
|
|
||||||
|
根据需求定义的组件类型:
|
||||||
|
- **text**: 文字类组件 (标题、正文、艺术字等)
|
||||||
|
- **image**: 图片类组件 (产品图、装饰图等)
|
||||||
|
- **form**: 表单组件
|
||||||
|
- **map**: 地图定位组件
|
||||||
|
- **background**: 背景类组件
|
||||||
|
- **music**: 音乐音频组件
|
||||||
|
- **extension**: 扩展组件 (包含 form、map 等)
|
||||||
|
|
||||||
|
### 7. JSON 数据结构
|
||||||
|
|
||||||
|
组件内容使用 JSON 格式存储,支持以下类型:
|
||||||
|
- image: 包含 url、width、height、transform 等属性
|
||||||
|
- text: 包含 content、fontFamily、fontSize、color 等属性
|
||||||
|
- svg: 包含 url、content、colors 等属性
|
||||||
|
- group: 包含 elements 数组 (可嵌套子元素)
|
||||||
|
- form: 包含 formData、formSchema、formItems 等属性
|
||||||
|
- map: 包含 longitude、latitude、address 等属性
|
||||||
|
|
||||||
|
## 下一步工作
|
||||||
|
|
||||||
|
### 阶段 2: 核心业务逻辑
|
||||||
|
- [ ] 组件推荐算法
|
||||||
|
- [ ] 标签智能匹配
|
||||||
|
- [ ] 组件收藏功能
|
||||||
|
- [ ] 用户上传自定义组件
|
||||||
|
|
||||||
|
### 阶段 3: 性能优化
|
||||||
|
- [ ] Redis 缓存热门数据
|
||||||
|
- [ ] 搜索引擎集成 (Elasticsearch)
|
||||||
|
- [ ] 图片 CDN 加速
|
||||||
|
- [ ] 批量操作优化
|
||||||
|
|
||||||
|
### 阶段 4: 扩展功能
|
||||||
|
- [ ] 组件版本管理
|
||||||
|
- [ ] 组件评价系统
|
||||||
|
- [ ] 组件下载统计
|
||||||
|
- [ ] 组件分享功能
|
||||||
|
|
||||||
|
## 编译验证
|
||||||
|
✅ 所有代码编译通过,无错误
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
1. 执行数据库脚本:`doc/dml/h5_component.sql`
|
||||||
|
2. 启动项目后访问 Swagger 文档查看 API
|
||||||
|
3. 使用 Postman 或前端项目进行接口测试
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
- 所有时间字段使用 Unix 时间戳 (秒级)
|
||||||
|
- 组件内容以 JSON 字符串形式存储
|
||||||
|
- 分类只支持两层结构,不支持多级嵌套
|
||||||
|
- 删除分类前会检查是否有子分类
|
||||||
@ -2,6 +2,7 @@
|
|||||||
package com.luban.api.controller;
|
package com.luban.api.controller;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.luban.api.dto.H5ComponentDTO;
|
||||||
import com.luban.api.entity.H5Component;
|
import com.luban.api.entity.H5Component;
|
||||||
import com.luban.api.service.H5ComponentService;
|
import com.luban.api.service.H5ComponentService;
|
||||||
import com.luban.api.vo.H5ComponentVO;
|
import com.luban.api.vo.H5ComponentVO;
|
||||||
@ -12,7 +13,10 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* H5 组件控制器
|
* H5 组件控制器
|
||||||
@ -48,26 +52,31 @@ public class H5ComponentController {
|
|||||||
return h5ComponentService.getPage(page, pageSize, type, keyword, categoryId, tagId);
|
return h5ComponentService.getPage(page, pageSize, type, keyword, categoryId, tagId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询指定分类下排行前 6 的组件")
|
||||||
|
@GetMapping("/top")
|
||||||
|
public Map<Long, List<H5ComponentVO>> getPage2(
|
||||||
|
@Parameter(description = "每页大小", required = true) @RequestParam Integer pageSize,
|
||||||
|
@Parameter(description = "分类 IDS", required = true) @RequestParam List<Long> categoryIds) {
|
||||||
|
|
||||||
|
return h5ComponentService.getPageByTopComponents(pageSize, categoryIds);
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "创建组件")
|
@Operation(summary = "创建组件")
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Long create(
|
public Long create(
|
||||||
@Parameter(description = "组件信息", required = true) @RequestBody @Validated H5Component component,
|
@Parameter(description = "组件信息", required = true) @RequestBody @Valid H5ComponentDTO dto) {
|
||||||
@Parameter(description = "分类 ID 列表") @RequestBody(required = false) List<Long> categoryIds,
|
|
||||||
@Parameter(description = "标签 ID 列表") @RequestBody(required = false) List<Long> tagIds) {
|
|
||||||
|
|
||||||
return h5ComponentService.create(component, categoryIds, tagIds);
|
return h5ComponentService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "更新组件")
|
@Operation(summary = "更新组件")
|
||||||
@PostMapping("/update/{id}")
|
@PostMapping("/update/{id}")
|
||||||
public void update(
|
public void update(
|
||||||
@Parameter(description = "组件 ID", required = true) @PathVariable Long id,
|
@Parameter(description = "组件 ID", required = true) @PathVariable Long id,
|
||||||
@Parameter(description = "组件信息", required = true) @RequestBody @Validated H5Component component,
|
@Parameter(description = "组件信息", required = true) @RequestBody @Valid H5ComponentDTO dto) {
|
||||||
@Parameter(description = "分类 ID 列表") @RequestBody(required = false) List<Long> categoryIds,
|
|
||||||
@Parameter(description = "标签 ID 列表") @RequestBody(required = false) List<Long> tagIds) {
|
|
||||||
|
|
||||||
component.setId(id);
|
dto.setId(id);
|
||||||
h5ComponentService.update(component, categoryIds, tagIds);
|
h5ComponentService.update(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "删除组件")
|
@Operation(summary = "删除组件")
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.luban.api.convert;
|
package com.luban.api.convert;
|
||||||
|
|
||||||
|
import com.luban.api.dto.H5ComponentDTO;
|
||||||
import com.luban.api.entity.H5Component;
|
import com.luban.api.entity.H5Component;
|
||||||
import com.luban.api.vo.H5ComponentVO;
|
import com.luban.api.vo.H5ComponentVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
@ -22,4 +23,12 @@ public interface H5ComponentConvert {
|
|||||||
* @return VO
|
* @return VO
|
||||||
*/
|
*/
|
||||||
H5ComponentVO toVO(H5Component entity);
|
H5ComponentVO toVO(H5Component entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DTO 转 Entity
|
||||||
|
*
|
||||||
|
* @param dto 数据传输对象
|
||||||
|
* @return 实体
|
||||||
|
*/
|
||||||
|
H5Component toEntity(H5ComponentDTO dto);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,9 @@ package com.luban.api.dao;
|
|||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.luban.api.entity.H5Component;
|
import com.luban.api.entity.H5Component;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* H5 组件 Mapper 接口
|
* H5 组件 Mapper 接口
|
||||||
@ -13,4 +16,11 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface H5ComponentDao extends BaseMapper<H5Component> {
|
public interface H5ComponentDao extends BaseMapper<H5Component> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定分类下的热门组件
|
||||||
|
* @param categoryId 分类 ID
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 组件列表
|
||||||
|
*/
|
||||||
|
List<H5Component> selectTopComponentsByCategory(@Param("categoryId") Long categoryId, @Param("pageSize") Integer pageSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
package com.luban.api.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* H5 组件创建/更新 DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @since 2026-03-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class H5ComponentDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件 ID(更新时使用)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "组件 ID(更新时使用)")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件名称
|
||||||
|
*/
|
||||||
|
@Parameter(description = "组件名称", required = true)
|
||||||
|
@NotBlank(message = "组件名称不能为空")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件类型 (text/image/form/map/background/music)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "组件类型 (text/image/form/map/background/music)", required = true)
|
||||||
|
@NotBlank(message = "组件类型不能为空")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩略图 URL
|
||||||
|
*/
|
||||||
|
@Parameter(description = "缩略图 URL")
|
||||||
|
private String thumbnailUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预览图 URL
|
||||||
|
*/
|
||||||
|
@Parameter(description = "预览图 URL")
|
||||||
|
private String previewUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件完整配置数据 (Map 格式)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "组件完整配置数据 (Map 格式)")
|
||||||
|
private Map<String, Object> content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用次数统计
|
||||||
|
*/
|
||||||
|
@Parameter(description = "使用次数统计")
|
||||||
|
private Long usageCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点赞数量
|
||||||
|
*/
|
||||||
|
@Parameter(description = "点赞数量")
|
||||||
|
private Long likeCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否付费组件 (1:是 0:否)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "是否付费组件 (1:是 0:否)")
|
||||||
|
private Integer isPremium;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否系统预设 (1:是 0:否)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "是否系统预设 (1:是 0:否)")
|
||||||
|
private Integer isSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 (1:启用 0:禁用)
|
||||||
|
*/
|
||||||
|
@Parameter(description = "状态 (1:启用 0:禁用)")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注说明
|
||||||
|
*/
|
||||||
|
@Parameter(description = "备注说明")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类 ID 列表
|
||||||
|
*/
|
||||||
|
@Parameter(description = "分类 ID 列表")
|
||||||
|
private List<Long> categoryIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签 ID 列表
|
||||||
|
*/
|
||||||
|
@Parameter(description = "标签 ID 列表")
|
||||||
|
private List<Long> tagIds;
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.luban.api.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询分类下热门组件请求 DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @since 2026-03-12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class H5ComponentTopQueryDTO {
|
||||||
|
|
||||||
|
@NotNull(message = "每页大小不能为空")
|
||||||
|
@Parameter(description = "每页大小", required = true)
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
@NotNull(message = "分类 IDS 不能为空")
|
||||||
|
@Parameter(description = "分类 IDS", required = true)
|
||||||
|
private List<Long> categoryIds;
|
||||||
|
}
|
||||||
@ -8,6 +8,8 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* H5 组件实体
|
* H5 组件实体
|
||||||
*
|
*
|
||||||
@ -50,7 +52,7 @@ public class H5Component {
|
|||||||
/**
|
/**
|
||||||
* 组件完整配置数据 (JSON 格式)
|
* 组件完整配置数据 (JSON 格式)
|
||||||
*/
|
*/
|
||||||
private String content;
|
private Map<String, Object> content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用次数统计
|
* 使用次数统计
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
package com.luban.api.service;
|
package com.luban.api.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.luban.api.dto.H5ComponentDTO;
|
||||||
import com.luban.api.entity.H5Component;
|
import com.luban.api.entity.H5Component;
|
||||||
import com.luban.api.vo.H5ComponentVO;
|
import com.luban.api.vo.H5ComponentVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* H5 组件服务接口
|
* H5 组件服务接口
|
||||||
@ -38,21 +40,17 @@ public interface H5ComponentService {
|
|||||||
/**
|
/**
|
||||||
* 创建组件
|
* 创建组件
|
||||||
*
|
*
|
||||||
* @param component 组件信息
|
* @param dto 组件信息 DTO
|
||||||
* @param categoryIds 分类 ID 列表
|
|
||||||
* @param tagIds 标签 ID 列表
|
|
||||||
* @return 组件 ID
|
* @return 组件 ID
|
||||||
*/
|
*/
|
||||||
Long create(H5Component component, List<Long> categoryIds, List<Long> tagIds);
|
Long create(H5ComponentDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新组件
|
* 更新组件
|
||||||
*
|
*
|
||||||
* @param component 组件信息
|
* @param dto 组件信息 DTO
|
||||||
* @param categoryIds 分类 ID 列表
|
|
||||||
* @param tagIds 标签 ID 列表
|
|
||||||
*/
|
*/
|
||||||
void update(H5Component component, List<Long> categoryIds, List<Long> tagIds);
|
void update(H5ComponentDTO dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除组件
|
* 删除组件
|
||||||
@ -90,4 +88,13 @@ public interface H5ComponentService {
|
|||||||
* @return 组件列表
|
* @return 组件列表
|
||||||
*/
|
*/
|
||||||
List<H5ComponentVO> getHotComponents(String type, Integer limit);
|
List<H5ComponentVO> getHotComponents(String type, Integer limit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定分类下排行前 6 的组件
|
||||||
|
*
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @param categoryIds 分类 IDS
|
||||||
|
* @return Map<分类 ID, 组件列表>
|
||||||
|
*/
|
||||||
|
Map<Long, List<H5ComponentVO>> getPageByTopComponents(Integer pageSize, List<Long> categoryIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,9 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.luban.api.dao.H5ComponentCategoryRelDao;
|
import com.luban.api.dao.H5ComponentCategoryRelDao;
|
||||||
import com.luban.api.dao.H5ComponentDao;
|
import com.luban.api.dao.H5ComponentDao;
|
||||||
import com.luban.api.dao.H5ComponentTagRelDao;
|
import com.luban.api.dao.H5ComponentTagRelDao;
|
||||||
|
import com.luban.api.dto.H5ComponentDTO;
|
||||||
import com.luban.api.entity.H5Component;
|
import com.luban.api.entity.H5Component;
|
||||||
|
import com.luban.api.entity.H5ComponentCategory;
|
||||||
import com.luban.api.entity.H5ComponentCategoryRel;
|
import com.luban.api.entity.H5ComponentCategoryRel;
|
||||||
import com.luban.api.entity.H5ComponentTagRel;
|
import com.luban.api.entity.H5ComponentTagRel;
|
||||||
import com.luban.api.service.H5ComponentService;
|
import com.luban.api.service.H5ComponentService;
|
||||||
@ -19,7 +21,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +35,7 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Component> implements H5ComponentService {
|
public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Component> implements H5ComponentService {
|
||||||
|
|
||||||
|
private final H5ComponentDao h5ComponentDao;
|
||||||
private final H5ComponentCategoryRelDao h5ComponentCategoryRelDao;
|
private final H5ComponentCategoryRelDao h5ComponentCategoryRelDao;
|
||||||
private final H5ComponentTagRelDao h5ComponentTagRelDao;
|
private final H5ComponentTagRelDao h5ComponentTagRelDao;
|
||||||
|
|
||||||
@ -90,9 +93,12 @@ public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Compon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long create(H5Component component, List<Long> categoryIds, List<Long> tagIds) {
|
public Long create(H5ComponentDTO dto) {
|
||||||
long now = Instant.now().getEpochSecond();
|
long now = Instant.now().getEpochSecond();
|
||||||
|
|
||||||
|
// 转换为实体对象
|
||||||
|
H5Component component = H5ComponentConvert.INSTANCE.toEntity(dto);
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
component.setCreateTime(now);
|
component.setCreateTime(now);
|
||||||
component.setUpdateTime(now);
|
component.setUpdateTime(now);
|
||||||
@ -103,11 +109,13 @@ public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Compon
|
|||||||
baseMapper.insert(component);
|
baseMapper.insert(component);
|
||||||
|
|
||||||
// 保存分类关联
|
// 保存分类关联
|
||||||
|
List<Long> categoryIds = dto.getCategoryIds();
|
||||||
if (categoryIds != null && !categoryIds.isEmpty()) {
|
if (categoryIds != null && !categoryIds.isEmpty()) {
|
||||||
saveCategoryRels(component.getId(), categoryIds, now);
|
saveCategoryRels(component.getId(), categoryIds, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存标签关联
|
// 保存标签关联
|
||||||
|
List<Long> tagIds = dto.getTagIds();
|
||||||
if (tagIds != null && !tagIds.isEmpty()) {
|
if (tagIds != null && !tagIds.isEmpty()) {
|
||||||
saveTagRels(component.getId(), tagIds, now);
|
saveTagRels(component.getId(), tagIds, now);
|
||||||
}
|
}
|
||||||
@ -117,13 +125,17 @@ public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Compon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void update(H5Component component, List<Long> categoryIds, List<Long> tagIds) {
|
public void update(H5ComponentDTO dto) {
|
||||||
long now = Instant.now().getEpochSecond();
|
long now = Instant.now().getEpochSecond();
|
||||||
|
|
||||||
|
// 转换为实体对象
|
||||||
|
H5Component component = H5ComponentConvert.INSTANCE.toEntity(dto);
|
||||||
component.setUpdateTime(now);
|
component.setUpdateTime(now);
|
||||||
|
|
||||||
baseMapper.updateById(component);
|
baseMapper.updateById(component);
|
||||||
|
|
||||||
// 更新分类关联
|
// 更新分类关联
|
||||||
|
List<Long> categoryIds = dto.getCategoryIds();
|
||||||
if (categoryIds != null) {
|
if (categoryIds != null) {
|
||||||
deleteCategoryRels(component.getId());
|
deleteCategoryRels(component.getId());
|
||||||
if (!categoryIds.isEmpty()) {
|
if (!categoryIds.isEmpty()) {
|
||||||
@ -132,6 +144,7 @@ public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Compon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新标签关联
|
// 更新标签关联
|
||||||
|
List<Long> tagIds = dto.getTagIds();
|
||||||
if (tagIds != null) {
|
if (tagIds != null) {
|
||||||
deleteTagRels(component.getId());
|
deleteTagRels(component.getId());
|
||||||
if (!tagIds.isEmpty()) {
|
if (!tagIds.isEmpty()) {
|
||||||
@ -199,6 +212,24 @@ public class H5ComponentServiceImpl extends ServiceImpl<H5ComponentDao, H5Compon
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, List<H5ComponentVO>> getPageByTopComponents(Integer pageSize, List<Long> categoryIds) {
|
||||||
|
if (categoryIds == null || categoryIds.isEmpty()) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Long, List<H5ComponentVO>> resultMap = new HashMap<>();
|
||||||
|
for (Long categoryId : categoryIds) {
|
||||||
|
List<H5Component> components = h5ComponentDao.selectTopComponentsByCategory(categoryId, pageSize);
|
||||||
|
List<H5ComponentVO> vos = components.stream()
|
||||||
|
.map(H5ComponentConvert.INSTANCE::toVO)
|
||||||
|
.toList();
|
||||||
|
resultMap.put(categoryId, vos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Long> getComponentIdsByCategory(Long categoryId) {
|
private List<Long> getComponentIdsByCategory(Long categoryId) {
|
||||||
LambdaQueryWrapper<H5ComponentCategoryRel> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<H5ComponentCategoryRel> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.eq(H5ComponentCategoryRel::getCategoryId, categoryId);
|
wrapper.eq(H5ComponentCategoryRel::getCategoryId, categoryId);
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.luban.api.dao.H5ComponentDao">
|
||||||
|
|
||||||
|
<!-- 查询指定分类下的热门组件 -->
|
||||||
|
<select id="selectTopComponentsByCategory" resultType="com.luban.api.entity.H5Component">
|
||||||
|
SELECT * FROM h5_component
|
||||||
|
WHERE status = 1
|
||||||
|
AND id IN (
|
||||||
|
SELECT component_id
|
||||||
|
FROM h5_component_category_rel
|
||||||
|
WHERE category_id = #{categoryId}
|
||||||
|
)
|
||||||
|
ORDER BY usage_count DESC, create_time DESC
|
||||||
|
LIMIT #{pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Loading…
Reference in New Issue
Block a user