<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)">
|
<!-- 渲染当前步骤对应的图标 -->
|
<template v-if="step.icon === 'qr'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
<rect x="7" y="7" width="3" height="3"></rect>
|
<rect x="14" y="7" width="3" height="3"></rect>
|
<rect x="7" y="14" width="3" height="3"></rect>
|
<rect x="14" y="14" width="3" height="3"></rect>
|
</svg>
|
</template>
|
<template v-else-if="step.icon === 'idcard'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<path d="M16 10h2"></path>
|
<path d="M16 14h2"></path>
|
<path d="M6.17 15a3 3 0 0 1 5.66 0"></path>
|
<circle cx="9" cy="11" r="2"></circle>
|
<rect x="2" y="5" width="20" height="14" rx="2"></rect>
|
</svg>
|
</template>
|
<template v-else-if="step.icon === 'face'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<path d="M3 7V5a2 2 0 0 1 2-2h2"></path>
|
<path d="M17 3h2a2 2 0 0 1 2 2v2"></path>
|
<path d="M21 17v2a2 2 0 0 1-2 2h-2"></path>
|
<path d="M7 21H5a2 2 0 0 1-2-2v-2"></path>
|
<path d="M8 14s1.5 2 4 2 4-2 4-2"></path>
|
<path d="M9 9h.01"></path>
|
<path d="M15 9h.01"></path>
|
</svg>
|
</template>
|
<template v-else-if="step.icon === 'user'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
|
<circle cx="9" cy="7" r="4"></circle>
|
<polyline points="16 11 18 13 22 9"></polyline>
|
</svg>
|
</template>
|
<template v-else-if="step.icon === 'form'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
<polyline points="14 2 14 8 20 8"></polyline>
|
<line x1="16" y1="13" x2="8" y2="13"></line>
|
<line x1="16" y1="17" x2="8" y2="17"></line>
|
<polyline points="10 9 9 9 8 9"></polyline>
|
</svg>
|
</template>
|
<template v-else-if="step.icon === 'print'">
|
<svg width="38" height="38" viewBox="0 0 24 24" fill="none" :stroke="getIconStroke(index + 1)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<polyline points="6 9 6 2 18 2 18 9"></polyline>
|
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
|
<rect x="6" y="14" width="12" height="8"></rect>
|
</svg>
|
</template>
|
</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';
|
|
const props = defineProps({
|
currentStep: {
|
type: Number,
|
default: 1
|
},
|
mode: {
|
type: String,
|
default: 'appointment' // 'appointment' 或 'online'
|
}
|
});
|
|
const stepsList = computed(() => {
|
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 getIconStroke = (stepNum) => {
|
if (stepNum < props.currentStep) return '#FFFFFF';
|
if (stepNum === props.currentStep) return '#2F6BFF';
|
return '#C7D7F6';
|
};
|
|
const getArrowSrc = (stepNum) => {
|
if (stepNum < props.currentStep) {
|
return '../../static/step-arrow-active.png';
|
}
|
return '../../static/step-arrow-inactive.png';
|
};
|
</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;
|
}
|
|
.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>
|