<template>
|
<view class="steps-card">
|
<view class="steps-row">
|
<template v-for="(step, index) in stepsList" :key="index">
|
<view class="step-item">
|
<view class="step-circle" :class="getCircleClass(index + 1)">
|
<image :src="getStepIconSrc(step.icon, index + 1)" class="step-icon" mode="aspectFit"></image>
|
</view>
|
<text class="step-text" :class="getTextClass(index + 1)">{{ step.text }}</text>
|
</view>
|
<view class="step-line" v-if="index < stepsList.length - 1">
|
<image :src="getArrowSrc(index + 1)" class="arrow-img" mode="aspectFit"></image>
|
</view>
|
</template>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { computed } from 'vue';
|
import qrActiveIcon from '../static/appointment-scan/qr-active.png';
|
import qrCompletedIcon from '../static/appointment-scan/qr-completed.png';
|
import idcardInactiveIcon from '../static/appointment-scan/idcard-inactive.png';
|
import idcardActiveIcon from '../static/appointment-scan/idcard-active.png';
|
import idcardCompletedIcon from '../static/appointment-scan/idcard-completed.png';
|
import faceInactiveIcon from '../static/appointment-scan/face-inactive.png';
|
import faceActiveIcon from '../static/appointment-scan/face-active.png';
|
import faceCompletedIcon from '../static/appointment-scan/face-completed.png';
|
import hostInactiveIcon from '../static/appointment-scan/host-inactive.png';
|
import hostActiveIcon from '../static/appointment-scan/host-active.png';
|
import hostCompletedIcon from '../static/appointment-scan/host-completed.png';
|
import formInactiveIcon from '../static/appointment-scan/form-inactive.png';
|
import formActiveIcon from '../static/appointment-scan/form-active.png';
|
import formCompletedIcon from '../static/appointment-scan/form-completed.png';
|
import printInactiveIcon from '../static/appointment-scan/print-inactive.png';
|
import printActiveIcon from '../static/appointment-scan/print-active.png';
|
import stepArrowActiveImage from '../static/appointment-scan/step-arrow-active.png';
|
import stepArrowInactiveImage from '../static/appointment-scan/step-arrow-inactive.png';
|
|
const props = defineProps({
|
currentStep: {
|
type: Number,
|
default: 1
|
},
|
mode: {
|
type: String,
|
default: 'appointment' // 'appointment' 或 'online'
|
},
|
steps: {
|
type: Array,
|
default: () => []
|
}
|
});
|
|
const stepsList = computed(() => {
|
if (Array.isArray(props.steps) && props.steps.length > 0) {
|
return props.steps;
|
}
|
|
if (props.mode === 'online') {
|
return [
|
{ text: '身份证验证', icon: 'idcard' },
|
{ text: '人脸验证', icon: 'face' },
|
{ text: '接待人验证', icon: 'user' },
|
{ text: '完善登记信息', icon: 'form' },
|
{ text: '打印凭条', icon: 'print' }
|
];
|
}
|
if (props.mode === 'signout') {
|
return [
|
{ text: '身份证验证', icon: 'idcard' },
|
{ text: '人脸验证', icon: 'face' },
|
{ text: '接待人验证', icon: 'user' }
|
];
|
}
|
return [
|
{ text: '预约码验证', icon: 'qr' },
|
{ text: '身份证验证', icon: 'idcard' },
|
{ text: '人脸验证', icon: 'face' },
|
{ text: '接待人验证', icon: 'user' },
|
{ text: '打印凭条', icon: 'print' }
|
];
|
});
|
|
const getCircleClass = (stepNum) => {
|
if (stepNum < props.currentStep) return 'completed-circle';
|
if (stepNum === props.currentStep) return 'active-circle';
|
return 'inactive-circle';
|
};
|
|
const getTextClass = (stepNum) => {
|
if (stepNum < props.currentStep) return 'completed-text';
|
if (stepNum === props.currentStep) return 'active-text';
|
return 'inactive-text';
|
};
|
|
const stepIconMap = {
|
qr: {
|
active: qrActiveIcon,
|
completed: qrCompletedIcon,
|
inactive: qrActiveIcon,
|
},
|
idcard: {
|
active: idcardActiveIcon,
|
completed: idcardCompletedIcon,
|
inactive: idcardInactiveIcon,
|
},
|
face: {
|
active: faceActiveIcon,
|
completed: faceCompletedIcon,
|
inactive: faceInactiveIcon,
|
},
|
user: {
|
active: hostActiveIcon,
|
completed: hostCompletedIcon,
|
inactive: hostInactiveIcon,
|
},
|
form: {
|
active: formActiveIcon,
|
completed: formCompletedIcon,
|
inactive: formInactiveIcon,
|
},
|
print: {
|
active: printActiveIcon,
|
completed: printInactiveIcon,
|
inactive: printInactiveIcon,
|
},
|
};
|
|
const getStepStatus = (stepNum) => {
|
if (stepNum < props.currentStep) return 'completed';
|
if (stepNum === props.currentStep) return 'active';
|
return 'inactive';
|
};
|
|
const getStepIconSrc = (iconKey, stepNum) => {
|
const iconGroup = stepIconMap[iconKey];
|
if (!iconGroup) {
|
return '';
|
}
|
return iconGroup[getStepStatus(stepNum)] || iconGroup.inactive;
|
};
|
|
const getArrowSrc = (stepNum) => {
|
if (stepNum < props.currentStep) {
|
return stepArrowActiveImage;
|
}
|
return stepArrowInactiveImage;
|
};
|
</script>
|
|
<style scoped>
|
/* 步骤卡片 */
|
.steps-card {
|
width: 1008px;
|
display: flex;
|
flex-direction: column;
|
margin-bottom: 24px;
|
z-index: 1;
|
}
|
|
.steps-row {
|
width: 100%;
|
height: 138px;
|
display: flex;
|
flex-direction: row;
|
align-items: flex-start;
|
justify-content: space-between;
|
}
|
|
.step-item {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 12px;
|
width: 120px;
|
}
|
|
.step-circle {
|
width: 82px;
|
height: 82px;
|
border-radius: 41px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.step-icon {
|
width: 38px;
|
height: 38px;
|
}
|
|
.completed-circle {
|
background: #78A8FF;
|
border: 1px solid #DDE9FF;
|
box-shadow: 0px 10px 18px rgba(14, 49, 138, 0.22);
|
}
|
|
.active-circle {
|
background: #FFFFFF;
|
border: 2px solid rgba(255, 255, 255, 0.4);
|
box-shadow: 0px 12px 24px rgba(15, 45, 125, 0.27);
|
}
|
|
.inactive-circle {
|
background: rgba(255, 255, 255, 0.07);
|
border: 1px solid rgba(255, 255, 255, 0.18);
|
box-shadow: 0px 8px 14px rgba(8, 32, 86, 0.07);
|
}
|
|
.step-text {
|
font-family: Inter, sans-serif;
|
font-size: 23px;
|
text-align: center;
|
white-space: nowrap;
|
}
|
|
.completed-text {
|
font-weight: 800;
|
color: rgba(255, 255, 255, 0.94);
|
}
|
|
.active-text {
|
font-weight: 900;
|
color: #FFFFFF;
|
}
|
|
.inactive-text {
|
font-weight: 600;
|
color: rgba(226, 235, 255, 0.66);
|
}
|
|
.step-line {
|
flex: 1;
|
height: 82px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.arrow-img {
|
width: 92px;
|
height: 82px;
|
}
|
</style>
|