2025-08-07 21:29:04 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="home">
|
|
|
|
|
<!-- 英雄区域 -->
|
|
|
|
|
<section class="hero">
|
|
|
|
|
<div class="hero-background ethnic-pattern">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="hero-content">
|
|
|
|
|
<div class="hero-text">
|
|
|
|
|
<h1 class="hero-title">
|
|
|
|
|
传承千年文化
|
|
|
|
|
<br>
|
|
|
|
|
<span class="highlight">鄂伦春族的瑰宝</span>
|
|
|
|
|
</h1>
|
|
|
|
|
<p class="hero-description">
|
|
|
|
|
探索中国东北森林深处的古老民族文化,感受狩猎文明的独特魅力,
|
|
|
|
|
体验桦皮工艺、传统刺绣等非物质文化遗产的精湛技艺。
|
|
|
|
|
</p>
|
|
|
|
|
<div class="hero-actions">
|
|
|
|
|
<router-link to="/culture" class="btn-primary hero-btn">
|
|
|
|
|
探索文化
|
|
|
|
|
</router-link>
|
|
|
|
|
<router-link to="/products" class="btn-secondary hero-btn">
|
|
|
|
|
精品商城
|
|
|
|
|
</router-link>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hero-image">
|
|
|
|
|
<div class="hero-image-placeholder">
|
|
|
|
|
<svg viewBox="0 0 400 300" class="hero-svg">
|
|
|
|
|
<!-- 森林背景 -->
|
|
|
|
|
<rect width="400" height="300" fill="#2d5016" opacity="0.1"/>
|
|
|
|
|
<!-- 传统建筑轮廓 -->
|
|
|
|
|
<path d="M50 250 L150 180 L250 250 L350 180 L350 280 L50 280 Z"
|
|
|
|
|
fill="var(--secondary-color)" opacity="0.6"/>
|
|
|
|
|
<!-- 装饰图案 -->
|
|
|
|
|
<circle cx="200" cy="150" r="40" fill="var(--primary-color)" opacity="0.3"/>
|
|
|
|
|
<text x="200" y="160" text-anchor="middle" fill="var(--primary-color)"
|
|
|
|
|
font-size="24" font-weight="bold">鄂</text>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- 特色板块 -->
|
|
|
|
|
<section class="features section">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<h2 class="section-title">文化瑰宝</h2>
|
|
|
|
|
<div class="features-grid">
|
|
|
|
|
<div class="feature-card card" @click="$router.push('/culture')">
|
|
|
|
|
<div class="feature-icon">
|
|
|
|
|
<svg viewBox="0 0 64 64" width="48" height="48">
|
|
|
|
|
<circle cx="32" cy="32" r="28" fill="var(--primary-color)" opacity="0.2"/>
|
|
|
|
|
<path d="M20 32 L32 20 L44 32 L32 44 Z" fill="var(--primary-color)"/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<h3 class="feature-title">传统文化</h3>
|
|
|
|
|
<p class="feature-description">
|
|
|
|
|
深入了解鄂伦春族的狩猎文化、节庆仪式、饮食习俗和居住文化
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="feature-card card" @click="$router.push('/heritage')">
|
|
|
|
|
<div class="feature-icon">
|
|
|
|
|
<svg viewBox="0 0 64 64" width="48" height="48">
|
|
|
|
|
<circle cx="32" cy="32" r="28" fill="var(--secondary-color)" opacity="0.2"/>
|
|
|
|
|
<rect x="24" y="24" width="16" height="16" fill="var(--secondary-color)"/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<h3 class="feature-title">非遗传承</h3>
|
|
|
|
|
<p class="feature-description">
|
|
|
|
|
桦皮制作技艺、传统刺绣、民族歌舞等非物质文化遗产的传承与保护
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="feature-card card" @click="$router.push('/products')">
|
|
|
|
|
<div class="feature-icon">
|
|
|
|
|
<svg viewBox="0 0 64 64" width="48" height="48">
|
|
|
|
|
<circle cx="32" cy="32" r="28" fill="var(--accent-color)" opacity="0.3"/>
|
|
|
|
|
<path d="M16 24 L48 24 L44 48 L20 48 Z" fill="var(--primary-color)"/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<h3 class="feature-title">特色产品</h3>
|
|
|
|
|
<p class="feature-description">
|
|
|
|
|
精美手工艺品、传统服饰、特色食品和现代文创产品
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- 热门产品 -->
|
|
|
|
|
<section class="popular-products section" style="background-color: var(--background-light);">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<h2 class="section-title">热门产品</h2>
|
|
|
|
|
<div class="products-grid">
|
|
|
|
|
<div v-for="product in featuredProducts" :key="product.id"
|
|
|
|
|
class="product-card card" @click="$router.push(`/product/${product.id}`)">
|
|
|
|
|
<div class="product-image">
|
|
|
|
|
<div class="product-image-placeholder">
|
|
|
|
|
<svg viewBox="0 0 200 150" width="100%" height="150">
|
|
|
|
|
<rect width="200" height="150" :fill="product.color" opacity="0.3"/>
|
|
|
|
|
<text x="100" y="80" text-anchor="middle" :fill="product.color"
|
|
|
|
|
font-size="14" font-weight="bold">{{ product.name }}</text>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="product-info">
|
|
|
|
|
<h3 class="product-name">{{ product.name }}</h3>
|
|
|
|
|
<p class="product-description">{{ product.description }}</p>
|
|
|
|
|
<div class="product-footer">
|
|
|
|
|
<span class="product-price">¥{{ product.price }}</span>
|
|
|
|
|
<el-button type="primary" size="small" @click.stop="addToCart(product)">
|
|
|
|
|
加入购物车
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="text-center" style="margin-top: 2rem;">
|
|
|
|
|
<router-link to="/products" class="btn-primary">查看更多产品</router-link>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- 文化故事 -->
|
|
|
|
|
<section class="culture-stories section">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<h2 class="section-title">文化故事</h2>
|
|
|
|
|
<div class="stories-grid">
|
|
|
|
|
<div v-for="story in stories" :key="story.id" class="story-card card">
|
|
|
|
|
<div class="story-image">
|
|
|
|
|
<div class="story-image-placeholder">
|
|
|
|
|
<svg viewBox="0 0 300 200" width="100%" height="200">
|
|
|
|
|
<rect width="300" height="200" :fill="story.color" opacity="0.2"/>
|
|
|
|
|
<circle cx="150" cy="100" r="40" :fill="story.color" opacity="0.5"/>
|
|
|
|
|
<text x="150" y="110" text-anchor="middle" :fill="story.color"
|
|
|
|
|
font-size="16" font-weight="bold">{{ story.title.charAt(0) }}</text>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="story-content">
|
|
|
|
|
<h3 class="story-title">{{ story.title }}</h3>
|
|
|
|
|
<p class="story-excerpt">{{ story.excerpt }}</p>
|
|
|
|
|
<div class="story-meta">
|
|
|
|
|
<span class="story-date">{{ story.date }}</span>
|
2025-08-10 20:42:49 +08:00
|
|
|
|
<a href="#" @click.prevent="showStoryDetail(story)" class="story-link">阅读更多</a>
|
2025-08-07 21:29:04 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- 统计数据 -->
|
|
|
|
|
<section class="stats section" style="background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="stats-grid">
|
|
|
|
|
<div class="stat-item">
|
|
|
|
|
<div class="stat-number">1000+</div>
|
|
|
|
|
<div class="stat-label">文化资料</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="stat-item">
|
|
|
|
|
<div class="stat-number">50+</div>
|
|
|
|
|
<div class="stat-label">非遗项目</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="stat-item">
|
|
|
|
|
<div class="stat-number">200+</div>
|
|
|
|
|
<div class="stat-label">特色产品</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="stat-item">
|
|
|
|
|
<div class="stat-number">10000+</div>
|
|
|
|
|
<div class="stat-label">用户关注</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</section>
|
|
|
|
|
</div>
|
2025-08-10 20:42:49 +08:00
|
|
|
|
|
|
|
|
|
<!-- 文化故事详情卡片 -->
|
|
|
|
|
<el-dialog
|
|
|
|
|
v-model="storyDetailVisible"
|
|
|
|
|
:title="selectedStory?.title"
|
|
|
|
|
width="70%"
|
|
|
|
|
top="5vh"
|
|
|
|
|
class="story-detail-dialog"
|
|
|
|
|
>
|
|
|
|
|
<div v-if="selectedStory" class="story-detail-content">
|
|
|
|
|
<!-- 故事头部信息 -->
|
|
|
|
|
<div class="story-header">
|
|
|
|
|
<div class="story-image-placeholder">
|
|
|
|
|
<svg width="100%" height="200" viewBox="0 0 400 200">
|
|
|
|
|
<rect width="400" height="200" :fill="selectedStory.color" opacity="0.2"/>
|
|
|
|
|
<circle cx="200" cy="100" r="50" :fill="selectedStory.color" opacity="0.5"/>
|
|
|
|
|
<text x="200" y="110" text-anchor="middle" :fill="selectedStory.color"
|
|
|
|
|
font-size="20" font-weight="bold">{{ selectedStory.title.substring(0, 2) }}</text>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="story-meta-info">
|
|
|
|
|
<p class="story-date">发布时间:{{ selectedStory.date }}</p>
|
|
|
|
|
<p class="story-category" v-if="selectedStory.categoryName">分类:{{ selectedStory.categoryName }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 故事内容 -->
|
|
|
|
|
<div class="story-content-section">
|
|
|
|
|
<h3>内容简介</h3>
|
|
|
|
|
<p class="story-description">{{ selectedStory.excerpt }}</p>
|
|
|
|
|
|
|
|
|
|
<div v-if="storyDetailData.content" class="story-full-content">
|
|
|
|
|
<h3>详细内容</h3>
|
|
|
|
|
<div class="content-text" v-html="storyDetailData.content"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="storyDetailData.tags" class="story-tags">
|
|
|
|
|
<h3>相关标签</h3>
|
|
|
|
|
<div class="tags-container">
|
|
|
|
|
<span class="tag" v-for="tag in parseTags(storyDetailData.tags)" :key="tag">
|
|
|
|
|
{{ tag }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
|
|
<div class="story-actions">
|
|
|
|
|
<el-button type="primary" @click="goToFullDetail">查看完整详情</el-button>
|
|
|
|
|
<el-button @click="storyDetailVisible = false">关闭</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="storyLoading" class="loading-container">
|
|
|
|
|
<el-icon class="is-loading"><Loading /></el-icon>
|
|
|
|
|
<p>加载中...</p>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
2025-08-07 21:29:04 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-08-10 20:42:49 +08:00
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
|
|
import { useRouter } from 'vue-router'
|
2025-08-07 21:29:04 +08:00
|
|
|
|
import { useMainStore } from '../stores'
|
|
|
|
|
import { ElMessage } from 'element-plus'
|
2025-08-10 20:42:49 +08:00
|
|
|
|
import { Loading } from '@element-plus/icons-vue'
|
|
|
|
|
import { productApi } from '../api/product'
|
|
|
|
|
import { cultureApi } from '../api/culture'
|
|
|
|
|
import { cartApi } from '../api/cart'
|
2025-08-07 21:29:04 +08:00
|
|
|
|
|
2025-08-10 20:42:49 +08:00
|
|
|
|
const router = useRouter()
|
2025-08-07 21:29:04 +08:00
|
|
|
|
const store = useMainStore()
|
|
|
|
|
|
|
|
|
|
// 特色产品数据
|
2025-08-10 20:42:49 +08:00
|
|
|
|
const featuredProducts = ref<any[]>([])
|
|
|
|
|
const loading = ref(false)
|
2025-08-07 21:29:04 +08:00
|
|
|
|
|
|
|
|
|
// 文化故事数据
|
2025-08-10 20:42:49 +08:00
|
|
|
|
const stories = ref<any[]>([])
|
|
|
|
|
|
|
|
|
|
// 故事详情相关
|
|
|
|
|
const storyDetailVisible = ref(false)
|
|
|
|
|
const selectedStory = ref<any>(null)
|
|
|
|
|
const storyDetailData = ref<any>({})
|
|
|
|
|
const storyLoading = ref(false)
|
|
|
|
|
|
|
|
|
|
// 获取热门产品
|
|
|
|
|
const getFeaturedProducts = async () => {
|
|
|
|
|
try {
|
|
|
|
|
loading.value = true
|
|
|
|
|
const response = await productApi.getProductList({
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
pageSize: 4,
|
|
|
|
|
status: 1 // 只获取上架的产品
|
|
|
|
|
})
|
|
|
|
|
if (response && response.records) {
|
|
|
|
|
featuredProducts.value = response.records.map((product: any) => ({
|
|
|
|
|
...product,
|
|
|
|
|
color: getRandomColor()
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取产品数据失败:', error)
|
|
|
|
|
ElMessage.error('获取产品数据失败,请稍后重试')
|
|
|
|
|
featuredProducts.value = []
|
|
|
|
|
} finally {
|
|
|
|
|
loading.value = false
|
2025-08-07 21:29:04 +08:00
|
|
|
|
}
|
2025-08-10 20:42:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取推荐文化内容
|
|
|
|
|
const getRecommendedStories = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await cultureApi.getRecommendedCulture()
|
|
|
|
|
if (response && response.length > 0) {
|
|
|
|
|
stories.value = response.slice(0, 3).map((story: any) => ({
|
|
|
|
|
id: story.id,
|
|
|
|
|
title: story.title,
|
|
|
|
|
excerpt: story.content ? story.content.substring(0, 100) + '...' : story.description,
|
|
|
|
|
date: story.createTime ? new Date(story.createTime).toLocaleDateString() : '2024-01-01',
|
|
|
|
|
color: getRandomColor()
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取文化内容失败:', error)
|
|
|
|
|
ElMessage.error('获取文化内容失败,请稍后重试')
|
|
|
|
|
stories.value = []
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取随机颜色
|
|
|
|
|
const getRandomColor = () => {
|
|
|
|
|
const colors = ['#8b4513', '#2d5016', '#8b4513', '#2d5016']
|
|
|
|
|
return colors[Math.floor(Math.random() * colors.length)]
|
|
|
|
|
}
|
2025-08-07 21:29:04 +08:00
|
|
|
|
|
|
|
|
|
// 添加到购物车
|
2025-08-10 20:42:49 +08:00
|
|
|
|
const addToCart = async (product: any) => {
|
|
|
|
|
try {
|
|
|
|
|
// 这里使用默认用户ID,实际应用中应该从用户状态获取
|
|
|
|
|
const userId = '1'
|
|
|
|
|
await cartApi.addToCart(userId, product.id, 1)
|
|
|
|
|
store.addToCart(product)
|
|
|
|
|
ElMessage.success('已添加到购物车')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('添加到购物车失败:', error)
|
|
|
|
|
ElMessage.error('添加到购物车失败,请稍后重试')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 显示故事详情
|
|
|
|
|
const showStoryDetail = async (story: any) => {
|
|
|
|
|
selectedStory.value = story
|
|
|
|
|
storyDetailVisible.value = true
|
|
|
|
|
storyLoading.value = true
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 获取完整的故事详情
|
|
|
|
|
const response = await cultureApi.getCultureById(story.id)
|
|
|
|
|
if (response) {
|
|
|
|
|
storyDetailData.value = response
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取故事详情失败:', error)
|
|
|
|
|
ElMessage.error('获取故事详情失败,请稍后重试')
|
|
|
|
|
} finally {
|
|
|
|
|
storyLoading.value = false
|
|
|
|
|
}
|
2025-08-07 21:29:04 +08:00
|
|
|
|
}
|
2025-08-10 20:42:49 +08:00
|
|
|
|
|
|
|
|
|
// 跳转到完整详情页
|
|
|
|
|
const goToFullDetail = () => {
|
|
|
|
|
if (selectedStory.value) {
|
|
|
|
|
router.push(`/culture/${selectedStory.value.id}`)
|
|
|
|
|
storyDetailVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析标签
|
|
|
|
|
const parseTags = (tags: string) => {
|
|
|
|
|
if (!tags) return []
|
|
|
|
|
return tags.split(',').map(tag => tag.trim()).filter(tag => tag)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 组件挂载时获取数据
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
getFeaturedProducts()
|
|
|
|
|
getRecommendedStories()
|
|
|
|
|
})
|
2025-08-07 21:29:04 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
/* 英雄区域 */
|
|
|
|
|
.hero {
|
|
|
|
|
position: relative;
|
|
|
|
|
min-height: 600px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-background {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
right: 0;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
background: linear-gradient(135deg, rgba(45, 80, 22, 0.9), rgba(139, 69, 19, 0.8));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-content {
|
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 2;
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
|
gap: 3rem;
|
|
|
|
|
align-items: center;
|
|
|
|
|
min-height: 500px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-title {
|
|
|
|
|
font-size: 3.5rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: white;
|
|
|
|
|
margin-bottom: 1.5rem;
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.highlight {
|
|
|
|
|
color: var(--accent-color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-description {
|
|
|
|
|
font-size: 1.2rem;
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-btn {
|
|
|
|
|
padding: 15px 30px;
|
|
|
|
|
font-size: 1.1rem;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-secondary {
|
|
|
|
|
background: transparent;
|
|
|
|
|
color: white;
|
|
|
|
|
border: 2px solid white;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.btn-secondary:hover {
|
|
|
|
|
background: white;
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-image-placeholder {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 400px;
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-svg {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 特色板块 */
|
|
|
|
|
.features-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.feature-card {
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
text-align: center;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.feature-card:hover {
|
|
|
|
|
transform: translateY(-10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.feature-icon {
|
|
|
|
|
margin-bottom: 1.5rem;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.feature-title {
|
|
|
|
|
font-size: 1.5rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.feature-description {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 产品网格 */
|
|
|
|
|
.products-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-card {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-image-placeholder {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 150px;
|
|
|
|
|
background: var(--background-light);
|
|
|
|
|
border-radius: 8px 8px 0 0;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-info {
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-name {
|
|
|
|
|
font-size: 1.2rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-description {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-footer {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-price {
|
|
|
|
|
font-size: 1.3rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: var(--secondary-color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 文化故事 */
|
|
|
|
|
.stories-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-card {
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-image-placeholder {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 200px;
|
|
|
|
|
background: var(--background-light);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-content {
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-title {
|
|
|
|
|
font-size: 1.3rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-excerpt {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-meta {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-date {
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-link {
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-link:hover {
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 统计数据 */
|
|
|
|
|
.stats {
|
|
|
|
|
color: white;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats-grid {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stat-item {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stat-number {
|
|
|
|
|
font-size: 3rem;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
margin-bottom: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stat-label {
|
|
|
|
|
font-size: 1.1rem;
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.text-center {
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-10 20:42:49 +08:00
|
|
|
|
/* 故事详情对话框样式 */
|
|
|
|
|
.story-detail-dialog :deep(.el-dialog) {
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-detail-content {
|
|
|
|
|
max-height: 70vh;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-header {
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-image-placeholder {
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-meta-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-content-section {
|
|
|
|
|
margin-bottom: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-content-section h3 {
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
font-size: 1.2rem;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
border-bottom: 2px solid var(--primary-color);
|
|
|
|
|
padding-bottom: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-description {
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
margin-bottom: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-full-content {
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content-text {
|
|
|
|
|
color: var(--text-color);
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-tags {
|
|
|
|
|
margin-top: 1.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tags-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tag {
|
|
|
|
|
background: var(--primary-color);
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 0.3rem 0.8rem;
|
|
|
|
|
border-radius: 15px;
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
gap: 1rem;
|
|
|
|
|
margin-top: 2rem;
|
|
|
|
|
padding-top: 1rem;
|
|
|
|
|
border-top: 1px solid var(--border-color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.loading-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
padding: 3rem;
|
|
|
|
|
color: var(--text-light);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.loading-container .el-icon {
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
margin-bottom: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-07 21:29:04 +08:00
|
|
|
|
/* 响应式设计 */
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
.hero-content {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
text-align: center;
|
|
|
|
|
gap: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-title {
|
|
|
|
|
font-size: 2.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-actions {
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.features-grid,
|
|
|
|
|
.products-grid,
|
|
|
|
|
.stories-grid {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats-grid {
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
}
|
2025-08-10 20:42:49 +08:00
|
|
|
|
|
|
|
|
|
.story-detail-dialog :deep(.el-dialog) {
|
|
|
|
|
width: 95% !important;
|
|
|
|
|
margin: 5vh auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-meta-info {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.story-actions {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
2025-08-07 21:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
.hero-title {
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.hero-actions {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stats-grid {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|