From c1d2051abc8ca88cd07f0d7c56c0dbf8165d5c33 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期四, 18 九月 2025 17:02:22 +0800 Subject: [PATCH] 2025.9.18 数据产品(待完成) --- src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 311 insertions(+), 35 deletions(-) diff --git a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue b/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue index fb18256..8d533e7 100644 --- a/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue +++ b/src/views/fysp/data-product/base-data-product/components/BaseProdProcess.vue @@ -1,62 +1,338 @@ <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 + 'px' }" + @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> + <el-button type="primary" @click="$emit('onStep2')"> + 涓嬭浇鏁版嵁浜у搧 + </el-button> + </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 + 'px' }" + @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 + :loading="loading" + :queryOpt="queryOpt" + @submit="onDownload" + ></ProdDownload> + </template> + </div> + </transition> + <transition + name="el-fade-in" + @after-leave="handleTransitionThumbnailEnd(3)" + > + <div + v-show="showStep3Thumbnail" + class="prod-thumbnail-wrapper" + :style="{ height: viewHeight + 'px' }" + @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, onUnmounted } 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', 'onStep2', 'onStep3']); + +const contentMaxHeight = inject('contentMaxHeight'); +const viewHeight = inject('viewHeight', contentMaxHeight.value); + +const btnDisabled = ref(false); + +const titleRef = ref(null); +const contentHeight = ref('50vh'); + +function calContentHeight() { + // console.log(titleRef.value.offsetHeight); + contentHeight.value = viewHeight.value - (titleRef.value?.offsetHeight || 0); + // console.log(contentHeight.value); +} + +// 鏁版嵁浜у搧鐢熸垚閫夐」 +const queryOpt = ref({}); + +// 姝ラ寮曠敤 +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); + +// 璁板綍鍔ㄧ敾鏄惁姝e湪杩涜涓� +const isAnimating = ref({}); + +// 鐩戝惉active鍙樺寲 +watch( + () => props.active, + (newActive, oldActive) => { + // 鏍囪鍔ㄧ敾寮�濮� + isAnimating.value[oldActive] = true; + isAnimating.value[newActive] = true; + + // 鍏堥殣钘忔墍鏈夊唴瀹癸紝绛夊緟鍔ㄧ敾缁撴潫鍚庡啀鏄剧ず姝g‘鐨勫唴瀹� + 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) { + queryOpt.value = opt; + emit('onStep1', opt); +} +function onDownload(val) { + emit('onStep3', val); +} +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); +} + +let resizeObserver = null; + +onMounted(() => { + if (titleRef.value) { + resizeObserver = new ResizeObserver(() => { + calContentHeight(); + }); + resizeObserver.observe(titleRef.value); + } +}); +// 鍦ㄧ粍浠跺嵏杞芥椂娓呯悊 +onUnmounted(() => { + if (resizeObserver && titleRef.value) { + resizeObserver.unobserve(titleRef); + } +}); </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: 20px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.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: 600; + 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> -- Gitblit v1.9.3