| | |
| | | <template> |
| | | <!-- <el-button type="primary" @click="changeActive">change</el-button> --> |
| | | <!-- <el-row> |
| | | <el-col |
| | | :span="active == 1 ? 16 : 4" |
| | | :class="active == 1 ? 'prod-active' : 'prod-inactive'" |
| | | >step1</el-col> |
| | | <el-col |
| | | :span="active == 2 ? 16 : 4" |
| | | :class="active == 2 ? 'prod-active' : 'prod-inactive'" |
| | | >step2</el-col> |
| | | <el-col |
| | | :span="active == 3 ? 16 : 4" |
| | | :class="active == 3 ? 'prod-active' : 'prod-inactive'" |
| | | >step3</el-col> |
| | | </el-row> --> |
| | | <el-row> |
| | | <div :class="active == 1 ? 'prod-active' : 'prod-inactive'"> |
| | | <slot name="step1"></slot> |
| | | <!-- 步骤1 数据产品生成选项 --> |
| | | <div :class="active == 1 ? 'prod-active' : 'prod-inactive'" ref="step1Ref"> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionContentEnd(1)" |
| | | > |
| | | <div v-show="showStep1Content"> |
| | | <template v-if="$slots.step1"> |
| | | <slot name="step1"></slot> |
| | | </template> |
| | | <template v-else> |
| | | <ProdQueryOpt :loading="loading" @submit="onSearch"> </ProdQueryOpt> |
| | | </template> |
| | | </div> |
| | | </transition> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionThumbnailEnd(1)" |
| | | > |
| | | <div |
| | | v-show="showStep1Thumbnail" |
| | | class="prod-thumbnail-wrapper" |
| | | :style="{ height: viewHeight }" |
| | | @click="changeActive(1)" |
| | | > |
| | | <div class="prod-thumbnail">①修改选项</div> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | <div :class="active == 2 ? 'prod-active' : 'prod-inactive'"> |
| | | <slot name="step2"></slot> |
| | | <!-- 步骤2 数据产品结果预览 --> |
| | | <div :class="active == 2 ? 'prod-active' : 'prod-inactive'" ref="step2Ref"> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionContentEnd(2)" |
| | | > |
| | | <div v-show="showStep2Content"> |
| | | <div ref="titleRef" class="prod-title"> |
| | | <el-text tag="b" size="large">数据产品预览</el-text> |
| | | </div> |
| | | <slot name="step2" :contentHeight="contentHeight"></slot> |
| | | </div> |
| | | </transition> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionThumbnailEnd(2)" |
| | | > |
| | | <div |
| | | v-show="showStep2Thumbnail" |
| | | class="prod-thumbnail-wrapper" |
| | | :style="{ height: viewHeight }" |
| | | @click="changeActive(2)" |
| | | > |
| | | <div |
| | | :class=" |
| | | 'prod-thumbnail prod-thumbnail_middle ' + |
| | | (active < 2 ? 'prod-thumbnail-disabled' : '') |
| | | " |
| | | > |
| | | ②数据产品预览 |
| | | </div> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | <div :class="active == 3 ? 'prod-active' : 'prod-inactive'"> |
| | | <slot name="step3"></slot> |
| | | <!-- 步骤3 数据产品表单下载 --> |
| | | <div :class="active == 3 ? 'prod-active' : 'prod-inactive'" ref="step3Ref"> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionContentEnd(3)" |
| | | > |
| | | <div v-show="showStep3Content"> |
| | | <template v-if="$slots.step3"> |
| | | <slot name="step3"></slot> |
| | | </template> |
| | | <template v-else> |
| | | <ProdDownload></ProdDownload> |
| | | </template> |
| | | </div> |
| | | </transition> |
| | | <transition |
| | | name="el-fade-in" |
| | | @after-leave="handleTransitionThumbnailEnd(3)" |
| | | > |
| | | <div |
| | | v-show="showStep3Thumbnail" |
| | | class="prod-thumbnail-wrapper" |
| | | :style="{ height: viewHeight }" |
| | | @click="changeActive(3)" |
| | | > |
| | | <div |
| | | :class=" |
| | | 'prod-thumbnail prod-thumbnail_end ' + |
| | | (active < 3 ? 'prod-thumbnail-disabled' : '') |
| | | " |
| | | > |
| | | ③数据产品下载 |
| | | </div> |
| | | </div> |
| | | </transition> |
| | | </div> |
| | | </el-row> |
| | | </template> |
| | | <script setup> |
| | | import { ref } from 'vue'; |
| | | import { computed, inject, ref, watch, onMounted } from 'vue'; |
| | | import { unCalc } from '@/utils/css-util'; |
| | | import ProdQueryOpt from '@/views/fysp/data-product/base-data-product/components/ProdQueryOpt.vue'; |
| | | import ProdDownload from '@/views/fysp/data-product/base-data-product/components/ProdDownload.vue'; |
| | | |
| | | const props = defineProps({ |
| | | active: { |
| | | type: Number, |
| | | default: 1 |
| | | }, |
| | | loading: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }); |
| | | |
| | | // function changeActive() { |
| | | // active.value++; |
| | | // active.value = active.value > 3 ? 1 : active.value; |
| | | // } |
| | | const emit = defineEmits(['update:active', 'onStep1']); |
| | | |
| | | const viewHeight = inject('viewHeight'); |
| | | |
| | | const btnDisabled = ref(false); |
| | | |
| | | const titleRef = ref(null); |
| | | const contentHeight = ref('50vh'); |
| | | |
| | | function calContentHeight() { |
| | | console.log(titleRef.value.offsetHeight); |
| | | contentHeight.value = `calc(${unCalc(viewHeight.value)} - ${ |
| | | titleRef.value?.offsetHeight || 0 |
| | | }px)`; |
| | | console.log(contentHeight.value); |
| | | |
| | | } |
| | | |
| | | // 步骤引用 |
| | | const step1Ref = ref(null); |
| | | const step2Ref = ref(null); |
| | | const step3Ref = ref(null); |
| | | |
| | | // 控制显示/隐藏的状态 |
| | | const showStep1Content = ref(props.active === 1); |
| | | const showStep1Thumbnail = ref(props.active != 1); |
| | | const showStep2Content = ref(props.active === 2); |
| | | const showStep2Thumbnail = ref(props.active != 2); |
| | | const showStep3Content = ref(props.active === 3); |
| | | const showStep3Thumbnail = ref(props.active != 3); |
| | | |
| | | // 记录动画是否正在进行中 |
| | | const isAnimating = ref({}); |
| | | |
| | | // 监听active变化 |
| | | watch( |
| | | () => props.active, |
| | | (newActive, oldActive) => { |
| | | // 标记动画开始 |
| | | isAnimating.value[oldActive] = true; |
| | | isAnimating.value[newActive] = true; |
| | | |
| | | // 先隐藏所有内容,等待动画结束后再显示正确的内容 |
| | | if (oldActive === 1) { |
| | | showStep1Content.value = false; |
| | | } else if (oldActive === 2) { |
| | | showStep2Content.value = false; |
| | | } else if (oldActive === 3) { |
| | | showStep3Content.value = false; |
| | | } |
| | | |
| | | if (newActive === 1) { |
| | | showStep1Thumbnail.value = false; |
| | | } else if (newActive === 2) { |
| | | showStep2Thumbnail.value = false; |
| | | } else if (newActive === 3) { |
| | | showStep3Thumbnail.value = false; |
| | | } |
| | | } |
| | | ); |
| | | |
| | | // 处理动画结束事件 |
| | | function handleTransitionThumbnailEnd(stepIndex) { |
| | | // 检查动画是否确实结束(避免重复触发) |
| | | if (isAnimating.value[stepIndex]) { |
| | | isAnimating.value[stepIndex] = false; |
| | | |
| | | // setTimeout(() => { |
| | | // 动画结束后,更新显示状态 |
| | | if (stepIndex === 1) { |
| | | showStep1Content.value = props.active === 1; |
| | | } else if (stepIndex === 2) { |
| | | showStep2Content.value = props.active === 2; |
| | | } else if (stepIndex === 3) { |
| | | showStep3Content.value = props.active === 3; |
| | | } |
| | | // }, 50); |
| | | } |
| | | } |
| | | |
| | | function handleTransitionContentEnd(stepIndex) { |
| | | // 检查动画是否确实结束(避免重复触发) |
| | | if (isAnimating.value[stepIndex]) { |
| | | isAnimating.value[stepIndex] = false; |
| | | |
| | | // setTimeout(() => { |
| | | // 动画结束后,更新显示状态 |
| | | if (stepIndex === 1) { |
| | | showStep1Thumbnail.value = props.active != 1; |
| | | } else if (stepIndex === 2) { |
| | | showStep2Thumbnail.value = props.active != 2; |
| | | } else if (stepIndex === 3) { |
| | | showStep3Thumbnail.value = props.active != 3; |
| | | } |
| | | // }, 50); |
| | | } |
| | | } |
| | | |
| | | function onSearch(opt) { |
| | | emit('onStep1', opt); |
| | | } |
| | | function changeActive(index) { |
| | | let isAnimate = false; |
| | | Object.values(isAnimating.value).forEach((item) => { |
| | | isAnimate = isAnimate || item; |
| | | }); |
| | | if (!isAnimate && !btnDisabled.value && props.active >= index) { |
| | | emit('update:active', index); |
| | | btnDisabled.value = true; |
| | | setTimeout(() => { |
| | | btnDisabled.value = false; |
| | | }, 500); |
| | | } |
| | | // emit('update:active', index); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | calContentHeight(); |
| | | }); |
| | | </script> |
| | | <style scoped> |
| | | .prod-active { |
| | | width: 66.667%; |
| | | /* width: 66.667%; */ |
| | | width: 90%; |
| | | transition: |
| | | width 0.5s ease, |
| | | box-shadow 0.3s ease; |
| | | /* background-color: #409eff; */ |
| | | margin: 5px 0; |
| | | border-radius: 4px; |
| | | box-shadow: |
| | | -3px 0 6px rgba(0, 0, 0, 0.1), |
| | | 3px 0 6px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .prod-inactive { |
| | | /* width: 16.667%; */ |
| | | width: 5%; |
| | | transition: width 0.5s ease; |
| | | background-color: #409eff; |
| | | color: white; |
| | | /* background-color: #e4e7ed; */ |
| | | margin: 5px 0; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .prod-inactive { |
| | | width: 16.667%; |
| | | transition: width 0.5s ease; |
| | | .prod-title { |
| | | padding: 10px; |
| | | } |
| | | |
| | | .prod-thumbnail-wrapper { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 0 2px; |
| | | } |
| | | |
| | | .prod-thumbnail { |
| | | height: 90%; |
| | | width: 100%; |
| | | background-color: #409eff; |
| | | color: white; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | writing-mode: vertical-rl; |
| | | text-orientation: upright; |
| | | letter-spacing: 8px; |
| | | font-size: 18px; |
| | | font-weight: 500; |
| | | border-top-left-radius: 4px; |
| | | border-bottom-left-radius: 4px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .prod-thumbnail_middle { |
| | | border-radius: 0px; |
| | | } |
| | | |
| | | .prod-thumbnail_end { |
| | | border-top-left-radius: 0px; |
| | | border-bottom-left-radius: 0px; |
| | | border-top-right-radius: 4px; |
| | | border-bottom-right-radius: 4px; |
| | | } |
| | | |
| | | .prod-thumbnail-disabled { |
| | | background-color: #e4e7ed; |
| | | color: #606266; |
| | | margin: 5px 0; |
| | | border-radius: 4px; |
| | | color: #c0c4cc; |
| | | cursor: not-allowed; |
| | | } |
| | | </style> |