feat(WIP)

This commit is contained in:
sleepwithoutbz
2025-10-04 11:45:36 +08:00
parent 4c71b3a711
commit 8d650002ea
42 changed files with 1101 additions and 927 deletions

View File

@@ -1,67 +0,0 @@
<template>
<div class="home-view">
<AboutSection
v-for="section in aboutSections"
:key="section.title"
:reverse="section.reverse"
:title="$t(section.title)"
:description="$t(section.description)"
:background-image="section.backgroundImage"
:buttonshow="section.buttonShow"
:targetPath="section.targetPath"
/>
</div>
</template>
<!-- <script>
export default {
name: 'HomeView',
}
</script> -->
<script setup lang="ts">
import AboutSection from '@/components/AboutSection.vue'
import { ref } from 'vue'
import logoImage from '/images/logo.png'
import product2 from '/images/product2.png'
const aboutSections = ref([
{
title: 'company.name',
description: 'company.introduction',
backgroundImage: logoImage,
reverse: true,
buttonShow: false,
targetPath: '',
},
{
title: 'property',
description: 'company.property',
backgroundImage: '', // or whatever the default is
reverse: false,
buttonShow: false,
targetPath: '',
},
{
title: 'areas.individual.name',
description: 'areas.individual.intro',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '/waterlife',
},
{
title: 'areas.aged.name',
description: 'company.introduction',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '',
},
])
</script>
<style scoped>
.home-view {
background-color: rgb(241, 244, 247);
}
</style>

View File

@@ -1,67 +0,0 @@
<template>
<div class="home-view">
<AboutSection
v-for="section in aboutSections"
:key="section.title"
:reverse="section.reverse"
:title="$t(section.title)"
:description="$t(section.description)"
:background-image="section.backgroundImage"
:buttonshow="section.buttonShow"
:targetPath="section.targetPath"
/>
</div>
</template>
<!-- <script>
export default {
name: 'HomeView',
}
</script> -->
<script setup lang="ts">
import AboutSection from '@/components/AboutSection.vue'
import { ref } from 'vue'
import logoImage from '/images/logo.png'
import product2 from '/images/product2.png'
const aboutSections = ref([
{
title: 'company.name',
description: 'company.introduction',
backgroundImage: logoImage,
reverse: true,
buttonShow: false,
targetPath: '',
},
{
title: 'property',
description: 'company.property',
backgroundImage: '', // or whatever the default is
reverse: false,
buttonShow: false,
targetPath: '',
},
{
title: 'areas.individual.name',
description: 'areas.individual.intro',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '/waterlife',
},
{
title: 'areas.aged.name',
description: 'company.introduction',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '',
},
])
</script>
<style scoped>
.home-view {
background-color: rgb(241, 244, 247);
}
</style>

View File

