feat: 实现商品详情页、用户信息页面和搜索功能
refactor: 重构商品列表和主页布局 style: 优化UI组件样式和交互效果 docs: 更新类型定义和路由配置 fix: 修复购物车商品重复问题 perf: 提升页面加载性能和响应速度 test: 添加商品详情页和搜索功能的测试用例 build: 更新依赖项以支持新功能 chore: 清理无用代码和文件
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
<Herde></Herde>
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterView } from "vue-router";
|
import { RouterView } from "vue-router";
|
||||||
|
import Herde from "@/Views/Herde.vue";
|
||||||
|
import './Style/App.css'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ import { createRouter, createWebHistory } from 'vue-router'
|
|||||||
// 导入组件
|
// 导入组件
|
||||||
import Home from '../Views/Home.vue'
|
import Home from '../Views/Home.vue'
|
||||||
import Login from '../Views/Login.vue'
|
import Login from '../Views/Login.vue'
|
||||||
|
import Search from '../Views/Search.vue'
|
||||||
|
import ProductDetail from '../Views/product/productdetil.vue'
|
||||||
|
import Cart from '../Views/Cart.vue'
|
||||||
|
import Order from '../Views/Order.vue'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@@ -10,11 +16,31 @@ const routes = [
|
|||||||
name: 'home',
|
name: 'home',
|
||||||
component: Home
|
component: Home
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/search',
|
||||||
|
name: 'search',
|
||||||
|
component: Search
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/product',
|
||||||
|
name: 'productDetail',
|
||||||
|
component: ProductDetail
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: Login
|
component: Login
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/cart',
|
||||||
|
name: 'cart',
|
||||||
|
component: Cart
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/order',
|
||||||
|
name: 'order',
|
||||||
|
component: Order
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
13
src/Style/App.css
Normal file
13
src/Style/App.css
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/* 全局样式 */
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
@@ -7,6 +7,45 @@ export type ProductDetail = {
|
|||||||
price: string
|
price: string
|
||||||
img: string
|
img: string
|
||||||
}
|
}
|
||||||
|
// 店铺详情类型
|
||||||
|
export type ShopDetail = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
img: string
|
||||||
|
}
|
||||||
|
// 购物车类型
|
||||||
|
export type Cart = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
price: string
|
||||||
|
img: string
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
|
||||||
|
// 商品类型
|
||||||
|
export type Product = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
price: string
|
||||||
|
img: string
|
||||||
|
model: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 订单详情类型
|
||||||
|
export type OrderDetail = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
price: string
|
||||||
|
img: string
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
// 注册类型
|
||||||
|
export type Register = {
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
confirmPassword: string
|
||||||
|
}
|
||||||
|
// 登录类型
|
||||||
export type Login = {
|
export type Login = {
|
||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
|
|||||||
1377
src/Views/Cart.vue
Normal file
1377
src/Views/Cart.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="home">
|
<div id="home">
|
||||||
<Header></Header>
|
|
||||||
<Main></Main>
|
<Main></Main>
|
||||||
<Footer></Footer>
|
<Footer></Footer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Header from "./herde.vue";
|
import Main from "@/Views/Main.vue";
|
||||||
import Main from "./main.vue";
|
import Footer from "@/Views/Footer.vue";
|
||||||
import Footer from "./footer.vue";
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
|
||||||
#home {
|
|
||||||
height: 100%;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
2
src/Views/Myttw.vue
Normal file
2
src/Views/Myttw.vue
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<!-- 我的ttw -->
|
||||||
|
<!-- 页面布局 左边 导航栏有二级菜单 可以跳转很多页面 列如订单页面 购物车等 -->
|
||||||
18
src/Views/Order.vue
Normal file
18
src/Views/Order.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!-- 订单页面 -->
|
||||||
|
<template>
|
||||||
|
<div id="order">
|
||||||
|
<h1>订单</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { Button, Col, Row, Carousel } from 'ant-design-vue';
|
||||||
|
const router = useRouter()
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
#order {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
46
src/Views/Search.vue
Normal file
46
src/Views/Search.vue
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<!-- 搜索结果页面 -->
|
||||||
|
<template>
|
||||||
|
<div id="search-container">
|
||||||
|
<productList :productList="productLists" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import productList from './product/productList.vue'
|
||||||
|
import Herde from "@/Views/Herde.vue";
|
||||||
|
import router from '@/Route/route';
|
||||||
|
|
||||||
|
const productLists = ref([
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '商品1',
|
||||||
|
price: '100',
|
||||||
|
img: 'https://example.com/product1.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '商品2',
|
||||||
|
price: '200',
|
||||||
|
img: 'https://example.com/product2.jpg',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '商品3',
|
||||||
|
price: '300',
|
||||||
|
img: 'https://example.com/product3.jpg',
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
// 监听路由参数变化
|
||||||
|
watch(() => router.currentRoute.value.query.keyword, (newValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
// 根据关键词搜索商品
|
||||||
|
//data(newValue)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
#search-container {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
19
src/Views/Shop.vue
Normal file
19
src/Views/Shop.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- 店铺详情 -->
|
||||||
|
<template>
|
||||||
|
<div id="shop-detail">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { type PropType } from 'vue'
|
||||||
|
import type { ShopDetail } from '@/Util/Type'
|
||||||
|
import { useGlobalStore } from '@/Util/globalStore'
|
||||||
|
import router from '@/Route/route'
|
||||||
|
// 接收父类传递的店铺详情
|
||||||
|
const props = defineProps({
|
||||||
|
shopDetail: {
|
||||||
|
type: Object as PropType<ShopDetail>,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
29
src/Views/User/Userinfo.vue
Normal file
29
src/Views/User/Userinfo.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!-- 用户信息 -->
|
||||||
|
<!-- 布局 从上到下 user信息:用户头像 用户名 -->
|
||||||
|
<template>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-info-top">
|
||||||
|
<div class="user-avatar">
|
||||||
|
<!-- <img :src="user.avatar" alt="用户头像"> -->
|
||||||
|
</div>
|
||||||
|
<div class="user-name">
|
||||||
|
<div>用户名:</div>
|
||||||
|
<div>关注店铺 收货地址</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-info-main">
|
||||||
|
<div>
|
||||||
|
购物信息 :购物车 待收货 代发货 待付款
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
订单信息 :已完成 待评价 待付款 待发货
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
优惠 :红包 优惠卷 淘币
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
足迹信息 : 已买完 收藏夹 购买过的店 足迹信息
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -42,12 +42,23 @@ const productLists = ref([
|
|||||||
price: '400',
|
price: '400',
|
||||||
img: '',
|
img: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '商品4',
|
||||||
|
price: '400',
|
||||||
|
img: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '商品4',
|
||||||
|
price: '400',
|
||||||
|
img: '',
|
||||||
|
},
|
||||||
])
|
])
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#footer {
|
#footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #f5f5f5;
|
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
|
|||||||
@@ -2,26 +2,88 @@
|
|||||||
<div id="header">
|
<div id="header">
|
||||||
<div id="header-profile">
|
<div id="header-profile">
|
||||||
<div id="header-profile-left">
|
<div id="header-profile-left">
|
||||||
<!-- 登录 注册 -->
|
<!-- 用户信息悬浮菜单 -->
|
||||||
<Button type="primary" @click="router.push('/login')">登录</Button>
|
<Dropdown :menu="{ items: userMenu }" trigger="hover">
|
||||||
<Button type="primary" @click="router.push('/register')">注册</Button>
|
<div class="user-info-container">
|
||||||
|
<Avatar size="large" src="https://api.dicebear.com/7.x/avataaars/svg?seed=user123" />
|
||||||
|
<span class="user-name">用户名</span>
|
||||||
|
<span class="user-arrow">▼</span>
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div id="header-profile-right">
|
<div id="header-profile-right">
|
||||||
<!-- 购物车 个人中心 -->
|
<!-- 右侧功能菜单 -->
|
||||||
|
<Dropdown :menu="{ items: rightMenu }" trigger="hover">
|
||||||
|
<Button type="text">更多</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<a href="/">首页</a>
|
||||||
<Button type="primary" @click="router.push('/cart')">购物车</Button>
|
<Button type="primary" @click="router.push('/cart')">购物车</Button>
|
||||||
<Button type="primary" @click="router.push('/user')">个人中心</Button>
|
<Button type="primary" @click="router.push('/order')">订单</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Row id="header-nav-row">
|
<Row id="header-nav-row" v-if="booleanSearch">
|
||||||
<Col :span="4">
|
<Col class="header-nav-Logo" :span="4">
|
||||||
<a href="/">TaoTaoWang</a>
|
<a href="/">TaoTaoWang</a>
|
||||||
</Col>
|
</Col>
|
||||||
<Col :span="16">
|
<Col class="header-nav-search" :span="16">
|
||||||
<a-input-search v-model:value="value" placeholder="请输入" style="width: 200px"
|
<div class="search-input-container" :class="{ 'search-focused': showHistory }">
|
||||||
@search="onSearch" />
|
<div class="search-wrapper">
|
||||||
|
<!-- 搜索类型选择 -->
|
||||||
|
<div class="search-type-selector">
|
||||||
|
<ul>
|
||||||
|
<li class="search-type-item active" @click="setSearchType('宝贝')">宝贝</li>
|
||||||
|
<li class="search-type-item" @click="setSearchType('店铺')">店铺</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 搜索输入区域 -->
|
||||||
|
<div class="search-input-wrapper">
|
||||||
|
<div class="search-input-prefix">
|
||||||
|
<i class="iconfont icon-sousuo prefix-icon"></i>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
v-model:value="searchValue"
|
||||||
|
placeholder="请输入搜索关键词"
|
||||||
|
style="width: 100%"
|
||||||
|
@search="onSearch"
|
||||||
|
@focus="onInputFocus"
|
||||||
|
@blur="onInputBlur"
|
||||||
|
class="custom-search-input"
|
||||||
|
/>
|
||||||
|
<div class="search-input-suffix" v-if="searchValue">
|
||||||
|
<i class="iconfont icon-guanbi" @click="clearSearch"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 搜索按钮 -->
|
||||||
|
<div class="search-button-container" @onclick="onSearch">
|
||||||
|
<span class="search-button-text">搜索</span>
|
||||||
|
<div class="search-button-icon">
|
||||||
|
<i class="iconfont icon-sousuo"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-history-container" v-if="showHistory">
|
||||||
|
<div class="search-history-header">
|
||||||
|
<span class="history-title">搜索历史</span>
|
||||||
|
<a class="clear-history" @click="clearHistory" href="javascript:void(0)">
|
||||||
|
清空历史
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="search-history-tags" v-if="historyList.length > 0">
|
||||||
|
<Tag v-for="(item, index) in historyList" :key="index" class="history-tag" @click="onClickHistory(item)">
|
||||||
|
{{ item }}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
<div class="no-history" v-else>
|
||||||
|
暂无搜索历史
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col :span="4">
|
<Col class="header-nav-product" :span="4">
|
||||||
<a href="/product">商品列表</a>
|
<a href="#">随便放点东西显得对称</a>
|
||||||
|
<!-- 其他页面的时候修改布局 -->
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,31 +92,157 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Button, Col, Row ,Space } from 'ant-design-vue';
|
import { Button, Col, Row, Space, Dropdown, Avatar, Menu, Divider, Tag } from 'ant-design-vue';
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
// 定义搜索框绑定的变量
|
// 定义搜索框绑定的变量
|
||||||
const value = ref('')
|
const searchValue = ref('')
|
||||||
|
// 控制历史记录显示状态
|
||||||
|
const showHistory = ref(false)
|
||||||
|
// 标志:是否正在清空历史记录
|
||||||
|
const isClearingHistory = ref(false)
|
||||||
|
// 标志:是否在搜索界面
|
||||||
|
const booleanSearch = ref(true)
|
||||||
|
// 路由事件
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
if (to.name === 'search' && to.query.keyword) {
|
||||||
|
searchValue.value = to.query.keyword as string
|
||||||
|
}
|
||||||
|
console.log(to.name)
|
||||||
|
// 如果在商品页面 隐藏搜索框
|
||||||
|
if (to.name === 'productDetail') {
|
||||||
|
booleanSearch.value = false
|
||||||
|
} else {
|
||||||
|
booleanSearch.value = true
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
})
|
||||||
// 定义搜索框的搜索事件
|
// 定义搜索框的搜索事件
|
||||||
const onSearch = (value: string) => {
|
const onSearch = (value: string) => {
|
||||||
console.log('搜索关键词:', value)
|
console.log('搜索关键词:', value)
|
||||||
|
// 跳转到搜索结果页面
|
||||||
|
if (value.trim()) {
|
||||||
|
// 添加到历史记录
|
||||||
|
if (!historyList.value.includes(value)) {
|
||||||
|
historyList.value.unshift(value)
|
||||||
|
// 限制历史记录数量
|
||||||
|
if (historyList.value.length > 10) {
|
||||||
|
historyList.value.pop()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// 判断是否在搜索界面 如果不在 则跳转到搜索界面 如果在搜索界面 则更新查询参数
|
||||||
|
if (router.currentRoute.value.name !== 'search') {
|
||||||
|
router.push({ name: 'search', query: { keyword: value } })
|
||||||
|
} else {
|
||||||
|
router.push({ name: 'search', query: { keyword: value } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索历史记录
|
||||||
|
const historyList = ref(['手机', '电脑', '耳机', '键盘', '鼠标'])
|
||||||
|
|
||||||
|
// 清空历史记录
|
||||||
|
const clearHistory = () => {
|
||||||
|
isClearingHistory.value = true
|
||||||
|
historyList.value = []
|
||||||
|
// 300ms后重置标志,确保onInputBlur的200ms延迟执行完毕
|
||||||
|
setTimeout(() => {
|
||||||
|
isClearingHistory.value = false
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击历史记录
|
||||||
|
const onClickHistory = (item: string) => {
|
||||||
|
searchValue.value = item
|
||||||
|
onSearch(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索框获得焦点
|
||||||
|
const onInputFocus = () => {
|
||||||
|
showHistory.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索框失去焦点
|
||||||
|
const onInputBlur = () => {
|
||||||
|
// 使用setTimeout确保点击历史记录的事件能先执行
|
||||||
|
setTimeout(() => {
|
||||||
|
// 如果正在清空历史记录,则不隐藏历史记录容器
|
||||||
|
if (!isClearingHistory.value) {
|
||||||
|
showHistory.value = false
|
||||||
|
}
|
||||||
|
}, 200)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置搜索类型
|
||||||
|
const setSearchType = (type: string) => {
|
||||||
|
const typeItems = document.querySelectorAll('.search-type-item')
|
||||||
|
typeItems.forEach(item => {
|
||||||
|
item.classList.remove('active')
|
||||||
|
})
|
||||||
|
// 添加active类到点击的元素
|
||||||
|
// event?.currentTarget?.classList.add('active')
|
||||||
|
console.log('搜索类型:', type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除搜索输入
|
||||||
|
const clearSearch = () => {
|
||||||
|
searchValue.value = ''
|
||||||
|
console.log('已清除搜索输入')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 左侧用户菜单
|
||||||
|
const userMenu = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: '个人中心'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: '设置'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: '退出登录',
|
||||||
|
danger: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 右侧功能菜单
|
||||||
|
const rightMenu = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: '浏览记录'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: '收藏夹'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: '帮助中心'
|
||||||
|
}
|
||||||
|
]
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#header {
|
#header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #f5f5f5;
|
background-color: #ffffff;
|
||||||
padding: 0 20px;
|
padding: 10px 20px;
|
||||||
|
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */
|
||||||
|
position: relative;
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
#header-nav-row {
|
||||||
color: #42b983;
|
height: 60px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-profile {
|
#header-profile {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 60px;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-profile-left {
|
#header-profile-left {
|
||||||
@@ -63,17 +251,512 @@ h1 {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-profile-left>button {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header-profile-right {
|
#header-profile-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header-profile-right>button {
|
/* 用户信息容器样式 */
|
||||||
margin-left: 10px;
|
.user-info-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-container:hover {
|
||||||
|
background-color: #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-arrow {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-container:hover .user-arrow {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo样式 */
|
||||||
|
.header-nav-Logo a {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #1890ff;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-nav-Logo a:hover {
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索框样式 */
|
||||||
|
.header-nav-search {
|
||||||
|
padding: 0 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container.search-focused {
|
||||||
|
/* box-shadow: 0 4px 16px rgba(255, 80, 0, 0.2); */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索框整体布局 */
|
||||||
|
.search-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 2px solid #e8e8e8;
|
||||||
|
border-radius: 28px;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container.search-focused .search-wrapper {
|
||||||
|
border-color: #ff5000;
|
||||||
|
box-shadow: 0 4px 20px rgba(255, 80, 0, 0.2);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索类型选择器 */
|
||||||
|
.search-type-selector {
|
||||||
|
padding: 3.5px 16px;
|
||||||
|
border-right: 1px solid #e8e8e8;
|
||||||
|
background-color: #fafafa;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
border-radius: 28px 0 0 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-selector:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-selector ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item {
|
||||||
|
padding: 14px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
position: relative;
|
||||||
|
user-select: none;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item.active {
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item.active::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 8px;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #ff5000;
|
||||||
|
border-radius: 1px;
|
||||||
|
animation: slideIn 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
width: 0;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索输入区域 */
|
||||||
|
.search-input-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-prefix {
|
||||||
|
position: absolute;
|
||||||
|
left: 16px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #999;
|
||||||
|
font-size: 18px;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container.search-focused .search-input-prefix {
|
||||||
|
color: #ff5000;
|
||||||
|
transform: translateY(-50%) scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search-input {
|
||||||
|
font-size: 16px;
|
||||||
|
min-height: 52px;
|
||||||
|
height: 52px;
|
||||||
|
padding: 0 50px 0 48px;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: transparent;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
box-sizing: border-box; /* 关键! */
|
||||||
|
outline: none; /* 避免默认焦点轮廓 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 可选:焦点状态 */
|
||||||
|
.custom-search-input:focus {
|
||||||
|
background-color: rgba(255, 255, 255, 0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search-input::placeholder {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search-input:focus {
|
||||||
|
border-color: transparent !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container.search-focused .custom-search-input::placeholder {
|
||||||
|
color: #ffccb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-suffix {
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
color: #999;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeIn 0.3s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-50%) scale(0.8);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-50%) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-suffix:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
background-color: #fff0e6;
|
||||||
|
transform: translateY(-50%) scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-container.search-focused .search-input-suffix {
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索按钮 */
|
||||||
|
.search-button-container {
|
||||||
|
margin-right: 1px;
|
||||||
|
padding: 15.5px;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, #ff5000, #ff8c00);
|
||||||
|
color: #ffffff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 600;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 0 28px 28px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.search-button-container:active {
|
||||||
|
transform: translateX(1px) translateY(0);
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
animation: shine 2.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @keyframes shine {
|
||||||
|
0% {
|
||||||
|
transform: rotate(45deg) translateX(-100%) translateY(-100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(45deg) translateX(100%) translateY(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
.search-button-text {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-icon {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container:hover .search-button-icon {
|
||||||
|
transform: scale(1.1) rotate(15deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container:hover .search-button-text {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式调整 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.search-type-selector {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-selector ul {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item {
|
||||||
|
padding: 12px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-wrapper {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search-input {
|
||||||
|
font-size: 14px !important;
|
||||||
|
height: 48px !important;
|
||||||
|
padding: 0 40px 0 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-prefix {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container {
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-text {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container:hover .search-button-icon {
|
||||||
|
transform: scale(1.05) rotate(10deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.search-type-selector {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-selector ul {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-type-item {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-wrapper {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-search-input {
|
||||||
|
font-size: 13px !important;
|
||||||
|
padding: 0 35px 0 35px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input-prefix {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-container {
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-text {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索历史样式 */
|
||||||
|
.search-history-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
z-index: 100;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-history {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-history:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-history-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-tag {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history-tag:hover {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
border-color: #91d5ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-history {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品列表链接样式 */
|
||||||
|
.header-nav-product a {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-nav-product a:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
background-color: #e6f7ff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,45 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="main-header">
|
<div id="main-header">
|
||||||
<Button type="primary" @click="router.push('/')">按钮1</Button>
|
|
||||||
<Button type="primary" @click="router.push('/list')">按钮2</Button>
|
|
||||||
<Button type="primary" @click="router.push('/cart')">按钮3</Button>
|
|
||||||
<Button type="primary" @click="router.push('/history')">按钮4</Button>
|
|
||||||
<Button type="primary" @click="router.push('/user')">按钮5</Button>
|
|
||||||
<Button type="primary" @click="router.push('/login')">按钮6</Button>
|
|
||||||
<Button type="primary" @click="router.push('/register')">按钮7</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Row id="main-content">
|
<Row id="main-content" :wrap="false">
|
||||||
<Col class="main-content-col-top" :span="6">
|
<Col class="main-content-col-top" :span="4">
|
||||||
<h2>商品列表</h2>
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<!-- 分类项 -->
|
||||||
|
<div class="category-item">
|
||||||
|
<i class="iconfont icon-zhineng"></i>
|
||||||
|
<a href="http://localhost:5173/search?keyword=电脑" >电脑</a>
|
||||||
|
<span>/</span>
|
||||||
|
<a href="http://localhost:5173/search?keyword=配件" >配件</a>
|
||||||
|
<span>/</span>
|
||||||
|
<a href="http://localhost:5173/search?keyword=办公" >办公</a>
|
||||||
|
<span>/</span>
|
||||||
|
<a href="http://localhost:5173/search?keyword=文具" >文具</a>
|
||||||
|
</div>
|
||||||
|
<!-- 分类详情 -->
|
||||||
|
<div v-if="true" class="category-detail">
|
||||||
|
<ul>
|
||||||
|
<li class="category-detail-item">
|
||||||
|
<a href="http://localhost:5173/search?keyword=电脑整机">电脑整机</a>
|
||||||
|
<span >></span>
|
||||||
|
<a href="http://localhost:5173/search?keyword=笔记本" >笔记本</a>
|
||||||
|
<a href="http://localhost:5173/search?keyword=台式机" >台式机</a>
|
||||||
|
<a href="http://localhost:5173/search?keyword=服务器" >服务器</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col class="main-content-col-center" :span="12">
|
<Col class="main-content-col-center" :span="15">
|
||||||
<Row id="main-content-ad">
|
<!-- 轮动广告 -->
|
||||||
<Col :span="12">
|
<div id="carousel-container">
|
||||||
<h2>轮动广告</h2>
|
<Carousel autoplay :dots="true" effect="fade" :autoplay-speed="3000">
|
||||||
|
<div v-for="ad in adList" :key="ad.id" class="carousel-item">
|
||||||
|
<a :href="ad.link" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img :src="ad.image" :alt="ad.title" class="carousel-image" />
|
||||||
|
<div class="carousel-title">{{ ad.title }}</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</Carousel>
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col :span="12">
|
<Col class="main-content-col-bottom" :span="4">
|
||||||
<h2>百亿补贴</h2>
|
<UserInfo />
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row id="main-content-hot-goods">
|
|
||||||
<!-- 热门商品展示 -->
|
|
||||||
<Col :span="6">
|
|
||||||
<h2>热门商品1</h2>
|
|
||||||
</Col>
|
|
||||||
<Col :span="6">
|
|
||||||
<h2>热门商品2</h2>
|
|
||||||
</Col>
|
|
||||||
<Col :span="6">
|
|
||||||
<h2>热门商品3</h2>
|
|
||||||
</Col>
|
|
||||||
<Col :span="6">
|
|
||||||
<h2>热门商品4</h2>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Col>
|
|
||||||
<Col class="main-content-col-bottom" :span="6">
|
|
||||||
<h2>个人信息</h2>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,22 +57,382 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Button, Col, Row } from 'ant-design-vue';
|
import { Button, Col, Row, Carousel } from 'ant-design-vue';
|
||||||
|
import UserInfo from '@/Views/User/Userinfo.vue'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
// 按钮数据数组
|
||||||
|
const buttonList = [
|
||||||
|
{ id: 1, text: '按钮1', route: '/' },
|
||||||
|
{ id: 2, text: '按钮2', route: '/list' },
|
||||||
|
{ id: 3, text: '按钮3', route: '/cart' },
|
||||||
|
{ id: 4, text: '按钮4', route: '/history' },
|
||||||
|
{ id: 5, text: '按钮5', route: '/user' },
|
||||||
|
{ id: 6, text: '按钮6', route: '/login' },
|
||||||
|
{ id: 7, text: '按钮7', route: '/register' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 广告数据
|
||||||
|
const adList = [
|
||||||
|
{ id: 1, title: '广告1', image: 'https://picsum.photos/id/237/800/300', link: '#' },
|
||||||
|
{ id: 2, title: '广告2', image: 'https://picsum.photos/id/238/800/300', link: '#' },
|
||||||
|
{ id: 3, title: '广告3', image: 'https://picsum.photos/id/239/800/300', link: '#' }
|
||||||
|
]
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#main {
|
#main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
color: #42b983;
|
color: #42b983;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main-header {
|
#main-header {
|
||||||
/* 根据中心对齐 分布按钮 */
|
/* 根据中心对齐 分布按钮 */
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 10px;
|
align-items: center;
|
||||||
padding: 8px 0;
|
gap: 20px;
|
||||||
|
padding: 16px 0;
|
||||||
|
width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-header .ant-btn {
|
||||||
|
width: 120px;
|
||||||
|
height: 45px;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-header .ant-btn-primary {
|
||||||
|
background-color: #1890ff;
|
||||||
|
border-color: #1890ff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-header .ant-btn-primary:hover {
|
||||||
|
background-color: #40a9ff;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
|
||||||
|
}
|
||||||
|
/* 商品分类样式 */
|
||||||
|
.main-content-col-top {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top:hover {
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes shine {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
20% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top li {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分类详情样式 */
|
||||||
|
.main-content-col-top li:hover {
|
||||||
|
background-color: #fff5f5;
|
||||||
|
transform: translateX(8px);
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分类项样式 */
|
||||||
|
.category-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-item:hover {
|
||||||
|
background-color: rgba(255, 80, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分类详情样式 */
|
||||||
|
.category-detail {
|
||||||
|
position: absolute;
|
||||||
|
left: 100%;
|
||||||
|
top: -60px;
|
||||||
|
width: 600px;
|
||||||
|
height: 400px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
padding: 20px;
|
||||||
|
margin-left: 10px;
|
||||||
|
z-index: 9999;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transform: translateX(-20px);
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
border: 2px solid #f0f0f0;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 悬停显示分类详情 */
|
||||||
|
.main-content-col-top li:hover .category-detail {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 1px solid #f5f5f5;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
padding-left: 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item a {
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item a:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
transform: translateX(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item a::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 1px;
|
||||||
|
background-color: #ff5000;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item a:hover::after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-detail-item span {
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top .iconfont {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #ff5000;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top li:hover .iconfont {
|
||||||
|
transform: scale(1.1) rotate(5deg);
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #333;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
position: relative;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top a:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
background-color: rgba(255, 80, 0, 0.1);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top span {
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-top li:hover span {
|
||||||
|
color: #ff5000;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主内容区域样式 */
|
||||||
|
#main-content {
|
||||||
|
margin-top: 20px;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-center{
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-center h2{
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-content-ad,
|
||||||
|
#main-content-hot-goods {
|
||||||
|
padding: 0 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-content-ad .ant-col,
|
||||||
|
#main-content-hot-goods .ant-col {
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-content-ad .ant-col:hover,
|
||||||
|
#main-content-hot-goods .ant-col:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
/* 轮播广告样式 */
|
||||||
|
#carousel-container {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-item:hover .carousel-image {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-title {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-carousel .slick-dots {
|
||||||
|
bottom: 20px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-carousel .slick-dots li button {
|
||||||
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-carousel .slick-dots li.slick-active button {
|
||||||
|
background-color: #ffffff;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 个人信息样式 */
|
||||||
|
.main-content-col-bottom {
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content-col-bottom h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 16px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,21 +1,23 @@
|
|||||||
<!-- 根据父类传递的商品列表渲染商品列表 -->
|
<!-- 根据父类传递的商品列表渲染商品列表 -->
|
||||||
<template>
|
<template>
|
||||||
<div id="product-list">
|
<div id="product-list">
|
||||||
<div id="product-list-header" v-for="product in productList" :key="product.id">
|
<div class="product-item" v-for="product in productList" :key="product.id">
|
||||||
<!-- 这个商品的id是加密 -->
|
<!-- 这个商品的id是加密 -->
|
||||||
<a href="http://localhost:5173/product/{{ product.id }}" target="_blank">
|
<div class="product-img-container" @click="handleClick(product)">
|
||||||
<div id="product-list-header-img">
|
<img class="product-img" :src="product.img || '/0.png'" alt="商品图片">
|
||||||
<img class="product-list-header-img" :src="product.img || '/0.png'" alt="商品图片">
|
<div class="product-img-mask">
|
||||||
<div class="product-list-header-img-mask">
|
<div class="product-img-actions">
|
||||||
|
<span class="action-btn">查看详情</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="product-list-header-content">
|
|
||||||
<h2>{{ product.name }}</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="product-list-header-price">
|
<div class="product-content">
|
||||||
<h2>{{ product.price }}</h2>
|
<h3 class="product-name">{{ product.name }}</h3>
|
||||||
|
<div class="product-price">
|
||||||
|
<span class="price-symbol">¥</span>
|
||||||
|
<span class="price-value">{{ product.price }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
import { type PropType } from 'vue'
|
import { type PropType } from 'vue'
|
||||||
import type { ProductDetail } from '@/Util/Type'
|
import type { ProductDetail } from '@/Util/Type'
|
||||||
import { useGlobalStore } from '@/Util/globalStore'
|
import { useGlobalStore } from '@/Util/globalStore'
|
||||||
|
import router from '@/Route/route'
|
||||||
// 接收父类传递的商品列表
|
// 接收父类传递的商品列表
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
productList: {
|
productList: {
|
||||||
@@ -30,7 +33,13 @@ const props = defineProps({
|
|||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
// 点击商品跳转详情页
|
||||||
|
const handleClick = (product: ProductDetail) => {
|
||||||
|
// id 加密
|
||||||
|
const encryptedId = btoa(product.id)
|
||||||
|
// 跳转详情页 (新开页面)
|
||||||
|
window.open(`/product?id=${encryptedId}`, '_blank')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* 自定义css */
|
/* 自定义css */
|
||||||
@@ -39,47 +48,242 @@ const props = defineProps({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
/* 商品项 */
|
||||||
color: #42b983;
|
.product-item {
|
||||||
|
flex: 0 0 calc(16.666666% - 16.666666px);
|
||||||
|
max-width: calc(16.666666% - 16.666666px);
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 商品 */
|
.product-item:hover {
|
||||||
#product-list-header {
|
transform: translateY(-6px);
|
||||||
max-width: 16.666666666666%;
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
|
||||||
height: initial;
|
|
||||||
margin: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#product-list-header-img {
|
.product-item::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, #ff5000, #ff8c00);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品链接 */
|
||||||
|
.product-item a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品图片容器 */
|
||||||
|
.product-img-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 180px;
|
padding-top: 100%; /* 1:1 宽高比 */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
border-radius: 16px 16px 0 0;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-list-header-img {
|
.product-item:hover .product-img-container {
|
||||||
width: 100%;
|
background-color: #f0f0f0;
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 鼠标图片悬浮亮度变低 */
|
.product-img {
|
||||||
.product-list-header-img-mask {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 8px;
|
object-fit: cover;
|
||||||
background-color: transparent;
|
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
transition: all 0.3s ease;
|
|
||||||
z-index: 999999;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#product-list-header-img:hover .product-list-header-img-mask {
|
.product-item:hover .product-img {
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图片遮罩层 */
|
||||||
|
.product-img-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
border-radius: 16px 16px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .product-img-mask {
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图片悬停操作按钮 */
|
||||||
|
.product-img-actions {
|
||||||
|
transform: translateY(20px);
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .product-img-actions {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #ff5000;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.2);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:hover {
|
||||||
|
background-color: #ff5000;
|
||||||
|
color: #ffffff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(255, 80, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
animation: shine 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shine {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%) rotate(45deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%) rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品内容 */
|
||||||
|
.product-content {
|
||||||
|
padding: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .product-content {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .product-name {
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 商品价格 */
|
||||||
|
.product-price {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 6px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-symbol {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .price-symbol {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-value {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-item:hover .price-value {
|
||||||
|
transform: scale(1.05);
|
||||||
|
text-shadow: 0 1px 2px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式调整 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.product-item {
|
||||||
|
flex: 0 0 calc(20% - 16px);
|
||||||
|
max-width: calc(20% - 16px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 992px) {
|
||||||
|
.product-item {
|
||||||
|
flex: 0 0 calc(25% - 15px);
|
||||||
|
max-width: calc(25% - 15px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.product-item {
|
||||||
|
flex: 0 0 calc(33.333333% - 13.333333px);
|
||||||
|
max-width: calc(33.333333% - 13.333333px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.product-item {
|
||||||
|
flex: 0 0 calc(50% - 10px);
|
||||||
|
max-width: calc(50% - 10px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -1,27 +1,809 @@
|
|||||||
<!-- 商品详情页面 -->
|
<!-- 商品详情页面 -->
|
||||||
<template>
|
<template>
|
||||||
<div id="product-detail">
|
<div id="product-detail">
|
||||||
<van-row id="product-detail-header">
|
<div class="product-detail-container">
|
||||||
<van-col :span="24">
|
<div class="left-panel">
|
||||||
<h2>商品详情</h2>
|
<div class="shop-info">
|
||||||
</van-col>
|
<!-- 店铺信息 -->
|
||||||
</van-row>
|
<div>
|
||||||
|
<!-- 店铺头像 -->
|
||||||
|
<Avatar size="large" src="https://api.dicebear.com/7.x/avataaars/svg?seed=user123" />
|
||||||
|
</div>
|
||||||
|
<!-- 店铺名称 店铺评分 -->
|
||||||
|
<div class="shop-info-item">
|
||||||
|
<div class="shop-info-label">店铺名称
|
||||||
|
<div class="shop-info-detail">
|
||||||
|
<div class="shop-info-detail-item">
|
||||||
|
<div class="shop-info-detail-label">店铺详情</div>
|
||||||
|
<div class="shop-info-detail-value">店铺详情内容</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="shop-info-value">店铺评分</div>
|
||||||
|
</div>
|
||||||
|
<!-- 按钮 客服 进店 -->
|
||||||
|
<div class="shop-btn-group">
|
||||||
|
<a href="#" class="btn btn-primary"><i class="iconfont icon-kefu"></i><span>客服</span></a>
|
||||||
|
<a href="#" class="btn btn-primary"><i class="iconfont icon-xiangyou"></i><span>进店</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gallery-container">
|
||||||
|
<div class="thumbnails">
|
||||||
|
<div v-for="(img, index) in images" :key="index" class="thumbnail-item"
|
||||||
|
:class="{ active: currentIndex === index }" @click="selectImage(index)">
|
||||||
|
<img :src="img" :alt="'缩略图' + (index + 1)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="main-image">
|
||||||
|
<a-image class="main-image-container" :src="currentImage" alt="商品主图" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-container">
|
||||||
|
<div class="tab-header">
|
||||||
|
<a-anchor direction="horizontal" :items="tabs" class="tab-item" />
|
||||||
|
</div>
|
||||||
|
<div class="tab-content">
|
||||||
|
<!-- 评论 -->
|
||||||
|
<div id="reviews">
|
||||||
|
<h2>
|
||||||
|
评论
|
||||||
|
<a href="#reviews"></a>
|
||||||
|
</h2>
|
||||||
|
<div class="reviews-content">
|
||||||
|
<!-- 评论内容 -->
|
||||||
|
<h3>用户评论</h3>
|
||||||
|
<!-- 更多评论... -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 文图详情 -->
|
||||||
|
<div id="description">
|
||||||
|
<h2>
|
||||||
|
文图详情
|
||||||
|
<a href="#description"></a>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<!-- 参数信息 -->
|
||||||
|
<div id="specs">
|
||||||
|
<h2>
|
||||||
|
参数信息
|
||||||
|
<a href="#specs"></a>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<!-- 本店推荐 -->
|
||||||
|
<div id="recommendations">
|
||||||
|
<h2>
|
||||||
|
本店推荐
|
||||||
|
<a href="#recommendations"></a>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right-panel">
|
||||||
|
<div class="product-info">
|
||||||
|
<h1 class="product-title">BenQ 明基投影仪 商务办公会议培训用 1080P高清智能投影机</h1>
|
||||||
|
<div class="price-section">
|
||||||
|
<div class="price-row">
|
||||||
|
<span class="price-label">券后价</span>
|
||||||
|
<span class="price-value">{{ selectedModelInfo?.price }}</span>
|
||||||
|
<span class="original-price">{{ selectedModelInfo?.originalPrice }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tags">
|
||||||
|
<span class="tag">官方正品</span>
|
||||||
|
<span class="tag">全国包邮</span>
|
||||||
|
<span class="tag">7天无理由退换</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="model-selection">
|
||||||
|
<div class="selection-container">
|
||||||
|
<h3 class="selection-title">选择型号</h3>
|
||||||
|
<div class="view-switch" @click="toggleView">
|
||||||
|
<p>{{ isSmallView ? '切换为大视图' : '切换为小视图' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 图(小)文从左到右 -->
|
||||||
|
<div v-if="isSmallView" class="model-options-small">
|
||||||
|
<div v-for="model in models" :key="model.id" class="model-option"
|
||||||
|
:class="{ active: selectedModel === model.id }" @click="selectModel(model.id)">
|
||||||
|
<div class="model-small-item">
|
||||||
|
<img :src="model.img" alt="{{ model.name }}">
|
||||||
|
<span> {{ model.name }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 图(大)文 图上文下-->
|
||||||
|
<div v-if="!isSmallView" class="model-options-big">
|
||||||
|
<div v-for="model in models" :key="model.id" class="model-option"
|
||||||
|
:class="{ active: selectedModel === model.id }" @click="selectModel(model.id)">
|
||||||
|
<!-- 图片 -->
|
||||||
|
<div class="model-image">
|
||||||
|
<img :src="model.img" alt="{{ model.name }}">
|
||||||
|
</div>
|
||||||
|
<div class="model-name">{{ model.name }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="action-section">
|
||||||
|
<div class="action-buttons">
|
||||||
|
<div @click="addToCart" class="btn-cart">加入购物车</div>
|
||||||
|
<div @click="buyProduct" class="btn-buy">领券购买</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-collect" @click="collectProduct">
|
||||||
|
<i class="iconfont icon-xiangyou"></i>
|
||||||
|
收藏
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
// 根据路由获取商品id
|
|
||||||
const productId = ref(router.currentRoute.value.params.productId)
|
const productId = ref(router.currentRoute.value.params.productId)
|
||||||
// 在根据service获取商品详情
|
|
||||||
|
const currentIndex = ref(0)
|
||||||
|
const images = ref([
|
||||||
|
'/0.png',
|
||||||
|
'/0.png',
|
||||||
|
'/0.png',
|
||||||
|
'/0.png',
|
||||||
|
'/0.png'
|
||||||
|
])
|
||||||
|
|
||||||
|
const currentImage = computed(() => images.value[currentIndex.value])
|
||||||
|
|
||||||
|
const selectImage = (index: number) => {
|
||||||
|
currentIndex.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedModel = ref('x500')
|
||||||
|
const models = ref([
|
||||||
|
{ id: 'x500', name: 'X500', price: '999', originalPrice: '1999', img: '/0.png' },
|
||||||
|
{ id: 'w600', name: 'W600', price: '1299', originalPrice: '2499', img: '/0.png' },
|
||||||
|
{ id: 'e800', name: 'E800', price: '1599', originalPrice: '3299', img: '/0.png' }
|
||||||
|
])
|
||||||
|
|
||||||
|
const selectModel = (id: string) => {
|
||||||
|
selectedModel.value = id
|
||||||
|
}
|
||||||
|
const selectedModelInfo = computed(() => models.value.find(model => model.id === selectedModel.value))
|
||||||
|
|
||||||
|
const activeTab = ref('reviews')
|
||||||
|
const tabs = ref([
|
||||||
|
{
|
||||||
|
key: 'reviews',
|
||||||
|
href: '#reviews',
|
||||||
|
title: '评论',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'description',
|
||||||
|
href: '#description',
|
||||||
|
title: '文图详情',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'specs',
|
||||||
|
href: '#specs',
|
||||||
|
title: '参数信息',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'recommendations',
|
||||||
|
href: '#recommendations',
|
||||||
|
title: '本店推荐',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const isSmallView = ref(true)
|
||||||
|
|
||||||
|
const toggleView = () => {
|
||||||
|
isSmallView.value = !isSmallView.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const collectProduct = () => {
|
||||||
|
console.log('收藏商品')
|
||||||
|
}
|
||||||
|
|
||||||
|
const addToCart = () => {
|
||||||
|
console.log('加入购物车')
|
||||||
|
}
|
||||||
|
|
||||||
|
const buyProduct = () => {
|
||||||
|
console.log('领券购买')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#product-detail {
|
#product-detail {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 20px;
|
min-height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
}
|
}
|
||||||
h2 {
|
|
||||||
color: #42b983;
|
.product-detail-container {
|
||||||
|
display: flex;
|
||||||
|
border-radius: 16px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
width: 50%;
|
||||||
|
padding: 25px;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.shop-info-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-info-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-info-detail {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||||
|
z-index: 100;
|
||||||
|
min-width: 200px;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-info-item:hover .shop-info-detail {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-info-value {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.shop-btn-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-btn-group .btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-btn-group .btn-primary {
|
||||||
|
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-btn-group .btn-primary:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shop-btn-group .btn span {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-image {
|
||||||
|
flex: 1;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnails {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 400px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-item {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-item:hover {
|
||||||
|
border-color: #ff5000;
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-item.active {
|
||||||
|
border-color: #ff5000;
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-item img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel {
|
||||||
|
flex: 1;
|
||||||
|
padding: 35px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-title {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
border-bottom: 2px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-section {
|
||||||
|
background: linear-gradient(135deg, #fff5f5 0%, #ffe8e8 100%);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #ffcccc;
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.08);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-section:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-value {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.original-price {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #ff5000;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fff5f5 100%);
|
||||||
|
border: 1px solid #ff5000;
|
||||||
|
padding: 6px 14px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 2px 6px rgba(255, 80, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag:hover {
|
||||||
|
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-selection {
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
/* 切换视图 */
|
||||||
|
.view-switch {
|
||||||
|
/* 靠右对齐 */
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-switch:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
.model-options-small, .model-options-big {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-option {
|
||||||
|
flex: 0 0 120px;
|
||||||
|
border: 2px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-option:hover {
|
||||||
|
border-color: #ff5000;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-option.active {
|
||||||
|
border-color: #ff5000;
|
||||||
|
background: linear-gradient(135deg, #fff5f5 0%, #ffe8e8 100%);
|
||||||
|
box-shadow: 0 4px 16px rgba(255, 80, 0, 0.25);
|
||||||
|
transform: translateY(-3px);
|
||||||
|
}
|
||||||
|
.model-image {
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.model-image img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
.model-name {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.model-small-item {
|
||||||
|
text-align: left;
|
||||||
|
border-radius: 8px;
|
||||||
|
flex: 0 0 120px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
}
|
||||||
|
.model-small-item img {
|
||||||
|
margin: 5px;
|
||||||
|
height: 30px;
|
||||||
|
align-items: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-price {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 30px;
|
||||||
|
right: 30px;
|
||||||
|
z-index: 1000;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
padding: 18px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cart,
|
||||||
|
.btn-buy {
|
||||||
|
text-align: center;
|
||||||
|
width: 200px;
|
||||||
|
line-height: 48px;
|
||||||
|
flex: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cart {
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fff5f5 100%);
|
||||||
|
color: #ff5000;
|
||||||
|
border: 2px solid #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-cart:hover {
|
||||||
|
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-buy {
|
||||||
|
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-buy:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(255, 80, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-collect {
|
||||||
|
flex: 1;
|
||||||
|
line-height: 48px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fff5f5 100%);
|
||||||
|
color: #ff5000;
|
||||||
|
margin-left: 10px;
|
||||||
|
border: 2px solid #ff5000;
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 0 20px;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-collect:hover {
|
||||||
|
background: linear-gradient(135deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
color: #ffffff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auxiliary-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aux-item {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aux-item:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-header {
|
||||||
|
display: flex;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 18px 35px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item:hover {
|
||||||
|
color: #ff5000;
|
||||||
|
background-color: #fff5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: #fff5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #ff5000 0%, #ff6b00 100%);
|
||||||
|
box-shadow: 0 2px 8px rgba(255, 80, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
padding: 30px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-panel {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-item {
|
||||||
|
padding: 20px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reviewer {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-rating {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-table td {
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-table td:first-child {
|
||||||
|
background-color: #fafafa;
|
||||||
|
color: #666;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-table td:last-child {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnails::-webkit-scrollbar {
|
||||||
|
height: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnails::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnails::-webkit-scrollbar-thumb {
|
||||||
|
background: #ccc;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnails::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel::-webkit-scrollbar,
|
||||||
|
.right-panel::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel::-webkit-scrollbar-track,
|
||||||
|
.right-panel::-webkit-scrollbar-track {
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel::-webkit-scrollbar-thumb,
|
||||||
|
.right-panel::-webkit-scrollbar-thumb {
|
||||||
|
background: #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel::-webkit-scrollbar-thumb:hover,
|
||||||
|
.right-panel::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #999;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
226
src/Views/product/productmodal.vue
Normal file
226
src/Views/product/productmodal.vue
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<!-- 根据数组渲染产品详情弹窗 -->
|
||||||
|
<template>
|
||||||
|
<a-modal v-model:open="showModel" @ok="handleOk">
|
||||||
|
<div class="product-modal">
|
||||||
|
<div class="product-modal-container">
|
||||||
|
<div class="product-modal-right">
|
||||||
|
<div class="product-modal-img">
|
||||||
|
<img :src="currentProduct.img" alt="产品图片" class="product-modal-image">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="product-modal-left">
|
||||||
|
<div class="product-modal-top">
|
||||||
|
<div class="product-modal-price">
|
||||||
|
<span class="price-label">价格:</span>
|
||||||
|
<span class="price-value">¥{{ currentProduct.price }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="product-modal-bottom">
|
||||||
|
<h3 class="model-title">选择型号</h3>
|
||||||
|
<div class="model-list">
|
||||||
|
<div v-for="item in currentItems" :key="item.id" class="model-item"
|
||||||
|
:class="{ active: currentProduct.id === item.id }" @click="selectProduct(item)">
|
||||||
|
<div class="model-img">
|
||||||
|
<img :src="item.img" alt="型号图片" class="model-image">
|
||||||
|
</div>
|
||||||
|
<div class="model-name">{{ item.model }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch } from 'vue'
|
||||||
|
import type { Product } from '@/Util/Type';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
currentItems: {
|
||||||
|
type: Array as () => Product[],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
showModel: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const emit = defineEmits(['selectProduct', 'update:showModel'])
|
||||||
|
// 监听 showModel 变化 用于更新弹窗的显示状态
|
||||||
|
watch(() => props.showModel, (newVal) => {
|
||||||
|
showModel.value = newVal
|
||||||
|
})
|
||||||
|
const showModel = ref(false)
|
||||||
|
const currentProduct = ref<Product>(props.currentItems[0] || {} as Product)
|
||||||
|
// 选择型号 并触发事件 用于更新当前选中的型号
|
||||||
|
const selectProduct = (item: Product) => {
|
||||||
|
currentProduct.value = item
|
||||||
|
}
|
||||||
|
// 点击确认按钮 触发事件 用于更新父组件的 selectedModel
|
||||||
|
const handleOk = () => {
|
||||||
|
emit('selectProduct', currentProduct.value)
|
||||||
|
showModel.value = false
|
||||||
|
emit('update:showModel', false)
|
||||||
|
}
|
||||||
|
// 监听弹窗关闭事件
|
||||||
|
watch(() => showModel.value, (newVal) => {
|
||||||
|
emit('update:showModel', newVal)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.product-modal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-container {
|
||||||
|
display: flex;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-right {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10 15px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-img {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 200px;
|
||||||
|
max-height: 200px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-image:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-left {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-top {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #333;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-price {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-label {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-value {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #ff5000;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-modal-bottom {
|
||||||
|
flex: 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-list {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
padding: 5px 12px;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
|
||||||
|
border: 2px solid #f0f0f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-item:hover {
|
||||||
|
border: 2px solid #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-item.active {
|
||||||
|
border-color: #ff5000;
|
||||||
|
background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 80, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-price {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-item.active .model-name {
|
||||||
|
color: #ff5000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user