Browse Source

Merge branch 'dev-meta' of xiongzhu/raex_back into master

sunkean 3 years ago
parent
commit
7b5de2e81f
27 changed files with 1187 additions and 17 deletions
  1. 41 0
      src/main/java/com/izouma/nineth/domain/MetaBoatPosition.java
  2. 8 11
      src/main/java/com/izouma/nineth/domain/MetaSpatialWharf.java
  3. 29 0
      src/main/java/com/izouma/nineth/domain/MetaVisitor.java
  4. 9 0
      src/main/java/com/izouma/nineth/domain/PublicScreenChat.java
  5. 21 0
      src/main/java/com/izouma/nineth/enums/MetaIsLandTypeEnum.java
  6. 21 0
      src/main/java/com/izouma/nineth/repo/MetaBoatPositionRepo.java
  7. 2 0
      src/main/java/com/izouma/nineth/repo/MetaSpatialInfoRepo.java
  8. 9 0
      src/main/java/com/izouma/nineth/repo/MetaSpatialWharfRepo.java
  9. 22 0
      src/main/java/com/izouma/nineth/repo/MetaVisitorRepo.java
  10. 8 0
      src/main/java/com/izouma/nineth/repo/PublicScreenChatRepo.java
  11. 74 0
      src/main/java/com/izouma/nineth/service/MetaBoatPositionService.java
  12. 6 5
      src/main/java/com/izouma/nineth/service/MetaSpatialWharfService.java
  13. 20 0
      src/main/java/com/izouma/nineth/service/MetaVisitorService.java
  14. 1 0
      src/main/java/com/izouma/nineth/utils/excel/ExcelUtils.java
  15. 42 0
      src/main/java/com/izouma/nineth/utils/excel/MetaIsLandTypeEnumConverter.java
  16. 72 0
      src/main/java/com/izouma/nineth/web/MetaBoatPositionController.java
  17. 6 0
      src/main/java/com/izouma/nineth/web/MetaSpatialWharfController.java
  18. 46 0
      src/main/java/com/izouma/nineth/web/MetaVisitorController.java
  19. 8 0
      src/main/java/com/izouma/nineth/web/PublicScreenChatController.java
  20. 1 0
      src/main/resources/genjson/MetaBoatPosition.json
  21. 1 0
      src/main/resources/genjson/MetaVisitor.json
  22. 33 0
      src/main/vue/src/router.js
  23. 165 0
      src/main/vue/src/views/LivePublicScreenChatList.vue
  24. 193 0
      src/main/vue/src/views/MetaBoatPositionEdit.vue
  25. 182 0
      src/main/vue/src/views/MetaBoatPositionList.vue
  26. 166 0
      src/main/vue/src/views/MetaVisitorList.vue
  27. 1 1
      src/main/vue/src/views/PublicScreenChatList.vue

+ 41 - 0
src/main/java/com/izouma/nineth/domain/MetaBoatPosition.java

@@ -0,0 +1,41 @@
+package com.izouma.nineth.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.nineth.converter.CoordinateConverter;
+import com.izouma.nineth.dto.CoordinateDTO;
+import com.izouma.nineth.enums.MetaIsLandTypeEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙空间船位")
+public class MetaBoatPosition extends BaseEntity {
+
+    @ApiModelProperty("岛屿类型")
+    @ExcelProperty("岛屿类型")
+    @Enumerated(EnumType.STRING)
+    private MetaIsLandTypeEnum type;
+
+    @ApiModelProperty("位置信息")
+    @ExcelProperty("位置信息")
+    @Convert(converter = CoordinateConverter.class)
+    private CoordinateDTO boatPos;
+
+    @ApiModelProperty("旋转值")
+    @ExcelProperty("旋转值")
+    @Convert(converter = CoordinateConverter.class)
+    private CoordinateDTO boatRot;
+
+    @Transient
+    @ExcelIgnore
+    private MetaSpatialWharf boatInfo;
+}

+ 8 - 11
src/main/java/com/izouma/nineth/domain/MetaSpatialWharf.java

@@ -1,16 +1,15 @@
 package com.izouma.nineth.domain;
 
+import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelProperty;
-import com.izouma.nineth.converter.CoordinateConverter;
-import com.izouma.nineth.dto.CoordinateDTO;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
-import javax.persistence.Convert;
 import javax.persistence.Entity;
+import javax.persistence.Transient;
 
 @Data
 @AllArgsConstructor
@@ -39,13 +38,11 @@ public class MetaSpatialWharf extends BaseEntity {
     @ExcelProperty("船只类型 NFT稀有度")
     private String boatType;
 
-    @ApiModelProperty("位置信息")
-    @ExcelProperty("位置信息")
-    @Convert(converter = CoordinateConverter.class)
-    private CoordinateDTO boatPos;
+    @ApiModelProperty("船位id")
+    @ExcelProperty("船位id")
+    private Long metaBoatPositionId;
 
-    @ApiModelProperty("旋转值")
-    @ExcelProperty("旋转值")
-    @Convert(converter = CoordinateConverter.class)
-    private CoordinateDTO boatRot;
+    @Transient
+    @ExcelIgnore
+    private boolean meUse;
 }

+ 29 - 0
src/main/java/com/izouma/nineth/domain/MetaVisitor.java

@@ -0,0 +1,29 @@
+package com.izouma.nineth.domain;
+
+import com.izouma.nineth.annotations.Searchable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@ApiModel("元宇宙游客")
+public class MetaVisitor extends BaseEntity {
+
+    @ApiModelProperty("游客头像")
+    private String avatar;
+
+    @ApiModelProperty("游客昵称")
+    @Searchable
+    private String nickname;
+
+    @ApiModelProperty("是否禁言")
+    private boolean taboo;
+
+}

