1498 lines
57 KiB
Vue
1498 lines
57 KiB
Vue
<template>
|
||
<view class="knzz-zzq-apply">
|
||
<!-- 选项卡容器 -->
|
||
<view class="tabs-container">
|
||
<view class="tabs-header">
|
||
<view class="tab-item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
|
||
<uni-icons type="contact" size="12" :color="activeTab === 0 ? '#409EFF' : '#666'"></uni-icons>
|
||
<text class="tab-text">基本信息</text>
|
||
</view>
|
||
<view class="tab-item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
|
||
<uni-icons type="compose" size="12" :color="activeTab === 1 ? '#409EFF' : '#666'"></uni-icons>
|
||
<text class="tab-text">学习情况</text>
|
||
</view>
|
||
<view class="tab-item" :class="{ active: activeTab === 2 }" @click="switchTab(2)">
|
||
<uni-icons type="chat" size="12" :color="activeTab === 2 ? '#409EFF' : '#666'"></uni-icons>
|
||
<text class="tab-text">申请理由</text>
|
||
</view>
|
||
<view class="tab-item" :class="{ active: activeTab === 3 }" @click="switchTab(3)">
|
||
<uni-icons type="document" size="12" :color="activeTab === 3 ? '#409EFF' : '#666'"></uni-icons>
|
||
<text class="tab-text">审核意见</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 表单内容区域 -->
|
||
<scroll-view scroll-y class="form-scroll" :style="{ height: formScrollHeight }">
|
||
<view class="form-wrapper">
|
||
<!-- 1. 基本信息标签页 -->
|
||
<view v-show="activeTab === 0" class="tab-panel">
|
||
<view class="form-card">
|
||
<view class="card-title">学生基本信息</view>
|
||
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>学号</label>
|
||
<input v-model="formData.stuNo" placeholder="请输入学号" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>姓名</label>
|
||
<input v-model="formData.stuName" placeholder="请输入姓名" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>性别</label>
|
||
<picker mode="selector" :range="genderOptions" :range-key="'text'" v-model="formData.gender" @change="handleGenderChange" :disabled="type === 'detail'">
|
||
<view class="picker-input">
|
||
{{ formData.gender ? formData.gender : '请选择性别' }}
|
||
</view>
|
||
</picker>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>出生年月</label>
|
||
<input v-model="formData.birthMonth" placeholder="请输入出生年月" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>民族</label>
|
||
<input v-model="formData.mz" placeholder="请输入民族" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>政治面貌</label>
|
||
<input v-model="formData.zzmm" placeholder="请输入政治面貌" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>学院</label>
|
||
<input v-model="formData.deptName" placeholder="请输入学院" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>专业</label>
|
||
<input v-model="formData.majorName" placeholder="请输入专业" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>班级</label>
|
||
<input v-model="formData.className" placeholder="请输入班级" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>所在年级</label>
|
||
<input v-model="formData.gradeName" placeholder="请输入所在年级" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>入学时间</label>
|
||
<input v-model="formData.inTime" placeholder="请输入入学时间" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>身份证号码</label>
|
||
<input v-model="formData.idCard" placeholder="请输入身份证号码" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>联系电话</label>
|
||
<input v-model="formData.stuPhone" placeholder="请输入联系电话" class="form-input" :disabled="type === 'detail'"></input>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>曾获何种奖励</label>
|
||
<textarea v-model="formData.helpHis" placeholder="请输入曾获何种奖励" class="form-textarea" :disabled="type === 'detail'"></textarea>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>证件照</label>
|
||
<!-- 编辑模式显示上传组件 -->
|
||
<view class="example-body" v-if="type !== 'detail'">
|
||
<uni-file-picker
|
||
@select="handlePhotoUpload"
|
||
@delete="deletePhoto"
|
||
:auto-upload="false"
|
||
limit="1"
|
||
:disabled="type === 'detail'"
|
||
mode="grid"
|
||
:value="filePickerValue"
|
||
></uni-file-picker>
|
||
</view>
|
||
<view class="upload-tip" v-if="type !== 'detail'">支持上传jpg/png格式照片,单个文件不超过5MB</view>
|
||
<!-- 详情模式显示照片预览 -->
|
||
<view class="photo-preview-container" v-if="formData.pic && type === 'detail'">
|
||
<image :src="getFullImageUrl(formData.pic)" mode="aspectFill"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 2. 学习情况标签页 -->
|
||
<view v-show="activeTab === 1" class="tab-panel">
|
||
<view class="form-card">
|
||
<view class="card-title">学习情况</view>
|
||
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>成绩排名(专业)</label>
|
||
<view class="rank-container">
|
||
<input v-model="formData.majorRank" placeholder="名次" class="rank-input" :disabled="type === 'detail'" type="number"></input>
|
||
<span class="rank-separator">/</span>
|
||
<input v-model="formData.majorNum" placeholder="总人数" class="rank-input" :disabled="type === 'detail'" type="number"></input>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>实行综合考评排名</label>
|
||
<view class="radio-container">
|
||
<view class="radio-item" @click="setIsCph('是')" :class="{ active: formData.isCph === '是' }">
|
||
<view class="radio-circle"></view>
|
||
<span class="radio-text">是</span>
|
||
</view>
|
||
<view class="radio-item" @click="setIsCph('否')" :class="{ active: formData.isCph === '否' }">
|
||
<view class="radio-circle"></view>
|
||
<span class="radio-text">否</span>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>必修课</label>
|
||
<view class="course-container">
|
||
<input v-model="formData.bxk" placeholder="门数" class="course-input" :disabled="type === 'detail'" type="number"></input>
|
||
<span class="course-text">门,其中及格以上</span>
|
||
<input v-model="formData.jg" placeholder="门数" class="course-input" :disabled="type === 'detail'" type="number"></input>
|
||
<span class="course-text">门</span>
|
||
</view>
|
||
</view>
|
||
<view class="form-item" v-if="formData.isCph === '是'">
|
||
<label class="form-label"><span class="red-tip">*</span>如是,排名(班级)</label>
|
||
<view class="rank-container">
|
||
<input v-model="formData.classRank" placeholder="名次" class="rank-input" :disabled="type === 'detail'" type="number"></input>
|
||
<span class="rank-separator">/</span>
|
||
<input v-model="formData.classNum" placeholder="总人数" class="rank-input" :disabled="type === 'detail'" type="number"></input>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 3. 申请理由标签页 -->
|
||
<view v-show="activeTab === 2" class="tab-panel">
|
||
<view class="form-card">
|
||
<view class="card-title">申请理由</view>
|
||
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>申请理由(100-150字)</label>
|
||
<textarea v-model="formData.applyReason" placeholder="请输入申请理由" class="form-textarea" :disabled="type === 'detail'"></textarea>
|
||
<view class="word-count">{{ formData.applyReason.length }}/150</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>证明材料</label>
|
||
<view class="upload-container">
|
||
<view class="upload-btn" @click="handleHardFileUpload" :class="{ 'upload-disabled': type === 'detail' }">
|
||
<text class="upload-icon">+</text>
|
||
<text>{{ type === 'detail' ? '已上传证明材料' : '上传文件' }}</text>
|
||
</view>
|
||
<view class="file-list" v-if="hardFiles.length">
|
||
<view class="file-item" v-for="(file, index) in hardFiles" :key="index">
|
||
<text class="file-name" @click="previewFile(file.url)">{{ file.name }}</text>
|
||
<uni-icons type="trash-filled" size="30" @click="deleteHardFile(index)" v-if="type !== 'detail'" class="delete-btn"></uni-icons>
|
||
</view>
|
||
</view>
|
||
<view class="upload-tip">请上传 大小不超过 10MB 格式为 doc/docx/xls/ppt/txt/pdf/xlsx 的文件</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<label class="form-label"><span class="red-tip">*</span>申请人签名</label>
|
||
<view class="sign-img" v-if="signImg">
|
||
<image :src="signImg" mode="aspectFit" style="width: 200px; height: 50px; cursor: pointer;"></image>
|
||
<text @tap="signToggle" class="re-sign-text">重新签名</text>
|
||
</view>
|
||
<view v-else class="sign" @tap="signToggle" :class="{ 'sign-disabled': type === 'detail' }">
|
||
点击签名
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 4. 审核意见标签页 -->
|
||
<view v-show="activeTab === 3" class="tab-panel">
|
||
<view class="form-card">
|
||
<view class="card-title">审核意见</view>
|
||
|
||
<!-- 辅导员审核意见 -->
|
||
<view class="approval-section">
|
||
<view class="section-title">辅导员意见</view>
|
||
<view class="approval-content">
|
||
<text v-if="formData.fdyCmt" class="approval-text">{{ formData.fdyCmt }}</text>
|
||
<text v-else class="no-content">暂无审核意见</text>
|
||
</view>
|
||
<view class="approval-info">
|
||
<text v-if="formData.fdyName">审核人:{{ formData.fdyName }}</text>
|
||
<text v-if="formData.fdyDate">审核时间:{{ formData.fdyDate }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 院系审核意见 -->
|
||
<view class="approval-section">
|
||
<view class="section-title">院系审核意见</view>
|
||
<view class="approval-content">
|
||
<text v-if="formData.deptCmt" class="approval-text">{{ formData.deptCmt }}</text>
|
||
<text v-else class="no-content">暂无审核意见</text>
|
||
</view>
|
||
<view class="approval-info">
|
||
<text v-if="formData.xwName">审核人:{{ formData.xwName }}</text>
|
||
<text v-if="formData.deptDate">审核时间:{{ formData.deptDate }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 学校审核意见 -->
|
||
<view class="approval-section">
|
||
<view class="section-title">学校审核意见</view>
|
||
<view class="approval-content">
|
||
<text v-if="formData.xgCmt" class="approval-text">{{ formData.xgCmt }}</text>
|
||
<text v-else class="no-content">暂无审核意见</text>
|
||
</view>
|
||
<view class="approval-info">
|
||
<text v-if="formData.xgName">审核人:{{ formData.xgName }}</text>
|
||
<text v-if="formData.xgDate">审核时间:{{ formData.xgDate }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 签名组件 -->
|
||
<jp-signature-popup ref="jpSignature" :required="true" popup @change="uploadSign" />
|
||
|
||
<!-- 提交按钮 -->
|
||
<view class="submit-container" v-if="type !== 'detail'">
|
||
<button class="submit-btn" @click="submitForm">{{ isReApply ? '重新提交' : '提交申请' }}</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getDetail, doApply, doEdit, doReApply, getOwnInfo, getOwnExtraInfo, getYearByTag } from '@/api/finance/knzzZzq';
|
||
import { getOwnSign } from '@/api/workStudy/post';
|
||
import uploadFile from "@/plugins/upload.js";
|
||
import config from "@/config.js";
|
||
export default {
|
||
name: "KnzzZzqApply",
|
||
data() {
|
||
return {
|
||
// 表单数据
|
||
formData: {
|
||
id: '',
|
||
stuNo: '',
|
||
stuName: '',
|
||
gender: '',
|
||
birthMonth: '',
|
||
mz: '',
|
||
zzmm: '',
|
||
inTime: '',
|
||
gradeName: '',
|
||
idCard: '',
|
||
stuPhone: '',
|
||
deptName: '',
|
||
majorName: '',
|
||
className: '',
|
||
pic: '',
|
||
helpHis: '',
|
||
majorRank: '',
|
||
majorNum: '',
|
||
isCph: '',
|
||
bxk: '',
|
||
jg: '',
|
||
classRank: '',
|
||
classNum: '',
|
||
applyReason: '',
|
||
applySign: '',
|
||
applyFile: '',
|
||
applyDate: '',
|
||
fdyCmt: '',
|
||
fdyDate: '',
|
||
fdyName: '',
|
||
deptCmt: '',
|
||
deptDate: '',
|
||
xwName: '',
|
||
xgCmt: '',
|
||
xgDate: '',
|
||
xgName: '',
|
||
leaderCmt: '',
|
||
leaderDate: '',
|
||
leaderName: ''
|
||
},
|
||
// 签名图片
|
||
signImg: '',
|
||
// 基础URL
|
||
baseUrl: config.baseUrl || '',
|
||
// 选项卡状态
|
||
activeTab: 0,
|
||
// 表单滚动高度
|
||
formScrollHeight: '',
|
||
// 类型:detail 查看,edit 编辑,add 新增
|
||
type: 'add',
|
||
// 是否重新提交
|
||
isReApply: false,
|
||
// 性别选项
|
||
genderOptions: [
|
||
{ value: '男', text: '男' },
|
||
{ value: '女', text: '女' }
|
||
],
|
||
// 证件照文件列表
|
||
photoFiles: [],
|
||
// 证明材料文件列表
|
||
hardFiles: []
|
||
};
|
||
},
|
||
onLoad(option) {
|
||
const id = option.id;
|
||
this.type = option.type || 'add';
|
||
this.isReApply = option.isReApply === 'true';
|
||
|
||
if (id) {
|
||
this.formData.id = id;
|
||
this.getDetail(id);
|
||
} else {
|
||
this.initData();
|
||
}
|
||
|
||
this.calculateFormHeight();
|
||
},
|
||
onShow() {
|
||
this.calculateFormHeight();
|
||
},
|
||
onResize() {
|
||
this.calculateFormHeight();
|
||
},
|
||
computed: {
|
||
filePickerValue() {
|
||
if (this.formData.pic) {
|
||
return [{
|
||
url: this.getFullImageUrl(this.formData.pic),
|
||
name: '证件照',
|
||
size: 0
|
||
}];
|
||
}
|
||
return [];
|
||
}
|
||
},
|
||
methods: {
|
||
// 计算表单高度
|
||
calculateFormHeight() {
|
||
const windowHeight = uni.getSystemInfoSync().windowHeight;
|
||
const tabsHeight = 80;
|
||
const submitHeight = this.type !== 'detail' ? 100 : 0;
|
||
this.formScrollHeight = `${windowHeight - tabsHeight - submitHeight}px`;
|
||
},
|
||
|
||
// 切换选项卡
|
||
switchTab(index) {
|
||
this.activeTab = index;
|
||
},
|
||
|
||
// 处理性别选择
|
||
handleGenderChange(e) {
|
||
const index = e.detail.value;
|
||
this.formData.gender = this.genderOptions[index].value;
|
||
},
|
||
|
||
// 初始化数据
|
||
async initData() {
|
||
try {
|
||
// 获取学年信息
|
||
await this.fetchYearData();
|
||
|
||
// 并行请求所有基础信息
|
||
const [infoRes, signRes] = await Promise.all([
|
||
getOwnInfo(),
|
||
getOwnSign()
|
||
]);
|
||
|
||
const infoData = infoRes.data || {};
|
||
|
||
// 填充基本信息
|
||
this.formData.stuNo = infoData.stuNo || infoData.userName || '';
|
||
this.formData.stuName = infoData.name || '';
|
||
this.formData.gender = infoData.gender || '';
|
||
this.formData.deptName = infoData.dept?.deptName || '';
|
||
this.formData.majorName = infoData.srsMajors?.majorName || infoData.major?.majorName || '';
|
||
this.formData.className = infoData.srsClass?.className || infoData.className || '';
|
||
this.formData.gradeName = infoData.gradeName || '';
|
||
this.formData.stuPhone = infoData.phone || infoData.mobile || '';
|
||
this.formData.idCard = infoData.idCard || '';
|
||
|
||
// 处理出生年月
|
||
if (infoData.birthday) {
|
||
const date = new Date(infoData.birthday);
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
this.formData.birthMonth = `${year}年${month}月`;
|
||
}
|
||
|
||
// 处理签名信息
|
||
if (signRes && signRes.data) {
|
||
this.formData.applySign = signRes.data;
|
||
this.signImg = this.baseUrl + signRes.data;
|
||
}
|
||
|
||
// 获取个人扩展信息
|
||
const extraRes = await getOwnExtraInfo();
|
||
const extraData = extraRes.data || {};
|
||
|
||
// 填充扩展信息
|
||
this.formData.mz = extraData.mz || '';
|
||
this.formData.zzmm = extraData.zzmm || '';
|
||
|
||
// 处理证件照
|
||
if (extraData.whitePhoto) {
|
||
this.formData.pic = extraData.whitePhoto;
|
||
// 从文件路径中提取文件名
|
||
const fileName = extraData.whitePhoto.split('/').pop();
|
||
// 构造完整的URL
|
||
const fullUrl = this.baseUrl + extraData.whitePhoto;
|
||
// 更新 photoFiles 数组,使 uni-file-picker 组件显示已有的证件照
|
||
this.photoFiles = [{
|
||
name: fileName,
|
||
path: extraData.whitePhoto,
|
||
url: fullUrl
|
||
}];
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('获取数据失败:', error);
|
||
uni.showToast({
|
||
title: '获取数据失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 获取学年信息
|
||
async fetchYearData() {
|
||
try {
|
||
const response = await getYearByTag('RMZF');
|
||
this.leaderList = response.data || [];
|
||
} catch (error) {
|
||
console.error('获取学年信息失败:', error);
|
||
}
|
||
},
|
||
|
||
// 获取详情
|
||
async getDetail(id) {
|
||
try {
|
||
const response = await getDetail(id);
|
||
const data = response.data || {};
|
||
|
||
// 填充表单数据
|
||
this.formData = {
|
||
...this.formData,
|
||
...data
|
||
};
|
||
|
||
// 处理证件照
|
||
if (data.pic) {
|
||
// 从文件路径中提取文件名
|
||
const fileName = data.pic.split('/').pop();
|
||
// 构造完整的URL
|
||
const fullUrl = this.getFullImageUrl(data.pic);
|
||
// 更新 photoFiles 数组,使编辑模式下能够预览图片
|
||
this.photoFiles = [{
|
||
name: fileName,
|
||
path: data.pic,
|
||
url: fullUrl
|
||
}];
|
||
console.log('处理证件照,formData.pic:', this.formData.pic);
|
||
console.log('fullUrl:', fullUrl);
|
||
console.log('photoFiles:', this.photoFiles);
|
||
}
|
||
|
||
// 处理证明材料
|
||
if (data.applyFile) {
|
||
const filePaths = data.applyFile.split(',');
|
||
this.hardFiles = filePaths.map(filePath => {
|
||
const fileName = filePath.split('/').pop();
|
||
return {
|
||
name: fileName,
|
||
path: filePath,
|
||
url: filePath
|
||
};
|
||
});
|
||
}
|
||
|
||
// 处理签名图片
|
||
if (data.applySign) {
|
||
this.formData.applySign = data.applySign;
|
||
this.signImg = this.baseUrl + data.applySign;
|
||
} else {
|
||
this.signImg = '';
|
||
}
|
||
} catch (error) {
|
||
console.error('获取详情失败:', error);
|
||
uni.showToast({
|
||
title: '获取详情失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 处理证件照上传
|
||
handlePhotoUpload(e) {
|
||
// 如果是详情模式,不执行上传操作
|
||
if (this.type === 'detail') {
|
||
return;
|
||
}
|
||
|
||
const tempFiles = e.tempFilePaths || [];
|
||
|
||
// 遍历选择的文件,逐个上传
|
||
for (const file of e.tempFiles) {
|
||
this.uploadFile(file);
|
||
}
|
||
},
|
||
|
||
// 上传文件的通用方法
|
||
async uploadFile(file) {
|
||
try {
|
||
// 检查文件大小(5MB = 5 * 1024 * 1024 bytes)
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 大小超过5MB,请重新选择`,
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查文件格式
|
||
const ext = file.name.split('.').pop().toLowerCase();
|
||
const allowedExts = ['jpg', 'jpeg', 'png'];
|
||
if (!allowedExts.includes(ext)) {
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 格式不支持,请选择 JPG、PNG 格式的文件`,
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 上传文件
|
||
const uploadRes = await uploadFile('/common/upload', file.path);
|
||
const result = typeof uploadRes === 'string' ? JSON.parse(uploadRes) : uploadRes;
|
||
|
||
// 上传结果校验
|
||
if (result && (result.code === 200 || !result.code)) {
|
||
// 构造文件信息对象
|
||
const fileUrl = result.savePath || result.fileName;
|
||
const fullUrl = this.getFullImageUrl(fileUrl);
|
||
const fileInfo = {
|
||
name: file.name,
|
||
path: fileUrl,
|
||
url: fullUrl
|
||
};
|
||
|
||
// 更新 formData.pic
|
||
this.formData.pic = fileUrl;
|
||
|
||
// 更新 photoFiles 数组,确保 uni-file-picker 组件能获取预览路径
|
||
this.photoFiles = [fileInfo];
|
||
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传成功`,
|
||
icon: 'success',
|
||
duration: 1500
|
||
});
|
||
} else {
|
||
// 上传失败处理
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传失败:${result.message || '未知错误'}`,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
} catch (error) {
|
||
// 异常捕获
|
||
console.error(`文件 ${file.name} 上传异常:`, error);
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传异常:${error.message || '请检查网络连接'}`,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
},
|
||
|
||
// 删除证件照
|
||
deletePhoto() {
|
||
this.formData.pic = '';
|
||
this.photoFiles = [];
|
||
uni.showToast({
|
||
title: '删除成功',
|
||
icon: 'success'
|
||
});
|
||
},
|
||
// 获取完整图片URL
|
||
getFullImageUrl(path) {
|
||
if (!path) return '';
|
||
// 调试信息
|
||
console.log('getFullImageUrl调用,path:', path);
|
||
// 如果已经是完整URL,则直接返回
|
||
if (path.startsWith('http://') || path.startsWith('https://')) {
|
||
return path;
|
||
}
|
||
// 使用配置文件中的baseUrl
|
||
const currentBaseUrl = config.baseUrl || '';
|
||
console.log('当前baseUrl:', currentBaseUrl);
|
||
// 处理baseUrl,确保结尾没有斜杠
|
||
const baseUrlClean = currentBaseUrl.replace(/\/$/, '');
|
||
// 处理path,确保开头没有斜杠
|
||
const pathClean = path.replace(/^\//, '');
|
||
// 拼接URL
|
||
const fullUrl = `${baseUrlClean}/${pathClean}`;
|
||
console.log('拼接后的完整URL:', fullUrl);
|
||
return fullUrl;
|
||
},
|
||
|
||
// 预览证件照
|
||
previewPhoto() {
|
||
if (this.photoFiles.length > 0) {
|
||
uni.previewImage({
|
||
urls: [this.photoFiles[0].url]
|
||
});
|
||
}
|
||
},
|
||
|
||
// 处理证明材料上传
|
||
handleHardFileUpload() {
|
||
// 如果是详情模式,不执行上传操作
|
||
if (this.type === 'detail') {
|
||
return;
|
||
}
|
||
|
||
uni.chooseFile({
|
||
count: 5 - this.hardFiles.length, // 最多选择剩余的文件数
|
||
extension: ['doc', 'docx', 'xls', 'ppt', 'txt', 'pdf', 'xlsx'], // 限制文件类型
|
||
success: async (chooseRes) => {
|
||
// 遍历选择的文件,逐个上传
|
||
for (const file of chooseRes.tempFiles) {
|
||
try {
|
||
// 检查文件大小(10MB = 10 * 1024 * 1024 bytes)
|
||
if (file.size > 10 * 1024 * 1024) {
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 大小超过10MB,请重新选择`,
|
||
icon: 'none'
|
||
});
|
||
continue;
|
||
}
|
||
|
||
// 检查文件格式
|
||
const ext = file.name.split('.').pop().toLowerCase();
|
||
const allowedExts = ['doc', 'docx', 'xls', 'ppt', 'txt', 'pdf', 'xlsx'];
|
||
if (!allowedExts.includes(ext)) {
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 格式不支持,请选择 doc/docx/xls/ppt/txt/pdf/xlsx 格式的文件`,
|
||
icon: 'none'
|
||
});
|
||
continue;
|
||
}
|
||
|
||
// 上传文件
|
||
const uploadRes = await uploadFile('/common/upload', file.path);
|
||
const result = typeof uploadRes === 'string' ? JSON.parse(uploadRes) : uploadRes;
|
||
|
||
// 上传结果校验
|
||
if (result && (result.code === 200 || !result.code)) {
|
||
// 构造文件信息对象
|
||
const fileInfo = {
|
||
name: file.name,
|
||
path: result.savePath || result.fileName,
|
||
url: result.savePath || result.fileName
|
||
};
|
||
|
||
// 去重逻辑
|
||
const isDuplicate = this.hardFiles.some(item =>
|
||
item.name === file.name && item.url === fileInfo.url
|
||
);
|
||
|
||
if (!isDuplicate) {
|
||
this.hardFiles.push(fileInfo);
|
||
}
|
||
|
||
// 更新 formData.applyFile
|
||
this.formData.applyFile = this.hardFiles.map(file => file.url).join(',');
|
||
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传成功`,
|
||
icon: 'success',
|
||
duration: 1500
|
||
});
|
||
} else {
|
||
// 上传失败处理
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传失败:${result.message || '未知错误'}`,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
} catch (error) {
|
||
// 异常捕获
|
||
console.error(`文件 ${file.name} 上传异常:`, error);
|
||
uni.showToast({
|
||
title: `文件 ${file.name} 上传异常:${error.message || '请检查网络连接'}`,
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
}
|
||
},
|
||
// 取消选择文件的处理
|
||
fail: (err) => {
|
||
console.error('选择文件失败:', err);
|
||
uni.showToast({
|
||
title: '选择文件失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
},
|
||
|
||
// 删除证明材料
|
||
deleteHardFile(index) {
|
||
this.hardFiles.splice(index, 1);
|
||
// 更新 formData.applyFile
|
||
this.formData.applyFile = this.hardFiles.map(file => file.url).join(',');
|
||
uni.showToast({
|
||
title: '删除成功',
|
||
icon: 'success'
|
||
});
|
||
},
|
||
|
||
// 预览文件
|
||
previewFile(url) {
|
||
uni.showToast({
|
||
title: '正在预览文件',
|
||
icon: 'none'
|
||
});
|
||
// 这里可以添加文件预览逻辑,根据文件类型选择不同的预览方式
|
||
// 例如,对于图片可以使用 uni.previewImage,对于PDF可以使用web-view等
|
||
},
|
||
|
||
// 签名切换
|
||
signToggle() {
|
||
if (this.$refs.jpSignature) {
|
||
this.$refs.jpSignature.toPop();
|
||
}
|
||
},
|
||
|
||
// 上传签名
|
||
async uploadSign(data) {
|
||
if (data) {
|
||
try {
|
||
// 上传签名图片到后端
|
||
const uploadRes = await uploadFile('/common/upload', data);
|
||
const result = typeof uploadRes === 'string' ? JSON.parse(uploadRes) : uploadRes;
|
||
if (result && (result.code === 200 || !result.code)) {
|
||
this.formData.applySign = result.fileName || result.savePath;
|
||
this.signImg = result.url || (this.baseUrl + (result.fileName || result.savePath));
|
||
} else {
|
||
uni.showToast({
|
||
title: '签名上传失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('签名上传失败:', error);
|
||
uni.showToast({
|
||
title: `签名上传失败:${error.message || '请检查网络连接'}`,
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
},
|
||
|
||
// 设置是否实行综合考评排名
|
||
setIsCph(value) {
|
||
this.formData.isCph = value;
|
||
},
|
||
|
||
// 表单验证
|
||
validateForm() {
|
||
// 基本信息验证
|
||
if (!this.formData.stuNo) {
|
||
uni.showToast({ title: '请输入学号', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.stuName) {
|
||
uni.showToast({ title: '请输入姓名', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.gender) {
|
||
uni.showToast({ title: '请选择性别', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.birthMonth) {
|
||
uni.showToast({ title: '请输入出生年月', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.mz) {
|
||
uni.showToast({ title: '请输入民族', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.zzmm) {
|
||
uni.showToast({ title: '请输入政治面貌', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.deptName) {
|
||
uni.showToast({ title: '请输入学院', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.majorName) {
|
||
uni.showToast({ title: '请输入专业', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.className) {
|
||
uni.showToast({ title: '请输入班级', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.gradeName) {
|
||
uni.showToast({ title: '请输入所在年级', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.inTime) {
|
||
uni.showToast({ title: '请输入入学时间', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.idCard) {
|
||
uni.showToast({ title: '请输入身份证号码', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.stuPhone) {
|
||
uni.showToast({ title: '请输入联系电话', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.helpHis) {
|
||
uni.showToast({ title: '请输入曾获何种奖励', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.pic) {
|
||
uni.showToast({ title: '请上传证件照', icon: 'none' });
|
||
return false;
|
||
}
|
||
|
||
// 学习情况验证
|
||
if (!this.formData.majorRank) {
|
||
uni.showToast({ title: '请输入专业排名', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.majorNum) {
|
||
uni.showToast({ title: '请输入专业总人数', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.isCph) {
|
||
uni.showToast({ title: '请选择是否实行综合考评排名', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.bxk) {
|
||
uni.showToast({ title: '请输入必修课门数', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.jg) {
|
||
uni.showToast({ title: '请输入及格门数', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (this.formData.isCph === '是') {
|
||
if (!this.formData.classRank) {
|
||
uni.showToast({ title: '请输入班级排名', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.classNum) {
|
||
uni.showToast({ title: '请输入班级总人数', icon: 'none' });
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 申请理由验证
|
||
if (!this.formData.applyReason) {
|
||
uni.showToast({ title: '请输入申请理由', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (this.formData.applyReason.length < 100 || this.formData.applyReason.length > 150) {
|
||
uni.showToast({ title: '申请理由必须为100-150字', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.applyFile) {
|
||
uni.showToast({ title: '请上传证明材料', icon: 'none' });
|
||
return false;
|
||
}
|
||
if (!this.formData.applySign) {
|
||
uni.showToast({ title: '请上传申请人签名', icon: 'none' });
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
// 提交表单
|
||
async submitForm() {
|
||
if (!this.validateForm()) {
|
||
return;
|
||
}
|
||
|
||
const submitData = { ...this.formData };
|
||
|
||
// 设置申请日期
|
||
submitData.applyDate = new Date();
|
||
|
||
try {
|
||
let res;
|
||
if (this.formData.id) {
|
||
if (this.isReApply) {
|
||
// 重新提交
|
||
res = await doReApply(submitData);
|
||
} else {
|
||
// 修改
|
||
res = await doEdit(submitData);
|
||
}
|
||
} else {
|
||
// 提交申请
|
||
res = await doApply(submitData);
|
||
}
|
||
|
||
if (res.code === 200 || res.code === 0) {
|
||
uni.showToast({
|
||
title: this.isReApply ? '重新提交成功' : (this.formData.id ? '修改成功' : '提交成功'),
|
||
icon: 'success'
|
||
});
|
||
setTimeout(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg || '操作失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error('操作失败:', error);
|
||
uni.showToast({
|
||
title: '操作失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.knzz-zzq-apply {
|
||
background-color: #F3F4F6;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.tabs-container {
|
||
background-color: white;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.tabs-header {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
position: relative;
|
||
}
|
||
|
||
.tabs-header::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 1rpx;
|
||
background-color: #f0f0f0;
|
||
}
|
||
|
||
.tab-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 10rpx 20rpx;
|
||
position: relative;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.tab-item.active {
|
||
color: #409EFF;
|
||
}
|
||
|
||
.tab-item.active::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -1rpx;
|
||
left: 10%;
|
||
width: 80%;
|
||
height: 4rpx;
|
||
background-color: #409EFF;
|
||
border-radius: 2rpx;
|
||
}
|
||
|
||
.tab-text {
|
||
font-size: 26rpx;
|
||
margin-top: 5rpx;
|
||
}
|
||
|
||
.form-scroll {
|
||
width: 100%;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.form-wrapper {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.form-card {
|
||
background-color: white;
|
||
border-radius: 10rpx;
|
||
padding: 20rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 20rpx;
|
||
padding-bottom: 10rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
}
|
||
|
||
.form-item {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.red-tip {
|
||
color: #f56c6c;
|
||
margin-right: 5rpx;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.form-input:disabled {
|
||
background-color: #f5f7fa;
|
||
color: #c0c4cc;
|
||
}
|
||
|
||
.picker-input {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #fafafa;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.form-textarea {
|
||
width: 100%;
|
||
min-height: 200rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #fafafa;
|
||
resize: none;
|
||
}
|
||
|
||
.form-textarea:disabled {
|
||
background-color: #f5f7fa;
|
||
color: #c0c4cc;
|
||
}
|
||
|
||
.upload-container {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.upload-tip {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.sign {
|
||
width: 200px;
|
||
height: 50px;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 10rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #fafafa;
|
||
cursor: pointer;
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
}
|
||
|
||
.sign-disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.sign-img {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.re-sign-text {
|
||
margin-top: 10rpx;
|
||
font-size: 24rpx;
|
||
color: #409EFF;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* 排名输入容器 */
|
||
.rank-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.rank-input {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.rank-separator {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 课程输入容器 */
|
||
.course-container {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.course-input {
|
||
width: 120rpx;
|
||
height: 80rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.course-text {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 单选框容器 */
|
||
.radio-container {
|
||
display: flex;
|
||
gap: 40rpx;
|
||
}
|
||
|
||
.radio-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.radio-circle {
|
||
width: 30rpx;
|
||
height: 30rpx;
|
||
border: 2rpx solid #dcdfe6;
|
||
border-radius: 50%;
|
||
position: relative;
|
||
}
|
||
|
||
.radio-item.active .radio-circle {
|
||
border-color: #409EFF;
|
||
}
|
||
|
||
.radio-item.active .radio-circle::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 16rpx;
|
||
height: 16rpx;
|
||
background-color: #409EFF;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.radio-text {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
/* 字数统计 */
|
||
.word-count {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
text-align: right;
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
/* 审核意见区域 */
|
||
.approval-section {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 26rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 15rpx;
|
||
}
|
||
|
||
.approval-content {
|
||
padding: 20rpx;
|
||
background-color: #F9F9F9;
|
||
border-radius: 10rpx;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.approval-text {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.no-content {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.approval-info {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 22rpx;
|
||
color: #999;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
.approval-item {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.approval-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.approval-node {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.approval-time {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
}
|
||
|
||
.approval-content {
|
||
margin-left: 20rpx;
|
||
}
|
||
|
||
.approval-textarea {
|
||
width: 100%;
|
||
min-height: 150rpx;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 5rpx;
|
||
padding: 20rpx;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
background-color: #f5f7fa;
|
||
resize: none;
|
||
}
|
||
|
||
.submit-container {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background-color: white;
|
||
padding: 20rpx;
|
||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||
z-index: 999;
|
||
}
|
||
|
||
.submit-btn {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
background-color: #409EFF;
|
||
color: white;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
border: none;
|
||
border-radius: 5rpx;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.submit-btn:hover {
|
||
background-color: #66b1ff;
|
||
}
|
||
|
||
.submit-btn:active {
|
||
background-color: #3a8ee6;
|
||
}
|
||
|
||
/* 上传容器 */
|
||
.upload-container {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
/* 上传按钮 */
|
||
.upload-btn {
|
||
width: 100%;
|
||
height: 100rpx;
|
||
border: 1rpx dashed #D9D9D9;
|
||
border-radius: 10rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
background-color: #F9F9F9;
|
||
transition: all 0.3s ease;
|
||
|
||
.upload-icon {
|
||
font-size: 40rpx;
|
||
color: #999;
|
||
margin-bottom: 10rpx;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
text {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
&:hover {
|
||
border-color: #409EFF;
|
||
background-color: rgba(64, 158, 255, 0.05);
|
||
transform: translateY(-2rpx);
|
||
|
||
.upload-icon {
|
||
color: #409EFF;
|
||
}
|
||
|
||
text {
|
||
color: #409EFF;
|
||
}
|
||
}
|
||
|
||
&.upload-disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.6;
|
||
|
||
&:hover {
|
||
border-color: #D9D9D9;
|
||
background-color: #F9F9F9;
|
||
transform: none;
|
||
|
||
.upload-icon {
|
||
color: #999;
|
||
}
|
||
|
||
text {
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 文件列表 */
|
||
.file-list {
|
||
margin-top: 20rpx;
|
||
|
||
.file-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 15rpx;
|
||
background-color: #F9F9F9;
|
||
border-radius: 8rpx;
|
||
margin-bottom: 10rpx;
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
background-color: #F0F0F0;
|
||
transform: translateX(5rpx);
|
||
}
|
||
|
||
.file-name {
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
color: #409EFF;
|
||
}
|
||
}
|
||
|
||
.delete-btn {
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
color: #FF4D4F;
|
||
transform: scale(1.1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 上传提示 */
|
||
.upload-tip {
|
||
font-size: 22rpx;
|
||
color: #999;
|
||
margin-top: 10rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
/* 证件照上传容器 */
|
||
.example-body {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
/* 照片预览容器 */
|
||
.photo-preview-container {
|
||
margin-top: 20rpx;
|
||
border-radius: 8rpx;
|
||
overflow: hidden;
|
||
}
|
||
.photo-preview-container image {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
</style> |