You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
710 lines
20 KiB
710 lines
20 KiB
<template>
|
|
<div class="app-container">
|
|
|
|
<!-- 消息通知 -->
|
|
<div class="info-container">
|
|
<div class="card-container">
|
|
<div class="info-card stat-card"
|
|
@click="$router.push('/vet-info/VetNotification')"
|
|
:class="{ shake: tjzs.unreadCount > 0 }"
|
|
>
|
|
<img class="info-icon" :src="require('@/assets/images/tongzhi.png')">
|
|
<div class="info-content">
|
|
<span class="info-title">通知</span>
|
|
<div class="status-container">
|
|
<div class="status-row">
|
|
<span class="status-text">未读:{{ tjzs.unreadCount }}</span>
|
|
</div>
|
|
<div class="status-row">
|
|
<span class="status-text">已读:{{ tjzs.readCount }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="card-icon icon-total">
|
|
<i class="el-icon-message"></i>
|
|
</div>
|
|
<div class="card-text">
|
|
<div class="card-title">总数</div>
|
|
<div class="card-value">{{ tjzs.totalCount }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="card-icon icon-pending">
|
|
<i class="el-icon-check"></i>
|
|
</div>
|
|
<div class="card-text">
|
|
<div class="card-title">已读</div>
|
|
<div class="card-value">{{ tjzs.readCount }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="card-icon icon-handled">
|
|
<i class="el-icon-bell"></i>
|
|
</div>
|
|
<div class="card-text">
|
|
<div class="card-title">未读</div>
|
|
<div class="card-value">{{ tjzs.unreadCount }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 资质弹窗 -->
|
|
<el-dialog :title="title" :visible.sync="flag" width="800px" append-to-body>
|
|
<el-steps :active="activeStep" finish-status="success" simple style="margin-bottom: 10px;">
|
|
<el-step title="选择经营范围"></el-step>
|
|
<el-step title="上传资质"></el-step>
|
|
<el-step title="提交审核"></el-step>
|
|
</el-steps>
|
|
|
|
<!-- 选择经营范围 -->
|
|
<div v-if="activeStep === 0">
|
|
<el-form ref="qualificationForm" :model="qualificationForm" :rules="rules" label-width="100px">
|
|
<el-form-item label="真实姓名" prop="realName">
|
|
<el-input v-model="qualificationForm.realName" placeholder="请输入您的真实姓名" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="身份证号" prop="idCard">
|
|
<el-input v-model="qualificationForm.idCard" placeholder="请输入身份证号" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="资质类型" prop="qualificationType">
|
|
<el-select
|
|
v-model="qualificationForm.qualificationType"
|
|
placeholder="请选择资质类型"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="option in qualificationTypeOptions"
|
|
:key="option.value"
|
|
:label="option.label"
|
|
:value="option.value"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="证书编号" prop="certificateNo">
|
|
<el-input v-model="qualificationForm.certificateNo" placeholder="请输入证书编号" />
|
|
</el-form-item>
|
|
<el-form-item label="经营范围" prop="scopeIds">
|
|
<el-select
|
|
v-model="qualificationForm.scopeIds"
|
|
multiple
|
|
placeholder="请选择经营范围"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="scope in scopeOptions"
|
|
:key="scope.value"
|
|
:label="scope.label"
|
|
:value="scope.value"
|
|
/>
|
|
</el-select>
|
|
<div class="scope-choice">
|
|
已选择:{{ qualificationForm.scopeIds ? qualificationForm.scopeIds.length : 0 }} 项
|
|
</div>
|
|
</el-form-item>
|
|
</el-form>
|
|
</div>
|
|
|
|
<!-- 上传资质 -->
|
|
<div v-if="activeStep === 1">
|
|
<div class="step-summary">
|
|
<div class="summary-item">
|
|
<span class="summary-label">资质类型:</span>
|
|
<div class="scope-tags">
|
|
<el-tag
|
|
v-for="qualificationType in qualificationForm.qualificationType"
|
|
:key="qualificationType"
|
|
type="info"
|
|
size="small"
|
|
class="scope-tag"
|
|
>
|
|
{{ getQualificationTypeLabel(qualificationForm.qualificationType) }}
|
|
</el-tag>
|
|
</div>
|
|
</div>
|
|
<div class="summary-item">
|
|
<span class="summary-label">经营范围:</span>
|
|
<div class="scope-tags">
|
|
<el-tag
|
|
v-for="scopeId in qualificationForm.scopeIds"
|
|
:key="scopeId"
|
|
type="info"
|
|
size="small"
|
|
class="scope-tag"
|
|
>
|
|
{{ getScopeLabel(scopeId) }}
|
|
</el-tag>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 15px; color: #f56c6c; font-size: 14px;">
|
|
<i class="el-icon-warning"></i>
|
|
需要您上传相关的资质文件:
|
|
</div>
|
|
|
|
<el-form>
|
|
<el-form-item label="资质文件" required>
|
|
<el-upload
|
|
ref="upload"
|
|
action="#"
|
|
:multiple="true"
|
|
:file-list="fileList"
|
|
:auto-upload="false"
|
|
:on-change="handleFileChange"
|
|
:on-remove="handleRemove"
|
|
:show-file-list="true"
|
|
accept=".jpg,.jpeg,.png,.pdf,.JPG,.JPEG,.PNG,.PDF"
|
|
>
|
|
<el-button type="primary">选择文件</el-button>
|
|
<div slot="tip" class="el-upload__tip">
|
|
请上传清晰的资质文件照片或扫描件(支持JPG、PNG、PDF格式)
|
|
</div>
|
|
</el-upload>
|
|
</el-form-item>
|
|
|
|
<div v-if="uploadedFiles.length > 0" class="uploaded-files">
|
|
<div class="file-list-title">已上传文件:</div>
|
|
<div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
|
|
<i class="el-icon-document"></i>
|
|
{{ file.name }}
|
|
</div>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
|
|
<!-- 提交审核 -->
|
|
<div v-if="activeStep === 2">
|
|
<div style="text-align: center; margin-bottom: 30px;">
|
|
<i class="el-icon-circle-check" style="font-size: 60px; color: #67C23A;"></i>
|
|
<div style="margin-top: 15px; font-size: 16px; color: #303133;">
|
|
请确认信息无误后提交审核
|
|
</div>
|
|
</div>
|
|
|
|
<div style="background: #f8f9fa; padding: 15px; border-radius: 4px; margin-bottom: 20px;">
|
|
<div style="margin-bottom: 8px;"><strong>基本信息</strong></div>
|
|
<div style="margin-bottom: 5px;">真实姓名:{{ qualificationForm.realName }}</div>
|
|
<div style="margin-bottom: 5px;">身份证号:{{ qualificationForm.idCard }}</div>
|
|
<div style="margin-bottom: 5px;">资质类型:{{ qualificationForm.qualificationType }}</div>
|
|
<div>证书编号:{{ qualificationForm.certificateNo }}</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 15px; color: #606266;">
|
|
<div>经营范围:</div>
|
|
<div class="scope-tags">
|
|
<el-tag
|
|
v-for="scopeId in qualificationForm.scopeIds"
|
|
:key="scopeId"
|
|
type="info"
|
|
size="medium"
|
|
class="scope-tag"
|
|
>
|
|
{{ getScopeLabel(scopeId) }}
|
|
</el-tag>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="background: #f8f9fa; padding: 15px; border-radius: 4px; margin-bottom: 20px;">
|
|
<div style="margin-bottom: 8px;"><strong>上传文件</strong></div>
|
|
<div v-if="fileList.length > 0">
|
|
<div v-for="(file, index) in fileList" :key="index" style="margin-bottom: 5px;">
|
|
{{ file.name }}
|
|
</div>
|
|
</div>
|
|
<div v-else style="color: #909399;">暂无文件</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 操作按钮 -->
|
|
<div slot="footer" class="dialog-footer">
|
|
<div v-if="activeStep > 0" style="float: left;">
|
|
<el-button @click="prevStep">上一步</el-button>
|
|
</div>
|
|
|
|
<div v-if="activeStep < 2">
|
|
<el-button type="primary" @click="nextStep">
|
|
{{ activeStep === 1 ? '下一步' : '下一步' }}
|
|
</el-button>
|
|
</div>
|
|
|
|
<div v-if="activeStep === 2">
|
|
<el-button @click="prevStep">上一步</el-button>
|
|
<el-button type="primary" @click="submitQualification" :loading="loading">
|
|
提交审核
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { submitAuditQualification, qualificationAudit, getQualificationTypeOptions, getScopeOptions, uploadQualification } from "../api/vet/qualification";
|
|
import { getStatsCard } from "../api/vet/notification";
|
|
|
|
export default {
|
|
name: "Syd",
|
|
data() {
|
|
return {
|
|
// 消息通知
|
|
tjzs: {},
|
|
|
|
// 资质弹窗
|
|
title: "兽医资质审核",
|
|
flag: true,
|
|
open: false,
|
|
loading: false,
|
|
activeStep: 0,
|
|
qualificationForm: {
|
|
qualificationId: "",
|
|
realName: '',
|
|
idCard: '',
|
|
qualificationType: '',
|
|
certificateNo: '',
|
|
scopeIds: [],
|
|
certificateFiles: '',
|
|
},
|
|
fileList: [],
|
|
scopeOptions: [],
|
|
|
|
uploadedFiles: [],
|
|
qualificationTypeOptions: [],
|
|
selectedScopesDetail: '',
|
|
fileUploadResponses: [],
|
|
|
|
rules: {
|
|
realName: [
|
|
{required: true, message: "请输入真实姓名", trigger: "blur"}
|
|
],
|
|
idCard: [
|
|
{required: true, message: "请输入身份证号", trigger: "blur"}
|
|
],
|
|
qualificationType: [
|
|
{required: true, message: "请选择资质类型", trigger: "change"}
|
|
],
|
|
certificateNo : [
|
|
{required: true, message: "请输入证书编号", trigger: "blur"}
|
|
],
|
|
scopeIds: [
|
|
{
|
|
required: true,
|
|
type: 'array',
|
|
message: "请选择至少一个经营范围",
|
|
trigger: "change"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
this.initOptions();
|
|
this.getcountSummary()
|
|
},
|
|
methods: {
|
|
// 获取通知数据
|
|
getcountSummary() {
|
|
getStatsCard().then(res => {
|
|
this.tjzs = res.data
|
|
})
|
|
},
|
|
|
|
// 初始化选项
|
|
initOptions() {
|
|
const fetchData = async () => {
|
|
const qtypeRes = await getQualificationTypeOptions();
|
|
this.qualificationTypeOptions = qtypeRes.data;
|
|
|
|
const scopeRes = await getScopeOptions();
|
|
this.scopeOptions = scopeRes.data;
|
|
}
|
|
fetchData();
|
|
},
|
|
|
|
// 获取资质类型标签
|
|
getQualificationTypeLabel(value) {
|
|
const option = this.qualificationTypeOptions.find(item => item.value === value);
|
|
return option ? option.label : value;
|
|
},
|
|
|
|
// 获取经营范围标签
|
|
getScopeLabel(scopeId) {
|
|
const scope = this.scopeOptions.find(item => item.value === scopeId);
|
|
return scope ? scope.label : scopeId;
|
|
},
|
|
|
|
// 文件上传
|
|
uploadSingleFile(file) {
|
|
return new Promise((resolve, reject) => {
|
|
const formData = new FormData();
|
|
formData.append('file', file.raw);
|
|
|
|
uploadQualification(formData)
|
|
.then(response => {
|
|
const filePath = response.data.filePath || response.data.path || response.data.url;
|
|
this.fileUploadResponses.push({
|
|
fileName: file.name,
|
|
filePath: filePath,
|
|
fileId: response.data.id || response.data.fileId
|
|
});
|
|
this.uploadedFiles.push({
|
|
name: file.name,
|
|
uid: file.uid,
|
|
path: filePath
|
|
});
|
|
this.$message.success(`${file.name} 上传成功`);
|
|
resolve(response);
|
|
})
|
|
.catch(error => {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
|
|
// 文件改变
|
|
handleFileChange(file, fileList) {
|
|
if (!file.raw ||
|
|
file.raw.size / 1024 / 1024 >= 10 ||
|
|
!['image/jpeg', 'image/png', 'application/pdf'].includes(file.raw.type)) {
|
|
let errorMsg = '';
|
|
if (!file.raw) errorMsg = '获取文件失败,请重新选择文件';
|
|
else if (file.raw.size / 1024 / 1024 >= 10) errorMsg = '文件大小不能超过10MB';
|
|
else errorMsg = '只能上传JPG、PNG或PDF格式的文件';
|
|
this.$message.error(errorMsg);
|
|
this.fileList = fileList.filter(item => item.uid !== file.uid);
|
|
return;
|
|
}
|
|
this.fileList = fileList;
|
|
if (file.status === 'ready') {
|
|
file.status = 'uploading';
|
|
this.uploadSingleFile(file)
|
|
.then(() => file.status = 'success')
|
|
.catch(() => file.status = 'fail');
|
|
}
|
|
},
|
|
|
|
// 文件移除
|
|
handleRemove(file, fileList) {
|
|
this.fileList = fileList;
|
|
const showIndex = this.uploadedFiles.findIndex(f => f.name === file.name);
|
|
if (showIndex > -1) {
|
|
this.uploadedFiles.splice(showIndex, 1);
|
|
}
|
|
const resIndex = this.fileUploadResponses.findIndex(f => f.fileName === file.name);
|
|
if (resIndex > -1) {
|
|
this.fileUploadResponses.splice(resIndex, 1);
|
|
}
|
|
},
|
|
|
|
// 上一步
|
|
prevStep() {
|
|
if (this.activeStep > 0) {
|
|
this.activeStep--
|
|
}
|
|
},
|
|
|
|
// 下一步
|
|
nextStep() {
|
|
if (this.activeStep === 0) {
|
|
this.$refs.qualificationForm.validate(valid => valid && (this.activeStep++));
|
|
return;
|
|
}
|
|
if (this.activeStep === 1) {
|
|
if (!this.fileList.length) {
|
|
this.$message.warning('请上传资质文件');
|
|
return;
|
|
}
|
|
const anyUploading = this.fileList.some(file => file.status === 'uploading');
|
|
const anyFailed = this.fileList.some(file => file.status === 'fail');
|
|
const allSuccess = this.fileList.every(file => file.status === 'success');
|
|
if (anyUploading) {
|
|
this.$message.warning('文件正在上传中,请等待上传完成');
|
|
} else if (anyFailed) {
|
|
this.$message.warning('存在上传失败的文件,请重新上传或移除失败的文件');
|
|
} else if (!allSuccess) {
|
|
this.$message.warning('请确保所有文件都上传成功');
|
|
} else {
|
|
this.activeStep++;
|
|
}
|
|
}
|
|
},
|
|
|
|
// 提交审核
|
|
submitQualification() {
|
|
this.loading = true;
|
|
|
|
const requestData = {
|
|
realName: this.qualificationForm.realName,
|
|
idCard: this.qualificationForm.idCard,
|
|
qualificationType: this.qualificationForm.qualificationType,
|
|
certificateNo: this.qualificationForm.certificateNo,
|
|
scopeIds: this.qualificationForm.scopeIds || [],
|
|
certificateFiles: this.fileUploadResponses.map(item => item.fileUrl).join(','),
|
|
certificateFileIds: this.fileUploadResponses.map(item => item.fileId).join(',')
|
|
};
|
|
// console.log('提交的数据:', JSON.stringify(requestData, null, 2));
|
|
submitAuditQualification(requestData)
|
|
.then(response => {
|
|
this.$modal.msgSuccess('提交成功,请等待审核');
|
|
this.flag = false;
|
|
this.resetForm();
|
|
})
|
|
.catch(error => {
|
|
console.error('提交失败:', error);
|
|
console.error('错误详情:', error.response?.data);
|
|
if (error.response?.data?.message) {
|
|
this.$message.error('提交失败: ' + error.response.data.message);
|
|
} else {
|
|
this.$message.error('提交失败,请重试');
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
/* 轮播背景 */
|
|
.card-container {
|
|
display: flex;
|
|
gap: 20px;
|
|
padding: 20px;
|
|
}
|
|
|
|
.stat-card {
|
|
flex: 1;
|
|
min-width: 0;
|
|
padding: 30px 20px;
|
|
border: 1px solid #e5e6eb;
|
|
border-radius: 16px;
|
|
background: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
min-height: 180px;
|
|
transform-origin: center center;
|
|
|
|
&:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
|
|
}
|
|
}
|
|
|
|
.info-card.stat-card {
|
|
background-color: #bbdefb;
|
|
color: #0d47a1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-around;
|
|
padding: 20px;
|
|
}
|
|
|
|
.shake {
|
|
animation: cardShake 1s infinite linear;
|
|
background-color: #fffde6 !important;
|
|
&:hover {
|
|
animation-play-state: paused;
|
|
background-color: #edeacd !important;
|
|
}
|
|
}
|
|
|
|
.info-card .info-icon {
|
|
width: 60%;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.info-card .info-title {
|
|
font-size: 28px;
|
|
font-weight: bold;
|
|
color: #42B983;
|
|
margin-bottom: 0;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.card-icon {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-right: 20px;
|
|
}
|
|
|
|
.card-icon i {
|
|
font-size: 30px;
|
|
color: #fff;
|
|
}
|
|
|
|
.card-text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 16px;
|
|
color: #333;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.card-value {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.icon-total {
|
|
background: linear-gradient(135deg, #ff9a44 0%, #ff6b08 100%);
|
|
}
|
|
.icon-pending {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
}
|
|
.icon-handled {
|
|
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
|
}
|
|
|
|
/* 资质弹窗 */
|
|
|
|
/* 经营范围 */
|
|
.scope-choice {
|
|
color: #b6bbc6;
|
|
font-size: 12px;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.step-summary {
|
|
margin-bottom: 20px;
|
|
padding: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.summary-item {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
margin-bottom: 10px;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
.summary-label {
|
|
min-width: 80px;
|
|
color: #606266;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.summary-value {
|
|
color: #303133;
|
|
}
|
|
|
|
.scope-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
}
|
|
|
|
.scope-tag {
|
|
margin-right: 5px;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.uploaded-files {
|
|
margin-top: 15px;
|
|
padding: 10px;
|
|
background: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.file-list-title {
|
|
font-weight: bold;
|
|
margin-bottom: 8px;
|
|
color: #303133;
|
|
}
|
|
|
|
.file-item {
|
|
padding: 5px 0;
|
|
color: #606266;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
i {
|
|
margin-right: 5px;
|
|
color: #409EFF;
|
|
}
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 768px) {
|
|
.card-container {
|
|
flex-direction: column;
|
|
padding: 10px;
|
|
gap: 15px;
|
|
}
|
|
|
|
.stat-card {
|
|
min-height: 150px;
|
|
padding: 20px 15px;
|
|
}
|
|
|
|
.card-icon {
|
|
width: 50px;
|
|
height: 50px;
|
|
margin-right: 15px;
|
|
|
|
i {
|
|
font-size: 24px;
|
|
}
|
|
}
|
|
|
|
.info-card .info-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
}
|
|
|
|
.info-card .info-title {
|
|
font-size: 20px;
|
|
}
|
|
|
|
.card-value {
|
|
font-size: 20px;
|
|
}
|
|
}
|
|
|
|
/* 抖动动画 */
|
|
@keyframes cardShake {
|
|
0% { transform: translateX(0); }
|
|
10% { transform: translateX(-5px) translateY(-2px); }
|
|
20% { transform: translateX(5px) translateY(2px); }
|
|
30% { transform: translateX(-5px) translateY(-2px); }
|
|
40% { transform: translateX(5px) translateY(2px); }
|
|
50% { transform: translateX(-3px) translateY(-1px); }
|
|
60% { transform: translateX(3px) translateY(1px); }
|
|
70% { transform: translateX(-3px) translateY(-1px); }
|
|
80% { transform: translateX(3px) translateY(1px); }
|
|
90% { transform: translateX(-2px) translateY(0); }
|
|
100% { transform: translateX(0); }
|
|
}
|
|
|
|
.shake {
|
|
animation: cardShake 1s infinite linear;
|
|
&:hover {
|
|
animation-play-state: paused;
|
|
}
|
|
}
|
|
</style>
|