Fix:3; Refactor:2; Feat3; Docs:1 #23

Merged
FatttSnake merged 9 commits from FatttSnake into dev 2024-05-06 09:30:17 +08:00
42 changed files with 608 additions and 116 deletions

View File

@@ -8,10 +8,12 @@ import top.fatweb.oxygen.api.annotation.Trim
import top.fatweb.oxygen.api.entity.common.ResponseCode
import top.fatweb.oxygen.api.entity.common.ResponseResult
import top.fatweb.oxygen.api.entity.tool.ToolBase
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam
import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam
import top.fatweb.oxygen.api.service.tool.IEditService
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo
import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -113,13 +115,16 @@ class EditController(
* @return Response object includes tool list
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see PageSortParam
* @see ResponseResult
* @see PageVo
* @see ToolVo
*/
@Trim
@Operation(summary = "获取个人工具")
@GetMapping
fun get(): ResponseResult<List<ToolVo>> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_SELECT_SUCCESS, data = editService.get())
fun get(@Valid pageSortParam: PageSortParam): ResponseResult<PageVo<ToolVo>> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_SELECT_SUCCESS, data = editService.getPage(pageSortParam))
/**
* Get tool detail

View File

@@ -2,12 +2,14 @@ package top.fatweb.oxygen.api.controller.tool
import io.swagger.v3.oas.annotations.Operation
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.*
import top.fatweb.oxygen.api.annotation.BaseController
import top.fatweb.oxygen.api.annotation.Trim
import top.fatweb.oxygen.api.entity.common.ResponseCode
import top.fatweb.oxygen.api.entity.common.ResponseResult
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteAddParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteRemoveParam
import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam
import top.fatweb.oxygen.api.service.tool.IStoreService
import top.fatweb.oxygen.api.vo.PageVo
@@ -60,4 +62,58 @@ class StoreController(
@GetMapping("/{username}")
fun get(@PathVariable username: String, @Valid pageSortParam: PageSortParam): ResponseResult<PageVo<ToolVo>> =
ResponseResult.databaseSuccess(data = storeService.getPage(pageSortParam, username.trim()))
/**
* Add favorite tool
*
* @param toolFavoriteAddParam Add favorite tool parameters
* @return Response object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolFavoriteAddParam
* @see ResponseResult
*/
@Operation(summary = "收藏工具")
@PostMapping("/favorite")
fun addFavorite(@RequestBody toolFavoriteAddParam: ToolFavoriteAddParam): ResponseResult<Nothing> {
storeService.addFavorite(toolFavoriteAddParam)
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS)
}
/**
* Remove favorite tool
*
* @param toolFavoriteRemoveParam Remove favorite tool parameters
* @return Response object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolFavoriteRemoveParam
* @see ResponseResult
*/
@Operation(summary = "收藏工具")
@DeleteMapping("/favorite")
fun addFavorite(@RequestBody toolFavoriteRemoveParam: ToolFavoriteRemoveParam): ResponseResult<Nothing> {
storeService.removeFavorite(toolFavoriteRemoveParam)
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

@@ -41,7 +41,8 @@ object ToolConverter {
publish = tool.publish,
review = tool.review,
createTime = tool.createTime,
updateTime = tool.updateTime
updateTime = tool.updateTime,
favorite = tool.favorite == 1
)
/**

View File

@@ -61,6 +61,7 @@ enum class ResponseCode(val code: Int) {
DATABASE_EXECUTE_ERROR(BusinessCode.DATABASE, 50),
DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51),
DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52),
DATABASE_RECORD_ALREADY_EXISTS(BusinessCode.DATABASE, 53),
TOOL_SUBMIT_SUCCESS(BusinessCode.TOOL, 10),
TOOL_CANCEL_SUCCESS(BusinessCode.TOOL, 11),

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.*
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler
import com.fasterxml.jackson.annotation.JsonValue
import top.fatweb.oxygen.api.entity.permission.User
import java.io.Serializable
import java.time.LocalDateTime
/**
@@ -13,7 +14,7 @@ import java.time.LocalDateTime
* @since 1.0.0
*/
@TableName("t_b_tool_main", autoResultMap = true)
class Tool {
class Tool : Serializable {
/**
* Tool review type enum
*
@@ -246,7 +247,16 @@ class Tool {
@TableField(exist = false)
var dist: ToolData? = null
/**
* Favorite
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField(exist = false)
var favorite: Int? = null
override fun toString(): String {
return "Tool(id=$id, name=$name, toolId=$toolId, icon=$icon, platform=$platform, description=$description, baseId=$baseId, authorId=$authorId, ver=$ver, keywords=$keywords, sourceId=$sourceId, distId=$distId, entryPoint=$entryPoint, publish=$publish, review=$review, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, author=$author, base=$base, categories=$categories, source=$source, dist=$dist)"
return "Tool(id=$id, name=$name, toolId=$toolId, icon=$icon, platform=$platform, description=$description, baseId=$baseId, authorId=$authorId, ver=$ver, keywords=$keywords, sourceId=$sourceId, distId=$distId, entryPoint=$entryPoint, publish=$publish, review=$review, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, author=$author, base=$base, categories=$categories, source=$source, dist=$dist, favorite=$favorite)"
}
}

View File

@@ -2,6 +2,7 @@ package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.*
import com.fasterxml.jackson.annotation.JsonValue
import java.io.Serializable
import java.time.LocalDateTime
/**
@@ -11,7 +12,7 @@ import java.time.LocalDateTime
* @since 1.0.0
*/
@TableName("t_b_tool_base")
class ToolBase {
class ToolBase : Serializable {
/**
* Platform enum
*

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.*
import java.io.Serializable
import java.time.LocalDateTime
/**
@@ -10,7 +11,7 @@ import java.time.LocalDateTime
* @since 1.0.0
*/
@TableName("t_b_tool_category")
class ToolCategory {
class ToolCategory : Serializable {
/**
* ID
*

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.*
import java.io.Serializable
import java.time.LocalDateTime
/**
@@ -10,7 +11,7 @@ import java.time.LocalDateTime
* @since 1.0.0
*/
@TableName("t_b_tool_data")
class ToolData {
class ToolData : Serializable {
/**
* ID
*

View File

@@ -0,0 +1,67 @@
package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.*
import java.io.Serializable
@TableName("t_b_tool_favorite")
class ToolFavorite : Serializable {
/**
* ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableId("id")
var id: Long? = null
/**
* User ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("user_id")
var userId: Long? = null
/**
* Author ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("author_id")
var authorId: Long? = null
/**
* Tool ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("tool_id")
var toolId: String? = null
/**
* Deleted
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("deleted")
@TableLogic
var deleted: Long? = null
/**
* Version
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@TableField("version")
@Version
var version: Int? = null
override fun toString(): String {
return "ToolFavorite(id=$id, userId=$userId, authorId=$authorId, toolId=$toolId, deleted=$deleted, version=$version)"
}
}

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.entity.tool
import com.baomidou.mybatisplus.annotation.*
import java.io.Serializable
import java.time.LocalDateTime
/**
@@ -10,7 +11,7 @@ import java.time.LocalDateTime
* @since 1.0.0
*/
@TableName("t_b_tool_template")
class ToolTemplate {
class ToolTemplate : Serializable {
/**
* ID
*

View File

@@ -0,0 +1,10 @@
package top.fatweb.oxygen.api.exception
/**
* Record already exists exception
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see RuntimeException
*/
class RecordAlreadyExists : RuntimeException("Record already exists")

View File

@@ -177,7 +177,11 @@ class ExceptionHandler {
is TwoFactorVerificationCodeErrorException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.PERMISSION_TWO_FACTOR_VERIFICATION_CODE_ERROR, e.localizedMessage, null)
ResponseResult.fail(
ResponseCode.PERMISSION_TWO_FACTOR_VERIFICATION_CODE_ERROR,
e.localizedMessage,
null
)
}
/* SQL */
@@ -226,6 +230,11 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, e.localizedMessage, null)
}
is RecordAlreadyExists -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.DATABASE_RECORD_ALREADY_EXISTS, e.localizedMessage, null)
}
/* Tool */
is IllegalVersionException -> {
logger.debug(e.localizedMessage, e)

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.mapper.tool
import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.baomidou.mybatisplus.core.metadata.IPage
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Param
import top.fatweb.oxygen.api.entity.tool.Tool
@@ -41,15 +42,28 @@ interface EditMapper : BaseMapper<Tool> {
fun selectOne(@Param("id") id: Long, @Param("userId") userId: Long): Tool?
/**
* Select tool in list by User ID
* Select tool ID by user ID in page
*
* @param page Pagination
* @param userId User ID
* @return List of tool object
* @return Tool ID in page
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IPage
*/
fun selectPersonalToolIdPage(page: IPage<String>, @Param("userId") userId: Long): IPage<String>
/**
* Select tool in list by tool IDs and user ID
*
* @param toolIds List of tool Ids
* @param userId User ID
* @return List of Tool object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see Tool
*/
fun selectPersonal(@Param("userId") userId: Long): List<Tool>
fun selectListByToolIds(@Param("toolIds") toolIds: List<String>, @Param("userId") userId: Long): List<Tool>
/**
* Select tool detail
@@ -69,5 +83,5 @@ interface EditMapper : BaseMapper<Tool> {
@Param("ver") ver: String,
@Param("platform") platform: ToolBase.Platform,
@Param("operator") operator: String?
): List<Tool>?
): Tool?
}

View File

@@ -29,28 +29,17 @@ interface StoreMapper : BaseMapper<Tool> {
fun selectAuthorToolIdPage(page: IPage<Long>, @Param("searchValue") searchValue: String?): IPage<String>
/**
* Select tool ID by username in page
* Select author and tool ID by username in page
*
* @param page Pagination
* @param username Username
* @return Tool ID in page
* @return Author:Tool_ID in page
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IPage
*/
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
*
@@ -60,5 +49,16 @@ interface StoreMapper : BaseMapper<Tool> {
* @since 1.0.0
* @see Tool
*/
fun selectListByAuthorToolIds(@Param("ids") ids: List<String>): 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

@@ -0,0 +1,16 @@
package top.fatweb.oxygen.api.mapper.tool
import com.baomidou.mybatisplus.core.mapper.BaseMapper
import org.apache.ibatis.annotations.Mapper
import top.fatweb.oxygen.api.entity.tool.ToolFavorite
/**
* Tool favorite mapper
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see BaseMapper
* @see ToolFavorite
*/
@Mapper
interface ToolFavoriteMapper : BaseMapper<ToolFavorite>

View File

@@ -38,7 +38,7 @@ data class ToolCreateParam(
@field: NotBlank(message = "ToolId can not be blank")
@field: Pattern(
regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$",
message = "Ver 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?,

View File

@@ -0,0 +1,40 @@
package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Pattern
import top.fatweb.oxygen.api.annotation.Trim
/**
* Add favorite tool parameters
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
data class ToolFavoriteAddParam(
/**
* Author ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Trim
@Schema(description = "作者 ID", required = true)
@field: NotBlank(message = "AuthorId cannot be blank")
var authorId: Long?,
/**
* Tool ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Trim
@Schema(description = "工具唯一 ID", required = true)
@field: NotBlank(message = "ToolId cannot be blank")
@field: Pattern(
regexp = "^[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?
)

View File

@@ -0,0 +1,40 @@
package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Pattern
import top.fatweb.oxygen.api.annotation.Trim
/**
* Remove favorite tool parameters
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
data class ToolFavoriteRemoveParam(
/**
* Author ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Trim
@Schema(description = "作者 ID", required = true)
@field: NotBlank(message = "AuthorId cannot be blank")
var authorId: Long?,
/**
* Tool ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Trim
@Schema(description = "工具唯一 ID", required = true)
@field: NotBlank(message = "ToolId cannot be blank")
@field: Pattern(
regexp = "^[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?,
)

View File

@@ -27,7 +27,7 @@ data class ToolUpgradeParam(
@field: NotBlank(message = "ToolId can not be blank")
@field: Pattern(
regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$",
message = "Ver 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?,

View File

@@ -46,9 +46,15 @@ import java.util.*
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see VelocityEngine
* @see AuthenticationManager
* @see PasswordEncoder
* @see RedisUtil
* @see TurnstileApi
* @see IUserService
* @see IUserInfoService
* @see ISensitiveWordService
* @see IAvatarService
* @see IAuthenticationService
*/
@Service

View File

@@ -13,6 +13,7 @@ import top.fatweb.oxygen.api.service.permission.IRUserRoleService
* @since 1.0.0
* @see ServiceImpl
* @see RUserRoleMapper
* @see RUserRole
* @see IRUserRoleService
*/
@Service

View File

@@ -16,7 +16,9 @@ import top.fatweb.oxygen.api.service.permission.IUserService
* @see UserDetailsService
*/
@Service
class UserDetailsServiceImpl(val userService: IUserService) : UserDetailsService {
class UserDetailsServiceImpl(
private val userService: IUserService
) : UserDetailsService {
override fun loadUserByUsername(account: String): UserDetails {
val user = userService.getUserWithPowerByAccount(account)
user ?: throw UserNotFoundException()

View File

@@ -13,6 +13,7 @@ import top.fatweb.oxygen.api.service.permission.IUserInfoService
* @since 1.0.0
* @see ServiceImpl
* @see UserInfoMapper
* @see UserInfo
* @see IUserInfoService
*/
@Service

View File

@@ -17,6 +17,10 @@ import top.fatweb.oxygen.api.service.system.IEventLogService
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see EventLogMapper
* @see EventLog
* @see IEventLogService
*/
@DS("sqlite")
@Service

View File

@@ -20,6 +20,10 @@ import top.fatweb.oxygen.api.vo.system.SensitiveWordVo
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see SensitiveWordMapper
* @see SensitiveWord
* @see ISensitiveWordService
*/
@Service
class SensitiveWordServiceImpl : ServiceImpl<SensitiveWordMapper, SensitiveWord>(), ISensitiveWordService {

View File

@@ -12,6 +12,10 @@ import top.fatweb.oxygen.api.service.system.IStatisticsLogService
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see StatisticsLogMapper
* @see StatisticsLog
* @see IStatisticsLogService
*/
@DS("sqlite")
@Service

View File

@@ -29,6 +29,10 @@ import java.util.concurrent.TimeUnit
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see RedisUtil
* @see IStatisticsLogService
* @see IEventLogService
* @see IStatisticsService
*/
@Service
class StatisticsServiceImpl(

View File

@@ -3,9 +3,11 @@ package top.fatweb.oxygen.api.service.tool
import com.baomidou.mybatisplus.extension.service.IService
import top.fatweb.oxygen.api.entity.tool.Tool
import top.fatweb.oxygen.api.entity.tool.ToolBase
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam
import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo
import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -100,12 +102,15 @@ interface IEditService : IService<Tool> {
/**
* Get personal tools
*
* @return List of ToolVo object
* @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 get(): List<ToolVo>
fun getPage(pageSortParam: PageSortParam): PageVo<ToolVo>
/**
* Get tool detail

View File

@@ -3,6 +3,8 @@ package top.fatweb.oxygen.api.service.tool
import com.baomidou.mybatisplus.extension.service.IService
import top.fatweb.oxygen.api.entity.tool.Tool
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteAddParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteRemoveParam
import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -19,16 +21,60 @@ interface IStoreService : IService<Tool> {
/**
* Get tool in page
*
* @param toolStoreGetParam Get tool parameters in tool store
* @return PageVo<ToolVo> object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolStoreGetParam
* @see PageVo
* @see ToolVo
*/
fun getPage(toolStoreGetParam: ToolStoreGetParam?): PageVo<ToolVo>
fun getPage(toolStoreGetParam: ToolStoreGetParam): PageVo<ToolVo>
/**
* Get tool by username in page
*
* @param pageSortParam Page sort parameters
* @param username Username
* @return PageVo<ToolVo< object
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see PageSortParam
* @see PageVo
* @see ToolVo
*/
fun getPage(pageSortParam: PageSortParam, username: String): PageVo<ToolVo>
/***
* Add favorite
*
* @param toolFavoriteAddParam Add favorite tool parameters
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolFavoriteAddParam
*/
fun addFavorite(toolFavoriteAddParam: ToolFavoriteAddParam)
/***
* Remove favorite tool
*
* @param toolFavoriteRemoveParam Remove favorite tool parameters
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see 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

@@ -0,0 +1,14 @@
package top.fatweb.oxygen.api.service.tool
import com.baomidou.mybatisplus.extension.service.IService
import top.fatweb.oxygen.api.entity.tool.ToolFavorite
/**
* Tool favorite service interface
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IService
* @see ToolFavorite
*/
interface IToolFavoriteService : IService<ToolFavorite>

View File

@@ -2,6 +2,7 @@ package top.fatweb.oxygen.api.service.tool.impl
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import org.springframework.dao.DuplicateKeyException
import org.springframework.stereotype.Service
@@ -12,11 +13,13 @@ import top.fatweb.oxygen.api.converter.tool.ToolTemplateConverter
import top.fatweb.oxygen.api.entity.tool.*
import top.fatweb.oxygen.api.exception.*
import top.fatweb.oxygen.api.mapper.tool.EditMapper
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam
import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam
import top.fatweb.oxygen.api.service.tool.*
import top.fatweb.oxygen.api.util.WebUtil
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo
import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -211,20 +214,26 @@ class EditServiceImpl(
return this.getOne(tool.id!!)
}
override fun get(): List<ToolVo> =
baseMapper.selectPersonal(WebUtil.getLoginUserId()!!)
.map(ToolConverter::toolToToolVo)
override fun getPage(pageSortParam: PageSortParam): PageVo<ToolVo> {
val toolIdsPage = Page<String>(pageSortParam.currentPage, 20)
toolIdsPage.setOptimizeCountSql(false)
val toolIdsIPage = baseMapper.selectPersonalToolIdPage(toolIdsPage, WebUtil.getLoginUserId()!!)
val toolPage = Page<Tool>(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total)
if (toolIdsIPage.total > 0) {
toolPage.setRecords(baseMapper.selectListByToolIds(toolIdsIPage.records, WebUtil.getLoginUserId()!!))
}
return ToolConverter.toolPageToToolPageVo(toolPage)
}
override fun detail(username: String, toolId: String, ver: String, platform: ToolBase.Platform): ToolVo {
if (username == "!" && WebUtil.getLoginUserId() == null) {
throw NoRecordFoundException()
}
val toolList = baseMapper.selectDetail(username, toolId, ver, platform, WebUtil.getLoginUsername())
if (toolList.isNullOrEmpty()) {
throw NoRecordFoundException()
}
return toolList.first().let(ToolConverter::toolToToolVo)
return baseMapper.selectDetail(username, toolId, ver, platform, WebUtil.getLoginUsername())
?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException()
}
override fun submit(id: Long): Boolean {

View File

@@ -29,6 +29,8 @@ import java.time.ZoneOffset
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IToolDataService
* @see IRToolCategoryService
* @see ServiceImpl
* @see ManagementMapper
* @see Tool
@@ -123,5 +125,4 @@ class ManagementServiceImpl(
return this.removeById(id)
}
}

View File

@@ -1,14 +1,23 @@
package top.fatweb.oxygen.api.service.tool.impl
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.fatweb.oxygen.api.converter.tool.ToolConverter
import top.fatweb.oxygen.api.entity.tool.Tool
import top.fatweb.oxygen.api.entity.tool.ToolFavorite
import top.fatweb.oxygen.api.exception.NoRecordFoundException
import top.fatweb.oxygen.api.exception.RecordAlreadyExists
import top.fatweb.oxygen.api.mapper.tool.StoreMapper
import top.fatweb.oxygen.api.param.PageSortParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteAddParam
import top.fatweb.oxygen.api.param.tool.ToolFavoriteRemoveParam
import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam
import top.fatweb.oxygen.api.service.tool.IStoreService
import top.fatweb.oxygen.api.service.tool.IToolFavoriteService
import top.fatweb.oxygen.api.util.WebUtil
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -23,15 +32,17 @@ import top.fatweb.oxygen.api.vo.tool.ToolVo
* @see IStoreService
*/
@Service
class StoreServiceImpl : ServiceImpl<StoreMapper, Tool>(), IStoreService {
override fun getPage(toolStoreGetParam: ToolStoreGetParam?): PageVo<ToolVo> {
val toolIdsPage = Page<Long>(toolStoreGetParam?.currentPage ?: 1, 20)
class StoreServiceImpl(
private val toolFavoriteService: IToolFavoriteService
) : ServiceImpl<StoreMapper, Tool>(), IStoreService {
override fun getPage(toolStoreGetParam: ToolStoreGetParam): PageVo<ToolVo> {
val toolIdsPage = Page<Long>(toolStoreGetParam.currentPage, 20)
toolIdsPage.setOptimizeCountSql(false)
val toolIdsIPage = baseMapper.selectAuthorToolIdPage(toolIdsPage, toolStoreGetParam?.searchValue)
val toolIdsIPage = baseMapper.selectAuthorToolIdPage(toolIdsPage, toolStoreGetParam.searchValue)
val toolPage = Page<Tool>(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total)
if (toolIdsIPage.total > 0) {
toolPage.setRecords(baseMapper.selectListByAuthorToolIds(toolIdsIPage.records))
toolPage.setRecords(baseMapper.selectListByAuthorToolIds(toolIdsIPage.records, WebUtil.getLoginUserId()))
}
return ToolConverter.toolPageToToolPageVo(toolPage)
@@ -44,7 +55,74 @@ class StoreServiceImpl : ServiceImpl<StoreMapper, Tool>(), IStoreService {
val toolIdsIPage = baseMapper.selectAuthorToolIdPageByUsername(toolIdsPage, username)
val toolPage = Page<Tool>(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total)
if (toolIdsIPage.total > 0) {
toolPage.setRecords(baseMapper.selectListByAuthorToolIds(toolIdsIPage.records))
toolPage.setRecords(baseMapper.selectListByAuthorToolIds(toolIdsIPage.records, WebUtil.getLoginUserId()))
}
return ToolConverter.toolPageToToolPageVo(toolPage)
}
@Transactional
override fun addFavorite(toolFavoriteAddParam: ToolFavoriteAddParam) {
if (toolFavoriteAddParam.authorId == WebUtil.getLoginUserId()) {
throw NoRecordFoundException()
}
if (toolFavoriteService.exists(
KtQueryWrapper(ToolFavorite())
.eq(ToolFavorite::userId, WebUtil.getLoginUserId())
.eq(ToolFavorite::authorId, toolFavoriteAddParam.authorId)
.eq(ToolFavorite::toolId, toolFavoriteAddParam.toolId)
)
) {
throw RecordAlreadyExists()
}
if (baseMapper.countPublishedToolByAuthorAndToolId(
toolFavoriteAddParam.authorId!!,
toolFavoriteAddParam.toolId!!
) <= 0
) {
throw NoRecordFoundException()
}
toolFavoriteService.save(
ToolFavorite().apply {
userId = WebUtil.getLoginUserId()
authorId = toolFavoriteAddParam.authorId
toolId = toolFavoriteAddParam.toolId
}
)
}
@Transactional
override fun removeFavorite(toolFavoriteRemoveParam: ToolFavoriteRemoveParam) {
if (!toolFavoriteService.remove(
KtQueryWrapper(ToolFavorite())
.eq(ToolFavorite::userId, WebUtil.getLoginUserId())
.eq(ToolFavorite::authorId, toolFavoriteRemoveParam.authorId)
.eq(ToolFavorite::toolId, toolFavoriteRemoveParam.toolId)
)
) {
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

@@ -24,6 +24,7 @@ import top.fatweb.oxygen.api.vo.tool.ToolBaseVo
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IToolDataService
* @see ServiceImpl
* @see ToolBaseMapper
* @see ToolBase

View File

@@ -0,0 +1,20 @@
package top.fatweb.oxygen.api.service.tool.impl
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import org.springframework.stereotype.Service
import top.fatweb.oxygen.api.entity.tool.ToolFavorite
import top.fatweb.oxygen.api.mapper.tool.ToolFavoriteMapper
import top.fatweb.oxygen.api.service.tool.IToolFavoriteService
/**
* Tool favorite service implement
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see ToolFavoriteMapper
* @see ToolFavorite
* @see IToolFavoriteService
*/
@Service
class ToolFavoriteServiceImpl : ServiceImpl<ToolFavoriteMapper, ToolFavorite>(), IToolFavoriteService

View File

@@ -24,6 +24,8 @@ import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IToolDataService
* @see IToolBaseService
* @see ServiceImpl
* @see ToolTemplateMapper
* @see ToolTemplate

View File

@@ -184,5 +184,14 @@ data class ToolVo(
* @see LocalDateTime
*/
@Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z")
val updateTime: LocalDateTime?
val updateTime: LocalDateTime?,
/**
* Favorite
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "收藏")
val favorite: Boolean?
)

View File

@@ -0,0 +1,12 @@
drop table if exists t_b_tool_favorite;
create table if not exists t_b_tool_favorite
(
id bigint not null primary key,
user_id bigint not null comment '用户 ID',
author_id bigint not null comment '作者 ID',
tool_id varchar(50) not null comment '工具 ID',
deleted bigint 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, author_id, tool_id, deleted)
) comment '工具-收藏表';

View File

@@ -94,7 +94,19 @@
and t_b_tool_main.id = #{id}
</select>
<select id="selectPersonal" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolMap">
<select id="selectPersonalToolIdPage" resultType="string">
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
where t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{userId}) tbtm
where tbtm.rn = 1
order by tbtm.id desc) t
</select>
<select id="selectListByToolIds" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolMap">
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,
@@ -126,9 +138,18 @@
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 t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{userId}
order by t_b_tool_main.id desc
<where>
and t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{userId}
<foreach collection="toolIds" item="item" index="index" open="and t_b_tool_main.tool_id in (" separator="," close=")"
nullable="true">
#{item}
</foreach>
</where>
<foreach collection="toolIds" item="item" index="index" open="order by field(t_b_tool_main.tool_id," separator=","
close="), t_b_tool_main.id desc" nullable="true">
#{item}
</foreach>
</select>
<select id="selectDetail" resultMap="top.fatweb.oxygen.api.mapper.tool.ManagementMapper.toolWithDataMap">
@@ -195,6 +216,7 @@
<choose>
<when test="operator == null">
and tsu.username = #{username}
and t_b_tool_main.publish != 0
</when>
<otherwise>
<choose>
@@ -206,11 +228,13 @@
</when>
<otherwise>
and tsu.username = #{username}
and t_b_tool_main.publish != 0
</otherwise>
</choose>
</otherwise>
</choose>
</where>
order by t_b_tool_main.id desc
limit 1
</select>
</mapper>

View File

@@ -237,6 +237,7 @@
<result property="createTime" column="tool_create_time"/>
<result property="deleted" column="tool_deleted"/>
<result property="version" column="tool_version"/>
<result property="favorite" column="tool_favorite"/>
<result property="keywords" column="tool_keywords"
typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<collection property="categories"

View File

@@ -8,12 +8,12 @@
from (select *, row_number() over (partition by t_b_tool_main.tool_id, t_b_tool_main.author_id order by t_b_tool_main.id desc) as rn1
from t_b_tool_main
where t_b_tool_main.deleted = 0
and t_b_tool_main.publish != 0 and t_b_tool_main.review = 'PASS'
) as temp0
where temp0.rn1 = 1
) as temp1
left join json_table(json_extract(temp1.keywords, '$[*]'), '$[*]' columns (keyword varchar(50) path '$')) as tk on true
<where>
and temp1.publish != 0 and temp1.review = 'PASS'
<if test="searchValue != null">
and (
temp1.name like concat('%', #{searchValue}, '%')
@@ -45,70 +45,18 @@
from (select *, row_number() over (partition by t_b_tool_main.tool_id, t_b_tool_main.author_id order by t_b_tool_main.id desc) as rn1
from t_b_tool_main
where t_b_tool_main.deleted = 0
and t_b_tool_main.publish != 0
and t_b_tool_main.review = 'PASS'
) as temp0
where temp0.rn1 = 1
) as temp1
left join (select * from t_s_user where deleted = 0) as tsu on tsu.id = temp1.author_id
where temp1.publish != 0
and temp1.review = 'PASS'
and tsu.username = #{username}
where tsu.username = #{username}
order by temp1.publish desc
) as temp2
where temp2.rn2 = 1
</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 tbtm.id as tool_id,
tbtm.name as tool_name,
@@ -140,7 +88,8 @@
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
tbtc.version as tool_category_version,
if(tbtf.id is null, 0, 1) as tool_favorite
from (select *, row_number() over (partition by t_b_tool_main.tool_id, t_b_tool_main.author_id, t_b_tool_main.platform order by t_b_tool_main.publish desc) as rn
from t_b_tool_main
where deleted = 0
@@ -149,11 +98,13 @@
) as tbtm
left join (select * from t_s_user where deleted = 0) as tsu on tsu.id = tbtm.author_id
left join (select * from t_s_user_info where deleted = 0) as tsui
on tsui.user_id = tbtm.author_id
on tsui.user_id = tbtm.author_id
left join (select * from t_r_tool_main_category where deleted = 0) as trtmc
on tbtm.id = trtmc.tool_id
on tbtm.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
on tbtc.id = trtmc.category_id
left join (select * from t_b_tool_favorite where deleted = 0) as tbtf
on tbtf.user_id = #{operator} and tbtf.author_id = tbtm.author_id and tbtf.tool_id = tbtm.tool_id
<where>
and tbtm.rn = 1
<foreach collection="ids" item="item" index="index" open="and concat(tbtm.author_id, ':', tbtm.tool_id) in (" separator="," close=")"
@@ -166,4 +117,14 @@
#{item}
</foreach>
</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>

View File

@@ -0,0 +1,10 @@
<?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="top.fatweb.oxygen.api.mapper.tool.ToolFavoriteMapper">
<resultMap id="toolFavoriteMap" type="toolFavorite">
<id property="id" column="tool_favorite_id"/>
<result property="userId" column="tool_favorite_user_id"/>
<result property="username" column="tool_favorite_username"/>
<result property="toolId" column="tool_favorite_tool_id"/>
</resultMap>
</mapper>