Add tool management api

This commit is contained in:
2024-02-02 17:43:09 +08:00
parent 13d8ba8e78
commit 9692550198
19 changed files with 557 additions and 188 deletions

View File

@@ -1,30 +1,88 @@
package top.fatweb.oxygen.api.controller.tool
import io.swagger.v3.oas.annotations.Operation
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import top.fatweb.oxygen.api.annotation.BaseController
import top.fatweb.oxygen.api.entity.common.ResponseCode
import top.fatweb.oxygen.api.entity.common.ResponseResult
import top.fatweb.oxygen.api.param.tool.ToolManagementGetParam
import top.fatweb.oxygen.api.service.tool.IManagementService
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
@BaseController(path = ["/system/tool"], name = "工具管理", description = "工具管理相关接口")
class ManagementController {
/* @Operation(summary = "获取单个工具")
@GetMapping("/{id}")
fun getOne(@PathVariable id: Long): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(data = toolService.getOne(id))
class ManagementController(
private val managementService: IManagementService
) {
/**
* Get tool by ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "获取单个工具")
@GetMapping("/{id}")
fun getOne(@PathVariable id: Long): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(data = managementService.getOne(id))
@Operation(summary = "获取工具")
@GetMapping
fun get(): ResponseResult<List<ToolVo>> =
ResponseResult.databaseSuccess(data = toolService.get())
/**
* Get tool paging information
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "获取工具")
@GetMapping
fun get(toolManagementGetParam: ToolManagementGetParam): ResponseResult<PageVo<ToolVo>> =
ResponseResult.databaseSuccess(data = managementService.getPage(toolManagementGetParam))
/**
* Pass tool review
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "通过审核")
@PostMapping("/{id}")
fun pass(@PathVariable id: Long): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = managementService.pass(id))
@Operation(summary = "更新工具")
@PutMapping
fun update(@RequestBody @Valid toolUpdateParam: ToolUpdateParam): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(
ResponseCode.DATABASE_UPDATE_SUCCESS,
data = toolService.update(toolUpdateParam)
)
/**
* Reject tool review
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "驳回审核")
@PutMapping("/{id}")
fun reject(@PathVariable id: Long): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = managementService.reject(id))
@Operation(summary = "删除工具")
@DeleteMapping("/{id}")
fun delete(@PathVariable id: Long): ResponseResult<Nothing> =
if (toolService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED)*/
/**
* Put off shelve
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "下架")
@PatchMapping("/{id}")
fun offShelve(@PathVariable id: Long):ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = managementService.offShelve(id))
/**
* Delete tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "删除工具")
@DeleteMapping("/{id}")
fun delete(@PathVariable id: Long): ResponseResult<Nothing> =
if (managementService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED)
}

View File

@@ -1,7 +1,9 @@
package top.fatweb.oxygen.api.converter.tool
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import top.fatweb.oxygen.api.converter.permission.UserConverter
import top.fatweb.oxygen.api.entity.tool.Tool
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
/**
@@ -40,4 +42,12 @@ object ToolConverter {
createTime = tool.createTime,
updateTime = tool.updateTime
)
fun toolPageToToolPageVo(toolPage: Page<Tool>): PageVo<ToolVo> = PageVo(
total = toolPage.total,
pages = toolPage.pages,
size = toolPage.size,
current = toolPage.current,
records = toolPage.records.map(this::toolToToolVo)
)
}

View File

@@ -64,7 +64,8 @@ enum class ResponseCode(val code: Int) {
TOOL_UNDER_REVIEW(BusinessCode.TOOL, 51),
TOOL_NOT_UNDER_REVIEW(BusinessCode.TOOL, 52),
TOOL_HAS_UNPUBLISHED_VERSION(BusinessCode.TOOL, 53),
TOOL_HAS_BEEN_PUBLISHED(BusinessCode.TOOL, 54),
TOOL_HAS_NOT_BEEN_PUBLISHED(BusinessCode.TOOL, 54),
TOOL_HAS_BEEN_PUBLISHED(BusinessCode.TOOL, 55),
TOOL_SUBMIT_ERROR(BusinessCode.TOOL, 60),
TOOL_CANCEL_ERROR(BusinessCode.TOOL, 61),

View File

@@ -0,0 +1,10 @@
package top.fatweb.oxygen.api.exception
/**
* Tool has not been published exception
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see RuntimeException
*/
class ToolHasNotBeenPublishedException : RuntimeException("Tool has not been published")

View File

@@ -232,6 +232,11 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.TOOL_HAS_UNPUBLISHED_VERSION, e.localizedMessage, null)
}
is ToolHasNotBeenPublishedException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.TOOL_HAS_NOT_BEEN_PUBLISHED, e.localizedMessage, null)
}
is ToolHasBeenPublishedException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.TOOL_HAS_BEEN_PUBLISHED, e.localizedMessage, null)

View File

