Преглед на файлове

Merge remote-tracking branch 'origin/master'

wujiefeng преди 1 година
родител
ревизия
85149b9f32
променени са 32 файла, в които са добавени 1115 реда и са изтрити 338 реда
  1. 2 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/org/OrganizationMiniModel.java
  2. 69 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/CreateOrderParam.java
  3. 49 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/ExpenseFlowPayShowModel.java
  4. 43 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/OrderPayModel.java
  5. 71 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/ProjectSceneInfoDetailModel.java
  6. 28 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleBindsSceneParam.java
  7. 42 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneComTreeModel.java
  8. 22 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneComponentModel.java
  9. 15 2
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneInfoModel.java
  10. 1 1
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/SceneInfoModel.java
  11. 0 1
      FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/SceneInfoParam.java
  12. 27 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/payment/OrderController.java
  13. 9 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/ProjectSceneInfoController.java
  14. 32 28
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/RoleSceneInfoController.java
  15. 9 5
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/SceneInfoController.java
  16. 6 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/scene/RoleSceneInfoDao.java
  17. 2 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/scene/SceneComponentDao.java
  18. 1 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/OrderConfig.java
  19. 3 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DeviceInfo.java
  20. 7 6
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/payment/ExpenseFlow.java
  21. 5 5
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/scene/ProjectSceneInfo.java
  22. 12 7
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/scene/RoleSceneInfo.java
  23. 6 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/CommonService.java
  24. 70 10
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceInfoServiceImpl.java
  25. 4 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceSyncFromIotService.java
  26. 12 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/deviceProduct/DeviceProductBindDeviceService.java
  27. 296 131
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/ExpenseFlowServiceImpl.java
  28. 8 15
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/OrderService.java
  29. 31 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/ProjectSceneInfoService.java
  30. 182 120
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/RoleSceneInfoService.java
  31. 50 4
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/SceneInfoService.java
  32. 1 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/util/NextNoUtil.java

+ 2 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/org/OrganizationMiniModel.java

@@ -25,6 +25,8 @@ public class OrganizationMiniModel {
     @Schema(description = "编码、项目ID、机构编号")
     private String code;
 
+    private String logo;
+
     @Schema(description = "机构类型")
     private AuthType authType = AuthType.Enterprise;
 

+ 69 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/CreateOrderParam.java

@@ -0,0 +1,69 @@
+package com.zhongshu.card.client.model.payment;
+
+import com.github.microservice.models.type.OrderFromType;
+import com.github.microservice.types.OrderModeType;
+import com.github.microservice.types.payment.ChargeableType;
+import com.github.microservice.types.payment.PaymentDeviceType;
+import com.github.microservice.types.payment.PaymentType;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2025/1/16
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CreateOrderParam {
+
+    @Schema(description = "消息ID")
+    private String mqttDataId;
+
+    @Schema(description = "订单方式")
+    private OrderModeType orderModeType = OrderModeType.Consume;
+
+    @Schema(description = "是否是设备订单")
+    private Boolean isDeviceOrder = Boolean.TRUE;
+
+    @Schema(description = "设备ID")
+    private String deviceId;
+
+    @Schema(description = "订单计费方式,定额支付")
+    private ChargeableType chargeableType = ChargeableType.Specified;
+
+    @Schema(description = "支付来源")
+    private OrderFromType orderFromType;
+
+    @Schema(description = "服务id、商品id")
+    private String productProvideId;
+
+    @Schema(description = "消费序号(年月日时分秒+2个字节序号(0~65535)),用于识别上传数据不重复")
+    private String orderNo;
+
+    @Schema(description = "10进制卡序列号(实体卡号或虚拟卡号)")
+    private String cardNo;
+
+    @Schema(description = "消费金额(Mode为2时,此字段传入值可能为0)")
+    private String amount;
+
+    @Schema(description = "支付方式")
+    private PaymentType paymentType;
+
+    @Schema(description = "支付设备和方式")
+    private PaymentDeviceType paymentDeviceType;
+
+    @Schema(description = "下单用户")
+    private String userId;
+
+    @Schema(description = "是否允许匿名下单")
+    private Boolean isAnonymous = Boolean.FALSE;
+
+    @Schema(description = "消费类型,如:餐饮消费、水费、电费 等等")
+    private String payType;
+
+    @Schema(description = "订单支付有效期时间,毫秒")
+    private Long expirationTime;
+}

+ 49 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/ExpenseFlowPayShowModel.java

@@ -0,0 +1,49 @@
+package com.zhongshu.card.client.model.payment;
+
+import com.zhongshu.card.client.model.base.SuperModel;
+import com.zhongshu.card.client.model.devices.DeviceInfoModel;
+import com.zhongshu.card.client.model.org.OrganizationMiniModel;
+import com.zhongshu.card.client.model.org.OrganizationSimpleModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * @author TRX
+ * @date 2024/6/17
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ExpenseFlowPayShowModel extends SuperModel {
+
+    @Schema(description = "消费订单号")
+    private String orderNo;
+
+    @Schema(description = "支付订单号")
+    private String paymentNo;
+
+    @Schema(description = "订单生效时间")
+    private Long startTime;
+
+    @Schema(description = "订单失效时间")
+    private Long expirationTime;
+
+    @Schema(description = "消费金额(单位:分)")
+    private BigDecimal payAmount;
+
+    @Schema(description = "设备信息")
+    private DeviceInfoModel deviceInfo;
+
+    @Schema(description = "收款机构信息")
+    private OrganizationMiniModel shopInfo;
+
+    @Schema(description = "是否可以支付")
+    private Boolean isCanPay = Boolean.FALSE;
+
+    @Schema(description = "支付提示")
+    private String payMsg = "";
+}

+ 43 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/payment/OrderPayModel.java

@@ -0,0 +1,43 @@
+package com.zhongshu.card.client.model.payment;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2025/1/16
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class OrderPayModel {
+
+    @Schema(description = "是否可以支付")
+    private Boolean isCanPay = Boolean.TRUE;
+
+    @Schema(description = "支付提示")
+    private String payMsg = "";
+
+    public OrderPayModel setFiled(String msg) {
+        this.isCanPay = Boolean.FALSE;
+        this.payMsg = msg;
+        return this;
+    }
+
+    public OrderPayModel setSuccess() {
+        this.isCanPay = Boolean.TRUE;
+        return this;
+    }
+
+    public OrderPayModel setSuccess(String msg) {
+        this.isCanPay = Boolean.TRUE;
+        this.payMsg = msg;
+        return this;
+    }
+
+    public boolean isSuccess() {
+        return this.isCanPay;
+    }
+}

+ 71 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/ProjectSceneInfoDetailModel.java

@@ -0,0 +1,71 @@
+package com.zhongshu.card.client.model.scene;
+
+import com.zhongshu.card.client.model.base.SuperModel;
+import com.zhongshu.card.client.type.DataState;
+import com.zhongshu.card.client.type.scene.SceneType;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/11/22
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProjectSceneInfoDetailModel extends SuperModel {
+
+    @Schema(description = "平台场景信息")
+    private SceneInfoModel sceneInfo;
+
+    @Schema(description = "包含的组件列表")
+    private List<SceneComponentModel> components = new ArrayList<>();
+
+    @Schema(description = "关联的数据ID")
+    private String sceneInfoId;
+
+    @Schema(description = "场景名称")
+    private String name;
+
+    @Schema(description = "类型")
+    private SceneType sceneType;
+
+    private String sceneTypeStr;
+
+    public String getSceneTypeStr() {
+        if (sceneType != null) {
+            return sceneType.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "外面的状态")
+    private DataState sceneState;
+
+    private String sceneStateStr;
+
+    public String getSceneStateStr() {
+        if (sceneState != null) {
+            return sceneState.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "状态")
+    private DataState state;
+
+    private String stateStr;
+
+    public String getStateStr() {
+        if (state != null) {
+            return state.getRemark();
+        }
+        return "";
+    }
+
+}

+ 28 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleBindsSceneParam.java

@@ -0,0 +1,28 @@
+package com.zhongshu.card.client.model.scene;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/11/22
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RoleBindsSceneParam {
+
+    @Schema(description = "组件数据id")
+    private List<String> ids = new ArrayList<>();
+
+    @Schema(description = "角色ID")
+    private String roleId;
+
+    @Schema(description = "项目oid")
+    private String projectOid;
+}

+ 42 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneComTreeModel.java

@@ -0,0 +1,42 @@
+package com.zhongshu.card.client.model.scene;
+
+import com.zhongshu.card.client.type.DataState;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author TRX
+ * @date 2024/11/22
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RoleSceneComTreeModel extends SceneInfoModel {
+
+    @Schema(description = "项目应用的数据ID")
+    private String projectSceneInfoId;
+
+    @Schema(description = "项目应用排序")
+    private Long pSort = 1L;
+
+    @Schema(description = "状态")
+    private DataState pState;
+
+    private String pStateStr;
+
+    public String getPStateStr() {
+        if (pState != null) {
+            return pState.getRemark();
+        }
+        return "";
+    }
+
+    @Schema(description = "包含的组件列表")
+    private List<RoleSceneComponentModel> children = new ArrayList<>();
+
+}

+ 22 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneComponentModel.java

@@ -0,0 +1,22 @@
+package com.zhongshu.card.client.model.scene;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author TRX
+ * @date 2024/12/4
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RoleSceneComponentModel extends SceneComponentModel{
+
+    @Schema(description = "角色绑定的数据id集合")
+    private String roleSceneId;
+
+    @Schema(description = "项目应用的数据ID")
+    private String projectSceneInfoId;
+}

+ 15 - 2
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/RoleSceneInfoModel.java

@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
 
 /**
  * @author TRX
@@ -15,13 +16,25 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 public class RoleSceneInfoModel extends SuperModel {
 
-    @Schema(description = "场景信息")
+    @Schema(description = "应用信息")
     private SceneInfoModel sceneInfo;
 
-    @Schema(description = "项目管理的场景ID")
+    private String sceneInfoName;
+
+    public String getSceneInfoName() {
+        if (ObjectUtils.isNotEmpty(sceneInfo)) {
+            return sceneInfo.getName();
+        }
+        return "";
+    }
+
+    @Schema(description = "项目管理的应用ID")
     private String projectSceneInfoId;
 
     @Schema(description = "角色ID")
     private String roleId;
 
+    @Schema(description = "组件信息")
+    private SceneComponentModel sceneComponent;
+
 }

+ 1 - 1
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/SceneInfoModel.java

@@ -17,7 +17,7 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 public class SceneInfoModel extends SuperModel {
 
-    @Schema(description = "场景名称")
+    @Schema(description = "应用名称")
     private String name;
 
     @Schema(description = "编码")

+ 0 - 1
FullCardClient/src/main/java/com/zhongshu/card/client/model/scene/SceneInfoParam.java

@@ -36,7 +36,6 @@ public class SceneInfoParam extends SuperParam {
     @Schema(description = "类型")
     private SceneType sceneType;
 
-    @NotEmpty
     @Schema(description = "布局尺寸")
     private String layout;
 

+ 27 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/payment/OrderController.java

@@ -4,7 +4,9 @@ package com.zhongshu.card.server.core.controller.payment;
 import com.github.microservice.auth.security.annotations.ResourceAuth;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.net.ResultContent;
+import com.zhongshu.card.client.model.base.IDParam;
 import com.zhongshu.card.client.model.devices.order.DeviceQrCodeParam;
+import com.zhongshu.card.server.core.service.payment.ExpenseFlowServiceImpl;
 import com.zhongshu.card.server.core.service.payment.OrderService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -24,6 +26,10 @@ public class OrderController {
     @Autowired
     private OrderService orderService;
 
+    @Autowired
+    private ExpenseFlowServiceImpl expenseFlowService;
+
+
     /**
      * 扫设备码下单
      */
@@ -34,4 +40,25 @@ public class OrderController {
         return orderService.cToBqrCodeBCreateOrder(param);
     }
 
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "支付订单详情")
+    @RequestMapping(value = {"getOrderPayDetail"}, method = {RequestMethod.POST})
+    public ResultContent getOrderPayDetail(@RequestBody IDParam param) {
+        return expenseFlowService.getOrderPayDetail(param.getId());
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "开始支付订单")
+    @RequestMapping(value = {"payOrder"}, method = {RequestMethod.POST})
+    public ResultContent payOrder(@RequestBody IDParam param) {
+        return expenseFlowService.initOrderPay(param.getId());
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "取消订单")
+    @RequestMapping(value = {"cancelOrder"}, method = {RequestMethod.POST})
+    public ResultContent cancelOrder(@RequestBody IDParam param) {
+        return expenseFlowService.cancelOrder(param.getId());
+    }
+
 }

+ 9 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/ProjectSceneInfoController.java

@@ -6,6 +6,7 @@ import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.net.ResultContent;
 import com.zhongshu.card.client.model.base.IDParam;
 import com.zhongshu.card.client.model.scene.ProjectBindSceneParam;
+import com.zhongshu.card.client.model.scene.ProjectSceneInfoDetailModel;
 import com.zhongshu.card.client.model.scene.ProjectSceneInfoModel;
 import com.zhongshu.card.client.model.scene.ProjectSceneInfoSearch;
 import com.zhongshu.card.client.type.DataState;
@@ -54,6 +55,14 @@ public class ProjectSceneInfoController {
         return projectSceneInfoService.page(param, pageable);
     }
 
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "项目场景列表(包括组件信息)-分页查询", description = "项目场景列表(包括组件信息)-分页查询")
+    @RequestMapping(value = {"pageAboutComponent"}, method = {RequestMethod.POST})
+    public ResultContent<Page<ProjectSceneInfoDetailModel>> pageAboutComponent(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, @Parameter(required = false) ProjectSceneInfoSearch param) {
+        Assert.hasText(param.getProjectOid(), "projectOid不能为空");
+        return projectSceneInfoService.pageAboutComponent(param, pageable);
+    }
+
     @ResourceAuth(value = "user", type = AuthType.User)
     @Operation(summary = "绑定场景", description = "绑定场景")
     @RequestMapping(value = "bindScene", method = {RequestMethod.POST})

