| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- <template>
- <!-- 简化显示版 -->
- <view class="progress-steps simple">
- <!-- 动态渲染步骤 -->
- <template v-for="(step, index) in steps" >
- <!-- 步骤项 -->
- <view class="step-item" :class="{
- active: currentStep === step.stepNumber
- }">
- <!-- 圆圈部分 -->
- <view class="step-circle">
- <!-- 已完成的步骤显示完成图标 -->
- <image v-if="currentStep > step.stepNumber"
- class="icon"
- :src="step.doneIcon || '/static/image/icon_step_done.png'">
- </image>
- <!-- 当前和未完成的步骤显示数字 -->
- <text v-else>{{ step.stepNumber }}</text>
- </view>
- <!-- 步骤文本 -->
- <view class="step-text" :class="{
- active: currentStep === step.stepNumber
-
- }">
- {{ step.title }}
- </view>
- </view>
-
- <!-- 步骤之间的连线(最后一个步骤后不显示) -->
- <view v-if="index < steps.length - 1"
- class="step-line"
- :class="{ active: currentStep > step.stepNumber }">
- </view>
- </template>
- </view>
- </template>
- <script>
- export default {
- name: 'ProgressSteps',
- props: {
- // 当前步骤
- step: {
- type: Number,
- default: 1,
- validator: (value) => value > 0
- },
- // 步骤配置数据(支持数组或JSON字符串)
- stepsData: {
- type: [Array, String],
- default: () => [
- { id: 1, stepNumber: 1, title: '填写任务' },
- { id: 2, stepNumber: 2, title: '选择客户' },
- { id: 3, stepNumber: 3, title: '积分设置' }
- ]
- },
- // 完成图标(可覆盖单个步骤的配置)
- doneIcon: {
- type: String,
- default: '/static/image/icon_step_done.png'
- }
- },
- data() {
- return {
- currentStep: this.step,
- steps: []
- }
- },
- created() {
- this.initSteps()
- },
- watch: {
- current(newVal) {
- this.currentStep = newVal
- },
- stepsData: {
- handler(newVal) {
- this.initSteps()
- },
- deep: true,
- immediate: true
- }
- },
- methods: {
- // 初始化步骤数据
- initSteps() {
- let steps = []
-
- try {
- // 如果传入的是字符串,尝试解析为JSON
- if (typeof this.stepsData === 'string') {
- steps = JSON.parse(this.stepsData)
- } else if (Array.isArray(this.stepsData)) {
- steps = this.stepsData
- }
-
- // 验证和标准化数据
- steps = steps.map((item, index) => {
- return {
- id: item.id || index + 1,
- stepNumber: item.stepNumber || index + 1,
- title: item.title || `步骤${index + 1}`,
- doneIcon: item.doneIcon || this.doneIcon,
- // 可以添加更多自定义字段
- ...item
- }
- })
-
- // 按步骤号排序
- steps.sort((a, b) => a.stepNumber - b.stepNumber)
-
- this.steps = steps
- } catch (error) {
- console.error('解析步骤数据失败:', error)
- // 使用默认步骤
- this.steps = [
- { id: 1, stepNumber: 1, title: '填写任务' },
- { id: 2, stepNumber: 2, title: '选择客户' },
- { id: 3, stepNumber: 3, title: '积分设置' }
- ]
- }
- },
-
- // 跳转到指定步骤
- goToStep(stepNumber) {
- const targetStep = this.steps.find(step => step.stepNumber === stepNumber)
- if (targetStep && stepNumber >= 1 && stepNumber <= this.steps.length) {
- const oldStep = this.currentStep
- this.currentStep = stepNumber
-
- // 触发事件
- this.$emit('step-change', {
- stepNumber: this.currentStep,
- stepData: targetStep,
- oldStep: oldStep
- })
-
- // 点击步骤事件
- this.$emit('step-click', {
- stepNumber: stepNumber,
- stepData: targetStep
- })
- }
- },
-
- // 下一步
- goNext() {
- if (this.currentStep < this.steps.length) {
- this.goToStep(this.currentStep + 1)
- this.$emit('next', this.currentStep)
- }
- },
-
- // 上一步
- goPrev() {
- if (this.currentStep > 1) {
- this.goToStep(this.currentStep - 1)
- this.$emit('prev', this.currentStep)
- }
- },
-
- // 提交
- handleSubmit() {
- this.$emit('submit')
- },
-
- // 获取当前步骤数据
- getCurrentStep() {
- return this.steps.find(step => step.stepNumber === this.currentStep) || null
- },
-
- // 获取所有步骤
- getAllSteps() {
- return [...this.steps]
- },
-
- // 更新步骤数据(可用于动态修改标题等)
- updateStep(stepNumber, newData) {
- const index = this.steps.findIndex(step => step.stepNumber === stepNumber)
- if (index !== -1) {
- this.steps[index] = { ...this.steps[index], ...newData }
- this.$forceUpdate() // 强制更新视图
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- /* 简化版样式 - 确保圆圈和连线无缝连接 */
- .progress-steps.simple {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 16rpx 38rpx;
- position: relative;
- margin: 30rpx 48rpx;
- .step-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- position: relative;
- z-index: 2;
- cursor: pointer;
- transition: all 0.3s ease;
- &:active {
- opacity: 0.7;
- }
- &.active {
- .step-circle {
- background: #388BFF;
- color: #FFFFFF;
- }
- }
- &:not(.active) {
- .step-circle {
- background: #FFFFFF;
- color: #C0C4CC;
- border: 2rpx solid #E4E7ED;
- }
- }
- }
- .step-circle {
- width: 48rpx;
- height: 48rpx;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 28rpx;
- font-weight: 500;
- margin-bottom: 8rpx;
- position: relative;
- z-index: 2;
- box-sizing: border-box;
- transition: all 0.3s ease;
- .icon {
- width: 100%;
- height: 100%;
- }
- }
- .step-text {
- font-size: 28rpx;
- color: #999999;
- white-space: nowrap;
- transition: all 0.3s ease;
- &.active {
- font-weight: 500;
- font-size: 28rpx;
- color: #333333;
- }
-
-
- }
- .step-line {
- flex: 1;
- height: 4rpx;
- background: #E4E7ED;
- margin: 0 -30rpx;
- /* 负边距让线延伸到圆圈边缘 */
- position: relative;
- top: -30rpx;
- max-width: 294rpx;
- /* 调整到圆圈中心位置 */
- z-index: 1;
- min-width: 60rpx;
- transition: all 0.3s ease;
- &.active {
- background: #388BFF;
- opacity: 0.2;
- }
- }
- }
- /* 响应式调整 */
- @media (max-width: 750px) {
- .progress-steps.simple {
- padding: 20rpx 15rpx;
- margin: 20rpx 30rpx;
- .step-circle {
- width: 50rpx;
- height: 50rpx;
- font-size: 24rpx;
- }
- .step-text {
- font-size: 24rpx;
-
- &.active {
- font-size: 24rpx;
- }
- }
- .step-line {
- margin: 0 -25rpx;
- top: -25rpx;
- min-width: 40rpx;
- }
- }
- }
- </style>
|