chuangte_bike_newxcx/page_shanghu/upload_license.vue

1449 lines
43 KiB
Vue
Raw Normal View History

2025-12-20 14:29:10 +08:00
<template>
<view class="page">
<u-navbar :title="isViewMode ? '企业认证信息' : '营业执照'" :border-bottom="false" :background="bgc" title-color='#fff' back-icon-color="#fff"
title-size='36' height='45'></u-navbar>
<view class="content">
<!-- 状态卡片 -->
<view class="status-card" v-if="isViewMode && status" :class="statusClass" :style="statusCardStyle">
<view class="status-header">
<view class="status-icon">
<u-icon :name="getStatusIcon()" :size="48" :color="getStatusIconColor()"></u-icon>
</view>
<view class="status-content">
<view class="status-title">{{getStatusText()}}</view>
<view class="status-desc">{{getStatusDesc()}}</view>
</view>
</view>
<view class="reject-reason" v-if="normalizedStatus === 'REJECT' && auditRemark">
<view class="reason-label">驳回原因</view>
<view class="reason-text">{{auditRemark}}</view>
</view>
</view>
<view class="upload-section">
<view class="section-title">上传营业执照</view>
<view class="upload-box" @click="chooseLicenseImage" v-if="!licenseImage && (!isViewMode || normalizedStatus === 'REJECT')">
<image class="upload-icon" src="https://api.ccttiot.com/smartmeter/img/static/udgL6KzisrZlMrk9AZb2" mode=""></image>
<text class="upload-tip">点击上传营业执照照片</text>
<text class="upload-desc">支持 JPGPNG 格式大小不超过 5MB</text>
</view>
<view class="upload-preview" v-else-if="licenseImage">
<image :src="licenseImage" mode="aspectFit" class="preview-img"></image>
<view class="preview-actions" v-if="!isViewMode || normalizedStatus === 'REJECT'">
<view class="action-btn" @click="chooseLicenseImage">重新上传</view>
<view class="action-btn delete" @click="removeLicenseImage" v-if="!isViewMode || normalizedStatus === 'REJECT'">删除</view>
</view>
</view>
<view class="upload-preview" v-else-if="isViewMode && !licenseImage">
<view class="empty-img">
<text>暂无营业执照图片</text>
</view>
</view>
</view>
<view class="form-section">
<view class="section-title">企业信息</view>
<view class="form-item">
<view class="form-label">公司名称 <text class="required" v-if="!isViewMode || normalizedStatus === 'REJECT'">*</text></view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="licenseName" placeholder="请输入公司名称" maxlength="100" />
<view v-else class="form-text">{{licenseName || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">企业简称</view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="licenseAlias" placeholder="请输入企业简称" maxlength="50" />
<view v-else class="form-text">{{licenseAlias || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">统一社会信用代码 <text class="required" v-if="!isViewMode || normalizedStatus === 'REJECT'">*</text></view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="licenseNo" placeholder="请输入统一社会信用代码" maxlength="50" />
<view v-else class="form-text">{{licenseNo || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">企业地址</view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="licenseAddress" placeholder="请输入企业地址" maxlength="200" />
<view v-else class="form-text">{{licenseAddress || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">有效期起始</view>
<picker v-if="!isViewMode || normalizedStatus === 'REJECT'" mode="date" :value="licenseStartTime" @change="onLicenseStartTimeChange">
<view class="picker-input">
<text :class="licenseStartTime ? '' : 'placeholder-text'">{{licenseStartTime || '请选择有效期起始日期'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</picker>
<view v-else class="form-text">{{licenseStartTime || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">有效期结束</view>
<picker v-if="!isViewMode || normalizedStatus === 'REJECT'" mode="date" :value="licenseEndTime" @change="onLicenseEndTimeChange">
<view class="picker-input">
<text :class="licenseEndTime ? '' : 'placeholder-text'">{{licenseEndTime || '请选择有效期结束日期'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</picker>
<view v-else class="form-text">{{licenseEndTime || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">是否长期</view>
<u-switch v-if="!isViewMode || normalizedStatus === 'REJECT'" v-model="licenseIsLongTime" size="24"></u-switch>
<view v-else class="form-text">{{licenseIsLongTime ? '是' : '否'}}</view>
</view>
</view>
<view class="upload-section">
<view class="section-title">法人身份证照片</view>
<view class="idcard-upload-row">
<view class="idcard-upload-item">
<view class="upload-label">身份证人像面</view>
<view class="upload-box-small" @click="chooseIdCardFace" v-if="!legalIdCardFace && (!isViewMode || normalizedStatus === 'REJECT')">
<image class="upload-icon-small" src="https://api.ccttiot.com/smartmeter/img/static/udgL6KzisrZlMrk9AZb2" mode=""></image>
<text class="upload-tip-small">点击上传</text>
</view>
<view class="upload-preview-small" v-else-if="legalIdCardFace">
<image :src="legalIdCardFace" mode="aspectFit" class="preview-img-small"></image>
<view class="preview-actions-small" v-if="!isViewMode || normalizedStatus === 'REJECT'">
<view class="action-btn-small" @click="chooseIdCardFace">重新上传</view>
<view class="action-btn-small delete" @click="removeIdCardFace">删除</view>
</view>
</view>
<view class="upload-preview-small" v-else-if="isViewMode && !legalIdCardFace">
<view class="empty-img-small">
<text>暂无图片</text>
</view>
</view>
</view>
<view class="idcard-upload-item">
<view class="upload-label">身份证国徽面</view>
<view class="upload-box-small" @click="chooseIdCardNational" v-if="!legalIdCardNational && (!isViewMode || normalizedStatus === 'REJECT')">
<image class="upload-icon-small" src="https://api.ccttiot.com/smartmeter/img/static/udgL6KzisrZlMrk9AZb2" mode=""></image>
<text class="upload-tip-small">点击上传</text>
</view>
<view class="upload-preview-small" v-else-if="legalIdCardNational">
<image :src="legalIdCardNational" mode="aspectFit" class="preview-img-small"></image>
<view class="preview-actions-small" v-if="!isViewMode || normalizedStatus === 'REJECT'">
<view class="action-btn-small" @click="chooseIdCardNational">重新上传</view>
<view class="action-btn-small delete" @click="removeIdCardNational">删除</view>
</view>
</view>
<view class="upload-preview-small" v-else-if="isViewMode && !legalIdCardNational">
<view class="empty-img-small">
<text>暂无图片</text>
</view>
</view>
</view>
</view>
</view>
<view class="form-section">
<view class="section-title">法人信息</view>
<view class="form-item">
<view class="form-label">法人姓名 <text class="required" v-if="!isViewMode || normalizedStatus === 'REJECT'">*</text></view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="legalName" placeholder="请输入法人姓名" maxlength="20" />
<view v-else class="form-text">{{legalName || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">法人身份证 <text class="required" v-if="!isViewMode || normalizedStatus === 'REJECT'">*</text></view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="legalIdCard" placeholder="请输入法人身份证号码" maxlength="18" type="idcard" />
<view v-else class="form-text">{{legalIdCard || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">法人手机号</view>
<input v-if="!isViewMode || normalizedStatus === 'REJECT'" class="form-input" v-model="legalMobile" placeholder="请输入法人手机号" maxlength="11" type="number" />
<view v-else class="form-text">{{legalMobile || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">法人身份证有效期起始</view>
<picker v-if="!isViewMode || normalizedStatus === 'REJECT'" mode="date" :value="legalStartTime" @change="onLegalStartTimeChange">
<view class="picker-input">
<text :class="legalStartTime ? '' : 'placeholder-text'">{{legalStartTime || '请选择身份证有效期起始日期'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</picker>
<view v-else class="form-text">{{legalStartTime || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">法人身份证有效期结束</view>
<picker v-if="!isViewMode || normalizedStatus === 'REJECT'" mode="date" :value="legalEndTime" @change="onLegalEndTimeChange">
<view class="picker-input">
<text :class="legalEndTime ? '' : 'placeholder-text'">{{legalEndTime || '请选择身份证有效期结束日期'}}</text>
<u-icon name="arrow-right" size="28" color="#999"></u-icon>
</view>
</picker>
<view v-else class="form-text">{{legalEndTime || '未填写'}}</view>
</view>
<view class="form-item">
<view class="form-label">是否长期身份证</view>
<u-switch v-if="!isViewMode || normalizedStatus === 'REJECT'" v-model="legalIsLongTime" size="24"></u-switch>
<view v-else class="form-text">{{legalIsLongTime ? '是' : '否'}}</view>
</view>
</view>
<view class="tips-section">
<view class="tips-title">温馨提示</view>
<view class="tips-item">1. 请确保营业执照信息清晰可见</view>
<view class="tips-item">2. 营业执照需在有效期内</view>
<view class="tips-item">3. 请如实填写企业信息信息需与营业执照一致</view>
<view class="tips-item">4. 上传后请等待审核审核通过后方可使用</view>
</view>
</view>
<view class="bottom-btn"
:class="bottomBtnClass"
@click="handleBottomBtnClick()"
v-if="!isViewMode || normalizedStatus === 'REJECT' || (isViewMode && status)">
<text>{{getBottomBtnText()}}</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
bgc: {
backgroundColor: "#4886F1",
},
licenseImage: '',
token: '',
licenseId: null, // 编辑时的ID
submitting: false,
licenseName: '', // 公司名称
licenseNo: '', // 统一社会信用代码
legalName: '', // 法人姓名
legalIdCard: '', // 法人身份证
isViewMode: false, // 是否为查看模式
status: '', // 审核状态WAIT_AUDIT(待审核)、SUCCESS(通过)、REJECT(驳回)
auditRemark: '', // 驳回原因
// 新增字段
licenseStartTime: '', // 有效期起始
licenseEndTime: '', // 有效期结束
licenseIsLongTime: false, // 是否长期
licenseAlias: '', // 企业简称
licenseAddress: '', // 企业地址
legalMobile: '', // 法人手机号
legalIdCardNational: '', // 法人身份证国徽面
legalIdCardFace: '', // 法人身份证人像面
legalStartTime: '', // 法人身份证有效期起始
legalEndTime: '', // 法人身份证有效期结束
legalIsLongTime: false // 是否长期身份证
}
},
computed: {
// 标准化状态值(计算属性)
normalizedStatus() {
if(!this.status) return ''
const statusUpper = String(this.status).toUpperCase()
// 支持多种可能的格式
if(statusUpper.includes('WAIT') || statusUpper.includes('AUDIT')){
return 'WAIT_AUDIT'
}
if(statusUpper.includes('SUCCESS') || statusUpper.includes('PASS') || statusUpper.includes('APPROVE')){
return 'SUCCESS'
}
if(statusUpper.includes('REJECT') || statusUpper.includes('REFUSE') || statusUpper.includes('FAIL')){
return 'REJECT'
}
return statusUpper
},
// 状态样式类(用于 :class
statusClass() {
const classMap = {
'WAIT_AUDIT': 'status-wait',
'SUCCESS': 'status-success',
'REJECT': 'status-reject'
}
return classMap[this.normalizedStatus] || ''
},
// 状态卡片样式(用于 :style
statusCardStyle() {
const styleMap = {
'WAIT_AUDIT': {
background: 'linear-gradient(135deg, #FFF7E6 0%, #FFFFFF 100%)',
'border-left': '6rpx solid #FF9500'
},
'SUCCESS': {
background: 'linear-gradient(135deg, #F6FFED 0%, #FFFFFF 100%)',
'border-left': '6rpx solid #52C41A'
},
'REJECT': {
background: 'linear-gradient(135deg, #FFF1F0 0%, #FFFFFF 100%)',
'border-left': '6rpx solid #FF4D4F'
}
}
return styleMap[this.normalizedStatus] || {}
},
// 底部按钮样式类(用于 :class
bottomBtnClass() {
if(this.isViewMode && this.normalizedStatus === 'REJECT'){
return 'btn-resubmit'
}
return ''
}
},
onLoad(option) {
// 获取userId
let userId = option.userId || ''
if(!userId){
// 如果没有userId尝试从存储中获取
let user = uni.getStorageSync('user')
userId = user ? user.userId : ''
}
if(!userId){
// 如果还是没有通过getInfo获取
this.$u.get("/getInfo").then((resp) => {
if(resp.code == 200 && resp.user && resp.user.userId){
this.checkEnterpriseAuth(resp.user.userId)
} else {
// 没有userId直接显示提交界面
this.isViewMode = false
this.getQiniuToken()
}
}).catch(() => {
// 获取失败,直接显示提交界面
this.isViewMode = false
this.getQiniuToken()
})
} else {
// 有userId检查是否有认证数据
this.checkEnterpriseAuth(userId)
}
// 如果有ID说明是编辑模式先获取已有数据
if(option.id){
this.licenseId = option.id
this.getLicenseInfo()
}
},
methods: {
// OCR识别
recognizeImage(type, url) {
let apiUrl = ''
if (type === 'license') {
apiUrl = '/common/ocr/businessLicense'
} else if (type === 'face') {
apiUrl = '/common/ocr/idCardFace'
} else if (type === 'national') {
apiUrl = '/common/ocr/idCardBack'
}
if (!apiUrl) {
uni.hideLoading()
return
}
// uploadImage 已经开启了 loading这里更新文字即可
uni.showLoading({
title: '智能识别中...',
mask: true
})
this.$u.get(apiUrl, {
url: url
}).then(res => {
uni.hideLoading()
console.log('OCR识别结果:', res)
if (res.code == 200 && res.data) {
this.fillFormData(type, res.data)
uni.showToast({
title: '识别成功',
icon: 'success'
})
} else {
uni.showToast({
title: '识别信息不全,请手动填写',
icon: 'none'
})
}
}).catch(err => {
uni.hideLoading()
console.error('OCR识别错误:', err)
uni.showToast({
title: '识别服务异常,请手动填写',
icon: 'none'
})
})
},
// 填充OCR数据
fillFormData(type, data) {
if (type === 'license') {
// 营业执照
// 兼容多种 OCR 返回格式,优先匹配用户提供的格式
this.licenseName = data.companyName || data.name || this.licenseName
this.licenseNo = data.creditCode || data.regNum || this.licenseNo
this.legalName = data.legalPerson || data.person || this.legalName
this.licenseAddress = data.businessAddress || data.address || this.licenseAddress
// 有效期起始
const startDate = data.validFromDate || data.registrationDate || data.establishDate
if (startDate) {
this.licenseStartTime = this.formatOCRDate(startDate)
}
// 有效期结束
// 检查 validToDate
if (data.validToDate) {
if (data.validToDate.includes('长期')) {
this.licenseIsLongTime = true
this.licenseEndTime = ''
} else {
this.licenseEndTime = this.formatOCRDate(data.validToDate)
this.licenseIsLongTime = false
}
}
// 检查 validPeriod (例如 "2023-05-24至长期")
else if (data.validPeriod) {
if (data.validPeriod.includes('长期')) {
this.licenseIsLongTime = true
this.licenseEndTime = ''
} else {
// 尝试解析范围字符串
// ... 简单的逻辑,如果不是长期,可能需要用户手动填
}
}
} else if (type === 'face') {
// 身份证人像面
if (data.name) this.legalName = data.name
// 兼容 idNumber 和 idNum
if (data.idNumber) this.legalIdCard = data.idNumber
else if (data.idNum) this.legalIdCard = data.idNum
} else if (type === 'national') {
// 身份证国徽面
// 优先使用 validStartDate / validEndDate
if (data.validStartDate) {
this.legalStartTime = this.formatOCRDate(data.validStartDate)
}
if (data.validEndDate) {
if (data.validEndDate === '长期' || data.validEndDate.includes('长期')) {
this.legalIsLongTime = true
this.legalEndTime = ''
} else {
this.legalEndTime = this.formatOCRDate(data.validEndDate)
this.legalIsLongTime = false
}
} else if (data.validDate) {
// 旧格式兼容 "20200101-20400101"
const dates = data.validDate.split('-')
if (dates.length >= 1 && !this.legalStartTime) {
this.legalStartTime = this.formatOCRDate(dates[0])
}
if (dates.length >= 2 && !this.legalEndTime && !this.legalIsLongTime) {
if (dates[1] === '长期') {
this.legalIsLongTime = true
this.legalEndTime = ''
} else {
this.legalEndTime = this.formatOCRDate(dates[1])
this.legalIsLongTime = false
}
}
}
}
},
// 辅助格式化OCR日期 (例如 YYYYMMDD -> YYYY-MM-DD)
formatOCRDate(dateStr) {
if (!dateStr) return ''
// 移除可能存在的点或横杠,统一处理
let cleanStr = String(dateStr).replace(/\./g, '').replace(/-/g, '')
if (cleanStr.length === 8) {
return `${cleanStr.substring(0, 4)}-${cleanStr.substring(4, 6)}-${cleanStr.substring(6, 8)}`
}
return dateStr // 无法处理则原样返回
},
// 获取七牛云上传token
getQiniuToken() {
this.$u.get("/common/qiniuToken").then((res) => {
if (res.code == 200) {
this.token = res.data
}
})
},
// 检查企业认证信息(判断是否有数据)
checkEnterpriseAuth(userId) {
this.$u.get(`/bst/enterpriseAuth/last?userId=${userId}`).then((res) => {
if(res.code == 200 && res.data && res.data.id){
// 有数据,显示查看模式
this.isViewMode = true
// 填充表单字段(基础字段)
this.licenseImage = res.data.licenseUrl || res.data.licenseImage || ''
this.licenseName = res.data.licenseName || ''
this.licenseNo = res.data.licenseNo || ''
this.legalName = res.data.legalName || ''
this.legalIdCard = res.data.legalIdCard || ''
this.status = res.data.status || ''
this.auditRemark = res.data.auditRemark || res.data.rejectReason || ''
// 填充新增字段(企业信息)
this.licenseStartTime = this.formatDate(res.data.licenseStartTime)
this.licenseEndTime = this.formatDate(res.data.licenseEndTime)
this.licenseIsLongTime = res.data.licenseIsLongTime === true || res.data.licenseIsLongTime === 1 || res.data.licenseIsLongTime === '1'
this.licenseAlias = res.data.licenseAlias || ''
this.licenseAddress = res.data.licenseAddress || ''
// 填充新增字段(法人信息)
this.legalMobile = res.data.legalMobile || ''
this.legalIdCardNational = res.data.legalIdCardNational || res.data.legalIdCardBack || ''
this.legalIdCardFace = res.data.legalIdCardFace || res.data.legalIdCardFront || ''
this.legalStartTime = this.formatDate(res.data.legalStartTime)
this.legalEndTime = this.formatDate(res.data.legalEndTime)
this.legalIsLongTime = res.data.legalIsLongTime === true || res.data.legalIsLongTime === 1 || res.data.legalIsLongTime === '1'
// 调试:打印完整数据
console.log('企业认证数据:', JSON.stringify(res.data))
// 如果是驳回状态需要获取token以便重新提交
// 使用 $nextTick 确保 computed 属性已更新
this.$nextTick(() => {
if(this.normalizedStatus === 'REJECT'){
this.getQiniuToken()
}
// 调试:打印状态值
console.log('认证状态:', this.status, '标准化后:', this.normalizedStatus)
})
} else {
// 没有数据或数据为空,显示提交界面
this.isViewMode = false
this.getQiniuToken()
}
}).catch(() => {
// 请求失败,显示提交界面
this.isViewMode = false
this.getQiniuToken()
})
},
// 获取营业执照信息(编辑模式)
getLicenseInfo() {
this.$u.get("/app/userLicense/byType?licenseType=1").then((res) => {
if(res.code == 200 && res.data && res.data.id){
// 兼容多种可能的字段名
this.licenseImage = res.data.licenseUrl || res.data.businessLicenseUrl || res.data.url || ''
this.licenseId = res.data.id
// 填充表单字段
this.licenseName = res.data.licenseName || ''
this.licenseNo = res.data.licenseNo || ''
this.legalName = res.data.legalName || ''
this.legalIdCard = res.data.legalIdCard || ''
// 填充新增字段
this.licenseStartTime = res.data.licenseStartTime ? this.formatDate(res.data.licenseStartTime) : ''
this.licenseEndTime = res.data.licenseEndTime ? this.formatDate(res.data.licenseEndTime) : ''
this.licenseIsLongTime = res.data.licenseIsLongTime || false
this.licenseAlias = res.data.licenseAlias || ''
this.licenseAddress = res.data.licenseAddress || ''
this.legalMobile = res.data.legalMobile || ''
this.legalIdCardNational = res.data.legalIdCardNational || ''
this.legalIdCardFace = res.data.legalIdCardFace || ''
this.legalStartTime = res.data.legalStartTime ? this.formatDate(res.data.legalStartTime) : ''
this.legalEndTime = res.data.legalEndTime ? this.formatDate(res.data.legalEndTime) : ''
this.legalIsLongTime = res.data.legalIsLongTime || false
}
}).catch(() => {
// 如果获取失败,可能是新增模式
})
},
// 选择营业执照图片
chooseLicenseImage() {
this.uploadImage('license')
},
// 删除图片
removeLicenseImage() {
uni.showModal({
title: '提示',
content: '确定要删除已上传的营业执照吗?',
success: (res) => {
if(res.confirm){
this.licenseImage = ''
}
}
})
},
// 提交营业执照
submitLicense() {
if(!this.licenseImage){
uni.showToast({
title: '请先上传营业执照',
icon: 'none',
duration:3000
})
return
}
if(!this.licenseName || !this.licenseName.trim()){
uni.showToast({
title: '请输入公司名称',
icon: 'none',
duration:3000
})
return
}
if(!this.licenseNo || !this.licenseNo.trim()){
uni.showToast({
title: '请输入统一社会信用代码',
icon: 'none',
duration:3000
})
return
}
if(!this.legalName || !this.legalName.trim()){
uni.showToast({
title: '请输入法人姓名',
icon: 'none',
duration:3000
})
return
}
if(!this.legalIdCard || !this.legalIdCard.trim()){
uni.showToast({
title: '请输入法人身份证号码',
icon: 'none',
duration:3000
})
return
}
// 验证身份证格式(简单验证)
if(this.legalIdCard.length !== 15 && this.legalIdCard.length !== 18){
uni.showToast({
title: '请输入正确的身份证号码',
icon: 'none',
duration:3000
})
return
}
if(this.submitting){
return
}
this.submitting = true
let user = uni.getStorageSync('user')
let userId = user ? user.userId : ''
if(!userId){
// 如果没有userId尝试从getInfo获取
this.$u.get("/getInfo").then((resp) => {
if(resp.code == 200 && resp.user && resp.user.userId){
this.submitData(resp.user.userId)
} else {
this.submitting = false
uni.showToast({
title: '获取用户信息失败,请重新登录',
icon: 'none',
duration:3000
})
}
}).catch(() => {
this.submitting = false
uni.showToast({
title: '获取用户信息失败,请重新登录',
icon: 'none',
duration:3000
})
})
} else {
this.submitData(userId)
}
},
// 获取状态文本
getStatusText() {
const statusMap = {
'WAIT_AUDIT': '审核中',
'SUCCESS': '已审核',
'REJECT': '已驳回'
}
return statusMap[this.normalizedStatus] || '未知状态'
},
// 获取状态描述
getStatusDesc() {
const descMap = {
'WAIT_AUDIT': '您的企业认证信息正在审核中,请耐心等待',
'SUCCESS': '恭喜!您的企业认证已通过审核',
'REJECT': '您的企业认证未通过审核,请根据驳回原因修改后重新提交'
}
return descMap[this.normalizedStatus] || ''
},
// 获取状态图标
getStatusIcon() {
const iconMap = {
'WAIT_AUDIT': 'clock',
'SUCCESS': 'checkmark-circle',
'REJECT': 'close-circle'
}
return iconMap[this.normalizedStatus] || 'info-circle'
},
// 获取状态图标颜色
getStatusIconColor() {
const colorMap = {
'WAIT_AUDIT': '#FF9500',
'SUCCESS': '#52C41A',
'REJECT': '#FF4D4F'
}
return colorMap[this.normalizedStatus] || '#999'
},
// 获取底部按钮文字
getBottomBtnText() {
if(this.isViewMode){
if(this.normalizedStatus === 'REJECT'){
return '重新提交'
} else {
return '返回'
}
} else {
return '提交'
}
},
// 处理底部按钮点击
handleBottomBtnClick() {
if(this.isViewMode){
if(this.normalizedStatus === 'REJECT'){
// 驳回状态,允许重新提交
this.submitLicense()
} else {
// 其他状态,返回
this.goBack()
}
} else {
// 非查看模式,提交
this.submitLicense()
}
},
// 返回
goBack() {
uni.navigateBack()
},
// 日期选择器变化事件
onLicenseStartTimeChange(e) {
this.licenseStartTime = e.detail.value
},
onLicenseEndTimeChange(e) {
this.licenseEndTime = e.detail.value
},
onLegalStartTimeChange(e) {
this.legalStartTime = e.detail.value
},
onLegalEndTimeChange(e) {
this.legalEndTime = e.detail.value
},
// 格式化日期(从后端格式转换为前端显示格式)
formatDate(dateStr) {
if(!dateStr) return ''
// 处理各种可能的日期格式
let date = String(dateStr)
// 如果是 "yyyy-MM-dd HH:mm:ss" 或 "yyyy-MM-ddTHH:mm:ss" 格式,只取日期部分
if(date.includes(' ')){
return date.split(' ')[0]
}
if(date.includes('T')){
return date.split('T')[0]
}
// 如果已经是 yyyy-MM-dd 格式,直接返回
if(date.match(/^\d{4}-\d{2}-\d{2}$/)){
return date
}
return date
},
// 格式化日期时间为后端格式(只返回日期部分,不包含时分秒)
formatDateTime(dateStr) {
if(!dateStr) return null
// 只取日期部分,去掉时分秒
let date = String(dateStr)
// 如果包含空格,只取日期部分
if(date.includes(' ')){
return date.split(' ')[0]
}
// 如果包含T只取日期部分
if(date.includes('T')){
return date.split('T')[0]
}
// 如果已经是 yyyy-MM-dd 格式,直接返回
if(date.length === 10 && date.match(/^\d{4}-\d{2}-\d{2}$/)){
return date
}
// 其他情况,尝试提取日期部分
return date.substring(0, 10)
},
// 选择身份证人像面
chooseIdCardFace() {
if(!this.token){
uni.showToast({
title: '上传token获取失败请重试',
icon: 'none',
duration:3000
})
return
}
this.uploadImage('face')
},
// 选择身份证国徽面
chooseIdCardNational() {
if(!this.token){
uni.showToast({
title: '上传token获取失败请重试',
icon: 'none',
duration:3000
})
return
}
this.uploadImage('national')
},
// 删除身份证人像面
removeIdCardFace() {
uni.showModal({
title: '提示',
content: '确定要删除已上传的身份证人像面吗?',
success: (res) => {
if(res.confirm){
this.legalIdCardFace = ''
}
}
})
},
// 删除身份证国徽面
removeIdCardNational() {
uni.showModal({
title: '提示',
content: '确定要删除已上传的身份证国徽面吗?',
success: (res) => {
if(res.confirm){
this.legalIdCardNational = ''
}
}
})
},
// 上传图片(通用方法,支持类型参数)
uploadImage(type) {
if(!this.token){
uni.showToast({
title: '上传token获取失败请重试',
icon: 'none',
duration:3000
})
return
}
let _this = this
let math = 'static/' + _this.$u.guid(20)
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success(res) {
const tempFilePaths = res.tempFilePaths[0]
// 检查文件大小5MB
uni.getFileInfo({
filePath: tempFilePaths,
success(fileInfo) {
if(fileInfo.size > 5 * 1024 * 1024){
uni.showToast({
title: '图片大小不能超过5MB',
icon: 'none',
duration:3000
})
return
}
// 显示上传加载提示
uni.showLoading({
title: '图片上传中...',
mask: true
})
// 上传到七牛云
wx.uploadFile({
url: 'https://up-z2.qiniup.com',
name: 'file',
filePath: tempFilePaths,
formData: {
token: _this.token,
key: 'smartmeter/img/' + math
},
success: function(res) {
try {
let str = JSON.parse(res.data)
let imageUrl = 'https://api.ccttiot.com/' + str.key
// 根据类型设置对应的图片
if(type === 'face'){
_this.legalIdCardFace = imageUrl
} else if(type === 'national'){
_this.legalIdCardNational = imageUrl
} else {
_this.licenseImage = imageUrl
}
// 不在这里隐藏 loading而是转到识别
// uni.showToast({
// title: '上传成功',
// icon: 'success',
// duration:3000
// })
// 触发OCR识别
_this.recognizeImage(type, imageUrl)
} catch(e) {
uni.hideLoading()
uni.showToast({
title: '上传失败,请重试',
icon: 'none',
duration:3000
})
}
},
fail: function() {
uni.hideLoading()
uni.showToast({
title: '上传失败,请重试',
icon: 'none',
duration:3000
})
}
})
}
})
}
})
},
// 提交数据
submitData(userId) {
let data = {
userId: userId,
licenseType: 1,
licenseUrl: this.licenseImage,
licenseName: this.licenseName.trim(),
licenseNo: this.licenseNo.trim(),
legalName: this.legalName.trim(),
legalIdCard: this.legalIdCard.trim(),
// 新增字段
licenseStartTime: this.licenseStartTime ? this.formatDateTime(this.licenseStartTime) : null,
licenseEndTime: this.licenseEndTime ? this.formatDateTime(this.licenseEndTime) : null,
licenseIsLongTime: this.licenseIsLongTime,
licenseAlias: this.licenseAlias.trim(),
licenseAddress: this.licenseAddress.trim(),
legalMobile: this.legalMobile.trim(),
legalIdCardNational: this.legalIdCardNational,
legalIdCardFace: this.legalIdCardFace,
legalStartTime: this.legalStartTime ? this.formatDateTime(this.legalStartTime) : null,
legalEndTime: this.legalEndTime ? this.formatDateTime(this.legalEndTime) : null,
legalIsLongTime: this.legalIsLongTime
}
// 如果是编辑模式使用PUT请求
let url = `/bst/enterpriseAuth`
let method = 'post'
this.$u[method](url, data).then((res) => {
this.submitting = false
if(res.code == 200){
uni.showToast({
title: this.licenseId ? '更新成功' : '提交成功',
icon: 'success',
duration: 2000
})
setTimeout(() => {
let pages = getCurrentPages()
if(pages.length > 1){
let prevPage = pages[pages.length - 2]
if(prevPage && typeof prevPage.getchaxun === 'function'){
prevPage.getchaxun()
}
}
uni.navigateBack()
}, 1500)
} else {
uni.showToast({
title: res.msg || '提交失败',
icon: 'none',
duration:2000
})
}
}).catch(() => {
this.submitting = false
uni.showToast({
title: '提交失败,请重试',
icon: 'none',
duration:2000
})
})
}
}
}
</script>
<style lang="scss">
page {
background: #F8FAFC;
}
.page {
min-height: 100vh;
padding-bottom: 220rpx;
position: relative;
overflow-x: hidden;
// 背景装饰光斑
&::before {
content: '';
position: absolute;
top: -100rpx;
right: -100rpx;
width: 600rpx;
height: 600rpx;
background: radial-gradient(circle, rgba(37, 99, 235, 0.08) 0%, rgba(37, 99, 235, 0) 70%);
border-radius: 50%;
pointer-events: none;
z-index: 0;
}
&::after {
content: '';
position: absolute;
top: 20%;
left: -200rpx;
width: 500rpx;
height: 500rpx;
background: radial-gradient(circle, rgba(139, 92, 246, 0.06) 0%, rgba(139, 92, 246, 0) 70%);
border-radius: 50%;
pointer-events: none;
z-index: 0;
}
}
.content {
padding: 32rpx;
position: relative;
z-index: 1;
}
// 通用卡片样式 - 玻璃质感微调
.card {
background: rgba(255, 255, 255, 0.95);
border-radius: 32rpx;
box-shadow: 0 4rpx 6rpx -1rpx rgba(0, 0, 0, 0.02),
0 10rpx 15rpx -3rpx rgba(0, 0, 0, 0.04),
0 0 0 1rpx rgba(0, 0, 0, 0.02); // 极细边框替代 border
overflow: hidden;
backdrop-filter: blur(10px);
}
// 状态卡片
.status-card {
@extend .card;
margin-bottom: 32rpx;
position: relative;
padding: 0 0 20rpx 0;
.status-header {
display: flex;
align-items: flex-start;
padding: 36rpx;
padding-bottom: 24rpx;
gap: 28rpx;
}
.status-icon {
width: 96rpx;
height: 96rpx;
border-radius: 28rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
box-shadow: inset 0 0 0 1rpx rgba(255,255,255,0.2);
}
.status-content {
flex: 1;
padding-top: 4rpx;
.status-title {
font-size: 34rpx;
font-weight: 800;
color: #1e293b;
margin-bottom: 8rpx;
letter-spacing: -0.5rpx;
}
.status-desc {
font-size: 26rpx;
color: #64748b;
line-height: 1.5;
}
}
.reject-reason {
margin: 0 36rpx 24rpx;
padding: 24rpx;
border-radius: 20rpx;
background: #FEF2F2;
border: 1rpx solid rgba(254, 202, 202, 0.5);
.reason-label {
font-size: 24rpx;
font-weight: 700;
color: #EF4444;
margin-bottom: 8rpx;
display: flex;
align-items: center;
&::before {
content: '';
display: inline-block;
width: 8rpx;
height: 8rpx;
background: #EF4444;
border-radius: 50%;
margin-right: 12rpx;
}
}
.reason-text {
font-size: 26rpx;
color: #7F1D1D;
line-height: 1.6;
}
}
&.status-wait {
.status-icon {
background: linear-gradient(135deg, #FFF7ED 0%, #FEF3C7 100%);
color: #D97706;
}
}
&.status-success {
.status-icon {
background: linear-gradient(135deg, #F0FDF4 0%, #DCFCE7 100%);
color: #059669;
}
}
&.status-reject {
.status-icon {
background: linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%);
color: #DC2626;
}
}
}
// 分段标题
.section-title {
font-size: 32rpx;
font-weight: 800;
color: #0f172a;
margin-bottom: 32rpx;
display: flex;
align-items: center;
&::after {
content: '';
flex: 1;
height: 2rpx;
background: linear-gradient(to right, #F1F5F9 0%, transparent 100%);
margin-left: 24rpx;
}
}
// 上传区域
.upload-section {
@extend .card;
padding: 40rpx;
margin-bottom: 32rpx;
.upload-box {
width: 100%;
height: 380rpx;
border-radius: 28rpx;
border: 3rpx dashed #CBD5E1;
background: linear-gradient(180deg, #F8FAFC 0%, #F1F5F9 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 16rpx;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&:active {
transform: scale(0.99);
border-color: #3B82F6;
background: #EFF6FF;
}
.upload-icon {
width: 108rpx;
height: 108rpx;
opacity: 0.9;
filter: drop-shadow(0 4rpx 6rpx rgba(0,0,0,0.05));
}
.upload-tip {
font-size: 30rpx;
font-weight: 700;
color: #334155;
}
.upload-desc {
font-size: 24rpx;
color: #94a3b8;
}
}
.upload-preview {
.preview-img {
width: 100%;
height: 500rpx;
border-radius: 28rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.08);
object-fit: cover;
}
.empty-img {
height: 400rpx;
border-radius: 28rpx;
background: #F8FAFC;
border: 2rpx dashed #E2E8F0;
display: flex;
align-items: center;
justify-content: center;
text {
font-size: 28rpx;
color: #94a3b8;
font-weight: 500;
}
}
.preview-actions {
margin-top: 32rpx;
display: flex;
gap: 24rpx;
.action-btn {
flex: 1;
height: 88rpx;
border-radius: 24rpx;
text-align: center;
line-height: 88rpx;
font-size: 28rpx;
font-weight: 700;
background: #EFF6FF;
color: #2563eb;
transition: all 0.2s;
border: 1rpx solid rgba(37, 99, 235, 0.1);
&:active { transform: scale(0.98); }
&.delete {
background: #FEF2F2;
color: #DC2626;
border-color: rgba(220, 38, 38, 0.1);
}
}
}
}
}
// 表单区域
.form-section {
@extend .card;
padding: 40rpx;
margin-bottom: 32rpx;
.form-item {
margin-bottom: 32rpx;
&:last-child { margin-bottom: 0; }
.form-label {
font-size: 28rpx;
color: #475569;
margin-bottom: 16rpx;
font-weight: 600;
display: flex;
align-items: center;
.required {
color: #EF4444;
margin-left: 8rpx;
font-size: 32rpx;
line-height: 1;
}
}
.form-input, .form-text, .picker-input {
width: 100%;
min-height: 100rpx;
background: #F8FAFC;
border: 2rpx solid transparent;
border-radius: 24rpx;
padding: 0 32rpx;
font-size: 30rpx;
color: #0f172a;
box-sizing: border-box;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:focus {
background: #ffffff;
border-color: #3B82F6;
box-shadow: 0 0 0 6rpx rgba(59, 130, 246, 0.1);
}
}
.form-text {
padding: 30rpx 32rpx;
line-height: 1.6;
color: #334155;
}
.picker-input {
display: flex;
align-items: center;
justify-content: space-between;
text { color: #0f172a; }
.placeholder-text { color: #94a3b8; }
}
}
}
// 身份证上传
.idcard-upload-row {
display: flex;
gap: 24rpx;
.idcard-upload-item { flex: 1; }
.upload-label {
font-size: 26rpx;
color: #475569;
margin-bottom: 16rpx;
text-align: center;
font-weight: 600;
}
}
.upload-box-small {
height: 240rpx;
background: #F8FAFC;
border: 3rpx dashed #CBD5E1;
border-radius: 24rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12rpx;
transition: all 0.2s;
&:active {
border-color: #3B82F6;
background: #EFF6FF;
}
.upload-icon-small { width: 64rpx; height: 64rpx; opacity: 0.7; }
.upload-tip-small { font-size: 24rpx; color: #64748B; font-weight: 500; }
}
.upload-preview-small {
height: 240rpx;
border-radius: 24rpx;
overflow: hidden;
position: relative;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
border: 1rpx solid rgba(0,0,0,0.05);
.preview-img-small { width: 100%; height: 100%; object-fit: cover; }
.preview-actions-small {
position: absolute;
left: 0; right: 0; bottom: 0;
display: flex;
gap: 16rpx;
padding: 16rpx;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(8rpx);
border-top: 1rpx solid rgba(255,255,255,0.5);
.action-btn-small {
flex: 1;
height: 60rpx;
line-height: 60rpx;
text-align: center;
border-radius: 16rpx;
font-size: 24rpx;
font-weight: 700;
color: #ffffff;
background: #3B82F6;
color: #fff;
box-shadow: 0 2rpx 6rpx rgba(59, 130, 246, 0.2);
&.delete { background: #EF4444; box-shadow: 0 2rpx 6rpx rgba(239, 68, 68, 0.2); }
}
}
.empty-img-small {
width: 100%; height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #F8FAFC;
color: #94a3b8;
font-size: 24rpx;
}
}
.tips-section {
@extend .card;
padding: 32rpx;
background: #F8FAFC;
border: 1rpx solid #E2E8F0;
box-shadow: none;
.tips-title {
font-size: 28rpx;
font-weight: 700;
color: #64748B;
margin-bottom: 16rpx;
}
.tips-item {
font-size: 24rpx;
color: #94A3B8;
line-height: 1.6;
margin-bottom: 8rpx;
}
}
// 底部按钮
.bottom-btn {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 180rpx;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40rpx;
z-index: 999;
pointer-events: none;
// 底部渐变遮罩,防止内容滚动时与按钮重叠太乱
background: linear-gradient(to top, rgba(248,250,252,0.9) 0%, rgba(248,250,252,0) 100%);
text {
pointer-events: auto;
width: 90%;
height: 100rpx;
border-radius: 50rpx;
line-height: 100rpx;
text-align: center;
font-size: 32rpx;
font-weight: 800;
color: #ffffff;
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
box-shadow: 0 20rpx 40rpx -10rpx rgba(37, 99, 235, 0.4);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
letter-spacing: 2rpx;
&:active {
transform: scale(0.96);
box-shadow: 0 10rpx 20rpx -5rpx rgba(37, 99, 235, 0.3);
}
}
&.btn-resubmit text {
background: linear-gradient(135deg, #EF4444 0%, #DC2626 100%);
box-shadow: 0 20rpx 40rpx -10rpx rgba(220, 38, 38, 0.4);
}
}
</style>