diff --git a/gringotts-frontend/components/ware/dialog-ware.css b/gringotts-frontend/components/ware/dialog-ware.css new file mode 100644 index 0000000..e297e56 --- /dev/null +++ b/gringotts-frontend/components/ware/dialog-ware.css @@ -0,0 +1,3 @@ +textarea { + resize: none !important; +} \ No newline at end of file diff --git a/gringotts-frontend/components/ware/dialog-ware.js b/gringotts-frontend/components/ware/dialog-ware.js new file mode 100644 index 0000000..49ac8b6 --- /dev/null +++ b/gringotts-frontend/components/ware/dialog-ware.js @@ -0,0 +1,119 @@ +import './dialog-ware.css' +import {apiGet, apiPost, formInputClearable, horizontalFormOptions, information} from "../constants.js"; + +function detailForm() { + return { + debug: information.debug, + type: 'form', + ...horizontalFormOptions(), + horizontal: { + left: 2, + }, + body: [ + { + type: 'hidden', + name: 'id', + }, + { + type: 'input-image', + name: 'icon', + label: '图标', + }, + { + type: 'input-text', + name: 'name', + label: '商品名称', + maxLength: 10, + showCounter: true, + required: true, + ...formInputClearable, + }, + { + type: 'textarea', + name: 'description', + label: '商品简介', + required: true, + ...formInputClearable, + showCounter: true, + trimContents: true, + minRows: 2, + maxRows: 2, + }, + { + type: 'input-rich-text', + name: 'content', + label: '商品详情', + required: true, + options: { + min_height: 300, + } + } + ] + } +} + +export function wareAddDialog() { + return { + actionType: 'dialog', + dialog: { + title: '上架数据产品', + size: 'md', + actions: [ + { + type: 'reset', + label: '重置', + }, + { + type: 'submit', + label: '确定', + level: 'primary', + } + ], + body: { + ...detailForm(), + api: apiPost(`\${base}/ware/save`), + } + } + } +} + +export function wareDetailDialog() { + return { + actionType: 'dialog', + dialog: { + title: '确权申请详情', + size: 'md', + body: { + ...detailForm(), + initApi: apiGet(`\${base}/ware/detail/\${id}`), + static: true, + } + } + } +} + +export function wareEditeDialog() { + return { + actionType: 'dialog', + dialog: { + title: '确权申请详情', + size: 'md', + actions: [ + { + type: 'reset', + label: '重置', + }, + { + type: 'submit', + label: '确定', + level: 'primary', + } + ], + body: { + ...detailForm(), + api: apiPost(`\${base}/ware/save`), + initApi: apiGet(`\${base}/ware/detail/\${${field}}`), + }, + } + } +} diff --git a/gringotts-frontend/pages/index/main.js b/gringotts-frontend/pages/index/main.js index 08aaf4f..ec62db0 100644 --- a/gringotts-frontend/pages/index/main.js +++ b/gringotts-frontend/pages/index/main.js @@ -5,6 +5,7 @@ import {tabData} from "./tab-data.js"; import {tabSettings} from "./tab-settings.js"; import {tabCheck} from "./tab-check.js"; import {tabPermissions} from "./tab-permissions.js"; +import {tabMarket} from "./tab-market.js"; useAmis(information => { return { @@ -58,7 +59,7 @@ useAmis(information => { tabsMode: 'vertical', tabs: [ // tabOverview(), - // tabMarket(), + tabMarket(), tabPermissions(), tabCheck(), tabData(), diff --git a/gringotts-frontend/pages/index/tab-market.js b/gringotts-frontend/pages/index/tab-market.js index e2dd260..fec9386 100644 --- a/gringotts-frontend/pages/index/tab-market.js +++ b/gringotts-frontend/pages/index/tab-market.js @@ -1,9 +1,16 @@ +import {wareAddDialog} from "../../components/ware/dialog-ware.js"; + export function tabMarket() { return { title: '数据市场', icon: 'fa fa-store', body: [ - 'hello world' + { + type: 'action', + label: '', + icon: 'fa fa-plus', + ...wareAddDialog() + }, ] } } \ No newline at end of file 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 new file mode 100644 index 0000000..13b8e43 --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/controller/WareController.java @@ -0,0 +1,98 @@ +package com.eshore.gringotts.web.domain.controller; + +import com.eshore.gringotts.web.domain.base.controller.SimpleControllerSupport; +import com.eshore.gringotts.web.domain.base.entity.FileInfo; +import com.eshore.gringotts.web.domain.base.entity.SimpleListItem; +import com.eshore.gringotts.web.domain.base.entity.SimpleSaveItem; +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 java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author lanyuanxiaoyao + * @date 2024-12-13 + */ +@Slf4j +@RestController +@RequestMapping("ware") +public class WareController extends SimpleControllerSupport { + private final DataResourceService dataResourceService; + private final DataFileService dataFileService; + + public WareController(WareService service, DataResourceService dataResourceService, DataFileService dataFileService) { + super(service); + this.dataResourceService = dataResourceService; + this.dataFileService = dataFileService; + } + + @Override + protected Ware fromSaveItem(SaveItem saveItem) throws Exception { + Ware ware = new Ware(); + ware.setResource(dataResourceService.detailOrThrow(saveItem.getResourceId())); + ware.setName(ware.getName()); + ware.setDescription(saveItem.getDescription()); + ware.setIcon(dataFileService.detailOrThrow(saveItem.getIcon().getValue())); + ware.setContent(saveItem.getContent()); + return ware; + } + + @Override + protected ListItem toListItem(Ware entity) throws Exception { + return new ListItem(entity); + } + + @Override + protected DetailItem toDetailItem(Ware entity) throws Exception { + return new DetailItem(entity); + } + + @Data + @EqualsAndHashCode(callSuper = true) + public static class SaveItem extends SimpleSaveItem { + private Long resourceId; + private String name; + private String description; + private FileInfo icon; + private String content; + } + + @Data + @EqualsAndHashCode(callSuper = true) + public static class ListItem extends SimpleListItem { + 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()); + } + } + + @Data + @EqualsAndHashCode(callSuper = true) + public static class DetailItem extends SaveItem { + 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.setName(ware.getName()); + this.setDescription(ware.getDescription()); + this.setIcon(new FileInfo(ware.getIcon())); + this.setContent(ware.getContent()); + } + } +} 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 new file mode 100644 index 0000000..58479a1 --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/entity/Ware.java @@ -0,0 +1,70 @@ +package com.eshore.gringotts.web.domain.entity; + +import com.eshore.gringotts.core.Constants; +import com.eshore.gringotts.web.domain.base.entity.LogicDeleteEntity; +import com.eshore.gringotts.web.domain.base.entity.SimpleEntity; +import javax.persistence.Basic; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.ConstraintMode; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.FetchType; +import javax.persistence.ForeignKey; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +/** + * 商品 + * + * @author lanyuanxiaoyao + * @date 2024-12-13 + */ +@Getter +@Setter +@ToString(callSuper = true) +@Entity +@EntityListeners(AuditingEntityListener.class) +@DynamicUpdate +@Table(name = Constants.TABLE_PREFIX + "ware") +@NamedEntityGraph(name = "ware.list", attributeNodes = { + @NamedAttributeNode(value = "createdUser"), +}) +@NamedEntityGraph(name = "ware.detail", attributeNodes = { + @NamedAttributeNode(value = "icon"), + @NamedAttributeNode(value = "content"), + @NamedAttributeNode(value = "createdUser"), + @NamedAttributeNode(value = "modifiedUser"), +}) +@SQLDelete(sql = "update " + Constants.TABLE_PREFIX + "ware" + " set deleted = true where id = ?") +@Where(clause = LogicDeleteEntity.LOGIC_DELETE_CLAUSE) +public class Ware extends SimpleEntity { + @OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER) + @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @ToString.Exclude + private DataResource resource; + @Column(nullable = false) + private String name; + @Column(nullable = false) + private String description; + @OneToOne(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY) + @JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @ToString.Exclude + private DataFile icon; + @Lob + @Basic(fetch = FetchType.LAZY) + @ToString.Exclude + @Column(nullable = false) + private String content; +} diff --git a/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java new file mode 100644 index 0000000..0a225f9 --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/repository/WareRepository.java @@ -0,0 +1,26 @@ +package com.eshore.gringotts.web.domain.repository; + +import com.eshore.gringotts.web.domain.base.repository.SimpleRepository; +import com.eshore.gringotts.web.domain.entity.Ware; +import java.util.List; +import java.util.Optional; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.stereotype.Repository; + +@SuppressWarnings("NullableProblems") +@Repository +public interface WareRepository extends SimpleRepository { + @Override + @EntityGraph(value = "ware.list", type = EntityGraph.EntityGraphType.FETCH) + List findAll(Specification specification); + + @Override + @EntityGraph(value = "ware.list", type = EntityGraph.EntityGraphType.FETCH) + List findAll(Specification specification, Sort sort); + + @Override + @EntityGraph(value = "ware.detail", type = EntityGraph.EntityGraphType.FETCH) + Optional findOne(Specification specification); +} \ No newline at end of file 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 new file mode 100644 index 0000000..4d75ecc --- /dev/null +++ b/gringotts-web/src/main/java/com/eshore/gringotts/web/domain/service/WareService.java @@ -0,0 +1,19 @@ +package com.eshore.gringotts.web.domain.service; + +import com.eshore.gringotts.web.domain.base.service.SimpleServiceSupport; +import com.eshore.gringotts.web.domain.entity.Ware; +import com.eshore.gringotts.web.domain.repository.WareRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @author lanyuanxiaoyao + * @date 2024-12-13 + */ +@Slf4j +@Service +public class WareService extends SimpleServiceSupport { + public WareService(WareRepository repository, UserService userService) { + super(repository, userService); + } +}