+ 32 - 28
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/RoleSceneInfoController.java

@@ -6,6 +6,7 @@ import com.github.microservice.net.ResultContent;
 import com.zhongshu.card.client.model.base.IDParam;
 import com.zhongshu.card.client.model.base.SortParam;
 import com.zhongshu.card.client.model.scene.*;
+import com.zhongshu.card.client.type.DataState;
 import com.zhongshu.card.server.core.service.scene.RoleSceneInfoService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -24,61 +25,64 @@ import java.util.List;
  */
 @RestController
 @RequestMapping("/roleSceneInfo")
-@Tag(name = "场景--角色场景管理")
+@Tag(name = "组件--角色组件管理")
 public class RoleSceneInfoController {
 
     @Autowired
     private RoleSceneInfoService roleSceneInfoService;
 
+
+    //----------------------------------配置 start---------------------------
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "角色绑定组件(多个)", description = "角色绑定组件(多个)")
+    @RequestMapping(value = "bindScenes", method = {RequestMethod.POST})
+    public ResultContent bindScenes(@RequestBody @Valid RoleBindsSceneParam param) {
+        return this.roleSceneInfoService.bindScenes(param);
+    }
+
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "角色场景列表", description = "角色场景列表")
+    @Operation(summary = "角色删除组件", description = "角色删除组件")
+    @RequestMapping(value = "deleteById", method = {RequestMethod.POST})
+    public ResultContent deleteById(@RequestBody IDParam param) {
+        return this.roleSceneInfoService.deleteById(param.getId());
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "角色组件列表(列表形式)", description = "角色组件列表(列表形式)")
     @RequestMapping(value = {"list"}, method = {RequestMethod.POST})
     public ResultContent<List<RoleSceneInfoModel>> list(@RequestBody IDParam param) {
         return roleSceneInfoService.list(param.getId());
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "得到角色所有已启用的场景列表", description = "得到角色所有已启用的场景列表")
+    @Operation(summary = "角色组件所有(树形式)", description = "角色组件所有(树形式)")
+    @RequestMapping(value = {"tree"}, method = {RequestMethod.POST})
+    public ResultContent<List<RoleSceneComTreeModel>> tree(@RequestBody IDParam param) {
+        return roleSceneInfoService.tree(List.of(param.getId()), null);
+    }
+    //----------------------------------配置 end------------------------------
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "得到角色所有已启用的组件列表", description = "得到角色所有已启用的组件列表")
     @RequestMapping(value = {"getRoleAllEnableScenes"}, method = {RequestMethod.POST})
-    public ResultContent<List<SceneInfoAboutComModel>> getRoleAllEnableScenes(@RequestBody IDParam param) {
-        return ResultContent.buildSuccess(roleSceneInfoService.getAllEnableScenes(param.getId()));
+    public ResultContent<List<RoleSceneComponentModel>> getRoleAllEnableScenes(@RequestBody IDParam param) {
+        return roleSceneInfoService.listByRoleIds(List.of(param.getId()), DataState.Enable);
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "得到用户所有场景", description = "得到用户所有场景")
+    @Operation(summary = "得到用户所有组件", description = "得到用户所有组件")
     @RequestMapping(value = {"getUserAllEnableScenes"}, method = {RequestMethod.GET})
     public ResultContent<List<SceneInfoAboutComModel>> getUserAllEnableScenes() {
         return ResultContent.buildSuccess(roleSceneInfoService.getUserAllEnableScenes());
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "角色绑定场景", description = "角色绑定场景")
-    @RequestMapping(value = "bindScene", method = {RequestMethod.POST})
-    public ResultContent bindScene(@RequestBody @Valid RoleBindSceneParam param) {
-        return this.roleSceneInfoService.bindScene(param);
-    }
-
-    @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "一次绑定多个(以前的删除)", description = "一次绑定多个(以前的删除)")
-    @RequestMapping(value = "bindList", method = {RequestMethod.POST})
-    public ResultContent bindList(@RequestBody @Valid RoleBindAllParam param) {
-        return this.roleSceneInfoService.bindList(param);
-    }
-
-    @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "根据场景数据ID 场景详情", description = "根据场景数据ID 场景详情")
+    @Operation(summary = "根据组件数据ID 组件详情", description = "根据组件数据ID 组件详情")
     @RequestMapping(value = "getDetailById", method = {RequestMethod.POST})
     public ResultContent<RoleSceneInfoModel> getDetailById(@RequestBody IDParam param) {
         return this.roleSceneInfoService.getDetailById(param.getId());
     }
 
-    @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "角色删除场景", description = "角色删除场景")
-    @RequestMapping(value = "deleteById", method = {RequestMethod.POST})
-    public ResultContent deleteById(@RequestBody IDParam param) {
-        return this.roleSceneInfoService.deleteById(param.getId());
-    }
-
     @ResourceAuth(value = "user", type = AuthType.User)
     @Operation(summary = "排序", description = "排序")
     @RequestMapping(value = "sort", method = {RequestMethod.POST})

+ 9 - 5
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/scene/SceneInfoController.java

@@ -4,10 +4,7 @@ import com.github.microservice.auth.security.annotations.ResourceAuth;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.net.ResultContent;
 import com.zhongshu.card.client.model.base.IDParam;
-import com.zhongshu.card.client.model.scene.SceneInfoAboutComModel;
-import com.zhongshu.card.client.model.scene.SceneInfoModel;
-import com.zhongshu.card.client.model.scene.SceneInfoParam;
-import com.zhongshu.card.client.model.scene.SceneInfoSearch;
+import com.zhongshu.card.client.model.scene.*;
 import com.zhongshu.card.client.type.DataState;
 import com.zhongshu.card.server.core.service.scene.SceneInfoService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -23,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
+import java.util.List;
 
 /**
  * @author TRX
@@ -39,7 +37,7 @@ public class SceneInfoController {
     @ResourceAuth(value = "user", type = AuthType.User)
     @Operation(summary = "场景列表-分页查询", description = "场景列表-分页查询")
     @RequestMapping(value = {"page"}, method = {RequestMethod.POST})
-    public ResultContent<Page<SceneInfoModel>> page(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, @Parameter(required = false) SceneInfoSearch param) {
+    public ResultContent<Page<SceneInfoAboutComModel>> page(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, @Parameter(required = false) SceneInfoSearch param) {
         return sceneInfoService.page(param, pageable);
     }
 
@@ -80,5 +78,11 @@ public class SceneInfoController {
 
     //--------------------场景的组件 start---------------------
 
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "查询查询下的 组件列表", description = "查询查询下的 组件列表")
+    @RequestMapping(value = {"getSceneAllComponents"}, method = {RequestMethod.POST})
+    public ResultContent<List<SceneComponentModel>> getSceneAllComponents(@RequestBody IDParam param) {
+        return ResultContent.buildSuccess(sceneInfoService.getSceneAllComponents(param.getId()));
+    }
 
 }

+ 6 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/scene/RoleSceneInfoDao.java

@@ -2,7 +2,7 @@ package com.zhongshu.card.server.core.dao.scene;
 
 import com.github.microservice.components.data.mongo.mongo.dao.MongoDao;
 import com.zhongshu.card.server.core.domain.scene.RoleSceneInfo;
-import com.zhongshu.card.server.core.domain.scene.SceneInfo;
+import com.zhongshu.card.server.core.domain.scene.SceneComponent;
 
 import java.util.List;
 
@@ -10,6 +10,8 @@ public interface RoleSceneInfoDao extends MongoDao<RoleSceneInfo> {
 
     RoleSceneInfo findTopById(String id);
 
+    RoleSceneInfo findTopByRoleIdAndComponentId(String roleId, SceneComponent component);
+
     RoleSceneInfo findTopByProjectSceneInfoIdAndRoleId(String projectSceneInfoId, String roleId);
 
     long countByRoleId(String roleId);
@@ -24,4 +26,7 @@ public interface RoleSceneInfoDao extends MongoDao<RoleSceneInfo> {
 
     long deleteByRoleId(String roleId);
 
+    long deleteByComponentId(String componentId);
+
+    long deleteByComponentIdIn(List<String> componentIds);
 }

+ 2 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/scene/SceneComponentDao.java

@@ -9,6 +9,8 @@ public interface SceneComponentDao extends MongoDao<SceneComponent> {
 
     SceneComponent findTopById(String id);
 
+
+
     List<SceneComponent> findBySceneInfoIdOrderBySortAsc(String sceneInfoId);
 
     long deleteByIdIn(List<String> ids);

+ 1 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/OrderConfig.java

@@ -6,7 +6,7 @@ package com.zhongshu.card.server.core.dataConfig;
  */
 public class OrderConfig {
 
-    // 订单最大有效时间
+    // 订单最大有效时间 (默认设置)
     public static final Long orderExpirationTime = 5 * 60 * 1000L;
 
 }

