Commit 4392984ece2031d65670d4a277acd52c2b22c4ad

Authored by xp.Huang
1 parent 2b03f2b4

fix:将3d-compoent模块的json以文件形式存储

... ... @@ -7,9 +7,10 @@ update tk_configuration_content_node set configuration_node_id = id;
7 7 CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
8 8 update tk_configuration_content_node set id = uuid_generate_v4();
9 9
  10 +--添加3d组件的新表
  11 +DROP TABLE IF EXISTS "public"."tk_3d_component";
10 12 CREATE TABLE "public"."tk_3d_component" (
11 13 "id" varchar(36) COLLATE "pg_catalog"."default" NOT NULL,
12   - "content" text COLLATE "pg_catalog"."default" NOT NULL,
13 14 "creator" varchar(36) COLLATE "pg_catalog"."default",
14 15 "updater" varchar(36) COLLATE "pg_catalog"."default",
15 16 "tenant_id" varchar(36) COLLATE "pg_catalog"."default" NOT NULL,
... ... @@ -17,11 +18,11 @@ CREATE TABLE "public"."tk_3d_component" (
17 18 "update_time" timestamp(6),
18 19 "name" varchar(128) COLLATE "pg_catalog"."default",
19 20 "state" int2,
20   - "image_url" varchar(255) COLLATE "pg_catalog"."default"
  21 + "image_url" varchar(255) COLLATE "pg_catalog"."default",
  22 + "json_path" varchar(1024) COLLATE "pg_catalog"."default"
21 23 )
22 24 ;
23 25 COMMENT ON COLUMN "public"."tk_3d_component"."id" IS '主建';
24   -COMMENT ON COLUMN "public"."tk_3d_component"."content" IS '模板内容';
25 26 COMMENT ON COLUMN "public"."tk_3d_component"."creator" IS '创建用户';
26 27 COMMENT ON COLUMN "public"."tk_3d_component"."updater" IS '更新用户';
27 28 COMMENT ON COLUMN "public"."tk_3d_component"."tenant_id" IS '租户ID';
... ...
... ... @@ -6,12 +6,18 @@ import io.swagger.annotations.ApiModelProperty;
6 6 import io.swagger.annotations.ApiOperation;
7 7 import io.swagger.annotations.ApiParam;
8 8 import lombok.Data;
  9 +import lombok.extern.slf4j.Slf4j;
9 10 import org.springframework.beans.BeanUtils;
  11 +import org.springframework.http.HttpHeaders;
  12 +import org.springframework.http.HttpStatus;
  13 +import org.springframework.http.MediaType;
10 14 import org.springframework.http.ResponseEntity;
11 15 import org.springframework.security.access.prepost.PreAuthorize;
12 16 import org.springframework.util.CollectionUtils;
  17 +import org.springframework.util.FileCopyUtils;
13 18 import org.springframework.util.StringUtils;
14 19 import org.springframework.web.bind.annotation.*;
  20 +import org.thingsboard.common.util.JacksonUtil;
15 21 import org.thingsboard.server.common.data.exception.ThingsboardException;
16 22 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
17 23 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
... ... @@ -23,11 +29,11 @@ import org.thingsboard.server.controller.BaseController;
23 29 import org.thingsboard.server.dao.yunteng.service.Tk3dComponentService;
24 30
25 31 import javax.annotation.Resource;
26   -import java.util.ArrayList;
27   -import java.util.HashMap;
28   -import java.util.List;
29   -import java.util.Set;
  32 +import java.io.File;
  33 +import java.io.FileInputStream;
  34 +import java.util.*;
30 35 import java.util.stream.Collectors;
  36 +import java.util.stream.Stream;
31 37
32 38 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
33 39 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.ORDER_TYPE;
... ... @@ -44,6 +50,7 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.
44 50 @RequestMapping("api/yt/3d_component")
45 51 @Api(tags = {"3D模型管理"})
46 52 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
  53 +@Slf4j
47 54 public class Tk3dComponentController extends BaseController {
48 55 @Resource
49 56 Tk3dComponentService tk3dComponentService;
... ... @@ -82,7 +89,7 @@ public class Tk3dComponentController extends BaseController {
82 89
83 90 @PostMapping
84 91 @ApiOperation("保存")
85   - public ResponseEntity<Tk3dComponentDTO> save(@ApiParam("id") @RequestParam("id") String id, @RequestParam("imageUrl") String imageUrl, @RequestBody JsonNode jsonNode) throws ThingsboardException {
  92 + public ResponseEntity<Tk3dComponentDTO> save(@ApiParam("id") @RequestParam("id") String id, @RequestParam("imageUrl") String imageUrl, @RequestBody JsonNode jsonNode) throws Exception {
86 93 if (!StringUtils.hasLength(id)) {
87 94 throw new TkDataValidationException(MessageUtils.message(ErrorMessage.INVALID_PARAMETER.getI18nCode()));
88 95 }
... ... @@ -90,8 +97,7 @@ public class Tk3dComponentController extends BaseController {
90 97 dto.setId(id);
91 98 dto.setImageUrl(imageUrl);
92 99 dto.setTenantId(getTenantId().getId().toString());
93   - dto.setContent(jsonNode);
94   - return ResponseEntity.ok(tk3dComponentService.save(dto));
  100 + return ResponseEntity.ok(tk3dComponentService.save(dto,jsonNode));
95 101 }
96 102
97 103 @PutMapping("/{id}/{name}")
... ... @@ -119,6 +125,7 @@ public class Tk3dComponentController extends BaseController {
119 125
120 126
121 127 @PutMapping("/publish/{state}")
  128 + @ApiOperation("批量发布")
122 129 public ResponseEntity<Boolean> publish(@PathVariable("state") Integer state, @RequestBody List<String> ids) throws ThingsboardException {
123 130 if (!CollectionUtils.isEmpty(ids)) {
124 131
... ... @@ -163,13 +170,26 @@ public class Tk3dComponentController extends BaseController {
163 170
164 171 @GetMapping("/json/{id}/{key}.json")
165 172 @ApiOperation("获取json数据")
166   - public ResponseEntity<JsonNode> json(@PathVariable("id") String id, @PathVariable("key") String key)
167   - throws Exception {
168   - Tk3dComponentDTO dto = tk3dComponentService.get(id, getCurrentUser().getCurrentTenantId());
169   - if (null == dto) {
  173 + public ResponseEntity<JsonNode> json(@PathVariable("id") String id, @PathVariable("key") String key) throws Exception {
  174 + try {
  175 + JsonNode jsonNode=JacksonUtil.toJsonNode(tk3dComponentService.downloadFile(id));
  176 + if(jsonNode==null){
  177 + return ResponseEntity.ok(null);
  178 + }
  179 + if(StringUtils.hasLength(key)){
  180 + if(key.equalsIgnoreCase("root") || key.equalsIgnoreCase("all") ){
  181 + return ResponseEntity.ok(jsonNode);
  182 + }else {
  183 + return ResponseEntity.ok(jsonNode.get(key));
  184 + }
  185 + }
  186 + else {
  187 + return ResponseEntity.ok(jsonNode);
  188 + }
  189 + }catch(Exception e) {
  190 + log.error(e.getMessage(),e);
170 191 throw new TkDataValidationException(MessageUtils.message(ErrorMessage.INVALID_PARAMETER.getI18nCode()));
171 192 }
172   - return ResponseEntity.ok(dto.getContent().get(key));
173 193 }
174 194
175 195 @DeleteMapping
... ... @@ -179,20 +199,4 @@ public class Tk3dComponentController extends BaseController {
179 199 return ResponseEntity.ok(tk3dComponentService.delete(getCurrentUser().getCurrentTenantId(), ids));
180 200 }
181 201
182   - @Data
183   - private static class ComponentParam {
184   -
185   - @ApiModelProperty("ID")
186   - String id;
187   -
188   - @ApiModelProperty("名称")
189   - String name;
190   -
191   - @ApiModelProperty("是否发布:0否,1是")
192   - Integer state;
193   -
194   - @ApiModelProperty("图标地址")
195   - String imageUrl;
196   - }
197   -
198 202 }
... ...
... ... @@ -1867,4 +1867,6 @@ thingskit:
1867 1867 date: "${THINGSKIT_RELEASE_DATE:20240930}"
1868 1868
1869 1869 protocol-template:
1870   - path: "${PROTOCOL_TEMPLATE_PTH:./protocol-template}"
\ No newline at end of file
  1870 + path: "${PROTOCOL_TEMPLATE_PATH:./protocol-template}"
  1871 +3d-component:
  1872 + path: "${3D-COMPONENT_PATH:./3d-component}"
\ No newline at end of file
... ...
1 1 package org.thingsboard.server.dao.yunteng.service;
  2 +import com.fasterxml.jackson.databind.JsonNode;
  3 +import io.minio.errors.*;
2 4 import org.thingsboard.server.common.data.yunteng.dto.Tk3dComponentDTO;
3 5 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
4 6
  7 +import java.io.File;
  8 +import java.io.IOException;
  9 +import java.security.InvalidKeyException;
  10 +import java.security.NoSuchAlgorithmException;
5 11 import java.util.List;
6 12 import java.util.Map;
7 13
... ... @@ -15,9 +21,13 @@ import java.util.Map;
15 21 */
16 22 public interface Tk3dComponentService {
17 23 TkPageData<Tk3dComponentDTO> page(Map<String, Object> queryMap, String tenantId );
  24 +
  25 + Tk3dComponentDTO save(Tk3dComponentDTO dto, JsonNode jsonNode) throws Exception;
18 26 Tk3dComponentDTO save(Tk3dComponentDTO dto);
19 27
20 28 boolean save(List<Tk3dComponentDTO> dto);
21 29 Tk3dComponentDTO get(String id, String tenantId);
22 30 boolean delete(String tenantId, List<String> ids);
  31 +
  32 + public String downloadFile(String id) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
23 33 }
... ...
1 1 package org.thingsboard.server.common.data.yunteng.core.utils;
2 2
  3 +import io.minio.errors.*;
3 4 import org.springframework.http.ResponseEntity;
4 5 import org.springframework.web.multipart.MultipartFile;
5 6 import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
6 7
7 8 import javax.servlet.http.HttpServletRequest;
8 9 import javax.servlet.http.HttpServletResponse;
  10 +import java.io.IOException;
9 11 import java.io.InputStream;
  12 +import java.security.InvalidKeyException;
  13 +import java.security.NoSuchAlgorithmException;
10 14
11 15 public interface FileStorageService {
12 16
... ... @@ -24,10 +28,12 @@ public interface FileStorageService {
24 28 * @param fileName 待下载文件名
25 29 * @param response {@link HttpServletResponse}
26 30 */
27   - ResponseEntity<?> download(
28   - String fileName, HttpServletRequest request, HttpServletResponse response);
  31 + ResponseEntity<?> download(String fileName, HttpServletRequest request, HttpServletResponse response);
  32 +
  33 + InputStream download(String fileName) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException;
29 34
30 35 String uploadFile(String fileName, String contentType, InputStream inputStream ) throws Exception;
31 36
32 37 boolean deleteFile(String deleteFilePath);
  38 +
33 39 }
... ...
... ... @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
22 22 import javax.servlet.http.HttpServletRequest;
23 23 import javax.servlet.http.HttpServletResponse;
24 24 import java.io.File;
  25 +import java.io.FileInputStream;
25 26 import java.io.IOException;
26 27 import java.io.InputStream;
27 28 import java.net.MalformedURLException;
... ... @@ -123,6 +124,13 @@ public class LocalFileStorageService implements FileStorageService {
123 124 }
124 125
125 126 @Override
  127 + public InputStream download(String file) throws IOException {
  128 + String fileName=file.substring(file.lastIndexOf("/")+1);
  129 + String filePath=fileStorageProperties.getUploadDir()+File.separator+ fileName;
  130 + return new FileInputStream(new File(filePath));
  131 + }
  132 +
  133 + @Override
126 134 public String uploadFile(String fileName, String contentType, InputStream inputStream )
127 135 throws IOException {
128 136 String name = storeFileByInputStream(fileName, inputStream);
... ... @@ -143,6 +151,7 @@ public class LocalFileStorageService implements FileStorageService {
143 151 return false;
144 152 }
145 153
  154 +
146 155 private String storeFileByInputStream(String fileName, InputStream inputStream)
147 156 throws IOException {
148 157 // random fileName if needed
... ...
... ... @@ -166,6 +166,17 @@ public class MinioFileStorageService implements FileStorageService {
166 166 }
167 167
168 168 @Override
  169 + public InputStream download(String fileName) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
  170 + InputStream inputStream =
  171 + minioClient.getObject(
  172 + GetObjectArgs.builder()
  173 + .bucket(fileStorageProperties.getBucketName())
  174 + .object(fileName.split(fileStorageProperties.getBucketName())[1])
  175 + .build());
  176 + return inputStream;
  177 + }
  178 +
  179 + @Override
169 180 public String uploadFile(String fileName, String contentType, InputStream inputStream )
170 181 throws IOException {
171 182 try {
... ...
... ... @@ -23,9 +23,6 @@ public class Tk3dComponentDTO extends BaseDTO implements Serializable {
23 23
24 24 private static final long serialVersionUID = 1L;
25 25
26   - @ApiModelProperty("模板内容")
27   - private JsonNode content;
28   -
29 26 @ApiModelProperty("名称")
30 27 String name;
31 28
... ...
... ... @@ -25,7 +25,9 @@ import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
25 25 @TableName(ModelConstants.Table.TK_3D_COMPONENT_NAME)
26 26 @ApiModel(value = "Tk3dComponentEntity对象")
27 27 public class Tk3dComponentEntity extends TenantBaseEntity implements Serializable {
  28 +
28 29 private static final long serialVersionUID = -4715245103595332141L;
  30 +
29 31 @TableField
30 32 String name;
31 33
... ... @@ -33,11 +35,9 @@ public class Tk3dComponentEntity extends TenantBaseEntity implements Serializabl
33 35 String imageUrl;
34 36
35 37 @TableField
36   - @ApiModelProperty("是否发布:0否,1是")
37   - Integer state=0;
  38 + String jsonPath;
38 39
39   - @ApiModelProperty("模板内容")
40   - @TableField(typeHandler = JacksonTypeHandler.class)
41   - private JsonNode content;
  40 + @TableField
  41 + Integer state=0;
42 42
43 43 }
... ...
... ... @@ -2,25 +2,38 @@ package org.thingsboard.server.dao.yunteng.impl;
2 2
3 3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 4 import com.baomidou.mybatisplus.core.metadata.IPage;
5   -import org.apache.commons.lang3.StringUtils;
  5 +import com.fasterxml.jackson.databind.JsonNode;
  6 +import io.minio.errors.*;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.beans.factory.annotation.Value;
6 10 import org.springframework.stereotype.Service;
7 11 import org.springframework.util.CollectionUtils;
  12 +import org.springframework.util.FileCopyUtils;
  13 +import org.springframework.util.StringUtils;
8 14 import org.thingsboard.server.common.data.yunteng.constant.QueryConstant;
9 15 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
10 16 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  17 +import org.thingsboard.server.common.data.yunteng.core.utils.FileStorageService;
11 18 import org.thingsboard.server.common.data.yunteng.dto.Tk3dComponentDTO;
12 19 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
13 20 import org.thingsboard.server.common.data.yunteng.utils.i18n.MessageUtils;
14 21 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
15 22 import org.thingsboard.server.dao.yunteng.entities.Tk3dComponentEntity;
16 23 import org.thingsboard.server.dao.yunteng.entities.TkAlarmEntity;
  24 +import org.thingsboard.server.dao.yunteng.entities.TkProtocolTemplateEntity;
17 25 import org.thingsboard.server.dao.yunteng.mapper.Tk3dComponentMapper;
18 26 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
19 27 import org.thingsboard.server.dao.yunteng.service.Tk3dComponentService;
20 28
  29 +import java.io.*;
  30 +import java.net.URI;
  31 +import java.security.InvalidKeyException;
  32 +import java.security.NoSuchAlgorithmException;
21 33 import java.util.Collections;
22 34 import java.util.List;
23 35 import java.util.Map;
  36 +import java.util.UUID;
24 37
25 38 /**
26 39 * <p>
... ... @@ -31,34 +44,39 @@ import java.util.Map;
31 44 * @since 2024-10-14
32 45 */
33 46 @Service
  47 +@Slf4j
34 48 public class Tk3dComponentServiceImpl extends AbstractBaseService<Tk3dComponentMapper, Tk3dComponentEntity> implements Tk3dComponentService {
35 49
  50 + @Autowired
  51 + FileStorageService fileStorageService;
  52 +
  53 + static final String base="/3d-component";
  54 +
36 55 @Override
37 56 public TkPageData<Tk3dComponentDTO> page(Map<String, Object> queryMap, String tenantId) {
38   - IPage<Tk3dComponentEntity> iPage =baseMapper.page(getPage(queryMap, queryMap.containsKey(QueryConstant.ORDER_FILED) ? queryMap.get(QueryConstant.ORDER_FILED).toString() : "create_time", queryMap.containsKey(QueryConstant.ORDER_TYPE) ? queryMap.get(QueryConstant.ORDER_TYPE).toString().equalsIgnoreCase(OrderTypeEnum.ASC.name()) : false),tenantId,queryMap);
  57 + IPage<Tk3dComponentEntity> iPage = baseMapper.page(getPage(queryMap, queryMap.containsKey(QueryConstant.ORDER_FILED) ? queryMap.get(QueryConstant.ORDER_FILED).toString() : "create_time", queryMap.containsKey(QueryConstant.ORDER_TYPE) ? queryMap.get(QueryConstant.ORDER_TYPE).toString().equalsIgnoreCase(OrderTypeEnum.ASC.name()) : false), tenantId, queryMap);
39 58 return getPageData(iPage, Tk3dComponentDTO.class);
40 59 }
41 60
42 61 @Override
43   - public Tk3dComponentDTO save(Tk3dComponentDTO dto) {
44   -
45   - if (baseMapper.exists(new LambdaQueryWrapper<Tk3dComponentEntity>()
46   - .eq(Tk3dComponentEntity::getTenantId, dto.getTenantId())
47   - .eq(Tk3dComponentEntity::getId, dto.getId()))) {
48   - baseMapper.updateById(dto.getEntity(Tk3dComponentEntity.class));
49   - } else {
50   - Tk3dComponentEntity entity=dto.getEntity(Tk3dComponentEntity.class);
51   - entity.setState(0);
52   - baseMapper.insert(entity);
53   - }
  62 + public Tk3dComponentDTO save(Tk3dComponentDTO dto, JsonNode jsonNode) throws Exception {
  63 + Tk3dComponentEntity entity = dto.getEntity(Tk3dComponentEntity.class);
  64 + entity.setJsonPath(createFile(dto.getId(),jsonNode));
  65 + save(entity);
  66 + return entity.getDTO(Tk3dComponentDTO.class);
  67 + }
54 68
55   - return dto;
  69 + @Override
  70 + public Tk3dComponentDTO save(Tk3dComponentDTO dto) {
  71 + Tk3dComponentEntity entity = dto.getEntity(Tk3dComponentEntity.class);
  72 + save(entity);
  73 + return entity.getDTO(Tk3dComponentDTO.class);
56 74 }
57 75
58 76 @Override
59 77 public boolean save(List<Tk3dComponentDTO> list) {
60   - if(!CollectionUtils.isEmpty(list)){
61   - list.stream().forEach(e->{
  78 + if (!CollectionUtils.isEmpty(list)) {
  79 + list.stream().forEach(e -> {
62 80 save(e);
63 81 });
64 82 return true;
... ... @@ -66,6 +84,18 @@ public class Tk3dComponentServiceImpl extends AbstractBaseService<Tk3dComponentM
66 84 return false;
67 85 }
68 86
  87 + private boolean save(Tk3dComponentEntity entity) {
  88 + if (baseMapper.exists(new LambdaQueryWrapper<Tk3dComponentEntity>()
  89 + .eq(Tk3dComponentEntity::getTenantId, entity.getTenantId())
  90 + .eq(Tk3dComponentEntity::getId, entity.getId()))) {
  91 + return baseMapper.updateById(entity)>0;
  92 + } else {
  93 + entity.setState(0);
  94 + return baseMapper.insert(entity)>0;
  95 + }
  96 + }
  97 +
  98 +
69 99 @Override
70 100 public Tk3dComponentDTO get(String id, String tenantId) {
71 101 Tk3dComponentEntity e = baseMapper.selectById(id);
... ... @@ -78,10 +108,48 @@ public class Tk3dComponentServiceImpl extends AbstractBaseService<Tk3dComponentM
78 108
79 109 @Override
80 110 public boolean delete(String tenantId, List<String> ids) {
81   - if(null ==ids){
  111 + if (null == ids) {
82 112 throw new TkDataValidationException(MessageUtils.message(ErrorMessage.INVALID_PARAMETER.getI18nCode()));
83 113 }
84   - return baseMapper.delete(new LambdaQueryWrapper<Tk3dComponentEntity>().eq(Tk3dComponentEntity::getTenantId,tenantId)
85   - .in(Tk3dComponentEntity::getId,ids))>0;
  114 + ids.stream().forEach(id->{
  115 + deleteFile(id);
  116 + });
  117 + return baseMapper.delete(new LambdaQueryWrapper<Tk3dComponentEntity>().eq(Tk3dComponentEntity::getTenantId, tenantId)
  118 + .in(Tk3dComponentEntity::getId, ids)) >0;
  119 + }
  120 +
  121 +
  122 +
  123 +
  124 +
  125 +
  126 + public void deleteFile(String id) {
  127 + Tk3dComponentEntity e = baseMapper.selectById(id);
  128 + if(e!=null && StringUtils.hasLength(e.getJsonPath())) {
  129 + fileStorageService.deleteFile(e.getJsonPath());
  130 + }
  131 + }
  132 +
  133 + public String createFile(String id, JsonNode jsonNode) throws Exception {
  134 + try {
  135 + deleteFile(id);
  136 + return fileStorageService.uploadFile(getJsonName(id),"json",new ByteArrayInputStream(jsonNode.toPrettyString().getBytes()));
  137 + } catch (Exception e) {
  138 + log.error(e.getMessage(),e);
  139 + return null;
  140 + }
  141 + }
  142 +
  143 + public String downloadFile(String id) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
  144 + Tk3dComponentEntity e = baseMapper.selectById(id);
  145 + if(e!=null && StringUtils.hasLength(e.getJsonPath())) {
  146 + InputStream inputStream = fileStorageService.download(e.getJsonPath());
  147 + return FileCopyUtils.copyToString(new InputStreamReader(inputStream));
  148 + }
  149 + return null;
  150 + }
  151 +
  152 + private static String getJsonName(String id){
  153 + return id+".json";
86 154 }
87 155 }
... ...