Commit ea5bbe9a by Hantao

优化写法

parent 434bda5c
<template>
<view class="bottom-bar">
<image src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/5d0f462d13ec4cbcb6eee7080c637897Group%20348447439.webp"
<image :src="IMAGES.testing"
style="width:0;height:0;opacity:0;position:absolute;pointer-events:none;"></image>
<image class="bar-bg" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a681444d883d4fe29851d702703302b0Rectangle%203597.webp" mode="scaleToFill"></image>
<image class="bar-bg" :src="IMAGES.background" mode="scaleToFill"></image>
<text class="test-status">当前测试: <text class="highlight">{{ statusText }}</text></text>
<view class="start-btn-wrapper" @click="handleStartTest" :class="{ 'disabled': isDisabled }">
<image class="start-btn-img" :src="btnImage" mode="scaleToFill"></image>
......@@ -12,7 +12,14 @@
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { computed } from 'vue';
const IMAGES = {
background: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a681444d883d4fe29851d702703302b0Rectangle%203597.webp',
start: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/51e1fc432e2b406d9d00f1028213221bGroup%20348447439.webp',
testing: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/5d0f462d13ec4cbcb6eee7080c637897Group%20348447439.webp',
finish: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/f8df9974d93a478f8c6b760fd32e15aaGroup%20348447439.webp'
};
const props = defineProps({
isTesting: {
......@@ -35,47 +42,34 @@ const props = defineProps({
const emit = defineEmits(['startTest', 'restartTest', 'showFinalCard', 'showCompletionPopup']);
const isDisabled = ref(false);
const statusText = computed(() => {
if (props.isSecondTest) return '2/2';
return props.isTesting ? '1/2' : '0/2';
});
const isDisabled = computed(() => {
return props.isTesting && !props.isProgressFinished && !props.isResultShown;
});
const btnImage = computed(() => {
if (props.isSecondTest) {
if (props.isResultShown) {
return 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/f8df9974d93a478f8c6b760fd32e15aaGroup%20348447439.webp';
return IMAGES.finish;
}
if (props.isTesting) {
return 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/5d0f462d13ec4cbcb6eee7080c637897Group%20348447439.webp';
return IMAGES.testing;
}
return 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/51e1fc432e2b406d9d00f1028213221bGroup%20348447439.webp';
}
if (props.isTesting && props.isProgressFinished && !props.isResultShown) {
return 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/5d0f462d13ec4cbcb6eee7080c637897Group%20348447439.webp';
}
return props.isTesting
? 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/5d0f462d13ec4cbcb6eee7080c637897Group%20348447439.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/51e1fc432e2b406d9d00f1028213221bGroup%20348447439.webp';
});
watch(() => props.isTesting, (newVal) => {
if (newVal) {
isDisabled.value = true;
return IMAGES.start;
}
});
watch(() => props.isProgressFinished, (newVal) => {
if (newVal) {
isDisabled.value = false;
}
});
watch(() => props.isResultShown, (newVal) => {
if (newVal) {
isDisabled.value = false;
if (props.isTesting) {
if (props.isProgressFinished && !props.isResultShown) {
return IMAGES.testing;
}
return IMAGES.testing;
}
return IMAGES.start;
});
const handleStartTest = () => {
......
<template>
<view class="tabs-instructions-container">
<view class="tabs-row">
<template v-if="!isSecondTest">
<view class="tab-container">
<image class="tab-btn-active tds-active-tab" :src="activeTabImage" mode="scaleToFill"></image>
</view>
<view class="tab-container">
<image class="tab-btn" :src="inactiveTabImage" mode="scaleToFill"></image>
</view>
</template>
<template v-else>
<view class="tab-container">
<image class="tab-btn ph-inactive-tab" :src="inactiveTabImage" mode="scaleToFill"></image>
</view>
<view class="tab-container">
<image class="tab-btn-active ph-active-tab" :src="activeTabImage" mode="scaleToFill"></image>
</view>
</template>
<view class="tabs-instructions-container">
<view class="tabs-row">
<template v-if="!isSecondTest">
<view class="tab-container">
<image
class="tab-btn-active tds-active-tab"
:src="activeTabImage"
mode="scaleToFill"
/>
</view>
<view class="tab-container">
<image class="tab-btn" :src="inactiveTabImage" mode="scaleToFill" />
</view>
</template>
<template v-else>
<view class="tab-container">
<image
class="tab-btn ph-inactive-tab"
:src="inactiveTabImage"
mode="scaleToFill"
/>
</view>
<view class="tab-container">
<image
class="tab-btn-active ph-active-tab"
:src="activeTabImage"
mode="scaleToFill"
/>
</view>
</template>
</view>
<view class="instructions-card" v-if="!isTesting">
<image class="card-bg" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/87e28ba2f4764f33a36b0d1cfd47d74aRectangle%203589.webp" mode="scaleToFill"></image>
<view class="card-content">
<view class="card-title">操作说明</view>
<view class="card-body">
<text class="instruction-text">{{ instructionText }}</text>
<image class="ppm-icon"
:class="{ 'ph-icon': isSecondTest }"
:src="instructionIcon"
:mode="iconMode"
v-if="instructionIcon"
@error="handleImageError"></image>
<image class="ph-label-img"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/536133e8a44f4482b2848016385d79cbPH.webp"
mode="aspectFit"
v-if="isSecondTest"></image>
</view>
</view>
<view class="instructions-card" v-if="!isTesting">
<image class="card-bg" :src="IMAGES.cardBg" mode="scaleToFill" />
<view class="card-content">
<view class="card-title">操作说明</view>
<view class="card-body">
<text class="instruction-text">{{ instructionText }}</text>
<image
class="ppm-icon"
:class="{ 'ph-icon': isSecondTest }"
:src="instructionIcon"
:mode="iconMode"
v-if="instructionIcon"
@error="handleImageError"
/>
<image
class="ph-label-img"
:src="IMAGES.phLabel"
mode="aspectFit"
v-if="isSecondTest"
/>
</view>
</view>
</view>
<view class="progress-panel" v-else>
<view class="progress-bar-container" v-if="!showFinalCard">
<image class="progress-bar-bg result-img"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/45cebdfeb99a44049d18ab3b04024ac2Group%20348447442.webp"
mode="scaleToFill"
v-if="showResults"></image>
<image class="progress-bar-bg initial-img"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/7b21b166605d4c7c9bb4377280202da7Group%20348447442.webp"
mode="scaleToFill"
v-if="!showResults"></image>
<view class="progress-panel" v-else>
<view class="progress-bar-container" v-if="!showFinalCard">
<image
class="progress-bar-bg result-img"
:src="IMAGES.progressResult"
mode="scaleToFill"
v-if="showResults"
/>
<image
class="progress-bar-bg initial-img"
:src="IMAGES.progressInitial"
mode="scaleToFill"
v-if="!showResults"
/>
</view>
<view class="result-card" v-if="showFinalCard">
<image class="card-bg" :src="IMAGES.cardBg" mode="scaleToFill" />
<view class="card-content">
<view class="card-title">检测结果</view>
<view class="card-body result-body" v-if="!isSecondTest">
<view class="comparison-section">
<text class="section-title">TDS值对比</text>
<view class="comparison-row">
<view class="value-badge before">
<text>前: 450ppm</text>
</view>
<text class="arrow"></text>
<view class="value-badge after">
<text>后: 15ppm</text>
</view>
</view>
<view class="rate-row">
<text class="rate-label">净化率:</text>
<text class="rate-value">96.7%</text>
<view class="rate-bar">
<view class="rate-fill" :style="{ width: '93.7%' }"></view>
</view>
</view>
</view>
<view class="result-card" v-if="showFinalCard">
<image class="card-bg" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/87e28ba2f4764f33a36b0d1cfd47d74aRectangle%203589.webp" mode="scaleToFill"></image>
<view class="card-content">
<view class="card-title">检测结果</view>
<view class="card-body result-body" v-if="!isSecondTest">
<view class="comparison-section">
<text class="section-title">TDS值对比</text>
<view class="comparison-row">
<view class="value-badge before">
<text>前: 450ppm</text>
</view>
<text class="arrow"></text>
<view class="value-badge after">
<text>后: 15ppm</text>
</view>
</view>
<view class="rate-row">
<text class="rate-label">净化率:</text>
<text class="rate-value">96.7%</text>
<view class="rate-bar">
<view class="rate-fill" :style="{ width: '93.7%' }"></view>
</view>
</view>
</view>
<view class="chart-section">
<view class="chart-container">
<view class="bar-group red">
<text class="bar-label">450ppm</text>
<view class="bar"></view>
</view>
<view class="bar-group green">
<text class="bar-label">15ppm</text>
<view class="bar"></view>
</view>
</view>
<image class="badge-icon" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/44463cae0882429ebd84049240ff5330Group%20348447451.webp" mode="aspectFit"></image>
</view>
</view>
<view class="card-body ph-result-body" v-else>
<view class="ph-comparison-row">
<view class="ph-value-group">
<text class="label">前: </text>
<text class="value highlight-green">8.5</text>
<view class="ph-tag alkaline">
<text>偏碱性</text>
</view>
</view>
<image class="ph-warning-icon" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/0c6358f526fd4a72a098e5e46c9a8759Frame%2017.webp" mode="aspectFit"></image>
<text class="ph-arrow"></text>
<view class="ph-value-group">
<text class="label">后: </text>
<text class="value highlight-lime">7.0</text>
<view class="ph-tag neutral">
<text>中性</text>
</view>
</view>
<image class="ph-success-icon" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/dd15bc1646cb4fcb86670b2b1ae04809Group%20348447459.webp" mode="aspectFit"></image>
</view>
<view class="ph-chart-container">
<image class="ph-chart-img" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/3df0383e2218465c83af9aeeae10e1baGroup%20348447462.webp" mode="widthFix"></image>
</view>
<view class="ph-footer-row">
<text class="ph-footer-label">酸碱度:<text class="highlight">已优化</text></text>
<view class="ph-badge">适合饮用</view>
</view>
</view>
<view class="chart-section">
<view class="chart-container">
<view class="bar-group red">
<text class="bar-label">450ppm</text>
<view class="bar"></view>
</view>
<view class="bar-group green">
<text class="bar-label">15ppm</text>
<view class="bar"></view>
</view>
</view>
<image class="badge-icon" :src="IMAGES.badgeIcon" mode="aspectFit" />
</view>
<view class="result-boxes" v-if="!showFinalCard">
<view class="result-box">
<text class="box-title">污染水</text>
<text class="box-value" :style="{ color: showResults ? '#FF3300' : '#25334D' }">{{ resultLabel }}:{{ pollutedValue }}</text>
<image class="status-icon"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/0c6358f526fd4a72a098e5e46c9a8759Frame%2017.webp"
alt="警告"
v-if="showResults"></image>
</view>
<view class="card-body ph-result-body" v-else>
<view class="ph-comparison-row">
<view class="ph-value-group">
<text class="label">前: </text>
<text class="value highlight-green">8.5</text>
<view class="ph-tag alkaline">
<text>偏碱性</text>
</view>
<view class="result-box">
<text class="box-title">净化水</text>
<text class="box-value" :style="{ color: showResults ? '#00CC99' : '#25334D' }">{{ resultLabel }}:{{ purifiedValue }}</text>
<image class="status-icon"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/e7e6a286a568480fada2cafab781cc3cFrame.webp"
alt="通过"
v-if="showResults"></image>
</view>
<image class="ph-warning-icon" :src="IMAGES.warningIcon" mode="aspectFit" />
<text class="ph-arrow"></text>
<view class="ph-value-group">
<text class="label">后: </text>
<text class="value highlight-lime">7.0</text>
<view class="ph-tag neutral">
<text>中性</text>
</view>
</view>
<image class="ph-success-icon" :src="IMAGES.successIcon" mode="aspectFit" />
</view>
</view>
<view class="tips-card">
<view class="tips-header">
<image class="bulb-icon" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d2a7b1b81bff44c2b9099a8d48d9d6f1Frame%282%29.webp" mode="widthFix"></image>
<text class="tips-title">你知道吗?</text>
<view class="ph-chart-container">
<image class="ph-chart-img" :src="IMAGES.phChart" mode="widthFix" />
</view>
<view class="tips-body">
<text>{{ tipsText }}</text>
<view class="ph-footer-row">
<text class="ph-footer-label"
>酸碱度:<text class="highlight">已优化</text></text
>
<view class="ph-badge">适合饮用</view>
</view>
</view>
</view>
</view>
<view class="result-boxes" v-if="!showFinalCard">
<view class="result-box">
<text class="box-title">污染水</text>
<text
class="box-value"
:style="{ color: showResults ? '#FF3300' : '#25334D' }"
>{{ resultLabel }}:{{ pollutedValue }}</text
>
<image
class="status-icon"
:src="IMAGES.warningIcon"
alt="警告"
v-if="showResults"
/>
</view>
<view class="result-box">
<text class="box-title">净化水</text>
<text
class="box-value"
:style="{ color: showResults ? '#00CC99' : '#25334D' }"
>{{ resultLabel }}:{{ purifiedValue }}</text
>
<image
class="status-icon"
:src="IMAGES.successIconFrame"
alt="通过"
v-if="showResults"
/>
</view>
</view>
</view>
<view class="tips-card">
<view class="tips-header">
<image class="bulb-icon" :src="IMAGES.bulbIcon" mode="widthFix" />
<text class="tips-title">你知道吗?</text>
</view>
<view class="tips-body">
<text>{{ tipsText }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
const props = defineProps({
isTesting: {
type: Boolean,
default: false
},
isSecondTest: {
type: Boolean,
default: false
},
triggerShowFinalCard: {
type: Boolean,
default: false
}
isTesting: {
type: Boolean,
default: false,
},
isSecondTest: {
type: Boolean,
default: false,
},
triggerShowFinalCard: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['resultShown', 'progressFinished']);
......@@ -184,695 +219,726 @@ const emit = defineEmits(['resultShown', 'progressFinished']);
const showResults = ref(false);
const showFinalCard = ref(false);
const IMAGES = {
// 两个选项图片
tabActiveTds: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/b91478ab6f2d4c2186a948ae9b614f45Group%20348447426.webp',
tabActivePh: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/b9c5667e95ea48a1b4c10f2d9ee84db6Group%20348447426.webp',
tabInactiveTds: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a4bd654c5fd4401bb4d09ce1a8e08aa3Group%20348447427.webp',
tabInactivePh: '/static/1.webp',
// 介绍内部图片
instructionTds: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/1a62746fad3743d19f01e8b612ed8d42Group%20348447435.webp',
instructionPh: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/32ac38db03994072aca53ae518b996eeGroup%20348447450.webp',
phLabel: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/536133e8a44f4482b2848016385d79cbPH.webp',
cardBg: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/87e28ba2f4764f33a36b0d1cfd47d74aRectangle%203589.webp',
// 进度条
progressResult: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/45cebdfeb99a44049d18ab3b04024ac2Group%20348447442.webp',
progressInitial: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/7b21b166605d4c7c9bb4377280202da7Group%20348447442.webp',
// 结果内部图片
warningIcon: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/0c6358f526fd4a72a098e5e46c9a8759Frame%2017.webp',
successIcon: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/dd15bc1646cb4fcb86670b2b1ae04809Group%20348447459.webp',
successIconFrame: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/e7e6a286a568480fada2cafab781cc3cFrame.webp',
badgeIcon: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/44463cae0882429ebd84049240ff5330Group%20348447451.webp',
phChart: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/3df0383e2218465c83af9aeeae10e1baGroup%20348447462.webp',
// 灯泡
bulbIcon: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d2a7b1b81bff44c2b9099a8d48d9d6f1Frame%282%29.webp',
};
const activeTabImage = computed(() => {
return props.isSecondTest
? '/static/1.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/b91478ab6f2d4c2186a948ae9b614f45Group%20348447426.webp';
return props.isSecondTest ? IMAGES.tabInactivePh : IMAGES.tabActiveTds;
});
const inactiveTabImage = computed(() => {
return props.isSecondTest
? 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/b9c5667e95ea48a1b4c10f2d9ee84db6Group%20348447426.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a4bd654c5fd4401bb4d09ce1a8e08aa3Group%20348447427.webp';
return props.isSecondTest ? IMAGES.tabActivePh : IMAGES.tabInactiveTds;
});
const instructionText = computed(() => {
return props.isSecondTest
? "点击‘开始检测’测试水的酸碱度"
: '点击"开始检测"按钮测试TDS值';
return props.isSecondTest
? "点击‘开始检测’测试水的酸碱度"
: '点击"开始检测"按钮测试TDS值';
});
const instructionIcon = computed(() => {
return props.isSecondTest
? 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/32ac38db03994072aca53ae518b996eeGroup%20348447450.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/1a62746fad3743d19f01e8b612ed8d42Group%20348447435.webp';
return props.isSecondTest ? IMAGES.instructionPh : IMAGES.instructionTds;
});
const iconMode = computed(() => {
return props.isSecondTest ? 'aspectFit' : 'heightFix';
return props.isSecondTest ? 'aspectFit' : 'heightFix';
});
const handleImageError = (e) => {
console.error('Image load failed:', e.detail.errMsg);
};
const tipsText = computed(() => {
if (props.isSecondTest) {
if (props.isTesting) {
return 'pH试纸通过颜色变化判断酸碱性';
}
return '理想饮用水pH值应在6.5-8.5之间';
if (props.isSecondTest) {
if (showFinalCard.value) {
return '中性水(pH 7.0)对人体最温和,是理想的饮用水';
}
if (!props.isTesting) {
return 'TDS代表总溶解固体,数值越低水质越纯净';
if (props.isTesting) {
return 'pH试纸通过颜色变化判断酸碱性';
}
return showFinalCard.value
? '优质饮用水TDS值应低于50ppm'
: '安吉尔RO反渗透技术可将TDS降至15以下';
return '理想饮用水pH值应在6.5-8.5之间';
}
if (!props.isTesting) {
return 'TDS代表总溶解固体,数值越低水质越纯净';
}
return showFinalCard.value
? '优质饮用水TDS值应低于50ppm'
: '安吉尔RO反渗透技术可将TDS降至15以下';
});
const resultLabel = computed(() => {
return props.isSecondTest ? 'PH值' : 'TDS值';
return props.isSecondTest ? 'PH值' : 'TDS值';
});
const pollutedValue = computed(() => {
if (!showResults.value) return '???';
return props.isSecondTest ? '8.5' : '450';
if (!showResults.value) return '???';
return props.isSecondTest ? '8.5' : '450';
});
const purifiedValue = computed(() => {
if (!showResults.value) return '???';
return props.isSecondTest ? '7.0' : '15';
if (!showResults.value) return '???';
return props.isSecondTest ? '7.0' : '15';
});
watch(() => props.isTesting, (newVal) => {
const handleImageError = (e) => {
console.error('Image load failed:', e.detail.errMsg);
};
watch(
() => props.isTesting,
(newVal) => {
if (newVal) {
showResults.value = false;
showFinalCard.value = false;
setTimeout(() => {
showResults.value = true;
emit('progressFinished');
}, 1000);
showResults.value = false;
showFinalCard.value = false;
setTimeout(() => {
showResults.value = true;
emit('progressFinished');
}, 1000);
} else {
showResults.value = false;
showFinalCard.value = false;
showResults.value = false;
showFinalCard.value = false;
}
});
}
);
watch(() => props.triggerShowFinalCard, (newVal) => {
watch(
() => props.triggerShowFinalCard,
(newVal) => {
if (newVal) {
showFinalCard.value = true;
emit('resultShown');
showFinalCard.value = true;
emit('resultShown');
}
});
}
);
</script>
<style scoped lang="scss">
.tabs-instructions-container {
width: 100%;
max-width: 100%;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.tabs-row {
display: flex;
justify-content: center;
gap: 60rpx;
margin-bottom: 0.5vh;
.tab-container {
position: relative;
display: flex;
justify-content: center;
gap: 60rpx;
margin-bottom: 0.5vh;
align-items: center;
}
.tab-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
.tab-btn-active {
width: 280rpx;
height: 84rpx;
// Specific style for TDS test active image (...426.webp)
&.tds-active-tab {
width: 280rpx;
height: 124rpx;
}
.tab-btn-active {
width: 280rpx;
height: 84rpx;
// Specific style for PH test active image (...426.webp)
&.ph-active-tab {
width: 274rpx;
height: 128rpx;
margin-top: 10rpx;
}
}
&.tds-active-tab {
width: 280rpx;
height: 124rpx;
}
.tab-btn {
width: 240rpx;
height: 84rpx;
&.ph-active-tab {
width: 274rpx;
height: 128rpx;
margin-top: 10rpx ;
}
// Specific style for PH test inactive image (/static/1.webp)
&.ph-inactive-tab {
width: 242rpx;
height: 94rpx;
margin-left: 20rpx;
}
}
}
.instructions-card {
position: relative;
width: 120%;
max-width: 710rpx;
height: 224rpx;
margin: 1vh 0;
border-radius: 24rpx;
border: 4rpx solid #457AAB;
background: #BEDCF3;
box-sizing: border-box;
flex-shrink: 0;
.card-bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 98%;
height: 94%;
z-index: 0;
display: block;
}
.card-content {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
.card-title {
text-align: center;
font-size: 34rpx;
font-weight: 600;
color: #25334D;
}
.tab-btn {
width: 240rpx;
.card-body {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 0 20rpx;
.instruction-text {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
}
.ppm-icon {
height: 84rpx;
margin-left: 10rpx;
}
&.ph-inactive-tab {
width: 242rpx;
height: 94rpx;
margin-left: 20rpx;
}
.ph-icon {
width: 112rpx;
height: 160rpx;
margin-top: 0;
position: absolute;
right: 12rpx;
top: 50%;
transform: translateY(-50%);
}
.ph-label-img {
position: absolute;
right: 96rpx;
top: 28%;
transform: translateY(-50%);
width: 50rpx;
height: 28rpx;
}
}
}
}
.instructions-card {
.progress-panel {
width: 120%;
max-width: 710rpx;
margin: 1vh 0 0;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
box-sizing: border-box;
.progress-bar-container {
width: 100%;
height: 64rpx;
margin-bottom: 24rpx;
position: relative;
.progress-bar-bg {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.result-img {
z-index: 1;
}
.initial-img {
z-index: 2;
}
}
.result-card {
position: relative;
width: 120%;
max-width: 710rpx;
height: 224rpx;
margin: 1vh 0;
width: 100%;
height: 226rpx;
margin-bottom: 24rpx;
border-radius: 24rpx;
border: 4rpx solid #457AAB;
background: #BEDCF3;
box-sizing: border-box;
flex-shrink: 0;
.card-bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 98%;
height: 94%;
z-index: 0;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 98%;
height: 94%;
z-index: 0;
display: block;
}
.card-content {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
position: relative;
z-index: 1;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
.card-title {
text-align: center;
font-size: 34rpx;
font-weight: 600;
color: #25334D;
}
.card-body {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
.card-title {
text-align: center;
font-size: 34rpx;
font-weight: 600;
color: #25334D;
align-items: center;
padding: 0 20rpx;
.instruction-text {
font-size: 30rpx;
color: #25334D;
}
.card-body {
flex: 1;
&.result-body {
justify-content: flex-start;
align-items: flex-start;
padding: 10rpx 40rpx;
.comparison-section {
display: flex;
justify-content: center;
align-items: center;
padding: 0 20rpx;
.instruction-text {
flex-direction: column;
gap: 12rpx;
.section-title {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
}
.comparison-row {
display: flex;
align-items: center;
gap: 16rpx;
.value-badge {
padding: 6rpx 14rpx;
border-radius: 16rpx;
font-size: 24rpx;
color: #FFFFFF;
font-weight: 600;
&.before {
background: #D93A12;
border: 3rpx solid #9D341A;
}
&.after {
background: #0FA983;
border: 3rpx solid #1F8F73;
}
}
.arrow {
color: #457AAB;
font-weight: bold;
font-size: 28rpx;
}
}
.rate-row {
display: flex;
align-items: center;
margin-top: 4rpx;
.rate-label {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
}
.ppm-icon {
height: 84rpx;
}
.rate-value {
font-size: 32rpx;
color: #00CC99;
font-weight: bold;
margin-left: 10rpx;
}
}
.ph-icon {
width: 112rpx;
height: 160rpx;
margin-top: 0;
.rate-bar {
width: 192rpx;
height: 28rpx;
background: #8FB2CE;
border-radius: 22rpx;
border: 1px solid rgba(69, 122, 171, 0.8);
box-shadow: 0 3rpx 4rpx 0 rgba(90, 108, 122, 0.4) inset;
margin-left: 20rpx;
overflow: hidden;
position: relative;
.rate-fill {
height: 100%;
background: #00CC99;
border-radius: 22rpx;
box-shadow: 0 0 4rpx 0 rgba(255, 255, 255, 0.7) inset;
}
}
}
}
.chart-section {
width: 186rpx;
height: 138rpx;
background: #BEDCF3;
border: 2rpx solid rgba(69, 122, 171, 0.5);
border-radius: 12rpx;
position: absolute;
right: 20rpx;
top: 60%;
transform: translateY(-50%);
box-sizing: border-box;
z-index: 10;
.chart-container {
width: 100%;
height: 100%;
position: relative;
display: flex;
align-items: flex-end;
padding: 0 20rpx 10rpx;
box-sizing: border-box;
gap: 30rpx;
.bar-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
position: absolute;
right: 12rpx;
top: 50%;
transform: translateY(-50%);
bottom: 3rpx;
.bar-label {
font-size: 20rpx;
font-weight: 600;
white-space: nowrap;
}
.bar {
width: 32rpx;
border-radius: 4rpx 4rpx 0 0;
}
&.red {
left: 15rpx;
.bar-label {
color: #D93A12;
}
.bar {
height: 80rpx;
background: linear-gradient(180deg, #EE6E4E 0%, #D93A12 100%);
border: 1rpx solid #9D341A;
}
}
&.green {
right: 20rpx;
.bar-label {
color: #0FA983;
margin-bottom: 4rpx;
}
.bar {
height: 16rpx;
background: linear-gradient(180deg, #36E6BB 0%, #0FA983 100%);
border: 1rpx solid #1F8F73;
}
}
}
}
.ph-label-img {
position: absolute;
right: 96rpx;
top: 28%;
transform: translateY(-50%);
width: 50rpx;
height: 28rpx;
.badge-icon {
position: absolute;
top: 10rpx;
right: 10rpx;
width: 68rpx;
height: 68rpx;
z-index: 2;
}
}
}
}
}
.progress-panel {
width: 120%;
max-width: 710rpx;
margin: 1vh 0 0;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
box-sizing: border-box;
&.ph-result-body {
flex-direction: column;
justify-content: space-between;
padding: 10rpx 30rpx !important;
.progress-bar-container {
width: 100%;
height: 64rpx;
margin-bottom: 24rpx;
position: relative;
.progress-bar-bg {
.ph-comparison-row {
display: flex;
align-items: center;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
justify-content: center;
gap: 16rpx;
.result-img {
z-index: 1;
}
.ph-value-group {
display: flex;
align-items: center;
gap: 8rpx;
.initial-img {
z-index: 2;
}
}
.label {
color: #25334D;
font-size: 30rpx;
font-weight: 600;
}
.result-card {
position: relative;
width: 100%;
height: 226rpx;
margin-bottom: 24rpx;
border-radius: 24rpx;
border: 4rpx solid #457AAB;
background: #BEDCF3;
box-sizing: border-box;
.card-bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 98%;
height: 94%;
z-index: 0;
display: block;
}
.card-content {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
.card-title {
text-align: center;
font-size: 34rpx;
.value {
font-size: 30rpx;
font-weight: 600;
color: #25334D;
}
.card-body {
flex: 1;
&.highlight-green {
color: #4C9F6A;
}
&.highlight-lime {
color: #B2C849;
}
}
.ph-tag {
display: flex;
justify-content: center;
align-items: center;
padding: 0 20rpx;
.instruction-text {
font-size: 30rpx;
color: #25334D;
text {
color: #fff;
font-size: 20rpx;
font-weight: 600;
line-height: 1;
}
&.result-body {
justify-content: flex-start;
align-items: flex-start;
padding: 10rpx 40rpx;
.comparison-section {
display: flex;
flex-direction: column;
gap: 12rpx;
.section-title {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
}
.comparison-row {
display: flex;
align-items: center;
gap: 16rpx;
.value-badge {
padding: 6rpx 14rpx;
border-radius: 16rpx;
font-size: 24rpx;
color: #FFFFFF;
font-weight: 600;
&.before {
background: #D93A12;
border: 3rpx solid #9D341A;
}
&.after {
background: #0FA983;
border: 3rpx solid #1F8F73;
}
}
.arrow {
color: #457AAB;
font-weight: bold;
font-size: 28rpx;
}
}
.rate-row {
display: flex;
align-items: center;
margin-top: 4rpx;
.rate-label {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
}
.rate-value {
font-size: 32rpx;
color: #00CC99;
font-weight: bold;
margin-left: 10rpx;
}
.rate-bar {
width: 192rpx;
height: 28rpx;
background: #8FB2CE;
border-radius: 22rpx;
border: 1px solid rgba(69, 122, 171, 0.8);
box-shadow: 0 3rpx 4rpx 0 rgba(90, 108, 122, 0.4) inset;
margin-left: 20rpx;
overflow: hidden;
position: relative;
.rate-fill {
height: 100%;
background: #00CC99;
border-radius: 22rpx;
box-shadow: 0 0 4rpx 0 rgba(255, 255, 255, 0.7) inset;
}
}
}
}
.chart-section {
width: 186rpx;
height: 138rpx;
background: #BEDCF3;
border: 2rpx solid rgba(69, 122, 171, 0.5);
border-radius: 12rpx;
position: absolute;
right: 20rpx;
top: 60%;
transform: translateY(-50%);
box-sizing: border-box;
z-index: 10;
.chart-container {
width: 100%;
height: 100%;
position: relative;
display: flex;
align-items: flex-end;
padding: 0 20rpx 10rpx;
box-sizing: border-box;
gap: 30rpx;
.bar-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 4rpx;
position: absolute;
bottom: 3rpx;
.bar-label {
font-size: 20rpx;
font-weight: 600;
white-space: nowrap;
}
.bar {
width: 32rpx;
border-radius: 4rpx 4rpx 0 0;
}
&.red {
left: 15rpx;
.bar-label { color: #D93A12; }
.bar {
height: 80rpx;
background: linear-gradient(180deg, #EE6E4E 0%, #D93A12 100%);
border: 1rpx solid #9D341A;
}
}
&.green {
right: 20rpx;
.bar-label {
color: #0FA983;
margin-bottom: 4rpx;
}
.bar {
height: 16rpx;
background: linear-gradient(180deg, #36E6BB 0%, #0FA983 100%);
border: 1rpx solid #1F8F73;
}
}
}
}
.badge-icon {
position: absolute;
top: 10rpx;
right: 10rpx;
width: 68rpx;
height: 68rpx;
z-index: 2;
}
}
&.alkaline {
width: 72rpx;
height: 30rpx;
border-radius: 26rpx;
border: 2rpx solid #0E692E;
background: #4C9F6A;
}
&.ph-result-body {
flex-direction: column;
justify-content: space-between;
padding: 10rpx 30rpx !important;
.ph-comparison-row {
display: flex;
align-items: center;
width: 100%;
justify-content: center;
gap: 16rpx;
margin-top: 18rpx;
.ph-value-group {
display: flex;
align-items: center;
gap: 8rpx;
.label {
color: #25334D;
font-size: 30rpx;
font-weight: 600;
}
.value {
font-size: 30rpx;
font-weight: 600;
&.highlight-green {
color: #4C9F6A;
}
&.highlight-lime {
color: #B2C849;
}
}
.ph-tag {
display: flex;
justify-content: center;
align-items: center;
text {
color: #fff;
font-size: 16rpx;
font-weight: 500;
line-height: 1;
}
&.alkaline {
width: 72rpx;
height: 30rpx;
border-radius: 26rpx;
border: 2rpx solid #0E692E;
background: #4C9F6A;
}
&.neutral {
width: 56rpx;
height: 30rpx;
border-radius: 26rpx;
border: 2rpx solid #748A08;
background: #B2C849;
}
}
}
.ph-warning-icon, .ph-success-icon {
width: 36rpx;
height: 36rpx;
}
.ph-success-icon {
width: 32rpx;
height: 32rpx;
}
.ph-arrow {
color: #457AAB;
font-weight: bold;
font-size: 32rpx;
margin: 0 10rpx;
}
}
.ph-chart-container {
width: 100%;
margin: 10rpx 0;
display: flex;
justify-content: center;
.ph-chart-img {
width: 95%;
}
}
.ph-footer-row {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10rpx;
.ph-footer-label {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
.highlight {
color: #B2C849;
}
}
.ph-badge {
background: #B2C849;
color: #fff;
font-size: 24rpx;
padding: 6rpx 16rpx;
border-radius: 36rpx;
font-weight: 600;
border: 2rpx solid #748A08;
}
}
&.neutral {
width: 56rpx;
height: 30rpx;
border-radius: 26rpx;
border: 2rpx solid #748A08;
background: #B2C849;
}
}
}
}
}
.result-boxes {
width: 100%;
display: flex;
justify-content: center;
gap: 32rpx;
.result-box {
flex: 1;
height: 140rpx;
border-radius: 24rpx;
border: 2rpx solid #FFF;
background: linear-gradient(180deg, #FAFBFD 0%, #DCEEFD 100%);
box-sizing: border-box;
.ph-warning-icon,
.ph-success-icon {
width: 36rpx;
height: 36rpx;
}
.ph-success-icon {
width: 32rpx;
height: 32rpx;
}
.ph-arrow {
color: #457AAB;
font-weight: bold;
font-size: 32rpx;
margin: 0 10rpx;
}
}
.ph-chart-container {
width: 100%;
margin: 10rpx 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding-left: 32rpx;
gap: 10rpx;
position: relative;
.box-title, .box-value {
font-size: 32rpx;
color: #25334D;
line-height: 1.2;
.ph-chart-img {
width: 95%;
}
}
.status-icon {
position: absolute;
right: 20rpx;
top: 53%;
transform: translateY(-50%);
width: 92rpx;
height: 92rpx;
.ph-footer-row {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10rpx;
.ph-footer-label {
font-size: 30rpx;
color: #25334D;
font-weight: 600;
.highlight {
color: #8CC24A;
}
}
.ph-badge {
background: #8CC24A;
color: #fff;
font-size: 24rpx;
padding: 6rpx 16rpx;
border-radius: 20rpx;
font-weight: 600;
border: 2rpx solid #6B9C35;
}
}
}
}
}
}
.result-boxes {
width: 100%;
display: flex;
justify-content: center;
gap: 32rpx;
.result-box {
flex: 1;
height: 140rpx;
border-radius: 24rpx;
border: 2rpx solid #FFF;
background: linear-gradient(180deg, #FAFBFD 0%, #DCEEFD 100%);
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding-left: 32rpx;
gap: 10rpx;
position: relative;
.box-title,
.box-value {
font-size: 32rpx;
color: #25334D;
line-height: 1.2;
}
.status-icon {
position: absolute;
right: 20rpx;
top: 53%;
transform: translateY(-50%);
width: 92rpx;
height: 92rpx;
}
}
}
}
.tips-card {
width: 120%;
max-width: 710rpx;
height: 116rpx;
background: #BEDCF3;
border-radius: 24rpx;
border: 4rpx solid #457AAB;
padding: 20rpx;
position: relative;
width: 120%;
max-width: 710rpx;
height: 116rpx;
background: #BEDCF3;
border-radius: 24rpx;
border: 4rpx solid #457AAB;
padding: 20rpx;
position: relative;
box-sizing: border-box;
margin-top: 2vh;
flex-shrink: 0;
.tips-header {
position: absolute;
top: -24rpx;
left: 0;
width: 220rpx;
height: 58rpx;
background: linear-gradient(180deg, #52A5D7 0%, #3E83CE 100%);
border-radius: 48rpx;
border: 4rpx solid #1B5CA3;
box-shadow: 0 0 8rpx 0 #FFF inset;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
margin-top: 2vh;
flex-shrink: 0;
.tips-header {
position: absolute;
top: -24rpx;
left: 0;
width: 220rpx;
height: 58rpx;
background: linear-gradient(180deg, #52A5D7 0%, #3E83CE 100%);
border-radius: 48rpx;
border: 4rpx solid #1B5CA3;
box-shadow: 0 0 8rpx 0 #FFF inset;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
z-index: 10;
.bulb-icon {
position: absolute;
left: -25rpx;
bottom: -10rpx;
width: 80rpx;
height: 80rpx;
z-index: 12;
}
.tips-title {
color: #fff;
font-size: 32rpx;
font-weight: 600;
margin-left: 28rpx;
}
z-index: 10;
.bulb-icon {
position: absolute;
left: -25rpx;
bottom: -10rpx;
width: 80rpx;
height: 80rpx;
z-index: 12;
}
.tips-body {
position: absolute;
top: 10rpx;
left: 13rpx;
font-size: 30rpx;
color: #25334D;
padding: 20rpx 16rpx 10rpx 46rpx;
border-radius: 24rpx;
background: linear-gradient(180deg, #FFF 0%, #D9EBF7 100%);
width: 96%;
height: 80%;
box-sizing: border-box;
z-index: 5;
display: flex;
align-items: center;
font-weight: 600;
.tips-title {
color: #fff;
font-size: 32rpx;
font-weight: 600;
margin-left: 28rpx;
}
}
.tips-body {
position: absolute;
top: 10rpx;
left: 13rpx;
font-size: 30rpx;
color: #25334D;
padding: 20rpx 16rpx 10rpx 46rpx;
border-radius: 24rpx;
background: linear-gradient(180deg, #FFF 0%, #D9EBF7 100%);
width: 96%;
height: 80%;
box-sizing: border-box;
z-index: 5;
display: flex;
align-items: center;
font-weight: 600;
}
}
</style>
</style>
\ No newline at end of file
<template>
<view class="main-content">
<view class="beaker-section">
<view class="beaker-item polluted-beaker" :class="{ 'no-transform': isSecondTest }">
<view class="beaker-img-wrapper">
<image class="beaker-img"
:class="{ 'img-hidden': isTesting }"
:src="pollutedImageDefault"
mode="aspectFit">
</image>
<image class="beaker-img beaker-img-overlay"
:class="{ 'img-visible': isTesting }"
:src="pollutedImageTesting"
mode="aspectFit">
</image>
</view>
<view class="beaker-label polluted">污染水</view>
</view>
<image class="vs-icon"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/8678ceab4c7b41ac80cc1982054c45f4VS.webp"
mode="widthFix"></image>
<view class="beaker-item">
<view class="beaker-img-wrapper">
<image class="beaker-img"
:class="{ 'img-hidden': isTesting }"
:src="purifiedImageDefault"
mode="aspectFit">
</image>
<image class="beaker-img beaker-img-overlay"
:class="{ 'img-visible': isTesting }"
:src="purifiedImageTesting"
mode="aspectFit">
</image>
</view>
<view class="beaker-label purified">净化水</view>
</view>
<view class="main-content">
<view class="beaker-section">
<view class="beaker-item polluted-beaker" :class="{ 'no-transform': isSecondTest }">
<view class="beaker-img-wrapper">
<image
class="beaker-img"
:class="{ 'img-hidden': isTesting }"
:src="IMAGES.pollutedDefault"
mode="aspectFit"
/>
<image
class="beaker-img beaker-img-overlay"
:class="{ 'img-visible': isTesting }"
:src="pollutedImageTesting"
mode="aspectFit"
/>
</view>
<view class="beaker-label polluted">污染水</view>
</view>
<image class="vs-icon" :src="IMAGES.vsIcon" mode="widthFix" />
<view class="beaker-item">
<view class="beaker-img-wrapper">
<image
class="beaker-img"
:class="{ 'img-hidden': isTesting }"
:src="IMAGES.purifiedDefault"
mode="aspectFit"
/>
<image
class="beaker-img beaker-img-overlay"
:class="{ 'img-visible': isTesting }"
:src="purifiedImageTesting"
mode="aspectFit"
/>
</view>
<view class="beaker-label purified">净化水</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
isTesting: {
type: Boolean,
default: false
},
isSecondTest: {
type: Boolean,
default: false
}
isTesting: {
type: Boolean,
default: false,
},
isSecondTest: {
type: Boolean,
default: false,
},
});
const pollutedImageDefault = 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d2729bd9ca6249728c29c66a6e7f1baf%E7%83%A7%E6%9D%AF_%E6%B1%A1%E6%9F%93%E6%B0%B4%E7%89%88%202.webp';
const purifiedImageDefault = 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/048d81b1821442c3b80d312e4ef7c1e4%E7%83%A7%E6%9D%AF_%E6%B0%B4%E9%9D%A2%E5%B9%B3%E6%95%B4%E7%89%88%201.webp';
//烧杯图片
const IMAGES = {
pollutedDefault: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d2729bd9ca6249728c29c66a6e7f1baf%E7%83%A7%E6%9D%AF_%E6%B1%A1%E6%9F%93%E6%B0%B4%E7%89%88%202.webp',
purifiedDefault: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/048d81b1821442c3b80d312e4ef7c1e4%E7%83%A7%E6%9D%AF_%E6%B0%B4%E9%9D%A2%E5%B9%B3%E6%95%B4%E7%89%88%201.webp',
vsIcon: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/8678ceab4c7b41ac80cc1982054c45f4VS.webp',
pollutedPh: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a277ce4fb175493c9cedd60f6aa788d1%E7%83%A7%E6%9D%AF_%E6%9C%AA%E4%BD%BF%E7%94%A8%E9%85%B8%E7%A2%B1%E8%AF%95%E7%BA%B8%201.webp',
pollutedTds: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d775e2166f2d426f857e69dc3d115d47%E7%83%A7%E6%9D%AF_%E6%97%A0%E6%B0%B4%E6%BB%B4%E5%9B%9B%E8%82%A2_%E5%9B%BE2%201.webp',
purifiedPh: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/7b1c0214a1344946908e8de7ddaaea5e%E7%83%A7%E6%9D%AF_%E6%9C%AA%E4%BD%BF%E7%94%A8%E9%85%B8%E7%A2%B1%E8%AF%95%E7%BA%B8_%E5%87%80%E5%8C%96%E6%B0%B4%201.webp',
purifiedTds: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/c18364684a82445382105028ec6d8f44%E7%83%A7%E6%9D%AF_%E6%97%A0%E6%B0%B4%E6%BB%B4%E5%9B%9B%E8%82%A2_%E5%9B%BE1%201.webp',
};
const pollutedImageTesting = computed(() => {
return props.isSecondTest
? 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/a277ce4fb175493c9cedd60f6aa788d1%E7%83%A7%E6%9D%AF_%E6%9C%AA%E4%BD%BF%E7%94%A8%E9%85%B8%E7%A2%B1%E8%AF%95%E7%BA%B8%201.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d775e2166f2d426f857e69dc3d115d47%E7%83%A7%E6%9D%AF_%E6%97%A0%E6%B0%B4%E6%BB%B4%E5%9B%9B%E8%82%A2_%E5%9B%BE2%201.webp';
return props.isSecondTest ? IMAGES.pollutedPh : IMAGES.pollutedTds;
});
const purifiedImageTesting = computed(() => {
return props.isSecondTest
? 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/7b1c0214a1344946908e8de7ddaaea5e%E7%83%A7%E6%9D%AF_%E6%9C%AA%E4%BD%BF%E7%94%A8%E9%85%B8%E7%A2%B1%E8%AF%95%E7%BA%B8_%E5%87%80%E5%8C%96%E6%B0%B4%201.webp'
: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/c18364684a82445382105028ec6d8f44%E7%83%A7%E6%9D%AF_%E6%97%A0%E6%B0%B4%E6%BB%B4%E5%9B%9B%E8%82%A2_%E5%9B%BE1%201.webp';
return props.isSecondTest ? IMAGES.purifiedPh : IMAGES.purifiedTds;
});
</script>
<style scoped lang="scss">
.main-content {
flex: 1;
padding: 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
overflow: hidden;
justify-content: center;
flex: 1;
padding: 0 40rpx;
display: flex;
flex-direction: column;
align-items: center;
overflow: hidden;
justify-content: center;
}
.beaker-section {
width: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: flex-end;
position: relative;
flex-shrink: 1;
.beaker-item {
display: flex;
justify-content: center;
align-items: flex-end;
position: relative;
flex-shrink: 1;
.beaker-item {
display: flex;
flex-direction: column;
align-items: center;
.beaker-img-wrapper {
width: 364rpx;
height: 541rpx;
position: relative;
}
.beaker-img {
width: 364rpx;
height: 541rpx;
position: absolute;
bottom: 0;
left: 0;
opacity: 1;
transition: opacity 0.15s ease-in-out;
&.img-hidden {
opacity: 0;
}
}
.beaker-img-overlay {
opacity: 0;
&.img-visible {
opacity: 1;
}
}
&.polluted-beaker:not(.no-transform) .beaker-img-overlay {
transform: scale(1.03) translateY(25rpx);
transform-origin: center bottom;
}
.beaker-label {
padding: 8rpx 32rpx;
border-radius: 48rpx;
color: #fff;
font-size: 34rpx;
position: relative;
top: -60rpx;
z-index: 1;
&.polluted {
background: linear-gradient(180deg, #B79669 0%, #8C6B46 100%);
border: 4rpx solid #503F34;
}
&.purified {
background: linear-gradient(180deg, #4CAAE4 0%, #3F80D2 100%);
border: 4rpx solid #3060AD;
}
}
flex-direction: column;
align-items: center;
.beaker-img-wrapper {
width: 364rpx;
height: 541rpx;
position: relative;
}
.beaker-img {
width: 364rpx;
height: 541rpx;
position: absolute;
bottom: 0;
left: 0;
opacity: 1;
transition: opacity 0.15s ease-in-out;
&.img-hidden {
opacity: 0;
}
}
.beaker-img-overlay {
opacity: 0;
&.img-visible {
opacity: 1;
}
}
&.polluted-beaker:not(.no-transform) .beaker-img-overlay {
transform: scale(1.03) translateY(25rpx);
transform-origin: center bottom;
}
.vs-icon {
width: 108rpx;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 99;
.beaker-label {
padding: 8rpx 32rpx;
border-radius: 48rpx;
color: #fff;
font-size: 34rpx;
position: relative;
top: -60rpx;
z-index: 1;
&.polluted {
background: linear-gradient(180deg, #b79669 0%, #8c6b46 100%);
border: 4rpx solid #503f34;
}
&.purified {
background: linear-gradient(180deg, #4caae4 0%, #3f80d2 100%);
border: 4rpx solid #3060ad;
}
}
}
.vs-icon {
width: 108rpx;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 99;
}
}
</style>
</style>
\ No newline at end of file
<template>
<view class="container">
<image class="bg" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/963079c98b914f349fe9ff5e600d0f65%E6%B0%B4%E8%B4%A8%E6%A3%80%E6%B5%8B%E7%AB%99_%E7%BA%AF%E8%83%8C%E6%99%AF%201.webp" mode="aspectFill"></image>
<view class="header" :style="{ paddingTop: statusBarHeight + 'px' }">
<image class="title" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/e9ddd6b498fe452b9254e86c04596df3Group%20348447251.webp" mode="heightFix"></image>
</view>
<Beaker :isTesting="isTesting" :isSecondTest="isSecondTest"/>
<view class="bottom-panel">
<TabsInstructionsPanel :isTesting="isTesting" :isSecondTest="isSecondTest" :triggerShowFinalCard="triggerShowFinalCard" @resultShown="handleResultShown" @progressFinished="handleProgressFinished"/>
<BottomActionBar :isTesting="isTesting" :isSecondTest="isSecondTest" :isResultShown="isResultShown" :isProgressFinished="isProgressFinished" @startTest="startTest" @restartTest="restartTest" @showFinalCard="handleShowFinalCard" @showCompletionPopup="handleShowCompletion"/>
</view>
<view class="completion-overlay" v-if="showCompletion" @click="closeCompletion">
<image class="completion-img" src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d204d71cf2a54b18a6404e6132618cd6%E5%AE%8C%E6%88%90%E5%BC%B9%E7%AA%97.webp" mode="scaleToFill" @click.stop="closeCompletion"></image>
</view>
</view>
<view class="container">
<image class="bg" :src="assets.bg" mode="aspectFill" />
<view class="header" :style="{ paddingTop: statusBarHeight + 'px' }">
<image class="title" :src="assets.title" mode="heightFix" />
</view>
<Beaker :isTesting="isTesting" :isSecondTest="isSecondTest" />
<view class="bottom-panel">
<TabsInstructionsPanel
:isTesting="isTesting"
:isSecondTest="isSecondTest"
:triggerShowFinalCard="triggerShowFinalCard"
@resultShown="handleResultShown"
@progressFinished="handleProgressFinished"
/>
<BottomActionBar
:isTesting="isTesting"
:isSecondTest="isSecondTest"
:isResultShown="isResultShown"
:isProgressFinished="isProgressFinished"
@startTest="startTest"
@restartTest="restartTest"
@showFinalCard="handleShowFinalCard"
@showCompletionPopup="handleShowCompletion"
/>
</view>
<view class="completion-overlay" v-if="showCompletion" @click="closeCompletion">
<image
class="completion-img"
:src="assets.completionPopup"
mode="scaleToFill"
@click.stop="closeCompletion"
/>
</view>
</view>
</template>
<script setup>
......@@ -28,6 +47,12 @@ import Beaker from './components/beaker.vue';
import TabsInstructionsPanel from './components/TabsInstructionsPanel.vue';
import BottomActionBar from './components/BottomActionBar.vue';
const assets = {
bg: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/963079c98b914f349fe9ff5e600d0f65%E6%B0%B4%E8%B4%A8%E6%A3%80%E6%B5%8B%E7%AB%99_%E7%BA%AF%E8%83%8C%E6%99%AF%201.webp',
title: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/e9ddd6b498fe452b9254e86c04596df3Group%20348447251.webp',
completionPopup: 'https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d204d71cf2a54b18a6404e6132618cd6%E5%AE%8C%E6%88%90%E5%BC%B9%E7%AA%97.webp'
};
const statusBarHeight = ref(20);
const isTesting = ref(false);
const isSecondTest = ref(false);
......@@ -37,154 +62,116 @@ const triggerShowFinalCard = ref(false);
const showCompletion = ref(false);
onLoad(() => {
const systemInfo = uni.getSystemInfoSync();
statusBarHeight.value = systemInfo.statusBarHeight || 20;
const systemInfo = uni.getSystemInfoSync();
statusBarHeight.value = systemInfo.statusBarHeight || 20;
});
const goBack = () => {
uni.navigateBack({
fail: () => {
uni.reLaunch({
url: '/pages/index/index'
});
}
});
};
const startTest = () => {
console.log('Start detection');
isTesting.value = true;
isProgressFinished.value = false;
triggerShowFinalCard.value = false;
console.log('Start detection');
isTesting.value = true;
isProgressFinished.value = false;
triggerShowFinalCard.value = false;
};
const handleResultShown = () => {
isResultShown.value = true;
isResultShown.value = true;
};
const handleProgressFinished = () => {
isProgressFinished.value = true;
isProgressFinished.value = true;
};
const handleShowFinalCard = () => {
triggerShowFinalCard.value = true;
triggerShowFinalCard.value = true;
};
const restartTest = () => {
console.log('Restart detection');
isTesting.value = false;
isResultShown.value = false;
isProgressFinished.value = false;
triggerShowFinalCard.value = false;
isSecondTest.value = true;
console.log('Restart detection');
isTesting.value = false;
isResultShown.value = false;
isProgressFinished.value = false;
triggerShowFinalCard.value = false;
isSecondTest.value = true;
};
const handleShowCompletion = () => {
showCompletion.value = true;
showCompletion.value = true;
};
const closeCompletion = () => {
showCompletion.value = false;
showCompletion.value = false;
};
</script>
<style lang="scss" scoped>
.container {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
flex-direction: column;
color: #333;
overflow: hidden;
box-sizing: border-box;
}
.bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
object-fit: cover;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 2vh;
flex-shrink: 0;
.nav-bar {
width: 100%;
height: 44px;
display: flex;
align-items: center;
padding: 0 20rpx;
box-sizing: border-box;
.back-btn {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.6);
padding: 8rpx 16rpx;
border-radius: 30rpx;
.back-arrow {
font-size: 32rpx;
margin-right: 6rpx;
line-height: 1;
}
.back-text {
font-size: 24rpx;
font-weight: 500;
}
}
}
.title {
height: 120rpx;
width: 54rpx;
}
}
.completion-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
.completion-img {
width: 100%;
height: 100%;
}
}
.bottom-panel {
width: 100%;
height: 48vh;
flex-shrink: 0;
border-radius: 24rpx 24rpx 0 0;
border-top: 4rpx solid #728FAF;
background: linear-gradient(180deg, #E0EBF6 0%, #C3D3E4 100%);
box-shadow: 0 10rpx 0 0 #FFF inset;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 3vh;
box-sizing: border-box;
position: absolute;
bottom: 0;
left: 0;
z-index: 10;
padding-bottom: env(safe-area-inset-bottom);
}
</style>
.container {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
flex-direction: column;
color: #333;
overflow: hidden;
box-sizing: border-box;
}
.bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
object-fit: cover;
}
.header {
display: flex;
flex-direction: column;
align-items: center;
padding-bottom: 2vh;
flex-shrink: 0;
.title {
height: 120rpx;
width: 54rpx;
}
}
.completion-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
.completion-img {
width: 100%;
height: 100%;
}
}
.bottom-panel {
width: 100%;
height: 48vh;
flex-shrink: 0;
border-radius: 24rpx 24rpx 0 0;
border-top: 4rpx solid #728FAF;
background: linear-gradient(180deg, #E0EBF6 0%, #C3D3E4 100%);
box-shadow: 0 10rpx 0 0 #FFF inset;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 3vh;
box-sizing: border-box;
position: absolute;
bottom: 0;
left: 0;
z-index: 10;
padding-bottom: env(safe-area-inset-bottom);
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment