mrr.sj.front/pages/ruzhu/qualification_sj.vue

2029 lines
60 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="qualification-page">
<!-- 营业执照部分 -->
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">营业执照</text>
</view>
<!-- 资质照片 -->
<view class="form-item box-cont">
<text class="label required">资质照片</text>
<view class="upload-tip">请保证图片上的文字清晰无遮挡证件边角可见</view>
<view class="upload-container">
<view class="upload-box" @click="chooseImage('business_license')">
<view class="upload-camera license-upload">
<image v-if="formData.business_license" :src="formData.business_license" mode="aspectFill" class="preview-image"></image>
<image v-else src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/92bd4268-b4d7-4725-8664-9e44f828c7d9" mode="aspectFit" class="camera-icon"></image>
<!-- 识别状态遮罩 -->
<!-- <view v-if="isRecognizing && recognizeType === 'business_license'" class="recognize-overlay">
<view class="recognize-loading"></view>
<text class="recognize-text">识别中...</text>
</view> -->
</view>
</view>
<text class="upload-label required">请上传营业执照原件</text>
</view>
</view>
<!-- 商户类型 -->
<view class="form-item-one box-cont">
<view class="label-wrapper">
<text class="label required">商户类型</text>
</view>
<input type="text" v-model="formData.merchant_type" placeholder="请输入商户类型"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
<!-- 营业执照信息 -->
<view class="form-item-one 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('license_number')"></image>
</view>
<input type="text" v-model="formData.license_number" placeholder="请输入营业执照的证件号码"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
<view class="form-item-one 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('company_name')"></image>
</view>
<input type="text" v-model="formData.company_name" placeholder="请输入营业执照的企业名称"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
</view>
<!-- 法人信息部分 -->
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text>法人信息</text>
</view>
<!-- 身份证照片部分 -->
<view class="section">
<view class="box-cont">
<view class="form-item">
<text class="label required">身份证照片</text>
<view class="upload-tip">请保证图片上的文字清晰、无遮挡、证件边角可见</view>
<view class="idcard-upload-vertical-container">
<!-- 身份证正面 -->
<view class="idcard-upload-vertical-item">
<view class="upload-box" @click="chooseImage('idcard_front')">
<view class="upload-camera idcard-front">
<image v-if="formData.idcard_front" :src="formData.idcard_front" mode="aspectFill" class="preview-image"></image>
<image v-else src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/043b0c97-79c1-4f95-810f-c33e3d5269a3" mode="aspectFit" class="camera-icon"></image>
<!-- 识别状态遮罩 -->
<!-- <view v-if="isRecognizing && recognizeType === 'idcard_front'" class="recognize-overlay">
<view class="recognize-loading"></view>
<text class="recognize-text">识别中...</text>
</view> -->
</view>
</view>
<text class="upload-label required">请上传身份证正面(人像面)</text>
</view>
<!-- 身份证反面 -->
<view class="idcard-upload-vertical-item">
<view class="upload-box" @click="chooseImage('idcard_back')">
<view class="upload-camera idcard-back">
<image v-if="formData.idcard_back" :src="formData.idcard_back" mode="aspectFill" class="preview-image"></image>
<image v-else src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/203cfdf4-2501-44e6-8565-ad251c6bf0fa" mode="aspectFit" class="camera-icon"></image>
<!-- 识别状态遮罩 -->
<!-- <view v-if="isRecognizing && recognizeType === 'idcard_back'" class="recognize-overlay">
<view class="recognize-loading"></view>
<text class="recognize-text">识别中...</text>
</view> -->
</view>
</view>
<text class="upload-label required">请上传身份证反面(国徽面)</text>
</view>
</view>
</view>
</view>
</view>
<view class="form-item-one 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_person')"></image>
</view>
<input type="text" v-model="formData.legal_person" placeholder="请输入营业执照的法人代表"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
<view class="form-item-one box-cont">
<text class="label required">法人联系方式</text>
<input type="number" v-model="formData.legal_phone" placeholder="请输入法人的联系方式"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
<view class="form-item-one box-cont">
<text class="label required">法人身份证号</text>
<input type="idcard" v-model="formData.legal_idcard" placeholder="请输入法人身份证号"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
<!-- 身份证有效期 -->
<view class="form-item box-cont">
<text class="label required">身份证有效期至</text>
<view class="radio-group">
<view class="radio-item" @click="setIdcardValidType('permanent')">
<view class="radio" :class="{ checked: formData.idcard_valid_type === 'permanent' }">
<image v-if="formData.idcard_valid_type === 'permanent'" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" class="radio-icon-image" mode="aspectFit"></image>
</view>
<text class="radio-label">长久有效</text>
</view>
<view class="radio-item" @click="setIdcardValidType('date')">
<view class="radio" :class="{ checked: formData.idcard_valid_type === 'date' }">
<image v-if="formData.idcard_valid_type === 'date'" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" class="radio-icon-image" mode="aspectFit"></image>
</view>
<text class="radio-label">指定日期有效</text>
</view>
</view>
</view>
<!-- 身份证有效期日期选择 -->
<view class="box-cont">
<view class="date-range-container">
<view class="date-item">
<text class="date-label">开始日期</text>
<view class="date-picker-box" @click="openDatePicker('idcard_start_date')">
<text :class="formData.idcard_start_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(formData.idcard_start_date) || '请选择日期'}}
</text>
<view class="date-divider"></view>
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ce52b49f-2261-49ca-96ed-e9ad47049649" class="date-arrow" mode="aspectFit"></image>
</view>
</view>
<view class="date-item">
<text class="date-label">结束日期</text>
<view class="date-picker-box" :class="{ disabled: formData.idcard_valid_type === 'permanent' }"
@click="formData.idcard_valid_type !== 'permanent' && openDatePicker('idcard_end_date')">
<text :class="formData.idcard_end_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(formData.idcard_end_date) || '请选择日期'}}
</text>
<view class="date-divider"></view>
<image :src="formData.idcard_valid_type === 'permanent' ?
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bb9a757f-a36c-46bb-a59f-2caddac5365b' :
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ce52b49f-2261-49ca-96ed-e9ad47049649'"
class="date-arrow" mode="aspectFit"></image>
</view>
</view>
</view>
</view>
</view>
<!-- 商户类型选择器 -->
<view class="popup" :class="{ show: showMerchantTypePickerFlag }">
<view class="popup-mask" @click="hideMerchantTypePicker"></view>
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">选择商户类型</text>
<text class="popup-close" @click="hideMerchantTypePicker">×</text>
</view>
<view class="popup-body">
<view class="radio-list">
<view class="radio-item" v-for="(item, index) in merchantTypeList" :key="index"
@click="selectMerchantType(item)">
<view class="radio" :class="{ checked: formData.merchant_type === item.value }">
<image v-if="formData.merchant_type === item.value" src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/cb185ec8-9d30-4e53-b5dc-14b546013a60" class="radio-icon-image" mode="aspectFit"></image>
</view>
<text class="radio-label">{{item.label}}</text>
</view>
</view>
</view>
<view class="popup-footer">
<view class="popup-btn confirm" @click="confirmMerchantType">
<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="cancel-text" @click="hideDatePicker">取消</text>
<text class="title">选择日期</text>
<text class="confirm-text" @click="confirmDate">确定</text>
</view>
<view class="region-body">
<picker-view :value="dateValue" @change="bindDateChange" class="picker-scroll"
:indicator-style="indicatorStyle" mode="date" fields="day">
<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>
</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" :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 { debounce } from '@/utils/debounce.js';
import uploadImage from '../../utils/uploadImage';
import permissionUtils from '../../utils/per';
import locationService from '../../utils/locationService';
import { recognizeIdCard, recognizeBusinessLicense, formatDateFromNumber, parseValidPeriod } from '../../utils/orc';
export default {
data() {
const currentDate = new Date();
const currentYear = new Date().getFullYear();
const years = Array.from({length: 130}, (_, i) => 1970 + i);
const months = Array.from({length: 12}, (_, i) => i + 1);
const days = Array.from({length: 31}, (_, i) => i + 1);
// 从本地存储加载数据
const loadedData = this.loadFormDataFromLocal();
return {
userId: null,
// 使用本地存储初始化数据
formData: loadedData || {
merchant_type: '',
business_license: '',
license_number: '',
company_name: '',
license_valid_type: '',
license_start_date: '',
license_end_date: '',
legal_person: '',
legal_phone: '',
legal_idcard: '',
idcard_valid_type: '',
idcard_start_date: '',
idcard_end_date: '',
idcard_front: '',
idcard_back: ''
},
showMerchantTypePickerFlag: false,
showDatePickerFlag: false,
showTipPopupFlag: false, // 提示弹窗显示状态
currentDateField: '',
merchantTypeList: [
{ label: '个体工商户营业执照', value: 'individual' },
{ label: '企业法人营业执照', value: 'corporate' },
],
years,
months,
days,
dateValue: [currentYear - 1970, currentDate.getMonth(), currentDate.getDate() - 1], // 默认选中今天
indicatorStyle: 'height: 68rpx;',
tipTitle: '', // 提示弹窗标题
tipImage: '', // 提示弹窗图片
isSubmit: false, // 防止重复提交
// 识别状态
isRecognizing: false,
recognizeType: '', // 'idcard_front', 'idcard_back', 'business_license'
identity: null
}
},
computed: {
merchantTypeText() {
const type = this.merchantTypeList.find(item => item.value === this.formData.merchant_type);
return type ? type.label : '';
}
},
// 添加 watch 监听表单数据变化
watch: {
'formData.license_number'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.company_name'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.legal_person'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.legal_phone'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.legal_idcard'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.business_license'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.idcard_front'(newVal) {
this.saveFormDataToLocalDebounce();
},
'formData.idcard_back'(newVal) {
this.saveFormDataToLocalDebounce();
}
},
// 页面生命周期
onLoad(options) {
this.loadFormData();
this.preloadImages();
console.log('页面加载,检查全局状态:', {
artisanType: getApp().globalData.artisanType,
userInfo: getApp().globalData.userInfo
});
// 获取身份类型
this.identity = getApp().globalData.artisanType;
console.log('身份类型:', this.identity);
// 获取用户信息,用于图片上传
this.getUserInfo();
// 检查全局状态中是否有数据(从前一页面带过来的)
this.checkGlobalData();
},
onShow() {
// 页面显示时重新从本地存储加载数据
const localData = this.loadFormDataFromLocal();
if (localData) {
// 合并数据,避免覆盖已有数据
this.formData = { ...this.formData, ...localData };
}
// 检查全局状态
this.checkGlobalData();
},
onHide() {
// 页面隐藏时保存数据
this.saveFormDataToLocal();
},
onUnload() {
// 页面卸载时保存数据
this.saveFormDataToLocal();
},
methods: {
// 检查全局数据
checkGlobalData() {
if (getApp().globalData.qualificationData) {
// 如果全局有数据,合并到当前表单
this.formData = { ...this.formData, ...getApp().globalData.qualificationData };
// 保存到本地存储
this.saveFormDataToLocal();
// 清空全局数据,避免重复使用
// delete getApp().globalData.qualificationData;
getApp().globalData.qualificationData = null;
}
},
// 从本地存储加载数据
loadFormDataFromLocal() {
try {
const stored = uni.getStorageSync('qualification_form_data');
if (stored) {
console.log('从本地存储加载数据:', stored);
return stored;
}
} catch (e) {
console.log('读取本地存储失败:', e);
}
return null;
},
// 保存数据到本地存储(带防抖)
saveFormDataToLocalDebounce: debounce(function() {
this.saveFormDataToLocal();
}, 500),
// 保存数据到本地存储
saveFormDataToLocal() {
try {
uni.setStorageSync('qualification_form_data', this.formData);
console.log('数据已保存到本地存储');
} catch (e) {
console.log('保存数据失败:', e);
}
},
// 清空本地存储(在表单提交成功后调用)
clearFormDataLocal() {
try {
uni.removeStorageSync('qualification_form_data');
console.log('已清空本地存储数据');
} catch (e) {
console.log('清空数据失败:', e);
}
},
// 获取用户信息
getUserInfo() {
return new Promise((resolve, reject) => {
request.post('/user/getuser', { type: 1 }).then(result => {
if (result.state === 1) {
this.userId = result.data.id;
console.log('用户ID获取成功:', this.userId);
resolve(this.userId);
} else {
console.error('获取用户信息失败:', result.msg);
reject(result.msg);
}
}).catch(error => {
console.error('获取用户信息接口错误:', error);
reject(error);
});
});
},
getFormData() {
return {
...this.formData,
license_start_date: this.formatDateForBackend(this.formData.license_start_date),
license_end_date: this.formData.license_end_date === '长久有效' ? 'permanent' : this.formatDateForBackend(this.formData.license_end_date),
idcard_start_date: this.formatDateForBackend(this.formData.idcard_start_date),
idcard_end_date: this.formData.idcard_end_date === '长久有效' ? 'permanent' : this.formatDateForBackend(this.formData.idcard_end_date)
};
},
// 添加日期格式化方法
formatDateForDisplay(dateStr) {
if (!dateStr) return '';
if (dateStr === '长久有效') return '长久有效';
// 如果是 YYYY-MM-DD 格式,转换为 年月日 格式显示
if (dateStr.includes('-')) {
const [year, month, day] = dateStr.split('-');
return `${year}${parseInt(month)}${parseInt(day)}`;
}
return dateStr; // 如果已经是年月日格式,直接返回
},
// 将日期转换为后端需要的格式
formatDateForBackend(dateStr) {
if (!dateStr) return '';
if (dateStr === '长久有效') return 'permanent'; // 根据后端需求返回
// 将 年月日 格式转换为 YYYY-MM-DD
const match = dateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
const year = match[1];
const month = match[2].padStart(2, '0');
const day = match[3].padStart(2, '0');
return `${year}-${month}-${day}`;
}
return dateStr; // 如果已经是 YYYY-MM-DD 格式,直接返回
},
// 显示提示弹窗
showTipPopup(field) {
// 根据字段设置对应的标题和图片
const tipConfig = {
'license_number': {
title: '如何找到证件号码',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/72856aac-f0ac-49a1-a7f1-be3220ecb314'
},
'company_name': {
title: '如何找到企业名称',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4fb3e0a2-4c1a-4433-a181-b7a1dfefd030'
},
'legal_person': {
title: '如何找到法人代表',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/24859872-da37-4beb-8e33-7743813bb5a1'
}
};
if (tipConfig[field]) {
this.tipTitle = tipConfig[field].title;
this.tipImage = tipConfig[field].image;
// 确保图片已加载再显示弹窗
this.ensureImageLoaded(this.tipImage).then(() => {
this.showTipPopupFlag = true;
}).catch(() => {
// 即使加载失败也显示弹窗,避免用户无法操作
this.showTipPopupFlag = true;
});
}
},
// 确保图片加载完成
ensureImageLoaded(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve();
img.onerror = () => reject();
img.src = src;
// 设置超时,避免长时间等待
setTimeout(() => resolve(), 500);
});
},
// 隐藏提示弹窗
hideTipPopup() {
this.showTipPopupFlag = false;
},
// 预加载所有弹窗图片
preloadImages() {
const images = [
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ab410a5d-5819-47f2-a0fc-3fd6b90d6770', // 弹窗背景
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/72856aac-f0ac-49a1-a7f1-be3220ecb314', // 证件号码
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4fb3e0a2-4c1a-4433-a181-b7a1dfefd030', // 企业名称
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/24859872-da37-4beb-8e33-7743813bb5a1' // 法人代表
];
images.forEach(src => {
const img = new Image();
img.src = src;
});
},
// 设置营业执照有效期类型
setLicenseValidType(type) {
this.formData.license_valid_type = type;
if (type === 'permanent') {
// 选择长久有效时,设置结束日期为"长久有效"
this.formData.license_end_date = '长久有效';
} else {
// 选择指定日期时,如果之前是长久有效,清空结束日期
if (this.formData.license_end_date === '长久有效') {
this.formData.license_end_date = '';
}
}
// 保存到本地存储
this.saveFormDataToLocal();
},
// 设置身份证有效期类型
setIdcardValidType(type) {
this.formData.idcard_valid_type = type;
if (type === 'permanent') {
// 选择长久有效时,设置结束日期为"长久有效"
this.formData.idcard_end_date = '长久有效';
} else {
// 选择指定日期时,如果之前是长久有效,清空结束日期
if (this.formData.idcard_end_date === '长久有效') {
this.formData.idcard_end_date = '';
}
// 如果已有开始日期自动计算20年后的结束日期
if (this.formData.idcard_start_date && !this.formData.idcard_end_date) {
const match = this.formData.idcard_start_date.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
const year = parseInt(match[1]) + 20;
const month = match[2];
const day = match[3];
this.formData.idcard_end_date = `${year}${month}${day}`;
}
}
}
// 保存到本地存储
this.saveFormDataToLocal();
},
// 显示商户类型选择器
showMerchantTypePicker() {
this.showMerchantTypePickerFlag = true;
},
// 隐藏商户类型选择器
hideMerchantTypePicker() {
this.showMerchantTypePickerFlag = false;
},
// 选择商户类型
selectMerchantType(item) {
this.formData.merchant_type = item.value;
// 保存到本地存储
this.saveFormDataToLocal();
},
// 确认商户类型选择
confirmMerchantType() {
this.hideMerchantTypePicker();
},
// 打开日期选择器
openDatePicker(field) {
this.currentDateField = field;
// 设置日期选择器的初始值
const currentDate = new Date();
let initialDate = currentDate;
// 如果该字段已经有值,解析该值作为初始值
if (this.formData[field]) {
const dateStr = this.formData[field];
const match = dateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
initialDate = new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
}
}
// 计算picker-view的value
const yearIndex = this.years.indexOf(initialDate.getFullYear());
const monthIndex = initialDate.getMonth();
const dayIndex = initialDate.getDate() - 1;
this.dateValue = [
yearIndex >= 0 ? yearIndex : 0,
monthIndex,
dayIndex
];
this.showDatePickerFlag = true;
},
// 隐藏日期选择器
hideDatePicker() {
this.showDatePickerFlag = false;
},
// 日期选择变化
bindDateChange(e) {
this.dateValue = e.detail.value;
},
// 确认日期选择
confirmDate() {
const [yearIndex, monthIndex, dayIndex] = this.dateValue;
const year = this.years[yearIndex];
const month = this.months[monthIndex];
const day = this.days[dayIndex];
const dateStr = `${year}${month}${day}`;
const selectedDate = new Date(year, month - 1, day);
const today = new Date();
today.setHours(0, 0, 0, 0);
// 验证日期逻辑
if (this.currentDateField.endsWith('_start_date')) {
// 开始日期验证:不能选择今天之后的日期
if (selectedDate > today) {
uni.showToast({
title: '开始日期不能晚于今天',
icon: 'none'
});
return;
}
// 如果对应的结束日期已经设置,检查开始日期是否晚于结束日期
const relatedEndField = this.currentDateField.replace('_start_date', '_end_date');
if (this.formData[relatedEndField] && this.formData[relatedEndField] !== '长久有效') {
const endDateStr = this.formData[relatedEndField];
const match = endDateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
const endDate = new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
if (selectedDate > endDate) {
uni.showToast({
title: '开始日期不能晚于结束日期',
icon: 'none'
});
return;
}
}
}
// 如果是身份证开始日期,自动计算结束日期
if (this.currentDateField === 'idcard_start_date') {
// 如果是"长久有效"类型,不自动设置结束日期
if (this.formData.idcard_valid_type === 'date') {
const endYear = year + 20;
const endDateStr = `${endYear}${month}${day}`;
this.formData.idcard_end_date = endDateStr;
} else if (this.formData.idcard_valid_type === 'permanent') {
// 如果是"长久有效"类型,保持结束日期为"长久有效"
this.formData.idcard_end_date = '长久有效';
}
}
} else if (this.currentDateField.endsWith('_end_date')) {
const relatedStartField = this.currentDateField.replace('_end_date', '_start_date');
if (this.formData[relatedStartField]) {
const startDateStr = this.formData[relatedStartField];
const match = startDateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
const startDate = new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
if (selectedDate <= startDate) {
uni.showToast({
title: '结束日期必须晚于开始日期',
icon: 'none'
});
return;
}
}
} else {
// 如果没有设置开始日期,结束日期不能早于今天
if (selectedDate < today) {
uni.showToast({
title: '结束日期不能早于今天',
icon: 'none'
});
return;
}
}
}
this.formData[this.currentDateField] = dateStr;
// 保存到本地存储
this.saveFormDataToLocal();
this.hideDatePicker();
},
// 选择图片
async chooseImage(type) {
try {
const systemInfo = uni.getSystemInfoSync()
if (systemInfo.platform === 'ios') {
this.openCamera(type);
} else {
let xcpermission = '';
let xjpermission = '';
if (systemInfo.platform === 'ios') {
xcpermission = 'photo_library',
xjpermission = 'camera'
} else {
xcpermission = `android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE`
xjpermission = 'android.permission.CAMERA'
}
const xjfirstRequest = !plus.storage.getItem(`perm_${xjpermission}`)
const xcfirstRequest = !plus.storage.getItem(`perm_${xcpermission}`)
if (xcfirstRequest || xjfirstRequest) {
this.isShowPer = true;
}
// 检查权限
const xc = await permissionUtils.checkPermission('photo_library', '需要相册权限用于上传照片');
const xj = await permissionUtils.checkPermission('camera', '需要相机权限用于拍摄照片');
if (xc.granted && xj.granted) {
this.openCamera(type);
return;
}
// 请求权限
const result1 = await permissionUtils.requestPermission('photo_library', '我们需要访问您的相册以上传图片/视频');
const result2 = await permissionUtils.requestPermission('camera', '我们需要访问您的相机以上传图片/视频');
if (result1 && result2) {
this.openCamera(type);
} else {
locationService.openAppSettings();
}
}
} catch (err) {
console.log('选择图片出错:', err);
// 出错时也直接调用图片选择
this.openCamera(type);
}
},
async openCamera(type) {
try {
// 确保用户信息正确
if (!this.userId) {
console.log('重新获取用户信息...');
await this.getUserInfo();
}
if (!this.identity) {
this.identity = getApp().globalData.artisanType;
}
// 直接使用 uni.chooseImage
const chooseResult = await new Promise((resolve, reject) => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: resolve,
fail: reject
});
});
if (!chooseResult.tempFilePaths || chooseResult.tempFilePaths.length === 0) {
uni.hideLoading();
return;
}
const tempFilePath = chooseResult.tempFilePaths[0];
// 直接构造文件对象
const file = {
path: tempFilePath,
size: 0
};
// 显示上传loading
uni.showLoading({
title: '上传中...',
mask: true
});
// 手动调用上传
const result = await this.directUpload(file, this.userId, this.identity + 1);
// 上传成功更新loading显示为识别中
uni.hideLoading();
if (result) {
this.formData[type] = result;
// 上传成功后自动识别
if (type === 'business_license') {
await this.recognizeBusinessLicense(result);
} else if (type === 'idcard_front') {
await this.recognizeIdCardFront(result);
} else if (type === 'idcard_back') {
await this.recognizeIdCardBack(result);
}
// 保存到本地存储
this.saveFormDataToLocal();
}
} catch (err) {
uni.hideLoading();
console.log('上传图片错误:', err);
if (!err.errMsg || !err.errMsg.includes('cancel')) {
uni.showToast({
title: '上传失败,请重试',
icon: 'none'
});
}
}
},
// 直接上传方法
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}`;
console.log('安全文件名:', name);
// 获取OSS配置
const ossConfig = await request.post('/user/getalioss', {type: type, kind: 1});
// 直接上传到OSS
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) {
const fileUrl = `${ossConfig.host}/${ossConfig.dir}${name}`;
resolve(fileUrl);
} else {
reject(new Error('上传失败'));
}
},
fail: reject
});
});
} catch (error) {
console.error('直接上传失败:', error);
throw error;
}
},
/**
* 识别营业执照
*/
async recognizeBusinessLicense(imageUrl) {
try {
this.isRecognizing = true;
this.recognizeType = 'business_license';
// uni.showLoading({
// title: '正在识别营业执照...',
// mask: true
// });
// 调用OCR接口
const result = await recognizeBusinessLicense(imageUrl);
console.log('营业执照识别结果:', result);
const hasRecognizedData = this.checkBusinessLicenseRecognition(result);
if (!hasRecognizedData) {
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.formData.company_name = result.uscc_name;
recognizedFields++;
} else {
// 如果是"无"或空值,设置为空字符串
this.formData.company_name = '';
}
if (result.uscc_num && result.uscc_num.trim()) {
this.formData.license_number = result.uscc_num;
recognizedFields++;
}
// 如果需要营业执照法人与法人代表关联则取消注释
// if (result.legal_name && result.legal_name.trim()) {
// this.formData.legal_person = result.legal_name;
// recognizedFields++;
// }
if (result.uscc_type && result.uscc_type.trim()) {
this.formData.merchant_type = result.uscc_type;
recognizedFields++;
}
// 根据识别的字段数量给出不同的提示
if (recognizedFields > 0) {
} else {
uni.showToast({
title: '识别完成,但未获取到有效信息',
icon: 'none',
duration: 3000
});
}
} catch (error) {
uni.showToast({
title: error.message || '识别失败,请手动填写',
icon: 'none',
// duration: 3000
});
console.error('营业执照识别失败:', error);
} finally {
this.isRecognizing = false;
uni.hideLoading();
}
},
// 检查营业执照识别结果是否有效
checkBusinessLicenseRecognition(result) {
const requiredFields = ['uscc_num', 'uscc_name', 'legal_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 = 'idcard_front';
uni.showLoading({
title: '正在识别身份证正面...',
mask: true
});
// 调用OCR接口
const result = await recognizeIdCard(imageUrl, 1);
// 验证是否真的识别到了数据
const hasRecognizedData = this.checkIdCardFrontRecognition(result);
if (!hasRecognizedData) {
uni.hideLoading();
uni.showToast({
title: '未识别到身份证信息,请手动填写或重新拍摄',
icon: 'none',
duration: 3000
});
this.isRecognizing = false;
return;
}
// 填充身份证正面信息
if (result.name) {
this.formData.legal_person = result.name;
}
if (result.id_number) {
this.formData.legal_idcard = result.id_number;
}
uni.showToast({
title: '身份证正面识别成功',
icon: 'none'
});
} catch (error) {
console.error('身份证正面识别失败:', error);
uni.showToast({
title: error.message || '识别失败,请手动填写',
icon: 'none',
duration: 3000
});
} finally {
this.isRecognizing = false;
uni.hideLoading();
}
},
// 检查身份证正面识别结果是否有效
checkIdCardFrontRecognition(result) {
return (result.name && result.name.trim()) || (result.id_number && result.id_number.trim());
},
/**
* 识别身份证反面
*/
async recognizeIdCardBack(imageUrl) {
try {
this.isRecognizing = true;
this.recognizeType = 'idcard_back';
uni.showLoading({
title: '正在识别身份证反面...',
mask: true
});
// 调用OCR接口
const result = await recognizeIdCard(imageUrl, 2);
// 验证是否真的识别到了数据
const hasRecognizedData = this.checkIdCardBackRecognition(result);
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.formData.idcard_start_date = validPeriod.startDate;
}
if (validPeriod.isPermanent) {
this.formData.idcard_valid_type = 'permanent';
this.formData.idcard_end_date = '长久有效';
} else if (validPeriod.endDate) {
this.formData.idcard_valid_type = 'date';
this.formData.idcard_end_date = validPeriod.endDate;
}
// 如果是长期有效,自动选择对应的选项
if (validPeriod.isPermanent) {
this.setIdcardValidType('permanent');
} else {
this.setIdcardValidType('date');
}
uni.showToast({
title: '身份证反面识别成功',
icon: 'none'
});
} catch (error) {
console.error('身份证反面识别失败:', error);
uni.showToast({
title: error.message || '识别失败,请手动填写',
icon: 'none',
duration: 3000
});
} finally {
this.isRecognizing = false;
uni.hideLoading();
}
},
// 检查身份证反面识别结果是否有效
checkIdCardBackRecognition(result) {
return (result.start_date && result.start_date.trim()) ||
(result.end_date && result.end_date.trim());
},
// 验证表单数据
validateForm() {
// 按照表单从上到下的顺序定义验证规则
const validationRules = [
{ field: 'business_license', message: '请上传营业执照照片' },
{ field: 'merchant_type', message: '请输入商户类型' },
{ field: 'license_number', message: '请输入营业执照号码' },
{ field: 'company_name', message: '请输入企业名称' },
{ field: 'idcard_front', message: '请上传身份证正面照片' },
{ field: 'idcard_back', message: '请上传身份证反面照片' },
{ field: 'legal_person', message: '请输入法人代表' },
{ field: 'legal_phone', message: '请输入法人联系方式' },
{ field: 'legal_idcard', message: '请输入法人身份证号' },
{
condition: () => !this.formData.idcard_valid_type,
message: '请选择身份证有效期类型'
},
{
condition: () => !this.formData.idcard_start_date,
message: '请选择身份证开始日期'
},
{
condition: () => {
if (this.formData.idcard_valid_type === 'data' && !this.formData.idcard_end_date) {
return true;
}
// 如果选择长久有效,则不需要结束日期
return false;
},
message: '请选择身份证结束日期'
},
];
// 按顺序验证
for (let rule of validationRules) {
let isValid = true;
if (rule.field) {
// 简单字段验证
if (!this.formData[rule.field]) {
isValid = false;
}
} else if (rule.condition) {
// 条件验证
if (rule.condition()) {
isValid = false;
}
}
if (!isValid) {
uni.showToast({
title: rule.message,
icon: 'none'
});
return false;
}
}
// 验证手机号格式
if (!/^1[3-9]\d{9}$/.test(this.formData.legal_phone)) {
uni.showToast({
title: '请输入正确的手机号码',
icon: 'none'
});
return false;
}
// 验证身份证格式
if (!/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(this.formData.legal_idcard)) {
uni.showToast({
title: '请输入正确的身份证号码',
icon: 'none'
});
return false;
}
return true;
},
// 将日期字符串转换为Date对象
parseDateString(dateStr) {
if (!dateStr) return null;
// 处理年月日格式
const match = dateStr.match(/(\d+)年(\d+)月(\d+)日/);
if (match) {
return new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]));
}
// 处理 YYYY-MM-DD 格式
if (dateStr.includes('-')) {
const dateParts = dateStr.split('-');
if (dateParts.length === 3) {
return new Date(parseInt(dateParts[0]), parseInt(dateParts[1]) - 1, parseInt(dateParts[2]));
}
}
return null;
},
// 保存表单数据(在进入下一步时调用)
// 修改后的 saveFormData 方法
saveFormData() {
console.log('开始验证表单数据');
console.log('表单数据:', this.formData);
console.log('法人姓名:', this.formData.legal_person);
console.log('法人身份证号:', this.formData.legal_idcard);
if (this.validateForm()) {
console.log('表单验证通过,开始验证法人信息');
// 验证法人姓名与身份证号是否匹配
return this.checkIdCardAndName();
}
console.log('表单验证失败');
return false;
},
// 修改后的 checkIdCardAndName 方法,添加详细调试
async checkIdCardAndName() {
if (this.isSubmit) {
console.log(' 重复提交被阻止 ');
return false;
}
this.isSubmit = true;
try {
console.log('开始调用身份验证接口');
console.log('请求参数:', {
name: this.formData.legal_person,
idcard: this.formData.legal_idcard
});
uni.showLoading({
title: '验证身份信息...'
});
// 调用身份验证接口
const checkRes = await request.post('/user/check', {
name: this.formData.legal_person,
idcard: this.formData.legal_idcard
});
uni.hideLoading();
console.log('身份验证接口返回结果 ');
console.log('完整响应:', checkRes);
console.log('响应Code:', checkRes.Code);
console.log('响应state:', checkRes.state);
console.log('响应msg:', checkRes.msg);
console.log('响应data:', checkRes.data);
console.log('响应ResultObject:', checkRes.ResultObject);
if (checkRes.ResultObject) {
console.log('ResultObject.BizCode:', checkRes.ResultObject.BizCode);
console.log('ResultObject其他属性:', Object.keys(checkRes.ResultObject));
}
// 根据参考代码的验证逻辑,但需要先检查响应结构
if (checkRes.Code === '401') {
console.log(' Code 401 验证失败 ');
uni.showToast({
title: '您的身份证号与姓名不匹配',
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
// 检查多种可能的响应结构
if (checkRes.ResultObject) {
// 如果 ResultObject 有 BizCode 属性
if (checkRes.ResultObject.BizCode && checkRes.ResultObject.BizCode != '1') {
console.log(' BizCode 验证失败 ');
uni.showToast({
title: '您的身份证号与姓名不匹配',
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
// 如果有其他表示失败的字段
if (checkRes.ResultObject.success === false || checkRes.ResultObject.result === false) {
console.log('success/result 验证失败');
uni.showToast({
title: '您的身份证号与姓名不匹配',
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
}
// 检查直接返回的状态字段
if (checkRes.state && checkRes.state !== 1) {
console.log('state 验证失败');
uni.showToast({
title: checkRes.msg || '您的身份证号与姓名不匹配',
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
// 如果直接返回 success: false
if (checkRes.success === false) {
console.log('success 验证失败');
uni.showToast({
title: checkRes.message || '您的身份证号与姓名不匹配',
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
console.log('身份验证通过 ');
// 验证通过,创建提交给后端的数据副本,将日期转换为 YYYY-MM-DD 格式
const submitData = {
...this.formData,
license_start_date: this.formatDateForBackend(this.formData.license_start_date),
license_end_date: this.formData.license_end_date === '长久有效' ? 'permanent' : this.formatDateForBackend(this.formData.license_end_date),
idcard_start_date: this.formatDateForBackend(this.formData.idcard_start_date),
idcard_end_date: this.formData.idcard_end_date === '长久有效' ? 'permanent' : this.formatDateForBackend(this.formData.idcard_end_date)
};
console.log('submitData:', submitData);
// 将表单数据保存到全局或本地存储,以便在下一步使用
getApp().globalData.qualificationData = submitData;
this.isSubmit = false;
return true;
} catch (error) {
uni.hideLoading();
console.error('身份验证接口调用失败');
console.error('错误信息:', error);
console.error('错误详情:', error.response || error.message || error);
// 根据错误类型显示不同的提示
let errorMessage = '身份验证失败';
if (error.response) {
console.error('响应状态:', error.response.status);
console.error('响应数据:', error.response.data);
errorMessage = `服务器错误: ${error.response.status}`;
} else if (error.message) {
errorMessage = error.message;
} else if (error.errMsg) {
errorMessage = error.errMsg;
}
uni.showToast({
title: errorMessage,
icon: 'none',
duration: 3000
});
this.isSubmit = false;
return false;
}
}
}
}
</script>
<style scoped>
.qualification-page {
/* padding: 0rpx 0; */
}
.section {
margin-bottom: 30rpx;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.title-bar {
width: 6rpx;
height: 30rpx;
background-color: #E8101E;
margin-right: 7rpx;
border-radius: 5rpx;
}
.title-text {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #1D2129;
line-height: 48rpx;
text-align: left;
font-style: normal;
}
.section-title text {
font-size: 36rpx;
color: #1D2129;
font-weight: 500;
}
.box-cont {
background: #FFFFFF;
border-radius: 20rpx;
margin-bottom: 24rpx;
margin-left: 8rpx;
margin-right: 8rpx;
box-shadow: none;
}
.form-item {
padding: 24rpx 22rpx;
}
.form-item-one {
display: flex;
align-items: center;
padding: 24rpx;
}
.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;
align-items: center;
}
.required::before {
content: '*';
color: #FF0000;
margin-right: 4rpx;
}
.upload-tip {
font-size: 26rpx;
color: #999;
margin: 16rpx 0 24rpx 0;
font-weight: 400;
font-family: PingFangSC, PingFang SC;
text-align: left;
font-style: normal;
}
.upload-container {
display: flex;
flex-direction: column;
align-items: center;
}
.upload-box {
display: flex;
justify-content: center;
align-items: center;
}
.upload-camera {
width: 446rpx;
height: 298rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 48rpx;
overflow: hidden;
background-color: #F8F9FD;
position: relative;
}
.idcard-upload-vertical-container {
display: flex;
flex-direction: column;
padding: 24rpx;
}
.idcard-upload-vertical-item {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 40rpx;
}
.idcard-upload-vertical-item:last-child {
margin-bottom: 0;
}
.upload-label.required::before {
content: '*';
color: #FF0000;
margin-right: 4rpx;
}
.license-upload {
background-size: cover;
background-repeat: no-repeat;
}
.idcard-front {
background-size: cover;
background-repeat: no-repeat;
}
.idcard-back {
background-size: cover;
background-repeat: no-repeat;
}
.camera-icon {
width: 446rpx;
height: 298rpx;
border-radius: 48rpx;
}
.preview-image {
border-radius: 48rpx;
width: 100%;
height: 100%;
}
/* 识别状态样式 */
.recognize-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 48rpx;
}
.recognize-loading {
width: 60rpx;
height: 60rpx;
border: 4rpx solid #fff;
border-top: 4rpx solid #E8101E;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 16rpx;
}
.recognize-text {
color: #fff;
font-size: 24rpx;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.picker-content {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
.picker-content text {
margin-right: 19rpx;
}
/* 日期选择框竖线分隔符 */
.date-divider {
width: 2rpx;
height: 30rpx;
background-color: #E9E9E9;
margin: 0 15rpx 0 0;
}
/* 置灰状态下的竖线 */
.date-picker-box.disabled .date-divider {
background-color: #F3F3F3;
}
/* 确保日期文字区域可以自动扩展 */
.date-picker-box text {
flex: 1;
}
.arrow-right {
width: 14rpx;
height: 26rpx;
}
.placeholder {
color: #999999;
font-size: 28rpx;
}
.picker-value {
font-size: 28rpx;
color: #333333;
}
.input {
flex: 1;
font-size: 28rpx;
color: #333333;
text-align: right;
margin-left: 20rpx;
}
.radio-group {
display: flex;
margin-top: 24rpx;
width: 100%;
}
.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: #E8101E;
border-color: #E8101E;
}
.radio-icon-image {
width: 32rpx;
height: 32rpx;
}
.radio-label {
font-size: 28rpx;
color: #333333;
}
/* 日期范围容器样式 */
.date-range-container {
padding: 24rpx;
display: flex;
justify-content: space-between;
}
.date-item {
flex: 1;
display: flex;
flex-direction: column;
}
.date-item:first-child {
margin-right: 24rpx;
}
.date-label {
font-size: 28rpx;
color: #333333;
margin-bottom: 16rpx;
font-weight: 500;
margin-left: 8rpx;
}
.date-picker-box {
display: flex;
align-items: center;
justify-content: space-between;
border: 2rpx solid #E9E9E9;
border-radius: 10rpx;
padding: 12rpx 19rpx;
background-color: transparent;
}
.date-picker-box.disabled {
border: 2rpx solid #F3F3F3;
}
.date-picker-box.disabled .date-value,
.date-picker-box.disabled .placeholder {
color: #CCCCCC;
}
.date-value {
font-size: 28rpx;
color: #333;
}
.date-arrow {
width: 35rpx;
height: 33rpx;
}
.upload-label {
font-family: Helvetica;
font-size: 28rpx;
color: #999;
line-height: 40rpx;
text-align: left;
font-style: normal;
margin-top: 24rpx;
}
/* 弹出框样式 */
.popup {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
}
.popup.show {
visibility: visible;
opacity: 1;
}
.popup-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.popup-content {
position: relative;
background-color: #FFFFFF;
border-radius: 24rpx 24rpx 0 0;
padding: 32rpx;
transform: translateY(100%);
transition: transform 0.3s ease;
max-height: 70vh;
}
.popup.show .popup-content {
transform: translateY(0);
}
.popup-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 32rpx;
}
.popup-title {
font-size: 32rpx;
color: #333333;
font-weight: 500;
}
.popup-close {
font-size: 40rpx;
color: #999999;
padding: 16rpx;
}
.popup-body {
max-height: 400rpx;
overflow-y: auto;
}
.radio-list .radio-item {
margin-bottom: 32rpx;
}
.popup-footer {
margin-top: 32rpx;
}
.popup-btn {
height: 88rpx;
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%);
}
.popup-btn .btn-text {
font-size: 32rpx;
font-weight: 500;
color: #FFFFFF;
}
.cancel-text, .confirm-text {
font-size: 32rpx;
padding: 16rpx;
}
.cancel-text {
color: #666666;
}
.confirm-text {
color: #E8101E;
font-weight: 500;
}
.picker-scroll {
height: 400rpx;
}
.picker-item {
height: 68rpx;
line-height: 68rpx;
text-align: center;
font-size: 28rpx;
}
/* 提示弹窗样式 */
.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: #E8101E 2rpx solid;
background-color: transparent;
color: #e8101e;
}
.tip-btn.confirm {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%);
color: #FFFFFF;
}
.tip-btn .btn-text {
color: inherit;
}
</style>