Selaa lähdekoodia

:sparkles:feat: 同步某一时间段内的 admin, equipment 表数据
:recycle:refactor: 取消 admin, equipment, order, coin_order 表的id自增

Ritchie 1 vuosi sitten
vanhempi
commit
69db70c790
24 muutettua tiedostoa jossa 546 lisäystä ja 41 poistoa
  1. 1 1
      src/main/java/com/szwl/aspect/MyWebMvcConfigurer.java
  2. 5 2
      src/main/java/com/szwl/controller/IndexController.java
  3. 60 0
      src/main/java/com/szwl/controller/SyncByClientController.java
  4. 279 0
      src/main/java/com/szwl/controller/SyncByTimeController.java
  5. 2 9
      src/main/java/com/szwl/controller/TAdminController.java
  6. 2 2
      src/main/java/com/szwl/controller/TEquipmentApplyController.java
  7. 2 2
      src/main/java/com/szwl/controller/TEquipmentController.java
  8. 4 2
      src/main/java/com/szwl/controller/TOrderController.java
  9. 2 0
      src/main/java/com/szwl/controller/TPromoCodeController.java
  10. 42 0
      src/main/java/com/szwl/feign/bean/SyncOldFeign.java
  11. 2 2
      src/main/java/com/szwl/mapper/TEquipmentApplyMapper.java
  12. 2 2
      src/main/java/com/szwl/mapper/TEquipmentMapper.java
  13. 4 1
      src/main/java/com/szwl/mapper/xml/TEquipmentApplyMapper.xml
  14. 9 1
      src/main/java/com/szwl/mapper/xml/TEquipmentMapper.xml
  15. 2 1
      src/main/java/com/szwl/model/entity/TAdmin.java
  16. 2 1
      src/main/java/com/szwl/model/entity/TCoinOrder.java
  17. 20 4
      src/main/java/com/szwl/model/entity/TEquipment.java
  18. 8 2
      src/main/java/com/szwl/model/entity/TEquipmentApply.java
  19. 2 1
      src/main/java/com/szwl/model/entity/TOrder.java
  20. 2 2
      src/main/java/com/szwl/service/TEquipmentApplyService.java
  21. 2 2
      src/main/java/com/szwl/service/TEquipmentService.java
  22. 2 2
      src/main/java/com/szwl/service/impl/TEquipmentApplyServiceImpl.java
  23. 2 2
      src/main/java/com/szwl/service/impl/TEquipmentServiceImpl.java
  24. 88 0
      src/main/java/com/szwl/util/IDGenerator.java

+ 1 - 1
src/main/java/com/szwl/aspect/MyWebMvcConfigurer.java

@@ -22,7 +22,7 @@ public class MyWebMvcConfigurer extends WebMvcConfigurationSupport {
         String[] myExcludes= {"/tAdmin/login","/tAdmin/save","/tAdmin/**","/tAdmin/updatePassword","/tMessageCode/**","/tJoinpayMch/**","/tLogo/**",
                 "/tProportion/**","/tProduct/**","/tPromoCode/**", "/tApkInfo/**", "/tProduct/selectProductList",  "/tApkInfo/**","/tJoinpayMchCheck/**","/tTimeRule/**","/sysRoleMenu/**",
                 "/tEquipmentApply/**","/tEquipment/**","/api/**","/tOrder/**","/tAlarmClock/**","/tNotice/**","/tParameters/**","/tAdmin/setRole",
-                "/tLabel/**","/tArea/**","/error","/tWechat/**","/wxLogin/**"};
+                "/tLabel/**","/tArea/**","/error","/tWechat/**","/wxLogin/**", "/syncByClient/**", "/syncByTime/**"};
         registry.addInterceptor(headTokenInterceptor).addPathPatterns("/**")
                 // swagger
                 .excludePathPatterns(swaggerExcludes)

+ 5 - 2
src/main/java/com/szwl/controller/IndexController.java