+ 9 - 0
src/main/java/com/izouma/nineth/domain/PublicScreenChat.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth.domain;
 
+import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.izouma.nineth.annotations.Searchable;
 import io.swagger.annotations.ApiModel;
@@ -57,6 +58,14 @@ public class PublicScreenChat extends BaseEntity {
     @ExcelProperty("消息是否合法")
     private boolean illegal;
 
+    @ApiModelProperty("1:正常,2:待撤回,3:已撤回")
+    @ExcelIgnore
+    private int recall;
+
+    @ApiModelProperty("类型 1:直播 2:元宇宙聊天")
+    @ExcelIgnore
+    private int type;
+
     @Transient
     private boolean myself;
 }

+ 21 - 0
src/main/java/com/izouma/nineth/enums/MetaIsLandTypeEnum.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.enums;
+
+
+public enum MetaIsLandTypeEnum {
+
+    TEN_THOUSAND("10000m²空间岛"),
+
+    SIX_THOUSAND("60000m²空间岛"),
+
+    NINE_THOUSAND("90000m²空间岛");
+
+    private final String description;
+
+    MetaIsLandTypeEnum(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}

+ 21 - 0
src/main/java/com/izouma/nineth/repo/MetaBoatPositionRepo.java

@@ -0,0 +1,21 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaBoatPosition;
+import com.izouma.nineth.enums.MetaIsLandTypeEnum;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+public interface MetaBoatPositionRepo extends JpaRepository<MetaBoatPosition, Long>, JpaSpecificationExecutor<MetaBoatPosition> {
+
+    @Query("update MetaBoatPosition t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    List<MetaBoatPosition> findAllByTypeAndDel(MetaIsLandTypeEnum type, boolean del);
+}

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

@@ -31,4 +31,6 @@ public interface MetaSpatialInfoRepo extends JpaRepository<MetaSpatialInfo, Long
     @Query(value = "select * from meta_spatial_info where type = ?1 and del = false and user_id <> ?2", nativeQuery = true)
     List<MetaSpatialInfo> findByTypeAndUserIdNot(int type, Long userId);
 
+    MetaSpatialInfo findByIdAndDel(Long id, boolean del);
+
 }

+ 9 - 0
src/main/java/com/izouma/nineth/repo/MetaSpatialWharfRepo.java

@@ -13,13 +13,22 @@ public interface MetaSpatialWharfRepo extends JpaRepository<MetaSpatialWharf, Lo
 
     MetaSpatialWharf findByBoatIdAndUserIdAndDel(Long boatId, Long userId, boolean del);
 
+    MetaSpatialWharf findByMetaBoatPositionIdAndDel(Long metaBoatPositionId, boolean del);
+
     @Query(value = "delete from meta_spatial_wharf where boat_id = ?1", nativeQuery = true)
     @Modifying
     @Transactional
     int back(Long boatId);
 
+    @Query(value = "delete from meta_spatial_wharf where user_id = ?1", nativeQuery = true)
+    @Modifying
+    @Transactional
+    int backAll(Long userId);
+
     MetaSpatialWharf findByBoatIdAndDel(Long boatId, boolean del);
 
     @Query(value = "select id from meta_spatial_wharf where user_id = ?1 and del = false", nativeQuery = true)
     List<Long> findParkingBoatIds(Long userId);
+
+    MetaSpatialWharf findAllByIsLandIdAndMetaBoatPositionIdAndDel(Long isLandId, Long metaPositionId, boolean del);
 }

+ 22 - 0
src/main/java/com/izouma/nineth/repo/MetaVisitorRepo.java

@@ -0,0 +1,22 @@
+package com.izouma.nineth.repo;
+
+import com.izouma.nineth.domain.MetaVisitor;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+
+public interface MetaVisitorRepo extends JpaRepository<MetaVisitor, Long>, JpaSpecificationExecutor<MetaVisitor> {
+
+    @Query("update MetaVisitor t set t.taboo = true where t.id = ?1 and t.del = false")
+    @Modifying
+    @Transactional
+    void taboo(Long id);
+
+    @Query("update MetaVisitor t set t.taboo = false where t.id = ?1 and t.del = false")
+    @Modifying
+    @Transactional
+    void cancelTaboo(Long id);
+}

+ 8 - 0
src/main/java/com/izouma/nineth/repo/PublicScreenChatRepo.java

@@ -3,7 +3,15 @@ package com.izouma.nineth.repo;
 import com.izouma.nineth.domain.PublicScreenChat;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
 
 public interface PublicScreenChatRepo extends JpaRepository<PublicScreenChat, Long>, JpaSpecificationExecutor<PublicScreenChat> {
 
+    @Query("update PublicScreenChat t set t.recall = 2 where t.id = ?1")
+    @Modifying
+    @Transactional
+    void recall(Long id);
 }

+ 74 - 0
src/main/java/com/izouma/nineth/service/MetaBoatPositionService.java