@@ -0,0 +1,30 @@
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
/**
* Tool mapper
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see BaseMapper
* @see Tool
*/
@Mapper
interface ManagementMapper : BaseMapper<Tool> {
fun selectOne(@Param("id") id: Long): Tool?
fun selectPage(
page: IPage<Long>,
@Param("review") review: List<String>?,
@Param("searchType") searchType: String,
@Param("searchValue") searchValue: String?,
@Param("searchRegex") searchRegex: Boolean
): IPage<Long>
fun selectListByIds(@Param("ids") ids: List<Long>): List<Tool>
}

View File

@@ -1,16 +0,0 @@
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.Tool
/**
* Tool mapper
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see BaseMapper
* @see Tool
*/
@Mapper
interface ToolMapper : BaseMapper<Tool>

View File

@@ -20,7 +20,11 @@ data class SysLogGetParam(
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "类型过滤(多个使用逗号分隔)", allowableValues = ["INFO", "ERROR"], example = "INFO")
@Schema(
description = "类型过滤(多个使用逗号分隔)",
allowableValues = ["INFO", "LOGIN", "LOGOUT", "REGISTER", "STATISTICS", "API", "ERROR"],
example = "INFO"
)
val logType: String?,
/**
@@ -51,10 +55,10 @@ data class SysLogGetParam(
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
/*
@Schema(description = "查询使用正则表达式", allowableValues = ["true", "false"], defaultValue = "false")
val searchRegex: Boolean = false,
*/
/*
@Schema(description = "查询使用正则表达式", allowableValues = ["true", "false"], defaultValue = "false")
val searchRegex: Boolean = false,
*/
/**
* Start time to search for

View File

@@ -0,0 +1,54 @@
package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema
import top.fatweb.oxygen.api.param.PageSortParam
data class ToolManagementGetParam(
/**
* Type of search
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(
description = "搜索类型",
allowableValues = ["ALL", "ID", "USERNAME", "NICKNAME", "EMAIL"],
defaultValue = "ALL",
example = "ALL"
)
val searchType: String = "ALL",
/**
* Value to search for
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "查询内容", example = "ToolName")
val searchValue: String?,
/**
* Use regex
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(
description = "查询使用正则表达式",
allowableValues = ["true", "false"],
defaultValue = "false",
example = "false"
)
val searchRegex: Boolean = false,
/**
* Review
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "审核状态过滤(多个使用逗号分隔)",
allowableValues = ["NONE", "PROCESSING", "REJECT", "PASS"],
example = "NONE,PASS")
val review: String?
) : PageSortParam()

View File

@@ -0,0 +1,29 @@
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.tool.ToolManagementGetParam
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
/**
* Tool management service interface
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see IService
* @see Tool
*/
interface IManagementService : IService<Tool> {
fun getOne(id: Long): ToolVo
fun getPage(toolManagementGetParam: ToolManagementGetParam?): PageVo<ToolVo>
fun pass(id: Long): ToolVo
fun reject(id: Long): ToolVo
fun offShelve(id: Long): ToolVo
fun delete(id: Long): Boolean
}

View File

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

View File