@@ -16,6 +16,7 @@ import com.szwl.model.utils.HttpClientSslUtils;
 import com.szwl.model.utils.PushUtils;
 import com.szwl.service.*;
 import com.szwl.service.es.EsTEquipmentService;
+import com.szwl.util.IDGenerator;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.io.IOUtils;
@@ -300,6 +301,7 @@ public class IndexController { ;
                             }else {
                                 equipment = list.get(0);
                             }
+                            equipment.setId(IDGenerator.commonID());
                             equipment.setClientId(clientId);
                             equipment.setGtClientId(gtClientId);
                             equipment.setAdminId(adminId);
@@ -360,6 +362,7 @@ public class IndexController { ;
                         }else{
 
                             TEquipment equipment = new TEquipment();
+                            equipment.setId(IDGenerator.commonID());
                             equipment.setCreateDate(new Date());
                             equipment.setModifyDate(new Date());
                             equipment.setClientId(clientId);
@@ -383,10 +386,10 @@ public class IndexController { ;
                                 equipment.setEquimentType(equimentType);
                             }
 //                            if(equimentType.equals("MG330")){
-//                                equipment.setEquimentType("MG330");
+//                                equipment.setEquipmentType("MG330");
 //                            }
 //                            if(equimentType.equals("POP320")){
-//                                equipment.setEquimentType(equimentType);
+//                                equipment.setEquipmentType(equipmentType);
 //                            }
                             if(!StringUtils.isEmpty(equimentType)&&equimentType.equals("MG280")){
                                 Long monthBegin = getMonthBegin(new Date());

+ 60 - 0
src/main/java/com/szwl/controller/SyncByClientController.java

@@ -0,0 +1,60 @@
+package com.szwl.controller;
+
+
+import com.szwl.feign.bean.SyncOldFeign;
+import com.szwl.model.bo.R;
+import com.szwl.model.bo.ResponseModel;
+import com.szwl.model.entity.TAdmin;
+import com.szwl.model.entity.TEquipment;
+import com.szwl.service.TAdminService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+@Slf4j
+@Api(value = "/syncByClient", tags = {"根据设备&用户同步旧系统数据"})
+@RestController
+@RequestMapping("/syncByClient")
+public class SyncByClientController {
+
+    TAdminService adminService;
+    SyncOldFeign syncOldFeign;
+
+    public SyncByClientController(TAdminService adminService, SyncOldFeign syncOldFeign) {
+        this.adminService = adminService;
+        this.syncOldFeign = syncOldFeign;
+    }
+
+
+    @ApiOperation(value = "根据设备同步旧系统数据")
+    @PostMapping("/syncOldByClient")
+    public ResponseModel<?> syncOldByClient(@RequestBody Map<String, String> params) {
+
+        // 查询 2023-03-19 开始到现在的所有表信息
+        String clientId = params.get("clientId");
+        String adminId = params.get("adminId");
+
+        // 查旧系统的admin信息
+//        ResponseModel<?> adminOld = syncOldFeign.getAdminById(adminId);
+//        adminOld.getData();
+
+        // 查旧系统的equipment信息
+        syncOldFeign.getEquipmentByClientId(clientId);
+
+        // 插入到新系统数据库
+        TAdmin adminNew = new TAdmin();
+        TEquipment equipmentNew = new TEquipment();
+
+        TAdmin adminOld = R.getDataIfSuccess(syncOldFeign.getAdminById(adminId));
+//        System.out.println(adminOld);
+
+        adminService.saveOrUpdate(adminOld);
+
+        return R.ok("同步成功");
+    }
+
+
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 279 - 0
src/main/java/com/szwl/controller/SyncByTimeController.java


+ 2 - 9
src/main/java/com/szwl/controller/TAdminController.java

@@ -3,9 +3,6 @@ package com.szwl.controller;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.UUID;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -24,24 +21,19 @@ import com.szwl.model.dto.RegisterParamDTO;
 import com.szwl.model.entity.*;
 import com.szwl.model.param.AddLoginUserParam;
 import com.szwl.model.param.UpdateLoginUserParam;
-import com.szwl.model.param.UpdateSysRoleParam;
 import com.szwl.model.utils.AdminUtils;
 import com.szwl.service.*;
+import com.szwl.util.IDGenerator;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.repository.query.Param;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-import java.math.BigDecimal;
 import java.util.*;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -505,6 +497,7 @@ public class TAdminController {
                 return R.fail(ResponseCodesEnum.A0002, "验证码错误");
             }
             tMessageCode.setStatus("1");
+            admin.setId(IDGenerator.commonID());
             admin.setCreateDate(new Date());
             admin.setModifyDate(new Date());
             admin.setIsAdmined(true);

+ 2 - 2
src/main/java/com/szwl/controller/TEquipmentApplyController.java

@@ -33,11 +33,11 @@ import java.util.stream.Collectors;
 
 /**
  * <p>
- * 设备连接申请表 前端控制器
+ *  前端控制器
  * </p>
  *
  * @author wuhs
- * @since 2022-04-21
+ * @since 2023-10-25
  */
 @RestController
 @Api(value = "/tEquipmentApply", tags = {"设备连接申请表"})

+ 2 - 2
src/main/java/com/szwl/controller/TEquipmentController.java

@@ -52,11 +52,11 @@ import static com.szwl.constant.ResponseCodesEnum.*;
 
 /**
  * <p>
- * 设备表 前端控制器
+ *  前端控制器
  * </p>
  *
  * @author wuhs
- * @since 2022-04-19
+ * @since 2023-10-25
  */
 @Api(value = "/tEquipment", tags = {"设备控制器"})
 @RestController

+ 4 - 2
src/main/java/com/szwl/controller/TOrderController.java

@@ -17,6 +17,7 @@ import com.szwl.model.bo.ResponseModel;
 import com.szwl.model.entity.*;
 import com.szwl.service.*;
 import com.szwl.service.es.EsTOrderService;
+import com.szwl.util.IDGenerator;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -71,7 +72,7 @@ public class TOrderController {
     private TProportionService proportionService;
 
     /**
-     *  退款
+     * 退款
      * @param
      * @return
      */
@@ -286,7 +287,7 @@ public class TOrderController {
         return R.ok("申请退款已成功");
     }
     /**
-     *  小程序退款
+     * 小程序退款
      * @param
      * @return
      */
@@ -556,6 +557,7 @@ public class TOrderController {
         BigDecimal marketingAmount = null;
 //                frpCode = "WEIXIN_NATIVE";
         TOrder order1 = new TOrder();
+        order1.setId(IDGenerator.orderID());
         order1.setSn(sn);
         order1.setType(0);
         order1.setAdminId(admin.getId());

+ 2 - 0
src/main/java/com/szwl/controller/TPromoCodeController.java

@@ -18,6 +18,7 @@ import com.szwl.model.dto.PromoCodeTarget;
 import com.szwl.model.entity.*;
 import com.szwl.model.utils.DateUtils;
 import com.szwl.service.*;
+import com.szwl.util.IDGenerator;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.lang.StringUtils;
@@ -401,6 +402,7 @@ public class TPromoCodeController {
                 BigDecimal marketingAmount = null;
 //                frpCode = "WEIXIN_NATIVE";
                 TOrder order1 = new TOrder();
+                order1.setId(IDGenerator.orderID());
                 order1.setSn(sn);
                 order1.setType(0);
                 order1.setAdminId(admin.getId());

+ 42 - 0
src/main/java/com/szwl/feign/bean/SyncOldFeign.java

@@ -0,0 +1,42 @@
+package com.szwl.feign.bean;
+
+import com.szwl.model.bo.ResponseModel;
+import com.szwl.model.entity.TAdmin;
+import com.szwl.model.entity.TEquipment;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.Date;
+import java.util.List;
+
+//@FeignClient(name = "syncOld-server")
+@FeignClient(name = "syncOld-server", url = "http://127.0.0.1:49015")
+public interface SyncOldFeign {
+
+    /**
+     * syncOldByClient
+     */
+
+    @GetMapping("/syncOldByClient/getAdminById")
+    ResponseModel<TAdmin> getAdminById(@RequestParam String adminId);
+
+    @GetMapping("/syncOldByClient/getEquipmentByClientId")
+    ResponseModel<TEquipment> getEquipmentByClientId(@RequestParam String clientId);
+
+
+
+    /**
+     * syncOldByTime
+     * @param startTime
+     * @param endTime
+     */
+    @PostMapping("/syncOldByTime/getEquipmentInTime")
+    ResponseModel<List<TEquipment>> getEquipmentInTime(@RequestParam String startTime, @RequestParam String endTime);
+
+    @PostMapping("/syncOldByTime/getAdminInTime")
+    ResponseModel<List<TAdmin>> getAdminInTime(@RequestParam String startTime, @RequestParam String endTime);
+
+
+}

+ 2 - 2
src/main/java/com/szwl/mapper/TEquipmentApplyMapper.java

@@ -5,11 +5,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
  * <p>
- * 设备连接申请表 Mapper 接口
+ *  Mapper 接口
  * </p>
  *
  * @author wuhs
- * @since 2022-04-21
+ * @since 2023-10-25
  */
 public interface TEquipmentApplyMapper extends BaseMapper<TEquipmentApply> {
 

+ 2 - 2
src/main/java/com/szwl/mapper/TEquipmentMapper.java

@@ -6,11 +6,11 @@ import com.szwl.model.query.StatisticsParam;
 
 /**
  * <p>
- * 设备表 Mapper 接口
+ *  Mapper 接口
  * </p>
  *
  * @author wuhs
- * @since 2022-04-19
+ * @since 2023-10-25
  */
 public interface TEquipmentMapper extends BaseMapper<TEquipment> {
 

+ 4 - 1
src/main/java/com/szwl/mapper/xml/TEquipmentApplyMapper.xml

@@ -13,6 +13,9 @@
         <result column="client_id" property="clientId" />
         <result column="manager_id" property="managerId" />
         <result column="status_type" property="statusType" />
+        <result column="agency_id" property="agencyId" />
+        <result column="merchant_id" property="merchantId" />
+        <result column="personage_id" property="personageId" />
         <result column="type" property="type" />
         <result column="gt_client_id" property="gtClientId" />
         <result column="equiment_type" property="equimentType" />
@@ -21,7 +24,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, create_date, modify_date, admin_id, admin_level, admin_user_name, client_id, manager_id, status_type, type, gt_client_id, equiment_type, machine_type
+        id, create_date, modify_date, admin_id, admin_level, admin_user_name, client_id, manager_id, status_type, agency_id, merchant_id, personage_id, type, gt_client_id, equiment_type, machine_type
     </sql>
 
 </mapper>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 9 - 1
src/main/java/com/szwl/mapper/xml/TEquipmentMapper.xml


+ 2 - 1
src/main/java/com/szwl/model/entity/TAdmin.java

@@ -28,7 +28,8 @@ public class TAdmin implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.AUTO)
+//    @TableId(value = "id", type = IdType.AUTO)
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
     private Long id;
 
     @ApiModelProperty(value = "创建时间")

+ 2 - 1
src/main/java/com/szwl/model/entity/TCoinOrder.java

@@ -25,7 +25,8 @@ public class TCoinOrder implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.AUTO)
+//    @TableId(value = "id", type = IdType.AUTO)
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
     private Long id;
 
     private Date createDate;

+ 20 - 4
src/main/java/com/szwl/model/entity/TEquipment.java

@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
  * </p>
  *
  * @author wuhs
- * @since 2023-06-21
+ * @since 2023-10-25
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -25,7 +25,7 @@ public class TEquipment implements Serializable {
     private static final long serialVersionUID = 1L;
 
     @ApiModelProperty(value = "设备唯一ID")
-    @TableId(value = "id", type = IdType.AUTO)
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
     private Long id;
 
     @ApiModelProperty(value = "创建时间")
@@ -123,10 +123,14 @@ public class TEquipment implements Serializable {
     @ApiModelProperty(value = "所属商家")
     private String adminUserName;
 
-    @ApiModelProperty(value = "公司电话")
+    private Long agencyId;
+
+    private Long merchantId;
+
     private String companyPhone;
 
-    @ApiModelProperty(value = "0:分账方2个,1:分账方3个,3:分账方4个,3:分账方超4个")
+    private Long personageId;
+
     private Integer type;
 
     @ApiModelProperty(value = "地址全名")
@@ -153,12 +157,20 @@ public class TEquipment implements Serializable {
     @ApiModelProperty(value = "睡眠状态,睡眠为true,不睡眠false")
     private Boolean isSleep;
 
+    private String advancedParameters;
+
     @ApiModelProperty(value = "音量")
     private String volume;
 
+    private String commonParameters;
+
     @ApiModelProperty(value = "远程开关机的时间戳")
     private String network;
 
+    private String offTime;
+
+    private String bootTime;
+
     @ApiModelProperty(value = "PLC版本")
     private String plcVersion;
 
@@ -183,4 +195,8 @@ public class TEquipment implements Serializable {
     @ApiModelProperty(value = "公司平台,0或空为申泽,1为七云")
     private String companyType;
 
+    @ApiModelProperty(value = "支付方式:为了远程修改支付方式")
+    private String paymentType;
+
+
 }

+ 8 - 2
src/main/java/com/szwl/model/entity/TEquipmentApply.java

@@ -11,11 +11,11 @@ import lombok.EqualsAndHashCode;
 
 /**
  * <p>
- * 设备连接申请表
+ * 
  * </p>
  *
  * @author wuhs
- * @since 2022-04-21
+ * @since 2023-10-25
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -49,6 +49,12 @@ public class TEquipmentApply implements Serializable {
     @ApiModelProperty(value = "申请状态,1,申请中;2,已拒绝;3,已同意;")
     private Integer statusType;
 
+    private Long agencyId;
+
+    private Long merchantId;
+
+    private Long personageId;
+
     @ApiModelProperty(value = "商家类型;")
     private Integer type;
 

+ 2 - 1
src/main/java/com/szwl/model/entity/TOrder.java

@@ -25,7 +25,8 @@ public class TOrder implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.AUTO)
+//    @TableId(value = "id", type = IdType.AUTO)
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
     private Long id;
 
     private Date createDate;

+ 2 - 2
src/main/java/com/szwl/service/TEquipmentApplyService.java

@@ -6,11 +6,11 @@ import com.szwl.service.base.MyIService;
 
 /**
  * <p>
- * 设备连接申请表 服务类
+ *  服务类
  * </p>
  *
  * @author wuhs
- * @since 2022-04-21
+ * @since 2023-10-25
  */
 public interface TEquipmentApplyService extends MyIService<TEquipmentApply> {
 

+ 2 - 2
src/main/java/com/szwl/service/TEquipmentService.java

@@ -6,11 +6,11 @@ import com.szwl.service.base.MyIService;
 
 /**
  * <p>
- * 设备表 服务类
+ *  服务类
  * </p>
  *
  * @author wuhs
- * @since 2022-04-19
+ * @since 2023-10-25
  */
 public interface TEquipmentService extends MyIService<TEquipment> {
     /**

+ 2 - 2
src/main/java/com/szwl/service/impl/TEquipmentApplyServiceImpl.java

@@ -8,11 +8,11 @@ import org.springframework.stereotype.Service;
 
 /**
  * <p>
- * 设备连接申请表 服务实现类
+ *  服务实现类
  * </p>
  *
  * @author wuhs
- * @since 2022-04-21
+ * @since 2023-10-25
  */
 @Service
 public class TEquipmentApplyServiceImpl extends ServiceImpl<TEquipmentApplyMapper, TEquipmentApply> implements TEquipmentApplyService {

+ 2 - 2
src/main/java/com/szwl/service/impl/TEquipmentServiceImpl.java

@@ -18,11 +18,11 @@ import java.util.List;
 
 /**
  * <p>
- * 设备表 服务实现类
+ *  服务实现类
  * </p>
  *
  * @author wuhs
- * @since 2022-04-19
+ * @since 2023-10-25
  */
 @Service
 public class TEquipmentServiceImpl extends ServiceImpl<TEquipmentMapper, TEquipment> implements TEquipmentService {

+ 88 - 0
src/main/java/com/szwl/util/IDGenerator.java

@@ -0,0 +1,88 @@
+package com.szwl.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class IDGenerator {
+    private static final AtomicLong seq = new AtomicLong(0);
+    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+    private static final SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+
+
+    /**
+     * 生成唯一的16位长整型ID --> admin,equipment等常用表
+     *
+     * @return 订单ID
+     */
+    public static synchronized long commonID() {
+        String timestamp = dateFormat1.format(new Date()).substring(2);
+        long threadId = Thread.currentThread().getId();
+
+        //huTool工具集的雪花算法 --> 生成19位id
+        //参数1为终端ID
+        //参数2为数据中心ID
+//        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
+//        long id = snowflake.nextId();
+//        System.out.println("id***" + id);
+
+        return Long.parseLong(timestamp + String.format("%01d", threadId));
+    }
+
+    /**
+     * 生成唯一的18位长整型ID --> 用于国内订单
+     *
+     * @return 订单ID
+     */
+    public static synchronized long orderID() {
+        String timestamp = dateFormat.format(new Date()).substring(2);
+        long threadId = Thread.currentThread().getId();
+        String randomNumber = generateRandomNumber();
+
+        // 乐观锁部分
+        long currentSeq;
+        long nextSeq;
+        do {
+            currentSeq = seq.get();
+            nextSeq = (currentSeq >= 999) ? 0 : currentSeq + 1;
+        } while (!seq.compareAndSet(currentSeq, nextSeq));
+
+        String s = "5"; // 表示国内订单
+        return Long.parseLong(s + timestamp + String.format("%01d", threadId) + randomNumber + String.format("%01d", nextSeq));
+    }
+
+    /**
+     * 生成唯一的18位长整型ID --> 用于海外订单
+     *
+     * @return 订单ID
+     */
+    public static synchronized long coinOrderID() {
+        String timestamp = dateFormat.format(new Date()).substring(2);
+        long threadId = Thread.currentThread().getId();
+        String randomNumber = generateRandomNumber();
+
+        // 乐观锁部分
+        long currentSeq;
+        long nextSeq;
+        do {
+            currentSeq = seq.get();
+            nextSeq = (currentSeq >= 999) ? 0 : currentSeq + 1;
+        } while (!seq.compareAndSet(currentSeq, nextSeq));
+
+        String s = "1"; // 表示海外订单
+        return Long.parseLong(s + timestamp + String.format("%01d", threadId) + randomNumber + String.format("%01d", nextSeq));
+    }
+
+    /**
+     * 生成3位伪随机数
+     * 因为long类型范围是-9223372036854775808到9223372036854775807,无法容纳更大范围数字,可以将数据库字段类型改为无符号,或者使用varchar类型
+     * @return 随机数
+     */
+    private static String generateRandomNumber() {
+        Random random = new Random();
+        int nextInt = random.nextInt(1000);
+        // 格式化为3位数,并在不满三位的数字前面补零
+        return String.format("%03d", nextInt);
+    }
+}