mrr.sj.front/pages/artisan/qualification_syr_change.vue

1657 lines
49 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">
<!-- 顶部导航栏 -->
<custom-navbar :title="navTitle" :showBack="true"></custom-navbar>
<!-- 变更提示 -->
<view class="change-tip" v-if="editable">
<text>请变更您需要变更的信息</text>
</view>
<!-- 页面内容容器 -->
<view class="content-area" :style="{ paddingBottom: buttonAreaHeight + 'px' }">
<!-- 健康证部分 -->
<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="editable ? chooseImage('health_card') : null">
<view class="upload-camera health-card-upload">
<image v-if="displayData.health_card" :src="displayData.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="editable && setHealthCardValidType('permanent')">
<view class="radio" :class="{ checked: displayData.health_card_expiry_type === 1 }">
<image v-if="displayData.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="editable && setHealthCardValidType('date')">
<view class="radio" :class="{ checked: displayData.health_card_expiry_type === 2 }">
<image v-if="displayData.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="editable && openDatePicker('health_card_start_date')">
<text :class="displayData.health_card_start_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(displayData.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: displayData.health_card_expiry_type === 1 }"
@click="editable && displayData.health_card_expiry_type !== 1 && openDatePicker('health_card_end_date')">
<text :class="displayData.health_card_end_date ? 'date-value' : 'placeholder'">
{{formatDateForDisplay(displayData.health_card_end_date) || '选择日期'}}
</text>
<view class="date-divider"></view>
<image :src="editable && displayData.health_card_expiry_type !== 1 ?
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/ce52b49f-2261-49ca-96ed-e9ad47049649' :
'https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/bb9a757f-a36c-46bb-a59f-2caddac5365b'"
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 displayData.qualifications" :key="index">
<image :src="item" mode="aspectFill" class="qualification-image"></image>
<view class="delete-btn" v-if="editable" @click="deleteQualification(index)">×</view>
</view>
<!-- 添加按钮 - 只在图片数量小于9张且可编辑时显示 -->
<view class="qualification-item add-item"
v-if="editable && displayData.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="safe-bottom"></view>
</view>
<!-- 底部按钮区域 -->
<view class="bottom-actions" ref="buttonArea">
<!-- 驳回原因提示 -->
<view class="reject-reason" v-if="shouldShowRejectReason">
<view class="reject-title">您的提交已驳回</view>
<view class="reject-detail">驳回原因:{{ backText }}</view>
</view>
<!-- 审核中提示 -->
<view class="audit-tip" v-if="showAuditTip">
<text class="audit-text">您的提交变更正在审核中...</text>
</view>
<!-- 变更信息按钮 -->
<view class="action-btn change-info-btn" v-if="buttonType === 'change'" @click="startChange">
<text class="btn-text">变更信息</text>
</view>
<!-- 取消和提交按钮 -->
<view class="action-buttons-row" v-if="buttonType === 'edit'">
<view class="action-btn cancel-btn" @click="cancelChange">
<text class="btn-text cancel-text">取消</text>
</view>
<view class="action-btn submit-btn" @click="submitChange">
<text class="btn-text">提交</text>
</view>
</view>
<!-- 查看我的变更/返回按钮 -->
<view class="action-btn view-change-btn" v-if="buttonType === 'view'" @click="togglePendingData">
<text class="btn-text">{{ showPendingData ? '返回' : '查看我的变更' }}</text>
</view>
<!-- 重新提交按钮 -->
<view class="action-btn resubmit-btn" v-if="buttonType === 'reject'" @click="startChange">
<text class="btn-text">重新提交</text>
</view>
</view>
<!-- 日期选择器 -->
<uni-popup ref="datePicker" type="bottom" background-color="#fff">
<view class="date-picker-popup">
<view class="picker-header">
<text class="picker-cancel" @click="hideDatePicker">取消</text>
<text class="picker-title">选择日期</text>
<text class="picker-confirm" @click="confirmDate">确定</text>
</view>
<picker-view :value="dateValue" @change="bindDateChange" :indicator-style="indicatorStyle" class="picker-view">
<picker-view-column>
<view class="picker-item" v-for="(item, index) in years" :key="index">{{item}}年</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in months" :key="index">{{item}}月</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item, index) in days" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</uni-popup>
</view>
</template>
<script>
import request from '../../utils/request';
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);
return {
// 页面状态
editable: false,
buttonType: 'change', // change-变更信息, edit-取消/提交, view-查看我的变更, reject-重新提交
showAuditTip: false,
auditStatus: null, // 审核状态: null-无申请, 1-审核中, 2-审核通过, 3-审核驳回
applyId: null,
showPendingData: false, // 是否显示待审核数据
navTitle: '资质信息',
buttonAreaHeight: 120,
backText: '', // 驳回原因
hasResubmitted: false,
// 数据管理
originalData: {}, // 老数据(当前生效的)
pendingData: {}, // 新数据(待审核的)
displayData: {}, // 当前显示的数据
// 用户信息
userId: null,
identity: null,
applyType: 4, // 资质信息变更
// 表单相关
currentDateField: '',
years,
months,
days,
dateValue: [currentYear - 1970, currentDate.getMonth(), currentDate.getDate() - 1],
indicatorStyle: 'height: 68rpx;',
userInfo: null,
artisanInfo: null
}
},
computed: {
shouldShowRejectReason() {
return this.auditStatus === 3 && !this.showPendingData && this.backText;
}
},
onLoad(options) {
this.initPage();
},
onReady() {
this.getButtonAreaHeight();
},
onShow() {
// 只有在非编辑状态下才重新加载数据
if (!this.editable) {
console.log('非编辑状态,刷新数据');
this.loadApplyDetails();
if (this.auditStatus !== 3) {
this.backText = '';
this.hasResubmitted = false;
}
} else {
console.log('编辑状态,保持当前状态不刷新');
}
},
methods: {
// 初始化页面
async initPage() {
try {
// 获取用户ID
await this.getUserInfo();
this.identity = getApp().globalData.artisanType;
// 获取用户详细信息
await this.getUserDetailInfo();
// 加载申请详情
await this.loadApplyDetails();
// 恢复保存的数据(如果有)
this.restoreData();
} catch (error) {
console.error('页面初始化失败:', error);
uni.showToast({
title: '页面加载失败',
icon: 'none'
});
}
},
// 获取用户基本信息获取用户ID
getUserInfo() {
return new Promise((resolve, reject) => {
request.post('/user/getuser', { type: 1 }).then(result => {
if (result.state === 1) {
this.userId = result.data.id;
this.userInfo = result.data;
console.log('用户ID获取成功:', this.userId);
resolve(this.userId);
} else {
console.error('获取用户信息失败:', result.msg);
reject(result.msg);
}
}).catch(error => {
console.error('获取用户信息接口错误:', error);
reject(error);
});
});
},
// 获取用户详细信息(包括资质信息)
async getUserDetailInfo() {
try {
// 获取手艺人信息
const artisanResult = await request.post('/user/getuser', { type: 2 });
if (artisanResult.state === 1) {
this.artisanInfo = artisanResult.data;
console.log('手艺人信息原始数据:', JSON.parse(JSON.stringify(this.artisanInfo)));
this.fillFormWithExistingData();
}
} catch (error) {
console.error('获取用户详细信息失败:', error);
}
},
// 检查图片是否有变更
hasImageChanged() {
let hasChanged = false;
// 检查健康证图片
if (this.displayData.health_card !== this.originalData.health_card) {
hasChanged = true;
console.log('健康证图片有变更');
}
// 检查资质照片
const displayQuals = this.displayData.qualifications || [];
const originalQuals = this.originalData.qualifications || [];
// 1. 检查数量是否相同
if (displayQuals.length !== originalQuals.length) {
hasChanged = true;
console.log('资质照片数量有变更', displayQuals.length, originalQuals.length);
return hasChanged; // 数量不同直接返回
}
// 2. 如果数量相同检查内容使用Set来比较忽略顺序
const displaySet = new Set(displayQuals);
const originalSet = new Set(originalQuals);
// 检查两个Set是否完全相同
if (displaySet.size !== originalSet.size) {
hasChanged = true;
console.log('资质照片集合大小不同');
} else {
// 检查每个元素是否都存在于对方集合中
for (const item of displaySet) {
if (!originalSet.has(item)) {
hasChanged = true;
console.log('资质照片内容不同');
break;
}
}
}
return hasChanged;
},
// 检查表单数据是否有变更
hasFormDataChanged() {
// 检查健康证有效期类型
if (this.displayData.health_card_expiry_type !== this.originalData.health_card_expiry_type) {
console.log('健康证有效期类型有变更');
return true;
}
// 检查开始日期
if (this.displayData.health_card_start_date !== this.originalData.health_card_start_date) {
console.log('开始日期有变更');
return true;
}
// 检查结束日期(仅在指定日期有效时比较)
if (this.displayData.health_card_expiry_type === 2 &&
this.displayData.health_card_end_date !== this.originalData.health_card_end_date) {
console.log('结束日期有变更');
return true;
}
// 检查图片是否有变更
if (this.hasImageChanged()) {
return true;
}
console.log('没有检测到任何变更');
return false;
},
// 加载申请详情
async loadApplyDetails() {
try {
console.log('开始加载申请详情...');
const res = await request.post('/syr/userSyrAuth/details', {
apply_type: this.applyType
});
console.log('申请详情接口返回:', res);
if (res.code === 200 && res.data) {
const detail = res.data;
this.applyId = detail.id;
this.auditStatus = detail.apply_state;
this.backText = detail.back_text || '';
console.log('审核状态:', this.auditStatus);
console.log('驳回原因:', this.backText);
// 更新pendingData
if (this.auditStatus === 1 || this.auditStatus === 3) {
this.pendingData = {
health_card: detail.health_card || this.originalData.health_card,
health_card_expiry_type: detail.health_expiry_type || this.originalData.health_card_expiry_type,
health_card_start_date: '',
health_card_end_date: '',
qualifications: detail.qualifications || this.originalData.qualifications
};
// 处理健康证有效期
if (detail.health_expiry) {
this.parseHealthExpiry(detail.health_expiry, this.pendingData);
}
}
// 审核通过时同步数据
if (this.auditStatus === 2) {
this.originalData = { ...this.pendingData };
}
this.updatePageStatus();
} else {
console.log('申请详情返回数据为空或code不为200:', res);
this.backText = '';
this.updatePageStatus();
}
} catch (error) {
console.error('加载申请详情失败:', error);
this.backText = '';
this.updatePageStatus();
}
},
// 更新页面状态
updatePageStatus() {
console.log('更新页面状态,审核状态:', this.auditStatus);
// 如果已经重新提交过,强制设置为审核中状态
if (this.hasResubmitted && this.auditStatus === 3) {
console.log('检测到已重新提交,强制设置为审核中状态');
this.auditStatus = 1;
this.backText = '';
}
if (this.auditStatus === 1) { // 审核中
this.showAuditTip = true;
this.buttonType = 'view';
this.editable = false;
this.showPendingData = false;
this.displayData = { ...this.originalData };
} else if (this.auditStatus === 3) { // 审核驳回
this.showAuditTip = false;
this.buttonType = 'reject';
this.editable = false;
this.showPendingData = false;
this.displayData = { ...this.originalData };
} else { // 无申请或审核通过
this.showAuditTip = false;
this.buttonType = 'change';
this.editable = false;
this.showPendingData = false;
this.displayData = { ...this.originalData };
}
this.updateNavTitle();
},
// 更新导航栏标题
updateNavTitle() {
if (this.editable || this.showPendingData) {
this.navTitle = '资质信息变更';
} else {
this.navTitle = '资质信息';
}
},
// 用现有数据填充表单
fillFormWithExistingData() {
if (!this.artisanInfo) return;
console.log('开始填充表单数据,手艺人信息:', this.artisanInfo);
// 初始化老数据
this.originalData = {
health_card: this.artisanInfo.health_card || '',
health_card_expiry_type: '',
health_card_start_date: '',
health_card_end_date: '',
qualifications: []
};
// 填充健康证信息
if (this.artisanInfo.health_card) {
this.originalData.health_card = this.artisanInfo.health_card;
}
// 填充健康证有效期信息
const healthExpiryType = this.artisanInfo.health_expiry_type;
const healthExpiry = this.artisanInfo.health_expiry;
console.log('健康证有效期类型:', healthExpiryType, '健康证有效期:', healthExpiry);
if (healthExpiryType && healthExpiryType !== '') {
this.originalData.health_card_expiry_type = healthExpiryType;
console.log('健康证有效期类型已设置:', this.originalData.health_card_expiry_type);
// 解析有效期字符串
if (this.artisanInfo.health_expiry) {
console.log('健康证有效期字符串:', this.artisanInfo.health_expiry);
this.parseHealthExpiry(this.artisanInfo.health_expiry, this.originalData);
}
} else {
console.log('健康证有效期类型为空,使用默认值: 2 (指定日期有效)');
this.originalData.health_card_expiry_type = 2;
const currentDate = new Date();
const nextYear = new Date(currentDate.getFullYear() + 1, currentDate.getMonth(), currentDate.getDate());
this.originalData.health_card_start_date = this.formatDateToDisplay(currentDate);
this.originalData.health_card_end_date = this.formatDateToDisplay(nextYear);
}
// 填充资质照片 - 确保是深拷贝
if (this.artisanInfo.qualifications && Array.isArray(this.artisanInfo.qualifications)) {
this.originalData.qualifications = [...this.artisanInfo.qualifications];
} else {
this.originalData.qualifications = [];
}
console.log('原始资质照片数量:', this.originalData.qualifications.length);
console.log('原始资质照片内容:', JSON.stringify(this.originalData.qualifications));
// 初始化pendingData和displayData - 确保深拷贝
this.pendingData = {
health_card: this.originalData.health_card,
health_card_expiry_type: this.originalData.health_card_expiry_type,
health_card_start_date: this.originalData.health_card_start_date,
health_card_end_date: this.originalData.health_card_end_date,
qualifications: [...this.originalData.qualifications] // 重要:使用深拷贝
};
this.displayData = {
health_card: this.originalData.health_card,
health_card_expiry_type: this.originalData.health_card_expiry_type,
health_card_start_date: this.originalData.health_card_start_date,
health_card_end_date: this.originalData.health_card_end_date,
qualifications: [...this.originalData.qualifications] // 重要:使用深拷贝
};
console.log('数据初始化完成:', {
originalData: this.originalData,
pendingData: this.pendingData,
displayData: this.displayData
});
},
// 将日期格式化为显示格式
formatDateToDisplay(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}${month}${day}`;
},
// 解析健康证有效期字符串
parseHealthExpiry(expiryStr, targetData) {
if (!expiryStr) return;
console.log('解析健康证有效期:', expiryStr);
// 处理不同的分隔符情况
const separators = ['——', '--', '-'];
let parts = [];
for (let sep of separators) {
if (expiryStr.includes(sep)) {
parts = expiryStr.split(sep).map(part => part.trim());
break;
}
}
if (parts.length === 2) {
// 开始日期
if (parts[0] && parts[0] !== '') {
const startDate = this.parseBackendDate(parts[0]);
if (startDate) {
targetData.health_card_start_date = startDate;
console.log('解析出的开始日期:', startDate);
} else {
console.log('开始日期解析失败,使用当前日期');
targetData.health_card_start_date = this.formatDateToDisplay(new Date());
}
} else {
console.log('开始日期为空,使用当前日期');
targetData.health_card_start_date = this.formatDateToDisplay(new Date());
}
// 结束日期
if (parts[1] && parts[1] !== '' && parts[1] !== ' ' && parts[1] !== 'permanent') {
const endDate = this.parseBackendDate(parts[1]);
if (endDate) {
targetData.health_card_end_date = endDate;
console.log('解析出的结束日期:', endDate);
} else {
console.log('结束日期解析失败,使用一年后日期');
const currentDate = new Date();
const nextYear = new Date(currentDate.getFullYear() + 1, currentDate.getMonth(), currentDate.getDate());
targetData.health_card_end_date = this.formatDateToDisplay(nextYear);
}
} else {
console.log('结束日期为空或为长久,设置为长久有效');
targetData.health_card_end_date = '长久有效';
targetData.health_card_expiry_type = 1;
}
} else {
console.log('无法解析有效期格式,使用默认日期');
const currentDate = new Date();
const nextYear = new Date(currentDate.getFullYear() + 1, currentDate.getMonth(), currentDate.getDate());
targetData.health_card_start_date = this.formatDateToDisplay(currentDate);
targetData.health_card_end_date = this.formatDateToDisplay(nextYear);
}
},
// 解析后端日期格式
parseBackendDate(dateStr) {
if (!dateStr) return '';
console.log('解析后端日期:', dateStr);
// 处理 YYYY-MM-DD 格式
const match1 = dateStr.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
if (match1) {
const year = match1[1];
const month = parseInt(match1[2]);
const day = parseInt(match1[3]);
return `${year}${month}${day}`;
}
// 处理 YYYY/MM/DD 格式
const match2 = dateStr.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/);
if (match2) {
const year = match2[1];
const month = parseInt(match2[2]);
const day = parseInt(match2[3]);
return `${year}${month}${day}`;
}
// 处理时间戳
if (!isNaN(dateStr)) {
const date = new Date(parseInt(dateStr));
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}${month}${day}`;
}
console.log('无法识别的日期格式:', dateStr);
return dateStr;
},
// 开始变更
startChange() {
this.editable = true;
this.buttonType = 'edit';
// 进入编辑模式时将pendingData复制到displayData进行编辑
this.displayData = { ...this.pendingData };
this.updateNavTitle();
},
// 取消变更
cancelChange() {
this.editable = false;
this.buttonType = 'change';
// 恢复显示原始数据
this.displayData = { ...this.originalData };
this.updateNavTitle();
},
// 切换显示待审核数据
togglePendingData() {
this.showPendingData = !this.showPendingData;
if (this.showPendingData) {
// 显示待审核数据
this.displayData = { ...this.pendingData };
} else {
// 显示原始数据
this.displayData = { ...this.originalData };
}
this.updateNavTitle();
},
// 准备提交数据
getSubmitData() {
const submitData = {
apply_type: this.applyType, // 资质信息变更
health_card: this.displayData.health_card,
health_expiry_type: this.displayData.health_card_expiry_type,
health_expiry: this.formatHealthCardExpiry(),
qualifications: this.displayData.qualifications
};
console.log('提交数据详情:', {
health_card: this.displayData.health_card,
health_expiry_type: this.displayData.health_card_expiry_type,
health_expiry: this.formatHealthCardExpiry(),
start_date: this.displayData.health_card_start_date,
end_date: this.displayData.health_card_end_date
});
return submitData;
},
// 格式化健康证有效期
formatHealthCardExpiry() {
if (!this.displayData.health_card_start_date) {
console.log('没有开始日期,返回空字符串');
return '';
}
const startDate = this.formatDateForBackend(this.displayData.health_card_start_date);
console.log('格式化后的开始日期:', startDate);
if (this.displayData.health_card_expiry_type === 1) {
const result = `${startDate} —— `;
console.log('长久有效格式:', result);
return result;
} else if (this.displayData.health_card_end_date) {
const endDate = this.formatDateForBackend(this.displayData.health_card_end_date);
const result = `${startDate} —— ${endDate}`;
console.log('指定日期格式:', result);
return result;
}
console.log('没有有效的有效期数据');
return '';
},
// 日期显示格式化
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) {
console.log('设置健康证有效期类型:', type);
this.displayData.health_card_expiry_type = type === 'permanent' ? 1 : 2;
if (type === 'permanent') {
this.displayData.health_card_end_date = '长久有效';
} else {
if (this.displayData.health_card_end_date === '长久有效') {
this.displayData.health_card_end_date = '';
}
}
},
// 日期选择
openDatePicker(field) {
this.currentDateField = field;
console.log('打开日期选择器,字段:', field, '当前值:', this.displayData[field]);
const currentDate = new Date();
let initialDate = currentDate;
if (this.displayData[field]) {
const dateStr = this.displayData[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.$refs.datePicker.open();
},
hideDatePicker() {
this.$refs.datePicker.close();
},
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}`;
console.log('选择的日期:', dateStr, '字段:', this.currentDateField);
this.displayData[this.currentDateField] = dateStr;
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.displayData[type] = result;
}
} 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;
}
},
// 添加技师资质照片方法
addQualification() {
if (this.displayData.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.displayData.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.displayData.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.displayData.qualifications.push(result);
}
}
} catch (err) {
console.log('上传资质照片错误:', err);
}
},
// 删除资质照片
deleteQualification(index) {
console.log('删除前的资质照片列表:', JSON.stringify(this.displayData.qualifications));
console.log('要删除的索引:', index);
console.log('要删除的图片URL:', this.displayData.qualifications[index]);
this.displayData.qualifications.splice(index, 1);
console.log('删除后的资质照片列表:', JSON.stringify(this.displayData.qualifications));
console.log('删除后的长度:', this.displayData.qualifications.length);
},
// 表单验证
validateForm() {
const validationRules = [
{ field: 'health_card', message: '请上传健康证' },
{ field: 'health_card_expiry_type', message: '请选择健康证有效期类型' },
{ field: 'health_card_start_date', message: '请选择健康证开始日期' },
{
condition: () => {
// 如果选择非永久有效期,则结束日期必填
if (this.displayData.health_card_expiry_type === 2 && !this.displayData.health_card_end_date) {
return true; // 条件不满足,需要验证
}
return false;
},
message: '请选择健康证结束日期'
},
{
condition: () => {
// 至少一张技师资质照片
return !this.displayData.qualifications || this.displayData.qualifications.length === 0;
},
message: '请上传至少一张技师资质照片'
}
];
for (let rule of validationRules) {
let isValid = true;
if (rule.field) {
// 简单字段验证
if (!this.displayData[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 (this.displayData.health_card_expiry_type === 2) {
const healthCardStart = new Date(this.formatDateForBackend(this.displayData.health_card_start_date));
const healthCardEnd = new Date(this.formatDateForBackend(this.displayData.health_card_end_date));
if (healthCardEnd <= healthCardStart) {
uni.showToast({
title: '健康证结束日期必须晚于开始日期',
icon: 'none'
});
return false;
}
}
return true;
},
// 提交变更
async submitChange() {
console.log('开始提交变更...');
// 添加详细的调试信息
console.log('originalData.qualifications:', JSON.stringify(this.originalData.qualifications));
console.log('displayData.qualifications:', JSON.stringify(this.displayData.qualifications));
console.log('originalData.qualifications 长度:', this.originalData.qualifications?.length || 0);
console.log('displayData.qualifications 长度:', this.displayData.qualifications?.length || 0);
if (!this.validateForm()) {
return;
}
// 检查是否有实际变更
const hasChanged = this.hasFormDataChanged();
console.log('表单变更检测结果:', hasChanged);
if (!hasChanged) {
// 检查数组引用
console.log('displayData.qualifications === originalData.qualifications:',
this.displayData.qualifications === this.originalData.qualifications);
// 逐个比较数组元素
if (this.displayData.qualifications && this.originalData.qualifications) {
console.log('逐个比较资质照片:');
for (let i = 0; i < Math.max(this.displayData.qualifications.length, this.originalData.qualifications.length); i++) {
const displayItem = this.displayData.qualifications[i];
const originalItem = this.originalData.qualifications[i];
console.log(`索引 ${i}: display = "${displayItem}", original = "${originalItem}", 相等 = ${displayItem === originalItem}`);
}
}
uni.showToast({
title: '未检测到变更,无需提交',
icon: 'none',
duration: 2000
});
return;
}
if (!this.validateForm()) {
return;
}
// 检查是否有实际变更
if (!this.hasFormDataChanged()) {
uni.showToast({
title: '未检测到变更,无需提交',
icon: 'none',
duration: 2000
});
return;
}
try {
uni.showLoading({
title: '提交中...',
mask: true
});
const submitData = this.getSubmitData();
console.log('最终提交数据:', submitData);
const result = await request.post('/syr/userSyrAuth/apply', submitData);
uni.hideLoading();
// 根据实际接口返回格式判断
if (result.code === 200 || result.state === 1) {
uni.showToast({
title: '提交成功',
icon: 'none',
duration: 2000
});
// 提交成功后重置状态
this.backText = '';
this.auditStatus = 1;
this.hasResubmitted = true;
console.log('提交成功,重置所有状态');
// 更新pendingData为当前提交的数据
this.pendingData = { ...this.displayData };
// 更新页面状态为审核中
this.editable = false;
this.buttonType = 'view';
this.showAuditTip = true;
this.showPendingData = false;
// 重新加载申请详情获取最新状态
setTimeout(() => {
this.loadApplyDetails();
}, 1500);
} else {
uni.showToast({
title: result.msg || '提交失败',
icon: 'none'
});
}
} catch (error) {
uni.hideLoading();
console.error('提交申请失败:', error);
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
});
}
},
// 从全局恢复数据
restoreData() {
const savedData = getApp().globalData.qualificationData;
if (savedData) {
// 恢复数据到表单
Object.keys(this.displayData).forEach(key => {
if (savedData[key] !== undefined) {
this.displayData[key] = savedData[key];
}
});
console.log('资质信息数据已恢复:', this.displayData);
}
},
// 获取按钮区域高度
getButtonAreaHeight() {
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('.bottom-actions').boundingClientRect(data => {
if (data) {
this.buttonAreaHeight = data.height + 20;
}
}).exec();
}, 100);
}
}
}
</script>
<style scoped>
.qualification-page {
display: flex;
flex-direction: column;
height: 100vh;
background: #f5f5f5;
}
.content-area {
flex: 1;
overflow-y: auto;
padding: 30rpx 20rpx;
padding-bottom: 0;
}
/* 变更提示 */
.change-tip {
background: #FAE7EC;
padding: 20rpx;
text-align: center;
}
.change-tip text {
font-size: 28rpx;
color: #D4131F;
}
/* 驳回原因样式 */
.reject-reason {
background: transparent;
padding: 24rpx;
}
.reject-title {
font-family: PingFangSC, PingFang SC;
font-weight: 500;
font-size: 32rpx;
color: #333333;
line-height: 45rpx;
text-align: center;
font-style: normal;
}
.reject-detail {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 28rpx;
color: #999999;
line-height: 40rpx;
text-align: center;
font-style: normal;
margin-top: 12rpx;
}
/* 审核中提示 */
.audit-tip {
margin: 20rpx 24rpx 20rpx 24rpx;
border-radius: 12rpx;
}
.audit-text {
font-weight: 400;
font-size: 32rpx;
color: #333333;
text-align: center;
display: block;
}
/* 底部按钮样式 */
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 0rpx 24rpx 40rpx 24rpx;
background: #ffffff;
/* z-index: 100; */
}
.action-btn {
height: 88rpx;
border-radius: 43rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: 400;
margin-top: 20rpx;
}
.change-info-btn, .view-change-btn, .resubmit-btn {
background: linear-gradient(180deg, #f52540 0%, #e8101e 100%);
}
/* 双按钮行样式 */
.action-buttons-row {
display: flex;
justify-content: space-between;
margin: 0 30rpx;
}
.action-buttons-row .action-btn {
width: 270rpx;
}
.cancel-btn {
background: #E5E5E5;
border-radius: 43rpx;
padding: 0 15rpx;
}
.submit-btn {
background: linear-gradient(180deg, #F52540 0%, #E8101E 100%, #E8101E 100%);
border-radius: 43rpx;
padding: 0 15rpx;
}
.btn-text {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 36rpx;
color: #FFFFFF;
line-height: 50rpx;
text-align: left;
font-style: normal;
}
.cancel-text {
color: #666666;
}
.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;
}
.box-cont {
background: #FFFFFF;
border-radius: 20rpx;
margin-bottom: 24rpx;
margin-left: 8rpx;
margin-right: 8rpx;
box-shadow: none;
}
.form-item {
padding: 24rpx 22rpx;
}
.label {
font-size: 28rpx;
color: #333333;
font-weight: 500;
line-height: 1;
}
.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-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;
}
.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;
}
.camera-icon {
width: 446rpx;
height: 298rpx;
border-radius: 48rpx;
}
.preview-image {
border-radius: 20rpx;
width: 100%;
height: 100%;
}
.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: #333333;
}
.placeholder {
color: #999999;
font-size: 28rpx;
}
.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-picker-box.disabled .date-divider {
background-color: #F3F3F3;
}
/* 确保日期文字区域可以自动扩展 */
.date-picker-box text {
flex: 1;
}
/* 技师资质照片样式 */
.qualifications-container {
margin: 20rpx 5rpx 10rpx 6rpx;
}
.qualifications-list {
display: flex;
flex-wrap: wrap;
gap: 9rpx;
}
.qualification-item {
position: relative;
width: 208rpx;
height: 208rpx;
border-radius: 11rpx;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.add-item {
background: #F5F5F5 ;
}
.qualification-image {
width: 100%;
height: 100%;
}
.upload-icon {
width: 100rpx;
/* height: 76rpx; */
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;
}
.safe-bottom {
height: 150rpx;
}
/* 日期选择器弹窗样式 */
.date-picker-popup {
height: 500rpx;
background: #fff;
}
.picker-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.picker-cancel, .picker-confirm {
font-size: 32rpx;
color: #666;
}
.picker-title {
font-size: 36rpx;
color: #333;
font-weight: 500;
}
.picker-view {
height: 400rpx;
}
.picker-item {
line-height: 68rpx;
text-align: center;
font-size: 32rpx;
}
</style>