@@ -190,7 +190,9 @@ class EditServiceImpl(
categoryId = it
})
}
}
if (!toolUpdateParam.source.isNullOrBlank()) {
toolDataService.updateById(ToolData().apply {
id = tool.sourceId
data = toolUpdateParam.source

View File

@@ -0,0 +1,125 @@
package top.fatweb.oxygen.api.service.tool.impl
import com.baomidou.mybatisplus.core.metadata.OrderItem
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.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import top.fatweb.oxygen.api.converter.tool.ToolConverter
import top.fatweb.oxygen.api.entity.tool.RToolCategory
import top.fatweb.oxygen.api.entity.tool.Tool
import top.fatweb.oxygen.api.exception.NoRecordFoundException
import top.fatweb.oxygen.api.exception.ToolHasNotBeenPublishedException
import top.fatweb.oxygen.api.exception.ToolNotUnderReviewException
import top.fatweb.oxygen.api.mapper.tool.ManagementMapper
import top.fatweb.oxygen.api.param.tool.ToolManagementGetParam
import top.fatweb.oxygen.api.service.tool.IEditService
import top.fatweb.oxygen.api.service.tool.IManagementService
import top.fatweb.oxygen.api.service.tool.IRToolCategoryService
import top.fatweb.oxygen.api.service.tool.IToolDataService
import top.fatweb.oxygen.api.util.PageUtil
import top.fatweb.oxygen.api.util.WebUtil
import top.fatweb.oxygen.api.vo.PageVo
import top.fatweb.oxygen.api.vo.tool.ToolVo
import java.time.LocalDateTime
import java.time.ZoneOffset
/**
* Tool management service implement
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see ManagementMapper
* @see Tool
* @see IManagementService
*/
@Service
class ManagementServiceImpl(
private val toolDataService: IToolDataService,
private val rToolCategoryService: IRToolCategoryService
) : ServiceImpl<ManagementMapper, Tool>(), IManagementService {
override fun getOne(id: Long): ToolVo =
baseMapper.selectOne(id)
?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException()
override fun getPage(toolManagementGetParam: ToolManagementGetParam?): PageVo<ToolVo> {
val toolIdsPage = Page<Long>(toolManagementGetParam?.currentPage ?: 1, toolManagementGetParam?.pageSize ?: 20)
PageUtil.setPageSort(toolManagementGetParam, toolIdsPage, OrderItem.desc("id"))
val toolIdsIPage =
baseMapper.selectPage(
toolIdsPage,
toolManagementGetParam?.review?.split(","),
toolManagementGetParam?.searchType ?: "ALL",
toolManagementGetParam?.searchValue,
toolManagementGetParam?.searchRegex ?: false
)
val toolPage = Page<Tool>(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total)
if (toolIdsIPage.total > 0) {
toolPage.setRecords(baseMapper.selectListByIds(toolIdsIPage.records))
}
return ToolConverter.toolPageToToolPageVo(toolPage)
}
override fun pass(id: Long): ToolVo {
val tool = this.getById(id) ?: throw NoRecordFoundException()
if (tool.review !== Tool.ReviewType.PROCESSING) {
throw ToolNotUnderReviewException()
}
this.update(
KtUpdateWrapper(Tool())
.eq(Tool::id, id)
.set(Tool::review, Tool.ReviewType.PASS)
.set(Tool::publish, LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli())
)
return this.getOne(id)
}
override fun reject(id: Long): ToolVo {
val tool = this.getById(id) ?: throw NoRecordFoundException()
if (tool.review !== Tool.ReviewType.PROCESSING) {
throw ToolNotUnderReviewException()
}
this.update(
KtUpdateWrapper(Tool())
.eq(Tool::id, id)
.set(Tool::review, Tool.ReviewType.REJECT)
)
return this.getOne(id)
}
override fun offShelve(id: Long): ToolVo {
val tool = this.getById(id) ?: throw NoRecordFoundException()
if (tool.review !== Tool.ReviewType.PASS && tool.publish == 0L) {
throw ToolHasNotBeenPublishedException()
}
this.update(
KtUpdateWrapper(Tool())
.eq(Tool::id, id)
.set(Tool::review, Tool.ReviewType.REJECT)
.set(Tool::publish, 0)
)
return this.getOne(id)
}
@Transactional
override fun delete(id: Long): Boolean {
val tool = this.getById(id) ?: throw NoRecordFoundException()
toolDataService.removeBatchByIds(listOf(tool.sourceId, tool.distId))
rToolCategoryService.remove(KtQueryWrapper(RToolCategory()).eq(RToolCategory::toolId, id))
return this.removeById(id)
}
}

View File

@@ -1,70 +0,0 @@
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.Tool
import top.fatweb.oxygen.api.mapper.tool.ToolMapper
import top.fatweb.oxygen.api.service.tool.IToolService
/**
* Tool service implement
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ServiceImpl
* @see ToolMapper
* @see Tool
* @see IToolService
*/
@Service
class ToolServiceImpl : ServiceImpl<ToolMapper, Tool>(), IToolService {
/*
override fun getOne(id: Long): ToolVo =
baseMapper.selectOne(id)?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException()
override fun get(): List<ToolVo> = baseMapper.selectList().map(ToolConverter::toolToToolVo)
@Transactional
override fun update(toolUpdateParam: ToolUpdateParam): ToolVo {
val tool = baseMapper.selectOne(toolUpdateParam.id!!) ?: throw NoRecordFoundException()
if (tool.publish == 1) {
throw ToolHasPublish()
}
userService.getOne(toolUpdateParam.authorId!!)
toolDataService.updateById(ToolData().apply {
id = tool.sourceId
data = toolUpdateParam.source
})
toolDataService.updateById(ToolData().apply {
id = tool.distId
data = toolUpdateParam.dist
})
this.updateById(Tool().apply {
id = toolUpdateParam.id
name = toolUpdateParam.name
toolId = toolUpdateParam.toolId
description = toolUpdateParam.description
authorId = toolUpdateParam.authorId
ver = toolUpdateParam.ver
privately = toolUpdateParam.privately?.let { if (it) 1 else 0 }
keywords = toolUpdateParam.keywords
})
// TODO Category process
return this.getOne(tool.id!!)
}
@Transactional
override fun delete(id: Long): Boolean {
val tool = this.getById(id)
return toolDataService.removeBatchByIds(listOf(tool.sourceId, tool.distId))
&& rToolCategoryService.remove(KtQueryWrapper(RToolCategory()).eq(RToolCategory::toolId, tool.id))
&& this.removeById(tool.id)
}
*/
}