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

1919 lines
53 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="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('health_card')">
<view class="upload-camera health-card-upload">
<image v-if="formData.health_card" :src="formData.health_card" 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>
</view>
<text class="upload-label required">请上传健康证</text>
</view>
</view>
</view>
</view>
</view>
<!-- 健康证有效期 -->
<view class="section">
<view class="form-item box-cont">
<text class="label required">健康证有效期至:</text>
<view class="radio-group">
<view class="radio-item" @click="setHealthCardValidType('permanent')">
<view class="radio" :class="{ checked: formData.health_card_expiry_type === 1 }">
<image v-if="formData.health_card_expiry_type === 1"
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="setHealthCardValidType('date')">
<view class="radio" :class="{ checked: formData.health_card_expiry_type === 2 }">
<image v-if="formData.health_card_expiry_type === 2"
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('health_card_start_date')">
<text :class="formData.health_card_start_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(formData.health_card_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.health_card_expiry_type === 1 }"
@click="formData.health_card_expiry_type !== 1 && openDatePicker('health_card_end_date')">
<text :class="formData.health_card_end_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(formData.health_card_end_date) || '选择日期'}}
</text>
<view class="date-divider"></view>
<image :src="formData.health_card_expiry_type === 1 ?
'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="section">
<view class="form-item box-cont">
<text class="label required">技师资质照片</text>
<view class="qualifications-container">
<view class="qualifications-list">
<!-- 已上传的图片 -->
<view class="qualification-item" v-for="(item, index) in formData.qualifications" :key="index">
<image :src="item" mode="aspectFill" class="qualification-image"></image>
<view class="delete-btn" @click="deleteQualification(index)">×</view>
</view>
<!-- 添加按钮 - 只在图片数量小于9张时显示 -->
<view class="qualification-item add-item"
v-if="formData.qualifications.length < 9"
@click="addQualification">
<image src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/d3aa85b5-6b36-40f9-99ce-682499a5e87d" mode="aspectFit" class="upload-icon"></image>
</view>
</view>
</view>
</view>
</view>
<!-- 所属门店 -->
<view class="section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">所属门店</text>
</view>
<!-- 资质照片、营业执照和门头照 -->
<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('uscc_photo')">
<view class="upload-camera idcard-front">
<image v-if="formData.uscc_photo" :src="formData.uscc_photo" 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 === 'uscc_photo'" 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('shop_photo')">
<view class="upload-camera idcard-front">
<image v-if="formData.shop_photo" :src="formData.shop_photo" mode="aspectFill" class="preview-image"></image>
<image v-else src="https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/60cdf929-bf63-4d56-a05d-467ae9903060" mode="aspectFit" class="camera-icon"></image>
</view>
</view>
<text class="upload-label required">请上传门头照</text>
</view>
</view>
</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.uscc_type" placeholder="请输入门店类型"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</view>
</view>
<!-- 证照号码 -->
<view class="section">
<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('uscc_num')"></image>
</view>
<input type="text" v-model="formData.uscc_num" 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('uscc_name')"></image>
</view>
<input type="text" v-model="formData.uscc_name" 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('for_shop')"></image>
</view>
<input type="text" v-model="formData.for_shop" placeholder="请输入营业执照的店铺名称"
placeholder-class="placeholder" class="input"
@input="saveFormDataToLocalDebounce" />
</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" :class="currentTipField" :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 uploadImage from '../../utils/uploadImage';
import permissionUtils from '../../utils/per';
import { debounce } from '@/utils/debounce.js';
// 添加OCR识别相关导入复用商家代码
import { recognizeBusinessLicense, recognizeIdCard, 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 {
formData: loadedData || {
// 健康证
health_card: '',
health_card_expiry_type: '',
health_card_start_date: '',
health_card_end_date: '',
// 资质照片
qualifications: [],
// 所属门店
uscc_type: '',
uscc_photo: '',
// 营业执照和门头照
shop_photo: '',
// 证照信息
uscc_num: '',
uscc_name: '',
for_shop: '',
uscc_expiry_type: '',
license_start_date: '',
license_end_date: ''
},
showStoreTypePickerFlag: false,
showDatePickerFlag: false,
showTipPopupFlag: false,
tipTitle: '',
tipImage: '',
currentDateField: '',
currentTipField: '',
storeTypeList: [
{ label: '个体工商户营业执照', value: '个体工商户营业执照' },
{ label: '企业法人营业执照', value: '企业法人营业执照' },
],
years,
months,
days,
dateValue: [currentYear - 1970, currentDate.getMonth(), currentDate.getDate() - 1],
indicatorStyle: 'height: 68rpx;',
userId: null,
identity: null,
// 表示是否需要从全局恢复数据
needRefreshFromGlobal: false,
// 添加营业执照识别相关状态(复用商家代码)
isRecognizing: false,
recognizeType: '', // 'uscc_photo', 'health_card'
}
},
computed: {
storeTypeText() {
const type = this.storeTypeList.find(item => item.value === this.formData.uscc_type);
return type ? type.label : '';
}
},
// 页面生命周期
onLoad(options) {
console.log('资质页面 onLoad参数:', options);
// 同步获取用户信息,不等待异步
this.getUserInfoSync();
this.identity = getApp().globalData.artisanType;
// 立即从本地存储加载数据
this.loadFormData();
// 检查全局状态中是否有数据(从前一页面带过来的)
this.checkGlobalData();
// 预加载提示弹窗图片
this.preloadTipImages();
},
onShow() {
// 从本地存储重新加载数据(确保最新)
this.loadFormDataFromLocalAndUpdate();
// 页面显示时重新检查并加载数据
this.loadFormData();
// 检查全局状态
this.checkGlobalData();
// 如果需要从全局刷新,执行刷新
if (this.needRefreshFromGlobal) {
this.loadFormDataFromLocalAndUpdate();
this.needRefreshFromGlobal = false;
}
},
mounted() {
console.log('资质页面 mounted');
console.log('当前表单数据:', this.formData);
// 调试:检查本地存储是否有数据
try {
const stored = uni.getStorageSync('artisan_qualification_form_data');
console.log('本地存储中的资质数据:', stored);
} catch (e) {
console.log('检查本地存储失败:', e);
}
},
onHide() {
// 页面隐藏时保存数据
this.saveFormDataToLocal();
},
onUnload() {
// 页面卸载时保存数据
this.saveFormDataToLocal();
},
methods: {
// 同步获取用户信息
getUserInfoSync() {
try {
const userInfo = uni.getStorageSync('userInfo');
if (userInfo && userInfo.id) {
this.userId = userInfo.id;
console.log('从缓存获取用户ID:', this.userId);
}
} catch (e) {
console.log('获取用户信息失败:', e);
}
},
// 获取用户信息(异步,只在需要时调用)
async getUserInfo() {
return new Promise((resolve, reject) => {
// 如果已经有用户ID直接返回
if (this.userId) {
resolve(this.userId);
return;
}
request.post('/user/getuser', { type: 1 }).then(result => {
if (result.state === 1) {
this.userId = result.data.id;
console.log('用户ID获取成功:', this.userId);
// 保存到缓存
try {
uni.setStorageSync('userInfo', { id: this.userId });
} catch (e) {
console.log('保存用户信息失败:', e);
}
resolve(this.userId);
} else {
console.error('获取用户信息失败:', result.msg);
reject(result.msg);
}
}).catch(error => {
console.error('获取用户信息接口错误:', error);
reject(error);
});
});
},
// 从本地存储加载数据
loadFormDataFromLocal() {
try {
const stored = uni.getStorageSync('artisan_qualification_form_data');
if (stored) {
console.log('从本地存储加载资质数据:', stored);
return stored;
}
} catch (e) {
console.log('读取资质数据失败:', e);
}
return null;
},
// 检查全局数据
checkGlobalData() {
// 检查全局状态中是否有数据(从前一页面带过来的)
if (getApp().globalData.qualificationData) {
console.log('发现全局资质数据,进行合并:', getApp().globalData.qualificationData);
// 将全局数据合并到当前表单
Object.assign(this.formData, getApp().globalData.qualificationData);
// 保存到本地存储
this.saveFormDataToLocal();
// 清空全局数据,避免重复使用
// delete getApp().globalData.qualificationData;
getApp().globalData.qualificationData = null;
// 设置需要刷新标记
this.needRefreshFromGlobal = true;
}
},
// 从本地存储加载数据
loadFormData() {
try {
// 先尝试用通用的key不依赖用户ID
let stored = uni.getStorageSync('artisan_qualification_form_data');
// 如果没有数据再尝试用带用户ID的key
if (!stored && this.userId) {
stored = uni.getStorageSync(`artisan_qualification_form_data_${this.userId}`);
}
if (stored) {
console.log('从本地存储加载数据:', stored);
// 直接替换formData对象保持响应式
Object.keys(stored).forEach(key => {
if (this.formData.hasOwnProperty(key)) {
// 如果是数组,确保复制一份新数组
if (key === 'qualifications' && Array.isArray(stored[key])) {
this.formData[key] = [...stored[key]];
} else {
this.formData[key] = stored[key];
}
}
});
}
} catch (e) {
console.log('读取本地存储失败:', e);
}
},
// 从本地存储加载并更新表单数据
loadFormDataFromLocalAndUpdate() {
const localData = this.loadFormDataFromLocal();
if (localData) {
console.log('从本地存储更新表单数据:', localData);
// 如果 uscc_type 是数字,转换为对应的中文字符串
if (localData.uscc_type === 1 || localData.uscc_type === 'individual') {
localData.uscc_type = '个体工商户营业执照';
} else if (localData.uscc_type === 2 || localData.uscc_type === 'corporate') {
localData.uscc_type = '企业法人营业执照';
}
// 更新表单数据
Object.keys(localData).forEach(key => {
if (this.formData.hasOwnProperty(key)) {
this.formData[key] = localData[key];
}
});
}
},
// 保存数据到本地存储(带防抖)
saveFormDataToLocalDebounce: debounce(function() {
this.saveFormDataToLocal();
}, 500),
// 保存数据到本地存储
saveFormDataToLocal() {
try {
uni.setStorageSync('artisan_qualification_form_data', this.formData);
console.log('资质数据已保存到本地存储');
} catch (e) {
console.log('保存资质数据失败:', e);
}
},
// 清空本地存储(只在审核成功时调用)
clearFormDataLocal() {
try {
uni.removeStorageSync('artisan_qualification_form_data');
console.log('已清空资质数据');
} catch (e) {
console.log('清空资质数据失败:', e);
}
},
getFormData() {
return {
health_card: this.formData.health_card,
health_expiry_type: this.formData.health_card_expiry_type,
health_expiry: this.formatHealthCardExpiry(),
qualifications: this.formData.qualifications,
uscc_type: this.formData.uscc_type,
uscc_photo: this.formData.uscc_photo,
shop_photo: this.formData.shop_photo,
uscc_num: this.formData.uscc_num,
uscc_name: this.formData.uscc_name,
for_shop: this.formData.for_shop,
uscc_expiry_type: this.formData.uscc_expiry_type,
uscc_expiry: this.formatLicenseExpiry()
};
},
// 格式化健康证有效期
formatHealthCardExpiry() {
if (!this.formData.health_card_start_date) return '';
const startDate = this.formatDateForBackend(this.formData.health_card_start_date);
if (this.formData.health_card_expiry_type === 1) {
return `${startDate} —— `;
} else if (this.formData.health_card_end_date) {
const endDate = this.formatDateForBackend(this.formData.health_card_end_date);
return `${startDate} —— ${endDate}`;
}
return '';
},
// 格式化营业执照有效期
formatLicenseExpiry() {
if (!this.formData.license_start_date) return '';
const startDate = this.formatDateForBackend(this.formData.license_start_date);
if (this.formData.uscc_expiry_type === 1) {
return `${startDate} —— `;
} else if (this.formData.license_end_date) {
const endDate = this.formatDateForBackend(this.formData.license_end_date);
return `${startDate} —— ${endDate}`;
}
return '';
},
// 预加载提示弹窗图片
preloadTipImages() {
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/151b2238-099a-4b94-9376-03197d994101' // 店铺名称
];
console.log('开始预加载提示弹窗图片...');
// 预加载所有图片
images.forEach(src => {
const img = new Image();
img.src = src;
});
console.log('提示弹窗图片预加载完成');
},
// 显示提示弹窗
showTipPopup(field) {
const tipConfig = {
'uscc_num': {
title: '如何找到证件号码',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/72856aac-f0ac-49a1-a7f1-be3220ecb314'
},
'uscc_name': {
title: '如何找到企业名称',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/4fb3e0a2-4c1a-4433-a181-b7a1dfefd030'
},
'for_shop': {
title: '如何找到店铺名称',
image: 'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/151b2238-099a-4b94-9376-03197d994101'
}
};
if (tipConfig[field]) {
this.tipTitle = tipConfig[field].title;
this.tipImage = tipConfig[field].image;
this.currentTipField = field;
// 使用异步显示,确保图片加载
setTimeout(() => {
this.showTipPopupFlag = true;
}, 50);
}
},
hideTipPopup() {
this.showTipPopupFlag = false;
setTimeout(() => {
this.currentTipField = '';
}, 300);
},
// 日期显示格式化
formatDateForDisplay(dateStr) {
if (!dateStr) return '';
if (dateStr === '长久有效') return '长久有效';
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';
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;
},
// 设置健康证有效期类型
setHealthCardValidType(type) {
this.formData.health_card_expiry_type = type === 'permanent' ? 1 : 2;
if (type === 'permanent') {
this.formData.health_card_end_date = '长久有效';
} else {
if (this.formData.health_card_end_date === '长久有效') {
this.formData.health_card_end_date = '';
}
}
// 保存到本地存储
this.saveFormDataToLocalDebounce();
},
// 设置营业执照有效期类型
setLicenseValidType(type) {
this.formData.uscc_expiry_type = type === 'permanent' ? 1 : 2;
if (type === 'permanent') {
this.formData.license_end_date = '长久有效';
} else {
if (this.formData.license_end_date === '长久有效') {
this.formData.license_end_date = '';
}
}
// 保存到本地存储
this.saveFormDataToLocalDebounce();
},
// 门店类型选择
showStoreTypePicker() {
this.showStoreTypePickerFlag = true;
},
hideStoreTypePicker() {
this.showStoreTypePickerFlag = false;
},
selectStoreType(item) {
this.formData.uscc_type = item.value;
// 保存到本地存储
this.saveFormDataToLocalDebounce();
},
confirmStoreType() {
this.hideStoreTypePicker();
},
// 日期选择
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]));
}
}
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') && selectedDate > today) {
uni.showToast({
title: '开始日期不能晚于今天',
icon: 'none'
});
return;
}
// 根据字段类型进行不同的验证
if (this.currentDateField.includes('health_card')) {
// 健康证日期验证
if (this.currentDateField === 'health_card_start_date') {
// 开始日期不能晚于结束日期
if (this.formData.health_card_end_date && this.formData.health_card_end_date !== '长久有效') {
const endDateStr = this.formData.health_card_end_date;
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;
}
}
}
this.formData[this.currentDateField] = dateStr;
// 如果结束日期为空或早于新的开始日期,重置结束日期
if (this.formData.health_card_end_date && this.formData.health_card_end_date !== '长久有效') {
const endDateStr = this.formData.health_card_end_date;
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) {
this.formData.health_card_end_date = '';
}
}
}
} else if (this.currentDateField === 'health_card_end_date') {
// 结束日期必须晚于开始日期
if (this.formData.health_card_start_date) {
const startDateStr = this.formData.health_card_start_date;
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 {
uni.showToast({
title: '请先选择开始日期',
icon: 'none'
});
return;
}
this.formData[this.currentDateField] = dateStr;
}
} else if (this.currentDateField.includes('license')) {
// 营业执照日期验证
if (this.currentDateField === 'license_start_date') {
// 开始日期不能晚于结束日期
if (this.formData.license_end_date && this.formData.license_end_date !== '长久有效') {
const endDateStr = this.formData.license_end_date;
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;
}
}
}
this.formData[this.currentDateField] = dateStr;
// 如果结束日期为空或早于新的开始日期,重置结束日期
if (this.formData.license_end_date && this.formData.license_end_date !== '长久有效') {
const endDateStr = this.formData.license_end_date;
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) {
this.formData.license_end_date = '';
}
}
}
} else if (this.currentDateField === 'license_end_date') {
// 结束日期必须晚于开始日期
if (this.formData.license_start_date) {
const startDateStr = this.formData.license_start_date;
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 {
uni.showToast({
title: '请先选择开始日期',
icon: 'none'
});
return;
}
this.formData[this.currentDateField] = dateStr;
}
}
// 保存到本地存储
this.saveFormDataToLocalDebounce();
// this.saveFormDataToLocal();
this.hideDatePicker();
},
// 图片上传 - 与商家端统一
async chooseImage(type) {
try {
if (!this.userId) {
await this.getUserInfo();
}
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) {
return;
}
const tempFilePath = chooseResult.tempFilePaths[0];
const file = {
path: tempFilePath,
size: 0
};
const result = await this.directUpload(file, this.userId, this.identity + 1);
if (result) {
this.formData[type] = result;
// 上传成功后自动识别营业执照
if (type === 'uscc_photo') {
await this.recognizeBusinessLicense(result);
}
// 保存到本地存储
this.saveFormDataToLocalDebounce();
}
} catch (err) {
console.log('上传图片错误:', err);
}
},
// 直接上传方法 - 与商家端统一
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) {
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 = 'uscc_photo';
uni.showLoading({
title: '正在识别营业执照...',
mask: true
});
// 调用OCR接口
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;
// 直接使用OCR返回的 uscc_type
if (result.uscc_type && result.uscc_type.trim()) {
this.formData.uscc_type = result.uscc_type;
recognizedFields++;
}
// 企业名称:如果识别结果为"无",就设置为空字符串
if (result.uscc_name && result.uscc_name.trim() && result.uscc_name !== '无') {
this.formData.uscc_name = result.uscc_name;
recognizedFields++;
} else {
// 如果是"无"或空值,设置为空字符串
this.formData.uscc_name = '';
}
if (result.uscc_num && result.uscc_num.trim()) {
this.formData.uscc_num = result.uscc_num;
recognizedFields++;
}
// 如果店铺名称为空,使用企业名称填充
if (result.uscc_name && result.uscc_name.trim() && result.uscc_name !== '无') {
this.formData.for_shop = result.uscc_name;
}else {
// 如果是"无"或空值,设置为空字符串
this.formData.uscc_name = '';
}
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;
},
// 添加技师资质照片方法
addQualification() {
if (this.formData.qualifications.length >= 9) {
uni.showToast({
title: '最多只能上传9张资质照片',
icon: 'none'
});
return;
}
this.chooseImageForQualifications();
},
async chooseImageForQualifications() {
try {
if (!this.userId) {
await this.getUserInfo();
}
const remainingCount = 9 - this.formData.qualifications.length;
const chooseResult = await new Promise((resolve, reject) => {
uni.chooseImage({
count: remainingCount,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: resolve,
fail: reject
});
});
if (!chooseResult.tempFilePaths || chooseResult.tempFilePaths.length === 0) {
return;
}
const totalAfterUpload = this.formData.qualifications.length + chooseResult.tempFilePaths.length;
if (totalAfterUpload > 9) {
uni.showToast({
title: '最多只能上传9张资质照片',
icon: 'none'
});
return;
}
for (const tempFilePath of chooseResult.tempFilePaths) {
const file = {
path: tempFilePath,
size: 0
};
const result = await this.directUpload(file, this.userId, this.identity + 1);
if (result) {
this.formData.qualifications.push(result);
}
}
// 保存到本地存储
this.saveFormDataToLocalDebounce();
} catch (err) {
console.log('上传资质照片错误:', err);
}
},
// 删除资质照片
deleteQualification(index) {
this.formData.qualifications.splice(index, 1);
// 保存到本地存储
this.saveFormDataToLocalDebounce();
},
// 表单验证
validateForm() {
if (!this.formData.health_card) {
uni.showToast({
title: '请上传健康证',
icon: 'none'
});
return false;
}
if (!this.formData.health_card_expiry_type) {
uni.showToast({
title: '请选择健康证有效期类型',
icon: 'none'
});
return false;
}
if (!this.formData.health_card_start_date) {
uni.showToast({
title: '请选择健康证开始日期',
icon: 'none'
});
return false;
}
if (this.formData.health_card_expiry_type === 2 && !this.formData.health_card_end_date) {
uni.showToast({
title: '请选择健康证结束日期',
icon: 'none'
});
return false;
}
if (this.formData.qualifications.length === 0) {
uni.showToast({
title: '请上传至少一张技师资质照片',
icon: 'none'
});
return false;
}
if (!this.formData.uscc_photo) {
uni.showToast({
title: '请上传营业执照原件',
icon: 'none'
});
return false;
}
if (!this.formData.shop_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.for_shop) {
uni.showToast({
title: '请输入营业执照的店铺名称',
icon: 'none'
});
return false;
}
return true;
},
// 保存表单数据
saveFormData() {
if (this.validateForm()) {
// 将表单数据保存到全局
getApp().globalData.qualificationData = this.getFormData();
// 同时保存到本地(双重保险)
this.saveFormDataToLocal();
console.log('资质信息保存成功:', getApp().globalData.qualificationData);
return true;
}
return false;
}
}
}
</script>
<style scoped>
.qualification-page {
padding: 28rpx 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;
}
.form-item-two {
display: flex;
justify-content: space-between;
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;
}
.upload-label {
font-family: Helvetica;
font-size: 28rpx;
color: #999;
line-height: 40rpx;
text-align: left;
font-style: normal;
margin-top: 24rpx;
}
.required::before {
content: '*';
color: #FF0000;
margin-right: 4rpx;
}
.upload-tip {
font-size: 26rpx;
color: #999;
margin: 5rpx 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: 40rpx 24rpx 0 24rpx;
}
.idcard-upload-vertical-item {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30rpx;
}
.upload-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.upload-icon {
width: 120rpx;
height: 120rpx;
/* margin-bottom: 16rpx; */
}
.camera-icon {
width: 446rpx;
height: 298rpx;
border-radius: 48rpx;
}
.preview-image {
border-radius: 20rpx;
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;
}
.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-value {
font-size: 28rpx;
color: #333;
}
.date-divider {
width: 2rpx;
height: 30rpx;
background-color: #E9E9E9;
margin: 0 15rpx 0 0;
}
.date-arrow {
width: 35rpx;
height: 33rpx;
}
/* 日期选择框置灰状态 */
.date-picker-box.disabled {
border: 2rpx solid #F3F3F3;
}
.date-picker-box.disabled .date-value,
.date-picker-box.disabled .placeholder {
color: #CCCCCC;
}
/* 日期选择框竖线分隔符 */
.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;
}
/* 技师资质照片样式 */
.qualifications-container {
/* margin-top: 15rpx; */
margin: 20rpx 5rpx 10rpx 6rpx;
}
.qualifications-list {
display: flex;
flex-wrap: wrap;
gap: 9rpx;
}
.qualification-item {
position: relative;
width: 208rpx;
height: 208rpx;
border-radius: 6rpx;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.add-item {
background: #F5F5F5 ;
}
.qualification-image {
width: 100%;
height: 100%;
}
.upload-icon {
width: 123rpx;
height: 100rpx;
border-radius: 20rpx;
}
.delete-btn {
position: absolute;
top: 8rpx;
right: 8rpx;
width: 36rpx;
height: 36rpx;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24rpx;
font-weight: bold;
}
.arrow-right {
width: 14rpx;
height: 26rpx;
margin-left: 16rpx;
}
/* 弹出框样式 */
.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;
/* z-index: 1001; */
}
.tip-popup-bg {
width: 620rpx;
height: 810rpx;
position: absolute;
top: 0;
left: 0;
}
.tip-popup-body {
position: relative;
/* z-index: 1002; */
/* height: 100%; */
/* display: flex; */
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: 521rpx;
height: 327rpx;
margin-left: 30rpx;
}
/* 店铺名称图片的特殊样式 */
.tip-image.for_shop {
width: 627rpx;
height: 327rpx;
margin-left: 13rpx;
}
.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>