Feat(StoreController): Add get favorite tool list api

Add get favorite tool list api to StoreController
This commit is contained in:
2024-04-28 15:29:06 +08:00
parent c49b7d7532
commit 059b5dc2cb
10 changed files with 118 additions and 145 deletions

View File

@@ -98,4 +98,22 @@ class StoreController(
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
} }
/**
* Get favorite tool
*
* @param pageSortParam Page sort parameters
* @return Response object includes favorite tool paging information
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see PageSortParam
* @see ResponseResult
* @see PageVo
* @see ToolVo
*/
@Trim
@Operation(summary = "获取收藏工具")
@GetMapping("/favorite")
fun getFavorite(@Valid pageSortParam: PageSortParam): ResponseResult<PageVo<ToolVo>> =
ResponseResult.databaseSuccess(data = storeService.getFavorite(pageSortParam))
} }

View File

@@ -1,10 +1,6 @@
package top.fatweb.oxygen.api.entity.tool package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.TableField import com.baomidou.mybatisplus.annotation.*
import com.baomidou.mybatisplus.annotation.TableId
import com.baomidou.mybatisplus.annotation.TableLogic
import com.baomidou.mybatisplus.annotation.TableName
import com.baomidou.mybatisplus.annotation.Version
import java.io.Serializable import java.io.Serializable
@TableName("t_b_tool_favorite") @TableName("t_b_tool_favorite")
@@ -28,13 +24,13 @@ class ToolFavorite : Serializable {
var userId: Long? = null var userId: Long? = null
/** /**
* Username * Author ID
* *
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@TableField("username") @TableField("author_id")
var username: String? = null var authorId: Long? = null
/** /**
* Tool ID * Tool ID
@@ -45,16 +41,6 @@ class ToolFavorite : Serializable {
@TableField("tool_id") @TableField("tool_id")
var toolId: String? = null var toolId: String? = null
/**
* Platform
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolBase.Platform
*/
@TableField("platform")
var platform: ToolBase.Platform? = null
/** /**
* Deleted * Deleted
* *
@@ -76,6 +62,6 @@ class ToolFavorite : Serializable {
var version: Int? = null var version: Int? = null
override fun toString(): String { override fun toString(): String {
return "ToolFavorite(id=$id, userId=$userId, username=$username, toolId=$toolId, platform=$platform, deleted=$deleted, version=$version)" return "ToolFavorite(id=$id, userId=$userId, authorId=$authorId, toolId=$toolId, deleted=$deleted, version=$version)"
} }
} }

View File

@@ -40,17 +40,6 @@ interface StoreMapper : BaseMapper<Tool> {
*/ */
fun selectAuthorToolIdPageByUsername(page: IPage<Long>, @Param("username") username: String): IPage<String> fun selectAuthorToolIdPageByUsername(page: IPage<Long>, @Param("username") username: String): IPage<String>
/**
* Select tool in list by tool IDs
*
* @param ids List of tool IDs
* @return List of Tool object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see Tool
*/
fun selectListByIds(@Param("ids") ids: List<Long>): List<Tool>
/** /**
* Select tool in list by Author:Tool_ID * Select tool in list by Author:Tool_ID
* *
@@ -61,4 +50,15 @@ interface StoreMapper : BaseMapper<Tool> {
* @see Tool * @see Tool
*/ */
fun selectListByAuthorToolIds(@Param("ids") ids: List<String>, @Param("operator") operator: Long?): List<Tool> fun selectListByAuthorToolIds(@Param("ids") ids: List<String>, @Param("operator") operator: Long?): List<Tool>
/**
* Count published tool by username and toolId
*
* @param authorId Author ID
* @param toolId Tool ID
* @return Number
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun countPublishedToolByAuthorAndToolId(@Param("authorId") authorId: Long, @Param("toolId") toolId: String): Long
} }

View File

@@ -2,10 +2,8 @@ package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern import jakarta.validation.constraints.Pattern
import top.fatweb.oxygen.api.annotation.Trim import top.fatweb.oxygen.api.annotation.Trim
import top.fatweb.oxygen.api.entity.tool.ToolBase
/** /**
* Add favorite tool parameters * Add favorite tool parameters
@@ -15,15 +13,15 @@ import top.fatweb.oxygen.api.entity.tool.ToolBase
*/ */
data class ToolFavoriteAddParam( data class ToolFavoriteAddParam(
/** /**
* Username * Author ID
* *
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Trim @Trim
@Schema(description = "用户名", required = true) @Schema(description = "作者 ID", required = true)
@field: NotBlank(message = "Username cannot be blank") @field: NotBlank(message = "AuthorId cannot be blank")
var username: String?, var authorId: Long?,
/** /**
* Tool ID * Tool ID
@@ -38,16 +36,5 @@ data class ToolFavoriteAddParam(
regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$", regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$",
message = "ToolId can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'" message = "ToolId can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'"
) )
var toolId: String?, var toolId: String?
/**
* Platform
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolBase.Platform
*/
@Schema(description = "平台")
@field:NotNull(message = "Platform can not be null")
val platform: ToolBase.Platform?
) )

View File

@@ -2,10 +2,8 @@ package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern import jakarta.validation.constraints.Pattern
import top.fatweb.oxygen.api.annotation.Trim import top.fatweb.oxygen.api.annotation.Trim
import top.fatweb.oxygen.api.entity.tool.ToolBase
/** /**
* Remove favorite tool parameters * Remove favorite tool parameters
@@ -15,15 +13,15 @@ import top.fatweb.oxygen.api.entity.tool.ToolBase
*/ */
data class ToolFavoriteRemoveParam( data class ToolFavoriteRemoveParam(
/** /**
* Username * Author ID
* *
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Trim @Trim
@Schema(description = "用户名", required = true) @Schema(description = "作者 ID", required = true)
@field: NotBlank(message = "Username cannot be blank") @field: NotBlank(message = "AuthorId cannot be blank")
var username: String?, var authorId: Long?,
/** /**
* Tool ID * Tool ID
@@ -39,15 +37,4 @@ data class ToolFavoriteRemoveParam(
message = "ToolId can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'" message = "ToolId can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'"
) )
var toolId: String?, var toolId: String?,
/**
* Platform
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolBase.Platform
*/
@Schema(description = "平台")
@field:NotNull(message = "Platform can not be null")
val platform: ToolBase.Platform?
) )

View File

@@ -64,4 +64,17 @@ interface IStoreService : IService<Tool> {
* @see ToolFavoriteRemoveParam * @see ToolFavoriteRemoveParam
*/ */
fun removeFavorite(toolFavoriteRemoveParam: ToolFavoriteRemoveParam) fun removeFavorite(toolFavoriteRemoveParam: ToolFavoriteRemoveParam)
/**
* Get favorite tool
*
* @param pageSortParam Page sort parameters
* @return PageVo<ToolVo> object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see PageSortParam
* @see PageVo
* @see ToolVo
*/
fun getFavorite(pageSortParam: PageSortParam): PageVo<ToolVo>
} }

