8 changed files with 422 additions and 17 deletions
@ -0,0 +1,122 @@ |
|||||
|
package com.zdxt.enforcementcode.controller.app.enforcement; |
||||
|
|
||||
|
import cn.dev33.satoken.annotation.SaIgnore; |
||||
|
import cn.hutool.core.util.StrUtil; |
||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
|
import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo; |
||||
|
import com.zdxt.enforcementcode.domain.vo.QrCodeGenerateHistoryVo; |
||||
|
import com.zdxt.enforcementcode.service.IEnterpriseInformationService; |
||||
|
import com.zdxt.enforcementcode.service.IQrCodeGenerateHistoryService; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.dromara.common.core.domain.R; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Slf4j |
||||
|
@RequiredArgsConstructor |
||||
|
@RestController |
||||
|
@RequestMapping("/app-enf/enterpriseInfo") |
||||
|
public class AppEnfEnterpriseInformationController { |
||||
|
|
||||
|
private final IEnterpriseInformationService enterpriseInformationService; |
||||
|
private final IQrCodeGenerateHistoryService qrCodeGenerateHistoryService; |
||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); |
||||
|
|
||||
|
/** |
||||
|
* 扫描二维码后获取企业信息(多级降级查询) |
||||
|
* <p> |
||||
|
* 查询优先级: |
||||
|
* 1. 通过 salt 查找企业信息 |
||||
|
* 2. 通过 codeId 查找二维码记录,再通过 enterpriseNumber 查找企业信息 |
||||
|
* 3. 通过二维码中的 enterpriseNumber 直接查找企业信息 |
||||
|
* </p> |
||||
|
* |
||||
|
* @param qrContent 前端解析二维码获取的原始文本内容 |
||||
|
* @return 企业信息(含二维码状态) |
||||
|
*/ |
||||
|
@SaIgnore |
||||
|
@GetMapping("/getEntInfoByQRCode") |
||||
|
public R<EnterpriseInformationVo> getEntInfoByQRCode(@RequestParam("qrContent") String qrContent) { |
||||
|
log.info("执法端扫码获取企业信息,二维码内容: {}", qrContent); |
||||
|
|
||||
|
// 1. 判断 qrContent 是否为 JSON,是则转为 Map,否则打印日志
|
||||
|
Map<String, String> qrMap = null; |
||||
|
try { |
||||
|
qrMap = OBJECT_MAPPER.readValue(qrContent, new TypeReference<Map<String, String>>() {}); |
||||
|
log.info("二维码内容解析为JSON: {}", qrMap); |
||||
|
} catch (Exception e) { |
||||
|
log.warn("二维码内容不是JSON格式,原始内容: {}", qrContent); |
||||
|
} |
||||
|
|
||||
|
EnterpriseInformationVo enterprise = null; |
||||
|
String salt = qrMap != null ? qrMap.get("salt") : null; |
||||
|
String codeId = qrMap != null ? qrMap.get("codeId") : null; |
||||
|
String enterpriseNumber = qrMap != null ? qrMap.get("enterpriseNumber") : null; |
||||
|
|
||||
|
// 2. 优先通过 salt 查找企业信息
|
||||
|
if (StrUtil.isNotBlank(salt)) { |
||||
|
enterprise = enterpriseInformationService.queryBySalt(salt); |
||||
|
if (enterprise != null) { |
||||
|
log.info("通过 salt 查询到企业信息: {}", enterprise.getEnterpriseName()); |
||||
|
} else { |
||||
|
log.info("通过 salt[{}] 未查询到企业信息,进入降级处理", salt); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 3. 降级:通过 codeId 查找二维码记录,再通过 enterpriseNumber 查找企业信息
|
||||
|
if (enterprise == null && StrUtil.isNotBlank(codeId)) { |
||||
|
QrCodeGenerateHistoryVo qrHistory = qrCodeGenerateHistoryService.queryById(codeId); |
||||
|
if (qrHistory != null && StrUtil.isNotBlank(qrHistory.getEnterpriseNumber())) { |
||||
|
enterprise = enterpriseInformationService.queryByEnterpriseNumber(qrHistory.getEnterpriseNumber()); |
||||
|
if (enterprise != null) { |
||||
|
log.info("通过 codeId[{}] -> enterpriseNumber[{}] 查询到企业信息: {}", |
||||
|
codeId, qrHistory.getEnterpriseNumber(), enterprise.getEnterpriseName()); |
||||
|
} else { |
||||
|
log.info("通过 codeId[{}] -> enterpriseNumber[{}] 未查询到企业信息", |
||||
|
codeId, qrHistory.getEnterpriseNumber()); |
||||
|
} |
||||
|
} else { |
||||
|
log.info("通过 codeId[{}] 未查询到二维码记录或记录中无 enterpriseNumber", codeId); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 4. 最终降级:通过二维码中的 enterpriseNumber 直接查找企业信息
|
||||
|
if (enterprise == null && StrUtil.isNotBlank(enterpriseNumber)) { |
||||
|
enterprise = enterpriseInformationService.queryByEnterpriseNumber(enterpriseNumber); |
||||
|
if (enterprise != null) { |
||||
|
log.info("通过二维码中的 enterpriseNumber[{}] 直接查询到企业信息: {}", |
||||
|
enterpriseNumber, enterprise.getEnterpriseName()); |
||||
|
} else { |
||||
|
log.info("通过 enterpriseNumber[{}] 未查询到企业信息", enterpriseNumber); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (enterprise == null) { |
||||
|
return R.fail("无法通过该二维码识别企业信息"); |
||||
|
} |
||||
|
|
||||
|
// 5. 校验二维码是否有效
|
||||
|
boolean qrCodeValid = false; |
||||
|
String checkCodeId = codeId; |
||||
|
// 如果二维码中没有 codeId,尝试用企业上的 qrCodeId
|
||||
|
if (StrUtil.isBlank(checkCodeId) && StrUtil.isNotBlank(enterprise.getQrCodeId())) { |
||||
|
checkCodeId = enterprise.getQrCodeId(); |
||||
|
} |
||||
|
if (StrUtil.isNotBlank(checkCodeId)) { |
||||
|
QrCodeGenerateHistoryVo qrCode = qrCodeGenerateHistoryService.queryById(checkCodeId); |
||||
|
if (qrCode != null && qrCode.getStatus() != null && qrCode.getStatus() == 0L) { |
||||
|
qrCodeValid = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 6. 设置二维码状态并返回
|
||||
|
enterprise.setQrCodeValid(qrCodeValid); |
||||
|
enterprise.setQrCodeMessage(qrCodeValid ? "二维码正常" : "二维码已过期"); |
||||
|
|
||||
|
log.info("执法端扫码查询成功,企业: {},二维码状态: {}", enterprise.getEnterpriseName(), qrCodeValid ? "正常" : "过期"); |
||||
|
return R.ok(enterprise); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,229 @@ |
|||||
|
<template> |
||||
|
<div class="home app_content"> |
||||
|
<!-- 返回首页 --> |
||||
|
<span class="tohome" @click="toEnforcementHome"> |
||||
|
<i class="van-badge__wrapper van-icon van-icon-wap-home-o"></i> |
||||
|
</span> |
||||
|
|
||||
|
<!-- 中间 --> |
||||
|
<div class="warp_body"> |
||||
|
<div class="white-body"> |
||||
|
<!-- Tab 切换 --> |
||||
|
<div class="tabs"> |
||||
|
<ul> |
||||
|
<li v-for="(item, index) in tabList" :key="index" |
||||
|
@click="currentTab = index" |
||||
|
:class="{ active: index === currentTab }"> |
||||
|
<span>{{ item.title }}</span> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 企业画像 Tab --> |
||||
|
<div v-if="currentTab === 0" class="tab-content"> |
||||
|
<div v-if="enterpriseData" class="enterprise-info"> |
||||
|
<van-cell-group inset> |
||||
|
<van-cell title="企业名称" :value="enterpriseData.enterpriseName" /> |
||||
|
<van-cell title="纳税识别号" :value="enterpriseData.enterpriseNumber" /> |
||||
|
<van-cell title="企业类型" :value="enterpriseData.enterpriseType" /> |
||||
|
<van-cell title="法定代表人" :value="enterpriseData.legalPerson" /> |
||||
|
<van-cell title="注册资本" :value="enterpriseData.registeredCapital" /> |
||||
|
<van-cell title="成立日期" :value="formatDate(enterpriseData.establishmentTime)" /> |
||||
|
<van-cell title="营业期限" :value="enterpriseData.operatingTerm" /> |
||||
|
<van-cell title="企业地址" :value="enterpriseData.enterpriseAddress" :label="enterpriseData.enterpriseAddress" /> |
||||
|
<van-cell title="经营范围" :label="enterpriseData.businessScope" /> |
||||
|
<van-cell title="联系电话" :value="enterpriseData.enterpriseTel" /> |
||||
|
<van-cell title="所属行业" :value="enterpriseData.industry" /> |
||||
|
</van-cell-group> |
||||
|
</div> |
||||
|
<van-empty v-else description="暂无企业信息" /> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 执法记录 Tab --> |
||||
|
<div v-if="currentTab === 1" class="tab-content"> |
||||
|
<van-empty description="执法记录功能待对接" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 登记按钮 --> |
||||
|
<div class="addinfo" @click="toSign">登记</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="EnterpriseScanPreview"> |
||||
|
import { ref, onMounted } from 'vue'; |
||||
|
import { useRouter, useRoute } from 'vue-router'; |
||||
|
import { showFailToast } from 'vant'; |
||||
|
|
||||
|
const router = useRouter(); |
||||
|
const route = useRoute(); |
||||
|
|
||||
|
// ========== 数据 ========== |
||||
|
const currentTab = ref(0); |
||||
|
const tabList = [ |
||||
|
{ title: '企业画像', value: '0' }, |
||||
|
{ title: '执法记录', value: '1' }, |
||||
|
]; |
||||
|
const enterpriseData = ref(null); |
||||
|
const enterpriseNumber = ref(''); |
||||
|
const qrCodeValid = ref(false); |
||||
|
|
||||
|
// ========== 初始化加载 ========== |
||||
|
onMounted(() => { |
||||
|
// 从 sessionStorage 读取扫码页传递的企业信息 |
||||
|
const cached = sessionStorage.getItem('enterpriseScanData'); |
||||
|
if (cached) { |
||||
|
try { |
||||
|
const data = JSON.parse(cached); |
||||
|
enterpriseData.value = data; |
||||
|
enterpriseNumber.value = data.enterpriseNumber || ''; |
||||
|
qrCodeValid.value = !!data.qrCodeValid; |
||||
|
console.log('企业详情加载成功(来自缓存):', data.enterpriseName); |
||||
|
} catch (e) { |
||||
|
console.error('解析企业缓存数据失败', e); |
||||
|
showFailToast('企业信息解析失败'); |
||||
|
} |
||||
|
} else { |
||||
|
showFailToast('缺少企业信息,请重新扫码'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// ========== 工具方法 ========== |
||||
|
const formatDate = (dateStr) => { |
||||
|
if (!dateStr) return ''; |
||||
|
const d = new Date(dateStr); |
||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; |
||||
|
}; |
||||
|
|
||||
|
// ========== 页面跳转 ========== |
||||
|
const toEnforcementHome = () => { |
||||
|
router.push({ path: '/enforcement/enforcementHome' }); |
||||
|
}; |
||||
|
|
||||
|
const toSign = () => { |
||||
|
router.push({ |
||||
|
path: '/sign', |
||||
|
query: { |
||||
|
enterpriseNumber: enterpriseNumber.value, |
||||
|
reason: route?.query?.reason || '', |
||||
|
checkCss: route?.query?.checkCss || '', |
||||
|
isNoScan: route?.query?.isNoScan || 'false', |
||||
|
}, |
||||
|
}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.home { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
overflow: hidden; |
||||
|
background-color: #ebf3fb; |
||||
|
|
||||
|
.warp_body { |
||||
|
position: relative; |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
background-image: linear-gradient(to bottom, #ebf3fb, transparent); |
||||
|
} |
||||
|
|
||||
|
.white-body { |
||||
|
margin: 0 3%; |
||||
|
width: 94%; |
||||
|
min-height: 100vh; |
||||
|
background-color: #fff; |
||||
|
border-radius: 0.27rem; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.tohome { |
||||
|
position: absolute; |
||||
|
top: 1.25%; |
||||
|
right: 5%; |
||||
|
font-size: 0.5rem; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
.tabs { |
||||
|
padding: 3% 3% 0; |
||||
|
width: 94%; |
||||
|
height: 1.25rem; |
||||
|
box-sizing: content-box; |
||||
|
} |
||||
|
|
||||
|
.tabs ul { |
||||
|
display: flex; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
font-size: 0.4rem; |
||||
|
line-height: 1.25rem; |
||||
|
text-align: center; |
||||
|
align-content: center; |
||||
|
justify-items: center; |
||||
|
} |
||||
|
|
||||
|
.tabs ul li { |
||||
|
float: left; |
||||
|
width: 50%; |
||||
|
height: 100%; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.tabs ul li span { |
||||
|
display: block; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
color: #4aa1f9; |
||||
|
background: #e6f0fd; |
||||
|
border-radius: 0.15rem; |
||||
|
} |
||||
|
|
||||
|
.tabs ul li.active span { |
||||
|
background: linear-gradient(135deg, #3b82f6, #2563eb); |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.tab-content { |
||||
|
padding: 0.3rem; |
||||
|
} |
||||
|
|
||||
|
.enterprise-info { |
||||
|
:deep(.van-cell) { |
||||
|
padding: 0.25rem 0.35rem; |
||||
|
font-size: 0.35rem; |
||||
|
} |
||||
|
:deep(.van-cell__title) { |
||||
|
color: #999; |
||||
|
flex: none; |
||||
|
width: 2.5rem; |
||||
|
} |
||||
|
:deep(.van-cell__value) { |
||||
|
color: #333; |
||||
|
} |
||||
|
:deep(.van-cell__label) { |
||||
|
color: #666; |
||||
|
font-size: 0.32rem; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.addinfo { |
||||
|
position: absolute; |
||||
|
bottom: 3%; |
||||
|
right: 2%; |
||||
|
z-index: 99999; |
||||
|
width: 1.5rem; |
||||
|
height: 1.5rem; |
||||
|
background-color: #1367fe; |
||||
|
border-radius: 50%; |
||||
|
box-shadow: 0 0 0.27rem #1367fe; |
||||
|
color: #fff; |
||||
|
font-size: 0.4rem; |
||||
|
text-align: center; |
||||
|
vertical-align: middle; |
||||
|
padding-top: 0.45rem; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue