|
|
@@ -13,7 +13,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.data.geo.Point;
|
|
|
import org.springframework.http.*;
|
|
|
@@ -37,7 +36,6 @@ import shop.alien.entity.storePlatform.StoreOperationalActivity;
|
|
|
import shop.alien.mapper.*;
|
|
|
import shop.alien.mapper.storePlantform.StoreLicenseHistoryMapper;
|
|
|
import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
|
|
|
-import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
|
|
|
import shop.alien.store.config.BaseRedisService;
|
|
|
import shop.alien.store.config.GaoDeMapUtil;
|
|
|
import shop.alien.store.config.WebSocketProcess;
|
|
|
@@ -46,7 +44,6 @@ import shop.alien.store.util.CommonConstant;
|
|
|
import shop.alien.store.util.FileUploadUtil;
|
|
|
import shop.alien.store.util.GroupConstant;
|
|
|
import shop.alien.store.util.ai.AiAuthTokenUtil;
|
|
|
-import shop.alien.store.util.ali.AliApi;
|
|
|
import shop.alien.util.ali.AliOSSUtil;
|
|
|
import shop.alien.util.common.DistanceUtil;
|
|
|
import shop.alien.util.common.constant.CouponStatusEnum;
|
|
|
@@ -914,10 +911,13 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
storeInfo.setFoodLicenceStatus(2);
|
|
|
storeInfo.setUpdateFoodLicenceTime(new Date());
|
|
|
}
|
|
|
- } else if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
|
|
|
- // 没有食品经营许可证URL,但有传入到期时间时直接使用
|
|
|
- storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
|
|
|
- log.info("无食品经营许可证URL,使用DTO中的到期时间:{}", storeInfoDto.getFoodLicenceExpirationTime());
|
|
|
+ } else {
|
|
|
+ // 没有食品经营许可证URL,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setFoodLicenceStatus(0);
|
|
|
+ if (storeInfoDto.getFoodLicenceExpirationTime() != null) {
|
|
|
+ storeInfo.setFoodLicenceExpirationTime(storeInfoDto.getFoodLicenceExpirationTime());
|
|
|
+ log.info("无食品经营许可证URL,使用DTO中的到期时间:{}", storeInfoDto.getFoodLicenceExpirationTime());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 处理娱乐经营许可证OCR数据(复用营业执照OCR类型,数据库中ocr_type存的是BUSINESS_LICENSE)
|
|
|
@@ -965,13 +965,78 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
storeInfo.setEntertainmentLicenceStatus(2);
|
|
|
storeInfo.setUpdateEntertainmentLicenceTime(new Date());
|
|
|
}
|
|
|
- } else if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
|
|
|
- // 没有娱乐经营许可证URL,但有传入到期时间时直接使用
|
|
|
- storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
|
|
|
- log.info("无娱乐经营许可证URL,使用DTO中的到期时间:{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
|
|
|
+ } else {
|
|
|
+ // 没有娱乐经营许可证URL,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setEntertainmentLicenceStatus(0);
|
|
|
+ if (storeInfoDto.getEntertainmentLicenceExpirationTime() != null) {
|
|
|
+ storeInfo.setEntertainmentLicenceExpirationTime(storeInfoDto.getEntertainmentLicenceExpirationTime());
|
|
|
+ log.info("无娱乐经营许可证URL,使用DTO中的到期时间:{}", storeInfoDto.getEntertainmentLicenceExpirationTime());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 计算并设置到期时间为三个过期时间的最小值
|
|
|
+ // 处理营业执照OCR数据(复用营业执照OCR类型,数据库中ocr_type存的是BUSINESS_LICENSE)
|
|
|
+ // 营业执照使用 businessLicenseAddress 列表中的第一个URL查询OCR
|
|
|
+ String businessLicenseOcrUrl = null;
|
|
|
+ if (!CollectionUtils.isEmpty(storeInfoDto.getBusinessLicenseAddress())) {
|
|
|
+ businessLicenseOcrUrl = storeInfoDto.getBusinessLicenseAddress().get(0);
|
|
|
+ } else if (StringUtils.isNotEmpty(storeInfoDto.getBusinessLicenseUrl())) {
|
|
|
+ businessLicenseOcrUrl = storeInfoDto.getBusinessLicenseUrl();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(businessLicenseOcrUrl)) {
|
|
|
+ // 查询营业执照OCR识别记录
|
|
|
+ OcrImageUpload businessLicenseOcr = ocrImageUploadMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<OcrImageUpload>()
|
|
|
+ .eq(OcrImageUpload::getImageUrl, businessLicenseOcrUrl)
|
|
|
+ .eq(OcrImageUpload::getOcrType, OcrTypeEnum.BUSINESS_LICENSE.getCode())
|
|
|
+ .orderByDesc(OcrImageUpload::getCreateTime)
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ if (businessLicenseOcr != null && StringUtils.isNotEmpty(businessLicenseOcr.getOcrResult())) {
|
|
|
+ try {
|
|
|
+ com.alibaba.fastjson2.JSONObject ocrResult = com.alibaba.fastjson2.JSONObject.parseObject(businessLicenseOcr.getOcrResult());
|
|
|
+ // 营业执照OCR字段:validToDate(优先,格式"20241217")、validPeriod(格式"2020年09月04日至2022年09月03日")
|
|
|
+ Date expirationTime = parseBusinessLicenseExpirationDate(ocrResult);
|
|
|
+ if (expirationTime != null) {
|
|
|
+ storeInfo.setBusinessLicenseExpirationTime(expirationTime);
|
|
|
+ } else if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
|
|
|
+ // OCR解析结果为空时,使用DTO中传入的值
|
|
|
+ storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ log.info("使用DTO中的营业执照到期时间:{}", storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ }
|
|
|
+ // 设置营业执照状态为"待审核"(字典值2)
|
|
|
+ storeInfo.setBusinessLicenseStatus(2);
|
|
|
+ storeInfo.setUpdateBusinessLicenseTime(new Date());
|
|
|
+ log.info("营业执照OCR数据解析成功,到期时间:{}", storeInfo.getBusinessLicenseExpirationTime());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析营业执照OCR数据失败", e);
|
|
|
+ // 解析失败时使用DTO中传入的值
|
|
|
+ if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
|
|
|
+ storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ log.info("OCR解析失败,使用DTO中的营业执照到期时间:{}", storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ }
|
|
|
+ storeInfo.setBusinessLicenseStatus(2);
|
|
|
+ storeInfo.setUpdateBusinessLicenseTime(new Date());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 没有OCR记录时,使用DTO中传入的值
|
|
|
+ if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
|
|
|
+ storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ log.info("无OCR记录,使用DTO中的营业执照到期时间:{}", storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ }
|
|
|
+ storeInfo.setBusinessLicenseStatus(2);
|
|
|
+ storeInfo.setUpdateBusinessLicenseTime(new Date());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 没有营业执照URL,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setBusinessLicenseStatus(0);
|
|
|
+ if (storeInfoDto.getBusinessLicenseExpirationTime() != null) {
|
|
|
+ storeInfo.setBusinessLicenseExpirationTime(storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ log.info("无营业执照URL,使用DTO中的到期时间:{}", storeInfoDto.getBusinessLicenseExpirationTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算并设置到期时间为五个过期时间的最小值(包含身份证过期时间)
|
|
|
List<Date> expirationTimeList = new ArrayList<>();
|
|
|
// 收集所有非空的过期时间
|
|
|
if (storeInfoDto.getExpirationTime() != null) {
|
|
|
@@ -983,6 +1048,10 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
if (storeInfo.getEntertainmentLicenceExpirationTime() != null) {
|
|
|
expirationTimeList.add(storeInfo.getEntertainmentLicenceExpirationTime());
|
|
|
}
|
|
|
+ if (storeInfo.getBusinessLicenseExpirationTime() != null) {
|
|
|
+ expirationTimeList.add(storeInfo.getBusinessLicenseExpirationTime());
|
|
|
+ }
|
|
|
+ // 注意:身份证过期时间在saveIdCardImages方法中设置,这里先不包含,后续会在saveIdCardImages后更新
|
|
|
// 取最小值设置为门店到期时间
|
|
|
if (!expirationTimeList.isEmpty()) {
|
|
|
Date minExpirationTime = Collections.min(expirationTimeList);
|
|
|
@@ -1054,6 +1123,23 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
storeImgMapper.insert(storeImg);
|
|
|
}
|
|
|
|
|
|
+ //存入身份证正反面图片
|
|
|
+ saveIdCardImages(storeInfo.getId(), storeUser.getId().toString(), storeInfo);
|
|
|
+
|
|
|
+ // 更新门店到期时间,包含身份证过期时间
|
|
|
+ if (storeInfo.getIdCardExpirationTime() != null) {
|
|
|
+ List<Date> allExpirationTimeList = new ArrayList<>();
|
|
|
+ if (storeInfo.getExpirationTime() != null) {
|
|
|
+ allExpirationTimeList.add(storeInfo.getExpirationTime());
|
|
|
+ }
|
|
|
+ allExpirationTimeList.add(storeInfo.getIdCardExpirationTime());
|
|
|
+ Date minExpirationTime = Collections.min(allExpirationTimeList);
|
|
|
+ storeInfo.setExpirationTime(minExpirationTime);
|
|
|
+ // 更新数据库中的过期时间
|
|
|
+ storeInfoMapper.updateById(storeInfo);
|
|
|
+ log.info("更新门店到期时间,包含身份证过期时间,最小值:{}", minExpirationTime);
|
|
|
+ }
|
|
|
+
|
|
|
//初始化标签数据
|
|
|
LambdaQueryWrapper<TagStoreRelation> tagStoreRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
|
|
tagStoreRelationLambdaQueryWrapper.eq(TagStoreRelation::getStoreId, storeInfo.getId());
|
|
|
@@ -1336,8 +1422,12 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
|
|
|
@Override
|
|
|
public List<StoreDictionaryVo> getBusinessSectionTypes(String parentId) {
|
|
|
- StoreDictionary businessSection = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "business_section").eq(StoreDictionary::getDictId, parentId));
|
|
|
- List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getParentId, businessSection.getId()));
|
|
|
+ StoreDictionary businessSection = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
|
|
|
+ .eq(StoreDictionary::getTypeName, "business_section")
|
|
|
+ .eq(StoreDictionary::getDictId, parentId)
|
|
|
+ .isNull(StoreDictionary::getParentId));
|
|
|
+ List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>()
|
|
|
+ .eq(StoreDictionary::getParentId, businessSection.getId()));
|
|
|
List<StoreDictionaryVo> voList = new ArrayList<>();
|
|
|
for (StoreDictionary storeDictionary : storeDictionaries) {
|
|
|
StoreDictionaryVo vo = new StoreDictionaryVo();
|
|
|
@@ -1950,7 +2040,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
List<String> storeIds = Arrays.asList(storeId.split(","));
|
|
|
if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
|
|
|
List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().in(StoreBusinessInfo::getStoreId, storeIds));
|
|
|
- DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
|
|
|
+ DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
|
|
|
List<StoreBusinessInfo> list = storeBusinessInfos.stream().filter(item -> {
|
|
|
// 商家开门时间
|
|
|
LocalTime timeStart = LocalTime.parse(item.getEndTime(), formatter);
|
|
|
@@ -2030,7 +2120,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
List<String> storeIds = Arrays.asList(storeId.split(","));
|
|
|
if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
|
|
|
List<StoreBusinessInfo> storeBusinessInfos = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().in(StoreBusinessInfo::getStoreId, storeIds));
|
|
|
- DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
|
|
|
+ DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendValue(ChronoField.HOUR_OF_DAY, 1, 2, SignStyle.NOT_NEGATIVE).appendLiteral(':').appendValue(ChronoField.MINUTE_OF_HOUR, 2).toFormatter();
|
|
|
List<StoreBusinessInfo> list = storeBusinessInfos.stream().filter(item -> {
|
|
|
// 商家开门时间
|
|
|
LocalTime timeStart = LocalTime.parse(item.getEndTime(), formatter);
|
|
|
@@ -2973,17 +3063,17 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
.eq(StoreOperationalActivity::getDeleteFlag, 0)
|
|
|
.eq(StoreOperationalActivity::getStatus, 5);
|
|
|
List<StoreOperationalActivity> activities = storeOperationalActivityMapper.selectList(activityWrapper);
|
|
|
-
|
|
|
+
|
|
|
// 如果没有活动,返回空列表
|
|
|
if (CollectionUtils.isEmpty(activities)) {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 获取活动ID列表
|
|
|
List<Integer> activityIds = activities.stream()
|
|
|
.map(StoreOperationalActivity::getId)
|
|
|
.collect(Collectors.toList());
|
|
|
-
|
|
|
+
|
|
|
// 查询与活动关联的图片
|
|
|
LambdaQueryWrapper<StoreImg> queryWrapper = new LambdaQueryWrapper<StoreImg>()
|
|
|
.eq(StoreImg::getStoreId, Integer.parseInt(storeId))
|
|
|
@@ -3110,9 +3200,9 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
// KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧的数值未知(由调用方传入)
|
|
|
queryWrapper.eq("a.business_section", businessType);
|
|
|
} else {
|
|
|
- // 如果没有指定businessType,则查询所有两种类型的店铺
|
|
|
+ // 如果没有指定businessType,则查询所有四种类型的店铺
|
|
|
// 需要查询字典表获取所有四种类型的dictId
|
|
|
- List<String> storeTypeNames = Arrays.asList("丽人美发", "运动健身");
|
|
|
+ List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗");
|
|
|
List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
|
|
|
new LambdaQueryWrapper<StoreDictionary>()
|
|
|
.eq(StoreDictionary::getTypeName, "business_section")
|
|
|
@@ -3218,7 +3308,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
LambdaQueryWrapper<LifeUserOrder> orderWrapper = new LambdaQueryWrapper<>();
|
|
|
orderWrapper.in(LifeUserOrder::getStoreId, storeIds)
|
|
|
.and(w -> w.and(w1 -> w1.eq(LifeUserOrder::getStatus, 7)
|
|
|
- .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
|
|
|
+ .ge(LifeUserOrder::getFinishTime, sevenDaysAgoStr))
|
|
|
.or(w2 -> w2.eq(LifeUserOrder::getStatus, 1)
|
|
|
.ge(LifeUserOrder::getPayTime, sevenDaysAgoStr)))
|
|
|
.eq(LifeUserOrder::getDeleteFlag, 0);
|
|
|
@@ -4649,6 +4739,42 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析营业执照OCR结果中的到期时间(复用营业执照OCR类型)
|
|
|
+ * 营业执照OCR返回字段:validToDate(格式"20241217"或空)、validPeriod(可能为空)
|
|
|
+ * 注意:营业执照的validToDate可能为空,表示长期有效
|
|
|
+ *
|
|
|
+ * @param ocrResult OCR识别结果JSON对象
|
|
|
+ * @return 到期日期,如果解析失败或为长期有效则返回null
|
|
|
+ */
|
|
|
+ private Date parseBusinessLicenseExpirationDate(com.alibaba.fastjson2.JSONObject ocrResult) {
|
|
|
+ if (ocrResult == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 优先使用validToDate字段(格式为yyyyMMdd,如"20241217",可能为空表示长期有效)
|
|
|
+ String validToDate = ocrResult.getString("validToDate");
|
|
|
+ if (StringUtils.isNotEmpty(validToDate)) {
|
|
|
+ Date date = parseDateString(validToDate);
|
|
|
+ if (date != null) {
|
|
|
+ return date;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 其次使用validPeriod字段(格式为"2020年09月04日至2022年09月03日",可能为空)
|
|
|
+ String validPeriod = ocrResult.getString("validPeriod");
|
|
|
+ if (StringUtils.isNotEmpty(validPeriod)) {
|
|
|
+ Date date = parseValidPeriodEndDate(validPeriod);
|
|
|
+ if (date != null) {
|
|
|
+ return date;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("营业执照OCR结果中未找到有效的到期时间,validToDate={},validPeriod={},可能为长期有效", validToDate, validPeriod);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 解析日期字符串
|
|
|
* 支持的格式:yyyyMMdd、yyyy-MM-dd、yyyy/MM/dd、yyyy年MM月dd日
|
|
|
@@ -4722,6 +4848,157 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
|
|
|
return parseDateString(endDateStr);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 保存身份证正反面图片到store_img表,并解析OCR结果设置过期时间和状态
|
|
|
+ *
|
|
|
+ * @param storeId 门店ID
|
|
|
+ * @param storeUserId 店铺用户ID
|
|
|
+ * @param storeInfo 门店信息对象(用于设置身份证状态和过期时间)
|
|
|
+ */
|
|
|
+ private void saveIdCardImages(Integer storeId, String storeUserId, StoreInfo storeInfo) {
|
|
|
+ try {
|
|
|
+ // 查询身份证OCR识别记录(根据storeUserId和ocrType=ID_CARD)
|
|
|
+ List<OcrImageUpload> idCardOcrList = ocrImageUploadMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<OcrImageUpload>()
|
|
|
+ .eq(OcrImageUpload::getStoreUserId, storeUserId)
|
|
|
+ .eq(OcrImageUpload::getOcrType, OcrTypeEnum.ID_CARD.getCode())
|
|
|
+ .orderByDesc(OcrImageUpload::getCreateTime)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(idCardOcrList)) {
|
|
|
+ log.info("未找到身份证OCR记录,storeUserId={}", storeUserId);
|
|
|
+ // 没有OCR记录时,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setIdCardStatus(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String idCardFrontUrl = null;
|
|
|
+ String idCardBackUrl = null;
|
|
|
+ Date idCardExpirationTime = null;
|
|
|
+
|
|
|
+ // 遍历OCR记录,区分正面和反面
|
|
|
+ for (OcrImageUpload ocrRecord : idCardOcrList) {
|
|
|
+ if (StringUtils.isEmpty(ocrRecord.getOcrResult())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 解析OCR结果JSON
|
|
|
+ com.alibaba.fastjson2.JSONObject ocrResultJson = com.alibaba.fastjson2.JSONObject.parseObject(ocrRecord.getOcrResult());
|
|
|
+
|
|
|
+ // 检查是正面还是反面
|
|
|
+ if (ocrResultJson.containsKey("face")) {
|
|
|
+ // 身份证正面
|
|
|
+ idCardFrontUrl = ocrRecord.getImageUrl();
|
|
|
+ log.info("找到身份证正面图片,URL={}", idCardFrontUrl);
|
|
|
+ } else if (ocrResultJson.containsKey("back")) {
|
|
|
+ // 身份证反面
|
|
|
+ idCardBackUrl = ocrRecord.getImageUrl();
|
|
|
+ log.info("找到身份证反面图片,URL={}", idCardBackUrl);
|
|
|
+
|
|
|
+ // 从反面OCR结果中提取有效期限
|
|
|
+ com.alibaba.fastjson2.JSONObject backData = ocrResultJson.getJSONObject("back");
|
|
|
+ if (backData != null) {
|
|
|
+ com.alibaba.fastjson2.JSONObject data = backData.getJSONObject("data");
|
|
|
+ if (data != null) {
|
|
|
+ String validPeriod = data.getString("validPeriod");
|
|
|
+ if (StringUtils.isNotEmpty(validPeriod)) {
|
|
|
+ idCardExpirationTime = parseIdCardExpirationDate(validPeriod);
|
|
|
+ if (idCardExpirationTime != null) {
|
|
|
+ log.info("解析身份证有效期限成功,过期时间:{}", idCardExpirationTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析身份证OCR结果失败,ocrRecordId={}", ocrRecord.getId(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存身份证正面图片到store_img表(img_type=33)
|
|
|
+ if (StringUtils.isNotEmpty(idCardFrontUrl)) {
|
|
|
+ StoreImg frontImg = new StoreImg();
|
|
|
+ frontImg.setStoreId(storeId);
|
|
|
+ frontImg.setImgType(33);
|
|
|
+ frontImg.setImgSort(1);
|
|
|
+ frontImg.setImgDescription("身份证正面");
|
|
|
+ frontImg.setImgUrl(idCardFrontUrl);
|
|
|
+ storeImgMapper.insert(frontImg);
|
|
|
+ log.info("保存身份证正面图片成功,storeId={}, imgUrl={}", storeId, idCardFrontUrl);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存身份证反面图片到store_img表(img_type=34)
|
|
|
+ if (StringUtils.isNotEmpty(idCardBackUrl)) {
|
|
|
+ StoreImg backImg = new StoreImg();
|
|
|
+ backImg.setStoreId(storeId);
|
|
|
+ backImg.setImgType(34);
|
|
|
+ backImg.setImgSort(2);
|
|
|
+ backImg.setImgDescription("身份证反面");
|
|
|
+ backImg.setImgUrl(idCardBackUrl);
|
|
|
+ storeImgMapper.insert(backImg);
|
|
|
+ log.info("保存身份证反面图片成功,storeId={}, imgUrl={}", storeId, idCardBackUrl);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置身份证状态和过期时间
|
|
|
+ if (StringUtils.isNotEmpty(idCardFrontUrl) || StringUtils.isNotEmpty(idCardBackUrl)) {
|
|
|
+ // 有身份证图片时,设置状态为"待审核"(字典值2,使用foodLicenceStatus字典)
|
|
|
+ storeInfo.setIdCardStatus(2);
|
|
|
+ storeInfo.setUpdateIdCardTime(new Date());
|
|
|
+ if (idCardExpirationTime != null) {
|
|
|
+ storeInfo.setIdCardExpirationTime(idCardExpirationTime);
|
|
|
+ }
|
|
|
+ log.info("设置身份证状态为待审核,过期时间:{}", idCardExpirationTime);
|
|
|
+ } else {
|
|
|
+ // 没有身份证图片时,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setIdCardStatus(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("保存身份证图片失败,storeId={}, storeUserId={}", storeId, storeUserId, e);
|
|
|
+ // 发生异常时,初始化状态为"未提交"(字典值0)
|
|
|
+ storeInfo.setIdCardStatus(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析身份证有效期限
|
|
|
+ * 身份证OCR返回格式:validPeriod="2023.05.29-2033.05.29"
|
|
|
+ *
|
|
|
+ * @param validPeriod 有效期限字符串,格式:"2023.05.29-2033.05.29"
|
|
|
+ * @return 到期日期,如果解析失败则返回null
|
|
|
+ */
|
|
|
+ private Date parseIdCardExpirationDate(String validPeriod) {
|
|
|
+ if (StringUtils.isEmpty(validPeriod)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理"长期"或"永久"情况
|
|
|
+ if (validPeriod.contains("长期") || validPeriod.contains("永久")) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 身份证格式:2023.05.29-2033.05.29,提取结束日期
|
|
|
+ if (validPeriod.contains("-")) {
|
|
|
+ String[] parts = validPeriod.split("-");
|
|
|
+ if (parts.length >= 2) {
|
|
|
+ String endDateStr = parts[1].trim();
|
|
|
+ // 将 "2023.05.29" 格式转换为 "2023-05-29"
|
|
|
+ endDateStr = endDateStr.replace(".", "-");
|
|
|
+ return parseDateString(endDateStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果格式不匹配,尝试直接解析
|
|
|
+ String normalizedDateStr = validPeriod.replace(".", "-");
|
|
|
+ return parseDateString(normalizedDateStr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("解析身份证有效期限失败,validPeriod={}", validPeriod, e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public StoreInfoVo getClientStoreDetail(String storeId, String userId, String jingdu, String weidu) {
|
|
|
StoreInfoVo result = new StoreInfoVo();
|