View File

@@ -15,7 +15,6 @@ import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteAddParam import top.fatweb.oxygen.api.param.tool.ToolFavoriteAddParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteRemoveParam import top.fatweb.oxygen.api.param.tool.ToolFavoriteRemoveParam
import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam
import top.fatweb.oxygen.api.service.tool.IEditService
import top.fatweb.oxygen.api.service.tool.IStoreService import top.fatweb.oxygen.api.service.tool.IStoreService
import top.fatweb.oxygen.api.service.tool.IToolFavoriteService import top.fatweb.oxygen.api.service.tool.IToolFavoriteService
import top.fatweb.oxygen.api.util.WebUtil import top.fatweb.oxygen.api.util.WebUtil
@@ -34,7 +33,6 @@ import top.fatweb.oxygen.api.vo.tool.ToolVo
*/ */
@Service @Service
class StoreServiceImpl( class StoreServiceImpl(
private val editService: IEditService,
private val toolFavoriteService: IToolFavoriteService private val toolFavoriteService: IToolFavoriteService
) : ServiceImpl<StoreMapper, Tool>(), IStoreService { ) : ServiceImpl<StoreMapper, Tool>(), IStoreService {
override fun getPage(toolStoreGetParam: ToolStoreGetParam): PageVo<ToolVo> { override fun getPage(toolStoreGetParam: ToolStoreGetParam): PageVo<ToolVo> {
@@ -65,30 +63,33 @@ class StoreServiceImpl(
@Transactional @Transactional
override fun addFavorite(toolFavoriteAddParam: ToolFavoriteAddParam) { override fun addFavorite(toolFavoriteAddParam: ToolFavoriteAddParam) {
if (toolFavoriteAddParam.authorId == WebUtil.getLoginUserId()) {
throw NoRecordFoundException()
}
if (toolFavoriteService.exists( if (toolFavoriteService.exists(
KtQueryWrapper(ToolFavorite()) KtQueryWrapper(ToolFavorite())
.eq(ToolFavorite::userId, WebUtil.getLoginUserId()) .eq(ToolFavorite::userId, WebUtil.getLoginUserId())
.eq(ToolFavorite::username, toolFavoriteAddParam.username) .eq(ToolFavorite::authorId, toolFavoriteAddParam.authorId)
.eq(ToolFavorite::toolId, toolFavoriteAddParam.toolId) .eq(ToolFavorite::toolId, toolFavoriteAddParam.toolId)
.eq(ToolFavorite::platform, toolFavoriteAddParam.platform)
) )
) { ) {
throw RecordAlreadyExists() throw RecordAlreadyExists()
} }
editService.detail( if (baseMapper.countPublishedToolByAuthorAndToolId(
toolFavoriteAddParam.username!!, toolFavoriteAddParam.authorId!!,
toolFavoriteAddParam.toolId!!, toolFavoriteAddParam.toolId!!
"latest", ) <= 0
toolFavoriteAddParam.platform!! ) {
) throw NoRecordFoundException()
}
toolFavoriteService.save( toolFavoriteService.save(
ToolFavorite().apply { ToolFavorite().apply {
userId = WebUtil.getLoginUserId() userId = WebUtil.getLoginUserId()
username = toolFavoriteAddParam.username authorId = toolFavoriteAddParam.authorId
toolId = toolFavoriteAddParam.toolId toolId = toolFavoriteAddParam.toolId
platform = toolFavoriteAddParam.platform
} }
) )
} }
@@ -98,12 +99,32 @@ class StoreServiceImpl(
if (!toolFavoriteService.remove( if (!toolFavoriteService.remove(
KtQueryWrapper(ToolFavorite()) KtQueryWrapper(ToolFavorite())
.eq(ToolFavorite::userId, WebUtil.getLoginUserId()) .eq(ToolFavorite::userId, WebUtil.getLoginUserId())
.eq(ToolFavorite::username, toolFavoriteRemoveParam.username) .eq(ToolFavorite::authorId, toolFavoriteRemoveParam.authorId)
.eq(ToolFavorite::toolId, toolFavoriteRemoveParam.toolId) .eq(ToolFavorite::toolId, toolFavoriteRemoveParam.toolId)
.eq(ToolFavorite::platform, toolFavoriteRemoveParam.platform)
) )
) { ) {
throw NoRecordFoundException() throw NoRecordFoundException()
} }
} }
override fun getFavorite(pageSortParam: PageSortParam): PageVo<ToolVo> {
val toolFavoritePage = Page<ToolFavorite>(pageSortParam.currentPage, 20)
val toolFavoriteIPage = toolFavoriteService.page(
toolFavoritePage,
KtQueryWrapper(ToolFavorite()).eq(ToolFavorite::userId, WebUtil.getLoginUserId())
)
val toolPage = Page<Tool>(toolFavoriteIPage.current, toolFavoriteIPage.size, toolFavoriteIPage.total)
if (toolFavoriteIPage.total > 0) {
toolPage.setRecords(
baseMapper.selectListByAuthorToolIds(
toolFavoriteIPage.records.map { "${it.authorId}:${it.toolId}" },
WebUtil.getLoginUserId()
)
)
}
return ToolConverter.toolPageToToolPageVo(toolPage)
}
} }

View File

@@ -4,10 +4,9 @@ create table if not exists t_b_tool_favorite
( (
id bigint not null primary key, id bigint not null primary key,
user_id bigint not null comment '用户 ID', user_id bigint not null comment '用户 ID',
username varchar(20) not null comment '用户名', author_id bigint not null comment '作者 ID',
tool_id varchar(50) not null comment '工具 ID', tool_id varchar(50) not null comment '工具 ID',
platform varchar(20) not null comment '平台',
deleted bigint not null default 0, deleted bigint not null default 0,
version int not null default 0, version int not null default 0,
constraint t_b_tool_favorite_unique_user_id_username_tool_id_platform unique (user_id, username, tool_id, platform, deleted) constraint t_b_tool_favorite_unique_user_id_username_tool_id_platform unique (user_id, author_id, tool_id, deleted)
) comment '工具-收藏表'; ) comment '工具-收藏表';

View File

@@ -95,11 +95,15 @@
</select> </select>
<select id="selectPersonalToolIdPage" resultType="string"> <select id="selectPersonalToolIdPage" resultType="string">
select distinct t_b_tool_main.tool_id select t.tool_id
from (select tbtm.tool_id
from (select *,
row_number() over (partition by t_b_tool_main.tool_id order by t_b_tool_main.id desc ) as rn
from t_b_tool_main from t_b_tool_main
where t_b_tool_main.deleted = 0 where t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{userId} and t_b_tool_main.author_id = #{userId}) tbtm
order by t_b_tool_main.id desc where tbtm.rn = 1
order by tbtm.id desc) t
</select> </select>
<select id="selectListByToolIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolMap"> <select id="selectListByToolIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolMap">

View File

@@ -57,58 +57,6 @@
where temp2.rn2 = 1 where temp2.rn2 = 1
</select> </select>
<select id="selectListByIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolWithAuthor">
select t_b_tool_main.id as tool_id,
t_b_tool_main.name as tool_name,
t_b_tool_main.tool_id as tool_tool_id,
t_b_tool_main.icon as tool_icon,
t_b_tool_main.platform as tool_platform,
t_b_tool_main.description as tool_description,
t_b_tool_main.base_id as tool_base_id,
t_b_tool_main.author_id as tool_author_id,
t_b_tool_main.ver as tool_ver,
t_b_tool_main.keywords as tool_keywords,
t_b_tool_main.source_id as tool_source_id,
t_b_tool_main.dist_id as tool_dist_id,
t_b_tool_main.entry_point as tool_entry_point,
t_b_tool_main.publish as tool_publish,
t_b_tool_main.review as tool_review,
t_b_tool_main.create_time as tool_create_time,
t_b_tool_main.update_time as tool_update_time,
t_b_tool_main.deleted as tool_deleted,
t_b_tool_main.version as tool_version,
tsu.id as user_id,
tsu.username as user_username,
tsui.id as user_info_id,
tsui.nickname as user_info_nickname,
tsui.avatar as user_info_avatar,
tbtc.id as tool_category_id,
tbtc.name as tool_category_name,
tbtc.enable as tool_category_enable,
tbtc.create_time as tool_category_create_time,
tbtc.update_time as tool_category_update_time,
tbtc.deleted as tool_category_deleted,
tbtc.version as tool_category_version
from t_b_tool_main
left join (select * from t_s_user where deleted = 0) as tsu on tsu.id = t_b_tool_main.author_id
left join (select * from t_s_user_info where deleted = 0) as tsui
on tsui.user_id = t_b_tool_main.author_id
left join (select * from t_r_tool_main_category where deleted = 0) as trtmc
on t_b_tool_main.id = trtmc.tool_id
left join (select * from t_b_tool_category where deleted = 0 and enable = 1) as tbtc
on tbtc.id = trtmc.category_id
<where>
<foreach collection="ids" item="item" index="index" open="and t_b_tool_main.id in (" separator="," close=")"
nullable="true">
#{item}
</foreach>
</where>
<foreach collection="ids" item="item" index="index" open="order by field(t_b_tool_main.id," separator=","
close=")" nullable="true">
#{item}
</foreach>
</select>
<select id="selectListByAuthorToolIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolWithAuthor"> <select id="selectListByAuthorToolIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolWithAuthor">
select tbtm.id as tool_id, select tbtm.id as tool_id,
tbtm.name as tool_name, tbtm.name as tool_name,
@@ -156,7 +104,7 @@
left join (select * from t_b_tool_category where deleted = 0 and enable = 1) as tbtc left join (select * from t_b_tool_category where deleted = 0 and enable = 1) as tbtc
on tbtc.id = trtmc.category_id on tbtc.id = trtmc.category_id
left join (select * from t_b_tool_favorite where deleted = 0) as tbtf left join (select * from t_b_tool_favorite where deleted = 0) as tbtf
on tbtf.user_id = ${operator} and tbtf.username = tsu.username and tbtf.tool_id = tbtm.tool_id and tbtf.platform = tbtm.platform on tbtf.user_id = #{operator} and tbtf.author_id = tbtm.author_id and tbtf.tool_id = tbtm.tool_id
<where> <where>
and tbtm.rn = 1 and tbtm.rn = 1
<foreach collection="ids" item="item" index="index" open="and concat(tbtm.author_id, ':', tbtm.tool_id) in (" separator="," close=")" <foreach collection="ids" item="item" index="index" open="and concat(tbtm.author_id, ':', tbtm.tool_id) in (" separator="," close=")"
@@ -169,4 +117,14 @@
#{item} #{item}
</foreach> </foreach>
</select> </select>
<select id="countPublishedToolByAuthorAndToolId" resultType="long">
select count(1)
from t_b_tool_main
where t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{authorId}
and t_b_tool_main.tool_id = #{toolId}
and t_b_tool_main.publish != 0
and t_b_tool_main.review = 'PASS'
</select>
</mapper> </mapper>