Compare commits
63 Commits
50927481d2
...
79ea08898b
Author | SHA1 | Date | |
---|---|---|---|
79ea08898b | |||
52d0c4bc36 | |||
84287df87b | |||
389c28300f | |||
10e7421672 | |||
cf3a49d590 | |||
083f67e516 | |||
3e53fd8367 | |||
86d09134a6 | |||
082d8830bd | |||
d95c16aa01 | |||
a45929753f | |||
a46d4d8fac | |||
c8874064f0 | |||
cecc7aa181 | |||
7cea8093c7 | |||
ff82644f47 | |||
b4aa3619ba | |||
117a13cc2c | |||
ab0f38cd97 | |||
0ab142e1c4 | |||
67dca0d4d4 | |||
36f1242e79 | |||
06ebc1d05e | |||
7d8483b6e4 | |||
dc7c4a13cb | |||
c963324cfb | |||
af2947e44a | |||
fcddc4fc8c | |||
da72e7e0a9 | |||
d9619e6fea | |||
938f9702ea | |||
4b03bfb871 | |||
80e93ecd39 | |||
e128101563 | |||
a1eb29c49d | |||
48a3dfb313 | |||
a08f4adf2d | |||
a0703e48c9 | |||
2b43d8a7b7 | |||
decfe18b9a | |||
9ec6825372 | |||
f9a8a5f20e | |||
a5f67b1eac | |||
a8601548c6 | |||
fd85b7ad77 | |||
bcf8e8e88d | |||
fb530a1eb4 | |||
8a7021d759 | |||
26dc53ca6a | |||
46f6532164 | |||
50a7c2e9c4 | |||
f36416bad2 | |||
180ba67de8 | |||
7e8eebdef5 | |||
eac1c48cb2 | |||
0ae47d3f71 | |||
072a1a6131 | |||
aa4048ad26 | |||
6bfff19c5a | |||
41aba63e5d | |||
05bc2773b9 | |||
c2ebbd71e2 |
69
pom.xml
69
pom.xml
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.12.RELEASE</version>
|
||||
<version>2.7.18</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.ycwl</groupId>
|
||||
@ -21,16 +21,18 @@
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
|
||||
<hutool-all.version>5.8.24</hutool-all.version>
|
||||
<mysql-connector.version>8.0.33</mysql-connector.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<knife4j-spring-boot-starter.version>2.0.7</knife4j-spring-boot-starter.version>
|
||||
<pagehelper.version>5.3.1</pagehelper.version>
|
||||
<tomcat.version>9.0.102</tomcat.version>
|
||||
<!--跳过单元测试-->
|
||||
<skipTests>true</skipTests>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<!-- 微信支付-->
|
||||
<!-- 微信支付 -->
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
@ -52,23 +54,13 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.lettuce</groupId>
|
||||
<artifactId>lettuce-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入mysql连接 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql-connector.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
@ -78,6 +70,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -95,7 +92,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<!--<scope>provided</scope>-->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool工具类 -->
|
||||
@ -159,17 +156,11 @@
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>3.22.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里云对象存储 -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>3.17.4</version>
|
||||
<version>3.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- S3对象存储 -->
|
||||
@ -195,14 +186,50 @@
|
||||
<artifactId>aliyun-java-sdk-facebody</artifactId>
|
||||
<version>2.0.12</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 百度智能云人脸识别 -->
|
||||
<dependency>
|
||||
<groupId>com.baidu.aip</groupId>
|
||||
<artifactId>java-sdk</artifactId>
|
||||
<version>4.16.19</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<!-- 确保 src/main/resources 下的资源文件被包含 -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/*.png</include> <!-- 明确包含 PNG 文件 -->
|
||||
<include>**/*.ttf</include> <!-- 明确包含 TTF 文件 -->
|
||||
<include>**/*</include> <!-- 包含其他所有资源文件 -->
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<!-- 跳过测试执行 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>${skipTests}</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 跳过测试编译 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<testExcludes>
|
||||
<testExclude>**/*Test.java</testExclude>
|
||||
</testExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.ycwl.basic.aspectj;
|
||||
|
||||
import com.ycwl.basic.annotation.RequestToFile;
|
||||
import com.ycwl.basic.config.CachedBodyHttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
@ -12,6 +13,7 @@ import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
@ -37,27 +39,8 @@ public class HttpSaver {
|
||||
}
|
||||
|
||||
public static void saveRequestToFile(HttpServletRequest request) throws IOException {
|
||||
StringBuilder rawReq = new StringBuilder();
|
||||
rawReq.append(request.getMethod()).append(" ").append(request.getRequestURL());
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null) {
|
||||
rawReq.append("?").append(queryString);
|
||||
}
|
||||
rawReq.append("\r\n");
|
||||
Enumeration<String> headerNames = request.getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerName = headerNames.nextElement();
|
||||
rawReq.append(headerName).append(": ").append(request.getHeader(headerName)).append("\r\n");
|
||||
}
|
||||
rawReq.append("\r\n");
|
||||
// 获取body
|
||||
try {
|
||||
rawReq.append(request.getReader().lines().collect(Collectors.joining("\r\n")));
|
||||
rawReq.append("\r\n");
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
// 写入文件
|
||||
File file = new File("./request/"+System.currentTimeMillis()+".http");
|
||||
// 写入文件
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
@ -65,7 +48,22 @@ public class HttpSaver {
|
||||
file.createNewFile();
|
||||
}
|
||||
try (java.io.FileWriter writer = new java.io.FileWriter(file, true)) {
|
||||
writer.write(rawReq.toString());
|
||||
writer.append(request.getMethod()).append(" ").append(request.getRequestURL());
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null) {
|
||||
writer.append("?").append(queryString);
|
||||
}
|
||||
writer.append("\r\n");
|
||||
Enumeration<String> headerNames = request.getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerName = headerNames.nextElement();
|
||||
writer.append(headerName).append(": ").append(request.getHeader(headerName)).append("\r\n");
|
||||
}
|
||||
writer.append("\r\n");
|
||||
// 获取body
|
||||
CachedBodyHttpServletRequest cachedRequest = (CachedBodyHttpServletRequest) request;
|
||||
writer.append(new String(cachedRequest.getCachedBody()));
|
||||
writer.append("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
91
src/main/java/com/ycwl/basic/biz/CouponBiz.java
Normal file
91
src/main/java/com/ycwl/basic/biz/CouponBiz.java
Normal file
@ -0,0 +1,91 @@
|
||||
package com.ycwl.basic.biz;
|
||||
|
||||
import com.ycwl.basic.mapper.CouponMapper;
|
||||
import com.ycwl.basic.mapper.CouponRecordMapper;
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
|
||||
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordQueryResp;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class CouponBiz {
|
||||
@Autowired
|
||||
private CouponMapper couponMapper;
|
||||
@Autowired
|
||||
private CouponRecordMapper couponRecordMapper;
|
||||
|
||||
public CouponRecordQueryResp queryUserCouponRecord(Long scenicId, Long memberId, Long faceId, String goodsId) {
|
||||
CouponRecordQueryResp resp = new CouponRecordQueryResp();
|
||||
List<CouponRecordEntity> recordList = couponRecordMapper.queryByUserWithGoodsId(scenicId, memberId, goodsId);
|
||||
if (recordList != null && !recordList.isEmpty()) {
|
||||
Optional<CouponRecordEntity> record = recordList.stream().filter(item -> item.getStatus() == 0).filter(item -> item.getFaceId() == null || item.getFaceId().equals(faceId)).findAny();
|
||||
if (record.isPresent()) {
|
||||
CouponRecordEntity recordEntity = record.get();
|
||||
resp.setExist(true);
|
||||
resp.setId(recordEntity.getId());
|
||||
resp.setCouponId(recordEntity.getCouponId());
|
||||
CouponEntity coupon = couponMapper.getById(recordEntity.getCouponId());
|
||||
if (coupon != null) {
|
||||
resp.setMemberId(recordEntity.getMemberId());
|
||||
resp.setFaceId(recordEntity.getFaceId());
|
||||
resp.setStatus(recordEntity.getStatus());
|
||||
resp.setCreateTime(recordEntity.getCreateTime());
|
||||
resp.setUsedTime(recordEntity.getUsedTime());
|
||||
resp.setUsedOrderId(recordEntity.getUsedOrderId());
|
||||
resp.setCoupon(coupon);
|
||||
} else {
|
||||
resp.setExist(false);
|
||||
}
|
||||
} else {
|
||||
Optional<CouponRecordEntity> usedRecord = recordList.stream().filter(item -> item.getStatus() != 0).filter(item -> item.getFaceId() == null || item.getFaceId().equals(faceId)).findAny();
|
||||
if (usedRecord.isPresent()) {
|
||||
CouponRecordEntity recordEntity = usedRecord.get();
|
||||
resp.setExist(true);
|
||||
resp.setId(recordEntity.getId());
|
||||
resp.setCouponId(recordEntity.getCouponId());
|
||||
CouponEntity coupon = couponMapper.getById(recordEntity.getCouponId());
|
||||
if (coupon != null) {
|
||||
resp.setMemberId(recordEntity.getMemberId());
|
||||
resp.setFaceId(recordEntity.getFaceId());
|
||||
resp.setStatus(recordEntity.getStatus());
|
||||
resp.setCreateTime(recordEntity.getCreateTime());
|
||||
resp.setUsedTime(recordEntity.getUsedTime());
|
||||
resp.setUsedOrderId(recordEntity.getUsedOrderId());
|
||||
resp.setCoupon(coupon);
|
||||
} else {
|
||||
resp.setExist(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
public boolean userGetCoupon(Long memberId, Long faceId, Integer couponId) {
|
||||
CouponEntity coupon = couponMapper.getById(couponId);
|
||||
if (coupon == null) {
|
||||
return false;
|
||||
}
|
||||
CouponRecordEntity entity = new CouponRecordEntity();
|
||||
entity.setCouponId(couponId);
|
||||
entity.setFaceId(faceId);
|
||||
entity.setMemberId(memberId);
|
||||
entity.setStatus(0);
|
||||
entity.setCreateTime(new Date());
|
||||
return couponRecordMapper.insert(entity) > 0;
|
||||
}
|
||||
|
||||
public boolean userUseCoupon(Long memberId, Long faceId, Integer couponRecordId, Long orderId) {
|
||||
CouponRecordEntity entity = new CouponRecordEntity();
|
||||
entity.setId(couponRecordId);
|
||||
entity.setStatus(1);
|
||||
entity.setUsedTime(new Date());
|
||||
entity.setUsedOrderId(orderId);
|
||||
return couponRecordMapper.updateById(entity) > 0;
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ import com.ycwl.basic.mapper.VideoMapper;
|
||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||
import com.ycwl.basic.model.mobile.order.PriceObj;
|
||||
import com.ycwl.basic.model.mobile.statistic.req.StatisticsRecordAddReq;
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordQueryResp;
|
||||
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||
import com.ycwl.basic.model.pc.order.entity.OrderEntity;
|
||||
import com.ycwl.basic.model.pc.order.entity.OrderItemEntity;
|
||||
@ -70,6 +72,8 @@ public class OrderBiz {
|
||||
private VideoTaskRepository videoTaskRepository;
|
||||
@Autowired
|
||||
private BrokerBiz brokerBiz;
|
||||
@Autowired
|
||||
private CouponBiz couponBiz;
|
||||
|
||||
public PriceObj queryPrice(Long scenicId, int goodsType, Long goodsId) {
|
||||
PriceObj priceObj = new PriceObj();
|
||||
@ -124,6 +128,18 @@ public class OrderBiz {
|
||||
return priceObj;
|
||||
}
|
||||
|
||||
public OrderEntity hasTypeOrder(Long userId, Long scenicId, int orderType, Integer configId) {
|
||||
OrderEntity orderEntity = orderMapper.queryTypeOrder(userId, scenicId, orderType, configId);
|
||||
if (orderEntity == null) {
|
||||
return null;
|
||||
}
|
||||
if (Integer.valueOf(1).equals(orderEntity.getStatus())) {
|
||||
return orderEntity;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IsBuyRespVO isBuy(Long userId, Long scenicId, int goodsType, Long goodsId) {
|
||||
IsBuyRespVO respVO = new IsBuyRespVO();
|
||||
boolean isBuy = orderRepository.checkUserBuyItem(userId, goodsType, goodsId);
|
||||
@ -160,8 +176,8 @@ public class OrderBiz {
|
||||
respVO.setOrderId(orderEntity.getId());
|
||||
}
|
||||
}
|
||||
// 还是没买
|
||||
respVO.setBuy(isBuy);
|
||||
// 还是没买
|
||||
if (!isBuy) {
|
||||
PriceObj priceObj = queryPrice(scenicId, goodsType, goodsId);
|
||||
if (priceObj == null) {
|
||||
@ -170,8 +186,38 @@ public class OrderBiz {
|
||||
respVO.setFree(priceObj.isFree());
|
||||
respVO.setGoodsType(goodsType);
|
||||
respVO.setGoodsId(goodsId);
|
||||
respVO.setPrice(priceObj.getPrice());
|
||||
respVO.setOrigPrice(priceObj.getPrice());
|
||||
respVO.setSlashPrice(priceObj.getSlashPrice());
|
||||
switch (goodsType) {
|
||||
case 0: // vlog
|
||||
VideoEntity video = videoRepository.getVideo(goodsId);
|
||||
TaskEntity taskById = videoTaskRepository.getTaskById(video.getTaskId());
|
||||
if (taskById != null) {
|
||||
CouponRecordQueryResp recordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, taskById.getFaceId(), taskById.getTemplateId().toString());
|
||||
if (recordQueryResp.isUsable()) {
|
||||
respVO.setCouponId(recordQueryResp.getCouponId());
|
||||
respVO.setCouponRecordId(recordQueryResp.getId());
|
||||
CouponEntity coupon = recordQueryResp.getCoupon();
|
||||
if (coupon != null) {
|
||||
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceObj.getPrice()));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
CouponRecordQueryResp recordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, goodsId, String.valueOf(goodsType));
|
||||
if (recordQueryResp.isUsable()) {
|
||||
respVO.setCouponId(recordQueryResp.getCouponId());
|
||||
respVO.setCouponRecordId(recordQueryResp.getId());
|
||||
CouponEntity coupon = recordQueryResp.getCoupon();
|
||||
if (coupon != null) {
|
||||
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceObj.getPrice()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return respVO;
|
||||
}
|
||||
@ -194,6 +240,9 @@ public class OrderBiz {
|
||||
}
|
||||
});
|
||||
orderRepository.clearOrderCache(orderId); // 更新完了,清理下
|
||||
if (order.getCouponRecordId() != null) {
|
||||
couponBiz.userUseCoupon(order.getMemberId(), order.getFaceId(), order.getCouponRecordId(), orderId);
|
||||
}
|
||||
|
||||
//支付时间
|
||||
OrderAppRespVO orderDetail = orderMapper.appDetail(orderId);
|
||||
@ -228,18 +277,12 @@ public class OrderBiz {
|
||||
|
||||
StatisticsRecordAddReq statisticsRecordAddReq = new StatisticsRecordAddReq();
|
||||
statisticsRecordAddReq.setMemberId(order.getMemberId());
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(goodsCreateTime);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 21);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
// TODO: 他的购买的内容于内容生成当天晚9点之前算现场订单,否则算推送订单
|
||||
if(calendar.getTime().compareTo(payAt)>0){//
|
||||
Long enterType = statisticsMapper.getUserRecentEnterType(order.getMemberId(), order.getCreateAt());
|
||||
if(!Long.valueOf(1014).equals(enterType)){//
|
||||
statisticsRecordAddReq.setType(StatisticEnum.ON_SITE_PAYMENT.code);
|
||||
}else {
|
||||
statisticsRecordAddReq.setType(StatisticEnum.POST_PAYMENT.code);
|
||||
}
|
||||
calendar.clear();
|
||||
statisticsRecordAddReq.setScenicId(order.getScenicId());
|
||||
statisticsRecordAddReq.setMorphId(orderId);
|
||||
statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
|
||||
|
@ -1,9 +1,15 @@
|
||||
package com.ycwl.basic.biz;
|
||||
|
||||
import com.ycwl.basic.model.mobile.order.IsBuyBatchRespVO;
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordQueryResp;
|
||||
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
|
||||
import com.ycwl.basic.model.pc.order.entity.OrderEntity;
|
||||
import com.ycwl.basic.model.pc.price.entity.PriceConfigEntity;
|
||||
import com.ycwl.basic.model.pc.price.resp.GoodsListRespVO;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
|
||||
import com.ycwl.basic.repository.FaceRepository;
|
||||
import com.ycwl.basic.repository.PriceRepository;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.repository.TemplateRepository;
|
||||
@ -11,6 +17,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -24,6 +31,12 @@ public class PriceBiz {
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private PriceRepository priceRepository;
|
||||
@Autowired
|
||||
private OrderBiz orderBiz;
|
||||
@Autowired
|
||||
private FaceRepository faceRepository;
|
||||
@Autowired
|
||||
private CouponBiz couponBiz;
|
||||
|
||||
public List<GoodsListRespVO> listGoodsByScenic(Long scenicId) {
|
||||
List<GoodsListRespVO> goodsList = new ArrayList<>();
|
||||
@ -66,4 +79,65 @@ public class PriceBiz {
|
||||
return false;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public IsBuyBatchRespVO isBuy(Long userId, Long faceId, Long scenicId, Integer type, String goodsIds) {
|
||||
IsBuyBatchRespVO respVO = new IsBuyBatchRespVO();
|
||||
PriceConfigEntity priceConfig = priceRepository.getPriceConfigByScenicTypeGoods(scenicId, type, goodsIds);
|
||||
if (priceConfig == null) {
|
||||
return null;
|
||||
}
|
||||
FaceEntity face = faceRepository.getFace(faceId);
|
||||
if (face != null && !face.getMemberId().equals(userId)) {
|
||||
return null;
|
||||
}
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null) {
|
||||
if (Integer.valueOf(1).equals(scenicConfig.getAllFree())) {
|
||||
// 景区全免
|
||||
respVO.setFree(true);
|
||||
respVO.setSlashPrice(BigDecimal.ZERO);
|
||||
return respVO;
|
||||
}
|
||||
}
|
||||
switch (type) {
|
||||
case 0: // 单个定价
|
||||
CouponRecordQueryResp recordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, faceId, goodsIds);
|
||||
if (recordQueryResp.isUsable()) {
|
||||
respVO.setCouponId(recordQueryResp.getCouponId());
|
||||
respVO.setCouponRecordId(recordQueryResp.getId());
|
||||
CouponEntity coupon = recordQueryResp.getCoupon();
|
||||
if (coupon != null) {
|
||||
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceConfig.getPrice()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
CouponRecordQueryResp oneCouponRecordQueryResp = couponBiz.queryUserCouponRecord(scenicId, userId, faceId, "-1");
|
||||
if (oneCouponRecordQueryResp.isUsable()) {
|
||||
respVO.setCouponId(oneCouponRecordQueryResp.getCouponId());
|
||||
respVO.setCouponRecordId(oneCouponRecordQueryResp.getId());
|
||||
CouponEntity coupon = oneCouponRecordQueryResp.getCoupon();
|
||||
if (coupon != null) {
|
||||
respVO.setCouponPrice(coupon.calculateDiscountPrice(priceConfig.getPrice()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
respVO.setConfigId(priceConfig.getId());
|
||||
respVO.setGoodsIds(goodsIds);
|
||||
respVO.setType(type);
|
||||
respVO.setOrigPrice(priceConfig.getPrice());
|
||||
respVO.setSlashPrice(priceConfig.getSlashPrice());
|
||||
|
||||
// 查询用户是否有此类订单
|
||||
respVO.setBuy(false);
|
||||
if (userId != null) {
|
||||
OrderEntity orderEntity = orderBiz.hasTypeOrder(userId, scenicId, type, priceConfig.getId());
|
||||
if (orderEntity != null) {
|
||||
respVO.setOrderId(orderEntity.getId());
|
||||
respVO.setBuy(Integer.valueOf(1).equals(orderEntity.getStatus()));
|
||||
}
|
||||
}
|
||||
return respVO;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
package com.ycwl.basic.config;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.*;
|
||||
|
||||
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
|
||||
private final byte[] cachedBody;
|
||||
|
||||
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
|
||||
super(request);
|
||||
// 缓存请求体内容
|
||||
InputStream requestInputStream = request.getInputStream();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = requestInputStream.read(buffer)) != -1) {
|
||||
byteArrayOutputStream.write(buffer, 0, read);
|
||||
}
|
||||
cachedBody = byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() {
|
||||
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachedBody);
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() {
|
||||
return byteArrayInputStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
// 不需要实现
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() {
|
||||
return new BufferedReader(new InputStreamReader(this.getInputStream()));
|
||||
}
|
||||
|
||||
public byte[] getCachedBody() {
|
||||
return cachedBody;
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.ycwl.basic.config;
|
||||
|
||||
import com.ycwl.basic.storage.entity.AliOssStorageConfig;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 阿里云OSS配置
|
||||
*
|
||||
* @author songmingsong
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
public class FaceDetectConfig {
|
||||
@Value("${aliFace.accessKeyId}")
|
||||
private String accessKeyId;
|
||||
@Value("${aliFace.accessKeySecret}")
|
||||
private String accessKeySecret;
|
||||
@Value("${aliFace.region}")
|
||||
private String region;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package com.ycwl.basic.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Resource
|
||||
private RedisConnectionFactory redisConnectionFactory;
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<Object, Object> redisTemplate() {
|
||||
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
// 使用Jackson2JsonRedisSerialize 替换默认序列化
|
||||
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
|
||||
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
|
||||
|
||||
// 设置value的序列化规则和 key的序列化规则
|
||||
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
|
||||
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
|
||||
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
|
||||
redisTemplate.setEnableDefaultSerializer(true);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
//package com.ycwl.basic.config;
|
||||
//
|
||||
//import org.redisson.Redisson;
|
||||
//import org.redisson.api.RedissonClient;
|
||||
//import org.redisson.config.Config;
|
||||
//import org.springframework.beans.factory.annotation.Value;
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//
|
||||
//@Configuration
|
||||
//public class RedissonConfig {
|
||||
//
|
||||
// @Value("${spring.redis.host}")
|
||||
// private String host;
|
||||
// @Value("${spring.redis.port}")
|
||||
// private String port;
|
||||
// @Value("${spring.redis.password}")
|
||||
// private String password;
|
||||
//
|
||||
// @Bean
|
||||
// public RedissonClient getRedisSon() {
|
||||
// Config config = new Config();
|
||||
// String address = new StringBuilder("redis://").append(host).append(":").append(port).toString();
|
||||
// config.useSingleServer().setAddress(address);
|
||||
// if (null != password && !"".equals(password.trim())) {
|
||||
// config.useSingleServer().setPassword(password);
|
||||
// }
|
||||
// return Redisson.create(config);
|
||||
// }
|
||||
//
|
||||
//}
|
@ -12,8 +12,11 @@ public class SchedulerConfig {
|
||||
@Bean
|
||||
public ThreadPoolTaskScheduler taskScheduler() {
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(256);
|
||||
scheduler.setPoolSize(32); // 核心/最大线程数
|
||||
scheduler.setAwaitTerminationSeconds(0); // 空闲线程存活时间(秒)
|
||||
scheduler.setThreadNamePrefix("Scheduler-");
|
||||
scheduler.setAwaitTerminationSeconds(60); // 等待任务终止的时间
|
||||
scheduler.setRemoveOnCancelPolicy(true); // 取消任务后移除线程
|
||||
return scheduler;
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ import java.util.List;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2WebMvc
|
||||
@Profile({"!prod"})
|
||||
@Profile({"test"})
|
||||
public class SwaggerConfig {
|
||||
|
||||
/**
|
||||
|
@ -58,7 +58,7 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
public CorsFilter corsFilter() {
|
||||
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
final CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
// config.setAllowCredentials(true);
|
||||
// 允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
|
||||
config.addAllowedOrigin("*");
|
||||
// 允许访问的头信息,*表示全部
|
||||
|
@ -4,4 +4,5 @@ public class StorageConstant {
|
||||
public static final String VLOG_PATH = "vlog";
|
||||
public static final String VIDEO_PIECE_PATH = "source_video";
|
||||
public static final String PHOTO_PATH = "source_photo";
|
||||
public static final String PHOTO_WATERMARKED_PATH = "photo_w";
|
||||
}
|
||||
|
@ -15,20 +15,16 @@ import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||
import com.ycwl.basic.model.pc.member.entity.MemberEntity;
|
||||
import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
|
||||
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
|
||||
import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
|
||||
import com.ycwl.basic.repository.VideoRepository;
|
||||
import com.ycwl.basic.repository.VideoTaskRepository;
|
||||
import com.ycwl.basic.service.mobile.AppScenicService;
|
||||
import com.ycwl.basic.service.mobile.GoodsService;
|
||||
import com.ycwl.basic.service.pc.FaceService;
|
||||
import com.ycwl.basic.service.task.impl.TaskTaskServiceImpl;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -197,7 +193,7 @@ public class LyCompatibleController {
|
||||
return R.error("用户没有上传过照片!");
|
||||
}
|
||||
VideoTaskStatusVO taskStatusVO = goodsService.getTaskStatusByScenicId(member.getId(), member.getScenicId());
|
||||
List<ContentPageVO> listApiResponse = appScenicService.faceContentList(member.getId(), faceVO.getId());
|
||||
List<ContentPageVO> listApiResponse = appScenicService.faceContentList(faceVO.getId());
|
||||
Map<Integer, List<ContentPageVO>> collect = listApiResponse.stream()
|
||||
.filter(contentPageVO -> contentPageVO.getLockType() < 0)
|
||||
.collect(Collectors.groupingBy(ContentPageVO::getGoodsType));
|
||||
@ -224,8 +220,9 @@ public class LyCompatibleController {
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
GoodsReqQuery goodsReqQuery = new GoodsReqQuery();
|
||||
goodsReqQuery.setFaceId(faceVO.getId());
|
||||
goodsReqQuery.setSourceType(1);
|
||||
List<GoodsDetailVO> sourceGoodsList = goodsService.sourceGoodsList(member.getId(), goodsReqQuery);
|
||||
List<GoodsDetailVO> sourceGoodsList = goodsService.sourceGoodsList(goodsReqQuery);
|
||||
List<Map<String, Object>> userVideoList = sourceGoodsList.stream().map(goodsDetailVO -> {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("id", goodsDetailVO.getGoodsId().toString());
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/mobile/controller/v1")
|
||||
public class AppCouponController {
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @Author:longbinbin
|
||||
* @Date:2024/12/6 10:18
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/mobile/scenic/v1")
|
||||
@Api(tags = "设备相关接口")
|
||||
public class AppDeviceController {
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||
import com.ycwl.basic.constant.BaseContextHandler;
|
||||
import com.ycwl.basic.exception.CheckTokenException;
|
||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||
import com.ycwl.basic.model.mobile.goods.*;
|
||||
import com.ycwl.basic.service.mobile.GoodsService;
|
||||
import com.ycwl.basic.service.task.TaskService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.JwtTokenUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -15,7 +12,6 @@ import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -30,10 +26,6 @@ public class AppGoodsController {
|
||||
|
||||
@Autowired
|
||||
private GoodsService goodsService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private TaskStatusBiz taskStatusBiz;
|
||||
|
||||
@ApiOperation("商品列表")
|
||||
@PostMapping("/goodsList")
|
||||
@ -44,10 +36,23 @@ public class AppGoodsController {
|
||||
@ApiOperation("源素材(原片/照片)商品列表")
|
||||
@PostMapping("/sourceGoodsList")
|
||||
public ApiResponse<List<GoodsDetailVO>> sourceGoodsList(@RequestBody GoodsReqQuery query) {
|
||||
List<GoodsDetailVO> goodsDetailVOS = goodsService.sourceGoodsList(Long.valueOf(BaseContextHandler.getUserId()), query);
|
||||
List<GoodsDetailVO> goodsDetailVOS = goodsService.sourceGoodsList(query);
|
||||
return ApiResponse.success(goodsDetailVOS);
|
||||
}
|
||||
|
||||
@PostMapping("/sourceGoodsList/preview")
|
||||
public ApiResponse<List<GoodsUrlVO>> sourceGoodsListPreview(@RequestBody GoodsReqQuery query) {
|
||||
List<GoodsUrlVO> goodsUrlList = goodsService.sourceGoodsListPreview(query);
|
||||
return ApiResponse.success(goodsUrlList);
|
||||
}
|
||||
|
||||
@PostMapping("/sourceGoodsList/download")
|
||||
public ApiResponse<List<GoodsUrlVO>> sourceGoodsListDownload(@RequestBody GoodsReqQuery query) {
|
||||
List<GoodsUrlVO> goodsUrlList = goodsService.sourceGoodsListDownload(query);
|
||||
return ApiResponse.success(goodsUrlList);
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("成片vlog商品详情")
|
||||
@GetMapping("/getVideoGoodsDetail/{videoId}")
|
||||
@IgnoreToken
|
||||
@ -62,8 +67,7 @@ public class AppGoodsController {
|
||||
|
||||
@GetMapping("/sourceGoods/{sourceId}")
|
||||
public ApiResponse<GoodsDetailVO> sourceGoodsInfo(@PathVariable("sourceId") Long sourceId) {
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
return goodsService.sourceGoodsInfo(worker.getUserId(), sourceId);
|
||||
return goodsService.sourceGoodsInfo(sourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +92,6 @@ public class AppGoodsController {
|
||||
@GetMapping("/task/face/{faceId}/template/{templateId}")
|
||||
public ApiResponse<VideoTaskStatusVO> getTemplateTaskStatus(@PathVariable("faceId") Long faceId, @PathVariable("templateId") Long templateId) {
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
return ApiResponse.success(goodsService.getTaskStatusByTemplateId(worker.getUserId(), faceId, templateId));
|
||||
return ApiResponse.success(goodsService.getTaskStatusByTemplateId(faceId, templateId));
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.model.mobile.index.TopStateResp;
|
||||
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
|
||||
import com.ycwl.basic.model.mobile.scenic.ScenicIndexVO;
|
||||
import com.ycwl.basic.service.mobile.AppScenicService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author:longbinbin
|
||||
* @Date:2024/12/5 10:20
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/mobile/index/v1")
|
||||
@Api(tags = "首页相关接口")
|
||||
public class AppIndexController {
|
||||
|
||||
@Autowired
|
||||
private AppScenicService scenicService;
|
||||
|
||||
/**
|
||||
* 首页景区列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
// @ApiOperation(value = "首页景区列表", notes = "首页景区列表")
|
||||
// @PostMapping("/scenicList")
|
||||
// @IgnoreToken
|
||||
// public ApiResponse<List<ScenicAppVO>> scenicList(@RequestBody ScenicIndexVO scenicIndexVO) {
|
||||
// return scenicService.scenicList(scenicIndexVO);
|
||||
// }
|
||||
|
||||
// @ApiOperation(value = "顶部状态", notes = "顶部状态")
|
||||
// @GetMapping("/topState")
|
||||
// @IgnoreToken
|
||||
// public ApiResponse<TopStateResp> topState() {
|
||||
// return scenicService.topState();
|
||||
// }
|
||||
|
||||
@GetMapping("/faceAgreement")
|
||||
public ApiResponse<String> faceAgreement() {
|
||||
return ApiResponse.success("人脸识别隐私协议:\n" +
|
||||
"1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n" +
|
||||
"1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n" +
|
||||
"1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n1、xxx\n");
|
||||
}
|
||||
}
|
@ -62,26 +62,6 @@ public class AppMemberController {
|
||||
return memberService.update(userInfoUpdateDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意用户协议
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("同意用户协议")
|
||||
@GetMapping("/agreement")
|
||||
public ApiResponse<?> agreement() {
|
||||
return memberService.agreement();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("是否首次获取视频")
|
||||
@GetMapping("/isFirstObtainVideo")
|
||||
public ApiResponse isFirstTimeObtainingVideo() {
|
||||
// TODO 判断是否首次获取视频逻辑
|
||||
|
||||
return ApiResponse.success("");
|
||||
}
|
||||
|
||||
@ApiOperation("新增或修改景区服务通知状态")
|
||||
@GetMapping("/updateScenicServiceNoticeStatus")
|
||||
public ApiResponse updateScenicServiceNoticeStatus(Long scenicId) {
|
||||
|
@ -2,18 +2,23 @@ package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.biz.OrderBiz;
|
||||
import com.ycwl.basic.biz.PriceBiz;
|
||||
import com.ycwl.basic.constant.BaseContextHandler;
|
||||
import com.ycwl.basic.mapper.FaceMapper;
|
||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||
import com.ycwl.basic.model.mobile.goods.GoodsPriceQueryReq;
|
||||
import com.ycwl.basic.model.mobile.order.IsBuyBatchRespVO;
|
||||
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
|
||||
import com.ycwl.basic.model.mobile.order.OrderAppPageReq;
|
||||
import com.ycwl.basic.model.mobile.order.RefundOrderReq;
|
||||
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||
import com.ycwl.basic.model.pc.order.req.CreateBatchOrderReqVO;
|
||||
import com.ycwl.basic.model.pc.order.req.CreateOrderReqVO;
|
||||
import com.ycwl.basic.model.pc.order.req.OrderAddReq;
|
||||
import com.ycwl.basic.model.pc.order.resp.OrderAppRespVO;
|
||||
import com.ycwl.basic.model.wx.WxPayRespVO;
|
||||
import com.ycwl.basic.repository.OrderRepository;
|
||||
import com.ycwl.basic.repository.PriceRepository;
|
||||
import com.ycwl.basic.service.mobile.GoodsService;
|
||||
import com.ycwl.basic.service.pc.OrderService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
@ -35,9 +40,11 @@ public class AppOrderController {
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
@Autowired
|
||||
private OrderRepository orderRepository;
|
||||
@Autowired
|
||||
private OrderBiz orderBiz;
|
||||
@Autowired
|
||||
private PriceBiz priceBiz;
|
||||
@Autowired
|
||||
private FaceMapper faceMapper;
|
||||
|
||||
@ApiOperation("用户端订单列表查询")
|
||||
@PostMapping("/page")
|
||||
@ -88,4 +95,18 @@ public class AppOrderController {
|
||||
Long userId = Long.parseLong(BaseContextHandler.getUserId());
|
||||
return ApiResponse.success(orderBiz.isBuy(userId, scenicId, type, goodsId));
|
||||
}
|
||||
|
||||
@GetMapping("/scenic/{scenicId}/queryBatchPrice")
|
||||
public ApiResponse<IsBuyBatchRespVO> queryPrice(@PathVariable("scenicId") Long scenicId, @RequestParam("type") Integer type, @RequestParam(value = "faceId", required = false) Long faceId, @RequestParam(value = "goodsIds", required = false) String goodsIds) {
|
||||
Long userId = Long.parseLong(BaseContextHandler.getUserId());
|
||||
if (faceId == null) {
|
||||
FaceRespVO lastFaceByUserId = faceMapper.findLastFaceByUserId(BaseContextHandler.getUserId());
|
||||
faceId = lastFaceByUserId.getId();
|
||||
}
|
||||
IsBuyBatchRespVO buy = priceBiz.isBuy(userId, faceId, scenicId, type, goodsIds);
|
||||
if (buy == null) {
|
||||
return ApiResponse.fail("该套餐暂未开放购买");
|
||||
}
|
||||
return ApiResponse.success(buy);
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,7 @@ package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.constant.BaseContextHandler;
|
||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||
import com.ycwl.basic.model.mobile.goods.GoodsPageVO;
|
||||
import com.ycwl.basic.model.mobile.goods.GoodsReqQuery;
|
||||
import com.ycwl.basic.model.mobile.scenic.ScenicAppVO;
|
||||
import com.ycwl.basic.model.mobile.scenic.ScenicDeviceCountVO;
|
||||
import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO;
|
||||
@ -14,7 +11,6 @@ import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
|
||||
import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.mobile.AppScenicService;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.JwtTokenUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -74,16 +70,8 @@ public class AppScenicController {
|
||||
|
||||
@ApiOperation("景区视频源素材列表")
|
||||
@GetMapping("/face/{faceId}/contentList")
|
||||
public ApiResponse<List<ContentPageVO>> contentList(@PathVariable String faceId) {
|
||||
if (!StringUtils.isNumeric(faceId)) {
|
||||
log.error("请求异常, faceId: [{}]",faceId);
|
||||
return ApiResponse.fail("请求异常");
|
||||
}
|
||||
Long id = Long.parseLong(faceId);
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
List<ContentPageVO> contentPageVOS = appScenicService.faceContentList(worker.getUserId(), id);
|
||||
public ApiResponse<List<ContentPageVO>> contentList(@PathVariable Long faceId) {
|
||||
List<ContentPageVO> contentPageVOS = appScenicService.faceContentList(faceId);
|
||||
return ApiResponse.success(contentPageVOS);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||
import com.ycwl.basic.model.jwt.JwtInfo;
|
||||
import com.ycwl.basic.model.mobile.goods.VideoTaskReq;
|
||||
import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO;
|
||||
@ -30,7 +29,7 @@ public class AppTaskController {
|
||||
@IgnoreLogReq
|
||||
public ApiResponse<VideoTaskStatusVO> getTaskStatusByFaceId(@PathVariable("faceId") Long faceId) {
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
return ApiResponse.success(goodsService.getTaskStatusByFaceId(worker.getUserId(), faceId));
|
||||
return ApiResponse.success(goodsService.getTaskStatusByFaceId(faceId));
|
||||
}
|
||||
@GetMapping("/scenic/{scenicId}")
|
||||
@IgnoreLogReq
|
||||
@ -52,7 +51,7 @@ public class AppTaskController {
|
||||
@IgnoreLogReq
|
||||
public ApiResponse<VideoTaskStatusVO> getTemplateTaskStatus(@PathVariable("faceId") Long faceId, @PathVariable("templateId") Long templateId) {
|
||||
JwtInfo worker = JwtTokenUtil.getWorker();
|
||||
return ApiResponse.success(goodsService.getTaskStatusByTemplateId(worker.getUserId(), faceId, templateId));
|
||||
return ApiResponse.success(goodsService.getTaskStatusByTemplateId(faceId, templateId));
|
||||
}
|
||||
|
||||
@PostMapping("/submit")
|
||||
|
@ -1,20 +1,14 @@
|
||||
package com.ycwl.basic.controller.mobile;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.model.wx.WechatMessageSubscribeForm;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.mobile.WxNotifyService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -31,8 +25,6 @@ import java.util.List;
|
||||
@RequestMapping("/api/mobile/wx/notify/v1")
|
||||
@Api(tags = "微信消息模板通知")
|
||||
public class AppWxNotifyController {
|
||||
@Autowired
|
||||
private WxNotifyService wxNotifyService;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
//
|
||||
|
@ -8,6 +8,7 @@ import com.ycwl.basic.model.pc.broker.resp.BrokerRespVO;
|
||||
import com.ycwl.basic.model.pc.broker.resp.DailySummaryRespVO;
|
||||
import com.ycwl.basic.service.pc.BrokerRecordService;
|
||||
import com.ycwl.basic.service.pc.BrokerService;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.WxMpUtil;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
@ -123,12 +124,16 @@ public class BrokerController {
|
||||
String appState = mpConfig.getState();
|
||||
String path = "pages/home/index?scenicId=" + broker.getScenicId() + "&morphId=" + id;
|
||||
String filePath = "qr_code_tk_" + id + ".jpg";
|
||||
IStorageAdapter adapter = StorageFactory.use();
|
||||
if (adapter.isExists(filePath)) {
|
||||
return ApiResponse.success(adapter.getUrl(filePath));
|
||||
}
|
||||
try {
|
||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||
IStorageAdapter adapter = StorageFactory.use();
|
||||
File file = new File(filePath);
|
||||
String s = adapter.uploadFile(file, filePath);
|
||||
file.delete();
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||
return ApiResponse.success(s);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.fail("生成二维码失败");
|
||||
|
@ -0,0 +1,72 @@
|
||||
package com.ycwl.basic.controller.pc;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.biz.PriceBiz;
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import com.ycwl.basic.model.pc.coupon.req.CouponQueryReq;
|
||||
import com.ycwl.basic.model.pc.coupon.resp.CouponRespVO;
|
||||
import com.ycwl.basic.model.pc.price.resp.GoodsListRespVO;
|
||||
import com.ycwl.basic.service.pc.CouponService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/coupon/v1")
|
||||
@Api(tags = "优惠券管理")
|
||||
public class CouponController {
|
||||
@Autowired
|
||||
private CouponService couponService;
|
||||
@Autowired
|
||||
private PriceBiz priceBiz;
|
||||
|
||||
@GetMapping("/{scenicId}/goodsList")
|
||||
public ApiResponse<List<GoodsListRespVO>> scenicGoodsList(@PathVariable Long scenicId) {
|
||||
List<GoodsListRespVO> data = priceBiz.listGoodsByScenic(scenicId);
|
||||
data.add(new GoodsListRespVO(-1L, "一口价"));
|
||||
return ApiResponse.success(data);
|
||||
}
|
||||
|
||||
@ApiOperation("新增优惠券")
|
||||
@PostMapping("/add")
|
||||
public ApiResponse<Integer> add(@RequestBody CouponEntity coupon) {
|
||||
return ApiResponse.success(couponService.add(coupon));
|
||||
}
|
||||
|
||||
@ApiOperation("更新优惠券")
|
||||
@PostMapping("/update/{id}")
|
||||
public ApiResponse<Boolean> update(@PathVariable Integer id, @RequestBody CouponEntity coupon) {
|
||||
coupon.setId(id);
|
||||
return ApiResponse.success(couponService.update(coupon));
|
||||
}
|
||||
|
||||
@PutMapping("/updateStatus/{id}")
|
||||
public ApiResponse<Boolean> updateStatus(@PathVariable Integer id) {
|
||||
return ApiResponse.success(couponService.updateStatus(id));
|
||||
}
|
||||
|
||||
@ApiOperation("删除优惠券")
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public ApiResponse<Boolean> delete(@PathVariable Integer id) {
|
||||
return ApiResponse.success(couponService.delete(id));
|
||||
}
|
||||
|
||||
@ApiOperation("根据ID查询优惠券")
|
||||
@GetMapping("/get/{id}")
|
||||
public ApiResponse<CouponEntity> getById(@PathVariable Integer id) {
|
||||
return ApiResponse.success(couponService.getById(id));
|
||||
}
|
||||
|
||||
@ApiOperation("分页查询优惠券列表")
|
||||
@PostMapping("/page")
|
||||
public ApiResponse<PageInfo<CouponRespVO>> list(@RequestBody CouponQueryReq couponQuery) {
|
||||
PageHelper.startPage(couponQuery.getPageNum(), couponQuery.getPageSize());
|
||||
List<CouponRespVO> list = couponService.list(couponQuery);
|
||||
PageInfo<CouponRespVO> pageInfo = new PageInfo<>(list);
|
||||
return ApiResponse.success(pageInfo);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.ycwl.basic.controller.pc;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity;
|
||||
import com.ycwl.basic.model.pc.device.req.DeviceAddOrUpdateReq;
|
||||
import com.ycwl.basic.model.pc.device.req.DeviceBatchSortRequest;
|
||||
import com.ycwl.basic.model.pc.device.req.DeviceReqQuery;
|
||||
import com.ycwl.basic.model.pc.device.req.DeviceSortRequest;
|
||||
import com.ycwl.basic.model.pc.device.resp.DeviceRespVO;
|
||||
@ -62,6 +63,11 @@ public class DeviceController {
|
||||
return deviceService.sortDevice(request.getDeviceId(), request.getAfterDeviceId());
|
||||
}
|
||||
|
||||
@PostMapping("/scenic/{scenicId}/sortBatch")
|
||||
public ApiResponse<Boolean> sortDeviceBatch(@PathVariable("scenicId") Long scenicId, @RequestBody DeviceBatchSortRequest request) {
|
||||
return deviceService.batchSort(scenicId, request);
|
||||
}
|
||||
|
||||
@GetMapping("/config/{id}")
|
||||
public ApiResponse<DeviceConfigEntity> getConfig(@PathVariable("id") Long id) {
|
||||
return ApiResponse.success(deviceService.getConfig(id));
|
||||
|
@ -0,0 +1,56 @@
|
||||
package com.ycwl.basic.controller.pc;
|
||||
|
||||
import com.ycwl.basic.constant.BaseContextHandler;
|
||||
import com.ycwl.basic.model.pc.permission.entity.PermissionEntity;
|
||||
import com.ycwl.basic.model.pc.permission.req.PermissionSaveReq;
|
||||
import com.ycwl.basic.model.pc.permission.resp.PermissionResp;
|
||||
import com.ycwl.basic.service.pc.PermissionService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/permission/v1")
|
||||
@Api(tags = "权限管理接口")
|
||||
public class PermissionController {
|
||||
@Autowired
|
||||
private PermissionService permissionService;
|
||||
|
||||
@GetMapping("/get/")
|
||||
public ApiResponse<PermissionResp> getPermissionByUser() {
|
||||
String userId = BaseContextHandler.getUserId();
|
||||
PermissionEntity permission = permissionService.getPermissionByUserId(Long.parseLong(userId));
|
||||
if (permission == null || StringUtils.isEmpty(permission.getPermString())) {
|
||||
return ApiResponse.success(new PermissionResp(new ArrayList<>()));
|
||||
}
|
||||
return ApiResponse.success(new PermissionResp(Arrays.asList(StringUtils.split(permission.getPermString(), ","))));
|
||||
}
|
||||
|
||||
@ApiOperation("根据用户ID查询权限信息")
|
||||
@GetMapping("/get/{userId}")
|
||||
public ApiResponse<PermissionResp> getPermissionByUser(@PathVariable Long userId) {
|
||||
PermissionEntity permission = permissionService.getPermissionByUserId(userId);
|
||||
if (permission == null || StringUtils.isEmpty(permission.getPermString())) {
|
||||
return ApiResponse.success(new PermissionResp(new ArrayList<>()));
|
||||
}
|
||||
return ApiResponse.success(new PermissionResp(Arrays.asList(StringUtils.split(permission.getPermString(), ","))));
|
||||
}
|
||||
|
||||
@ApiOperation("保存或更新权限信息")
|
||||
@PostMapping("/save/{userId}")
|
||||
public ApiResponse saveOrUpdate(@PathVariable Long userId, @RequestBody PermissionSaveReq req) {
|
||||
permissionService.saveOrUpdate(userId, StringUtils.join(req.getPermissions(), ","));
|
||||
return ApiResponse.success(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.ycwl.basic.controller.pc;
|
||||
|
||||
import com.ycwl.basic.model.pc.printer.entity.PrinterEntity;
|
||||
import com.ycwl.basic.service.printer.PrinterService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/printer/v1")
|
||||
public class PrinterController {
|
||||
@Autowired
|
||||
private PrinterService printerService;
|
||||
|
||||
@ApiOperation("查询列表")
|
||||
@PostMapping("/list")
|
||||
public ApiResponse<List<PrinterEntity>> list(@RequestBody PrinterEntity condition) {
|
||||
return printerService.list(condition);
|
||||
}
|
||||
|
||||
@ApiOperation("获取详情")
|
||||
@GetMapping("/get/{id}")
|
||||
public ApiResponse<PrinterEntity> get(@PathVariable("id") Integer id) {
|
||||
return printerService.get(id);
|
||||
}
|
||||
|
||||
@ApiOperation("新增")
|
||||
@PostMapping("/add")
|
||||
public ApiResponse<Integer> add(@RequestBody PrinterEntity entity) {
|
||||
return printerService.add(entity);
|
||||
}
|
||||
|
||||
@ApiOperation("更新")
|
||||
@PostMapping("/update")
|
||||
public ApiResponse<Integer> update(@RequestBody PrinterEntity entity) {
|
||||
return printerService.update(entity);
|
||||
}
|
||||
|
||||
@ApiOperation("删除")
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public ApiResponse<Integer> delete(@PathVariable("id") Integer id) {
|
||||
return printerService.delete(id);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.ycwl.basic.controller.pc;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
|
||||
import com.ycwl.basic.model.pc.scenic.req.ScenicAccountReqQuery;
|
||||
import com.ycwl.basic.service.pc.ScenicAccountService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/scenicAccount/v1")
|
||||
public class ScenicAccountController {
|
||||
@Autowired
|
||||
private ScenicAccountService service;
|
||||
|
||||
// 添加景区账号
|
||||
@PostMapping("/add")
|
||||
public ApiResponse addScenicAccount(@RequestBody ScenicAccountEntity entity) {
|
||||
int result = service.addScenicAccount(entity);
|
||||
return result > 0 ? ApiResponse.success("添加成功") : ApiResponse.fail("添加失败");
|
||||
}
|
||||
|
||||
// 删除景区账号
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public ApiResponse deleteScenicAccount(@PathVariable Long id) {
|
||||
int result = service.deleteScenicAccount(id);
|
||||
return result > 0 ? ApiResponse.success("删除成功") : ApiResponse.fail("删除失败");
|
||||
}
|
||||
@PostMapping("/updateStatus/{id}")
|
||||
public ApiResponse updateStatus(@PathVariable Long id) {
|
||||
int result = service.updateStatus(id);
|
||||
return result > 0 ? ApiResponse.success("更新成功") : ApiResponse.fail("更新失败");
|
||||
}
|
||||
|
||||
// 更新景区账号
|
||||
@PostMapping("/update")
|
||||
public ApiResponse updateScenicAccount(@RequestBody ScenicAccountEntity entity) {
|
||||
int result = service.updateScenicAccount(entity);
|
||||
return result > 0 ? ApiResponse.success("更新成功") : ApiResponse.fail("更新失败");
|
||||
}
|
||||
|
||||
// 根据ID查询景区账号
|
||||
@GetMapping("/get/{id}")
|
||||
public ApiResponse getScenicAccount(@PathVariable Long id) {
|
||||
ScenicAccountEntity entity = service.getScenicAccountById(id);
|
||||
return entity != null ? ApiResponse.success(entity) : ApiResponse.fail("未找到该账号");
|
||||
}
|
||||
|
||||
// 根据景区ID查询超级账号
|
||||
@GetMapping("/super/{scenicId}")
|
||||
public ApiResponse getSuperAccount(@PathVariable Long scenicId) {
|
||||
ScenicAccountEntity entity = service.getSuperAccountByScenicId(scenicId);
|
||||
return entity != null ? ApiResponse.success(entity) : ApiResponse.fail("未找到超级账号");
|
||||
}
|
||||
|
||||
// 新增分页查询接口
|
||||
@PostMapping("/page")
|
||||
public ApiResponse<PageInfo<ScenicAccountEntity>> pageQuery(@RequestBody ScenicAccountReqQuery req) {
|
||||
PageHelper.startPage(req.getPageNum(), req.getPageSize());
|
||||
List<ScenicAccountEntity> list = service.pageQuery(req);
|
||||
PageInfo<ScenicAccountEntity> pageInfo = new PageInfo<>(list);
|
||||
return ApiResponse.success(pageInfo);
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import com.ycwl.basic.model.pc.scenic.resp.ScenicRespVO;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.WxMpUtil;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
@ -109,12 +110,16 @@ public class ScenicController {
|
||||
String appState = mpConfig.getState();
|
||||
String path = "pages/home/index?scenicId=" + id;
|
||||
String filePath = "qr_code_" + id + ".jpg";
|
||||
IStorageAdapter adapter = StorageFactory.use();
|
||||
if (adapter.isExists(filePath)) {
|
||||
return ApiResponse.success(adapter.getUrl(filePath));
|
||||
}
|
||||
try {
|
||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||
IStorageAdapter adapter = StorageFactory.use();
|
||||
File file = new File(filePath);
|
||||
String s = adapter.uploadFile(file, filePath);
|
||||
file.delete();
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||
return ApiResponse.success(s);
|
||||
} catch (Exception e) {
|
||||
return ApiResponse.fail("生成二维码失败");
|
||||
|
@ -0,0 +1,44 @@
|
||||
package com.ycwl.basic.controller.printer;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.model.printer.req.PrinterSyncReq;
|
||||
import com.ycwl.basic.model.printer.req.WorkerAuthReqVo;
|
||||
import com.ycwl.basic.model.printer.resp.PrintTaskResp;
|
||||
import com.ycwl.basic.model.printer.resp.TaskSyncResp;
|
||||
import com.ycwl.basic.service.printer.PrinterService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IgnoreToken
|
||||
@Api(tags = "打印机对接接口")
|
||||
@RestController
|
||||
@RequestMapping("/printer/v1")
|
||||
public class PrinterTaskController {
|
||||
@Autowired
|
||||
private PrinterService printerService;
|
||||
|
||||
@PostMapping("/sync")
|
||||
public ApiResponse<TaskSyncResp> sync(@RequestBody PrinterSyncReq req) {
|
||||
List<PrintTaskResp> tasks = printerService.sync(req);
|
||||
TaskSyncResp resp = new TaskSyncResp();
|
||||
resp.setTasks(tasks);
|
||||
return ApiResponse.success(resp);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{taskId}/success")
|
||||
public ApiResponse taskSuccess(@PathVariable Integer taskId, @RequestBody WorkerAuthReqVo req) {
|
||||
printerService.taskSuccess(taskId, req);
|
||||
return ApiResponse.success("OK");
|
||||
}
|
||||
|
||||
@PostMapping("/{taskId}/fail")
|
||||
public ApiResponse taskFail(@PathVariable Integer taskId, @RequestBody WorkerAuthReqVo req) {
|
||||
printerService.taskFail(taskId, req);
|
||||
return ApiResponse.success("OK");
|
||||
}
|
||||
}
|
@ -7,6 +7,10 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.ycwl.basic.annotation.IgnoreLogReq;
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.annotation.RequestToFile;
|
||||
import com.ycwl.basic.aspectj.HttpSaver;
|
||||
import com.ycwl.basic.facebody.FaceBodyFactory;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||
import com.ycwl.basic.mapper.DeviceMapper;
|
||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||
import com.ycwl.basic.mapper.SourceMapper;
|
||||
@ -19,6 +23,8 @@ import com.ycwl.basic.model.viid.entity.DeviceIdObject;
|
||||
import com.ycwl.basic.model.viid.entity.FaceListObject;
|
||||
import com.ycwl.basic.model.viid.entity.FaceObject;
|
||||
import com.ycwl.basic.model.viid.entity.FacePositionObject;
|
||||
import com.ycwl.basic.model.viid.entity.ImageListObject;
|
||||
import com.ycwl.basic.model.viid.entity.ImageObject;
|
||||
import com.ycwl.basic.model.viid.entity.ResponseStatusObject;
|
||||
import com.ycwl.basic.model.viid.entity.SubImageInfoObject;
|
||||
import com.ycwl.basic.model.viid.entity.SubImageList;
|
||||
@ -32,6 +38,7 @@ import com.ycwl.basic.model.viid.resp.SystemTimeResp;
|
||||
import com.ycwl.basic.model.viid.resp.VIIDBaseResp;
|
||||
import com.ycwl.basic.repository.DeviceRepository;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.service.task.TaskFaceService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
@ -52,6 +59,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@ -59,9 +67,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.ycwl.basic.constant.StorageConstant.PHOTO_PATH;
|
||||
import static com.ycwl.basic.service.task.impl.TaskFaceServiceImpl.generateEntityId;
|
||||
|
||||
@IgnoreToken
|
||||
@RestController
|
||||
@ -78,6 +91,20 @@ public class ViidController {
|
||||
private DeviceRepository deviceRepository;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private TaskFaceService taskFaceService;
|
||||
private final Map<String, ThreadPoolExecutor> executors = new ConcurrentHashMap<>();
|
||||
@Autowired
|
||||
private ScenicService scenicService;
|
||||
|
||||
private ThreadPoolExecutor getExecutor(String deviceId) {
|
||||
ThreadPoolExecutor executor = executors.get(deviceId);
|
||||
if (executor == null) {
|
||||
executor = new ThreadPoolExecutor(4, 4096, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(4096));
|
||||
executors.put(deviceId, executor);
|
||||
}
|
||||
return executor;
|
||||
}
|
||||
|
||||
// region 注册注销基础接口
|
||||
/**
|
||||
@ -194,8 +221,6 @@ public class ViidController {
|
||||
@Autowired
|
||||
private FaceSampleMapper faceSampleMapper;
|
||||
|
||||
@Autowired
|
||||
private TaskFaceService taskFaceService;
|
||||
private final SimpleDateFormat sdfTime = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
|
||||
|
||||
@ -220,10 +245,6 @@ public class ViidController {
|
||||
if (device == null) {
|
||||
continue;
|
||||
}
|
||||
if (!Integer.valueOf(1).equals(device.getStatus())) {
|
||||
log.info("设备状态为关闭,跳过该设备。deviceId:{}", deviceID);
|
||||
continue;
|
||||
}
|
||||
DeviceConfigEntity deviceConfig = deviceRepository.getDeviceConfig(device.getId());
|
||||
int viidMode = 0;
|
||||
if (deviceConfig != null && deviceConfig.getViidType() != null) {
|
||||
@ -255,14 +276,8 @@ public class ViidController {
|
||||
if (scenicId == null) {
|
||||
continue;
|
||||
}
|
||||
IStorageAdapter scenicStorageAdapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
scenicStorageAdapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
scenicStorageAdapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} else {
|
||||
scenicStorageAdapter = StorageFactory.use("video");
|
||||
}
|
||||
IStorageAdapter scenicStorageAdapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
IFaceBodyAdapter faceBodyAdapter = scenicService.getScenicFaceBodyAdapter(scenicId);
|
||||
FacePositionObject facePosition = new FacePositionObject();
|
||||
facePosition.setLtY(face.getLeftTopY());
|
||||
facePosition.setLtX(face.getLeftTopX());
|
||||
@ -284,22 +299,33 @@ public class ViidController {
|
||||
// Type=11 人脸
|
||||
if (subImage.getType().equals("11")) {
|
||||
// 上传oss
|
||||
FaceSampleEntity faceSample = new FaceSampleEntity();
|
||||
Long newFaceSampleId = SnowFlakeUtil.getLongId();
|
||||
faceSample.setId(newFaceSampleId);
|
||||
faceSample.setScenicId(scenicId);
|
||||
faceSample.setDeviceId(device.getId());
|
||||
faceSample.setStatus(0);
|
||||
faceSample.setCreateAt(shotTime);
|
||||
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
||||
faceSample.setFaceUrl(url);
|
||||
faceSampleMapper.add(faceSample);
|
||||
new Thread(() -> {
|
||||
taskFaceService.addFaceSample(faceSample.getId());
|
||||
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
}
|
||||
}).start();
|
||||
if (Integer.valueOf(1).equals(device.getStatus())) {
|
||||
FaceSampleEntity faceSample = new FaceSampleEntity();
|
||||
faceSample.setId(newFaceSampleId);
|
||||
faceSample.setScenicId(scenicId);
|
||||
faceSample.setDeviceId(device.getId());
|
||||
faceSample.setStatus(0);
|
||||
faceSample.setCreateAt(shotTime);
|
||||
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
||||
faceSample.setFaceUrl(url);
|
||||
faceSampleMapper.add(faceSample);
|
||||
ThreadPoolExecutor executor = getExecutor(device.getId().toString());
|
||||
executor.execute(() -> {
|
||||
if (faceBodyAdapter != null) {
|
||||
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
||||
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), generateEntityId(faceSample), url, newFaceSampleId.toString());
|
||||
if (addFaceResp != null) {
|
||||
faceSample.setScore(addFaceResp.getScore());
|
||||
faceSampleMapper.update(faceSample);
|
||||
}
|
||||
}
|
||||
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (SubImageInfoObject _subImage : type14ImageList) {
|
||||
facePosition.setImgHeight(_subImage.getHeight());
|
||||
facePosition.setImgWidth(_subImage.getWidth());
|
||||
@ -334,24 +360,34 @@ public class ViidController {
|
||||
// Type=14 人脸,传™的,有这么传的嘛
|
||||
if (subImage.getType().equals("14")) {
|
||||
// 上传oss
|
||||
FaceSampleEntity faceSample = new FaceSampleEntity();
|
||||
Long newFaceSampleId = SnowFlakeUtil.getLongId();
|
||||
faceSample.setId(newFaceSampleId);
|
||||
faceSample.setScenicId(scenicId);
|
||||
faceSample.setDeviceId(device.getId());
|
||||
faceSample.setStatus(0);
|
||||
faceSample.setCreateAt(shotTime);
|
||||
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
||||
faceSample.setFaceUrl(url);
|
||||
faceSampleMapper.add(faceSample);
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
new Thread(() -> {
|
||||
taskFaceService.addFaceSample(faceSample.getId());
|
||||
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
}
|
||||
}).start();
|
||||
log.info("模式1人脸信息入库成功!设备ID:{}", deviceID);
|
||||
if (Integer.valueOf(1).equals(device.getStatus())) {
|
||||
FaceSampleEntity faceSample = new FaceSampleEntity();
|
||||
Long newFaceSampleId = SnowFlakeUtil.getLongId();
|
||||
faceSample.setId(newFaceSampleId);
|
||||
faceSample.setScenicId(scenicId);
|
||||
faceSample.setDeviceId(device.getId());
|
||||
faceSample.setStatus(0);
|
||||
faceSample.setCreateAt(shotTime);
|
||||
String url = adapter.uploadFile(file, "user-face", UUID.randomUUID() + "." + ext);
|
||||
faceSample.setFaceUrl(url);
|
||||
faceSampleMapper.add(faceSample);
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
ThreadPoolExecutor executor = getExecutor(device.getId().toString());
|
||||
executor.execute(() -> {
|
||||
if (faceBodyAdapter != null) {
|
||||
taskFaceService.assureFaceDb(faceBodyAdapter, scenicId.toString());
|
||||
AddFaceResp addFaceResp = faceBodyAdapter.addFace(scenicId.toString(), generateEntityId(faceSample), url, newFaceSampleId.toString());
|
||||
if (addFaceResp != null) {
|
||||
faceSample.setScore(addFaceResp.getScore());
|
||||
faceSampleMapper.update(faceSample);
|
||||
}
|
||||
}
|
||||
if (deviceConfig != null && Integer.valueOf(1).equals(deviceConfig.getEnablePreBook())) {
|
||||
DynamicTaskGenerator.addTask(faceSample.getId());
|
||||
}
|
||||
});
|
||||
log.info("模式1人脸信息入库成功!设备ID:{}", deviceID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -365,8 +401,9 @@ public class ViidController {
|
||||
|
||||
@RequestMapping(value = "/Images", method = RequestMethod.POST)
|
||||
@IgnoreLogReq
|
||||
public VIIDBaseResp images(@RequestBody ImageUploadReq req) {
|
||||
log.info("Images:{}", req);
|
||||
public VIIDBaseResp images(HttpServletRequest request, @RequestBody ImageUploadReq req) throws IOException {
|
||||
// log.info("Images:{}", req);
|
||||
HttpSaver.saveRequestToFile(request);
|
||||
return new VIIDBaseResp(
|
||||
new ResponseStatusObject("1", "/VIID/Images", "0", "OK", sdfTime.format(new Date()))
|
||||
);
|
||||
|
@ -7,9 +7,11 @@ import com.ycwl.basic.constant.StorageConstant;
|
||||
import com.ycwl.basic.device.entity.common.FileObject;
|
||||
import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
|
||||
import com.ycwl.basic.device.operator.VptPassiveStorageOperator;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
@ -18,6 +20,7 @@ import com.ycwl.basic.utils.ApiResponse;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@ -35,11 +38,8 @@ import java.util.Map;
|
||||
@RequestMapping("/vpt/v1/")
|
||||
public class VptController {
|
||||
|
||||
private final ScenicRepository scenicRepository;
|
||||
|
||||
public VptController(ScenicRepository scenicRepository) {
|
||||
this.scenicRepository = scenicRepository;
|
||||
}
|
||||
@Autowired
|
||||
private ScenicService scenicService;
|
||||
|
||||
@IgnoreLogReq
|
||||
@PostMapping("/scenic/{scenicId}/sync")
|
||||
@ -48,14 +48,7 @@ public class VptController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} else {
|
||||
adapter = StorageFactory.use("video");
|
||||
}
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||
@ -63,14 +56,7 @@ public class VptController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} else {
|
||||
adapter = StorageFactory.use("video");
|
||||
}
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
fileObject.setUrl(adapter.getUrl(filename));
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||
|
@ -10,6 +10,7 @@ import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
|
||||
import com.ycwl.basic.model.wvp.WvpSyncReqVo;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.pc.DeviceService;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
@ -39,7 +40,7 @@ public class WvpController {
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
private ScenicService scenicService;
|
||||
|
||||
@IgnoreLogReq
|
||||
@PostMapping("/scenic/{scenicId}/sync")
|
||||
@ -50,14 +51,7 @@ public class WvpController {
|
||||
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} else {
|
||||
adapter = StorageFactory.use("video");
|
||||
}
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||
@ -65,14 +59,7 @@ public class WvpController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} else {
|
||||
adapter = StorageFactory.use("video");
|
||||
}
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
fileObject.setUrl(adapter.getUrl(filename));
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||
|
@ -76,7 +76,7 @@ public class AliOssStorageOperator extends ADeviceStorageOperator {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(startDate);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd/HHmm");
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
while (calendar.getTime().before(endDate)) {
|
||||
String prefix = dateFormat.format(calendar.getTime());
|
||||
List<FileObject> fileListByPrefix = getOssFileListByPrefix(prefix);
|
||||
|
@ -81,7 +81,7 @@ public class VptPassiveStorageOperator extends ADeviceStorageOperator {
|
||||
log.info("任务{}获取视频开始!共{}", task.taskId, taskList.size());
|
||||
Date taskStartTime = new Date();
|
||||
while (true) {
|
||||
if (new Date().getTime() - taskStartTime.getTime() > 80000L) {
|
||||
if (new Date().getTime() - taskStartTime.getTime() > 60000L) {
|
||||
log.info("任务{}获取视频超时!", task.taskId);
|
||||
fileListMap.remove(task.taskId);
|
||||
return Collections.emptyList();
|
||||
|
@ -75,7 +75,7 @@ public class WvpPassiveStorageOperator extends ADeviceStorageOperator {
|
||||
taskList.add(task);
|
||||
Date taskStartTime = new Date();
|
||||
while (true) {
|
||||
if (new Date().getTime() - taskStartTime.getTime() > 80000L) {
|
||||
if (new Date().getTime() - taskStartTime.getTime() > 60000L) {
|
||||
log.info("任务{}获取视频超时!", task.taskId);
|
||||
fileListMap.remove(task.taskId);
|
||||
return Collections.emptyList();
|
||||
|
@ -74,55 +74,9 @@ public class CustomExceptionHandle {
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
public ApiResponse<String> handle(Exception e) {
|
||||
LOGGER.error("系统异常 -> {}", e.getMessage(), e);
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attributes != null) {
|
||||
try {
|
||||
HttpSaver.saveRequestToFile(attributes.getRequest());
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("保存请求信息失败 -> {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return ApiResponse.buildResult(BizCodeEnum.SERVER_UNKONWN_ERROR);
|
||||
}
|
||||
|
||||
public String getStackTrace(Throwable e) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StackTraceElement[] stackTrace = e.getStackTrace();
|
||||
sb.append(e.getClass().getName()).append(": ").append(e.getMessage()).append("\r\n");
|
||||
for (StackTraceElement stackTraceElement : stackTrace) {
|
||||
sb.append("\tat ").append(stackTraceElement.toString()).append("\r\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getRequestAsText() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attributes == null) {
|
||||
return "---";
|
||||
}
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
StringBuilder rawReq = new StringBuilder();
|
||||
rawReq.append(request.getMethod()).append(" ").append(request.getRequestURL());
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null) {
|
||||
rawReq.append("?").append(queryString);
|
||||
}
|
||||
rawReq.append("\r\n");
|
||||
Enumeration<String> headerNames = request.getHeaderNames();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerName = headerNames.nextElement();
|
||||
rawReq.append(headerName).append(": ").append(request.getHeader(headerName)).append("\r\n");
|
||||
}
|
||||
rawReq.append("\r\n");
|
||||
// 获取body
|
||||
try {
|
||||
rawReq.append(request.getReader().lines().collect(Collectors.joining("\r\n")));
|
||||
rawReq.append("\r\n");
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return rawReq.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动端自定义异常统一处理类
|
||||
*/
|
||||
|
62
src/main/java/com/ycwl/basic/facebody/FaceBodyFactory.java
Normal file
62
src/main/java/com/ycwl/basic/facebody/FaceBodyFactory.java
Normal file
@ -0,0 +1,62 @@
|
||||
package com.ycwl.basic.facebody;
|
||||
|
||||
import com.ycwl.basic.facebody.adapter.AliFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.adapter.BceFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||
import com.ycwl.basic.facebody.exceptions.FaceBodyUnsupportedException;
|
||||
import com.ycwl.basic.storage.exceptions.StorageConfigException;
|
||||
import com.ycwl.basic.storage.exceptions.StorageUndefinedException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FaceBodyFactory {
|
||||
public static IFaceBodyAdapter getAdapter(String typeName) {
|
||||
FaceBodyAdapterType adapterEnum;
|
||||
try {
|
||||
adapterEnum = FaceBodyAdapterType.valueOf(typeName);
|
||||
} catch (Exception e) {
|
||||
throw new FaceBodyUnsupportedException("不支持的Adapter类型");
|
||||
}
|
||||
return getAdapter(adapterEnum);
|
||||
}
|
||||
|
||||
public static IFaceBodyAdapter getAdapter(FaceBodyAdapterType type) {
|
||||
switch (type) {
|
||||
case ALI:
|
||||
return new AliFaceBodyAdapter();
|
||||
case BCE:
|
||||
return new BceFaceBodyAdapter();
|
||||
default:
|
||||
throw new FaceBodyUnsupportedException("不支持的Adapter类型");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static Map<String, IFaceBodyAdapter> namedAdapter = new HashMap<>();
|
||||
protected static IFaceBodyAdapter defaultAdapter = null;
|
||||
|
||||
public static void register(String name, IFaceBodyAdapter adapter) {
|
||||
namedAdapter.put(name, adapter);
|
||||
}
|
||||
|
||||
public static IFaceBodyAdapter use(String name) {
|
||||
IFaceBodyAdapter adapter = namedAdapter.get(name);
|
||||
if (adapter == null) {
|
||||
throw new StorageUndefinedException("未定义的存储方式:"+name);
|
||||
}
|
||||
return adapter;
|
||||
}
|
||||
|
||||
public static IFaceBodyAdapter use() {
|
||||
if (defaultAdapter == null) {
|
||||
throw new StorageConfigException("未定义默认存储方式");
|
||||
}
|
||||
return defaultAdapter;
|
||||
}
|
||||
|
||||
public static void setDefault(String defaultName) {
|
||||
FaceBodyFactory.defaultAdapter = use(defaultName);
|
||||
}
|
||||
}
|
@ -0,0 +1,333 @@
|
||||
package com.ycwl.basic.facebody.adapter;
|
||||
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.facebody.model.v20191230.AddFaceEntityRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.AddFaceRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.AddFaceResponse;
|
||||
import com.aliyuncs.facebody.model.v20191230.CreateFaceDbRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.DeleteFaceDbRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.DeleteFaceEntityRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.ListFaceDbsRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.ListFaceDbsResponse;
|
||||
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.ListFaceEntitiesResponse;
|
||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceRequest;
|
||||
import com.aliyuncs.facebody.model.v20191230.SearchFaceResponse;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||
import com.ycwl.basic.facebody.entity.AliFaceBodyConfig;
|
||||
import com.ycwl.basic.facebody.entity.SearchFaceResp;
|
||||
import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
|
||||
import com.ycwl.basic.utils.ratelimiter.FixedRateLimiter;
|
||||
import com.ycwl.basic.utils.ratelimiter.IRateLimiter;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class AliFaceBodyAdapter implements IFaceBodyAdapter {
|
||||
private static final Map<String, IRateLimiter> addEntityLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> addFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> addDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> listDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> listFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> searchFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> deleteDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> deleteEntityLimiters = new ConcurrentHashMap<>();
|
||||
|
||||
private AliFaceBodyConfig config;
|
||||
|
||||
public boolean setConfig(AliFaceBodyConfig config) {
|
||||
this.config = config;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadConfig(Map<String, String> _config) {
|
||||
AliFaceBodyConfig config = new AliFaceBodyConfig();
|
||||
config.setAccessKeyId(_config.get("accessKeyId"));
|
||||
config.setAccessKeySecret(_config.get("accessKeySecret"));
|
||||
config.setRegion(_config.get("region"));
|
||||
this.config = config;
|
||||
return true;
|
||||
}
|
||||
|
||||
private IRateLimiter getLimiter(LOCK_TYPE type) {
|
||||
switch (type) {
|
||||
case ADD_DB:
|
||||
return addDbLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||
case ADD_ENTITY:
|
||||
return addEntityLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||
case ADD_FACE:
|
||||
return addFaceLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||
case LIST_DB:
|
||||
return listDbLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(500, TimeUnit.MILLISECONDS));
|
||||
case LIST_FACE:
|
||||
return listFaceLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(2));
|
||||
case SEARCH_FACE:
|
||||
return searchFaceLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(200, TimeUnit.MILLISECONDS));
|
||||
case DELETE_DB:
|
||||
return deleteDbLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||
case DELETE_ENTITY:
|
||||
return deleteEntityLimiters.computeIfAbsent(config.getAccessKeyId(), k -> new FixedRateLimiter(600, TimeUnit.MILLISECONDS));
|
||||
default:
|
||||
return new FixedRateLimiter(600, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFaceDb(String dbName) {
|
||||
IRateLimiter addDbLimiter = getLimiter(LOCK_TYPE.ADD_DB);
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
CreateFaceDbRequest request = new CreateFaceDbRequest();
|
||||
request.setName(dbName);
|
||||
try {
|
||||
addDbLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
client.getAcsResponse(request);
|
||||
return true;
|
||||
} catch (ClientException e) {
|
||||
log.error("阿里云添加人脸数据库失败!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFaceDb(String dbName) {
|
||||
ListFaceEntitiesRequest request = new ListFaceEntitiesRequest();
|
||||
IRateLimiter deleteEntityLimiter = getLimiter(LOCK_TYPE.DELETE_ENTITY);
|
||||
IRateLimiter deleteDbLimiter = getLimiter(LOCK_TYPE.DELETE_DB);
|
||||
request.setDbName(dbName);
|
||||
request.setLimit(200);
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
while (true) {
|
||||
ListFaceEntitiesResponse response = client.getAcsResponse(request);
|
||||
if (response.getData().getTotalCount() == 0) {
|
||||
break;
|
||||
}
|
||||
response.getData().getEntities().forEach(entity -> {
|
||||
DeleteFaceEntityRequest deleteFaceEntityRequest = new DeleteFaceEntityRequest();
|
||||
deleteFaceEntityRequest.setDbName(entity.getDbName());
|
||||
deleteFaceEntityRequest.setEntityId(entity.getEntityId());
|
||||
try {
|
||||
deleteEntityLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
client.getAcsResponse(deleteFaceEntityRequest);
|
||||
} catch (ClientException e) {
|
||||
log.error("删除人脸数据失败!", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
DeleteFaceDbRequest deleteFaceDbRequest = new DeleteFaceDbRequest();
|
||||
deleteFaceDbRequest.setName(dbName);
|
||||
try {
|
||||
deleteDbLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
client.getAcsResponse(deleteFaceDbRequest);
|
||||
} catch (ClientException e) {
|
||||
log.error("删除人脸数据库失败!", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listFaceDb() {
|
||||
ListFaceDbsRequest request = new ListFaceDbsRequest();
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
ListFaceDbsResponse response = client.getAcsResponse(request);
|
||||
return response.getData().getDbList().stream().map(ListFaceDbsResponse.Data.DbListItem::getName).collect(Collectors.toList());
|
||||
} catch (ClientException e) {
|
||||
log.error("获取人脸数据库失败!", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddFaceResp addFace(String dbName, String entityId, String faceUrl, String extData) {
|
||||
IRateLimiter addEntityLimiter = getLimiter(LOCK_TYPE.ADD_ENTITY);
|
||||
IRateLimiter addFaceLimiter = getLimiter(LOCK_TYPE.ADD_FACE);
|
||||
AddFaceEntityRequest request = new AddFaceEntityRequest();
|
||||
request.setDbName(dbName);
|
||||
request.setEntityId(entityId);
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
try {
|
||||
addEntityLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
client.getAcsResponse(request);
|
||||
} catch (ClientException e) {
|
||||
log.error("addFaceEntity, {}/{}", dbName, entityId, e);
|
||||
return null;
|
||||
}
|
||||
AddFaceRequest addFaceRequest = new AddFaceRequest();
|
||||
addFaceRequest.setDbName(dbName);
|
||||
addFaceRequest.setEntityId(entityId);
|
||||
addFaceRequest.setImageUrl(faceUrl);
|
||||
addFaceRequest.setExtraData(extData);
|
||||
AddFaceResp respVo = new AddFaceResp();
|
||||
try {
|
||||
addFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
AddFaceResponse acsResponse = client.getAcsResponse(addFaceRequest);
|
||||
respVo.setScore(acsResponse.getData().getQualitieScore());
|
||||
return respVo;
|
||||
} catch (ClientException e) {
|
||||
log.error("addFace, {}/{}", dbName, entityId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFace(String dbName, String entityId) {
|
||||
IRateLimiter deleteEntityLimiter = getLimiter(LOCK_TYPE.DELETE_ENTITY);
|
||||
DeleteFaceEntityRequest request = new DeleteFaceEntityRequest();
|
||||
request.setDbName(dbName);
|
||||
request.setEntityId(entityId);
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
try {
|
||||
deleteEntityLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
client.getAcsResponse(request);
|
||||
return true;
|
||||
} catch (ClientException e) {
|
||||
log.error("删除人脸数据失败!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listFace(String dbName, String prefix, Integer offset, Integer size) {
|
||||
IRateLimiter listFaceLimiter = getLimiter(LOCK_TYPE.LIST_FACE);
|
||||
ListFaceEntitiesRequest listFaceEntitiesRequest = new ListFaceEntitiesRequest();
|
||||
listFaceEntitiesRequest.setDbName(dbName);
|
||||
listFaceEntitiesRequest.setOrder("asc");
|
||||
if (offset != null) {
|
||||
listFaceEntitiesRequest.setOffset(offset);
|
||||
}
|
||||
if (size != null) {
|
||||
listFaceEntitiesRequest.setLimit(size);
|
||||
} else {
|
||||
listFaceEntitiesRequest.setLimit(200);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(prefix)) {
|
||||
listFaceEntitiesRequest.setEntityIdPrefix(prefix);
|
||||
}
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
try {
|
||||
listFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
ListFaceEntitiesResponse response = client.getAcsResponse(listFaceEntitiesRequest);
|
||||
return response.getData().getEntities().stream().map(ListFaceEntitiesResponse.Data.Entity::getEntityId).collect(Collectors.toList());
|
||||
} catch (ClientException e) {
|
||||
log.error("获取人脸数据失败!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchFaceResp searchFace(String dbName, String faceUrl) {
|
||||
SearchFaceResp resp = new SearchFaceResp();
|
||||
IRateLimiter searchFaceLimiter = getLimiter(LOCK_TYPE.SEARCH_FACE);
|
||||
try (ClientWrapper clientWrapper = getClient()) {
|
||||
IAcsClient client = clientWrapper.getClient();
|
||||
SearchFaceRequest request = new SearchFaceRequest();
|
||||
request.setDbName(dbName);
|
||||
request.setImageUrl(faceUrl);
|
||||
request.setLimit(100);
|
||||
try {
|
||||
searchFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
try {
|
||||
SearchFaceResponse response = client.getAcsResponse(request);
|
||||
List<SearchFaceResponse.Data.MatchListItem> matchList = response.getData().getMatchList();
|
||||
if (matchList.isEmpty()) {
|
||||
resp.setOriginalFaceScore(0f);
|
||||
return resp;
|
||||
}
|
||||
SearchFaceResponse.Data.MatchListItem matchItem = matchList.get(0);
|
||||
resp.setOriginalFaceScore(matchItem.getQualitieScore());
|
||||
resp.setResult(matchItem.getFaceItems().stream().map(item -> {
|
||||
SearchFaceResultItem resultItem = new SearchFaceResultItem();
|
||||
resultItem.setDbName(dbName);
|
||||
resultItem.setFaceId(item.getFaceId());
|
||||
resultItem.setExtData(item.getExtraData());
|
||||
resultItem.setScore(item.getScore());
|
||||
return resultItem;
|
||||
}).collect(Collectors.toList()));
|
||||
if (!resp.getResult().isEmpty()) {
|
||||
resp.setFirstMatchRate(resp.getResult().get(0).getScore());
|
||||
}
|
||||
return resp;
|
||||
} catch (ClientException e) {
|
||||
log.error("搜索人脸失败!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ClientWrapper getClient() {
|
||||
DefaultProfile profile = DefaultProfile.getProfile(
|
||||
config.getRegion(), config.getAccessKeyId(), config.getAccessKeySecret());
|
||||
IAcsClient client = new DefaultAcsClient(profile);
|
||||
return new ClientWrapper(client);
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class ClientWrapper implements AutoCloseable {
|
||||
private final IAcsClient client;
|
||||
|
||||
public ClientWrapper(IAcsClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (client == null) {
|
||||
return;
|
||||
}
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
protected enum LOCK_TYPE {
|
||||
ADD_DB,
|
||||
ADD_ENTITY,
|
||||
ADD_FACE,
|
||||
LIST_DB,
|
||||
LIST_FACE,
|
||||
SEARCH_FACE,
|
||||
DELETE_DB,
|
||||
DELETE_ENTITY,
|
||||
}
|
||||
}
|
@ -0,0 +1,358 @@
|
||||
package com.ycwl.basic.facebody.adapter;
|
||||
|
||||
import com.baidu.aip.face.AipFace;
|
||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||
import com.ycwl.basic.facebody.entity.AliFaceBodyConfig;
|
||||
import com.ycwl.basic.facebody.entity.BceFaceBodyConfig;
|
||||
import com.ycwl.basic.facebody.entity.SearchFaceResp;
|
||||
import com.ycwl.basic.facebody.entity.SearchFaceResultItem;
|
||||
import com.ycwl.basic.utils.ratelimiter.FixedRateLimiter;
|
||||
import com.ycwl.basic.utils.ratelimiter.IRateLimiter;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class BceFaceBodyAdapter implements IFaceBodyAdapter {
|
||||
protected static final Map<String, AipFace> clients = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> addEntityLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> addFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> addDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> listDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> listFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> searchFaceLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> deleteDbLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> deleteEntityLimiters = new ConcurrentHashMap<>();
|
||||
private static final Map<String, IRateLimiter> deleteFaceLimiters = new ConcurrentHashMap<>();
|
||||
private BceFaceBodyConfig config;
|
||||
|
||||
public boolean setConfig(BceFaceBodyConfig config) {
|
||||
this.config = config;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadConfig(Map<String, String> _config) {
|
||||
BceFaceBodyConfig config = new BceFaceBodyConfig();
|
||||
config.setAppId(_config.get("appId"));
|
||||
config.setApiKey(_config.get("apiKey"));
|
||||
config.setSecretKey(_config.get("secretKey"));
|
||||
config.setAddQps(Float.parseFloat(_config.get("addQps")));
|
||||
config.setSearchQps(Float.parseFloat(_config.get("searchQps")));
|
||||
this.config = config;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addFaceDb(String dbName) {
|
||||
IRateLimiter addDbLimiter = getLimiter(LOCK_TYPE.ADD_DB);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
try {
|
||||
addDbLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.groupAdd(dbName, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
return true;
|
||||
} else {
|
||||
log.warn("创建人脸库失败!{}", response);
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("创建人脸库失败!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFaceDb(String dbName) {
|
||||
IRateLimiter deleteDbLimiter = getLimiter(LOCK_TYPE.DELETE_DB);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
try {
|
||||
deleteDbLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.groupDelete(dbName, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
return true;
|
||||
} else {
|
||||
log.warn("删除人脸库失败!{}", response);
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("删除人脸库失败!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listFaceDb() {
|
||||
IRateLimiter listDbLimiter = getLimiter(LOCK_TYPE.LIST_DB);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put("start", "0");
|
||||
options.put("length", "1000");
|
||||
try {
|
||||
listDbLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.getGroupList(options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
JSONObject resultObj = response.getJSONObject("result");
|
||||
if (resultObj != null) {
|
||||
JSONArray data = resultObj.getJSONArray("group_id_list");
|
||||
List<String> result = new ArrayList<>();
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
result.add(data.getString(i));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else {
|
||||
log.warn("获取人脸库列表失败!{}", response);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取人脸库列表失败!", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddFaceResp addFace(String dbName, String entityId, String faceUrl, String extData) {
|
||||
IRateLimiter addEntityLimiter = getLimiter(LOCK_TYPE.ADD_FACE);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put("user_info", extData);
|
||||
// options.put("quality_control", "LOW");
|
||||
options.put("action_type", "REPLACE");
|
||||
try {
|
||||
addEntityLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.addUser(faceUrl, "URL", dbName, entityId, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
AddFaceResp resp = new AddFaceResp();
|
||||
resp.setScore(100f);
|
||||
return resp;
|
||||
} else {
|
||||
log.warn("创建人脸失败!{}", response);
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("创建人脸失败!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFace(String dbName, String entityId) {
|
||||
IRateLimiter deleteFaceLimiter = getLimiter(LOCK_TYPE.DELETE_FACE);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
List<String> tokenList = listUserFace(dbName, entityId);
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
tokenList.forEach(faceToken -> {
|
||||
try {
|
||||
try {
|
||||
deleteFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.faceDelete(entityId, dbName, faceToken, options);
|
||||
if (response.getInt("error_code") != 0) {
|
||||
log.warn("删除人脸失败!{}", response);
|
||||
} else {
|
||||
count.incrementAndGet();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("删除人脸失败!", e);
|
||||
}
|
||||
});
|
||||
return Integer.valueOf(count.get()).equals(tokenList.size());
|
||||
} catch (Exception e) {
|
||||
log.error("删除人脸失败!", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listFace(String dbName, String prefix, Integer offset, Integer size) {
|
||||
IRateLimiter listFaceLimiter = getLimiter(LOCK_TYPE.LIST_FACE);
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put("start", offset == null ? "0" : offset.toString());
|
||||
options.put("length", size == null ? "1000" : size.toString());
|
||||
try {
|
||||
listFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.getGroupUsers(dbName, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
JSONObject resultObj = response.getJSONObject("result");
|
||||
if (resultObj != null) {
|
||||
JSONArray data = resultObj.getJSONArray("user_id_list");
|
||||
List<String> result = new ArrayList<>();
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
result.add(data.getString(i));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else {
|
||||
log.warn("获取人脸列表失败!{}", response);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取人脸列表失败!", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> listUserFace(String dbName, String entityId) {
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
JSONObject response = client.faceGetlist(entityId, dbName, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
JSONObject resultObj = response.getJSONObject("result");
|
||||
if (resultObj != null) {
|
||||
JSONArray faceList = resultObj.getJSONArray("face_list");
|
||||
List<String> result = new ArrayList<>();
|
||||
for (int i = 0; i < faceList.length(); i++) {
|
||||
JSONObject jsonObject = faceList.getJSONObject(i);
|
||||
result.add(jsonObject.getString("face_token"));
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} else {
|
||||
log.warn("获取人脸列表失败!{}", response);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取人脸列表失败!", e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchFaceResp searchFace(String dbName, String faceUrl) {
|
||||
IRateLimiter searchFaceLimiter = getLimiter(LOCK_TYPE.SEARCH_FACE);
|
||||
SearchFaceResp resp = new SearchFaceResp();
|
||||
try {
|
||||
AipFace client = getClient();
|
||||
HashMap<String, Object> options = new HashMap<>();
|
||||
options.put("quality_control", "LOW");
|
||||
options.put("max_user_num", "50");
|
||||
try {
|
||||
searchFaceLimiter.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
JSONObject response = client.search(faceUrl, "URL", dbName, options);
|
||||
if (response.getInt("error_code") == 0) {
|
||||
resp.setOriginalFaceScore(100f);
|
||||
JSONObject resultObj = response.getJSONObject("result");
|
||||
if (resultObj == null) {
|
||||
resp.setFirstMatchRate(0f);
|
||||
return resp;
|
||||
}
|
||||
JSONArray userList = resultObj.getJSONArray("user_list");
|
||||
List<SearchFaceResultItem> result = new ArrayList<>();
|
||||
for (int i = 0; i < userList.length(); i++) {
|
||||
JSONObject user = userList.getJSONObject(i);
|
||||
SearchFaceResultItem item = new SearchFaceResultItem();
|
||||
item.setDbName(dbName);
|
||||
item.setFaceId(user.getString("user_id"));
|
||||
item.setExtData(user.getString("user_info"));
|
||||
item.setScore(user.getBigDecimal("score").divide(BigDecimal.valueOf(100), 6, RoundingMode.HALF_UP).floatValue());
|
||||
result.add(item);
|
||||
}
|
||||
resp.setResult(result);
|
||||
if (!result.isEmpty()) {
|
||||
resp.setFirstMatchRate(result.get(0).getScore());
|
||||
}
|
||||
return resp;
|
||||
} else {
|
||||
resp.setOriginalFaceScore(0f);
|
||||
return resp;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("搜索人脸失败!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AipFace getClient() {
|
||||
if (clients.containsKey(config.getAppId())) {
|
||||
return clients.get(config.getAppId());
|
||||
}
|
||||
synchronized (clients) {
|
||||
if (clients.containsKey(config.getAppId())) {
|
||||
return clients.get(config.getAppId());
|
||||
}
|
||||
AipFace client = new AipFace(config.getAppId(), config.getApiKey(), config.getSecretKey());
|
||||
client.setConnectionTimeoutInMillis(5000);
|
||||
client.setSocketTimeoutInMillis(60000);
|
||||
clients.put(config.getAppId(), client);
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
private IRateLimiter getLimiter(LOCK_TYPE type) {
|
||||
switch (type) {
|
||||
case ADD_DB:
|
||||
return addDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
case ADD_FACE:
|
||||
return addFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getAddQps()));
|
||||
case LIST_DB:
|
||||
return listDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
case LIST_FACE:
|
||||
return listFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
case SEARCH_FACE:
|
||||
return searchFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(config.getSearchQps()));
|
||||
case DELETE_DB:
|
||||
return deleteDbLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
case DELETE_ENTITY:
|
||||
return deleteEntityLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
case DELETE_FACE:
|
||||
return deleteFaceLimiters.computeIfAbsent(config.getAppId(), k -> new FixedRateLimiter(100, TimeUnit.MILLISECONDS));
|
||||
default:
|
||||
return new FixedRateLimiter(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
protected enum LOCK_TYPE {
|
||||
ADD_DB,
|
||||
ADD_FACE,
|
||||
LIST_DB,
|
||||
LIST_FACE,
|
||||
SEARCH_FACE,
|
||||
DELETE_DB,
|
||||
DELETE_ENTITY,
|
||||
DELETE_FACE,
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.ycwl.basic.facebody.adapter;
|
||||
|
||||
import com.ycwl.basic.facebody.entity.AddFaceResp;
|
||||
import com.ycwl.basic.facebody.entity.SearchFaceResp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IFaceBodyAdapter {
|
||||
boolean loadConfig(Map<String, String> _config);
|
||||
|
||||
default boolean assureFaceDb(String dbName) {
|
||||
List<String> faceDbs = listFaceDb();
|
||||
return faceDbs.contains(dbName) || addFaceDb(dbName);
|
||||
}
|
||||
|
||||
boolean addFaceDb(String dbName);
|
||||
boolean deleteFaceDb(String dbName);
|
||||
|
||||
List<String> listFaceDb();
|
||||
|
||||
AddFaceResp addFace(String dbName, String entityId, String faceUrl, String extData);
|
||||
|
||||
boolean deleteFace(String dbName, String entityId);
|
||||
|
||||
List<String> listFace(String dbName, String prefix, Integer offset, Integer size);
|
||||
|
||||
SearchFaceResp searchFace(String dbName, String faceUrl);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.ycwl.basic.facebody.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AddFaceResp {
|
||||
private Float score;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.ycwl.basic.facebody.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AliFaceBodyConfig {
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String region;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.facebody.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BceFaceBodyConfig {
|
||||
private String appId;
|
||||
private String apiKey;
|
||||
private String secretKey;
|
||||
private float addQps = 2.0f;
|
||||
private float searchQps = 2.0f;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.facebody.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SearchFaceResp {
|
||||
private Float originalFaceScore;
|
||||
private List<SearchFaceResultItem> result = new ArrayList<>();
|
||||
private Float firstMatchRate;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.facebody.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SearchFaceResultItem {
|
||||
private String dbName;
|
||||
private String faceId;
|
||||
private String extData;
|
||||
/** 置信度,0~1 */
|
||||
private Float score;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.ycwl.basic.facebody.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum FaceBodyAdapterType {
|
||||
ALI("ALI"),
|
||||
BCE("BCE"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
|
||||
FaceBodyAdapterType(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.ycwl.basic.facebody.exceptions;
|
||||
|
||||
public class FaceBodyException extends RuntimeException {
|
||||
public FaceBodyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.ycwl.basic.facebody.exceptions;
|
||||
|
||||
public class FaceBodyUnsupportedException extends RuntimeException {
|
||||
public FaceBodyUnsupportedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.ycwl.basic.facebody.starter;
|
||||
|
||||
import com.ycwl.basic.facebody.FaceBodyFactory;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
import com.ycwl.basic.facebody.starter.config.FaceBodyConfig;
|
||||
import com.ycwl.basic.facebody.starter.config.OverallFaceBodyConfig;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class FaceBodyAutoConfiguration {
|
||||
private final OverallFaceBodyConfig config;
|
||||
public FaceBodyAutoConfiguration(OverallFaceBodyConfig config) {
|
||||
this.config = config;
|
||||
if (config != null) {
|
||||
if (config.getConfigs() != null) {
|
||||
loadConfig();
|
||||
}
|
||||
if (StringUtils.isNotBlank(config.getDefaultUse())) {
|
||||
FaceBodyFactory.setDefault(config.getDefaultUse());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
for (FaceBodyConfig item : config.getConfigs()) {
|
||||
IFaceBodyAdapter adapter = FaceBodyFactory.getAdapter(item.getType());
|
||||
adapter.loadConfig(item.getConfig());
|
||||
FaceBodyFactory.register(item.getName(), adapter);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.facebody.starter.config;
|
||||
|
||||
import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class FaceBodyConfig {
|
||||
private String name;
|
||||
private FaceBodyAdapterType type;
|
||||
private Map<String, String> config;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.ycwl.basic.facebody.starter.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "facebody")
|
||||
@Data
|
||||
public class OverallFaceBodyConfig {
|
||||
private String defaultUse;
|
||||
private List<FaceBodyConfig> configs;
|
||||
}
|
21
src/main/java/com/ycwl/basic/filter/RequestCacheFilter.java
Normal file
21
src/main/java/com/ycwl/basic/filter/RequestCacheFilter.java
Normal file
@ -0,0 +1,21 @@
|
||||
package com.ycwl.basic.filter;
|
||||
|
||||
import com.ycwl.basic.config.CachedBodyHttpServletRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class RequestCacheFilter implements Filter {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
// 包装原始请求
|
||||
HttpServletRequestWrapper wrappedRequest = new CachedBodyHttpServletRequest((HttpServletRequest) request);
|
||||
// 继续处理请求链
|
||||
chain.doFilter(wrappedRequest, response);
|
||||
}
|
||||
}
|
4
src/main/java/com/ycwl/basic/image/util/ImageUtil.java
Normal file
4
src/main/java/com/ycwl/basic/image/util/ImageUtil.java
Normal file
@ -0,0 +1,4 @@
|
||||
package com.ycwl.basic.image.util;
|
||||
|
||||
public class ImageUtil {
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.ycwl.basic.image.watermark;
|
||||
|
||||
import com.ycwl.basic.image.watermark.enums.ImageWatermarkOperatorEnum;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkUnsupportedException;
|
||||
import com.ycwl.basic.image.watermark.operator.IOperator;
|
||||
import com.ycwl.basic.image.watermark.operator.DefaultImageWatermarkOperator;
|
||||
import com.ycwl.basic.image.watermark.operator.LeicaWatermarkOperator;
|
||||
import com.ycwl.basic.image.watermark.operator.NormalWatermarkOperator;
|
||||
|
||||
public class ImageWatermarkFactory {
|
||||
public static IOperator get(String watermarkType) {
|
||||
ImageWatermarkOperatorEnum type = ImageWatermarkOperatorEnum.getByCode(watermarkType);
|
||||
if (type == null) {
|
||||
throw new ImageWatermarkUnsupportedException(watermarkType);
|
||||
}
|
||||
return get(type);
|
||||
}
|
||||
public static IOperator get(ImageWatermarkOperatorEnum type) {
|
||||
switch (type) {
|
||||
case WATERMARK:
|
||||
return new DefaultImageWatermarkOperator();
|
||||
case NORMAL:
|
||||
return new NormalWatermarkOperator();
|
||||
case LEICA:
|
||||
return new LeicaWatermarkOperator();
|
||||
default:
|
||||
throw new ImageWatermarkUnsupportedException("不支持的类型"+type.name());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.ycwl.basic.image.watermark.entity;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class WatermarkInfo {
|
||||
private File originalFile;
|
||||
/**
|
||||
* 输出文件
|
||||
*/
|
||||
private File watermarkedFile;
|
||||
private File qrcodeFile;
|
||||
private String scenicLine;
|
||||
private String secondLine;
|
||||
private String thirdLine;
|
||||
private String fourthLine;
|
||||
private Date datetime;
|
||||
private String dtFormat;
|
||||
private String datetimeLine;
|
||||
|
||||
public String getDatetimeLine() {
|
||||
if (datetimeLine == null) {
|
||||
datetimeLine = DateUtil.format(datetime, dtFormat);
|
||||
}
|
||||
return datetimeLine;
|
||||
}
|
||||
|
||||
public String getScenicLine() {
|
||||
if (scenicLine == null) {
|
||||
scenicLine = "";
|
||||
}
|
||||
return scenicLine;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.ycwl.basic.image.watermark.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ImageWatermarkOperatorEnum {
|
||||
WATERMARK("defW", "jpg"),
|
||||
LEICA("leica", "png"),
|
||||
NORMAL("normal", "png");
|
||||
|
||||
private final String type;
|
||||
private final String preferFileType;
|
||||
|
||||
ImageWatermarkOperatorEnum(String type, String preferFileType) {
|
||||
this.type = type;
|
||||
this.preferFileType = preferFileType;
|
||||
}
|
||||
|
||||
public static ImageWatermarkOperatorEnum getByCode(String type) {
|
||||
for (ImageWatermarkOperatorEnum imageWatermarkOperatorEnum : ImageWatermarkOperatorEnum.values()) {
|
||||
if (imageWatermarkOperatorEnum.type.equals(type)) {
|
||||
return imageWatermarkOperatorEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.ycwl.basic.image.watermark.exception;
|
||||
|
||||
public class ImageWatermarkException extends RuntimeException {
|
||||
public ImageWatermarkException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.ycwl.basic.image.watermark.exception;
|
||||
|
||||
public class ImageWatermarkUnsupportedException extends ImageWatermarkException {
|
||||
public ImageWatermarkUnsupportedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.ycwl.basic.image.watermark.operator;
|
||||
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
public class DefaultImageWatermarkOperator implements IOperator {
|
||||
@Override
|
||||
public File process(WatermarkInfo info) throws ImageWatermarkException {
|
||||
BufferedImage baseImage;
|
||||
BufferedImage watermarkImage;
|
||||
InputStream logoInputStream = getClass().getResourceAsStream("/watermark.png");
|
||||
if (logoInputStream == null) {
|
||||
throw new ImageWatermarkException("无法找到 watermark.png 资源文件");
|
||||
}
|
||||
try {
|
||||
baseImage = ImageIO.read(info.getOriginalFile());
|
||||
watermarkImage = ImageIO.read(logoInputStream);
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片打开失败");
|
||||
}
|
||||
// 新图像画布
|
||||
BufferedImage newImage = new BufferedImage(baseImage.getWidth(), baseImage.getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = newImage.createGraphics();
|
||||
g2d.drawImage(baseImage, 0, 0, null);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
|
||||
g2d.drawImage(watermarkImage, 0, 0, baseImage.getWidth(), baseImage.getHeight(), null);
|
||||
String fileName = info.getWatermarkedFile().getName();
|
||||
String formatName = "jpg"; // 默认格式为 jpg
|
||||
if (fileName.endsWith(".png")) {
|
||||
formatName = "png";
|
||||
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
||||
formatName = "jpg";
|
||||
}
|
||||
ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next();
|
||||
ImageOutputStream ios;
|
||||
try {
|
||||
ios = ImageIO.createImageOutputStream(info.getWatermarkedFile());
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败,目标文件无法写入");
|
||||
}
|
||||
writer.setOutput(ios);
|
||||
try {
|
||||
// 使用 ImageWriter 设置写入质量
|
||||
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||
if (writeParam.canWriteCompressed()) {
|
||||
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
writeParam.setCompressionQuality(0.8f); // 设置写入质量为 80%
|
||||
}
|
||||
writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam);
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败");
|
||||
}
|
||||
finally {
|
||||
g2d.dispose();
|
||||
try {
|
||||
ios.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
writer.dispose();
|
||||
}
|
||||
return info.getWatermarkedFile();
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.ycwl.basic.image.watermark.operator;
|
||||
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface IOperator {
|
||||
File process(WatermarkInfo info) throws ImageWatermarkException;
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
package com.ycwl.basic.image.watermark.operator;
|
||||
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 徕卡水印
|
||||
*/
|
||||
@Slf4j
|
||||
public class LeicaWatermarkOperator implements IOperator {
|
||||
private static final String FONT_PATH = "/PingFang_SC.ttf";
|
||||
public static String defaultFontName;
|
||||
public static float FONT_GLOBAL_OFFSET_PERCENT = 0;
|
||||
static {
|
||||
try {
|
||||
// 加载字体文件流
|
||||
InputStream fontStream = LeicaWatermarkOperator.class.getResourceAsStream(FONT_PATH);
|
||||
if (fontStream == null) {
|
||||
throw new RuntimeException("字体文件未找到!路径:" + FONT_PATH);
|
||||
}
|
||||
|
||||
// 创建字体对象
|
||||
Font customFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
|
||||
|
||||
// 注册字体到系统
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
ge.registerFont(customFont);
|
||||
|
||||
// 更新默认字体名称为新字体的逻辑名称
|
||||
defaultFontName = customFont.getName(); // 如 "PingFang SC"
|
||||
FONT_GLOBAL_OFFSET_PERCENT = -0.3f;
|
||||
} catch (FontFormatException | IOException e) {
|
||||
log.error("加载字体文件失败", e);
|
||||
defaultFontName = "宋体";
|
||||
}
|
||||
}
|
||||
public static int EXTRA_BOTTOM_PX = 140;
|
||||
public static int EXTRA_BORDER_PX = 0;
|
||||
public static Color BG_COLOR = Color.WHITE;
|
||||
public static int LOGO_SIZE = 50;
|
||||
public static int LOGO_EXTRA_BORDER = 20;
|
||||
public static int LOGO_FONT_SIZE = 38;
|
||||
public static Color logoTextColor = new Color(0x33, 0x33, 0x33);
|
||||
public static int QRCODE_SIZE = 80;
|
||||
public static int QRCODE_OFFSET_X = 5;
|
||||
public static int OFFSET_X = 80;
|
||||
public static int OFFSET_Y = 30;
|
||||
public static int SCENIC_FONT_SIZE = 32;
|
||||
public static Color scenicColor = new Color(0x33, 0x33, 0x33);
|
||||
public static int DATETIME_FONT_SIZE = 28;
|
||||
public static Color datetimeColor = new Color(0x99, 0x99, 0x99);
|
||||
|
||||
@Override
|
||||
public File process(WatermarkInfo info) throws ImageWatermarkException {
|
||||
BufferedImage baseImage;
|
||||
BufferedImage qrcodeImage;
|
||||
BufferedImage logoImage;
|
||||
// 从类路径加载 zt-logo.png
|
||||
InputStream logoInputStream = getClass().getResourceAsStream("/zt-logo.png");
|
||||
if (logoInputStream == null) {
|
||||
throw new ImageWatermarkException("无法找到 zt-logo.png 资源文件");
|
||||
}
|
||||
try {
|
||||
baseImage = ImageIO.read(info.getOriginalFile());
|
||||
qrcodeImage = ImageIO.read(info.getQrcodeFile());
|
||||
logoImage = ImageIO.read(logoInputStream);
|
||||
logoInputStream.close();
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片打开失败");
|
||||
}
|
||||
// 新图像画布
|
||||
BufferedImage newImage = new BufferedImage(baseImage.getWidth() + 2 * EXTRA_BORDER_PX, baseImage.getHeight() + 2 * EXTRA_BORDER_PX + EXTRA_BOTTOM_PX, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = newImage.createGraphics();
|
||||
g2d.setColor(BG_COLOR);
|
||||
g2d.fillRect(0, 0, newImage.getWidth(), newImage.getHeight());
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.drawImage(baseImage, EXTRA_BORDER_PX, EXTRA_BORDER_PX, null);
|
||||
int logoHeight = LOGO_SIZE;
|
||||
int logoWidth = (int) (logoHeight * 1.0 / logoImage.getHeight() * logoImage.getWidth());
|
||||
g2d.drawImage(logoImage, EXTRA_BORDER_PX + OFFSET_X, EXTRA_BORDER_PX + baseImage.getHeight() + OFFSET_Y + LOGO_EXTRA_BORDER, logoWidth, logoHeight, null);
|
||||
Font logoTextFont = new Font(defaultFontName, Font.PLAIN, LOGO_FONT_SIZE);
|
||||
g2d.setFont(logoTextFont);
|
||||
g2d.setColor(logoTextColor);
|
||||
FontMetrics logoFontMetrics = g2d.getFontMetrics(logoTextFont);
|
||||
int logoTextHeight = logoFontMetrics.getHeight();
|
||||
int logoTextOffsetY = (LOGO_SIZE - logoHeight) / 2;
|
||||
g2d.drawString("帧途", EXTRA_BORDER_PX + OFFSET_X + logoWidth + 5, EXTRA_BORDER_PX + baseImage.getHeight() + OFFSET_Y + logoTextHeight + LOGO_EXTRA_BORDER + logoTextOffsetY + logoTextHeight * FONT_GLOBAL_OFFSET_PERCENT);
|
||||
int newQrcodeHeight = QRCODE_SIZE;
|
||||
int newQrcodeWidth = (int) (newQrcodeHeight * 1.0 / qrcodeImage.getHeight() * qrcodeImage.getWidth());
|
||||
Font scenicFont = new Font(defaultFontName, Font.PLAIN, SCENIC_FONT_SIZE);
|
||||
Font datetimeFont = new Font(defaultFontName, Font.PLAIN, DATETIME_FONT_SIZE);
|
||||
FontMetrics scenicFontMetrics = g2d.getFontMetrics(scenicFont);
|
||||
FontMetrics datetimeFontMetrics = g2d.getFontMetrics(datetimeFont);
|
||||
int scenicLineHeight = scenicFontMetrics.getHeight();
|
||||
int dtLineHeight = datetimeFontMetrics.getHeight();
|
||||
int scenicLineWidth = scenicFontMetrics.stringWidth(info.getScenicLine());
|
||||
int datetimeLineWidth = scenicFontMetrics.stringWidth(info.getDatetimeLine());
|
||||
g2d.drawImage(qrcodeImage, newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - newQrcodeWidth - QRCODE_OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + + OFFSET_Y, newQrcodeWidth, newQrcodeHeight, null);
|
||||
g2d.setFont(scenicFont);
|
||||
g2d.setColor(scenicColor);
|
||||
g2d.drawString(info.getScenicLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + + OFFSET_Y + scenicLineHeight + scenicLineHeight * FONT_GLOBAL_OFFSET_PERCENT);
|
||||
g2d.setFont(datetimeFont);
|
||||
g2d.setColor(datetimeColor);
|
||||
g2d.drawString(info.getDatetimeLine(), newImage.getWidth() + EXTRA_BORDER_PX - OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth), EXTRA_BORDER_PX + baseImage.getHeight() + + OFFSET_Y + scenicLineHeight + dtLineHeight + dtLineHeight * FONT_GLOBAL_OFFSET_PERCENT);
|
||||
String fileName = info.getWatermarkedFile().getName();
|
||||
String formatName = "jpg"; // 默认格式为 jpg
|
||||
if (fileName.endsWith(".png")) {
|
||||
formatName = "png";
|
||||
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
||||
formatName = "jpg";
|
||||
}
|
||||
ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next();
|
||||
ImageOutputStream ios;
|
||||
try {
|
||||
ios = ImageIO.createImageOutputStream(info.getWatermarkedFile());
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败,目标文件无法写入");
|
||||
}
|
||||
writer.setOutput(ios);
|
||||
try {
|
||||
// 使用 ImageWriter 设置写入质量
|
||||
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||
if (writeParam.canWriteCompressed()) {
|
||||
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
writeParam.setCompressionQuality(0.95f); // 设置写入质量为 95%
|
||||
}
|
||||
writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam);
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败");
|
||||
}
|
||||
finally {
|
||||
g2d.dispose();
|
||||
try {
|
||||
ios.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
writer.dispose();
|
||||
}
|
||||
return info.getWatermarkedFile();
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package com.ycwl.basic.image.watermark.operator;
|
||||
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
public class NormalWatermarkOperator implements IOperator {
|
||||
private static final String FONT_PATH = "/PingFang_SC.ttf";
|
||||
public static String defaultFontName;
|
||||
public static float FONT_GLOBAL_OFFSET_PERCENT = 0;
|
||||
static {
|
||||
try {
|
||||
// 加载字体文件流
|
||||
InputStream fontStream = LeicaWatermarkOperator.class.getResourceAsStream(FONT_PATH);
|
||||
if (fontStream == null) {
|
||||
throw new RuntimeException("字体文件未找到!路径:" + FONT_PATH);
|
||||
}
|
||||
|
||||
// 创建字体对象
|
||||
Font customFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
|
||||
|
||||
// 注册字体到系统
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
ge.registerFont(customFont);
|
||||
|
||||
// 更新默认字体名称为新字体的逻辑名称
|
||||
defaultFontName = customFont.getName(); // 如 "PingFang SC"
|
||||
FONT_GLOBAL_OFFSET_PERCENT = -0.3f;
|
||||
} catch (FontFormatException | IOException e) {
|
||||
log.error("加载字体文件失败", e);
|
||||
defaultFontName = "宋体";
|
||||
}
|
||||
}
|
||||
public static int EXTRA_BORDER_PX = 0;
|
||||
public static int OFFSET_Y = 90;
|
||||
public static Color BG_COLOR = Color.WHITE;
|
||||
public static int QRCODE_SIZE = 100;
|
||||
public static int QRCODE_OFFSET_X = 10;
|
||||
|
||||
public static int SCENIC_FONT_SIZE = 42;
|
||||
public static Color scenicColor = Color.white;
|
||||
public static int DATETIME_FONT_SIZE = 42;
|
||||
public static Color datetimeColor = Color.white;
|
||||
|
||||
@Override
|
||||
public File process(WatermarkInfo info) throws ImageWatermarkException {
|
||||
BufferedImage baseImage;
|
||||
BufferedImage qrcodeImage;
|
||||
try {
|
||||
baseImage = ImageIO.read(info.getOriginalFile());
|
||||
qrcodeImage = ImageIO.read(info.getQrcodeFile());
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片打开失败");
|
||||
}
|
||||
// 新图像画布
|
||||
BufferedImage newImage = new BufferedImage(baseImage.getWidth() + 2 * EXTRA_BORDER_PX, baseImage.getHeight() + 2 * EXTRA_BORDER_PX, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = newImage.createGraphics();
|
||||
g2d.setColor(BG_COLOR);
|
||||
g2d.fillRect(0, 0, newImage.getWidth(), newImage.getHeight());
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.drawImage(baseImage, EXTRA_BORDER_PX, EXTRA_BORDER_PX, null);
|
||||
int newQrcodeHeight = QRCODE_SIZE;
|
||||
int newQrcodeWidth = (int) (newQrcodeHeight * 1.0 / qrcodeImage.getHeight() * qrcodeImage.getWidth());
|
||||
Font scenicFont = new Font(defaultFontName, Font.PLAIN, SCENIC_FONT_SIZE);
|
||||
Font datetimeFont = new Font(defaultFontName, Font.PLAIN, DATETIME_FONT_SIZE);
|
||||
FontMetrics scenicFontMetrics = g2d.getFontMetrics(scenicFont);
|
||||
FontMetrics datetimeFontMetrics = g2d.getFontMetrics(datetimeFont);
|
||||
int scenicLineHeight = scenicFontMetrics.getHeight();
|
||||
int dtLineHeight = datetimeFontMetrics.getHeight();
|
||||
int scenicLineWidth = scenicFontMetrics.stringWidth(info.getScenicLine());
|
||||
int datetimeLineWidth = scenicFontMetrics.stringWidth(info.getDatetimeLine());
|
||||
int offsetX = (newImage.getWidth() - newQrcodeWidth - QRCODE_OFFSET_X - Math.max(scenicLineWidth, datetimeLineWidth)) / 2;
|
||||
int offsetY = EXTRA_BORDER_PX + baseImage.getHeight() - OFFSET_Y - newQrcodeHeight;
|
||||
g2d.drawImage(qrcodeImage, offsetX, offsetY, newQrcodeWidth, newQrcodeHeight, null);
|
||||
g2d.setFont(scenicFont);
|
||||
g2d.setColor(scenicColor);
|
||||
g2d.drawString(info.getScenicLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, offsetY + scenicLineHeight + FONT_GLOBAL_OFFSET_PERCENT * scenicLineHeight);
|
||||
g2d.setFont(datetimeFont);
|
||||
g2d.setColor(datetimeColor);
|
||||
g2d.drawString(info.getDatetimeLine(), offsetX + newQrcodeWidth + QRCODE_OFFSET_X, offsetY + scenicLineHeight + dtLineHeight + FONT_GLOBAL_OFFSET_PERCENT * dtLineHeight);
|
||||
String fileName = info.getWatermarkedFile().getName();
|
||||
String formatName = "jpg"; // 默认格式为 jpg
|
||||
if (fileName.endsWith(".png")) {
|
||||
formatName = "png";
|
||||
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
||||
formatName = "jpg";
|
||||
}
|
||||
ImageWriter writer = ImageIO.getImageWritersByFormatName(formatName).next();
|
||||
ImageOutputStream ios;
|
||||
try {
|
||||
ios = ImageIO.createImageOutputStream(info.getWatermarkedFile());
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败,目标文件无法写入");
|
||||
}
|
||||
writer.setOutput(ios);
|
||||
try {
|
||||
// 使用 ImageWriter 设置写入质量
|
||||
ImageWriteParam writeParam = writer.getDefaultWriteParam();
|
||||
if (writeParam.canWriteCompressed()) {
|
||||
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
writeParam.setCompressionQuality(0.95f); // 设置写入质量为 95%
|
||||
}
|
||||
writer.write(null, new javax.imageio.IIOImage(newImage, null, null), writeParam);
|
||||
} catch (IOException e) {
|
||||
throw new ImageWatermarkException("图片保存失败");
|
||||
}
|
||||
finally {
|
||||
g2d.dispose();
|
||||
try {
|
||||
ios.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
writer.dispose();
|
||||
}
|
||||
return info.getWatermarkedFile();
|
||||
}
|
||||
}
|
17
src/main/java/com/ycwl/basic/mapper/CouponMapper.java
Normal file
17
src/main/java/com/ycwl/basic/mapper/CouponMapper.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.model.pc.coupon.req.CouponQueryReq;
|
||||
import com.ycwl.basic.model.pc.coupon.resp.CouponRespVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CouponMapper extends BaseMapper<CouponEntity> {
|
||||
List<CouponRespVO> selectByQuery(CouponQueryReq query);
|
||||
|
||||
int updateStatus(Integer id);
|
||||
|
||||
CouponEntity getById(Integer couponId);
|
||||
}
|
12
src/main/java/com/ycwl/basic/mapper/CouponRecordMapper.java
Normal file
12
src/main/java/com/ycwl/basic/mapper/CouponRecordMapper.java
Normal file
@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CouponRecordMapper extends BaseMapper<CouponRecordEntity> {
|
||||
List<CouponRecordEntity> queryByUserWithGoodsId(Long scenicId, Long memberId, String goodsId);
|
||||
}
|
@ -6,6 +6,7 @@ import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -16,6 +17,7 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface FaceMapper {
|
||||
List<FaceRespVO> list(FaceReqQuery faceReqQuery);
|
||||
List<FaceRespVO> test();
|
||||
List<FaceRespVO> listByScenicIdAndNotFinished(Long scenicId);
|
||||
FaceRespVO getById(Long id);
|
||||
FaceEntity get(Long id);
|
||||
@ -32,4 +34,6 @@ public interface FaceMapper {
|
||||
FaceRespVO findLastFaceByScenicAndUserId(Long scenicId, Long userId);
|
||||
|
||||
List<FaceRespVO> listByScenicAndUserId(String scenicId, Long userId);
|
||||
|
||||
List<FaceEntity> listEntityBeforeDate(Long scenicId, Date endDate);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.ycwl.basic.mapper;
|
||||
import com.ycwl.basic.model.pc.member.entity.MemberEntity;
|
||||
import com.ycwl.basic.model.pc.member.req.MemberReqQuery;
|
||||
import com.ycwl.basic.model.pc.member.resp.MemberRespVO;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
|
@ -49,5 +49,10 @@ public interface OrderMapper {
|
||||
|
||||
OrderItemEntity getOrderItem(Long orderItemId);
|
||||
|
||||
int updateOrderPrice(OrderEntity updateEntity);
|
||||
int updateOrder(OrderEntity updateEntity);
|
||||
|
||||
OrderEntity queryTypeOrder(Long userId, Long scenicId, int orderType, Integer priceConfigId);
|
||||
|
||||
OrderEntity getUserOrderItem(Long userId, Long scenicId, int orderType, Long configId, Integer goodsType, Long goodsId);
|
||||
}
|
||||
|
15
src/main/java/com/ycwl/basic/mapper/PermissionMapper.java
Normal file
15
src/main/java/com/ycwl/basic/mapper/PermissionMapper.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ycwl.basic.model.pc.permission.entity.PermissionEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@Mapper
|
||||
public interface PermissionMapper extends BaseMapper<PermissionEntity> {
|
||||
// 新增用户ID查询方法
|
||||
PermissionEntity selectByUserId(@Param("userId") Long userId);
|
||||
|
||||
void insertPermission(PermissionEntity entity);
|
||||
void updatePermission(PermissionEntity entity);
|
||||
}
|
29
src/main/java/com/ycwl/basic/mapper/PrinterMapper.java
Normal file
29
src/main/java/com/ycwl/basic/mapper/PrinterMapper.java
Normal file
@ -0,0 +1,29 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
|
||||
import com.ycwl.basic.model.pc.printer.entity.PrintTaskEntity;
|
||||
import com.ycwl.basic.model.pc.printer.entity.PrinterEntity;
|
||||
import com.ycwl.basic.model.printer.resp.PrintTaskResp;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PrinterMapper {
|
||||
List<PrinterEntity> list(@Param("condition") PrinterEntity condition);
|
||||
|
||||
PrinterEntity getById(@Param("id") Integer id);
|
||||
|
||||
int add(PrinterEntity entity);
|
||||
|
||||
int update(PrinterEntity entity);
|
||||
|
||||
int deleteById(@Param("id") Integer id);
|
||||
|
||||
PrinterEntity findByAccessKey(String accessKey);
|
||||
|
||||
PrintTaskResp findTaskByPrinterId(Integer printerId);
|
||||
|
||||
int updateTaskStatus(@Param("id") Integer id, @Param("status") Integer status);
|
||||
|
||||
PrintTaskEntity getTaskById(Integer id);
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package com.ycwl.basic.mapper;
|
||||
|
||||
import com.ycwl.basic.model.pc.scenic.entity.ScenicAccountEntity;
|
||||
import com.ycwl.basic.model.pc.scenic.req.ScenicAccountReqQuery;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ScenicAccountMapper {
|
||||
ScenicAccountEntity getByAccount(String account);
|
||||
@ -14,4 +17,6 @@ public interface ScenicAccountMapper {
|
||||
int deleteByScenicId(Long scenicId);
|
||||
|
||||
ScenicAccountEntity findAccountById(String id);
|
||||
List<ScenicAccountEntity> pageQuery(ScenicAccountReqQuery req);
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.ycwl.basic.mapper;
|
||||
|
||||
import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceWatermarkEntity;
|
||||
import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
|
||||
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@ -74,4 +75,7 @@ public interface SourceMapper {
|
||||
int deleteNotBuyRelations(Long scenicId, Date endDate);
|
||||
|
||||
int deleteNotBuyFaceRelation(Long userId, Long faceId);
|
||||
List<SourceWatermarkEntity> listSourceWatermark(List<Long> sourceIds, Long faceId, String watermarkType);
|
||||
|
||||
void addSourceWatermark(Long sourceId, Long faceId, String type, String url);
|
||||
}
|
||||
|
@ -91,4 +91,6 @@ public interface StatisticsMapper {
|
||||
int addStatisticsRecord(StatisticsRecordAddReq req);
|
||||
|
||||
List<Long> getBrokerIdListForUser(Long memberId, Date startTime, Date endTime);
|
||||
|
||||
Long getUserRecentEnterType(Long memberId, Date endTime);
|
||||
}
|
||||
|
@ -53,4 +53,6 @@ public interface TaskMapper {
|
||||
TaskEntity get(Long taskId);
|
||||
|
||||
List<TaskEntity> listEntity(TaskReqQuery taskReqQuery);
|
||||
|
||||
List<TaskRespVO> selectNotRunningByScenicId(Long scenicOnly);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public interface VideoMapper {
|
||||
MemberVideoEntity queryRelationByMemberTask(Long userId, Long taskId);
|
||||
List<MemberVideoEntity> listRelationByTask(Long taskId);
|
||||
List<MemberVideoEntity> listRelationByFace(Long userId, Long faceId);
|
||||
List<MemberVideoEntity> listRelationByFaceAndTemplate(Long userId, Long faceId, Long templateId);
|
||||
List<MemberVideoEntity> listRelationByFaceAndTemplate(Long faceId, Long templateId);
|
||||
|
||||
List<TaskEntity> listTaskByScenicRelation(Long userId, Long scenicId);
|
||||
|
||||
|
@ -43,4 +43,5 @@ public class GoodsDetailVO {
|
||||
private BigDecimal price;
|
||||
@ApiModelProperty("是否已购买 0否 1是")
|
||||
private Integer isBuy;
|
||||
private Integer isFree;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ public class GoodsReqQuery {
|
||||
@ApiModelProperty("是否已购买 0否 1是")
|
||||
private Integer isBuy;
|
||||
private Long faceId;
|
||||
private Long goodsId;
|
||||
@ApiModelProperty("景区id")
|
||||
private Long scenicId;
|
||||
@ApiModelProperty("源素材商品类型 1视频 2图像")
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.ycwl.basic.model.mobile.goods;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author:longbinbin
|
||||
* @Date:2024/12/5 15:10
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("商品详情")
|
||||
public class GoodsUrlVO {
|
||||
@ApiModelProperty("商品类型 0:vlog 1:成片视频 2:源素材")
|
||||
private Integer goodsType;
|
||||
@ApiModelProperty("商品id goodsType=0时为videoId,goodsType=2时为sourceId")
|
||||
private Long goodsId;
|
||||
@ApiModelProperty("图片文件存储地址")
|
||||
private String url;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createTime;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.ycwl.basic.model.mobile.order;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class IsBuyBatchRespVO {
|
||||
private boolean buy;
|
||||
private boolean free;
|
||||
private Long orderId;
|
||||
private Integer configId;
|
||||
private int type;
|
||||
private String goodsIds;
|
||||
private BigDecimal origPrice = BigDecimal.ZERO;
|
||||
private Integer couponId;
|
||||
private Integer couponRecordId;
|
||||
private BigDecimal couponPrice = BigDecimal.ZERO;
|
||||
private BigDecimal slashPrice;
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return origPrice.subtract(couponPrice);
|
||||
}
|
||||
public BigDecimal getDiscountPrice() {
|
||||
if (slashPrice == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return slashPrice.subtract(origPrice);
|
||||
}
|
||||
}
|
@ -11,6 +11,22 @@ public class IsBuyRespVO {
|
||||
private Long orderId;
|
||||
private int goodsType;
|
||||
private Long goodsId;
|
||||
private BigDecimal price;
|
||||
private BigDecimal origPrice = BigDecimal.ZERO;
|
||||
private Integer couponId;
|
||||
private Integer couponRecordId;
|
||||
private BigDecimal couponPrice = BigDecimal.ZERO;
|
||||
private BigDecimal slashPrice;
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return origPrice.subtract(couponPrice);
|
||||
}
|
||||
public BigDecimal getDiscountPrice() {
|
||||
if (slashPrice == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return slashPrice.subtract(origPrice);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package com.ycwl.basic.model.pc.coupon.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("coupon")
|
||||
public class CouponEntity {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private Long scenicId;
|
||||
|
||||
// 新增优惠券名称字段
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 优惠券类别,0:普通优惠券;1:第一次推送;2:第二次;3:第三次
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 价格配置ID,逗号分隔字符串
|
||||
*/
|
||||
private String configIds;
|
||||
/**
|
||||
* 0降价,1打折
|
||||
*/
|
||||
private Integer discountType;
|
||||
private BigDecimal discountPrice;
|
||||
/**
|
||||
* 状态:0不开启;1开启
|
||||
*/
|
||||
private Integer status;
|
||||
private Date createAt;
|
||||
|
||||
public BigDecimal calculateDiscountPrice(BigDecimal originalPrice) {
|
||||
if (discountType == 0) {
|
||||
return discountPrice;
|
||||
} else {
|
||||
return originalPrice.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN).multiply(discountPrice);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.ycwl.basic.model.pc.coupon.req;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import com.ycwl.basic.model.common.BaseQueryParameterReq;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@ApiModel("优惠券查询请求参数")
|
||||
public class CouponQueryReq extends BaseQueryParameterReq {
|
||||
@ApiModelProperty("景区ID")
|
||||
private Long scenicId;
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("优惠券类型:0普通/1首次推送/2二次/3三次")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty("折扣类型:0降价/1打折")
|
||||
private Integer discountType;
|
||||
|
||||
@ApiModelProperty("状态:0关闭/1开启")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty("创建时间起始")
|
||||
private Date createAtStart;
|
||||
|
||||
@ApiModelProperty("创建时间结束")
|
||||
private Date createAtEnd;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.ycwl.basic.model.pc.coupon.resp;
|
||||
|
||||
import lombok.Data;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CouponRespVO {
|
||||
private Integer id;
|
||||
private Long scenicId;
|
||||
private String scenicName;
|
||||
|
||||
// 新增优惠券名称字段
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 优惠券类别,0:普通优惠券;1:第一次推送;2:第二次;3:第三次
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 价格配置ID,逗号分隔字符串
|
||||
*/
|
||||
private String configIds;
|
||||
/**
|
||||
* 0降价,1打折
|
||||
*/
|
||||
private Integer discountType;
|
||||
private BigDecimal discountPrice;
|
||||
/**
|
||||
* 状态:0不开启;1开启
|
||||
*/
|
||||
private Integer status;
|
||||
private Date createAt;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.ycwl.basic.model.pc.couponRecord.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CouponRecordEntity {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
private Integer couponId;
|
||||
private Long memberId;
|
||||
private Long faceId;
|
||||
private Integer status;
|
||||
private Date createTime;
|
||||
private Date usedTime;
|
||||
private Long usedOrderId;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.ycwl.basic.model.pc.couponRecord.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CouponRecordUserQueryReq {
|
||||
private Long scenicId;
|
||||
private Long memberId;
|
||||
private Long faceId;
|
||||
private Integer couponType;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.ycwl.basic.model.pc.couponRecord.resp;
|
||||
|
||||
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class CouponRecordQueryResp {
|
||||
private boolean exist = false;
|
||||
private Integer id;
|
||||
private Long scenicId;
|
||||
private Integer couponId;
|
||||
private Long memberId;
|
||||
private Long faceId;
|
||||
private Integer status;
|
||||
private Date createTime;
|
||||
private Date usedTime;
|
||||
private Long usedOrderId;
|
||||
private CouponEntity coupon;
|
||||
|
||||
public boolean isUsable() {
|
||||
return Integer.valueOf(0).equals(status);
|
||||
}
|
||||
}
|
@ -58,4 +58,7 @@ public class DeviceConfigEntity {
|
||||
*/
|
||||
private BigDecimal cutPost;
|
||||
private Integer enablePreBook;
|
||||
private Integer imageFree;
|
||||
private Integer videoFree;
|
||||
private Long pairDevice;
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.ycwl.basic.model.pc.device.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DeviceBatchSortRequest {
|
||||
private List<SortItem> list;
|
||||
|
||||
@Data
|
||||
public static class SortItem {
|
||||
private Long id;
|
||||
private Integer sort;
|
||||
}
|
||||
}
|
@ -31,6 +31,9 @@ public class DeviceRespVO {
|
||||
private Integer status;
|
||||
@ApiModelProperty("是否在线,0不在线,1在线")
|
||||
private Integer online;
|
||||
private String coverUrl;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date coverTime;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createAt;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
|
@ -33,7 +33,7 @@ public class FaceDetectLog {
|
||||
private String matchLocalRecord;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<SearchFaceResponse.Data.MatchListItem.FaceItemsItem> matchRawRecord;
|
||||
private List matchRawRecord;
|
||||
|
||||
public static FaceDetectLog quickCreate(String reason) {
|
||||
FaceDetectLog log = new FaceDetectLog();
|
||||
@ -53,19 +53,19 @@ public class FaceDetectLog {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FaceDetectLog fillResponse(SearchFaceResponse response) {
|
||||
this.matchRawResult = JSONObject.toJSONString(response.getData());
|
||||
public FaceDetectLog fillResponse(Object response) {
|
||||
this.matchRawResult = JSONObject.toJSONString(response);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<MatchLocalRecord> matchLocalRecord() {
|
||||
public List matchLocalRecord() {
|
||||
if (matchLocalRecord == null) {
|
||||
return null;
|
||||
}
|
||||
return JSONArray.parseArray(matchLocalRecord, MatchLocalRecord.class);
|
||||
}
|
||||
|
||||
public void matchLocalRecord(List<MatchLocalRecord> matchLocalRecord) {
|
||||
public void matchLocalRecord(List matchLocalRecord) {
|
||||
if (matchLocalRecord == null) {
|
||||
this.matchLocalRecord = null;
|
||||
} else {
|
||||
|
@ -10,8 +10,8 @@ public class MatchLocalRecord {
|
||||
private String deviceName;
|
||||
private String faceUrl;
|
||||
private Float score;
|
||||
private Float confidence;
|
||||
private String idStr;
|
||||
private Date shotDate;
|
||||
private Boolean matched;
|
||||
private Boolean accept;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import java.util.Date;
|
||||
@Data
|
||||
@ApiModel("查询用户信息响应参数")
|
||||
public class MemberRespVO {
|
||||
private Long uid;
|
||||
private Long id;
|
||||
private Long scenicId;
|
||||
/**
|
||||
|
@ -35,6 +35,9 @@ public class OrderEntity {
|
||||
* 划线价
|
||||
*/
|
||||
private BigDecimal slashPrice;
|
||||
private BigDecimal couponPrice = BigDecimal.ZERO;
|
||||
private Integer couponId;
|
||||
private Integer couponRecordId;
|
||||
/**
|
||||
* 优惠价格
|
||||
*/
|
||||
@ -88,4 +91,13 @@ public class OrderEntity {
|
||||
*/
|
||||
private Date refundAt;
|
||||
|
||||
public BigDecimal getDiscountPrice() {
|
||||
if (slashPrice == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return slashPrice.subtract(price);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ public class OrderReqQuery extends BaseQueryParameterReq {
|
||||
private Long memberId;
|
||||
@ApiModelProperty("用户昵称")
|
||||
private String memberNickname;
|
||||
private String memberUid;
|
||||
@ApiModelProperty("用户真实名称")
|
||||
private String memberRealName;
|
||||
/**
|
||||
|
@ -89,4 +89,14 @@ public class OrderAppRespVO {
|
||||
private Integer goodsType;
|
||||
@ApiModelProperty("订单明细")
|
||||
private List<OrderItemVO> orderItemList;
|
||||
|
||||
public BigDecimal getDiscountPrice() {
|
||||
if (slashPrice == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return slashPrice.subtract(price);
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,11 @@ public class OrderRespVO {
|
||||
private Long faceId;
|
||||
private String faceUrl;
|
||||
private Integer type;
|
||||
private String orderType;
|
||||
private String goodsName;
|
||||
@ApiModelProperty("用户昵称")
|
||||
private String memberNickname;
|
||||
private String memberUid;
|
||||
@ApiModelProperty("用户真实名称")
|
||||
private String memberRealName;
|
||||
/**
|
||||
@ -108,4 +111,14 @@ public class OrderRespVO {
|
||||
private List<OrderItemVO> orderItemList;
|
||||
private Long scenicId;
|
||||
private String scenicName;
|
||||
|
||||
public BigDecimal getDiscountPrice() {
|
||||
if (slashPrice == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return slashPrice.subtract(price);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.ycwl.basic.model.pc.permission.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("permission")
|
||||
public class PermissionEntity implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@TableField("user_id")
|
||||
private Long userId; // 确保字段映射
|
||||
|
||||
@TableField("perm_str")
|
||||
private String permString;
|
||||
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
@TableField("update_time")
|
||||
private Date updateTime;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.ycwl.basic.model.pc.permission.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PermissionSaveReq {
|
||||
private List<String> permissions;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.model.pc.permission.resp;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class PermissionResp {
|
||||
private List<String> permissions;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user