Commit 551bbb4c by wusiyi

feat: 官网2.0样式优化

parent a7e95afc
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
"vue-router": "^3.5.3", "vue-router": "^3.5.3",
"vue-seamless-scroll": "^1.1.23", "vue-seamless-scroll": "^1.1.23",
"vue-selecto": "~1.10.1", "vue-selecto": "~1.10.1",
"vue-slick-carousel": "^1.0.6",
"vuedraggable": "~2.23.2", "vuedraggable": "~2.23.2",
"vuex": "^3.4.0", "vuex": "^3.4.0",
"vxe-table": "~3.3.12", "vxe-table": "~3.3.12",
...@@ -18756,21 +18755,6 @@ ...@@ -18756,21 +18755,6 @@
"vue": "*" "vue": "*"
} }
}, },
"node_modules/vue-slick-carousel": {
"version": "1.0.6",
"resolved": "https://registry.npmmirror.com/vue-slick-carousel/-/vue-slick-carousel-1.0.6.tgz",
"integrity": "sha512-1CN/hpWC8m1U/eO7Kuc71jntJqdg6Z/ieLji21OPfQUhs8ZYnnGhQSu1covpa3IyuovM9T5puPCVgexs3DDF5A==",
"dependencies": {
"enquire.js": "2.1.6",
"json2mq": "0.2.0",
"lodash.assign": "^4.2.0",
"lodash.debounce": "^4.0.8",
"lodash.get": "^4.4.2",
"lodash.pick": "^4.4.0",
"resize-observer-polyfill": "1.5.1",
"vue": "^2.6.10"
}
},
"node_modules/vue-style-loader": { "node_modules/vue-style-loader": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
"vue-router": "^3.5.3", "vue-router": "^3.5.3",
"vue-seamless-scroll": "^1.1.23", "vue-seamless-scroll": "^1.1.23",
"vue-selecto": "~1.10.1", "vue-selecto": "~1.10.1",
"vue-slick-carousel": "^1.0.6",
"vuedraggable": "~2.23.2", "vuedraggable": "~2.23.2",
"vuex": "^3.4.0", "vuex": "^3.4.0",
"vxe-table": "~3.3.12", "vxe-table": "~3.3.12",
......
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24">
<g fill="none">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path fill="#d28f0f" d="M20 17.5a1.5 1.5 0 0 1 .144 2.993L20 20.5H4a1.5 1.5 0 0 1-.144-2.993L4 17.5zm0-7a1.5 1.5 0 0 1 0 3H4a1.5 1.5 0 0 1 0-3zm0-7a1.5 1.5 0 0 1 0 3H4a1.5 1.5 0 1 1 0-3z" />
</g>
</svg>
\ No newline at end of file
<template> <template>
<div class="header-nav-mobile"> <div class="header-nav-mobile">
<div class="header-nav-mobile_trigger"> <div class="header-nav-mobile_trigger">
<a class="nav-icon icon-menu" href="javascript:;" @click="toggleShow"></a> <Icon
@click.native="toggleShow"
icon="typcn:th-menu"
color="var(--primary-color)"
width="20"
height="20" />
<!-- <a class="nav-icon icon-menu" href="javascript:;" @click="toggleShow"></a> -->
</div> </div>
<div @click="goHome" class="header-nav-mobile_logo"> <div @click="goHome" class="header-nav-mobile_logo">
<img src="../assets/logo.png" style="height: 40px" /> <img src="../assets/logo.png" style="height: 40px" />
...@@ -101,6 +107,7 @@ ...@@ -101,6 +107,7 @@
</template> </template>
<script> <script>
import { mapMutations } from 'vuex' import { mapMutations } from 'vuex'
import { Icon } from '@iconify/vue2'
import productionSvg from '../assets/images/home/production.svg' import productionSvg from '../assets/images/home/production.svg'
import customSvg from '../assets/images/home/custom.svg' import customSvg from '../assets/images/home/custom.svg'
import supplyChainSvg from '../assets/images/home/earth.svg' import supplyChainSvg from '../assets/images/home/earth.svg'
...@@ -112,6 +119,9 @@ export default { ...@@ -112,6 +119,9 @@ export default {
inject: { inject: {
scrollParent: 'scrollParent', scrollParent: 'scrollParent',
}, },
components: {
Icon,
},
data() { data() {
return { return {
showing: false, showing: false,
...@@ -291,19 +301,6 @@ export default { ...@@ -291,19 +301,6 @@ export default {
flex: 1; flex: 1;
} }
.nav-icon {
width: 25px;
height: 25px;
display: block;
}
.icon-menu {
background-size: 100%;
background-repeat: no-repeat;
background-position: center;
background-image: url(../assets/mobile.svg);
}
.header-nav-mobile-enter-active, .header-nav-mobile-enter-active,
.header-nav-mobile-leave-active { .header-nav-mobile-leave-active {
transition: 0.3s; transition: 0.3s;
......
...@@ -62,6 +62,8 @@ import { ...@@ -62,6 +62,8 @@ import {
BreadcrumbItem, BreadcrumbItem,
Breadcrumb, Breadcrumb,
Popconfirm, Popconfirm,
Timeline,
TimelineItem,
} from 'element-ui' } from 'element-ui'
Vue.prototype.$ELEMENT = { size: 'mini' } Vue.prototype.$ELEMENT = { size: 'mini' }
...@@ -103,6 +105,8 @@ Vue.use(Tabs) ...@@ -103,6 +105,8 @@ Vue.use(Tabs)
Vue.use(Breadcrumb) Vue.use(Breadcrumb)
Vue.use(BreadcrumbItem) Vue.use(BreadcrumbItem)
Vue.use(Popconfirm) Vue.use(Popconfirm)
Vue.use(Timeline)
Vue.use(TimelineItem)
Vue.prototype.$alert = MessageBox.alert Vue.prototype.$alert = MessageBox.alert
Vue.prototype.$message = (message) => Vue.prototype.$message = (message) =>
typeof message === 'string' typeof message === 'string'
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="bg-colorBg w-full flex flex-col m-auto mt-20 py-20"> <div class="bg-colorBg w-full flex flex-col m-auto mt-20 py-10">
<h2 class="text-center">发展历程</h2> <h2 class="text-center">发展历程</h2>
<timeline /> <timeline />
</div> </div>
......
...@@ -16,53 +16,41 @@ ...@@ -16,53 +16,41 @@
</div> </div>
</div> </div>
</div> </div>
<VueSlickCarousel <div class="timeline-cards-container" ref="cardsContainer">
v-bind="settings" <div
ref="slick" class="timeline-cards-wrapper"
@beforeChange="beforeChange"> :style="{ transform: `translateX(${translateX}px)` }">
<div v-for="(item, index) in timelineItems" :key="index">
<div <div
class="timeline-card p-10 h-80 w-104 shadow-xl rounded-lg cursor-pointer" v-for="(item, index) in timelineItems"
:class="{ 'timeline-card-current': currentIndex === index }"> :key="index"
<div class="w-full text-gray-600 font-semibold text-2xl"> class="timeline-card-item"
{{ item.title }} ref="cardItems">
</div>
<div class="bg-gray-200 mt-3 h-px" />
<div <div
v-for="(content, index) in item.content" class="timeline-card p-10 h-80 w-104 shadow-xl rounded-lg cursor-pointer"
:key="index" :class="{ 'timeline-card-current': currentIndex === index }"
class="card-content text-gray-600 relative pt-5 pl-5"> @click="selectTime(index)">
{{ content }} <div class="w-full text-gray-600 font-semibold text-2xl">
{{ item.title }}
</div>
<div class="bg-gray-200 mt-3 h-px" />
<el-timeline class="mt-5">
<el-timeline-item
v-for="(content, index) in item.content"
:key="index"
color="var(--el-color-primary-light-3)">
{{ content }}
</el-timeline-item>
</el-timeline>
</div> </div>
</div> </div>
</div> </div>
</VueSlickCarousel> </div>
</div> </div>
</template> </template>
<script> <script>
// vue-slick 组件中文文档: https://www.cnblogs.com/isylar/p/11103570.html
// vue-slick 组件官方文档: https://gs-shop.github.io/vue-slick-carousel/#/
import VueSlickCarousel from 'vue-slick-carousel'
import 'vue-slick-carousel/dist/vue-slick-carousel.css'
// optional style for arrows & dots
import 'vue-slick-carousel/dist/vue-slick-carousel-theme.css'
export default { export default {
components: {
VueSlickCarousel,
},
data() { data() {
return { return {
// VueSlickCarousel 设置
settings: {
arrows: false,
dots: false,
centerMode: true,
focusOnSelect: true,
infinite: true, // 这里使用false会导致后半内容无法居中
slidesToShow: 3,
autoplay: false,
},
timelineItems: [ timelineItems: [
{ {
title: '2022年', title: '2022年',
...@@ -82,31 +70,78 @@ export default { ...@@ -82,31 +70,78 @@ export default {
}, },
], ],
currentIndex: 0, currentIndex: 0,
translateX: 0,
cardGap: 80, // gap-20 = 5rem = 80px
} }
}, },
methods: { methods: {
selectTime(index) { selectTime(index) {
this.currentIndex = index this.currentIndex = index
this.$refs.slick.goTo(index) this.centerCard(index)
}, },
beforeChange(oldindex, index) { beforeChange(oldindex, index) {
this.currentIndex = index this.currentIndex = index
this.centerCard(index)
},
centerCard(index) {
this.$nextTick(() => {
if (!this.$refs.cardsContainer || !this.$refs.cardItems) {
return
}
const container = this.$refs.cardsContainer
const containerWidth = container.offsetWidth
const cardItems = this.$refs.cardItems
if (!cardItems || cardItems.length === 0) {
return
}
// 获取第一个卡片的宽度(所有卡片宽度相同)
const cardWidth = cardItems[0].offsetWidth
const cardGap = this.cardGap
// 计算目标卡片的位置
// 每个卡片的位置 = index * (cardWidth + cardGap)
const targetCardLeft = index * (cardWidth + cardGap)
// 计算需要移动的距离,使目标卡片居中
// 容器中心位置 = containerWidth / 2
// 目标卡片中心位置 = targetCardLeft + cardWidth / 2
// translateX = 容器中心 - 目标卡片中心
const containerCenter = containerWidth / 2
const targetCardCenter = targetCardLeft + cardWidth / 2
this.translateX = containerCenter - targetCardCenter
})
}, },
}, },
created() { created() {
this.currentIndex = this.timelineItems.length - 1 this.currentIndex = this.timelineItems.length - 1
}, },
mounted() {
// 初始化时居中显示当前卡片
this.centerCard(this.currentIndex)
// 监听窗口大小变化,重新计算位置
this.handleResize = () => {
this.centerCard(this.currentIndex)
}
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
// 清理事件监听器
if (this.handleResize) {
window.removeEventListener('resize', this.handleResize)
}
},
watch: {
currentIndex(newIndex) {
this.centerCard(newIndex)
},
},
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep .slick-list {
overflow: visible !important;
}
::v-deep .slick-slide {
outline: none; /* 防止点击时出现默认 outline 导致“深色”闪烁感 */
}
.timeline-dot { .timeline-dot {
width: 20px; width: 20px;
height: 20px; height: 20px;
...@@ -128,6 +163,31 @@ export default { ...@@ -128,6 +163,31 @@ export default {
background-color: var(--light-color); background-color: var(--light-color);
} }
.timeline-cards-container {
width: 100%;
overflow-x: hidden;
overflow-y: visible;
position: relative;
padding: 10px 0 50px 0;
}
.timeline-cards-wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
will-change: transform;
}
.timeline-card-item {
flex-shrink: 0;
margin-right: 80px; // gap-20 = 5rem = 80px
&:last-child {
margin-right: 0;
}
}
.timeline-card { .timeline-card {
border: 1px solid transparent; border: 1px solid transparent;
background-image: linear-gradient( background-image: linear-gradient(
...@@ -149,17 +209,7 @@ export default { ...@@ -149,17 +209,7 @@ export default {
border-color: rgba(153, 151, 148, 0.548); border-color: rgba(153, 151, 148, 0.548);
} }
.card-content { ::v-deep .el-timeline-item__tail {
&::before { border-left: 1px solid var(--el-color-primary-light-5) !important;
background-color: var(--primary-color);
border-radius: 50%;
position: absolute;
left: 5px;
top: 30px;
content: '';
width: 6px;
height: 6px;
box-shadow: 0 0 0 5px var(--shadow-color);
}
} }
</style> </style>
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
</div> </div>
</div> </div>
<div class="h-full py-10" ref="tabsSection"> <div class="h-full py-10" ref="tabsSection">
<div class="pb-10 w-1/2 m-auto flex justify-center items-center gap-20"> <div class="pt-10 w-full m-auto flex justify-center items-center gap-20">
<div <div
class="product-tabs-item w-52 font-semibold text-gray-500 flex flex-col items-center gap-2 cursor-pointer" class="product-tabs-item w-52 font-semibold text-gray-500 flex flex-col items-center gap-2 cursor-pointer"
:class="{ active: activeTab === item.key }" :class="{ active: activeTab === item.key }"
......
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