xiongzhu 4 лет назад
Родитель
Сommit
a512436256

+ 286 - 0
0001-3d.patch

@@ -0,0 +1,286 @@
+From 30c5e5f1f7b70d18d7006266640f6e24b1a000b9 Mon Sep 17 00:00:00 2001
+From: xiongzhu <692949348@qq.com>
+Date: Wed, 29 Dec 2021 18:15:08 +0800
+Subject: [PATCH] 3d
+
+---
+ .../com/izouma/nineth/domain/Collection.java  |  4 ++
+ .../izouma/nineth/service/AssetService.java   |  2 +-
+ .../com/izouma/nineth/utils/FileUtils.java    | 66 +++++++++++++++++++
+ .../nineth/web/FileUploadController.java      | 33 ++++++++--
+ src/main/vue/src/components/FileUpload.vue    |  7 +-
+ src/main/vue/src/views/BlindBoxEdit.vue       |  4 +-
+ src/main/vue/src/views/CollectionEdit.vue     | 13 +++-
+ 7 files changed, 119 insertions(+), 10 deletions(-)
+
+diff --git a/src/main/java/com/izouma/nineth/domain/Collection.java b/src/main/java/com/izouma/nineth/domain/Collection.java
+index f3ee2ed..75c7949 100644
+--- a/src/main/java/com/izouma/nineth/domain/Collection.java
++++ b/src/main/java/com/izouma/nineth/domain/Collection.java
+@@ -37,6 +37,10 @@ public class Collection extends BaseEntity {
+     @Convert(converter = FileObjectListConverter.class)
+     private List<FileObject> pic;
+ 
++    @Column(columnDefinition = "TEXT")
++    @Convert(converter = FileObjectListConverter.class)
++    private FileObject model3d;
++
+     @ApiModelProperty("铸造者")
+     @Searchable
+     private String minter;
+diff --git a/src/main/java/com/izouma/nineth/service/AssetService.java b/src/main/java/com/izouma/nineth/service/AssetService.java
+index 134a056..01e1b01 100644
+--- a/src/main/java/com/izouma/nineth/service/AssetService.java
++++ b/src/main/java/com/izouma/nineth/service/AssetService.java
+@@ -289,7 +289,7 @@ public class AssetService {
+                 .toUserId(toUser.getId())
+                 .toAvatar(toUser.getAvatar())
+                 .operation(reason)
+-                .price("转赠".equals(reason) ? price : null)
++                .price("转赠".equals(reason) ? null : price)
+                 .build());
+ 
+         asset.setPublicShow(false);
+diff --git a/src/main/java/com/izouma/nineth/utils/FileUtils.java b/src/main/java/com/izouma/nineth/utils/FileUtils.java
+index 3545e2c..d4454d9 100644
+--- a/src/main/java/com/izouma/nineth/utils/FileUtils.java
++++ b/src/main/java/com/izouma/nineth/utils/FileUtils.java
+@@ -3,13 +3,18 @@ package com.izouma.nineth.utils;
+ import org.apache.commons.lang3.StringUtils;
+ 
+ import java.io.*;
++import java.nio.charset.Charset;
++import java.nio.charset.StandardCharsets;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.attribute.PosixFileAttributeView;
+ import java.nio.file.attribute.PosixFileAttributes;
+ import java.nio.file.attribute.PosixFilePermission;
+ import java.nio.file.attribute.PosixFilePermissions;
++import java.util.Optional;
+ import java.util.Set;
++import java.util.zip.ZipEntry;
++import java.util.zip.ZipInputStream;
+ 
+ public class FileUtils {
+ 
+@@ -200,5 +205,66 @@ public class FileUtils {
+ 
+     }
+ 
++    public static void unzip(InputStream in, File destDir) throws IOException {
++        try {
++            unzip(in, destDir, StandardCharsets.UTF_8);
++        } catch (Exception e) {
++            unzip(in, destDir, Charset.forName("GB2312"));
++        }
++    }
++
++    public static void unzip(InputStream in, File destDir, Charset charset) throws IOException {
++        byte[] buffer = new byte[1024];
++        ZipInputStream zis = new ZipInputStream(in);
++        ZipEntry zipEntry = zis.getNextEntry();
++        while (zipEntry != null) {
++            File newFile = newFile(destDir, zipEntry);
++            if (zipEntry.isDirectory()) {
++                if (!newFile.isDirectory() && !newFile.mkdirs()) {
++                    throw new IOException("Failed to create directory " + newFile);
++                }
++            } else {
++                // fix for Windows-created archives
++                File parent = newFile.getParentFile();
++                if (!parent.isDirectory() && !parent.mkdirs()) {
++                    throw new IOException("Failed to create directory " + parent);
++                }
+ 
++                // write file content
++                FileOutputStream fos = new FileOutputStream(newFile);
++                int len;
++                while ((len = zis.read(buffer)) > 0) {
++                    fos.write(buffer, 0, len);
++                }
++                fos.close();
++            }
++            zipEntry = zis.getNextEntry();
++        }
++        zis.closeEntry();
++        zis.close();
++    }
++
++    public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
++        File destFile = new File(destinationDir, zipEntry.getName());
++
++        String destDirPath = destinationDir.getCanonicalPath();
++        String destFilePath = destFile.getCanonicalPath();
++
++        if (!destFilePath.startsWith(destDirPath + File.separator)) {
++            throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
++        }
++
++        return destFile;
++    }
++
++    public static File findInDir(File dir, String ext) {
++        if (!(dir.exists() && dir.isDirectory())) return null;
++        for (File file : Optional.ofNullable(dir.listFiles()).orElse(new File[0])) {
++            String name = file.getName().toLowerCase();
++            if (name.endsWith(ext.toLowerCase()) && !file.isHidden()) {
++                return file;
++            }
++        }
++        return null;
++    }
+ }
+diff --git a/src/main/java/com/izouma/nineth/web/FileUploadController.java b/src/main/java/com/izouma/nineth/web/FileUploadController.java
+index 47580f3..114788e 100644
+--- a/src/main/java/com/izouma/nineth/web/FileUploadController.java
++++ b/src/main/java/com/izouma/nineth/web/FileUploadController.java
+@@ -10,10 +10,10 @@ import org.apache.commons.io.FilenameUtils;
+ import org.apache.commons.lang3.ArrayUtils;
+ import org.apache.commons.lang3.RandomStringUtils;
+ import org.apache.commons.lang3.StringUtils;
++import org.apache.poi.util.TempFile;
+ import org.bytedeco.javacv.FFmpegFrameGrabber;
+ import org.bytedeco.javacv.Frame;
+ import org.bytedeco.javacv.Java2DFrameConverter;
+-import org.pngquant.PngQuant;
+ import org.springframework.beans.factory.annotation.Autowired;
+ import org.springframework.web.bind.annotation.PostMapping;
+ import org.springframework.web.bind.annotation.RequestMapping;
+@@ -26,10 +26,7 @@ import java.awt.image.BufferedImage;
+ import java.io.*;
+ import java.net.URLConnection;
+ import java.text.SimpleDateFormat;
+-import java.util.Base64;
+-import java.util.Date;
+-import java.util.Objects;
+-import java.util.Optional;
++import java.util.*;
+ import java.util.regex.Pattern;
+ 
+ 
+@@ -182,4 +179,30 @@ public class FileUploadController {
+ 
+         return new FileObject(file.getOriginalFilename(), url, thumbUrl, file.getContentType());
+     }
++
++    @PostMapping("/3dModel")
++    public FileObject upload3dModel(@RequestParam("file") MultipartFile file) throws IOException {
++        if (!"zip".equalsIgnoreCase(FilenameUtils.getExtension(file.getOriginalFilename()))) {
++            throw new BusinessException("只能上传zip");
++        }
++        File destDir = TempFile.createTempDirectory(RandomStringUtils.randomAlphabetic(20));
++        com.izouma.nineth.utils.FileUtils.unzip(file.getInputStream(), destDir);
++        File fbxFile = com.izouma.nineth.utils.FileUtils.findInDir(destDir, ".fbx");
++        if (fbxFile == null) {
++            throw new BusinessException("找不到fbx文件");
++        }
++        File fbxDir = fbxFile.getParentFile();
++        String basePath = "fbx/"
++                + new SimpleDateFormat("yyyy-MM_dd-HH").format(new Date()) + "/"
++                + RandomStringUtils.randomAlphabetic(16);
++        List<String> urls = new ArrayList<>();
++        for (File listFile : fbxDir.listFiles()) {
++            if (!listFile.isHidden() && !listFile.isDirectory()) {
++                urls.add(storageService.uploadFromInputStream(new FileInputStream(listFile), basePath + "/" + listFile.getName()));
++            }
++        }
++        String fbxUrl = urls.stream().filter(s -> s.toLowerCase().endsWith(".fbx")).findAny()
++                .orElseThrow(new BusinessException("找不到fbx文件"));
++        return new FileObject(fbxFile.getName(), fbxUrl, null, "fbx");
++    }
+ }
+diff --git a/src/main/vue/src/components/FileUpload.vue b/src/main/vue/src/components/FileUpload.vue
+index beed236..e5257e1 100644
+--- a/src/main/vue/src/components/FileUpload.vue
++++ b/src/main/vue/src/components/FileUpload.vue
+@@ -1,13 +1,14 @@
+ <template>
+     <el-upload
+         class="file-upload"
+-        :action="uploadUrl"
++        :action="customUrl || uploadUrl"
+         :on-success="onSuccess"
+         :headers="headers"
+         :file-list="fileList"
+         :limit="filesLimit"
+         :on-exceed="onExceed"
+         :on-preview="onPreview"
++        :accept="accept || '*/*'"
+         ref="upload"
+     >
+         <el-button type="primary" size="mini" slot="trigger"> 点击上传 </el-button>
+@@ -62,7 +63,9 @@ export default {
+         format: {
+             type: String,
+             default: 'string'
+-        }
++        },
++        customUrl: {},
++        accept: {}
+     },
+     data() {
+         return {
+diff --git a/src/main/vue/src/views/BlindBoxEdit.vue b/src/main/vue/src/views/BlindBoxEdit.vue
+index 773a3aa..2459522 100644
+--- a/src/main/vue/src/views/BlindBoxEdit.vue
++++ b/src/main/vue/src/views/BlindBoxEdit.vue
+@@ -189,6 +189,7 @@
+     </div>
+ </template>
+ <script>
++import resolveUrl from 'resolve-url';
+ export default {
+     name: 'BlindBoxEdit',
+     created() {
+@@ -428,7 +429,8 @@ export default {
+                 id: [{ required: true, message: '请选择作品' }],
+                 total: [{ required: true, message: '请输入数量' }]
+             },
+-            cateogories: ['勋章', '收藏品', '数字艺术', '门票', '游戏', '音乐', '使用', '其他']
++            cateogories: ['勋章', '收藏品', '数字艺术', '门票', '游戏', '音乐', '使用', '其他'],
++            customUrl: resolveUrl(this.$baseUrl, 'upload/3dModel')
+         };
+     },
+     methods: {
+diff --git a/src/main/vue/src/views/CollectionEdit.vue b/src/main/vue/src/views/CollectionEdit.vue
+index d794f0d..5574fc7 100644
+--- a/src/main/vue/src/views/CollectionEdit.vue
++++ b/src/main/vue/src/views/CollectionEdit.vue
+@@ -29,6 +29,15 @@
+                         ></object-upload>
+                         <div class="tip">支持JPG、PNG、GIF、MP4,推荐长宽比1:1</div>
+                     </el-form-item>
++                    <el-form-item prop="model3d" label="3D模型">
++                        <file-upload
++                            :limit="1"
++                            v-model="formData.model3d"
++                            :customUrl="customUrl"
++                            accept="application/zip"
++                        ></file-upload>
++                        <div class="tip">请将FBX文件与贴图打包成zip压缩包上传</div>
++                    </el-form-item>
+                     <el-form-item prop="minterId" label="铸造者">
+                         <minter-select
+                             v-model="formData.minterId"
+@@ -221,6 +230,7 @@
+     </div>
+ </template>
+ <script>
++import resolveUrl from 'resolve-url';
+ export default {
+     name: 'CollectionEdit',
+     created() {
+@@ -418,7 +428,8 @@ export default {
+             privelegeRules: {
+                 detail: [{ required: true, message: '请填写内容' }],
+                 remark: [{ required: true, message: '请填写说明' }]
+-            }
++            },
++            customUrl: resolveUrl(this.$baseUrl, 'upload/3dModel')
+         };
+     },
+     methods: {
+-- 
+2.30.1 (Apple Git-130)
+

+ 3 - 0
src/main/java/com/izouma/nineth/repo/AssetRepo.java

@@ -46,4 +46,7 @@ public interface AssetRepo extends JpaRepository<Asset, Long>, JpaSpecificationE
 
     @Query("select a from Asset a left join TokenHistory t on a.tokenId = t.tokenId where t.id is null")
     List<Asset> findByNoHistory();
+
+
+    List<Asset> findByTokenIdAndCreatedAtBetween(String tokenId, LocalDateTime start, LocalDateTime end);
 }

+ 2 - 0
src/main/java/com/izouma/nineth/repo/TokenHistoryRepo.java

@@ -23,4 +23,6 @@ public interface TokenHistoryRepo extends JpaRepository<TokenHistory, Long>, Jpa
 
     @Query("select t from TokenHistory t where t.fromUserId = t.toUserId")
     List<TokenHistory> findError();
+
+    List<TokenHistory> findByOperationAndPriceNull(String oper);
 }

+ 20 - 0
src/test/java/com/izouma/nineth/service/AssetServiceTest.java

@@ -3,6 +3,7 @@ package com.izouma.nineth.service;
 import com.izouma.nineth.ApplicationTests;
 import com.izouma.nineth.TokenHistory;
 import com.izouma.nineth.domain.*;
+import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.*;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.Test;
@@ -109,4 +110,23 @@ class AssetServiceTest extends ApplicationTests {
         }
         System.out.println(assets);
     }
+
+
+    @Test
+    public void fixHistoryPrice() {
+        List<TokenHistory> list = tokenHistoryRepo.findByOperationAndPriceNull("转让");
+        System.out.println(list.size());
+        StringBuilder builder = new StringBuilder();
+        list.parallelStream().forEach(tokenHistory -> {
+            List<Asset> assets = assetRepo.findByTokenIdAndCreatedAtBetween(tokenHistory.getTokenId(), tokenHistory.getCreatedAt()
+                    .minusSeconds(10), tokenHistory.getCreatedAt().plusSeconds(1));
+            if (assets.size() != 1) {
+                throw new BusinessException("");
+            }
+            Order order = orderRepo.findById(assets.get(0).getOrderId())
+                    .orElseThrow(new BusinessException(assets.get(0).getId() + "订单没找到"));
+            builder.append(order.getId()).append(",").append(order.getPrice()).append("\n");
+        });
+        System.out.println(builder);
+    }
 }