mrr.sj.front/pages/ruzhu/sj-info.vue

1651 lines
50 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="sj-info-page">
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">营业执照</text>
</view>
<view class="form-item-one box-cont">
<text class="label required">资质照片</text>
<text class="upload-desc">请保证照片上的文字清晰无遮挡证件边角可见</text>
<view class="" @click="chooseImage('uscc_photo')">
<image v-if="formData.uscc_photo" :src="formData.uscc_photo" mode="aspectFill" class="upload-preview"></image>
<view class="" v-else>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/fa75ea1c-8f9d-4b2a-8d0c-b94de516afd0.png"
mode="widthFix" class="upload-camera-img"></image>
</view>
</view>
<text class="required placeholder1">请上传营业执照原件</text>
</view>
<view class="form-item-two box-cont">
<text class="label required">商户类型</text>
<input type="text" v-model="formData.uscc_type" placeholder="请输入商户类型" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-two box-cont">
<view class="label-wrapper">
<text class="label required">证件号码</text>
<image class="label-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/25bd7f38-1a3e-4282-84ea-190d7f820108"
mode="aspectFit" @click="showTipPopup('uscc_num')"></image>
</view>
<input type="text" v-model="formData.uscc_num" placeholder="请输入营业执照的证件号码" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-two box-cont">
<view class="label-wrapper">
<text class="label required">企业名称</text>
<image class="label-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/25bd7f38-1a3e-4282-84ea-190d7f820108"
mode="aspectFit" @click="showTipPopup('uscc_name')"></image>
</view>
<input type="text" v-model="formData.uscc_name" placeholder="请输入营业执照的企业名称" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-two box-cont" @click="showRegionPicker">
<text class="label required">注册地区</text>
<view class="picker-content">
<text :class="formData.uscc_dependency ? 'picker-value' : 'placeholder1'">
{{ formData.uscc_dependency || '请选择' }}
</text>
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/dccc4513-377c-4bfa-9fd2-a5cfdb9798f3"
class="arrow-right" mode="aspectFit"></image>
</view>
</view>
<view class="form-item-two box-cont" @click="getAddressInfo">
<text class="label required">注册详细地址</text>
<view class="picker-content">
<text :class="formData.uscc_address ? 'picker-value' : 'placeholder'">
{{ formData.uscc_address || '请选择' }}
</text>
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/dccc4513-377c-4bfa-9fd2-a5cfdb9798f3"
class="arrow-right" mode="aspectFit"></image>
</view>
</view>
</view>
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">法人信息</text>
</view>
<view class="form-item-one box-cont">
<text class="label required">身份证照片</text>
<text class="upload-desc">请保证照片上的文字清晰、无遮挡、证件边角可见</text>
<view class="upload-area" @click="chooseImage('legal_idcard_positive')">
<image v-if="formData.legal_idcard_positive" :src="formData.legal_idcard_positive" mode="aspectFill"
class="upload-preview">
</image>
<view class="" v-else>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/fa75ea1c-8f9d-4b2a-8d0c-b94de516afd0.png"
mode="widthFix" class="upload-camera-img" style="margin-left: -30rpx;"></image>
</view>
<text class="placeholder1 required">请上传身份证正面(人像面)</text>
</view>
<view class="upload-area" @click="chooseImage('legal_idcard_negative')" style="margin-top: 48rpx;">
<image v-if="formData.legal_idcard_negative" :src="formData.legal_idcard_negative" mode="aspectFill"
class="upload-preview">
</image>
<view class="" v-else>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/fa75ea1c-8f9d-4b2a-8d0c-b94de516afd0.png"
mode="widthFix" class="upload-camera-img" style="margin-left: -30rpx;"></image>
</view>
<text class="placeholder1 required">请上传身份证反面(国徽面)</text>
</view>
</view>
<view class="form-item-two box-cont">
<view class="label-wrapper">
<text class="label required">法人代表</text>
<image class="label-icon"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/25bd7f38-1a3e-4282-84ea-190d7f820108"
mode="aspectFit" @click="showTipPopup('legal_name')"></image>
</view>
<input type="text" v-model="formData.legal_name" placeholder="请输入营业执照的法人代表" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-two box-cont">
<text class="label required">法人联系方式</text>
<input type="number" v-model="formData.legal_phone" placeholder="请输入法人的联系方式" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-two box-cont">
<text class="label required">法人身份证号</text>
<input type="text" v-model="formData.legal_idcard_num" placeholder="请输入法人的身份证号码" placeholder-class="placeholder"
class="input" />
</view>
<view class="form-item-column box-cont">
<text class="label required">身份证有效期:</text>
<view class="radio-group">
<view class="radio-item" @click="setIdcardExpiryType('1')">
<view class="radio" :class="{ checked: formData.legal_idcard_expiry_type === '1' }">
<image v-if="formData.legal_idcard_expiry_type === '1'" src="/static/images/agree_y.png"
class="radio-icon-image" mode="aspectFit"></image>
</view>
<text class="radio-label">永久有效</text>
</view>
<view class="radio-item" @click="setIdcardExpiryType('2')">
<view class="radio" :class="{ checked: formData.legal_idcard_expiry_type === '2' }">
<image v-if="formData.legal_idcard_expiry_type === '2'" src="/static/images/agree_y.png"
class="radio-icon-image" mode="aspectFit"></image>
</view>
<text class="radio-label">指定日期有效</text>
</view>
</view>
</view>
<view class="date-row box-cont">
<view class="date-col" @click="showDatePicker('start')">
<text class="date-label">开始日期</text>
<view class="date-input-box">
<text :class="formData.legal_idcard_expiry_start ? 'date-value' : 'date-placeholder'">
{{ formData.legal_idcard_expiry_start || '选择日期' }}
</text>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5b01823b-7672-4e60-b6cc-a4de52294605.png"
class="date-icon" mode="aspectFit"></image>
</view>
</view>
<view class="date-col" @click="showDatePicker('end')">
<text class="date-label">结束日期</text>
<view class="date-input-box">
<text :class="formData.legal_idcard_expiry_end ? 'date-value' : 'date-placeholder'">
{{ formData.legal_idcard_expiry_end || '选择日期' }}
</text>
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/5b01823b-7672-4e60-b6cc-a4de52294605.png"
class="date-icon" mode="aspectFit"></image>
</view>
</view>
</view>
</view>
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">其他信息</text>
</view>
<view class="form-item-one box-cont">
<text class="label">行业资质</text>
<view class="image-list">
<view class="image-item" v-for="(img, index) in formData.qualifications_sector" :key="'industry-' + index">
<image :src="img" mode="aspectFill" class="qualification-image"></image>
<view class="image-delete" @click="removeImage('qualifications_sector', index)">×</view>
</view>
<view class="image-add" @click="chooseMultiImage('qualifications_sector')"
v-if="(formData.qualifications_sector || []).length < 9">
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0d4af728-c7bf-447d-85b2-e7c682471b86.png"
mode="aspectFit" class="upload-icon-small"></image>
<text class="add-text">添加照片</text>
</view>
</view>
<text class="label" style="margin-top: 30rpx;">其他资质</text>
<view class="image-list">
<view class="image-item" v-for="(img, index) in formData.qualifications_other" :key="'other-' + index">
<image :src="img" mode="aspectFill" class="qualification-image"></image>
<view class="image-delete" @click="removeImage('qualifications_other', index)">×</view>
</view>
<view class="image-add" @click="chooseMultiImage('qualifications_other')"
v-if="(formData.qualifications_other || []).length < 9">
<image
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/0d4af728-c7bf-447d-85b2-e7c682471b86.png"
mode="aspectFit" class="upload-icon-small"></image>
<text class="add-text">添加照片</text>
</view>
</view>
</view>
</view>
<view class="popup" :class="{ show: showRegionPopupFlag }">
<view class="popup-mask" @click="hideRegionPopup"></view>
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">选择注册地区</text>
<text class="popup-close" @click="hideRegionPopup">×</text>
</view>
<view class="region-body">
<picker-view @change="bindChangeRegion" class="picker-scroll" :indicator-style="indicatorStyle"
:value="regionValue">
<picker-view-column>
<view class="picker-item" v-for="(item, index) in ChinaCitys" :key="index">
{{ item.province }}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in regionCitys" :key="index">
{{ item.city }}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in regionAreas" :key="index">
{{ item.area }}
</view>
</picker-view-column>
</picker-view>
</view>
<view class="popup-footer">
<view class="popup-btn cancel" @click="hideRegionPopup">
<text class="btn-text">取消</text>
</view>
<view class="popup-btn confirm" @click="confirmRegionSelect">
<text class="btn-text">确定</text>
</view>
</view>
</view>
</view>
<view class="popup" :class="{ show: showDatePickerFlag }">
<view class="popup-mask" @click="hideDatePicker"></view>
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">{{ currentPickerType === 'start' ? '选择开始日期' : '选择结束日期' }}</text>
<text class="popup-close" @click="hideDatePicker">×</text>
</view>
<view class="region-body">
<picker-view :value="datePickerValue" @change="bindDateChange" class="picker-scroll"
:indicator-style="indicatorStyle">
<picker-view-column>
<view class="picker-item" v-for="(year, index) in years" :key="index">
{{ year }}年
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(month, index) in months" :key="index">
{{ month }}月
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(day, index) in days" :key="index">
{{ day }}
</view>
</picker-view-column>
</picker-view>
</view>
<view class="popup-footer">
<view class="popup-btn cancel" @click="hideDatePicker">
<text class="btn-text">取消</text>
</view>
<view class="popup-btn confirm" @click="confirmDateSelect">
<text class="btn-text">确定</text>
</view>
</view>
</view>
</view>
<view class="tip-popup" :class="{ show: showTipPopupFlag }">
<view class="tip-popup-mask" @click="hideTipPopup"></view>
<view class="tip-popup-content">
<image class="tip-popup-bg"
src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ab410a5d-5819-47f2-a0fc-3fd6b90d6770"
mode="aspectFit"></image>
<view class="tip-popup-body">
<view class="tip-title">{{ tipTitle }}</view>
<view class="tip-image-container">
<image class="tip-image" :class="currentTipType" :src="tipImage" mode="widthFix"></image>
</view>
<view class="tip-buttons">
<view class="tip-btn cancel" @click="hideTipPopup">
<text class="btn-text">取消</text>
</view>
<view class="tip-btn confirm" @click="hideTipPopup">
<text class="btn-text">我已了解</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import request from '../../utils/request';
import ChinaCitys from '../../static/data/ChinaCitys.json';
import { recognizeIdCard, recognizeBusinessLicense, parseValidPeriod } from '../../utils/orc';
export default {
data() {
return {
formData: {
uscc_photo: '',
uscc_type: '',
uscc_num: '',
uscc_name: '',
uscc_dependency: '',
uscc_address: '',
uscc_province: '',
uscc_city: '',
uscc_area: '',
longitude: '',
latitude: '',
legal_idcard_positive: '',
legal_idcard_negative: '',
legal_name: '',
legal_phone: '',
legal_idcard_num: '',
legal_idcard_expiry_type: '1',
legal_idcard_expiry_start: '',
legal_idcard_expiry_end: '',
qualifications_sector: [],
qualifications_other: []
},
ChinaCitys: ChinaCitys,
regionCitys: [],
regionAreas: [],
regionValue: [0, 0, 0],
showRegionPopupFlag: false,
showDatePickerFlag: false,
currentPickerType: 'start',
datePickerValue: [0, 0, 0],
indicatorStyle: 'height: 68rpx;',
isRecognizing: false,
recognizeType: '',
userId: null,
identity: 3,
addressListener: null,
sjAddressListener: null,
showTipPopupFlag: false,
tipTitle: '',
tipImage: '',
currentTipType: ''
}
},
computed: {
years() {
return Array.from({
length: 50
}, (_, i) => 2020 + i);
},
months() {
return Array.from({
length: 12
}, (_, i) => i + 1);
},
days() {
return Array.from({
length: 31
}, (_, i) => i + 1);
}
},
async mounted() {
await this.getUserInfo();
this.regionCitys = this.ChinaCitys[0].citys;
this.regionAreas = this.regionCitys[0].areas;
this.setupAddressListener();
await this.loadDetailsData();
},
beforeDestroy() {
this.removeAddressListener();
},
methods: {
getUserInfo() {
return request.post('/sj/User/getUser').then(result => {
this.userId = result.data.id;
}).catch(err => {
console.error('获取用户信息失败:', err);
});
},
async loadDetailsData() {
try {
const res = await request.post('/sj/userSjAuth/details', {
type: 1
});
if (res.code === 200 && res.data) {
const data = res.data;
this.$set(this.formData, 'uscc_photo', data.uscc_photo || '');
this.$set(this.formData, 'uscc_type', data.uscc_type || '');
this.$set(this.formData, 'uscc_num', data.uscc_num || '');
this.$set(this.formData, 'uscc_name', data.uscc_name || '');
this.$set(this.formData, 'uscc_dependency', data.uscc_dependency || '');
this.$set(this.formData, 'uscc_address', data.uscc_address || '');
this.$set(this.formData, 'uscc_province', data.uscc_province || '');
this.$set(this.formData, 'uscc_city', data.uscc_city || '');
this.$set(this.formData, 'uscc_area', data.uscc_area || '');
this.$set(this.formData, 'longitude', data.longitude || '');
this.$set(this.formData, 'latitude', data.latitude || '');
this.$set(this.formData, 'legal_idcard_positive', data.legal_idcard_positive || '');
this.$set(this.formData, 'legal_idcard_negative', data.legal_idcard_negative || '');
this.$set(this.formData, 'legal_name', data.legal_name || '');
this.$set(this.formData, 'legal_phone', data.legal_phone || '');
this.$set(this.formData, 'legal_idcard_num', data.legal_idcard_num || '');
// 处理身份证有效期legal_idcard_expiry 拆分为 type、start、end
if (data.legal_idcard_expiry) {
const expiry = data.legal_idcard_expiry;
if (expiry === '长久' || expiry === '长久有效') {
this.$set(this.formData, 'legal_idcard_expiry_type', '1');
this.$set(this.formData, 'legal_idcard_expiry_end', '长久有效');
} else if (expiry.includes('——') || expiry.includes('--') || expiry.includes('-')) {
const separator = expiry.includes('——') ? '——' : (expiry.includes('--') ? '--' : '-');
const [startStr, endStr] = expiry.split(separator);
const startDate = startStr.trim();
const endDate = endStr.trim();
this.$set(this.formData, 'legal_idcard_expiry_start', startDate);
if (endDate === '长久' || !endDate) {
this.$set(this.formData, 'legal_idcard_expiry_type', '1');
this.$set(this.formData, 'legal_idcard_expiry_end', '长久有效');
} else {
this.$set(this.formData, 'legal_idcard_expiry_type', '2');
this.$set(this.formData, 'legal_idcard_expiry_end', endDate);
}
}
} else {
this.$set(this.formData, 'legal_idcard_expiry_type', data.legal_idcard_expiry_type || '1');
this.$set(this.formData, 'legal_idcard_expiry_start', data.legal_idcard_expiry_start || '');
this.$set(this.formData, 'legal_idcard_expiry_end', data.legal_idcard_expiry_end || '');
}
if (data.qualifications_sector) {
this.$set(this.formData, 'qualifications_sector', typeof data.qualifications_sector === 'string' ? JSON.parse(data.qualifications_sector) : data.qualifications_sector);
}
if (data.qualifications_other) {
this.$set(this.formData, 'qualifications_other', typeof data.qualifications_other === 'string' ? JSON.parse(data.qualifications_other) : data.qualifications_other);
}
console.log('sj-info 数据回显完成:', this.formData);
}
} catch (error) {
console.error('获取详情数据失败:', error);
}
},
chooseImage(type) {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: async (res) => {
if (!res.tempFilePaths || res.tempFilePaths.length === 0) return;
const tempFilePath = res.tempFilePaths[0];
const file = {
path: tempFilePath,
size: 0
};
const url = await this.directUpload(file, this.userId, 3);
if (url) {
this.$set(this.formData, type, url);
if (type === 'uscc_photo') {
await this.recognizeBusinessLicense(url);
} else if (type === 'legal_idcard_positive') {
await this.recognizeIdCardFront(url);
} else if (type === 'legal_idcard_negative') {
await this.recognizeIdCardBack(url);
}
}
}
});
},
chooseMultiImage(type) {
const current = this.formData[type] || [];
const remaining = 9 - current.length;
if (remaining <= 0) {
uni.showToast({
title: '最多上传9张图片',
icon: 'none'
});
return;
}
uni.chooseImage({
count: remaining,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: async (res) => {
if (!res.tempFilePaths || res.tempFilePaths.length === 0) return;
uni.showLoading({
title: '上传中...'
});
for (const tempFilePath of res.tempFilePaths) {
const file = {
path: tempFilePath,
size: 0
};
try {
const url = await this.directUpload(file, this.userId, 3);
if (url) {
current.push(url);
}
} catch (e) {
console.error('上传失败:', e);
}
}
this.$set(this.formData, type, current);
uni.hideLoading();
}
});
},
removeImage(type, index) {
const list = [...this.formData[type]];
list.splice(index, 1);
this.$set(this.formData, type, list);
},
async directUpload(file, userId, type) {
try {
let date = new Date().getTime();
let artisan = type == 1 ? 'yh' : type == 2 ? 'syr' : type == 3 ? 'sj' : '';
let fileExtension = 'jpg';
if (file.path.includes('.')) {
let parts = file.path.split('.');
let ext = parts[parts.length - 1].toLowerCase();
if (ext && ext.length <= 4) fileExtension = ext;
}
let name = `${userId}_${artisan}_${date}.${fileExtension}`;
const ossConfig = await request.post('/user/getalioss', {
type: type,
kind: 1
});
return await new Promise((resolve, reject) => {
uni.uploadFile({
url: ossConfig.host,
filePath: file.path,
name: 'file',
formData: {
key: ossConfig.dir + name,
policy: ossConfig.policy,
OSSAccessKeyId: ossConfig.ossAccessKeyId,
success_action_status: '200',
signature: ossConfig.signature
},
success: (res) => {
if (res.statusCode === 200) {
resolve(`${ossConfig.host}/${ossConfig.dir}${name}`);
} else {
reject(new Error('上传失败'));
}
},
fail: reject
});
});
} catch (error) {
console.error('上传失败:', error);
throw error;
}
},
showRegionPicker() {
this.showRegionPopupFlag = true;
},
hideRegionPopup() {
this.showRegionPopupFlag = false;
},
bindChangeRegion(e) {
this.regionValue = e.detail.value;
let index1 = e.detail.value[0] || 0;
let index2 = e.detail.value[1] || 0;
this.regionCitys = this.ChinaCitys[index1].citys;
this.regionAreas = this.regionCitys[index2].areas;
},
confirmRegionSelect() {
let valueArr = this.regionValue;
let index1 = valueArr[0] || 0;
let index2 = valueArr[1] || 0;
let index3 = valueArr[2] || 0;
let province = this.ChinaCitys[index1].province;
let city = this.regionCitys[index2].city;
let area = this.regionAreas[index3].area;
this.formData.uscc_dependency = province + '-' + city + '-' + area;
if (this.ChinaCitys[index1] && this.ChinaCitys[index1].code) {
this.formData.uscc_province = String(this.ChinaCitys[index1].code).substring(0, 6);
}
if (this.regionCitys[index2] && this.regionCitys[index2].code) {
this.formData.uscc_city = String(this.regionCitys[index2].code).substring(0, 6);
}
if (this.regionAreas[index3] && this.regionAreas[index3].code) {
this.formData.uscc_area = String(this.regionAreas[index3].code).substring(0, 6);
}
this.formData.uscc_address = '';
this.formData.longitude = '';
this.formData.latitude = '';
this.hideRegionPopup();
},
showHouseholdTypePicker() {
this.showRegionPopupFlag = true;
},
hideRegionPopup() {
this.showRegionPopupFlag = false;
},
setIdcardExpiryType(type) {
this.$set(this.formData, 'legal_idcard_expiry_type', type);
if (type === '1') {
this.formData.legal_idcard_expiry_end = '长久有效';
} else {
if (this.formData.legal_idcard_expiry_end === '长久有效') {
this.formData.legal_idcard_expiry_end = '';
}
}
},
showDatePicker(type) {
this.currentPickerType = type;
this.showDatePickerFlag = true;
},
hideDatePicker() {
this.showDatePickerFlag = false;
},
bindDateChange(e) {
this.datePickerValue = e.detail.value;
},
confirmDateSelect() {
const year = this.years[this.datePickerValue[0]];
const month = this.months[this.datePickerValue[1]];
const day = this.days[this.datePickerValue[2]];
const dateStr = `${year}${month < 10 ? '0' + month : month}${day < 10 ? '0' + day : day}`;
if (this.currentPickerType === 'start') {
this.formData.legal_idcard_expiry_start = dateStr;
} else {
this.formData.legal_idcard_expiry_end = dateStr;
}
this.hideDatePicker();
},
buildRegionTextForSearch() {
const dependency = String(this.formData.uscc_dependency || '').trim();
if (!dependency) return '';
const parts = dependency.split('-');
const province = parts[0] || '';
const city = parts[1] || '';
const district = parts[2] || '';
let regionText = '';
if (province) regionText += province;
if (city && city !== province) regionText += city;
if (district) regionText += district;
return regionText;
},
getAddressValueForSearch() {
const rawAddress = String(this.formData.uscc_address || '').trim();
if (!rawAddress) return '';
const dependencyText = String(this.formData.uscc_dependency || '').trim();
const regionText = this.buildRegionTextForSearch();
let detail = rawAddress;
if (regionText && detail.indexOf(regionText) === 0) {
detail = detail.slice(regionText.length).trim();
} else if (dependencyText && detail.indexOf(dependencyText) === 0) {
detail = detail.slice(dependencyText.length).trim();
}
detail = detail.replace(/^[\s,-]+/, '').trim();
return detail || rawAddress;
},
getAddressInfo() {
const dependency = String(this.formData.uscc_dependency || '').trim();
const dependencyCode = String(this.formData.uscc_area || '').trim();
const address = this.getAddressValueForSearch();
const longitude = String(this.formData.longitude || '').trim();
const latitude = String(this.formData.latitude || '').trim();
const hasDependency = !!dependency;
const hasAddress = !!address;
const hasLocation = !!(longitude && latitude);
let params = 'source=sj_info';
if (hasDependency) {
params += `&dependency=${encodeURIComponent(dependency)}`;
if (dependencyCode) {
params += `&dependency_code=${dependencyCode}`;
}
}
if (hasAddress) {
params += `&address=${encodeURIComponent(address)}`;
}
if (hasLocation) {
params += `&longitude=${longitude}&latitude=${latitude}`;
}
if (!hasDependency && !hasAddress && !hasLocation) {
params += '&init_current_location=1&silent_locate=1';
}
uni.navigateTo({
url: `/pages/address/search?${params}`
});
},
setupAddressListener() {
this.addressListener = (addressData) => {
this.handleAddressSelected(addressData);
};
this.sjAddressListener = (addressData) => {
this.handleAddressSelected(addressData);
};
uni.$on('address-selected', this.addressListener);
uni.$on('address-selected-for-sj', this.sjAddressListener);
},
removeAddressListener() {
if (this.addressListener) {
uni.$off('address-selected', this.addressListener);
this.addressListener = null;
}
if (this.sjAddressListener) {
uni.$off('address-selected-for-sj', this.sjAddressListener);
this.sjAddressListener = null;
}
},
checkAddressData() {
try {
const storedAddress = uni.getStorageSync('sj_selected_address');
if (storedAddress) {
this.handleAddressSelected(storedAddress);
uni.removeStorageSync('sj_selected_address');
return;
}
} catch (e) { }
if (getApp().globalData && getApp().globalData.selectedAddress) {
this.handleAddressSelected(getApp().globalData.selectedAddress);
delete getApp().globalData.selectedAddress;
}
try {
const selectedAddress = uni.getStorageSync('selectedAddress');
if (selectedAddress) {
this.handleAddressSelected(selectedAddress);
uni.removeStorageSync('selectedAddress');
}
} catch (e) { }
},
handleAddressSelected(addressData) {
if (!addressData) return;
let detailAddress = '';
if (addressData.address) {
detailAddress = String(addressData.address).trim();
} else if (addressData.name) {
detailAddress = String(addressData.name).trim();
const regionParts = [];
if (addressData.pname) regionParts.push(addressData.pname);
if (addressData.cityname && addressData.cityname !== addressData.pname) regionParts.push(addressData.cityname);
if (addressData.adname) regionParts.push(addressData.adname);
const regionText = regionParts.join('');
if (regionText && detailAddress.indexOf(regionText) === 0) {
detailAddress = detailAddress.slice(regionText.length).trim();
}
detailAddress = detailAddress.replace(/^[\s,-]+/, '').trim();
}
this.$set(this.formData, 'uscc_address', detailAddress);
if (addressData.location) {
const [longitude, latitude] = String(addressData.location).split(',');
this.$set(this.formData, 'longitude', longitude || '');
this.$set(this.formData, 'latitude', latitude || '');
}
if (addressData.pname || addressData.cityname || addressData.adname) {
const locationParts = [];
if (addressData.pname) locationParts.push(addressData.pname);
if (addressData.cityname) locationParts.push(addressData.cityname);
if (addressData.adname) locationParts.push(addressData.adname);
this.$set(this.formData, 'uscc_dependency', locationParts.join('-'));
}
if (addressData.provinceCode) {
this.$set(this.formData, 'uscc_province', String(addressData.provinceCode).substring(0, 6));
}
if (addressData.cityCode) {
this.$set(this.formData, 'uscc_city', String(addressData.cityCode).substring(0, 6));
}
if (addressData.districtCode) {
this.$set(this.formData, 'uscc_area', String(addressData.districtCode).substring(0, 6));
}
this.$forceUpdate();
},
async recognizeBusinessLicense(imageUrl) {
try {
this.isRecognizing = true;
this.recognizeType = 'uscc_photo';
uni.showLoading({ title: '正在识别营业执照...', mask: true });
const result = await recognizeBusinessLicense(imageUrl);
console.log('营业执照识别结果:', result);
const hasRecognizedData = this.checkBusinessLicenseRecognition(result);
if (!hasRecognizedData) {
uni.hideLoading();
uni.showToast({ title: '未识别到营业执照信息,请手动填写或重新拍摄', icon: 'none', duration: 3000 });
this.isRecognizing = false;
return;
}
let recognizedFields = 0;
if (result.uscc_name && result.uscc_name.trim() && result.uscc_name !== '无') {
this.$set(this.formData, 'uscc_name', result.uscc_name);
recognizedFields++;
}
if (result.uscc_num && result.uscc_num.trim()) {
this.$set(this.formData, 'uscc_num', result.uscc_num);
recognizedFields++;
}
if (result.uscc_type && result.uscc_type.trim()) {
this.$set(this.formData, 'uscc_type', result.uscc_type);
recognizedFields++;
}
uni.hideLoading();
if (recognizedFields > 0) {
uni.showToast({ title: '营业执照识别成功', icon: 'none', duration: 2000 });
} else {
uni.showToast({ title: '识别完成,但未获取到有效信息', icon: 'none', duration: 3000 });
}
} catch (error) {
console.error('营业执照识别失败:', error);
uni.hideLoading();
uni.showToast({ title: error.message || '识别失败,请手动填写', icon: 'none', duration: 3000 });
} finally {
this.isRecognizing = false;
}
},
checkBusinessLicenseRecognition(result) {
const requiredFields = ['uscc_num', 'uscc_name', 'uscc_type'];
for (const field of requiredFields) {
if (result[field] && result[field].trim()) return true;
}
return false;
},
async recognizeIdCardFront(imageUrl) {
try {
this.isRecognizing = true;
this.recognizeType = 'legal_idcard_positive';
uni.showLoading({ title: '正在识别身份证正面...', mask: true });
const result = await recognizeIdCard(imageUrl, 1);
const hasRecognizedData = (result.name && result.name.trim()) || (result.id_number && result.id_number.trim());
if (!hasRecognizedData) {
uni.hideLoading();
uni.showToast({ title: '未识别到身份证信息,请手动填写或重新拍摄', icon: 'none', duration: 3000 });
this.isRecognizing = false;
return;
}
if (result.name) {
this.$set(this.formData, 'legal_name', result.name);
}
if (result.id_number) {
this.$set(this.formData, 'legal_idcard_num', result.id_number);
}
uni.hideLoading();
uni.showToast({ title: '身份证正面识别成功', icon: 'none' });
} catch (error) {
console.error('身份证正面识别失败:', error);
uni.hideLoading();
uni.showToast({ title: error.message || '识别失败,请手动填写', icon: 'none', duration: 3000 });
} finally {
this.isRecognizing = false;
}
},
async recognizeIdCardBack(imageUrl) {
try {
this.isRecognizing = true;
this.recognizeType = 'legal_idcard_negative';
uni.showLoading({ title: '正在识别身份证反面...', mask: true });
const result = await recognizeIdCard(imageUrl, 2);
const hasRecognizedData = (result.start_date && result.start_date.trim()) || (result.end_date && result.end_date.trim());
if (!hasRecognizedData) {
uni.hideLoading();
uni.showToast({ title: '未识别到身份证有效期信息,请手动填写或重新拍摄', icon: 'none', duration: 3000 });
this.isRecognizing = false;
return;
}
const validPeriod = parseValidPeriod(result.start_date, result.end_date);
if (validPeriod.startDate) {
this.$set(this.formData, 'legal_idcard_expiry_start', validPeriod.startDate);
}
if (validPeriod.isPermanent) {
this.$set(this.formData, 'legal_idcard_expiry_type', '1');
this.$set(this.formData, 'legal_idcard_expiry_end', '长久有效');
} else if (validPeriod.endDate) {
this.$set(this.formData, 'legal_idcard_expiry_type', '2');
this.$set(this.formData, 'legal_idcard_expiry_end', validPeriod.endDate);
}
uni.hideLoading();
uni.showToast({ title: '身份证反面识别成功', icon: 'none' });
} catch (error) {
console.error('身份证反面识别失败:', error);
uni.hideLoading();
uni.showToast({ title: error.message || '识别失败,请手动填写', icon: 'none', duration: 3000 });
} finally {
this.isRecognizing = false;
}
},
showTipPopup(field) {
const tipConfig = {
'uscc_num': {
title: '如何查看证件号码',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/c5d8d00b-de1e-414f-b310-0a3f99ed8ddb.png'
},
'uscc_name': {
title: '如何查看企业名称',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b8df241d-899f-4f8e-89c5-b61b61a9f1b1.png'
},
'legal_name': {
title: '如何查看法定代表人',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/b8df241d-899f-4f8e-89c5-b61b61a9f1b1.png'
}
};
if (tipConfig[field]) {
this.currentTipType = field;
this.tipTitle = tipConfig[field].title;
this.tipImage = tipConfig[field].image;
this.showTipPopupFlag = true;
}
},
hideTipPopup() {
this.showTipPopupFlag = false;
},
getFormData() {
return this.formData;
},
setData(data) {
if (!data) return;
const keys = Object.keys(this.formData);
keys.forEach(key => {
if (data[key] !== undefined && data[key] !== null) {
this.$set(this.formData, key, data[key]);
}
});
},
saveFormData() {
if (!this.formData.uscc_photo) {
uni.showToast({
title: '请上传营业执照',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_type) {
uni.showToast({
title: '请选择户主类型',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_num) {
uni.showToast({
title: '请输入证件号码',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_name) {
uni.showToast({
title: '请输入企业名称',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_dependency) {
uni.showToast({
title: '请选择注册地区',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_address) {
uni.showToast({
title: '请输入注册详细地址',
icon: 'none'
});
return false;
}
if (!this.formData.legal_idcard_positive) {
uni.showToast({
title: '请上传法人身份证正面',
icon: 'none'
});
return false;
}
if (!this.formData.legal_idcard_negative) {
uni.showToast({
title: '请上传法人身份证反面',
icon: 'none'
});
return false;
}
if (!this.formData.legal_name) {
uni.showToast({
title: '请输入法人代表',
icon: 'none'
});
return false;
}
if (!this.formData.legal_phone) {
uni.showToast({
title: '请输入法人联系方式',
icon: 'none'
});
return false;
}
if (!/^1[3-9]\d{9}$/.test(this.formData.legal_phone)) {
uni.showToast({
title: '请输入正确的手机号码',
icon: 'none'
});
return false;
}
if (!this.formData.legal_idcard_num) {
uni.showToast({
title: '请输入法人身份证号',
icon: 'none'
});
return false;
}
if (!this.formData.legal_idcard_expiry_start) {
uni.showToast({
title: '请选择开始日期',
icon: 'none'
});
return false;
}
if (!this.formData.legal_idcard_expiry_end) {
uni.showToast({
title: '请选择结束日期',
icon: 'none'
});
return false;
}
return true;
}
}
}
</script>
<style scoped>
.sj-info-page {}
.section {
margin-bottom: 30rpx;
}
.section-title {
display: flex;
align-items: center;
padding-bottom: 20rpx;
padding-top: 16rpx;
}
.title-bar {
width: 8rpx;
height: 32rpx;
background-color: #FF4767;
border-radius: 4rpx;
margin-right: 12rpx;
}
.title-text {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #1D2129;
}
.box-cont {
background: #FFFFFF;
border-radius: 20rpx;
margin-bottom: 24rpx;
margin-left: 8rpx;
margin-right: 8rpx;
box-shadow: none;
}
.form-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx;
}
.form-item-one {
display: flex;
flex-direction: column;
padding: 24rpx;
}
.form-item-two {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx;
}
.form-item-column {
display: flex;
flex-direction: column;
padding: 24rpx;
}
.form-item-column .label {
margin-bottom: 24rpx;
}
.date-row {
display: flex;
padding: 24rpx;
}
.date-col {
flex: 1;
display: flex;
flex-direction: column;
}
.date-col:first-child {
margin-right: 24rpx;
}
.date-label {
font-size: 28rpx;
color: #333333;
font-weight: 500;
margin-bottom: 16rpx;
}
.date-input-box {
display: flex;
align-items: center;
justify-content: space-between;
border: 2rpx solid #E8E8E8;
border-radius: 12rpx;
padding: 0 20rpx;
height: 76rpx;
}
.date-value {
font-size: 28rpx;
color: #333333;
}
.date-placeholder {
font-size: 28rpx;
color: #CCCCCC;
}
.date-icon {
width: 36rpx;
height: 36rpx;
flex-shrink: 0;
}
.label-wrapper {
display: inline-flex;
align-items: center;
}
.label {
font-size: 28rpx;
color: #333333;
font-weight: 500;
line-height: 1;
}
.label-icon {
width: 26rpx;
height: 26rpx;
margin-left: 8rpx;
}
.label.required::before {
content: '*';
color: #FF4767;
margin-right: 4rpx;
}
.input {
font-size: 28rpx;
color: #333333;
text-align: right;
flex: 1;
}
.placeholder {
font-size: 28rpx;
color: #CCCCCC;
margin-left: -20rpx;
}
.placeholder1 {
text-align: center;
font-size: 28rpx;
color: #333333;
}
.placeholder1.required::before {
content: '*';
color: #FF4767;
margin-right: 4rpx;
}
.picker-content {
display: flex;
align-items: center;
flex: 1;
justify-content: flex-end;
}
.picker-value {
font-size: 28rpx;
color: #333333;
margin-right: 8rpx;
}
.arrow-right {
width: 24rpx;
height: 24rpx;
flex-shrink: 0;
}
.radio-group {
display: flex;
align-items: center;
}
.radio-item {
display: flex;
align-items: center;
margin-right: 130rpx;
}
.radio {
width: 30rpx;
height: 30rpx;
border: 2rpx solid #DDDDDD;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
}
.radio.checked {
background-color: #FF4767;
border-color: #FF4767;
}
.radio-icon-image {
width: 32rpx;
height: 32rpx;
}
.radio-label {
font-size: 28rpx;
color: #333333;
}
.upload-area {
display: flex;
flex-direction: column;
align-items: center;
}
.upload-preview {
width: 100%;
height: 300rpx;
border-radius: 12rpx;
margin-bottom: 16rpx;
}
.upload-placeholder {
width: 100%;
height: 300rpx;
background: #F7F8FA;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
border: 2rpx dashed #DDDDDD;
}
.upload-icon {
width: 80rpx;
height: 80rpx;
}
.upload-hint {
font-size: 24rpx;
/* color: #FF4767; */
text-align: center;
}
.upload-desc {
font-size: 24rpx;
color: #999999;
margin-bottom: 20rpx;
margin-top: 12rpx;
}
.upload-dashed {
width: 100%;
border: 2rpx dashed #DDDDDD;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx;
margin-bottom: 16rpx;
background: #FAFBFC;
}
.upload-camera-img {
width: 446rpx;
height: 298rpx;
margin-left: 100rpx;
}
.image-list {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
margin-top: 16rpx;
}
.image-item {
position: relative;
width: 200rpx;
height: 200rpx;
}
.qualification-image {
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
}
.image-delete {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 36rpx;
height: 36rpx;
background: #FF4767;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #FFFFFF;
font-size: 28rpx;
}
.image-add {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 2rpx dashed #DDDDDD;
width: 214rpx;
height: 214rpx;
background: #F5F5F5;
border-radius: 20rpx;
}
.upload-icon-small {
width: 48rpx;
height: 48rpx;
margin-bottom: 8rpx;
}
.add-text {
font-size: 22rpx;
color: #999999;
}
.popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
visibility: hidden;
transition: visibility 0.3s;
}
.popup.show {
visibility: visible;
}
.popup-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
}
.popup-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #FFFFFF;
border-radius: 24rpx 24rpx 0 0;
padding-bottom: env(safe-area-inset-bottom);
}
.popup-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 30rpx;
border-bottom: 1rpx solid #F0F0F0;
}
.popup-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
.popup-close {
font-size: 40rpx;
color: #999999;
}
.region-body {
height: 500rpx;
}
.picker-scroll {
width: 100%;
height: 100%;
}
.picker-item {
line-height: 68rpx;
text-align: center;
font-size: 28rpx;
color: #333333;
}
.popup-footer {
display: flex;
padding: 20rpx 30rpx;
gap: 20rpx;
}
.popup-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12rpx;
}
.popup-btn.cancel {
background: #F5F5F5;
}
.popup-btn.confirm {
background: #FF4767;
}
.popup-btn .btn-text {
font-size: 28rpx;
}
.popup-btn.cancel .btn-text {
color: #666666;
}
.popup-btn.confirm .btn-text {
color: #FFFFFF;
}
.picker-list {
padding: 20rpx 0;
}
.picker-item-row {
padding: 24rpx 30rpx;
font-size: 28rpx;
color: #333333;
text-align: center;
}
.picker-item-row text.active {
color: #FF4767;
}
.tip-popup {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
}
.tip-popup.show {
visibility: visible;
opacity: 1;
}
.tip-popup-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.tip-popup-content {
position: relative;
width: 620rpx;
height: 810rpx;
}
.tip-popup-bg {
width: 620rpx;
height: 810rpx;
position: absolute;
top: 0;
left: 0;
}
.tip-popup-body {
position: relative;
flex-direction: column;
padding: 80rpx 20rpx 40rpx 20rpx;
box-sizing: border-box;
}
.tip-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
text-align: center;
margin-top: 107rpx;
margin-bottom: 37rpx;
}
.tip-image-container {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 50rpx;
}
.tip-image {
width: 90%;
max-height: 400rpx;
}
.tip-buttons {
display: flex;
justify-content: space-between;
padding: 0 28rpx;
}
.tip-btn {
width: 250rpx;
height: 80rpx;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: 500;
}
.tip-btn.cancel {
border: #FF4767 2rpx solid;
background-color: transparent;
color: #FF4767;
}
.tip-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #FF4767 100%);
color: #FFFFFF;
}
.tip-btn .btn-text {
color: inherit;
}
</style>