+ 3 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DeviceInfo.java

@@ -72,6 +72,9 @@ public class DeviceInfo extends SuperMain {
     @Schema(description = "最上线时间")
     private Long lastOnlineTime;
 
+    @Schema(description = "最后下线时间")
+    private Long lastOfflineTime;
+
     @Schema(description = "设备IP地址")
     private String ip;
 

+ 7 - 6
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/payment/ExpenseFlow.java

@@ -54,7 +54,7 @@ public class ExpenseFlow extends SuperMain {
     private OrderState orderState;
 
     @Schema(description = "订单创建类型, 是消费还是查询余额")
-    private OrderModeType orderModeType = OrderModeType.Consume;
+    private OrderModeType orderModeType;
 
     @Schema(description = "消费类型,如:餐饮消费、水费、电费 等等")
     private String payType;
@@ -72,7 +72,7 @@ public class ExpenseFlow extends SuperMain {
     @Schema(description = "订单生效时间")
     private Long startTime;
 
-    @Schema(description = "订单失效时间")
+    @Schema(description = "订单支付失效时间, (不会为空,有默认值)")
     private Long expirationTime;
 
     @Schema(description = "消费金额(单位:分)")
@@ -97,6 +97,10 @@ public class ExpenseFlow extends SuperMain {
     private UserAccount userAccount;
 
     //-----------------------修复关联的设备信息 start--------------------
+
+    @Schema(description = "是否是设备订单")
+    private Boolean isDeviceOrder = Boolean.TRUE;
+
     @Schema(description = "消费机设备ID")
     private String deviceId;
 
@@ -134,9 +138,6 @@ public class ExpenseFlow extends SuperMain {
     @Indexed
     private Object param;
 
-    // 交易模式(0:刷卡扣费 1:现金充值2:余额查询 3:钱包转账 4:现金退款)
-    private Integer mode = 0;
-
     //-----------------------订单创建-支付信息 start----------------------
 
     @Schema(description = "订单是否创建成功")
@@ -170,7 +171,7 @@ public class ExpenseFlow extends SuperMain {
     @Schema(description = "支付订单状态")
     private String paymentStatus;
 
-    @Schema(description = "支付是否成功")
+    @Schema(description = "支付是否成功,为空就是未支付过")
     private Boolean isPaySuccess;
 
     @Schema(description = "调用支付的 支付结果,保存支付结果返回的以后要使用的参数")

+ 5 - 5
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/scene/ProjectSceneInfo.java

@@ -12,7 +12,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 /**
- * 项目引用场景
+ * 项目引用应用
  *
  * @author TRX
  * @date 2024/11/22
@@ -24,15 +24,15 @@ import org.springframework.data.mongodb.core.mapping.Document;
 @NoArgsConstructor
 public class ProjectSceneInfo extends SuperMain {
 
-    //-------------------场景信息 start -------------------
-    @Schema(description = "场景数据")
+    //-------------------应用信息 start -------------------
+    @Schema(description = "应用数据")
     @DBRef(lazy = true)
     private SceneInfo sceneInfo;
 
     @Schema(description = "关联的数据ID")
     private String sceneInfoId;
 
-    @Schema(description = "场景名称")
+    @Schema(description = "应用名称")
     private String name;
 
     @Schema(description = "类型")
@@ -40,7 +40,7 @@ public class ProjectSceneInfo extends SuperMain {
 
     @Schema(description = "外面的状态")
     private DataState sceneState;
-    //-------------------场景信息 end --------------------
+    //-------------------应用信息 end --------------------
 
     @Schema(description = "状态")
     private DataState state = DataState.Enable;

+ 12 - 7
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/scene/RoleSceneInfo.java

@@ -1,7 +1,5 @@
 package com.zhongshu.card.server.core.domain.scene;
 
-import com.zhongshu.card.client.type.DataState;
-import com.zhongshu.card.client.type.scene.SceneType;
 import com.zhongshu.card.server.core.domain.base.SuperMain;
 import com.zhongshu.card.server.core.domain.org.Role;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -13,7 +11,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 /**
- * 项目引用场景
+ * 项目引用应用
  *
  * @author TRX
  * @date 2024/11/22
@@ -25,21 +23,28 @@ import org.springframework.data.mongodb.core.mapping.Document;
 @NoArgsConstructor
 public class RoleSceneInfo extends SuperMain {
 
-    @Schema(description = "场景数据")
+    @Schema(description = "应用数据")
     @DBRef(lazy = true)
     private SceneInfo sceneInfo;
 
+    @Schema(description = "组件")
+    @DBRef(lazy = true)
+    private SceneComponent component;
+
+    @Schema(description = "组件ID")
+    private String componentId;
+
     @Schema(description = "关联的数据ID")
     private String sceneInfoId;
 
-    @Schema(description = "项目管理的数据")
+    @Schema(description = "项目关联的应用数据")
     @DBRef(lazy = true)
     private ProjectSceneInfo projectSceneInfo;
 
-    @Schema(description = "项目管理的场景ID")
+    @Schema(description = "项目管理的应用ID")
     private String projectSceneInfoId;
 
-    @Schema(description = "场景数据")
+    @Schema(description = "应用数据")
     @DBRef(lazy = true)
     private Role role;
 

+ 6 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/CommonService.java

@@ -51,6 +51,9 @@ public class CommonService {
     }
 
     public Object updateData(String id, Map<String, Object> standardData, String collectionName) {
+        if (standardData == null || standardData.isEmpty()) {
+            return null;
+        }
         collectionName = CommonUtil.getCollectionName(collectionName);
         Query query = new Query(Criteria.where("_id").is(id));
         Update update = new Update();
@@ -64,6 +67,9 @@ public class CommonService {
     }
 
     public Object updateData(Map<String, Object> where, Map<String, Object> standardData, String collectionName) {
+        if (standardData == null || standardData.isEmpty()) {
+            return null;
+        }
         collectionName = CommonUtil.getCollectionName(collectionName);
         Criteria criteria = new Criteria();
         if (where != null) {

+ 70 - 10
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceInfoServiceImpl.java

@@ -16,6 +16,7 @@ import com.zhongshu.card.server.core.dao.org.OrganizationDao;
 import com.zhongshu.card.server.core.dao.school.AreaDao;
 import com.zhongshu.card.server.core.dataConfig.DeviceConfig;
 import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
+import com.zhongshu.card.server.core.domain.devices.DeviceProductBindDevice;
 import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
 import com.zhongshu.card.server.core.domain.org.Organization;
 import com.zhongshu.card.server.core.domain.school.Area;
@@ -82,7 +83,7 @@ public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoSer
     private DeviceProductBindDeviceService deviceProductBindDeviceService;
 
     /**
-     * 同步设备 (设备基础信息)
+     * 同步设备 (设备基础信息) 从物联网来
      *
      * @param param
      * @return
@@ -90,6 +91,17 @@ public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoSer
     @Override
     public ResultContent syncDeviceInfo(DeviceInfoSyncParam param) {
         Assert.hasText(param.getDeviceId(), "deviceId不能为空");
+        if (StringUtils.isEmpty(param.getProjectInfoCode())) {
+            return ResultContent.buildFail("projectInfoCode不能为空");
+        }
+        Organization projectInfo = null;
+        if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
+            projectInfo = organizationDao.findTopByCode(param.getProjectInfoCode());
+            if (ObjectUtils.isEmpty(projectInfo)) {
+                return ResultContent.buildFail("所属项目未找到,同步失败");
+            }
+        }
+
         // 设备号
         String deviceId = param.getDeviceId();
         DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
@@ -102,16 +114,14 @@ public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoSer
             initEntityNoCheckOid(deviceInfo);
             BeanUtils.copyProperties(param, deviceInfo, "id");
         }
-        deviceInfo.setProjectInfoName(organizationServiceImpl.getOrgNameByCode(param.getProjectInfoCode()));
-
-        if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
-            Organization projectInfo = organizationDao.findTopByOrgCode(param.getProjectInfoCode());
-            if (ObjectUtils.isNotEmpty(projectInfo)) {
-                deviceInfo.setProjectOid(projectInfo.getOid());
-                deviceInfo.setAboutOid(projectInfo.getOid());
-                deviceInfo.setAboutAuthType(projectInfo.getAuthType());
-            }
+        // 所属项目信息
+        if (ObjectUtils.isNotEmpty(projectInfo)) {
+            deviceInfo.setProjectOid(projectInfo.getOid());
+            deviceInfo.setAboutOid(projectInfo.getOid());
+            deviceInfo.setAboutAuthType(projectInfo.getAuthType());
+            deviceInfo.setProjectInfoName(projectInfo.getName());
         }
+
         deviceInfoDao.save(deviceInfo);
 
         // 修改其他的关联设备信息
@@ -399,6 +409,17 @@ public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoSer
         return Lists.newArrayList();
     }
 
+    public DeviceInfoModel getDeviceInfoModel(String deviceId) {
+        if (StringUtils.isEmpty(deviceId)) {
+            return null;
+        }
+        DeviceInfo deviceInfo = deviceInfoDao.findTopById(deviceId);
+        if (ObjectUtils.isNotEmpty(deviceInfo)) {
+            return toModel(deviceInfo);
+        }
+        return null;
+    }
+
     /**
      * 设备基础信息
      *
@@ -448,6 +469,45 @@ public class DeviceInfoServiceImpl extends SuperService implements DeviceInfoSer
         return model;
     }
 
+    /**
+     * 查询设备的 收款 机构
+     *
+     * @param deviceId
+     * @return
+     */
+    public Organization getDeviceReceiveOrganization(String deviceId) {
+        if (StringUtils.isNotEmpty(deviceId)) {
+            DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
+            return getDeviceReceiveOrganization(deviceInfo);
+        }
+        return null;
+    }
+
+    /**
+     * 查询设备的 收款 机构
+     *
+     * @param deviceInfo
+     * @return
+     */
+    public Organization getDeviceReceiveOrganization(DeviceInfo deviceInfo) {
+        Organization organization = null;
+        if (ObjectUtils.isNotEmpty(deviceInfo)) {
+            String oid = deviceInfo.getBeLongOid();
+            if (StringUtils.isEmpty(oid)) {
+                // 查找产品绑定的产品
+                DeviceProductBindDevice bindInfo = deviceProductBindDeviceService.getDeviceBindInfo(deviceInfo);
+                if (ObjectUtils.isNotEmpty(bindInfo) && bindInfo.getDeviceProduct() != null) {
+                    oid = bindInfo.getDeviceProduct().getBeLongOid();
+                }
+            }
+
+            if (StringUtils.isNotEmpty(oid)) {
+                organization = organizationDao.findTopByOid(oid);
+            }
+        }
+        return organization;
+    }
+
     /**
      * 设备信息  简单模型
      *

+ 4 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceSyncFromIotService.java

@@ -17,6 +17,7 @@ import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
 import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.user.OperationLogsService;
 import com.zhongshu.card.server.core.util.CommonUtil;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -88,9 +89,11 @@ public class DeviceSyncFromIotService {
 
         HashMap<String, Object> map = new HashMap<>();
         map.put("lastOnlineTime", param.getLastOnlineTime());
+        map.put("lastOfflineTime", param.getLastOfflineTime());
         map.put("onLineState", CommonUtil.getEnumByName(OnLineState.class, param.getOnLineState()));
         map.put("state", param.getState());
         map.put("lastOnlineTimeStr", DateUtils.paresTime(param.getLastOnlineTime(), DateUtils.FORMAT_LONG));
+
         commonService.updateData(where, map, DeviceInfo.class.getSimpleName());
         commonService.updateData(where, map, DeviceBind.class.getSimpleName());
 
@@ -109,6 +112,7 @@ public class DeviceSyncFromIotService {
         HashMap<String, Object> map = new HashMap<>();
         map.put("lastOnlineTime", param.getLastOnlineTime());
         map.put("lastOnlineTimeStr", DateUtils.paresTime(param.getLastOnlineTime(), DateUtils.FORMAT_LONG));
+        map.put("lastOfflineTime", param.getLastOfflineTime());
         commonService.updateData(where, map, DeviceInfo.class.getSimpleName());
         return ResultContent.buildSuccess();
     }

+ 12 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/deviceProduct/DeviceProductBindDeviceService.java

@@ -171,6 +171,18 @@ public class DeviceProductBindDeviceService extends SuperService {
         return Lists.newArrayList();
     }
 
+    /**
+     * 得到设备的绑定产品 关系信息
+     *
+     * @param deviceInfo
+     * @return
+     */
+    public DeviceProductBindDevice getDeviceBindInfo(DeviceInfo deviceInfo) {
+        if (deviceInfo != null) {
+            return deviceProductBindDeviceDao.findTopByDeviceIdOrderByCreateTimeDesc(deviceInfo.getDeviceId());
+        }
+        return null;
+    }
 
     private DeviceProductBindDeviceModel toModel(DeviceProductBindDevice entity) {
         DeviceProductBindDeviceModel model = new DeviceProductBindDeviceModel();

+ 296 - 131
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/ExpenseFlowServiceImpl.java

@@ -15,9 +15,11 @@ import com.github.microservice.net.ResultContent;
 import com.github.microservice.net.ResultMessage;
 import com.github.microservice.types.OrderModeType;
 import com.github.microservice.types.OrderState;
+import com.github.microservice.types.payment.ChargeableType;
 import com.github.microservice.types.payment.PaymentDeviceType;
 import com.github.microservice.types.payment.PaymentType;
 import com.zhongshu.card.client.model.base.SuperSearch;
+import com.zhongshu.card.client.model.org.OrganizationMiniModel;
 import com.zhongshu.card.client.model.org.UserJoinBusOrgModel;
 import com.zhongshu.card.client.model.payment.*;
 import com.zhongshu.card.client.model.payment.statistic.BusinessMainStatisticModel;
@@ -25,7 +27,6 @@ import com.zhongshu.card.client.model.payment.statistic.StatisticItem;
 import com.zhongshu.card.client.model.payment.statistic.StatisticSearch;
 import com.zhongshu.card.client.model.school.AreaSimpleModel;
 import com.zhongshu.card.client.service.payment.ExpenseFlowService;
-import com.zhongshu.card.client.type.DataState;
 import com.zhongshu.card.client.type.RefundState;
 import com.zhongshu.card.client.type.StatisticType;
 import com.zhongshu.card.client.type.UserState;
@@ -38,15 +39,19 @@ import com.zhongshu.card.server.core.dao.org.OrganizationDao;
 import com.zhongshu.card.server.core.dao.org.UserCountDao;
 import com.zhongshu.card.server.core.dao.payment.ExpenseFlowDao;
 import com.zhongshu.card.server.core.dao.school.CardInfoDao;
+import com.zhongshu.card.server.core.dataConfig.OrderConfig;
 import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
-import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
 import com.zhongshu.card.server.core.domain.org.Organization;
 import com.zhongshu.card.server.core.domain.org.UserAccount;
 import com.zhongshu.card.server.core.domain.payment.ExpenseFlow;
 import com.zhongshu.card.server.core.domain.school.CardInfo;
 import com.zhongshu.card.server.core.httpRequest.ApiRequestService;
+import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.base.SuperService;
+import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
+import com.zhongshu.card.server.core.service.devices.permiss.DevicePermissVerifyService;
 import com.zhongshu.card.server.core.service.org.OrganizationServiceImpl;
+import com.zhongshu.card.server.core.service.orgManager.OrganizationManagerServiceImpl;
 import com.zhongshu.card.server.core.service.paySetting.ProjectPaySettingServiceImpl;
 import com.zhongshu.card.server.core.service.school.AreaServiceImpl;
 import com.zhongshu.card.server.core.util.*;
@@ -60,10 +65,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -107,6 +109,17 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
     @Autowired
     private AreaServiceImpl areaService;
 
+    @Autowired
+    private DevicePermissVerifyService devicePermissVerifyService;
+
+    @Autowired
+    private DeviceInfoServiceImpl deviceInfoService;
+
+    @Autowired
+    private OrganizationManagerServiceImpl organizationManagerService;
+    @Autowired
+    private CommonService commonService;
+
     /**
      * 创建流水
      *
@@ -125,39 +138,58 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
      * @return
      */
     public ResultContent<ExpenseFlow> createExpenseFlowByHxz(ConsumTransactionsModel iotParam, ExpenseFlow expenseFlow) {
-        BeanUtils.copyProperties(iotParam, expenseFlow, "id");
+        CreateOrderParam param = new CreateOrderParam();
+        // 渠道订单支付模式
+        if (iotParam.getMode() == 0) {
+            param.setOrderModeType(OrderModeType.Consume);
+        } else if (iotParam.getMode() == 2) {
+            // 查询余额
+            param.setOrderModeType(OrderModeType.BalanceInquiry);
+        }
+        // 消费来源
+        param.setOrderFromType(iotParam.getOrderFromType());
+        // 消息id
+        param.setMqttDataId(iotParam.getMqttDataId());
+        // 消费订单号
+        param.setOrderNo(iotParam.getOrder());
+        // 卡号
+        param.setCardNo(iotParam.getCardNo());
+        // 消费金额
+        param.setAmount(iotParam.getAmount());
+        // 设备deviceId
+        param.setDeviceId(iotParam.getDeviceId());
 
-        expenseFlow.setUserId(iotParam.getUserId());
+        // 定额支付
+        param.setChargeableType(ChargeableType.Specified);
 
-        // 订单产生 类型、方式(订单来源)
-        expenseFlow.setOrderFromType(iotParam.getOrderFromType());
-        // 订单关联的商品信息
-        expenseFlow.setProductProvideId(iotParam.getProductProvideId());
-        // 订单计费方式
-        expenseFlow.setChargeableType(iotParam.getChargeableType());
+        // 是否可以匿名下单
+        param.setIsAnonymous(Boolean.FALSE);
 
-        expenseFlow.setMqttDataId(iotParam.getMqttDataId());
+        return createOrder(param, expenseFlow);
+    }
+
+    /**
+     * 创建订单
+     *
+     * @param param
+     * @param expenseFlow
+     * @return
+     */
+    public ResultContent<ExpenseFlow> createOrder(CreateOrderParam param, ExpenseFlow expenseFlow) {
+        BeanUtils.copyProperties(param, expenseFlow, "id");
 
         expenseFlow.setTimes();
-        // 消费订单号
-        expenseFlow.setOrderNo(iotParam.getOrder());
-        // 卡片信息
-        expenseFlow.setCardNo(iotParam.getCardNo());
         // 本地订单号
         String paymentNo = NextNoUtil.getNextPaymentNo(null);
         // 支付订单号
         expenseFlow.setPaymentNo(paymentNo);
+
         // 支付金额
-        BigDecimal amount = CommonUtil.turnMoney2BigDecimal(iotParam.getAmount());
+        BigDecimal amount = CommonUtil.turnMoney2BigDecimal(param.getAmount());
         expenseFlow.setPayAmount(amount);
 
-        expenseFlow.setDeviceId(iotParam.getDeviceId());
-
         // 传过来的参数
-        expenseFlow.setParam(iotParam);
-
-        // 来源设备产品类型
-        expenseFlow.setPaymentDeviceType(iotParam.getPaymentDeviceType());
+        expenseFlow.setParam(param);
 
         // 订单支付状态
         expenseFlow.setOrderState(OrderState.WAIT_PAYMENT);
@@ -165,48 +197,18 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         // 默认未结算状态
         expenseFlow.setSettlementState(SettlementState.Unsettled);
 
-        // 验证参数、填充数据
-        commonVerifyExpenseFlow(expenseFlow);
-        return ResultContent.buildSuccess(expenseFlow);
-    }
-
+        expenseFlow.setStartTime(System.currentTimeMillis());
 
-    /**
-     * 订单支付
-     *
-     * @param entity
-     * @return
-     */
-    public ResultContent<ExpenseFlow> orderPay(ExpenseFlow entity) {
-        // 判断参数是否符合要求
-        if (entity.getVerifyParamIsSuccess() == null || !entity.getVerifyParamIsSuccess()) {
-            // 参数验证失败
-            entity.setIsPaySuccess(Boolean.FALSE);
-            entity.setPayRemark(entity.getVerifyParamMsg());
-            entity.setPaymentStatus("支付失败");
-            expenseFlowDao.save(entity);
-            return ResultContent.buildSuccess(entity);
+        // 订单支付的有效期
+        Long expirationTime = param.getExpirationTime();
+        if (expirationTime == null || expirationTime <= 0) {
+            expirationTime = OrderConfig.orderExpirationTime;
         }
-        expenseFlowDao.save(entity);
+        expenseFlow.setExpirationTime(System.currentTimeMillis() + expirationTime);
 
-        if (entity.getMode() != null) {
-            if (entity.getMode() == 0) {
-                // 支付模式
-                entity.setOrderModeType(OrderModeType.Consume);
-                // 支付
-                payCallService.payOrder(entity);
-            } else if (entity.getMode() == 2) {
-                // 查询余额模式 因为只有钱包有余额,所以 默认默认为钱包支付渠道
-                entity.setOrderModeType(OrderModeType.BalanceInquiry);
-                entity.setPaymentStatus("查询余额");
-                entity.setPayRemark("查询余额");
-                entity.setOrderState(OrderState.PAID_ERROR);
-                entity.setIsPaySuccess(Boolean.TRUE);
-                entity.setPaymentType(PaymentType.UserWallet);
-                expenseFlowDao.save(entity);
-            }
-        }
-        return ResultContent.buildSuccess();
+        // 验证参数、填充数据
+        commonVerifyExpenseFlow(expenseFlow);
+        return ResultContent.buildSuccess(expenseFlow);
     }
 
     /**
@@ -255,47 +257,68 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         return ResultContent.buildSuccess(expenseFlow);
     }
 
+
     /**
      * 同意验证 支付订单的数据是否符合要求
      *
      * @param entity
      */
     private void commonVerifyExpenseFlow(ExpenseFlow entity) {
-        String deviceId = entity.getDeviceId();
-        // 验证设备
-        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
-        if (ObjectUtils.isEmpty(deviceInfo)) {
-            entity.setVerifyError("业务设备未注册");
-            return;
-        }
+        String projectOid = entity.getProjectOid();
+        String payType = entity.getPayType();
+        String userId = entity.getUserId();
+
+        // 设备消费模式
+        if (entity.getIsDeviceOrder() != null && entity.getIsDeviceOrder()) {
+            String deviceId = entity.getDeviceId();
+            // 验证设备
+            DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
+            if (ObjectUtils.isEmpty(deviceInfo)) {
+                entity.setVerifyError("业务设备未注册");
+                return;
+            }
+            // 设备已停用
+            if (deviceInfo.getState() != null && deviceInfo.getState() != DeviceState.Enable) {
+                entity.setVerifyError(String.format("设备%s", deviceInfo.getState().getRemark()));
+                return;
+            }
 
-        // 设备已停用
-        if (deviceInfo.getState() != null && deviceInfo.getState() != DeviceState.Enable) {
-            entity.setVerifyError(String.format("设备%s", deviceInfo.getState().getRemark()));
-            return;
+            // 检查设备是否绑定机构
+            if (StringUtils.isEmpty(deviceInfo.getBeLongOid())) {
+                entity.setVerifyError(String.format("设备未绑定机构"));
+                return;
+            }
+            Organization organization = deviceInfoService.getDeviceReceiveOrganization(deviceInfo);
+            // 设备所属的商户/机构
+            entity.setShopOid(organization.getOid());
+            entity.setOid(organization.getOid());
+            // 设备区域
+            entity.setArea(areaService.toSimpleModel(deviceInfo.getArea()));
+            // 填充项目信息
+            projectOid = deviceInfo.getProjectOid();
+
+            if (StringUtils.isEmpty(payType) && deviceInfo.getDeviceType() != null) {
+                payType = deviceInfo.getDeviceType().getRemark();
+            }
         }
+        entity.setPayType(payType);
 
-        // 检查设备是否绑定机构
-        if (StringUtils.isEmpty(deviceInfo.getBeLongOid())) {
-            entity.setVerifyError(String.format("设备未绑定机构"));
-            return;
-        }
-        // 设备所属的商户/机构
-        entity.setShopOid(deviceInfo.getBeLongOid());
-        // 设备区域
-        entity.setArea(areaService.toSimpleModel(deviceInfo.getArea()));
-        // 填充项目信息
-        String projectOid = deviceInfo.getProjectOid();
-        Organization projectInfo = organizationDao.findTopByOid(projectOid);
-        if (ObjectUtils.isNotEmpty(projectInfo)) {
-            entity.setProjectCode(projectInfo.getCode());
-            entity.setProjectOid(projectInfo.getOid());
+        // 确定项目信息
+        if (StringUtils.isNotEmpty(projectOid)) {
+            Organization projectInfo = organizationDao.findTopByOid(projectOid);
+            if (ObjectUtils.isNotEmpty(projectInfo)) {
+                entity.setProjectCode(projectInfo.getCode());
+                entity.setProjectOid(projectInfo.getOid());
+            }
         }
+
         // 验证项目信息
         if (StringUtils.isEmpty(entity.getProjectCode())) {
             entity.setVerifyError("未绑定项目信息");
             return;
         }
+
+        // 刷卡消费
         if (entity.getOrderFromType() == OrderFromType.Swipe) {
             CardInfo cardInfo = cardInfoDao.findByCode(entity.getCardNo());
             // 验证卡片
@@ -304,7 +327,7 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
                 return;
             }
             entity.setCardInfo(cardInfo);
-            entity.setUserId(cardInfo.getUserId());
+            userId = cardInfo.getUserId();
 
             // 判断卡片是否可用
             if (cardInfo.getCardState() != CardState.Enable) {
@@ -316,53 +339,47 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
                 entity.setVerifyError(String.format("卡片已作废"));
                 return;
             }
-
-            ConsumTransactionsModel iotParam = (ConsumTransactionsModel) entity.getParam();
-            if ((iotParam.getMode() != 0 || iotParam.getMode() != 2) && iotParam.getPayType() != 0) {
-                entity.setVerifyError("消费模式不支持");
-                return;
-            }
-            entity.setMode(iotParam.getMode());
         }
 
-        // 验证用户信息
-        if (StringUtils.isEmpty(entity.getUserId())) {
-            entity.setVerifyError("订单未找到用户");
+        if (entity.getOrderModeType() == null) {
+            entity.setVerifyError("消费模式不支持");
             return;
         }
 
-        UserAccount userAccount = userCountDao.findTopByUserId(entity.getUserId());
-        if (ObjectUtils.isEmpty(userAccount)) {
-            entity.setVerifyError("用户未注册");
-            return;
-        }
-        entity.setUserName(userAccount.getName());
-        entity.setUserAccount(userAccount);
+        // 验证用户信息
+        if ((entity.getIsAnonymous() == null || !entity.getIsAnonymous())) {
+            if (StringUtils.isEmpty(userId)) {
+                entity.setVerifyError("订单未找到用户");
+                return;
+            }
+            entity.setUserId(userId);
 
-        if (userAccount.getState() == UserState.Locked) {
-            entity.setVerifyError("用户已锁定");
-            return;
-        }
-        // 判断设备和用户是否绑定
-        DevicePermiss devicePermiss = devicePermissDao.findTopByUserIdAndDeviceIdAndProjectOid(entity.getUserId(), entity.getDeviceId(), entity.getProjectOid());
-        if (ObjectUtils.isEmpty(devicePermiss)) {
-            entity.setVerifyError("用户没有使用设备权限");
-            return;
-        }
-        if (devicePermiss.getDataState() == null || devicePermiss.getDataState() != DataState.Enable) {
-            entity.setVerifyError("用户设备权限未启用");
-            return;
-        }
-        // 消费设备信息
-        if (deviceInfo.getDeviceType() != null) {
-            entity.setPayType(deviceInfo.getDeviceType().getRemark());
-        } else {
-            entity.setPayType("消费");
+            UserAccount userAccount = userCountDao.findTopByUserId(entity.getUserId());
+            if (ObjectUtils.isEmpty(userAccount)) {
+                entity.setVerifyError("用户未注册");
+                return;
+            }
+            entity.setUserName(userAccount.getName());
+            entity.setUserAccount(userAccount);
+
+            if (userAccount.getState() == UserState.Locked) {
+                entity.setVerifyError("用户已锁定");
+                return;
+            }
+
+            if (entity.getIsDeviceOrder() != null && entity.getIsDeviceOrder()) {
+                // 判断用户是否有设备使用权限
+                ResultContent<String> verifyDeviceContent = devicePermissVerifyService.verifyDevice(entity.getUserId(), entity.getDeviceId(), null);
+                if (verifyDeviceContent.isFailed()) {
+                    entity.setVerifyError(verifyDeviceContent.getMsg());
+                    return;
+                }
+            }
         }
 
         // 金额判断
         BigDecimal payAmount = entity.getPayAmount();
-        if (entity.getMode() == 0 && CommonUtil.bigDecimalIsEmpty(payAmount)) {
+        if (entity.getOrderModeType() == OrderModeType.Consume && CommonUtil.bigDecimalIsEmpty(payAmount)) {
             entity.setVerifyError("消费金额不能小于等于0");
             return;
         }
@@ -370,6 +387,79 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         entity.setVerifyParamMsg("参数验证成功");
     }
 
+    /**
+     * 开始支付订单(主要是检查订单是否可以支付)
+     *
+     * @param id
+     * @return
+     */
+    public ResultContent initOrderPay(String id) {
+        ExpenseFlow expenseFlow = expenseFlowDao.findTopById(id);
+        if (ObjectUtils.isEmpty(expenseFlow)) {
+            return ResultContent.buildFail("订单不存在");
+        }
+        OrderPayModel orderPayModel = isCanPay(expenseFlow);
+        if (!orderPayModel.isSuccess()) {
+            return ResultContent.buildFail(orderPayModel.getPayMsg());
+        }
+
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 取消订单
+     *
+     * @param id
+     * @return
+     */
+    public ResultContent cancelOrder(String id) {
+        ExpenseFlow expenseFlow = expenseFlowDao.findTopById(id);
+        if (ObjectUtils.isEmpty(expenseFlow)) {
+            return ResultContent.buildFail("订单不存在");
+        }
+        OrderPayModel orderPayModel = isCanPay(expenseFlow);
+        if (!orderPayModel.isSuccess()) {
+            return ResultContent.buildFail(orderPayModel.getPayMsg());
+        }
+        expenseFlow.setOrderState(OrderState.CANCEL);
+        expenseFlowDao.save(expenseFlow);
+
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 订单支付
+     *
+     * @param entity
+     * @return
+     */
+    public ResultContent<ExpenseFlow> orderPay(ExpenseFlow entity) {
+        if (entity.getVerifyParamIsSuccess() == null || !entity.getVerifyParamIsSuccess()) {
+            // 参数验证失败
+            entity.setIsPaySuccess(Boolean.FALSE);
+            entity.setPayRemark(entity.getVerifyParamMsg());
+            entity.setPaymentStatus("支付失败");
+            expenseFlowDao.save(entity);
+            return ResultContent.buildSuccess(entity);
+        }
+
+        expenseFlowDao.save(entity);
+        if (entity.getOrderModeType() == OrderModeType.Consume) {
+            // 支付
+            payCallService.payOrder(entity);
+        } else if (entity.getOrderModeType() == OrderModeType.BalanceInquiry) {
+            // 查询余额模式 因为只有钱包有余额,所以 默认默认为钱包支付渠道
+            entity.setOrderModeType(OrderModeType.BalanceInquiry);
+            entity.setPaymentStatus("查询余额");
+            entity.setPayRemark("查询余额");
+            entity.setOrderState(OrderState.PAID_ERROR);
+            entity.setIsPaySuccess(Boolean.TRUE);
+            entity.setPaymentType(PaymentType.UserWallet);
+            expenseFlowDao.save(entity);
+        }
+        return ResultContent.buildSuccess();
+    }
+
     public ExpenseFlow saveInfo(ExpenseFlow entity) {
         if (ObjectUtils.isNotEmpty(entity)) {
             expenseFlowDao.save(entity);
@@ -781,6 +871,83 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 得到订单支付显示信息
+     *
+     * @param id
+     * @return
+     */
+    public ResultContent getOrderPayDetail(String id) {
+        ExpenseFlow entity = expenseFlowDao.findTopById(id);
+        ExpenseFlowPayShowModel model = toPayShowModel(entity);
+        return ResultContent.buildSuccess(model);
+    }
+
+    /**
+     * 支付订单的详情(简要)转换
+     *
+     * @param entity
+     * @return
+     */
+    public ExpenseFlowPayShowModel toPayShowModel(ExpenseFlow entity) {
+        ExpenseFlowPayShowModel model = new ExpenseFlowPayShowModel();
+        if (ObjectUtils.isNotEmpty(entity)) {
+            BeanUtils.copyProperties(entity, model);
+
+            // 设备信息
+            if (StringUtils.isNotEmpty(entity.getDeviceId())) {
+                model.setDeviceInfo(deviceInfoService.getDeviceInfoModel(entity.getDeviceId()));
+            }
+
+            // 收款机构信息
+            OrganizationMiniModel organizationMiniModel = organizationManagerService.toMiniModel(organizationService.getOrgByOid(entity.getShopOid()));
+            model.setShopInfo(organizationMiniModel);
+
+            // 判断是否可以支付
+            OrderPayModel payModel = isCanPay(entity);
+            BeanUtils.copyProperties(payModel, model);
+        }
+        return model;
+    }
+
+    /**
+     * 判断订单是否可以支付
+     *
+     * @param entity
+     * @return
+     */
+    public OrderPayModel isCanPay(ExpenseFlow entity) {
+        OrderPayModel model = new OrderPayModel();
+        if (ObjectUtils.isNotEmpty(entity)) {
+            if (entity.getVerifyParamIsSuccess() == null || !entity.getVerifyParamIsSuccess()) {
+                return model.setFiled(entity.getVerifyParamMsg());
+            }
+            OrderState orderState = entity.getOrderState();
+            if (orderState != OrderState.WAIT_PAYMENT) {
+                return model.setFiled(String.format("订单状态:%S", orderState.getRemark()));
+            }
+            if (entity.getExpirationTime() <= System.currentTimeMillis()) {
+                markOrderTimeOut(entity);
+                return model.setFiled("支付超时");
+            }
+        }
+        model.setSuccess();
+        return model;
+    }
+
+    /**
+     * 标记订单已超时
+     *
+     * @param entity
+     */
+    public void markOrderTimeOut(ExpenseFlow entity) {
+        if (entity != null) {
+            Map<String, Object> standardData = new HashMap<>();
+            standardData.put("orderState", OrderState.CLOSED);
+            standardData.put("payRemark", "超时关闭");
+            commonService.updateData(entity.getId(), standardData, ExpenseFlow.class.getSimpleName());
+        }
+    }
 
     /**
      * 模型转换
@@ -792,8 +959,6 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         ExpenseFlowModel model = new ExpenseFlowModel();
         if (ObjectUtils.isNotEmpty(entity)) {
             BeanUtils.copyProperties(entity, model);
-            // 卡片信息
-            // 用户信息
         }
         return model;
     }

+ 8 - 15
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/OrderService.java

@@ -1,11 +1,10 @@
 package com.zhongshu.card.server.core.service.payment;
 
-import com.github.microservice.models.gateDoor.use.GateDoorUseParam;
-import com.github.microservice.models.hxz.ConsumTransactionsModel;
 import com.github.microservice.models.type.OrderFromType;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.payment.ChargeableType;
 import com.zhongshu.card.client.model.devices.order.DeviceQrCodeParam;
+import com.zhongshu.card.client.model.payment.CreateOrderParam;
 import com.zhongshu.card.server.core.dao.devices.DeviceInfoDao;
 import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
 import com.zhongshu.card.server.core.domain.devices.DeviceProduct;
@@ -37,9 +36,6 @@ public class OrderService extends SuperService {
     @Autowired
     private DeviceInfoDao deviceInfoDao;
 
-    @Autowired
-    private DevicePermissVerifyService devicePermissVerifyService;
-
     @Autowired
     private ExpenseFlowServiceImpl expenseFlowService;
 
@@ -57,12 +53,6 @@ public class OrderService extends SuperService {
         if (ObjectUtils.isEmpty(deviceInfo)) {
             return ResultContent.buildFail("设备不存在");
         }
-        // 检查用户设备权限
-        GateDoorUseParam param1 = new GateDoorUseParam();
-        ResultContent<String> verifyDeviceContent = devicePermissVerifyService.verifyDevice(userAccount.getUserId(), param.getDeviceId(), param1);
-        if (verifyDeviceContent.isFailed()) {
-            return ResultContent.buildFail(verifyDeviceContent.getMsg());
-        }
 
         // 检查设备是否绑定产品
         ResultContent<DeviceProduct> deviceProductResultContent = deviceProductBindDeviceService.checkAndGetDeviceProduct(deviceInfo.getDeviceId());
@@ -83,10 +73,10 @@ public class OrderService extends SuperService {
             return ResultContent.buildFail("订单生成失败,请稍后再试");
         }
         String amount = param.getAmount().toPlainString();
-        ConsumTransactionsModel orderParam = new ConsumTransactionsModel();
+        CreateOrderParam orderParam = new CreateOrderParam();
         orderParam.setDeviceId(deviceInfo.getDeviceId());
         orderParam.setUserId(userAccount.getUserId());
-        orderParam.setOrder(CommonUtil.UUID());
+        orderParam.setOrderNo(CommonUtil.UUID());
         orderParam.setAmount(amount);
         orderParam.setProductProvideId(param.getProductProvideId());
         // 扫码下单
@@ -96,10 +86,13 @@ public class OrderService extends SuperService {
         // 是否是浮动计费 计费方式
         orderParam.setChargeableType(ChargeableType.Specified);
 
-        ResultContent<ExpenseFlow> content = expenseFlowService.createExpenseFlowByHxz(orderParam, expenseFlow);
+        ResultContent<ExpenseFlow> content = expenseFlowService.createOrder(orderParam, expenseFlow);
         expenseFlow = expenseFlowService.saveInfo(expenseFlow);
+        if (!expenseFlow.getVerifyParamIsSuccess()) {
+            return ResultContent.buildFail(expenseFlow.getVerifyParamMsg());
+        }
 
-        return ResultContent.buildSuccess();
+        return expenseFlowService.getOrderPayDetail(expenseFlow.getId());
     }
 
 }

+ 31 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/ProjectSceneInfoService.java

@@ -4,6 +4,7 @@ import com.github.microservice.components.data.base.util.PageEntityUtil;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.net.ResultMessage;
 import com.zhongshu.card.client.model.scene.ProjectBindSceneParam;
+import com.zhongshu.card.client.model.scene.ProjectSceneInfoDetailModel;
 import com.zhongshu.card.client.model.scene.ProjectSceneInfoModel;
 import com.zhongshu.card.client.model.scene.ProjectSceneInfoSearch;
 import com.zhongshu.card.client.type.DataState;
@@ -117,11 +118,30 @@ public class ProjectSceneInfoService extends SuperService {
         return projectSceneInfo;
     }
 
+    /**
+     * 项目的应用列表
+     *
+     * @param param
+     * @param pageable
+     * @return
+     */
     public ResultContent<Page<ProjectSceneInfoModel>> page(ProjectSceneInfoSearch param, Pageable pageable) {
         Page<ProjectSceneInfo> page = projectSceneInfoDao.page(pageable, param);
         return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
     }
 
+    /**
+     * 项目的应用列表
+     *
+     * @param param
+     * @param pageable
+     * @return
+     */
+    public ResultContent<Page<ProjectSceneInfoDetailModel>> pageAboutComponent(ProjectSceneInfoSearch param, Pageable pageable) {
+        Page<ProjectSceneInfo> page = projectSceneInfoDao.page(pageable, param);
+        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toDetailModel));
+    }
+
     public ResultContent<ProjectSceneInfoModel> getDetailById(String id) {
         ProjectSceneInfo entity = projectSceneInfoDao.findTopById(id);
         if (ObjectUtils.isEmpty(entity)) {
@@ -215,4 +235,15 @@ public class ProjectSceneInfoService extends SuperService {
         return model;
     }
 
+    public ProjectSceneInfoDetailModel toDetailModel(ProjectSceneInfo entity) {
+        ProjectSceneInfoDetailModel model = new ProjectSceneInfoDetailModel();
+        if (ObjectUtils.isNotEmpty(entity)) {
+            BeanUtils.copyProperties(entity, model);
+            model.setSceneInfo(sceneInfoService.toModel(entity.getSceneInfo()));
+            model.setComponents(sceneInfoService.getSceneAllComponents(entity.getSceneInfoId()));
+        }
+        return model;
+    }
+
+
 }

+ 182 - 120
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/RoleSceneInfoService.java

@@ -5,18 +5,17 @@ import com.github.microservice.net.ResultMessage;
 import com.google.common.collect.Lists;
 import com.zhongshu.card.client.model.base.SortParam;
 import com.zhongshu.card.client.model.org.role.RoleSimpleModel;
-import com.zhongshu.card.client.model.scene.RoleBindAllParam;
-import com.zhongshu.card.client.model.scene.RoleBindSceneParam;
-import com.zhongshu.card.client.model.scene.RoleSceneInfoModel;
-import com.zhongshu.card.client.model.scene.SceneInfoAboutComModel;
+import com.zhongshu.card.client.model.scene.*;
 import com.zhongshu.card.client.type.DataState;
 import com.zhongshu.card.server.core.dao.org.RoleDao;
 import com.zhongshu.card.server.core.dao.scene.ProjectSceneInfoDao;
 import com.zhongshu.card.server.core.dao.scene.RoleSceneInfoDao;
+import com.zhongshu.card.server.core.dao.scene.SceneComponentDao;
 import com.zhongshu.card.server.core.dao.scene.SceneInfoDao;
 import com.zhongshu.card.server.core.domain.org.Role;
 import com.zhongshu.card.server.core.domain.scene.ProjectSceneInfo;
 import com.zhongshu.card.server.core.domain.scene.RoleSceneInfo;
+import com.zhongshu.card.server.core.domain.scene.SceneComponent;
 import com.zhongshu.card.server.core.domain.scene.SceneInfo;
 import com.zhongshu.card.server.core.service.base.SuperService;
 import com.zhongshu.card.server.core.service.user.RoleServiceImpl;
@@ -26,11 +25,8 @@ import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -59,69 +55,83 @@ public class RoleSceneInfoService extends SuperService {
     @Autowired
     private RoleServiceImpl roleServiceImpl;
 
-    public ResultContent bindScene(RoleBindSceneParam param) {
-        ProjectSceneInfo entity = projectSceneInfoDao.findTopById(param.getId());
-        if (ObjectUtils.isEmpty(entity)) {
-            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, param.getId()));
-        }
-        Role role = roleDao.findTopById(param.getRoleId());
-        if (ObjectUtils.isEmpty(role)) {
-            return ResultContent.buildFail("角色不存在");
+    @Autowired
+    private SceneComponentDao sceneComponentDao;
+
+    /**
+     * 绑定组件
+     *
+     * @param param
+     * @return
+     */
+    public ResultContent bindScenes(RoleBindsSceneParam param) {
+        List<String> ids = param.getIds();
+        if (ObjectUtils.isEmpty(ids)) {
+            return ResultContent.buildFail("");
         }
-//        RoleSceneInfo roleSceneInfo = roleSceneInfoDao.findTopByProjectSceneInfoIdAndRoleId(entity.getId(), role.getId());
-//        if (ObjectUtils.isNotEmpty(roleSceneInfo)) {
-//            return ResultContent.buildFail(String.format("角色已存在场景:%s", entity.getName()));
-//        }
-        RoleSceneInfo roleSceneInfo = buildProjectSceneInfo(entity, role);
-        long index = roleSceneInfoDao.countByRoleId(role.getId());
-        roleSceneInfo.setSort(index + 1);
-        roleSceneInfoDao.save(roleSceneInfo);
-        return ResultContent.buildSuccess();
-    }
 
-    @Transactional
-    public ResultContent bindList(RoleBindAllParam param) {
         Role role = roleDao.findTopById(param.getRoleId());
         if (ObjectUtils.isEmpty(role)) {
             return ResultContent.buildFail("角色不存在");
         }
+        String projectOid = param.getProjectOid();
+        if (StringUtils.isEmpty(projectOid)) {
+            return ResultContent.buildFail("projectOid不能为空");
+        }
+
+        long i = 1;
         List<RoleSceneInfo> list = new ArrayList<>();
-        List<String> projectSceneInfoIds = param.getProjectSceneInfoIds();
-        if (ObjectUtils.isNotEmpty(projectSceneInfoIds)) {
-            long i = 1;
-            for (String projectSceneInfoId : projectSceneInfoIds) {
-                // 项目的场景
-                ProjectSceneInfo projectSceneInfo = projectSceneInfoDao.findTopById(projectSceneInfoId);
-                if (ObjectUtils.isNotEmpty(projectSceneInfo)) {
-                    RoleSceneInfo roleSceneInfo = buildProjectSceneInfo(projectSceneInfo, role);
-                    roleSceneInfo.setSort(i);
-                    i++;
-                    list.add(roleSceneInfo);
-                }
+        for (String id : ids) {
+            SceneComponent sceneComponent = sceneComponentDao.findTopById(id);
+            if (ObjectUtils.isEmpty(sceneComponent)) {
+                continue;
             }
+            SceneInfo sceneInfo = sceneComponent.getSceneInfo();
+            ProjectSceneInfo projectSceneInfo = projectSceneInfoDao.findTopBySceneInfoAndProjectOid(sceneInfo, projectOid);
+            if (ObjectUtils.isEmpty(projectSceneInfo)) {
+                continue;
+            }
+
+            RoleSceneInfo roleSceneInfo = roleSceneInfoDao.findTopByRoleIdAndComponentId(role.getId(), sceneComponent);
+            if (ObjectUtils.isEmpty(roleSceneInfo)) {
+                roleSceneInfo = new RoleSceneInfo();
+                initEntityNoCheckOid(roleSceneInfo);
+            }
+            // 角色信息
+            roleSceneInfo.setRole(role);
+            roleSceneInfo.setRoleId(role.getId());
+            roleSceneInfo.setProjectOid(projectOid);
+
+            // 组件信息
+            roleSceneInfo.setComponent(sceneComponent);
+            roleSceneInfo.setComponentId(sceneComponent.getId());
+
+            // 应用信息
+            roleSceneInfo.setSceneInfo(sceneInfo);
+            roleSceneInfo.setSceneInfoId(sceneInfo.getId());
+
+            // 项目管理的应用
+            roleSceneInfo.setProjectSceneInfo(projectSceneInfo);
+            roleSceneInfo.setProjectSceneInfoId(projectSceneInfo.getId());
+
+            roleSceneInfo.setSort(i);
+            list.add(roleSceneInfo);
+            i++;
         }
-        if (ObjectUtils.isNotEmpty(list)) {
-            roleSceneInfoDao.saveAll(list);
-        }
+        roleSceneInfoDao.saveAll(list);
         return ResultContent.buildSuccess();
     }
 
-    public RoleSceneInfo buildProjectSceneInfo(ProjectSceneInfo projectSceneInfo, Role role) {
-        RoleSceneInfo roleSceneInfo = roleSceneInfoDao.findTopByProjectSceneInfoIdAndRoleId(projectSceneInfo.getId(), role.getId());
-        if (ObjectUtils.isEmpty(roleSceneInfo)) {
-            roleSceneInfo = new RoleSceneInfo();
-            initEntityNoCheckOid(roleSceneInfo);
-            roleSceneInfo.setSceneInfo(projectSceneInfo.getSceneInfo());
-            roleSceneInfo.setSceneInfoId(projectSceneInfo.getId());
-            roleSceneInfo.setProjectSceneInfo(projectSceneInfo);
-            roleSceneInfo.setProjectSceneInfoId(projectSceneInfo.getId());
-        } else {
-            initUpdateEntity(roleSceneInfo);
+
+    public ResultContent deleteById(String id) {
+        RoleSceneInfo entity = roleSceneInfoDao.findTopById(id);
+        if (ObjectUtils.isEmpty(entity)) {
+            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
         }
-        roleSceneInfo.setProjectOid(projectSceneInfo.getProjectOid());
-        roleSceneInfo.setRole(role);
-        roleSceneInfo.setRoleId(role.getId());
-        return roleSceneInfo;
+        // 判断是否可以删除
+        roleSceneInfoDao.delete(entity);
+        // 删除关联的信息
+        return ResultContent.buildSuccess();
     }
 
     /**
@@ -139,64 +149,98 @@ public class RoleSceneInfoService extends SuperService {
         return ResultContent.buildSuccess(models);
     }
 
-    /**
-     * 查询角色可用的场景
-     *
-     * @param roleId
-     * @return
-     */
-    public List<SceneInfoAboutComModel> getAllEnableScenes(String roleId) {
-        List<SceneInfoAboutComModel> models = new ArrayList<>();
+    public ResultContent<List<RoleSceneComTreeModel>> tree(List<String> roleIds, DataState state) {
+        List<RoleSceneComTreeModel> models = new ArrayList<>();
+        List<RoleSceneInfo> list = roleSceneInfoDao.findByRoleIdInOrderBySortAsc(roleIds);
+        if (ObjectUtils.isNotEmpty(list)) {
+            if (state != null) {
+                list = list.stream().filter(it -> {
+                    return it.getProjectSceneInfo().getState() == state && it.getSceneInfo().getState() == state;
+                }).collect(Collectors.toList());
+            }
+            if (ObjectUtils.isEmpty(list)) {
+                return ResultContent.buildSuccess(models);
+            }
 
-        if (StringUtils.isNotEmpty(roleId)) {
-            // 角色关联的场景数据
-            List<RoleSceneInfo> list = roleSceneInfoDao.findByRoleIdOrderBySortAsc(roleId);
-            if (ObjectUtils.isNotEmpty(list)) {
-                list.stream().forEach(it -> {
-                    SceneInfo sceneInfo = it.getSceneInfo();
-                    ProjectSceneInfo projectSceneInfo = it.getProjectSceneInfo();
-                    if (ObjectUtils.isNotEmpty(projectSceneInfo) && ObjectUtils.isNotEmpty(sceneInfo)) {
-                        if (projectSceneInfo.getState() == DataState.Enable && sceneInfo.getState() == DataState.Enable) {
-                            models.add(sceneInfoService.toAboutComModel(sceneInfo));
-                        }
-                    }
+            // 以项目应用ID
+            Map<String, List<RoleSceneInfo>> map = list.stream().collect(
+                    Collectors.toMap(RoleSceneInfo::getProjectSceneInfoId, e -> {
+                        List<RoleSceneInfo> objects = new ArrayList<>();
+                        objects.add(e);
+                        return objects;
+                    }, (newList, oldList) -> {
+                        oldList.addAll(newList);
+                        return oldList;
+                    }));
+            for (String projectSceneInfoId : map.keySet()) {
+                ProjectSceneInfo projectSceneInfo = projectSceneInfoDao.findTopById(projectSceneInfoId);
+                if (ObjectUtils.isEmpty(projectSceneInfo)) {
+                    continue;
+                }
+                RoleSceneComTreeModel model = new RoleSceneComTreeModel();
+                SceneInfoModel sceneInfoModel = sceneInfoService.toModel(projectSceneInfo.getSceneInfo());
+                BeanUtils.copyProperties(sceneInfoModel, model);
+
+                model.setProjectSceneInfoId(projectSceneInfoId);
+                model.setPSort(projectSceneInfo.getSort());
+                model.setPState(projectSceneInfo.getState());
+
+                // 组件信息
+                List<RoleSceneInfo> roleSceneInfos = map.get(projectSceneInfoId);
+                List<RoleSceneComponentModel> children = roleSceneInfos.stream().map(it -> {
+                    RoleSceneComponentModel componentModel = new RoleSceneComponentModel();
+                    SceneComponentModel sceneComponentModel = sceneInfoService.toComponentModel(it.getComponent());
+                    BeanUtils.copyProperties(sceneComponentModel, componentModel);
+                    componentModel.setRoleSceneId(it.getId());
+                    componentModel.setProjectSceneInfoId(projectSceneInfoId);
+
+                    return componentModel;
+                }).collect(Collectors.toList());
+
+                model.setChildren(children);
+                models.add(model);
+            }
+
+            // 排序
+            Collections.sort(models, new Comparator<RoleSceneComTreeModel>() {
+                @Override
+                public int compare(RoleSceneComTreeModel o1, RoleSceneComTreeModel o2) {
+                    return (int) (o1.getPSort() - o2.getPSort());
+                }
+            });
+        }
+        return ResultContent.buildSuccess(models);
+    }
+
+    public ResultContent<List<RoleSceneComponentModel>> listByRoleIds(List<String> roleIds, DataState state) {
+        List<RoleSceneComponentModel> list = new ArrayList<>();
+        ResultContent<List<RoleSceneComTreeModel>> content = tree(roleIds, state);
+        if (content.isSuccess()) {
+            List<RoleSceneComTreeModel> models = content.getContent();
+            if (ObjectUtils.isNotEmpty(models)) {
+                models.stream().forEach(it -> {
+                    list.addAll(it.getChildren());
                 });
             }
         }
-        return models;
+        return ResultContent.buildSuccess(list);
     }
 
-    public List<SceneInfoAboutComModel> getUserAllEnableScenes() {
+    /**
+     * 得到当前用户可以的 场景 组件信息
+     *
+     * @return
+     */
+    public List<RoleSceneComponentModel> getUserAllEnableScenes() {
         // 得到当前用户所有的角色
         ResultContent<List<RoleSimpleModel>> content = roleServiceImpl.xcxGetCurrentRoles();
         if (content.isSuccess()) {
             List<RoleSimpleModel> roles = content.getContent();
             if (ObjectUtils.isNotEmpty(roles)) {
-                List<SceneInfoAboutComModel> models = new ArrayList<>();
-
-                List<String> roleIds = roles.stream().map(it -> it.getId()).collect(Collectors.toUnmodifiableList());
-                List<RoleSceneInfo> list = roleSceneInfoDao.findByRoleIdInOrderBySortAsc(roleIds);
-                if (ObjectUtils.isNotEmpty(list)) {
-                    list.stream().forEach(it -> {
-                        SceneInfo sceneInfo = it.getSceneInfo();
-                        ProjectSceneInfo projectSceneInfo = it.getProjectSceneInfo();
-                        if (ObjectUtils.isNotEmpty(projectSceneInfo) && ObjectUtils.isNotEmpty(sceneInfo)) {
-                            if (projectSceneInfo.getState() == DataState.Enable && sceneInfo.getState() == DataState.Enable) {
-                                models.add(sceneInfoService.toAboutComModel(sceneInfo));
-                            }
-                        }
-                    });
-                }
-                List<SceneInfoAboutComModel> reModels = new ArrayList<>();
-                HashMap<String, String> map = new HashMap<>();
-                for (SceneInfoAboutComModel model : models) {
-                    if(!map.containsKey(model.getId())) {
-                        map.put(model.getId(), model.getName());
-                        reModels.add(model);
-                    }
+                ResultContent<List<RoleSceneComponentModel>> treeContent = listByRoleIds(roles.stream().map(RoleSimpleModel::getId).collect(Collectors.toList()), DataState.Enable);
+                if (treeContent.isSuccess()) {
+                    return treeContent.getContent();
                 }
-                // 去重
-                return reModels;
             }
         }
         return Lists.newArrayList();
@@ -210,17 +254,6 @@ public class RoleSceneInfoService extends SuperService {
         return ResultContent.buildSuccess(toModel(entity));
     }
 
-    public ResultContent deleteById(String id) {
-        RoleSceneInfo entity = roleSceneInfoDao.findTopById(id);
-        if (ObjectUtils.isEmpty(entity)) {
-            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
-        }
-        // 判断是否可以删除
-        roleSceneInfoDao.delete(entity);
-        // 删除关联的信息
-        return ResultContent.buildSuccess();
-    }
-
     /**
      * 数据排序
      *
@@ -246,31 +279,57 @@ public class RoleSceneInfoService extends SuperService {
     }
 
     /**
-     * 根据项目的场景id删除角色的
+     * 根据项目的应用id删除角色的
      *
      * @param projectSceneInfoId
      * @return
      */
     public ResultContent deleteByProjectSceneId(String projectSceneInfoId) {
-        if (ObjectUtils.isNotEmpty(projectSceneInfoId)) {
+        if (StringUtils.isNotEmpty(projectSceneInfoId)) {
             roleSceneInfoDao.deleteByProjectSceneInfoId(projectSceneInfoId);
         }
         return ResultContent.buildSuccess();
     }
 
     /**
-     * 根据平台的场景id删除
+     * 根据平台的应用id删除
      *
      * @param sceneInfoId
      * @return
      */
     public ResultContent deleteBySceneInfoId(String sceneInfoId) {
-        if (ObjectUtils.isNotEmpty(sceneInfoId)) {
+        if (StringUtils.isNotEmpty(sceneInfoId)) {
             roleSceneInfoDao.deleteBySceneInfoId(sceneInfoId);
         }
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 根据组件ID删除
+     *
+     * @param componentId
+     * @return
+     */
+    public ResultContent deleteByComponentId(String componentId) {
+        if (StringUtils.isNotEmpty(componentId)) {
+            roleSceneInfoDao.deleteByComponentId(componentId);
+        }
+        return ResultContent.buildSuccess();
+    }
+
+    /**
+     * 根据组件id集合删除
+     *
+     * @param componentIds
+     * @return
+     */
+    public ResultContent deleteByComponentIds(List<String> componentIds) {
+        if (ObjectUtils.isNotEmpty(componentIds)) {
+            roleSceneInfoDao.deleteByComponentIdIn(componentIds);
+        }
+        return ResultContent.buildSuccess();
+    }
+
     /**
      * 根据角色id删除数据
      *
@@ -278,7 +337,7 @@ public class RoleSceneInfoService extends SuperService {
      * @return
      */
     public ResultContent deleteByRoleId(String roleId) {
-        if (ObjectUtils.isNotEmpty(roleId)) {
+        if (StringUtils.isNotEmpty(roleId)) {
             roleSceneInfoDao.deleteByRoleId(roleId);
         }
         return ResultContent.buildSuccess();
@@ -288,7 +347,10 @@ public class RoleSceneInfoService extends SuperService {
         RoleSceneInfoModel model = new RoleSceneInfoModel();
         if (ObjectUtils.isNotEmpty(entity)) {
             BeanUtils.copyProperties(entity, model);
+            // 关联的应用信息
             model.setSceneInfo(sceneInfoService.toModel(entity.getSceneInfo()));
+            // 关联的组件信息
+            model.setSceneComponent(sceneInfoService.toComponentModel(entity.getComponent()));
         }
         return model;
     }

+ 50 - 4
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/scene/SceneInfoService.java

@@ -46,8 +46,8 @@ public class SceneInfoService extends SuperService {
 
     public ResultContent saveInfo(SceneInfoParam param) {
         boolean isAdd = true;
-        SceneInfo entity = null;
 
+        SceneInfo entity = null;
         SceneInfo temp = sceneInfoDao.findTopByName(param.getName());
 //        SceneInfo codeTemp = sceneInfoDao.findTopByCode(param.getCode());
         if (StringUtils.isNotEmpty(param.getId())) {
@@ -86,11 +86,17 @@ public class SceneInfoService extends SuperService {
         return ResultContent.buildSuccess();
     }
 
-    public ResultContent<Page<SceneInfoModel>> page(SceneInfoSearch param, Pageable pageable) {
+    public ResultContent<Page<SceneInfoAboutComModel>> page(SceneInfoSearch param, Pageable pageable) {
         Page<SceneInfo> page = sceneInfoDao.page(pageable, param);
-        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
+        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toAboutComModel));
     }
 
+    /**
+     * 得到应用详情(包括组件)
+     *
+     * @param id
+     * @return
+     */
     public ResultContent<SceneInfoAboutComModel> getDetailById(String id) {
         SceneInfo entity = sceneInfoDao.findTopById(id);
         if (ObjectUtils.isEmpty(entity)) {
@@ -149,7 +155,15 @@ public class SceneInfoService extends SuperService {
             if (ObjectUtils.isNotEmpty(components)) {
                 List<SceneComponent> componentEntitys = new ArrayList<>();
                 for (SceneComponentParam param : components) {
-                    SceneComponent component = new SceneComponent();
+                    SceneComponent component = null;
+                    if (StringUtils.isNotEmpty(param.getId())) {
+                        component = sceneComponentDao.findTopById(param.getId());
+                    }
+                    if (ObjectUtils.isEmpty(component)) {
+                        component = new SceneComponent();
+                    }
+                    component.setSceneInfo(sceneInfo);
+                    component.setSceneInfoId(sceneInfo.getId());
                     BeanUtils.copyProperties(param, component);
                     componentEntitys.add(component);
                     if (StringUtils.isNotEmpty(param.getId()) && ids.contains(param.getId())) {
@@ -166,6 +180,12 @@ public class SceneInfoService extends SuperService {
         return ResultContent.buildSuccess();
     }
 
+    /**
+     * 根据应用id 查询所有的组件
+     *
+     * @param sceneInfoId
+     * @return
+     */
     public List<SceneComponentModel> getSceneAllComponents(String sceneInfoId) {
         List<SceneComponentModel> models = new ArrayList<>();
         if (StringUtils.isNotEmpty(sceneInfoId)) {
@@ -177,8 +197,22 @@ public class SceneInfoService extends SuperService {
         return models;
     }
 
+    public List<SceneComponentModel> getSceneAllComponents(List<SceneComponent> components) {
+        List<SceneComponentModel> models = new ArrayList<>();
+        if (ObjectUtils.isNotEmpty(components)) {
+            models = components.stream().map(this::toComponentModel).collect(Collectors.toUnmodifiableList());
+        }
+        return models;
+    }
+
     //--------------------------场景组件信息 end-----------------------
 
+    /**
+     * 转换应用基本信息模型
+     *
+     * @param entity
+     * @return
+     */
     public SceneInfoModel toModel(SceneInfo entity) {
         SceneInfoModel model = new SceneInfoModel();
         if (ObjectUtils.isNotEmpty(entity)) {
@@ -187,6 +221,12 @@ public class SceneInfoService extends SuperService {
         return model;
     }
 
+    /**
+     * 转换应用模型 (包含组件)
+     *
+     * @param entity
+     * @return
+     */
     public SceneInfoAboutComModel toAboutComModel(SceneInfo entity) {
         SceneInfoAboutComModel model = new SceneInfoAboutComModel();
         if (ObjectUtils.isNotEmpty(entity)) {
@@ -197,6 +237,12 @@ public class SceneInfoService extends SuperService {
         return model;
     }
 
+    /**
+     * 转换组件模型
+     *
+     * @param entity
+     * @return
+     */
     public SceneComponentModel toComponentModel(SceneComponent entity) {
         SceneComponentModel model = new SceneComponentModel();
         if (ObjectUtils.isNotEmpty(entity)) {

+ 1 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/util/NextNoUtil.java

@@ -16,7 +16,7 @@ public class NextNoUtil {
     private final static SimpleDateFormat shortSdf = new SimpleDateFormat("yyyyMMdd");
     private final static SimpleDateFormat longSdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
 
-    public static String getNextPaymentNo(String sign) {
+    public static synchronized String getNextPaymentNo(String sign) {
         if (sign == null) {
             sign = "P";
         }