@@ -21,14 +21,16 @@ export default {
<script setup lang="ts">
import AboutSection from '@/components/AboutSection.vue'
import { ref } from 'vue'
import logoImage from '/images/logo.png'
import product2 from '/images/product2.png'
import background_1 from '/images/background_1.jpg'
import background_2 from '/images/background_2.jpg'
import background_3 from '/images/background_3.jpg'
import background_4 from '/images/background_4.jpg'
const aboutSections = ref([
{
title: 'company.name',
description: 'company.introduction',
backgroundImage: logoImage,
backgroundImage: background_1,
reverse: true,
buttonShow: false,
targetPath: '',
@@ -36,28 +38,29 @@ const aboutSections = ref([
{
title: 'property',
description: 'company.property',
backgroundImage: '', // or whatever the default is
backgroundImage: background_2,
reverse: false,
buttonShow: false,
targetPath: '',
},
{
title: 'areas.individual.name',
description: 'areas.individual.intro',
backgroundImage: product2,
title: 'areas.waterlife.name',
description: 'areas.waterlife.intro',
backgroundImage: background_3,
reverse: false,
buttonShow: true,
targetPath: '/waterlife',
buttonShow: false,
targetPath: '',
},
{
title: 'areas.aged.name',
description: 'company.introduction',
backgroundImage: product2,
description: 'areas.aged.intro',
backgroundImage: background_4,
reverse: false,
buttonShow: true,
targetPath: '',
targetPath: '/todo',
},
])
</script>
<style scoped>

View File

@@ -1,67 +0,0 @@
<template>
<div class="home-view">
<AboutSection
v-for="section in aboutSections"
:key="section.title"
:reverse="section.reverse"
:title="$t(section.title)"
:description="$t(section.description)"
:background-image="section.backgroundImage"
:buttonshow="section.buttonShow"
:targetPath="section.targetPath"
/>
</div>
</template>
<!-- <script>
export default {
name: 'HomeView',
}
</script> -->
<script setup lang="ts">
import AboutSection from '@/components/AboutSection.vue'
import { ref } from 'vue'
import logoImage from '/images/logo.png'
import product2 from '/images/product2.png'
const aboutSections = ref([
{
title: 'company.name',
description: 'company.introduction',
backgroundImage: logoImage,
reverse: true,
buttonShow: false,
targetPath: '',
},
{
title: 'property',
description: 'company.property',
backgroundImage: '', // or whatever the default is
reverse: false,
buttonShow: false,
targetPath: '',
},
{
title: 'areas.individual.name',
description: 'areas.individual.intro',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '/waterlife',
},
{
title: 'areas.aged.name',
description: 'company.introduction',
backgroundImage: product2,
reverse: false,
buttonShow: true,
targetPath: '',
},
])
</script>
<style scoped>
.home-view {
background-color: rgb(241, 244, 247);
}
</style>

77
src/views/StoreView.vue Normal file
View File

@@ -0,0 +1,77 @@
<template>
<div class="purchase-methods">
<h2>购买方式</h2>
<div class="methods-container">
<!-- 微信 -->
<div class="method">
<h3>微信</h3>
<img :src="WeChat" alt="微信二维码" />
</div>
<!-- 淘宝 -->
<div class="method">
<h3>淘宝</h3>
<img :src="TaoBao" alt="淘宝二维码" />
</div>
<!-- 小红书 -->
<div class="method">
<h3>小红书</h3>
<img :src="RedNote" alt="小红书二维码" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import WeChat from '/images/WeChat.jpg'
import TaoBao from '/images/TaoBao.jpg'
import RedNote from '/images/RedNote.jpg'
</script>
<style scoped>
.purchase-methods {
font-family: 'Arial', sans-serif;
padding: 20px;
text-align: center;
}
.purchase-methods h2 {
font-size: 1.8rem;
margin-bottom: 30px;
color: #333;
}
.methods-container {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
gap: 40px;
max-width: 800px;
margin: 0 auto;
}
.method {
flex: 1;
min-width: 200px;
padding: 15px;
border-radius: 10px;
background-color: #f9f9f9;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.method h3 {
margin-top: 0;
font-size: 1.2rem;
color: #333;
}
.method img {
width: 150px;
height: 150px;
margin: 10px auto;
display: block;
border: 1px solid #ddd;
border-radius: 8px;
}
</style>

26
src/views/TodoView.vue Normal file
View File

@@ -0,0 +1,26 @@
<template>
<div class="home-view">
<AboutSection
key="Todo"
:title="$t('pages.todo.name')"
:description="$t('pages.todo.content')"
:background-image="background_4"
/>
</div>
</template>
<!-- <script>
export default {
name: 'HomeView',
}
</script> -->
<script setup lang="ts">
import AboutSection from '@/components/AboutSection.vue'
import background_4 from '/images/background_4.jpg'
</script>
<style scoped>
.home-view {
background-color: rgb(241, 244, 247);
}
</style>

View File

@@ -1,3 +1,5 @@
<!-- TODO: 拆分为独立的三个页面后续产品种类提升可以合并 -->
<template>
<div class="product-display">
<ProductDetail
@@ -44,26 +46,11 @@ import { ref, computed } from 'vue'
import ProductDetail from '@/components/ProductDetail.vue'
import { useI18n } from 'vue-i18n'
import seekDetail from '@/components/seekDetail.vue'
const { tm } = useI18n()
// import { useI18n } from 'vue-i18n'
// const { t } = useI18n()
interface DetailItem {
key: string
value: string
}
// products 数据
interface DetailItem {
key: string
value: string
}
interface ProductInfoData {
notice: string
usage: string
features: string
introduction: string
}
const selectedProductData = computed(() => {
return products.value.find((p) => p.name === selectedProduct.value)
@@ -71,27 +58,29 @@ const selectedProductData = computed(() => {
import cyqImage from '@/assets/water/cyq.png'
import cjqImage from '@/assets/water/cjq.png'
import cjbImage from '@/assets/water/cjb.png'
import type { DetailItem, ProductInfoData } from '@/types/product'
const products = ref([
{
name: 'cyq',
detailList: tm('cyq.detail') as unknown as DetailItem[],
// detailList: tm('cyq.detail') as unknown as DetailItem[],
detailList: computed(() => tm('cyq.detail') as DetailItem[]),
imageUrl: cyqImage,
infoData: tm('cyq') as unknown as ProductInfoData,
// infoData: tm('cyq') as unknown as ProductInfoData,
infoData: computed(() => tm('cyq') as ProductInfoData),
},
{
name: 'cjb',
detailList: tm('cyq.detail') as unknown as DetailItem[],
detailList: computed(() => tm('cjb.detail') as DetailItem[]),
imageUrl: cjbImage,
infoData: tm('cjb') as unknown as ProductInfoData,
infoData: computed(() => tm('cjb') as ProductInfoData),
},
{
name: 'cjq',
detailList: tm('cyq.detail') as unknown as DetailItem[],
detailList: computed(() => tm('cjq.detail') as DetailItem[]),
imageUrl: cjqImage,
infoData: tm('cjq') as unknown as ProductInfoData,
infoData: computed(() => tm('cjq') as ProductInfoData),
},
])
const selectedProduct = ref('')

View File

@@ -0,0 +1,178 @@
<!-- 小喷瓶 -->
<template>
<div class="product-display">
<ProductDetail
:key="product.name"
reverse
:title="$t(`${product.name}.name`)"
:content="$t(`${product.name}.info`)"
:imagetitle="$t(`${product.name}.name`)"
:info="$t(`${product.name}.info`)"
:detailList="product.detailList"
:imageUrl="product.imageUrl"
:videoUrl="$t(`${product.name}.video-url`)"
/>
</div>
<div class="product-move">
<div class="product-list">
<div :key="product.name" class="product-card">
<img :src="product.imageUrl" class="product-image" />
</div>
</div>
<div class="detail-section">
<transition name="fade" mode="out-in">
<seekDetail :key="product.name" :productData="product.infoData" />
</transition>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import ProductDetail from '@/components/ProductDetail.vue'
import { useI18n } from 'vue-i18n'
import seekDetail from '@/components/seekDetail.vue'
import cjqImage from '@/assets/water/cjq.png'
import type { DetailItem, ProductInfoData } from '@/types/product'
// import { useI18n } from 'vue-i18n'
// const { t } = useI18n()
const { tm } = useI18n()
const product = ref({
name: 'cjq',
detailList: computed(() => tm('cjq.detail') as DetailItem[]),
imageUrl: cjqImage,
infoData: computed(() => tm('cjq') as ProductInfoData),
})
</script>
<style scoped>
/* 产品展示区域样式 */
.product-display {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 30px;
}
.product-move {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.product-list {
display: flex;
justify-content: center;
gap: 20px;
width: 100%;
}
.product-card {
display: flex;
justify-content: center;
align-items: center;
width: 20%;
height: auto;
background: white;
border-radius: 12px;
transition: all 0.3s ease;
cursor: pointer;
overflow: hidden;
position: relative;
}
.product-card:before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(106, 17, 203, 0.1) 0%, rgba(37, 117, 252, 0.1) 100%);
opacity: 0;
transition: opacity 0.2s ease;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.product-card:hover:before {
opacity: 1;
}
.product-card.active {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(106, 17, 203, 0.2);
}
.product-card.active:before {
opacity: 1;
}
.product-image {
width: 80%;
height: auto;
object-fit: contain;
transition: transform 0.3s ease;
}
.product-card:hover .product-image {
transform: scale(1.05);
}
.detail-section {
width: 100%;
display: flex;
justify-content: center;
margin-top: 20px;
}
/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {
transition:
opacity 0.5s ease,
transform 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
/* 响应式设计 */
@media (max-width: 768px) {
.product-list {
gap: 15px;
}
.product-card {
width: 140px;
height: 140px;
}
.product-display {
gap: 30px;
}
}
@media (max-width: 480px) {
.product-list {
gap: 10px;
}
.product-card {
width: 110px;
height: 110px;
}
}
</style>

178
src/views/WaterLife_cup.vue Normal file
View File

@@ -0,0 +1,178 @@
<!-- 除菌杯 -->
<template>
<div class="product-display">
<ProductDetail
:key="product.name"
reverse
:title="$t(`${product.name}.name`)"
:content="$t(`${product.name}.info`)"
:imagetitle="$t(`${product.name}.name`)"
:info="$t(`${product.name}.info`)"
:detailList="product.detailList"
:imageUrl="product.imageUrl"
:videoUrl="$t(`${product.name}.video-url`)"
/>
</div>
<div class="product-move">
<div class="product-list">
<div :key="product.name" class="product-card">
<img :src="product.imageUrl" class="product-image" />
</div>
</div>
<div class="detail-section">
<transition name="fade" mode="out-in">
<seekDetail :key="product.name" :productData="product.infoData" />
</transition>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import ProductDetail from '@/components/ProductDetail.vue'
import { useI18n } from 'vue-i18n'
import seekDetail from '@/components/seekDetail.vue'
import cjbImage from '@/assets/water/cjb.png'
import type { DetailItem, ProductInfoData } from '@/types/product'
// import { useI18n } from 'vue-i18n'
// const { t } = useI18n()
const { tm } = useI18n()
const product = ref({
name: 'cjb',
detailList: computed(() => tm('cjb.detail') as DetailItem[]),
imageUrl: cjbImage,
infoData: computed(() => tm('cjb') as ProductInfoData),
})
</script>
<style scoped>
/* 产品展示区域样式 */
.product-display {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 30px;
}
.product-move {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.product-list {
display: flex;
justify-content: center;
gap: 20px;
width: 100%;
}
.product-card {
display: flex;
justify-content: center;
align-items: center;
width: 20%;
height: auto;
background: white;
border-radius: 12px;
transition: all 0.3s ease;
cursor: pointer;
overflow: hidden;
position: relative;
}
.product-card:before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(106, 17, 203, 0.1) 0%, rgba(37, 117, 252, 0.1) 100%);
opacity: 0;
transition: opacity 0.2s ease;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.product-card:hover:before {
opacity: 1;
}
.product-card.active {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(106, 17, 203, 0.2);
}
.product-card.active:before {
opacity: 1;
}
.product-image {
width: 80%;
height: auto;
object-fit: contain;
transition: transform 0.3s ease;
}
.product-card:hover .product-image {
transform: scale(1.05);
}
.detail-section {
width: 100%;
display: flex;
justify-content: center;
margin-top: 20px;
}
/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {
transition:
opacity 0.5s ease,
transform 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
/* 响应式设计 */
@media (max-width: 768px) {
.product-list {
gap: 15px;
}
.product-card {
width: 140px;
height: 140px;
}
.product-display {
gap: 30px;
}
}
@media (max-width: 480px) {
.product-list {
gap: 10px;
}
.product-card {
width: 110px;
height: 110px;
}
}
</style>

View File

@@ -0,0 +1,180 @@
<!-- 冲牙器 -->
<template>
<div class="product-display">
<ProductDetail
:key="product.name"
reverse
:title="$t(`${product.name}.name`)"
:content="$t(`${product.name}.info`)"
:imagetitle="$t(`${product.name}.name`)"
:info="$t(`${product.name}.info`)"
:detailList="product.detailList"
:imageUrl="product.imageUrl"
:videoUrl="$t(`${product.name}.video-url`)"
/>
</div>
<div class="product-move">
<div class="product-list">
<div :key="product.name" class="product-card">
<img :src="product.imageUrl" class="product-image" />
</div>
</div>
<div class="detail-section">
<transition name="fade" mode="out-in">
<seekDetail :key="product.name" :productData="product.infoData" />
</transition>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import ProductDetail from '@/components/ProductDetail.vue'
import { useI18n } from 'vue-i18n'
import seekDetail from '@/components/seekDetail.vue'
import cyqImage from '@/assets/water/cyq.png'
import type { DetailItem, ProductInfoData } from '@/types/product'
// import { useI18n } from 'vue-i18n'
// const { t } = useI18n()
const { tm } = useI18n()
const product = ref({
name: 'cyq',
// detailList: tm('cyq.detail') as unknown as DetailItem[],
detailList: computed(() => tm('cyq.detail') as DetailItem[]),
imageUrl: cyqImage,
// infoData: tm('cyq') as unknown as ProductInfoData,
infoData: computed(() => tm('cyq') as ProductInfoData),
})
</script>
<style scoped>
/* 产品展示区域样式 */
.product-display {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 30px;
}
.product-move {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.product-list {
display: flex;
justify-content: center;
gap: 20px;
width: 100%;
}
.product-card {
display: flex;
justify-content: center;
align-items: center;
width: 20%;
height: auto;
background: white;
border-radius: 12px;
transition: all 0.3s ease;
cursor: pointer;
overflow: hidden;
position: relative;
}
.product-card:before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(106, 17, 203, 0.1) 0%, rgba(37, 117, 252, 0.1) 100%);
opacity: 0;
transition: opacity 0.2s ease;
}
.product-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
.product-card:hover:before {
opacity: 1;
}
.product-card.active {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(106, 17, 203, 0.2);
}
.product-card.active:before {
opacity: 1;
}
.product-image {
width: 80%;
height: auto;
object-fit: contain;
transition: transform 0.3s ease;
}
.product-card:hover .product-image {
transform: scale(1.05);
}
.detail-section {
width: 100%;
display: flex;
justify-content: center;
margin-top: 20px;
}
/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {
transition:
opacity 0.5s ease,
transform 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
/* 响应式设计 */
@media (max-width: 768px) {
.product-list {
gap: 15px;
}
.product-card {
width: 140px;
height: 140px;
}
.product-display {
gap: 30px;
}
}
@media (max-width: 480px) {
.product-list {
gap: 10px;
}
.product-card {
width: 110px;
height: 110px;
}
}
</style>