@@ -0,0 +1,74 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaBoatPosition;
+import com.izouma.nineth.domain.MetaSpatialInfo;
+import com.izouma.nineth.domain.MetaSpatialWharf;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.enums.MetaIsLandTypeEnum;
+import com.izouma.nineth.repo.MetaBoatPositionRepo;
+import com.izouma.nineth.repo.MetaSpatialInfoRepo;
+import com.izouma.nineth.repo.MetaSpatialWharfRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import com.izouma.nineth.utils.SecurityUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@AllArgsConstructor
+public class MetaBoatPositionService {
+
+    private MetaBoatPositionRepo metaBoatPositionRepo;
+
+    private MetaSpatialInfoRepo metaSpatialInfoRepo;
+
+    private MetaSpatialWharfRepo metaSpatialWharfRepo;
+
+    public Page<MetaBoatPosition> all(PageQuery pageQuery) {
+        return metaBoatPositionRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaBoatPosition.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public MetaRestResult<List<MetaBoatPosition>> queryBoatPosition(Long spaceInfoId) {
+        Long userId = SecurityUtils.getAuthenticatedUser().getId();
+        MetaSpatialInfo metaSpatialInfo = metaSpatialInfoRepo.findByIdAndDel(spaceInfoId, false);
+        if (Objects.isNull(metaSpatialInfo)) {
+            return MetaRestResult.returnError("查询不到空间信息");
+        }
+        if (!metaSpatialInfo.getUserId().equals(userId)) {
+            return MetaRestResult.returnError("该空间不属于你");
+        }
+        if (metaSpatialInfo.getType() != 2) {
+            return MetaRestResult.returnError("该空间不属于万岛空间");
+        }
+        MetaIsLandTypeEnum metaIsLandTypeEnum = queryIsLandType(metaSpatialInfo.getSize());
+        if (Objects.isNull(metaIsLandTypeEnum)) {
+            return MetaRestResult.returnError("该空间大小不合法");
+        }
+        List<MetaBoatPosition> metaBoatPositions = metaBoatPositionRepo.findAllByTypeAndDel(metaIsLandTypeEnum, false);
+        metaBoatPositions.forEach(metaBoatPosition -> {
+            MetaSpatialWharf metaSpatialWharf = metaSpatialWharfRepo.findAllByIsLandIdAndMetaBoatPositionIdAndDel(spaceInfoId, metaBoatPosition.getId(), false);
+            if (Objects.nonNull(metaSpatialWharf)) {
+                metaSpatialWharf.setMeUse(metaSpatialWharf.getUserId().equals(userId));
+                metaBoatPosition.setBoatInfo(metaSpatialWharf);
+            }
+        });
+        return MetaRestResult.returnSuccess(metaBoatPositions);
+    }
+
+    private MetaIsLandTypeEnum queryIsLandType(int size) {
+        switch (size) {
+            case 10000:
+                return MetaIsLandTypeEnum.TEN_THOUSAND;
+            case 60000:
+                return MetaIsLandTypeEnum.SIX_THOUSAND;
+            case 90000:
+                return MetaIsLandTypeEnum.NINE_THOUSAND;
+            default:
+                return null;
+        }
+    }
+}

+ 6 - 5
src/main/java/com/izouma/nineth/service/MetaSpatialWharfService.java

@@ -51,11 +51,12 @@ public class MetaSpatialWharfService {
         if (StringUtils.isBlank(metaSpatialWharf.getBoatType())) {
             return MetaRestResult.returnError("Illegal parameter : boatType can not be null");
         }
-        if (Objects.isNull(metaSpatialWharf.getBoatPos())) {
-            return MetaRestResult.returnError("Illegal parameter : boatPos can not be null");
+        if (Objects.isNull(metaSpatialWharf.getMetaBoatPositionId())) {
+            return MetaRestResult.returnError("Illegal parameter : metaBoatPositionId can not be null");
         }
-        if (Objects.isNull(metaSpatialWharf.getBoatRot())) {
-            return MetaRestResult.returnError("Illegal parameter : boatRot can not be null");
+        MetaSpatialWharf position = metaSpatialWharfRepo.findByMetaBoatPositionIdAndDel(metaSpatialWharf.getMetaBoatPositionId(), false);
+        if (Objects.nonNull(position)) {
+            return MetaRestResult.returnError(String.format("该位置已被船[%S]停靠", position.getBoatId()));
         }
         MetaSpatialWharf dbMetaSpatialWharf = metaSpatialWharfRepo.findByBoatIdAndUserIdAndDel(metaSpatialWharf.getBoatId(), metaSpatialWharf.getUserId(), false);
         if (Objects.nonNull(dbMetaSpatialWharf)) {
@@ -66,7 +67,7 @@ public class MetaSpatialWharfService {
             return MetaRestResult.returnError(String.format("藏品[%S]不存在", metaSpatialWharf.getBoatId()));
         }
         metaSpatialWharf.setBoatImg(asset.getPic().get(0).getUrl());
-        return MetaRestResult.returnSuccess("", metaSpatialWharfRepo.save(metaSpatialWharf));
+        return MetaRestResult.returnSuccess("停靠成功", metaSpatialWharfRepo.save(metaSpatialWharf));
     }
 
     private String getRarityType(String name) {

+ 20 - 0
src/main/java/com/izouma/nineth/service/MetaVisitorService.java

@@ -0,0 +1,20 @@
+package com.izouma.nineth.service;
+
+import com.izouma.nineth.domain.MetaVisitor;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.MetaVisitorRepo;
+import com.izouma.nineth.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class MetaVisitorService {
+
+    private MetaVisitorRepo metaVisitorRepo;
+
+    public Page<MetaVisitor> all(PageQuery pageQuery) {
+        return metaVisitorRepo.findAll(JpaUtils.toSpecification(pageQuery, MetaVisitor.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 1 - 0
src/main/java/com/izouma/nineth/utils/excel/ExcelUtils.java

@@ -38,6 +38,7 @@ public class ExcelUtils<T> {
                 .registerConverter(new OperationSourceConverter())
                 .registerConverter(new RecordTypeConverter())
                 .registerConverter(new MetaPointTypeEnumConverter())
+                .registerConverter(new MetaIsLandTypeEnumConverter())
                 .doWrite(data);
     }
 }

+ 42 - 0
src/main/java/com/izouma/nineth/utils/excel/MetaIsLandTypeEnumConverter.java

@@ -0,0 +1,42 @@
+package com.izouma.nineth.utils.excel;
+
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.izouma.nineth.enums.MetaIsLandTypeEnum;
+
+public class MetaIsLandTypeEnumConverter implements Converter<MetaIsLandTypeEnum> {
+
+    @Override
+    public Class supportJavaTypeKey() {
+        return MetaIsLandTypeEnum.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public MetaIsLandTypeEnum convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        try {
+            for (MetaIsLandTypeEnum value : MetaIsLandTypeEnum.values()) {
+                if (value.getDescription().equals(cellData.getStringValue())) {
+                    return value;
+                }
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
+
+    @Override
+    public CellData convertToExcelData(MetaIsLandTypeEnum value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+        if (value != null) {
+            return new CellData(value.getDescription());
+        }
+        return null;
+    }
+}

+ 72 - 0
src/main/java/com/izouma/nineth/web/MetaBoatPositionController.java

@@ -0,0 +1,72 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaBoatPosition;
+import com.izouma.nineth.dto.MetaRestResult;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.exception.BusinessException;
+import com.izouma.nineth.repo.MetaBoatPositionRepo;
+import com.izouma.nineth.repo.MetaSpatialInfoRepo;
+import com.izouma.nineth.repo.MetaSpatialWharfRepo;
+import com.izouma.nineth.service.MetaBoatPositionService;
+import com.izouma.nineth.utils.ObjUtils;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/metaBoatPosition")
+@AllArgsConstructor
+public class MetaBoatPositionController extends BaseController {
+    private MetaBoatPositionService metaBoatPositionService;
+    private MetaBoatPositionRepo metaBoatPositionRepo;
+
+    private MetaSpatialInfoRepo metaSpatialInfoRepo;
+
+    private MetaSpatialWharfRepo metaSpatialWharfRepo;
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public MetaBoatPosition save(@RequestBody MetaBoatPosition record) {
+        if (record.getId() != null) {
+            MetaBoatPosition orig = metaBoatPositionRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return metaBoatPositionRepo.save(orig);
+        }
+        return metaBoatPositionRepo.save(record);
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaBoatPosition> all(@RequestBody PageQuery pageQuery) {
+        return metaBoatPositionService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public MetaBoatPosition get(@PathVariable Long id) {
+        return metaBoatPositionRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        metaBoatPositionRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaBoatPosition> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/{spaceInfoId}/queryBoatPosition")
+    public MetaRestResult<List<MetaBoatPosition>> queryBoatPosition(@PathVariable Long spaceInfoId) {
+        return metaBoatPositionService.queryBoatPosition(spaceInfoId);
+    }
+}
+

+ 6 - 0
src/main/java/com/izouma/nineth/web/MetaSpatialWharfController.java

@@ -56,6 +56,12 @@ public class MetaSpatialWharfController extends BaseController {
         return MetaRestResult.returnSuccess("收回船只成功!");
     }
 
+    @PostMapping("/backAll")
+    public MetaRestResult<Void> backAll() {
+        metaSpatialWharfRepo.backAll(SecurityUtils.getAuthenticatedUser().getId());
+        return MetaRestResult.returnSuccess("收回船只成功!");
+    }
+
     @GetMapping("/{boatId}/myself")
     public MetaRestResult<Boolean> myself(@PathVariable Long boatId) {
         MetaSpatialWharf metaSpatialWharf = metaSpatialWharfRepo.findByBoatIdAndDel(boatId, false);

+ 46 - 0
src/main/java/com/izouma/nineth/web/MetaVisitorController.java

@@ -0,0 +1,46 @@
+package com.izouma.nineth.web;
+
+import com.izouma.nineth.domain.MetaVisitor;
+import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.MetaVisitorRepo;
+import com.izouma.nineth.service.MetaVisitorService;
+import com.izouma.nineth.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/metaVisitor")
+@AllArgsConstructor
+public class MetaVisitorController extends BaseController {
+    private MetaVisitorService metaVisitorService;
+    private MetaVisitorRepo metaVisitorRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<MetaVisitor> all(@RequestBody PageQuery pageQuery) {
+        return metaVisitorService.all(pageQuery);
+    }
+
+    @PostMapping("/taboo/{id}")
+    public void taboo(@PathVariable Long id) {
+        metaVisitorRepo.taboo(id);
+    }
+
+    @PostMapping("/cancelTaboo/{id}")
+    public void cancelTaboo(@PathVariable Long id) {
+        metaVisitorRepo.cancelTaboo(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<MetaVisitor> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 8 - 0
src/main/java/com/izouma/nineth/web/PublicScreenChatController.java

@@ -2,6 +2,7 @@ package com.izouma.nineth.web;
 
 import com.izouma.nineth.domain.PublicScreenChat;
 import com.izouma.nineth.dto.PageQuery;
+import com.izouma.nineth.repo.PublicScreenChatRepo;
 import com.izouma.nineth.service.PublicScreenChatService;
 import com.izouma.nineth.utils.excel.ExcelUtils;
 import lombok.AllArgsConstructor;
@@ -18,6 +19,8 @@ import java.util.List;
 public class PublicScreenChatController extends BaseController {
     private PublicScreenChatService publicScreenChatService;
 
+    private PublicScreenChatRepo publicScreenChatRepo;
+
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
     public Page<PublicScreenChat> all(@RequestBody PageQuery pageQuery) {
@@ -31,5 +34,10 @@ public class PublicScreenChatController extends BaseController {
         List<PublicScreenChat> data = all(pageQuery).getContent();
         ExcelUtils.export(response, data);
     }
+
+    @PostMapping("/recall/{id}")
+    public void recall(@PathVariable Long id) {
+        publicScreenChatRepo.recall(id);
+    }
 }
 

+ 1 - 0
src/main/resources/genjson/MetaBoatPosition.json

@@ -0,0 +1 @@
+{"tableName":"MetaBoatPosition","className":"MetaBoatPosition","remark":"空间船位管理","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/java/com/izouma/nineth","viewPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src/views","routerPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src","resourcesPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"isLandId","modelName":"isLandId","remark":"岛屿ID","showInList":true,"showInForm":true,"formType":"number","required":true,"validate":false},{"name":"type","modelName":"type","remark":"岛屿类型","showInList":false,"showInForm":false,"formType":"singleLineText"},{"name":"boatPos","modelName":"boatPos","remark":"位置信息","showInList":true,"showInForm":true,"formType":"singleLineText","required":true},{"name":"boatRot","modelName":"boatRot","remark":"旋转值","showInList":true,"showInForm":true,"formType":"singleLineText","required":true}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.MetaBoatPosition"}

+ 1 - 0
src/main/resources/genjson/MetaVisitor.json

@@ -0,0 +1 @@
+{"tableName":"MetaVisitor","className":"MetaVisitor","remark":"游客管理","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/java/com/izouma/nineth","viewPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src/views","routerPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/vue/src","resourcesPath":"/Users/xiaohuoban/IdeaProjects/raex_back/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"avatar","modelName":"avatar","remark":"头像","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"nickname","modelName":"nickname","remark":"昵称","showInList":true,"showInForm":true,"formType":"singleLineText"}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.nineth","tablePackage":"com.izouma.nineth.domain.MetaVisitor"}

+ 33 - 0
src/main/vue/src/router.js

@@ -1256,6 +1256,15 @@ const router = new Router({
                         title: '公屏对话'
                     }
                 },
+                {
+                    path: '/livePublicScreenChatList',
+                    name: 'LivePublicScreenChatList',
+                    component: () =>
+                        import(/* webpackChunkName: "livePublicScreenChatList" */ '@/views/LivePublicScreenChatList.vue'),
+                    meta: {
+                        title: '直播聊天内容管理'
+                    }
+                },
                 {
                     path: '/metaItemEdit',
                     name: 'MetaItemEdit',
@@ -1443,6 +1452,30 @@ const router = new Router({
                     meta: {
                        title: '船只停靠列表',
                     },
+               },
+                {
+                    path: '/metaBoatPositionEdit',
+                    name: 'MetaBoatPositionEdit',
+                    component: () => import(/* webpackChunkName: "metaBoatPositionEdit" */ '@/views/MetaBoatPositionEdit.vue'),
+                    meta: {
+                       title: '空间船位管理编辑',
+                    },
+                },
+                {
+                    path: '/metaBoatPositionList',
+                    name: 'MetaBoatPositionList',
+                    component: () => import(/* webpackChunkName: "metaBoatPositionList" */ '@/views/MetaBoatPositionList.vue'),
+                    meta: {
+                       title: '空间船位管理',
+                    },
+               },
+                {
+                    path: '/metaVisitorList',
+                    name: 'MetaVisitorList',
+                    component: () => import(/* webpackChunkName: "metaVisitorList" */ '@/views/MetaVisitorList.vue'),
+                    meta: {
+                       title: '游客管理',
+                    },
                }
                 /**INSERT_LOCATION**/
             ]

+ 165 - 0
src/main/vue/src/views/LivePublicScreenChatList.vue

@@ -0,0 +1,165 @@
+<template>
+	<div class="list-view">
+		<page-title>
+			<el-button
+				@click="download"
+				icon="el-icon-upload2"
+				:loading="downloading"
+				:disabled="fetchingData"
+				class="filter-item"
+			>
+				导出
+			</el-button>
+		</page-title>
+		<div class="filters-container">
+			<el-input
+				placeholder="搜索..."
+				v-model="search"
+				clearable
+				class="filter-item search"
+				@keyup.enter.native="getData"
+			>
+				<el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+			</el-input>
+		</div>
+		<el-table
+			:data="tableData"
+			row-key="id"
+			ref="table"
+			header-row-class-name="table-header-row"
+			header-cell-class-name="table-header-cell"
+			row-class-name="table-row"
+			cell-class-name="table-cell"
+			:height="tableHeight"
+			v-loading="fetchingData"
+		>
+			<el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+			<el-table-column prop="nickname" align="center" label="用户昵称"> </el-table-column>
+			<el-table-column prop="userId" align="center" label="用户id"> </el-table-column>
+			<el-table-column prop="avatar" align="center" label="头像">
+				<template slot-scope="{ row }">
+					<el-image
+						style="width: 30px; height: 30px"
+						:src="row.avatar"
+						fit="cover"
+						:preview-src-list="[row.avatar]"
+					>
+					</el-image>
+				</template>
+			</el-table-column>
+			<el-table-column prop="messageInfo" align="center" width="600" label="消息内容"> </el-table-column>
+			<el-table-column prop="illegal" align="center" label="是否合法">
+				<template slot-scope="{ row }">
+					<el-tag :type="row.illegal ? '' : 'info'"> {{ row.illegal }} </el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column prop="recall" align="center" label="是否撤回">
+				<template v-slot="{ row }">
+                    <template v-if="row.recall === 2">
+                        {{ '待撤回' }}
+                    </template>
+					<template v-else-if="row.recall === 3">
+                        {{ '已撤回' }}
+                    </template>
+                    <template v-else>
+                        {{ '正常' }}
+                    </template>
+                </template>
+            </el-table-column>
+			<el-table-column prop="time" align="center" width="200" label="消息发送时间"> </el-table-column>
+			<el-table-column label="操作" align="center" fixed="right" width="100">
+                <template slot-scope="{ row }">
+                    <el-button @click="recall(row)" type="danger" size="mini" plain>撤回</el-button>
+                </template>
+            </el-table-column>
+		</el-table>
+		<div class="pagination-wrapper">
+			<el-pagination
+				background
+				@size-change="onSizeChange"
+				@current-change="onCurrentChange"
+				:current-page="page"
+				:page-sizes="[10, 20, 30, 40, 50]"
+				:page-size="pageSize"
+				layout="total, sizes, prev, pager, next, jumper"
+				:total="totalElements"
+			>
+			</el-pagination>
+		</div>
+	</div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+	name: 'PublicScreenChatList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			multipleMode: false,
+			search: '',
+			url: '/publicScreenChat/all',
+			downloading: false
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		beforeGetData() {
+			return { search: this.search, query: { del: false, type: 2 } };
+		},
+		toggleMultipleMode(multipleMode) {
+			this.multipleMode = multipleMode;
+			if (!multipleMode) {
+				this.$refs.table.clearSelection();
+			}
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/publicScreenChat/excel', {
+					responseType: 'blob',
+					params: { size: 10000 ,query: { del: false }},
+				})
+				.then(res => {
+					console.log(res);
+					this.downloading = false;
+					const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+					const link = document.createElement('a');
+					link.href = downloadUrl;
+					link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+					document.body.appendChild(link);
+					link.click();
+					link.remove();
+				})
+				.catch(e => {
+					console.log(e);
+					this.downloading = false;
+					this.$message.error(e.error);
+				});
+		},
+		recall(row) {
+			this.$alert('确定要将该信息撤回吗?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/publicScreenChat/recall/${row.id}`);
+				})
+				.then(() => {
+					this.$message.success('操作成功,等待服务器撤回');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+		}
+	}
+};
+</script>
+<style lang="less" scoped>
+
+</style>

+ 193 - 0
src/main/vue/src/views/MetaBoatPositionEdit.vue

@@ -0,0 +1,193 @@
+<template>
+	<div class="edit-view">
+		<page-title>
+			<el-button @click="$router.go(-1)" :disabled="saving"> 取消 </el-button>
+			<el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id"> 删除 </el-button>
+			<el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
+		</page-title>
+		<div class="edit-view__content-wrapper">
+			<div class="edit-view__content-section">
+				<el-form
+					:model="formData"
+					:rules="rules"
+					ref="form"
+					label-width="80px"
+					label-position="right"
+					size="small"
+					style="max-width: 500px"
+				>
+					<el-form-item prop="type" label="岛屿类型">
+						<el-select v-model="formData.type" clearable filterable placeholder="请选择">
+							<el-option
+								v-for="item in typeOptions"
+								:key="item.value"
+								:label="item.label"
+								:value="item.value"
+							>
+							</el-option>
+						</el-select>
+					</el-form-item>
+					<el-form-item prop="boatPos" label="位置信息">
+						<el-input v-model="formData.boatPos.x" placeholder="请输入位置信息 -> x"> </el-input>
+						<el-input v-model="formData.boatPos.y" placeholder="请输入位置信息 -> y"> </el-input>
+						<el-input v-model="formData.boatPos.z" placeholder="请输入位置信息 -> z"> </el-input>
+					</el-form-item>
+					<el-form-item prop="boatRot" label="旋转值">
+						<el-input v-model="formData.boatRot.x" placeholder="请输入旋转值 -> x"> </el-input>
+						<el-input v-model="formData.boatRot.y" placeholder="请输入旋转值 -> x"> </el-input>
+						<el-input v-model="formData.boatRot.z" placeholder="请输入旋转值 -> x"> </el-input>
+					</el-form-item>
+					<el-form-item class="form-submit">
+						<el-button @click="onSave" :loading="saving" type="primary"> 保存 </el-button>
+						<el-button @click="onDelete" :disabled="saving" type="danger" v-if="formData.id">
+							删除
+						</el-button>
+						<el-button @click="$router.go(-1)" :disabled="saving"> 取消 </el-button>
+					</el-form-item>
+				</el-form>
+			</div>
+		</div>
+	</div>
+</template>
+<script>
+export default {
+	name: 'MetaBoatPositionEdit',
+	created() {
+		if (this.$route.query.id) {
+			this.$http
+				.get('metaBoatPosition/get/' + this.$route.query.id)
+				.then(res => {
+					this.formData = res;
+				})
+				.catch(e => {
+					console.log(e);
+					this.$message.error(e.error);
+				});
+		}
+	},
+	data() {
+		return {
+			saving: false,
+			formData: {
+				boatPos: {
+					x: '',
+					y: '',
+					z: ''
+				},
+				boatRot: {
+					x: '',
+					y: '',
+					z: ''
+				}
+			},
+			typeOptions: [
+				{ label: '10000m²空间岛', value: 'TEN_THOUSAND' },
+				{ label: '60000m²空间岛', value: 'SIX_THOUSAND' },
+				{ label: '90000m²空间岛', value: 'NINE_THOUSAND' }
+			],
+			rules: {
+				isLandId: [
+					{
+						required: true,
+						message: '请输入岛屿ID',
+						trigger: 'blur'
+					}
+				],
+				boatPos: [
+					{
+						required: true,
+						message: '请输入位置相关信息',
+						trigger: 'blur'
+					},
+					{
+						validator: (rule, value, callback) => {
+							if (value.x === null || value.x === undefined || value.x === '') {
+								callback(new Error('请输入位置信息 -> x'));
+								return;
+							} else if (value.y === null || value.y === undefined || value.y === '') {
+								callback(new Error('请输入位置信息 -> y'));
+								return;
+							} else if (value.z === null || value.z === undefined || value.z === '') {
+								callback(new Error('请输入位置信息 -> z'));
+								return;
+							} else {
+								callback();
+							}
+						}
+					}
+				],
+				boatRot: [
+					{
+						required: true,
+						message: '请输入旋转值相关信息',
+						trigger: 'blur'
+					},
+					{
+						validator: (rule, value, callback) => {
+							if (value.x === null || value.x === undefined || value.x === '') {
+								callback(new Error('请输入旋转值 -> x'));
+								return;
+							} else if (value.y === null || value.y === undefined || value.y === '') {
+								callback(new Error('请输入旋转值 -> y'));
+								return;
+							} else if (value.z === null || value.z === undefined || value.z === '') {
+								callback(new Error('请输入旋转值 -> z'));
+								return;
+							} else {
+								callback();
+							}
+						}
+					}
+				]
+			}
+		};
+	},
+	methods: {
+		onSave() {
+			this.$refs.form.validate(valid => {
+				if (valid) {
+					this.submit();
+				} else {
+					return false;
+				}
+			});
+		},
+		submit() {
+			let data = { ...this.formData };
+
+			this.saving = true;
+			this.$http
+				.post('/metaBoatPosition/save', data, { body: 'json' })
+				.then(res => {
+					this.saving = false;
+					this.$message.success('成功');
+					this.$router.go(-1);
+				})
+				.catch(e => {
+					console.log(e);
+					this.saving = false;
+					this.$message.error(e.error);
+				});
+		},
+		onDelete() {
+			this.$confirm('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/metaBoatPosition/del/${this.formData.id}`);
+				})
+				.then(() => {
+					this.$message.success('删除成功');
+					this.$router.go(-1);
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						console.log(e);
+						this.$message.error((e || {}).error || '删除失败');
+					}
+				});
+		}
+	}
+};
+</script>
+<style lang="less" scoped>
+
+</style>

+ 182 - 0
src/main/vue/src/views/MetaBoatPositionList.vue

@@ -0,0 +1,182 @@
+<template>
+	<div class="list-view">
+		<page-title>
+			<el-button
+				@click="addRow"
+				type="primary"
+				icon="el-icon-plus"
+				:disabled="fetchingData || downloading"
+				class="filter-item"
+			>
+				新增
+			</el-button>
+			<el-button
+				@click="download"
+				icon="el-icon-upload2"
+				:loading="downloading"
+				:disabled="fetchingData"
+				class="filter-item"
+			>
+				导出
+			</el-button>
+		</page-title>
+		<div class="filters-container">
+			<el-input
+				placeholder="搜索..."
+				v-model="search"
+				clearable
+				class="filter-item search"
+				@keyup.enter.native="getData"
+			>
+				<el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+			</el-input>
+		</div>
+		<el-table
+			:data="tableData"
+			row-key="id"
+			ref="table"
+			header-row-class-name="table-header-row"
+			header-cell-class-name="table-header-cell"
+			row-class-name="table-row"
+			cell-class-name="table-cell"
+			:height="tableHeight"
+			v-loading="fetchingData"
+		>
+			<el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+			<el-table-column prop="id" align="center" label="船位ID" width="100"> </el-table-column>
+			<el-table-column prop="type" align="center" label="岛屿类型" :formatter="typeFormatter"> </el-table-column>
+			<el-table-column align="center" prop="boatPos" label="位置信息">
+				<template slot-scope="{ row }">
+					{{ 'x=' + row.boatPos.x + ' , ' + 'y=' + row.boatPos.y + ' , ' + 'z=' + row.boatPos.z }}
+				</template>
+			</el-table-column>
+			<el-table-column align="center" prop="boatRot" label="旋转值">
+				<template slot-scope="{ row }">
+					{{ 'x=' + row.boatRot.x + ' , ' + 'y=' + row.boatRot.y + ' , ' + 'z=' + row.boatRot.z }}
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" align="center" fixed="right" width="150">
+				<template slot-scope="{ row }">
+					<el-button @click="editRow(row)" type="primary" size="mini" plain> 编辑 </el-button>
+					<el-button @click="deleteRow(row)" type="danger" size="mini" plain> 删除 </el-button>
+				</template>
+			</el-table-column>
+		</el-table>
+		<div class="pagination-wrapper">
+			<el-pagination
+				background
+				@size-change="onSizeChange"
+				@current-change="onCurrentChange"
+				:current-page="page"
+				:page-sizes="[10, 20, 30, 40, 50]"
+				:page-size="pageSize"
+				layout="total, sizes, prev, pager, next, jumper"
+				:total="totalElements"
+			>
+			</el-pagination>
+		</div>
+	</div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+	name: 'MetaBoatPositionList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			multipleMode: false,
+			search: '',
+			url: '/metaBoatPosition/all',
+			downloading: false,
+			typeOptions: [
+				{ label: '10000m²空间岛', value: 'TEN_THOUSAND' },
+				{ label: '60000m²空间岛', value: 'SIX_THOUSAND' },
+				{ label: '90000m²空间岛', value: 'NINE_THOUSAND' }
+			]
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		typeFormatter(row, column, cellValue, index) {
+			let selectedOption = this.typeOptions.find(i => i.value === cellValue);
+			if (selectedOption) {
+				return selectedOption.label;
+			}
+			return '';
+		},
+		beforeGetData() {
+			return { search: this.search, query: { del: false } };
+		},
+		toggleMultipleMode(multipleMode) {
+			this.multipleMode = multipleMode;
+			if (!multipleMode) {
+				this.$refs.table.clearSelection();
+			}
+		},
+		addRow() {
+			this.$router.push({
+				path: '/metaBoatPositionEdit',
+				query: {
+					...this.$route.query
+				}
+			});
+		},
+		editRow(row) {
+			this.$router.push({
+				path: '/metaBoatPositionEdit',
+				query: {
+					id: row.id
+				}
+			});
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/metaBoatPosition/excel', {
+					responseType: 'blob',
+					params: { size: 10000, query: { del: false } }
+				})
+				.then(res => {
+					console.log(res);
+					this.downloading = false;
+					const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+					const link = document.createElement('a');
+					link.href = downloadUrl;
+					link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+					document.body.appendChild(link);
+					link.click();
+					link.remove();
+				})
+				.catch(e => {
+					console.log(e);
+					this.downloading = false;
+					this.$message.error(e.error);
+				});
+		},
+		deleteRow(row) {
+			this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/metaBoatPosition/del/${row.id}`);
+				})
+				.then(() => {
+					this.$message.success('删除成功');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+		}
+	}
+};
+</script>
+<style lang="less" scoped>
+
+</style>

+ 166 - 0
src/main/vue/src/views/MetaVisitorList.vue

@@ -0,0 +1,166 @@
+<template>
+	<div class="list-view">
+		<page-title>
+			<el-button
+				@click="download"
+				icon="el-icon-upload2"
+				:loading="downloading"
+				:disabled="fetchingData"
+				class="filter-item"
+			>
+				导出
+			</el-button>
+		</page-title>
+		<div class="filters-container">
+			<el-input
+				placeholder="搜索..."
+				v-model="search"
+				clearable
+				class="filter-item search"
+				@keyup.enter.native="getData"
+			>
+				<el-button @click="getData" slot="append" icon="el-icon-search"> </el-button>
+			</el-input>
+		</div>
+		<el-table
+			:data="tableData"
+			row-key="id"
+			ref="table"
+			header-row-class-name="table-header-row"
+			header-cell-class-name="table-header-cell"
+			row-class-name="table-row"
+			cell-class-name="table-cell"
+			:height="tableHeight"
+			v-loading="fetchingData"
+		>
+			<el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+			<el-table-column prop="id" align="center" label="游客ID" width="100"> </el-table-column>
+			<el-table-column prop="avatar" align="center" label="头像">
+				<template slot-scope="{ row }">
+					<el-image
+						style="width: 30px; height: 30px"
+						:src="row.avatar"
+						fit="cover"
+						:preview-src-list="[row.avatar]"
+					>
+					</el-image>
+				</template>
+			</el-table-column>
+			<el-table-column prop="nickname" align="center" label="昵称"> </el-table-column>
+			<el-table-column prop="taboo" align="center" label="是否禁言">
+				<template slot-scope="{ row }">
+					<el-tag :type="row.taboo ? '' : 'info'"> {{ row.taboo }} </el-tag>
+				</template>
+			</el-table-column>
+			<el-table-column label="操作" align="center" fixed="right" width="350">
+				<template slot-scope="{ row }">
+					<el-button @click="cancelTaboo(row)" type="danger" size="mini" plain v-if="row.taboo"> 解除禁言 </el-button>
+					<el-button @click="taboo(row)" type="danger" size="mini" plain v-if="!row.taboo"> 禁言 </el-button>
+				</template>
+			</el-table-column>
+		</el-table>
+		<div class="pagination-wrapper">
+			<el-pagination
+				background
+				@size-change="onSizeChange"
+				@current-change="onCurrentChange"
+				:current-page="page"
+				:page-sizes="[10, 20, 30, 40, 50]"
+				:page-size="pageSize"
+				layout="total, sizes, prev, pager, next, jumper"
+				:total="totalElements"
+			>
+			</el-pagination>
+		</div>
+	</div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+	name: 'MetaVisitorList',
+	mixins: [pageableTable],
+	data() {
+		return {
+			multipleMode: false,
+			search: '',
+			url: '/metaVisitor/all',
+			downloading: false
+		};
+	},
+	computed: {
+		selection() {
+			return this.$refs.table.selection.map(i => i.id);
+		}
+	},
+	methods: {
+		beforeGetData() {
+			return { search: this.search, query: { del: false } };
+		},
+		toggleMultipleMode(multipleMode) {
+			this.multipleMode = multipleMode;
+			if (!multipleMode) {
+				this.$refs.table.clearSelection();
+			}
+		},
+		download() {
+			this.downloading = true;
+			this.$axios
+				.get('/metaVisitor/excel', {
+					responseType: 'blob',
+					params: { size: 10000, query: { del: false } }
+				})
+				.then(res => {
+					console.log(res);
+					this.downloading = false;
+					const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+					const link = document.createElement('a');
+					link.href = downloadUrl;
+					link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+					document.body.appendChild(link);
+					link.click();
+					link.remove();
+				})
+				.catch(e => {
+					console.log(e);
+					this.downloading = false;
+					this.$message.error(e.error);
+				});
+		},
+		taboo(row) {
+			this.$alert('确定要将该玩家禁言吗?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/metaVisitor/taboo/${row.id}`);
+				})
+				.then(() => {
+					this.$message.success('禁言成功');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+		},
+		cancelTaboo(row) {
+			this.$alert('确定要解除该玩家禁言吗?', '警告', { type: 'error' })
+				.then(() => {
+					return this.$http.post(`/metaVisitor/cancelTaboo/${row.id}`);
+				})
+				.then(() => {
+					this.$message.success('解除禁言成功');
+					this.getData();
+				})
+				.catch(e => {
+					if (e !== 'cancel') {
+						this.$message.error(e.error);
+					}
+				});
+		}
+	}
+};
+</script>
+<style lang="less" scoped>
+
+</style>

+ 1 - 1
src/main/vue/src/views/PublicScreenChatList.vue

@@ -95,7 +95,7 @@ export default {
 	},
 	methods: {
 		beforeGetData() {
-			return { search: this.search, query: { del: false } };
+			return { search: this.search, query: { del: false, type: 1 } };
 		},
 		toggleMultipleMode(multipleMode) {
 			this.multipleMode = multipleMode;