feat(可回溯): 重构
重构为mysql
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.wabestway.recall</groupId>
|
||||
<artifactId>afis-recall</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>afis-recall-web</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
|
||||
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.wabestway.engine</groupId>
|
||||
<artifactId>afis-engine-api</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||
<version>${spring-cloud-alibaba.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.wabestway.recall;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients(basePackages = {"com.wabestway.engine"})
|
||||
public class AfisRecallApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AfisRecallApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
|
||||
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.wabestway.recall.model;
|
||||
|
||||
import lombok.Data;
|
||||
import org.bson.codecs.pojo.annotations.BsonIgnore;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Document(collection = "orders")
|
||||
public class Order {
|
||||
@Id
|
||||
private String id;
|
||||
private String appKey;
|
||||
private String tenantId;
|
||||
private String productCode;
|
||||
private String productName;
|
||||
@BsonIgnore
|
||||
private List<String> events;
|
||||
@Indexed(unique = true)
|
||||
private String traceId;
|
||||
@Indexed(unique = true)
|
||||
private String orderId;
|
||||
private String complete;
|
||||
private String archived;
|
||||
private String fileId;
|
||||
private String fileUrl;
|
||||
private long createAt;
|
||||
@BsonIgnore
|
||||
private int page;
|
||||
@BsonIgnore
|
||||
private int pageSize;
|
||||
|
||||
private String startDate;
|
||||
private String endDate;
|
||||
private String policyNo;
|
||||
private String holderName;
|
||||
private String holderPhone;
|
||||
private String supplierName;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.wabestway.recall.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OrderList {
|
||||
private int page;
|
||||
private int pageSize;
|
||||
private long total;
|
||||
private List<Order> list;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.wabestway.recall.model;
|
||||
|
||||
import lombok.Data;
|
||||
import org.bson.codecs.pojo.annotations.BsonIgnore;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Document(collection = "records")
|
||||
public class Record {
|
||||
@Id
|
||||
private String id;
|
||||
private List<String> events;
|
||||
private String traceId;
|
||||
@BsonIgnore
|
||||
private String orderId;
|
||||
private boolean last;
|
||||
private String productCode;
|
||||
private String productName;
|
||||
private long createAt;
|
||||
@BsonIgnore
|
||||
private String appKey;
|
||||
private String module;
|
||||
private String content;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.wabestway.recall.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ResObj<T> {
|
||||
private static final String SUCCESS = "success";
|
||||
|
||||
private static final String FAILURE = "failure";
|
||||
|
||||
private static final Integer SUCCESS_CODE = 200;
|
||||
|
||||
private static final Integer FAILURE_CODE = 400;
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
private String _trackId;
|
||||
|
||||
private T data;
|
||||
|
||||
private Map extr;
|
||||
|
||||
private long timestamp;
|
||||
|
||||
private Integer _status;
|
||||
|
||||
private ResObj(Integer code, T data) {
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private ResObj(Integer code, String message, T data) {
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
this.message = message;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private ResObj(T data) {
|
||||
this.data = data;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private ResObj(Integer code) {
|
||||
this.code = code;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return SUCCESS_CODE.equals(this.code);
|
||||
}
|
||||
|
||||
public T data() {
|
||||
return (T) this.data;
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
if (this.data != null && key != null) {
|
||||
return ((Map) this.data).get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ResObj() {
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static ResObj ok() {
|
||||
ResObj o = new ResObj(SUCCESS_CODE);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static ResObj ok(Object data) {
|
||||
ResObj o = new ResObj(SUCCESS_CODE, data);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static ResObj fail(String msg) {
|
||||
ResObj o = new ResObj(FAILURE_CODE, msg, null);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
public static ResObj fail() {
|
||||
ResObj o = new ResObj(FAILURE_CODE);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static ResObj result(Integer code, Object data) {
|
||||
ResObj o = new ResObj(code, data);
|
||||
return o;
|
||||
}
|
||||
|
||||
public static ResObj result(Integer code, String message, Object data) {
|
||||
ResObj o = new ResObj(code, message, data);
|
||||
return o;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ResObj<T> setData(T data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public ResObj setTimestamp(Long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map getExtr() {
|
||||
return extr;
|
||||
}
|
||||
|
||||
|
||||
public Integer get_status() {
|
||||
return _status;
|
||||
}
|
||||
|
||||
public void set_status(Integer _status) {
|
||||
this._status = _status;
|
||||
}
|
||||
|
||||
public String get_trackId() {
|
||||
return _trackId;
|
||||
}
|
||||
|
||||
public void set_trackId(String _trackId) {
|
||||
this._trackId = _trackId;
|
||||
}
|
||||
|
||||
public ResObj trackId(String _trackId) {
|
||||
this._trackId = _trackId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (message == null) {
|
||||
return "ResObj(" + code + ")";
|
||||
}
|
||||
return "ResObj(" + code + "){" + message + "}";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.wabestway.recall.repository;
|
||||
|
||||
import com.wabestway.recall.model.Order;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface OrderRepository extends ReactiveMongoRepository<Order, String> {
|
||||
Mono<Order> findByOrderId(String orderId);
|
||||
|
||||
Mono<Order> findByTraceId(String traceId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.wabestway.recall.repository;
|
||||
|
||||
|
||||
import com.wabestway.recall.model.Record;
|
||||
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
|
||||
public interface RecordRepository extends ReactiveMongoRepository<Record, String> {
|
||||
Flux<Record> findAllByTraceIdOrderByCreateAtAsc(String traceId);
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.wabestway.recall.trace.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import com.wabestway.recall.trace.dto.RecallOrderDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallOrderVO;
|
||||
import com.wabestway.recall.trace.service.RecallOrderApiService;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/trace/recallOrder")
|
||||
@Api(tags = {"-接口"}, description = "-接口")
|
||||
public class RecallOrderController {
|
||||
@Autowired
|
||||
private RecallOrderApiService recallOrderApiService;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
@ApiOperation(value = "分页列表查询", notes = "条件分页查询列表", httpMethod = "POST")
|
||||
public ResObj<Paging<RecallOrderVO>> list(@RequestBody RecallOrderDTO paramRequest) {
|
||||
return recallOrderApiService.list(paramRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 信息
|
||||
*/
|
||||
@GetMapping("/info/{id}")
|
||||
@ApiOperation(value = "根据id查详情", notes = "根据id查详情", httpMethod = "GET")
|
||||
public ResObj<RecallOrderVO> info(@PathVariable("id") String id) {
|
||||
return recallOrderApiService.getRecallOrder(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
@PostMapping("/save")
|
||||
@ApiOperation(value = "保存", notes = "保存", httpMethod = "POST")
|
||||
public ResObj saveRecallOrder(@RequestBody RecallOrderDTO paramRequest) {
|
||||
return recallOrderApiService.saveRecallOrder(paramRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "修改", notes = "修改", httpMethod = "POST")
|
||||
public ResObj updateRecallOrder(@RequestBody RecallOrderDTO paramRequest) {
|
||||
return recallOrderApiService.updateRecallOrder(paramRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/changeStatus")
|
||||
@ApiOperation(value = "启禁用更新", notes = "启禁用更新", httpMethod = "POST")
|
||||
public ResObj changeStatus(@RequestBody RecallOrderDTO paramRequest) {
|
||||
return recallOrderApiService.changeStatus(paramRequest.getId(), paramRequest.getStatus());
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package com.wabestway.recall.trace.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import com.wabestway.recall.trace.dto.RecallRecordDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallRecordVO;
|
||||
import com.wabestway.recall.trace.service.RecallRecordApiService;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/trace/recallRecord")
|
||||
@Api(tags = {"-接口"}, description = "-接口")
|
||||
public class RecallRecordController {
|
||||
@Autowired
|
||||
private RecallRecordApiService recallRecordApiService;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
@ApiOperation(value = "分页列表查询", notes = "条件分页查询列表", httpMethod = "POST")
|
||||
public ResObj<Paging<RecallRecordVO>> list(@RequestBody RecallRecordDTO paramRequest) {
|
||||
return recallRecordApiService.list(paramRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 信息
|
||||
*/
|
||||
@GetMapping("/info/{id}")
|
||||
@ApiOperation(value = "根据id查详情", notes = "根据id查详情", httpMethod = "GET")
|
||||
public ResObj<RecallRecordVO> info(@PathVariable("id") String id) {
|
||||
return recallRecordApiService.getRecallRecord(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*/
|
||||
@PostMapping("/save")
|
||||
@ApiOperation(value = "保存", notes = "保存", httpMethod = "POST")
|
||||
public ResObj saveRecallRecord(@RequestBody RecallRecordDTO paramRequest) {
|
||||
return recallRecordApiService.saveRecallRecord(paramRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@ApiOperation(value = "修改", notes = "修改", httpMethod = "POST")
|
||||
public ResObj updateRecallRecord(@RequestBody RecallRecordDTO paramRequest) {
|
||||
return recallRecordApiService.updateRecallRecord(paramRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/changeStatus")
|
||||
@ApiOperation(value = "启禁用更新", notes = "启禁用更新", httpMethod = "POST")
|
||||
public ResObj changeStatus(@RequestBody RecallRecordDTO paramRequest) {
|
||||
return recallRecordApiService.changeStatus(paramRequest.getId(), paramRequest.getStatus());
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.wabestway.recall.trace.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.wabestway.recall.trace.dto.RecallOrderDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallOrderVO;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
public interface RecallOrderApiService {
|
||||
|
||||
/**
|
||||
* 列表
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj<Paging<RecallOrderVO>> list(RecallOrderDTO paramReq);
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
ResObj<RecallOrderVO> getRecallOrder(String id);
|
||||
|
||||
/**
|
||||
* 保存
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj saveRecallOrder(RecallOrderDTO paramReq);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj updateRecallOrder(RecallOrderDTO paramReq);
|
||||
|
||||
/**
|
||||
* 启禁用
|
||||
* @param id
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
ResObj changeStatus(String id, String status);
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.wabestway.recall.trace.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.wabestway.recall.trace.dto.RecallRecordDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallRecordVO;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
public interface RecallRecordApiService {
|
||||
|
||||
/**
|
||||
* 列表
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj<Paging<RecallRecordVO>> list(RecallRecordDTO paramReq);
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
ResObj<RecallRecordVO> getRecallRecord(String id);
|
||||
|
||||
/**
|
||||
* 保存
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj saveRecallRecord(RecallRecordDTO paramReq);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param paramReq
|
||||
* @return
|
||||
*/
|
||||
ResObj updateRecallRecord(RecallRecordDTO paramReq);
|
||||
|
||||
/**
|
||||
* 启禁用
|
||||
* @param id
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
ResObj changeStatus(String id, String status);
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.wabestway.recall.trace.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
import com.wabestway.commons.enums.DataValidEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import com.wabestway.ins.utils.UUIDUtil;
|
||||
import com.wabestway.recall.trace.entity.RecallOrderEntity;
|
||||
import com.wabestway.recall.trace.dto.RecallOrderDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallOrderVO;
|
||||
import com.wabestway.recall.trace.service.RecallOrderApiService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.wabestway.recall.trace.util.HeaderDataUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
@Service
|
||||
public class RecallOrderApiServiceImpl implements RecallOrderApiService {
|
||||
@Autowired
|
||||
private RecallOrderService recallOrderService;
|
||||
|
||||
@Override
|
||||
public ResObj<Paging<RecallOrderVO>> list(RecallOrderDTO paramReq) {
|
||||
IPage<RecallOrderVO> resultPage = recallOrderService.queryRecallOrderByCondition(paramReq.getPage(), paramReq.getPageSize(), paramReq);
|
||||
|
||||
Paging<RecallOrderVO> paging = new Paging(resultPage.getRecords(), paramReq.getPage(), resultPage.getSize(), resultPage.getTotal());
|
||||
return ResObj.ok(paging);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResObj<RecallOrderVO> getRecallOrder(String id) {
|
||||
RecallOrderVO recallOrderVO = recallOrderService.queryRecallOrderById(id);
|
||||
|
||||
return ResObj.ok(recallOrderVO);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj saveRecallOrder(RecallOrderDTO paramReq) {
|
||||
RecallOrderEntity recallOrder = new RecallOrderEntity();
|
||||
BeanUtils.copyProperties(paramReq, recallOrder);
|
||||
|
||||
recallOrder.setId(UUIDUtil.generate());//赋值id
|
||||
recallOrder.setStatus(DataValidEnum.VALID.getCode());
|
||||
recallOrder.setCreateBy(HeaderDataUtil.getUserId());//创建人
|
||||
recallOrder.setCreateTime(System.currentTimeMillis());//创建时间
|
||||
recallOrder.setUpdateBy(HeaderDataUtil.getUserId());//更新人
|
||||
recallOrder.setUpdateTime(System.currentTimeMillis());//更新时间
|
||||
|
||||
recallOrderService.save(recallOrder);
|
||||
return ResObj.ok();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj updateRecallOrder(RecallOrderDTO paramReq) {
|
||||
RecallOrderEntity recallOrder = new RecallOrderEntity();
|
||||
BeanUtils.copyProperties(paramReq, recallOrder);
|
||||
recallOrder.setUpdateBy(HeaderDataUtil.getUserId());//更新人
|
||||
recallOrder.setUpdateTime(System.currentTimeMillis());//更新时间
|
||||
recallOrderService.updateById(recallOrder);
|
||||
return ResObj.ok();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj changeStatus(String id, String status) {
|
||||
RecallOrderEntity recallOrder = new RecallOrderEntity();
|
||||
recallOrder.setId(id);
|
||||
recallOrder.setStatus(status);
|
||||
recallOrder.setUpdateBy(HeaderDataUtil.getUserId());
|
||||
recallOrder.setUpdateTime(System.currentTimeMillis());
|
||||
recallOrderService.updateRecallOrderById(recallOrder);
|
||||
|
||||
return ResObj.ok();
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.wabestway.recall.trace.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.wabestway.commons.http.Paging;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
import com.wabestway.commons.enums.DataValidEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import com.wabestway.ins.utils.UUIDUtil;
|
||||
import com.wabestway.recall.trace.entity.RecallRecordEntity;
|
||||
import com.wabestway.recall.trace.dto.RecallRecordDTO;
|
||||
import com.wabestway.recall.trace.vo.RecallRecordVO;
|
||||
import com.wabestway.recall.trace.service.RecallRecordApiService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.wabestway.recall.trace.util.HeaderDataUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author wangH
|
||||
* @company 北京华焱坤泰科技有限公司
|
||||
* @Time 2023-05-06 17:37:03
|
||||
*/
|
||||
@Service
|
||||
public class RecallRecordApiServiceImpl implements RecallRecordApiService {
|
||||
@Autowired
|
||||
private RecallRecordService recallRecordService;
|
||||
|
||||
@Override
|
||||
public ResObj<Paging<RecallRecordVO>> list(RecallRecordDTO paramReq) {
|
||||
IPage<RecallRecordVO> resultPage = recallRecordService.queryRecallRecordByCondition(paramReq.getPage(), paramReq.getPageSize(), paramReq);
|
||||
|
||||
Paging<RecallRecordVO> paging = new Paging(resultPage.getRecords(), paramReq.getPage(), resultPage.getSize(), resultPage.getTotal());
|
||||
return ResObj.ok(paging);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResObj<RecallRecordVO> getRecallRecord(String id) {
|
||||
RecallRecordVO recallRecordVO = recallRecordService.queryRecallRecordById(id);
|
||||
|
||||
return ResObj.ok(recallRecordVO);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj saveRecallRecord(RecallRecordDTO paramReq) {
|
||||
RecallRecordEntity recallRecord = new RecallRecordEntity();
|
||||
BeanUtils.copyProperties(paramReq, recallRecord);
|
||||
|
||||
recallRecord.setId(UUIDUtil.generate());//赋值id
|
||||
recallRecord.setStatus(DataValidEnum.VALID.getCode());
|
||||
recallRecord.setCreateBy(HeaderDataUtil.getUserId());//创建人
|
||||
recallRecord.setCreateTime(System.currentTimeMillis());//创建时间
|
||||
recallRecord.setUpdateBy(HeaderDataUtil.getUserId());//更新人
|
||||
recallRecord.setUpdateTime(System.currentTimeMillis());//更新时间
|
||||
|
||||
recallRecordService.save(recallRecord);
|
||||
return ResObj.ok();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj updateRecallRecord(RecallRecordDTO paramReq) {
|
||||
RecallRecordEntity recallRecord = new RecallRecordEntity();
|
||||
BeanUtils.copyProperties(paramReq, recallRecord);
|
||||
recallRecord.setUpdateBy(HeaderDataUtil.getUserId());//更新人
|
||||
recallRecord.setUpdateTime(System.currentTimeMillis());//更新时间
|
||||
recallRecordService.updateById(recallRecord);
|
||||
return ResObj.ok();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ResObj changeStatus(String id, String status) {
|
||||
RecallRecordEntity recallRecord = new RecallRecordEntity();
|
||||
recallRecord.setId(id);
|
||||
recallRecord.setStatus(status);
|
||||
recallRecord.setUpdateBy(HeaderDataUtil.getUserId());
|
||||
recallRecord.setUpdateTime(System.currentTimeMillis());
|
||||
recallRecordService.updateRecallRecordById(recallRecord);
|
||||
|
||||
return ResObj.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.wabestway.recall.web;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.wabestway.commons.http.ResObj;
|
||||
import com.wabestway.engine.api.dfs.UploadFileDTO;
|
||||
import com.wabestway.engine.api.dfs.UploadRespVO;
|
||||
import com.wabestway.engine.api.feign.DfsStorageFeignClient;
|
||||
import com.wabestway.recall.model.Order;
|
||||
import com.wabestway.recall.model.OrderList;
|
||||
import com.wabestway.recall.model.Record;
|
||||
import com.wabestway.recall.repository.OrderRepository;
|
||||
import com.wabestway.recall.repository.RecordRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/order")
|
||||
public class OrderController {
|
||||
private final RecordRepository recordRepository;
|
||||
private final OrderRepository orderRepository;
|
||||
|
||||
private final DfsStorageFeignClient storageFeignClient;
|
||||
|
||||
public OrderController(RecordRepository recordRepository, OrderRepository orderRepository, DfsStorageFeignClient storageFeignClient) {
|
||||
this.recordRepository = recordRepository;
|
||||
this.orderRepository = orderRepository;
|
||||
this.storageFeignClient = storageFeignClient;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Flux<Order> getAllOrders() {
|
||||
return orderRepository.findAll();
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
public Mono<ResObj> list(@RequestBody Order order) {
|
||||
OrderList resList = new OrderList();
|
||||
List<Order> list = new ArrayList<>();
|
||||
Sort s = Sort.by("createAt").descending();
|
||||
PageRequest pageRequest = PageRequest.of(order.getPage() - 1, order.getPageSize(), s);
|
||||
ExampleMatcher matcher = ExampleMatcher.matching()
|
||||
.withIgnoreNullValues().withIgnorePaths("createAt", "last", "page", "pageSize");
|
||||
Example<Order> ep = Example.of(order, matcher);
|
||||
Flux<Order> flux = orderRepository.findAll(ep, s);
|
||||
flux.skip(pageRequest.getOffset()).limitRequest(pageRequest.getPageSize()).subscribe(list::add);
|
||||
resList.setList(list);
|
||||
return flux.count().flatMap(count -> {
|
||||
resList.setTotal(count);
|
||||
return Mono.just(ResObj.ok(resList));
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping("/recallUp")
|
||||
public Mono<ResObj> recallUp(@RequestBody Order order) {
|
||||
Mono<Order> queryOrder = orderRepository.findByOrderId(order.getOrderId());
|
||||
return queryOrder.flatMap(ss -> {
|
||||
ss.setStartDate(order.getStartDate());
|
||||
ss.setEndDate(order.getEndDate());
|
||||
ss.setHolderName(order.getHolderName());
|
||||
ss.setHolderPhone(order.getHolderPhone());
|
||||
ss.setSupplierName(order.getSupplierName());
|
||||
orderRepository.save(ss).subscribe();
|
||||
return Mono.just(ResObj.ok());
|
||||
}).defaultIfEmpty(ResObj.fail("订单不存在"));
|
||||
}
|
||||
|
||||
@PostMapping("/info/{orderId}")
|
||||
public Mono<ResObj> findByOrderId(@PathVariable String orderId) {
|
||||
Mono<Order> forder = orderRepository.findByOrderId(orderId);
|
||||
return forder.flatMap(fo -> {
|
||||
Flux<Record> rs = recordRepository.findAllByTraceIdOrderByCreateAtAsc(fo.getTraceId());
|
||||
Mono<List<List<String>>> es = rs.map(rr -> rr.getEvents()).collectList();
|
||||
Mono<List<String>> events = es.flatMapIterable(lists -> lists).flatMapIterable(list -> list).collectList();
|
||||
return events.flatMap(e -> {
|
||||
fo.setEvents(e);
|
||||
return Mono.just(ResObj.ok(fo));
|
||||
});
|
||||
}).defaultIfEmpty(ResObj.fail("订单不存在"));
|
||||
}
|
||||
|
||||
@GetMapping("/ffmpeg")
|
||||
public Mono<ResObj> createMp4() {
|
||||
Order order = new Order();
|
||||
order.setComplete("1");
|
||||
ExampleMatcher matcher = ExampleMatcher.matching()
|
||||
.withIgnoreNullValues().withIgnorePaths("createAt", "last", "page", "pageSize");
|
||||
Example<Order> ep = Example.of(order, matcher);
|
||||
Sort s = Sort.by("createAt");
|
||||
Flux<Order> flux = orderRepository.findAll(ep, s);
|
||||
flux.filter(fo -> fo.getFileId() == null).subscribe(fo -> {
|
||||
Mono<List<List<String>>> es = recordRepository.findAllByTraceIdOrderByCreateAtAsc(fo.getTraceId()).map(rr -> rr.getEvents()).collectList();
|
||||
Mono<List<String>> events = es.flatMapIterable(lists -> lists).flatMapIterable(list -> list).collectList();
|
||||
events.subscribe(e -> {
|
||||
JSONArray array = JSONArray.parseArray(JSON.toJSONString(e));
|
||||
try {
|
||||
createVideo(fo, array.toJSONString());
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
});
|
||||
return Mono.just(ResObj.ok());
|
||||
}
|
||||
|
||||
void createVideo(Order fo, String jsonData) throws IOException {
|
||||
|
||||
// 创建临时目录
|
||||
Path tempDir = null;
|
||||
try {
|
||||
tempDir = Files.createTempDirectory("ts");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("Created temporary directory: " + tempDir);
|
||||
|
||||
try {
|
||||
File tempFile = new File(tempDir.toFile(), "traces.json");
|
||||
FileWriter fw = new FileWriter(tempFile);
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
bw.write(jsonData);
|
||||
bw.flush();
|
||||
bw.close();
|
||||
fw.close();
|
||||
String[] command = {"ts-node", "/opt/trace-transform/src/index.ts"};
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
processBuilder.directory(tempDir.toFile());
|
||||
// 在临时目录下执行命令
|
||||
Process process = processBuilder.start();
|
||||
|
||||
Thread processThread = new Thread(() -> {
|
||||
try {
|
||||
// 读取命令输出
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
reader.close();
|
||||
// 等待命令执行完成
|
||||
int exitCode = process.waitFor();
|
||||
|
||||
System.out.println("Command exited with code " + exitCode);
|
||||
} catch (InterruptedException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
processThread.start();
|
||||
|
||||
// Continue with other tasks here...
|
||||
|
||||
try {
|
||||
processThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
File file = new File(tempDir.toFile(), "video.mp4");
|
||||
if (file.exists()) {
|
||||
log.info(String.valueOf(file.length()));
|
||||
//byte[] fileBytes = Files.readAllBytes(file.toPath());
|
||||
byte[] fileBytes = FileUtil.readBytes(file);
|
||||
String titles = fo.getOrderId() + ".mp4";
|
||||
UploadFileDTO uploadFileDTO = new UploadFileDTO(fileBytes, "RECALL", titles);
|
||||
|
||||
ResObj<UploadRespVO> uploadResObj = storageFeignClient.uploadBytes(uploadFileDTO);
|
||||
log.info(JSON.toJSONString(uploadResObj));
|
||||
if (uploadResObj.isOk()) {
|
||||
fo.setFileId(uploadResObj.getData().getFileId());
|
||||
fo.setFileUrl(uploadResObj.getData().getFileUrl());
|
||||
orderRepository.save(fo).subscribe();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
} finally {
|
||||
// 删除临时目录
|
||||
// Files.walk(tempDir)
|
||||
// .sorted(Comparator.reverseOrder())
|
||||
// .map(Path::toFile)
|
||||
// .forEach(File::delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.wabestway.recall.web;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.wabestway.recall.model.Order;
|
||||
import com.wabestway.recall.model.Record;
|
||||
import com.wabestway.recall.model.ResObj;
|
||||
import com.wabestway.recall.repository.OrderRepository;
|
||||
import com.wabestway.recall.repository.RecordRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/track")
|
||||
public class RecallController {
|
||||
private final RecordRepository recordRepository;
|
||||
private final OrderRepository orderRepository;
|
||||
|
||||
public RecallController(RecordRepository recordRepository, OrderRepository orderRepository) {
|
||||
this.recordRepository = recordRepository;
|
||||
this.orderRepository = orderRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Flux<Record> getAllUsers() {
|
||||
return recordRepository.findAll();
|
||||
}
|
||||
|
||||
@PostMapping("/save")
|
||||
public Mono<ResObj> save(@RequestBody Record record) {
|
||||
if (record.getOrderId() != null && !record.getOrderId().isEmpty()) {
|
||||
Mono<Order> order = orderRepository.findByOrderId(record.getOrderId());
|
||||
order.hasElement().subscribe(exit -> {
|
||||
if (!exit) {
|
||||
if (record.getTraceId() != null && !record.getTraceId().isEmpty()) {
|
||||
Mono<Order> tcOrder = orderRepository.findByTraceId(record.getTraceId());
|
||||
tcOrder.filter(to -> to.getId() != null).flatMap(to -> {
|
||||
to.setOrderId(record.getOrderId());
|
||||
if (record.isLast()) {
|
||||
to.setComplete("1");
|
||||
}
|
||||
return orderRepository.save(to);
|
||||
}).subscribe();
|
||||
} else {
|
||||
record.setTraceId(UUID.randomUUID().toString().replace("-", ""));
|
||||
Order forder = new Order();
|
||||
forder.setOrderId(record.getOrderId());
|
||||
forder.setTraceId(record.getTraceId());
|
||||
forder.setProductCode(record.getProductCode());
|
||||
forder.setProductName(record.getProductName());
|
||||
forder.setCreateAt(System.currentTimeMillis());
|
||||
forder.setAppKey(record.getAppKey());
|
||||
forder.setArchived("0");
|
||||
forder.setComplete("0");
|
||||
// forder.setHolderName("王五");
|
||||
// forder.setHolderPhone("18515064530");
|
||||
// forder.setSupplierName("阳光保险");
|
||||
// forder.setStartDate("2023-01-01");
|
||||
// forder.setEndDate("2035-01-01");
|
||||
if (record.isLast()) {
|
||||
forder.setComplete("1");
|
||||
}
|
||||
orderRepository.save(forder).subscribe();
|
||||
}
|
||||
} else {
|
||||
order.subscribe(to -> {
|
||||
if (record.isLast()) {
|
||||
to.setComplete("1");
|
||||
orderRepository.save(to).subscribe();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (record.getTraceId() == null || record.getTraceId().isEmpty()) {
|
||||
record.setTraceId(UUID.randomUUID().toString().replace("-", ""));
|
||||
Order order = new Order();
|
||||
order.setTraceId(record.getTraceId());
|
||||
order.setProductCode(record.getProductCode());
|
||||
order.setProductName(record.getProductName());
|
||||
order.setCreateAt(System.currentTimeMillis());
|
||||
order.setAppKey(record.getAppKey());
|
||||
order.setArchived("0");
|
||||
order.setComplete("0");
|
||||
// order.setHolderName("王五");
|
||||
// order.setHolderPhone("18515064530");
|
||||
// order.setSupplierName("阳光保险");
|
||||
// order.setStartDate("2023-01-01");
|
||||
// order.setEndDate("2035-01-01");
|
||||
if (record.isLast()) {
|
||||
order.setComplete("1");
|
||||
}
|
||||
orderRepository.save(order).subscribe();
|
||||
}
|
||||
}
|
||||
record.setCreateAt(System.currentTimeMillis());
|
||||
log.info("保存数据:{}", JSON.toJSONString(record));
|
||||
return recordRepository.save(record).flatMap(ss -> {
|
||||
ss.setEvents(null);
|
||||
return Mono.just(ResObj.ok(ss));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user