From 3138539bc5a4cec38ce017afff0cd6eabfc3ab10 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Tue, 17 Dec 2024 18:29:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20=E5=AE=9E=E7=8E=B0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E4=BA=A7=E5=93=81=E4=B8=8A=E6=9E=B6=E5=AE=A1=E6=A0=B8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增数据产品列表、详情、编辑等功能页面 - 实现数据产品提交审核、撤销审核、同意审核等操作 - 优化数据产品相关API接口,支持审核功能 - 重构部分代码以支持新功能 --- gringotts-frontend/components/constants.js | 3 +- .../components/ware/dialog-ware.js | 52 +++++-- gringotts-frontend/pages/index/tab-check.js | 35 +++++ gringotts-frontend/pages/index/tab-market.js | 128 +++++++++++++++++- .../web/configuration/HostConfiguration.java | 16 +++ .../configuration/SaTokenConfiguration.java | 11 +- .../domain/controller/DataFileController.java | 19 +-- .../web/domain/controller/WareController.java | 83 ++++++++---- .../web/domain/entity/CheckOrder.java | 1 + .../gringotts/web/domain/entity/Ware.java | 5 +- .../web/domain/service/DataFileService.java | 4 + .../web/domain/service/WareService.java | 80 ++++++++++- 12 files changed, 377 insertions(+), 60 deletions(-) create mode 100644 gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/HostConfiguration.java diff --git a/gringotts-frontend/components/constants.js b/gringotts-frontend/components/constants.js index 8f70f83..697087d 100644 --- a/gringotts-frontend/components/constants.js +++ b/gringotts-frontend/components/constants.js @@ -1,5 +1,5 @@ export const information = { - debug: true, + debug: false, // baseUrl: '', baseUrl: 'http://127.0.0.1:20080', title: '可信供给中心', @@ -262,6 +262,7 @@ export const permissionStateMapping = [ export const checkTypeMapping = [ mappingItem('确权审查', 'CONFIRMATION', 'bg-blue-500'), mappingItem('授权审查', 'AUTHENTICATION', 'bg-purple-500'), + mappingItem('上架审查', 'MARKET', 'bg-green-500'), ] export const checkOverMapping = [ diff --git a/gringotts-frontend/components/ware/dialog-ware.js b/gringotts-frontend/components/ware/dialog-ware.js index bcc524e..35c608a 100644 --- a/gringotts-frontend/components/ware/dialog-ware.js +++ b/gringotts-frontend/components/ware/dialog-ware.js @@ -5,6 +5,7 @@ import {resourceDetailDialog} from '../resource/dialog-resource.js' function detailForm() { return { + id: 'ware-form', debug: information.debug, type: 'form', ...horizontalFormOptions(), @@ -17,13 +18,38 @@ function detailForm() { name: 'id', }, { + visibleOn: '${!detail}', type: 'input-image', name: 'icon', label: '图标', required: true, receiver: apiPost("${base}/upload"), - autoFill: { - iconId: '${id}', + onEvent: { + success: { + actions: [ + { + actionType: 'setValue', + componentId: 'ware-form', + args: { + value: { + iconId: '${event.data.result.id}' + } + } + } + ] + } + } + }, + { + visibleOn: '${detail}', + type: 'control', + name: 'icon', + label: '图标', + required: true, + body: { + type: 'image', + src: '${icon}', + innerClassName: 'no-border', } }, { @@ -79,7 +105,7 @@ function detailForm() { name: 'content', label: '商品详情', required: true, - receiver: '', + receiver: apiPost("${base}/upload"), options: { min_height: 300, } @@ -108,21 +134,28 @@ export function wareAddDialog() { body: { ...detailForm(), api: apiPost(`\${base}/ware/save`), + data: { + add: true, + } } } } } -export function wareDetailDialog() { +export function wareDetailDialog(field = 'id', actions = []) { return { actionType: 'dialog', dialog: { - title: '确权申请详情', + title: '数据产品详情', size: 'md', + actions: actions, body: { ...detailForm(), - initApi: apiGet(`\${base}/ware/detail/\${id}`), + initApi: apiGet(`\${base}/ware/detail/\${${field}}`), static: true, + data: { + detail: true, + } } } } @@ -132,7 +165,7 @@ export function wareEditeDialog() { return { actionType: 'dialog', dialog: { - title: '确权申请详情', + title: '数据产品详情', size: 'md', actions: [ { @@ -148,7 +181,10 @@ export function wareEditeDialog() { body: { ...detailForm(), api: apiPost(`\${base}/ware/save`), - initApi: apiGet(`\${base}/ware/detail/\${${field}}`), + initApi: apiGet(`\${base}/ware/detail/\${id}`), + data: { + edit: true + } }, } } diff --git a/gringotts-frontend/pages/index/tab-check.js b/gringotts-frontend/pages/index/tab-check.js index 36f895d..1a185e2 100644 --- a/gringotts-frontend/pages/index/tab-check.js +++ b/gringotts-frontend/pages/index/tab-check.js @@ -10,6 +10,7 @@ import { timeField, } from "../../components/constants.js"; import {authenticationDetailDialog, confirmationDetailDialog} from "../../components/permission/dialog-permission.js"; +import {wareDetailDialog} from "../../components/ware/dialog-ware.js"; export function tabCheck() { return { @@ -103,6 +104,40 @@ export function tabCheck() { level: 'link', ...authenticationDetailDialog('parameters.authenticationId'), }, + { + visibleOn: `\${type === 'MARKET' && state === 'CHECKING'}`, + type: 'action', + label: '处理', + level: 'link', + ...wareDetailDialog( + 'parameters.wareId', + [ + { + type: 'action', + label: '同意', + actionType: 'ajax', + close: true, + api: apiGet('${base}/check_order/operation/${checkOrderId}/APPLY'), + reload: 'check_order_list', + }, + { + type: 'action', + label: '拒绝', + actionType: 'ajax', + close: true, + api: apiGet('${base}/check_order/operation/${checkOrderId}/REJECT'), + reload: 'check_order_list', + }, + ], + ), + }, + { + visibleOn: `\${type === 'MARKET' && state !== NORMAL}`, + type: 'action', + label: '查看', + level: 'link', + ...wareDetailDialog('parameters.wareId'), + }, ]), ], }, diff --git a/gringotts-frontend/pages/index/tab-market.js b/gringotts-frontend/pages/index/tab-market.js index fec9386..a86846f 100644 --- a/gringotts-frontend/pages/index/tab-market.js +++ b/gringotts-frontend/pages/index/tab-market.js @@ -1,16 +1,132 @@ -import {wareAddDialog} from "../../components/ware/dialog-ware.js"; +import {wareAddDialog, wareDetailDialog, wareEditeDialog} from "../../components/ware/dialog-ware.js"; +import { + apiGet, + crudCommonOptions, + mappingField, + operationField, + permissionStateMapping, + timeField +} from "../../components/constants.js"; + +function listColumns() { + return { + columns: [ + { + name: 'name', + label: '名称', + width: 200, + }, + { + name: 'description', + label: '描述', + }, + { + visibleOn: '${!public}', + ...mappingField('state', '状态', permissionStateMapping) + }, + timeField('createdTime', '创建时间'), + operationField('操作', undefined, [ + { + type: 'action', + label: '查看', + level: 'link', + ...wareDetailDialog(), + }, + { + visibleOn: "${state === 'CHECKING'}", + type: 'action', + label: '撤销', + level: 'link', + confirmTitle: '确认撤销', + confirmText: '确认撤销名称为「${name}」的确权申请吗?', + actionType: 'ajax', + api: apiGet('${base}/ware/retract/${id}'), + }, + { + visibleOn: "${state === 'DRAFT' || state === 'REJECT'}", + type: 'action', + label: '提交', + level: 'link', + confirmTitle: '确认提交', + confirmText: '确认提交名称为「${name}」的确权申请吗?', + actionType: 'ajax', + api: apiGet('${base}/ware/submit/${id}'), + }, + { + visibleOn: "${!public}", + type: 'dropdown-button', + level: 'link', + icon: 'fa fa-ellipsis-h', + hideCaret: true, + trigger: 'hover', + buttons: [ + { + disabledOn: "${state !== 'DRAFT'}", + type: 'action', + label: '编辑', + level: 'link', + ...wareEditeDialog(), + }, + { + disabledOn: "${state === 'CHECKING'}", + type: 'action', + label: "删除", + confirmTitle: '确认删除', + confirmText: '确认删除名称为「${name}」的确权申请吗?删除后对应的数据资源处于未确权状态。', + actionType: 'ajax', + api: apiGet('${base}/ware/remove/${id}'), + }, + ] + }, + ]), + ] + } +} export function tabMarket() { return { title: '数据市场', icon: 'fa fa-store', + reload: true, body: [ { - type: 'action', - label: '', - icon: 'fa fa-plus', - ...wareAddDialog() - }, + type: 'tabs', + tabs: [ + { + title: '公开数据', + body: { + type: 'crud', + api: apiGet('${base}/ware/list_public'), + ...crudCommonOptions(), + headerToolbar: [ + 'reload', + ], + data: { + public: true + }, + ...listColumns(), + } + }, + { + title: '我的数据', + body: { + type: 'crud', + api: apiGet('${base}/ware/list'), + ...crudCommonOptions(), + headerToolbar: [ + 'reload', + { + type: 'action', + label: '', + icon: 'fa fa-plus', + ...wareAddDialog() + }, + ], + ...listColumns(), + } + }, + ] + } ] } } \ No newline at end of file diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/HostConfiguration.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/HostConfiguration.java new file mode 100644 index 0000000..eafffc8 --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/HostConfiguration.java @@ -0,0 +1,16 @@ +package com.eshore.gringotts.web.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author lanyuanxiaoyao + * @date 2024-12-17 + */ +@Data +@ConfigurationProperties(prefix = "gringotts.host") +@Configuration +public class HostConfiguration { + private String prefix = "http://127.0.0.1:20080"; +} diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/SaTokenConfiguration.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/SaTokenConfiguration.java index 063e3b4..630bc03 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/SaTokenConfiguration.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/configuration/SaTokenConfiguration.java @@ -3,8 +3,7 @@ package com.eshore.gringotts.web.configuration; import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -12,13 +11,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * web配置 * - * @author lanyuanxiaoyao - * @date 2024-11-14 + * @author wn + * @since 2024-11-14 */ +@Slf4j @Configuration public class SaTokenConfiguration implements WebMvcConfigurer { - private static final Logger logger = LoggerFactory.getLogger(SaTokenConfiguration.class); - @Override public void addInterceptors(InterceptorRegistry registry) { registry @@ -31,6 +29,7 @@ public class SaTokenConfiguration implements WebMvcConfigurer { .notMatch("/assets/**") .notMatch("/pages/**") .notMatch("/user/**") + .notMatch("/upload/download/**") .check(r -> { try { StpUtil.checkLogin(); diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/DataFileController.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/DataFileController.java index b95ca16..c406259 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/DataFileController.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/DataFileController.java @@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; +import com.eshore.gringotts.web.configuration.HostConfiguration; import com.eshore.gringotts.web.configuration.UploadConfiguration; import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.domain.entity.DataFile; @@ -19,9 +20,8 @@ import javax.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.eclipse.collections.api.list.ImmutableList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -37,17 +37,18 @@ import org.springframework.web.multipart.MultipartFile; * @author lanyuanxiaoyao * @date 2024-11-21 */ +@Slf4j @RestController @RequestMapping("/upload") public class DataFileController { - private static final Logger logger = LoggerFactory.getLogger(DataFileController.class); - + private final HostConfiguration hostConfiguration; private final DataFileService dataFileService; private final String uploadFolderPath; private final String cacheFolderPath; private final String sliceFolderPath; - public DataFileController(UploadConfiguration uploadConfiguration, DataFileService dataFileService) { + public DataFileController(HostConfiguration hostConfiguration, UploadConfiguration uploadConfiguration, DataFileService dataFileService) { + this.hostConfiguration = hostConfiguration; this.dataFileService = dataFileService; this.uploadFolderPath = uploadConfiguration.getUploadPath(); @@ -59,7 +60,7 @@ public class DataFileController { public AmisResponse upload(@RequestParam("file") MultipartFile file) throws IOException { String filename = file.getOriginalFilename(); Long id = dataFileService.initialDataFile(filename); - String url = StrUtil.format("/upload/download/{}", id); + String url = StrUtil.format("{}/upload/download/{}", hostConfiguration.getPrefix(), id); byte[] bytes = file.getBytes(); String originMd5 = SecureUtil.md5(new ByteArrayInputStream(bytes)); File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, originMd5)); @@ -80,7 +81,7 @@ public class DataFileController { @GetMapping("/download/{id}") public void download(@PathVariable Long id, HttpServletResponse response) throws IOException { - DataFile dataFile = dataFileService.detailOrThrow(id); + DataFile dataFile = dataFileService.downloadFile(id); File targetFile = new File(dataFile.getPath()); response.setHeader("Access-Control-Expose-Headers", "Content-Type"); response.setHeader("Content-Type", dataFile.getType()); @@ -91,7 +92,7 @@ public class DataFileController { @PostMapping("/start") public AmisResponse start(@RequestBody StartRequest request) { - logger.info("Request: {}", request); + log.info("Request: {}", request); Long id = dataFileService.initialDataFile(request.filename); return AmisResponse.responseSuccess(new StartResponse(id.toString())); } @@ -158,7 +159,7 @@ public class DataFileController { request.uploadId, request.filename, request.uploadId.toString(), - StrUtil.format("/upload/download/{}", request.uploadId) + StrUtil.format("{}/upload/download/{}", hostConfiguration.getPrefix(), request.uploadId) )); } else { throw new RuntimeException("合并文件失败"); diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/WareController.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/WareController.java index 408c61e..4769b8a 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/WareController.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/WareController.java @@ -1,5 +1,8 @@ package com.eshore.gringotts.web.domain.controller; +import cn.hutool.core.util.StrUtil; +import com.eshore.gringotts.web.configuration.HostConfiguration; +import com.eshore.gringotts.web.configuration.amis.AmisResponse; import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport; import com.eshore.gringotts.web.domain.base.entity.SimpleListItem; import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem; @@ -7,33 +10,59 @@ import com.eshore.gringotts.web.domain.entity.Ware; import com.eshore.gringotts.web.domain.service.DataFileService; import com.eshore.gringotts.web.domain.service.DataResourceService; import com.eshore.gringotts.web.domain.service.WareService; +import com.fasterxml.jackson.core.JsonProcessingException; import java.time.LocalDateTime; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; +import org.eclipse.collections.api.list.ImmutableList; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author lanyuanxiaoyao - * @date 2024-12-13 + * @version 2024-12-13 */ @Slf4j @RestController @RequestMapping("ware") public class WareController extends SimpleControllerSupport { + private final HostConfiguration hostConfiguration; + private final WareService wareService; private final DataResourceService dataResourceService; private final DataFileService dataFileService; - public WareController(WareService service, DataResourceService dataResourceService, DataFileService dataFileService) { + public WareController(HostConfiguration hostConfiguration, WareService service, DataResourceService dataResourceService, DataFileService dataFileService) { super(service); + this.hostConfiguration = hostConfiguration; + this.wareService = service; this.dataResourceService = dataResourceService; this.dataFileService = dataFileService; } + @GetMapping(LIST + "_public") + public AmisResponse> listPublic() throws Exception { + return AmisResponse.responseSuccess(wareService.listPublic().collect(this::toListItem)); + } + + @GetMapping("/submit/{id}") + public AmisResponse submit(@PathVariable Long id) throws JsonProcessingException { + wareService.submit(id); + return AmisResponse.responseSuccess(); + } + + @GetMapping("/retract/{id}") + public AmisResponse retract(@PathVariable Long id) { + wareService.retract(id); + return AmisResponse.responseSuccess(); + } + @Override - protected Ware fromSaveItem(SaveItem saveItem) throws Exception { + protected Ware fromSaveItem(SaveItem saveItem) { Ware ware = new Ware(); + ware.setId(saveItem.getId()); ware.setResource(dataResourceService.detailOrThrow(saveItem.getResourceId())); ware.setName(saveItem.getName()); ware.setDescription(saveItem.getDescription()); @@ -43,13 +72,33 @@ public class WareController extends SimpleControllerSupport { private String name; private String description; - - public ListItem(Ware ware) { - this.setId(ware.getId()); - this.setName(ware.getName()); - this.setDescription(ware.getDescription()); - this.setCreatedTime(ware.getCreatedTime()); - this.setCreatedUsername(ware.getCreatedUser().getUsername()); - } + private String state; } @Data @EqualsAndHashCode(callSuper = true) public static class DetailItem extends SaveItem { + private String icon; private String resourceName; private LocalDateTime createdTime; private String createdUsername; private LocalDateTime modifiedTime; private String modifiedUsername; - - public DetailItem(Ware ware) { - this.setId(ware.getId()); - this.setResourceId(ware.getResource().getId()); - this.setResourceName(ware.getResource().getName()); - this.setName(ware.getName()); - this.setDescription(ware.getDescription()); - this.setIconId(ware.getIcon().getId()); - this.setContent(ware.getContent()); - } } } diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/CheckOrder.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/CheckOrder.java index cc18d38..1e90f38 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/CheckOrder.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/CheckOrder.java @@ -114,6 +114,7 @@ public class CheckOrder extends SimpleEntity { public enum Type { CONFIRMATION, AUTHENTICATION, + MARKET, } public enum Target { diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/Ware.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/Ware.java index 3adb2d7..ff6aa0e 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/Ware.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/Ware.java @@ -1,6 +1,7 @@ package com.eshore.gringotts.web.domain.entity; import com.eshore.gringotts.core.Constants; +import com.eshore.gringotts.web.domain.base.entity.CheckingNeededEntity; import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; import javax.persistence.Basic; import javax.persistence.CascadeType; @@ -48,7 +49,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; }) @SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "ware" + " set deleted = true where id = ?") @Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE) -public class Ware extends LogicDeleteEntity { +public class Ware extends CheckingNeededEntity { @OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @ToString.Exclude @@ -57,7 +58,7 @@ public class Ware extends LogicDeleteEntity { private String name; @Column(nullable = false) private String description; - @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) + @OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY) @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) @ToString.Exclude private DataFile icon; diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/DataFileService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/DataFileService.java index 1753b75..7c41744 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/DataFileService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/DataFileService.java @@ -68,6 +68,10 @@ public class DataFileService extends SimpleServiceSupport { )); } + public DataFile downloadFile(Long id) { + return dataFileRepository.findOne((root, query, builder) -> builder.equal(root.get(DataFile_.id), id)).orElseThrow(DataFileNotFoundException::new); + } + public Long initialDataFile(String filename) { DataFile dataFile = new DataFile(); dataFile.setFilename(filename); diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java index 4d75ecc..1ebd1c7 100644 --- a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java @@ -1,9 +1,21 @@ package com.eshore.gringotts.web.domain.service; +import cn.hutool.core.util.StrUtil; +import com.eshore.gringotts.web.domain.base.service.CheckingService; import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport; +import com.eshore.gringotts.web.domain.entity.CheckOrder; +import com.eshore.gringotts.web.domain.entity.User; import com.eshore.gringotts.web.domain.entity.Ware; import com.eshore.gringotts.web.domain.repository.WareRepository; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Maps; +import org.eclipse.collections.api.list.ImmutableList; +import org.eclipse.collections.api.map.ImmutableMap; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.stereotype.Service; /** @@ -11,9 +23,71 @@ import org.springframework.stereotype.Service; * @date 2024-12-13 */ @Slf4j -@Service -public class WareService extends SimpleServiceSupport { - public WareService(WareRepository repository, UserService userService) { +@Service("com.eshore.gringotts.web.domain.service.WareService") +public class WareService extends SimpleServiceSupport implements CheckingService { + private final WareRepository wareRepository; + private final CheckOrderService checkOrderService; + private final ObjectMapper mapper; + + public WareService(WareRepository repository, UserService userService, CheckOrderService checkOrderService, Jackson2ObjectMapperBuilder builder) { super(repository, userService); + this.wareRepository = repository; + this.checkOrderService = checkOrderService; + this.mapper = builder.build(); + } + + public ImmutableList listPublic() { + return Lists.immutable.ofAll( + wareRepository.findAll((root, query, builder) -> builder.equal(root.get("state"), Ware.State.NORMAL)) + ); + } + + @Transactional(rollbackOn = Throwable.class) + @Override + public void onChecked(CheckOrder order, CheckOrder.Operation operation, ImmutableMap parameters) { + if (StrUtil.equals(order.getKeyword(), "ware_check")) { + Long wareId = (Long) parameters.get("wareId"); + Ware ware = detailOrThrow(wareId); + switch (operation) { + case APPLY: + ware.setState(Ware.State.NORMAL); + order.setState(CheckOrder.State.OVER); + break; + case REJECT: + ware.setState(Ware.State.DRAFT); + order.setState(CheckOrder.State.OVER); + break; + } + save(ware); + checkOrderService.save(order); + } + } + + @Transactional(rollbackOn = Throwable.class) + public void submit(Long id) throws JsonProcessingException { + Ware ware = detailOrThrow(id); + ware.setState(Ware.State.CHECKING); + Long orderId = checkOrderService.save(new CheckOrder( + "ware_check", + StrUtil.format("数据资源「{}」的上架申请", ware.getName()), + CheckOrder.Type.MARKET, + mapper.writeValueAsString(Maps.immutable.of("wareId", ware.getId())), + "com.eshore.gringotts.web.domain.service.WareService", + User.Role.CHECKER + )); + CheckOrder order = checkOrderService.detailOrThrow(orderId); + ware.setOrder(order); + save(ware); + } + + @Transactional(rollbackOn = Throwable.class) + public void retract(Long id) { + Ware ware = detailOrThrow(id); + ware.setState(Ware.State.DRAFT); + save(ware); + + CheckOrder order = ware.getOrder(); + order.setState(CheckOrder.State.RETRACT); + checkOrderService.save(order); } }