2026-06-09 15:24:50 +08:00

1123 lines
28 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="jd-homepage">
<!-- 搜索区域 -->
<!-- <div class="search-box">
<search></search>
</div> -->
<!-- 主内容区域 -->
<main class="main-content">
<section id="banner" class="public-hero">
<div class="floating-orb orb-1"></div>
<div class="floating-orb orb-2"></div>
<div class="floating-orb orb-3"></div>
<div class="floating-orb orb-4"></div>
<div class="hero-glow glow-blue"></div>
<div class="hero-glow glow-purple"></div>
<div class="hero-glow glow-warm"></div>
<div class="hero-particles">
<span v-for="item in 30" :key="item"></span>
</div>
<div class="hero-inner">
<p class="hero-slogan">好用还省钱Token 就上开元云</p>
<h1><span>OPC</span>公共服务平台</h1>
<p class="hero-subtitle">
为 <strong>OPC</strong> 而生,极致性价比一站式模型平台
</p>
<div class="hero-service-list">
<div class="circle-item token" @click="goTokenMarket">
<div class="circle-ring">
<div class="circle-core">
<svg viewBox="0 0 80 80" aria-hidden="true">
<defs>
<linearGradient id="tokenGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#93c5fd" />
<stop offset="50%" stop-color="#3b82f6" />
<stop offset="100%" stop-color="#1d4ed8" />
</linearGradient>
</defs>
<polygon points="40,8 68,24 68,56 40,72 12,56 12,24" fill="rgba(59,130,246,0.18)" stroke="url(#tokenGradient)" stroke-width="2" />
<polygon points="40,18 56,28 56,48 40,58 24,48 24,28" fill="url(#tokenGradient)" opacity="0.75" />
<text x="40" y="45" text-anchor="middle" fill="#fff" font-size="20" font-weight="700">T</text>
<line x1="40" y1="8" x2="40" y2="2" stroke="#60a5fa" stroke-width="1.5" />
<line x1="68" y1="24" x2="74" y2="20" stroke="#60a5fa" stroke-width="1.5" />
<line x1="12" y1="24" x2="6" y2="20" stroke="#60a5fa" stroke-width="1.5" />
</svg>
</div>
</div>
<h3>Token市集</h3>
<p>汇聚海量精品模型,以更低成本畅享极致 AI 体验</p>
<button type="button" @click.stop="goTokenMarket">立即体验</button>
</div>
<div class="circle-item workshop" @click="goCreativeWorkshop">
<div class="circle-ring">
<div class="circle-core">
<svg viewBox="0 0 80 80" aria-hidden="true">
<defs>
<linearGradient id="lensGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#e9d5ff" />
<stop offset="50%" stop-color="#a855f7" />
<stop offset="100%" stop-color="#7c3aed" />
</linearGradient>
</defs>
<circle cx="40" cy="40" r="32" fill="rgba(139,92,246,0.15)" stroke="url(#lensGradient)" stroke-width="2" />
<circle cx="40" cy="40" r="22" fill="rgba(168,85,247,0.32)" stroke="#c084fc" stroke-width="1.5" />
<circle cx="40" cy="40" r="12" fill="url(#lensGradient)" opacity="0.85" />
<ellipse cx="35" cy="35" rx="6" ry="3" fill="#fff" opacity="0.45" transform="rotate(-30 35 35)" />
<line x1="40" y1="18" x2="40" y2="8" stroke="#c084fc" stroke-width="1.5" />
<line x1="40" y1="62" x2="40" y2="72" stroke="#c084fc" stroke-width="1.5" />
<line x1="18" y1="40" x2="8" y2="40" stroke="#c084fc" stroke-width="1.5" />
<line x1="62" y1="40" x2="72" y2="40" stroke="#c084fc" stroke-width="1.5" />
</svg>
</div>
</div>
<h3>创镜工坊</h3>
<p>以文筑境,以镜生画,全场景 AI 影像创作</p>
<button type="button" @click.stop="goCreativeWorkshop">了解更多</button>
</div>
<div class="circle-item base" @click="goCloudBase">
<div class="circle-ring">
<div class="circle-core">
<svg viewBox="0 0 80 80" aria-hidden="true">
<defs>
<linearGradient id="cloudGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#a7f3d0" />
<stop offset="50%" stop-color="#10b981" />
<stop offset="100%" stop-color="#059669" />
</linearGradient>
</defs>
<rect x="14" y="48" width="52" height="14" rx="4" fill="rgba(16,185,129,0.25)" stroke="#34d399" />
<rect x="14" y="32" width="52" height="14" rx="4" fill="rgba(16,185,129,0.38)" stroke="#34d399" />
<rect x="14" y="16" width="52" height="14" rx="4" fill="url(#cloudGradient)" opacity="0.78" stroke="#a7f3d0" />
<circle cx="22" cy="23" r="2" fill="#a7f3d0" />
<circle cx="22" cy="39" r="2" fill="#34d399" />
<circle cx="22" cy="55" r="2" fill="#34d399" />
<line x1="40" y1="30" x2="40" y2="32" stroke="#34d399" stroke-width="1.5" />
<line x1="40" y1="46" x2="40" y2="48" stroke="#34d399" stroke-width="1.5" />
<path d="M56 20 Q60 16 64 20" stroke="#a7f3d0" stroke-width="1.5" fill="none" />
<path d="M54 17 Q60 10 66 17" stroke="#a7f3d0" stroke-width="1.2" fill="none" opacity="0.55" />
</svg>
</div>
</div>
<h3>云枢基座</h3>
<p>深耕基础云服务,筑牢 AI 平台数字根基</p>
<button type="button" @click.stop="goCloudBase">了解更多</button>
</div>
</div>
<div class="hero-stat-list">
<div class="hero-stat-item">
<strong>50+</strong>
<span>精品模型</span>
</div>
<div class="hero-stat-item">
<strong>99.9%</strong>
<span>服务可用性</span>
</div>
<div class="hero-stat-item">
<strong>4800+</strong>
<span>企业用户</span>
</div>
<div class="hero-stat-item highlight">
<strong>低至0.001</strong>
<span>每千Token起步价</span>
</div>
</div>
</div>
</section>
</main>
<!-- 产品列表区域 -->
<!-- <div class="productList">
<ul class="myTab">
<li v-for="menu in product" :class="currentHotMenu === menu.id ? 'activeMenu' : ''" @click="clickNetMenu(menu)"
:key="menu.name">
<span class="tab-text">{{ menu.product_category }}</span>
</li>
</ul>
<productCard v-loading="boxLoading" :productList="hotProductList"></productCard>
<el-pagination @current-change="handleCurrentChange" :page-size="page_size" layout="total, prev, pager, next"
:total="total">
</el-pagination>
</div> -->
<!-- 发布商品/需求对话框 -->
<!-- <el-dialog :title="publish_type === '2' ? '发布需求' : '发布商品'" width="60vw" top="5vh"
:visible.sync="sendProductVisible">
<sendProduct :isEdit="false" v-if="publish_type" @success="sendProductSuccess" :publish_type="publish_type">
</sendProduct>
</el-dialog> -->
<!-- 提示对话框 -->
<el-dialog title="温馨提示" :visible.sync="showTip" width="30%">
<span>您还没有完善企业信息完善企业信息审核通过后您可以发布需求与商品</span>
<span slot="footer" class="dialog-footer">
<span>
<span style="margin-right: 10px;">跳转到</span>
<el-button size="small" type="primary" @click="goInfo">信息完善</el-button>
</span>
</span>
</el-dialog>
</div>
</template>
<script>
import Vue from 'vue'
import { reqPublishProductSearchFirstPage, reqEnterpriseAuditInfoSearch, reqHomepageProductCategory, reqGetSupplyAndDemandSquareList } from '@/api/ncmatch'
import { mapGetters, mapState } from "vuex";
import { gotoYuanJingAPI } from '@/api/gotoYuanJing'
export default Vue.extend({
name: "mainPage",
components: {
// sendProduct: () => import('../ncmatch/sendProduct/index.vue'),
// productCard: () => import('./productCard/index.vue'),
// search: () => import('../search/index.vue'),
// menuAside: () => import('./menuAside/index.vue')
},
created() {
this.getHomepageProductCategory()
},
data() {
return {
boxLoading: false,
selectedCategory: "",
showTip: false,
total: 0,
publish_type: null,
sendProductVisible: false,
currentHotMenu: "",
product: [],
hotProductList: [],
current_page: 1,
page_size: 8,
}
},
computed: {
...mapGetters(["sidebar", "avatar", "device"]),
...mapState({
isShowPanel: (state) => state.product.showHomeNav,
navIndex: (state) => state.product.navIndex,
gridObj: state => state.operationAnalysis.gridObj,
mybalance: state => state.user.mybalance,
logoutUrl: state => state.login.logoutUrl,
loginStateVuex: state => state.login.loginState,
logoInfoNew: state => state.product.logoInfoNew,
}),
loginState() {
const userId = sessionStorage.getItem('userId');
return this.loginStateVuex || (userId !== null && userId !== 'null' && userId !== '');
},
},
methods: {
goTokenMarket() {
if (!this.loginState) {
this.$router.push({
path: '/tokenMarket',
query: {
category: 'TOKEN市集',
from: 'home',
single: '1'
}
})
return
}
this.$router.push({
path: '/product',
query: {
category: 'TOKEN市集',
from: 'home'
}
})
},
goCloudBase() {
if (!this.loginState) {
this.$message.warning('请先登录哦~')
return
}
this.$router.push({
path: '/product',
query: {
category: '基础云',
from: 'home'
}
})
},
getHomepageProductCategory() {
reqHomepageProductCategory({
url_link: window.location.href,
publish_type: "1"
}).then(res => {
if (res.status) {
this.categories = res.data
this.product = res.data
this.currentHotMenu = res.data[0].id
this.selectedCategory = res.data[0].id
this.initData()
}
})
},
goInfo() {
this.showTip = false
this.$router.push('/customer/approve')
},
async goCreativeWorkshop() {
if (!this.loginState) {
window.open('https://ai.opencomputing.cn/', '_blank')
return
}
const yuanJingWindow = window.open('', '_blank')
try {
const res = await gotoYuanJingAPI({
user_id: sessionStorage.getItem('userId')
})
const deerer = this.getYuanJingAuthorization(res)
if (!deerer) {
if (yuanJingWindow) {
yuanJingWindow.close()
}
this.$message.error((res && res.msg) || '获取元境授权参数失败')
return
}
const loginUrl = `https://ai.opencomputing.cn/#/getCookie?deerer=${encodeURIComponent(deerer)}`
if (yuanJingWindow) {
yuanJingWindow.location.href = loginUrl
} else {
window.location.href = loginUrl
}
} catch (error) {
if (yuanJingWindow) {
yuanJingWindow.close()
}
this.$message.error('跳转元境失败,请稍后重试')
}
},
getYuanJingAuthorization(res) {
if (!res) {
return ''
}
if (typeof res === 'string') {
return res
}
const data = res.data || res
if (typeof data === 'string') {
return data
}
return data.Authorization || data.authorization || data.token || data.header || data.value || ''
},
handleCurrentChange(val) {
this.current_page = val
this.initData()
},
sendInfo(type) {
if (this.loginState) {
reqEnterpriseAuditInfoSearch({
url_link: window.location.href,
}).then(res => {
const dataList = res && res.data && res.data.data
const hasAuditInfo = Array.isArray(dataList) && dataList.length !== 0
const roles = sessionStorage.getItem('jueseNew')
const isCustomer = roles ? roles.includes('客户') : true
// 安全检查:确保 data[0] 存在
if (hasAuditInfo && dataList[0]) {
const auditStatus = dataList[0].audit_status
if (auditStatus === 'pending') {
this.$message.warning('您的审核状态为待审核,请等待审核通过后发布~')
} else if (auditStatus === 'rejected') {
this.$message.warning('您的审核状态为驳回,请重新提交~')
} else {
// 审核通过或其他状态,允许发布
this.publish_type = type
this.sendProductVisible = true
}
} else if (!isCustomer) {
// 非客户角色,允许发布
this.publish_type = type
this.sendProductVisible = true
} else {
// 没有审核信息且是客户角色,显示提示
this.showTip = true
}
})
} else {
this.$router.push('/login')
}
},
initData() {
this.boxLoading = true
let ploay = {
product_category: this.selectedCategory,
to_page: "first_page",
url_link: window.location.href,
page_size: this.page_size,
current_page: this.current_page,
publish_type: "1"
}
reqGetSupplyAndDemandSquareList(ploay).then(res => {
this.boxLoading = false
if (res.status) {
if (res.data.length === 0) {
this.hotProductList = []
this.total = 0
} else {
this.hotProductList = res.data[0].product_list
this.total = res.data[0].total_count
}
}
})
},
init_product_list() {
reqPublishProductSearchFirstPage({
publish_type: "1",
url_link: window.location.href,
to_page: 'first_page',
page_size: this.page_size,
current_page: this.current_page,
product_type: this.currentHotMenu
}).then(res => {
if (res.status) {
if (res.data.length > 0) {
this.currentHotMenu = res.data[0].id
this.hotProductList = res.data[0].product_list
this.product = res.data
this.total = res.data[0].total_count
}
}
})
},
sendProductSuccess() {
this.sendProductVisible = false; // 关闭弹窗
this.init_product_list()
},
clickNetMenu(menu) {
this.current_page = 1
this.currentHotMenu = menu.id;
this.selectedCategory = menu.id
this.initData()
},
goFavorite() {
if (this.loginState) {
this.$router.push('/ncmatchHome/favoriteBox')
} else {
this.$router.push('/login')
}
},
goHistory() {
if (this.loginState) {
this.$router.push('/ncmatchHome/historyBox')
} else {
this.$router.push('/login')
}
}
}
})
</script>
<style scoped lang="scss">
.jd-homepage {
margin: 0;
// padding-top: 92px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(180deg, #f0f7ff 0%, #ffffff 46%, #f7faff 74%, #f8fafc 100%);
overflow-x: hidden;
}
.search-box {
max-width: 1280px;
margin: 0 auto 18px;
padding: 0 24px;
}
/* 主内容区域 */
.main-content {
width: 100%;
padding: 0;
}
/* 横幅样式 */
.public-hero {
width: 100%;
min-height: 760px;
margin: 0 auto;
overflow: hidden;
position: relative;
color: #111827;
background:
radial-gradient(circle at 16% 18%, rgba(45, 91, 255, 0.12), transparent 28%),
radial-gradient(circle at 82% 28%, rgba(124, 58, 237, 0.1), transparent 30%),
radial-gradient(circle at 50% 52%, rgba(245, 158, 11, 0.08), transparent 36%),
linear-gradient(180deg, #f0f7ff 0%, #ffffff 66%, #f7faff 88%, #f8fafc 100%);
}
.hero-inner {
position: relative;
z-index: 3;
display: flex;
flex-direction: column;
align-items: center;
max-width: 1280px;
margin: 0 auto;
padding: 76px 48px 64px;
text-align: center;
}
.hero-slogan {
margin: 0 0 28px;
font-size: 18px;
font-weight: 600;
letter-spacing: 0.04em;
background: linear-gradient(90deg, #f59e0b 0%, #ef4444 25%, #f59e0b 50%, #2d5bff 75%, #f59e0b 100%);
background-size: 200% auto;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: sloganShine 4s linear infinite;
}
.public-hero h1 {
margin: 0;
color: #111827;
font-size: 64px;
line-height: 1.1;
font-weight: 800;
letter-spacing: 0.02em;
span {
margin: 0 4px;
background: linear-gradient(135deg, #2d5bff 0%, #7c3aed 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
.hero-subtitle {
max-width: 760px;
margin: 22px auto 70px;
color: #666666;
font-size: 22px;
line-height: 1.7;
strong {
color: #2d5bff;
font-weight: 700;
}
}
.floating-orb {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.08;
pointer-events: none;
z-index: 0;
&.orb-1 {
top: -110px;
left: -100px;
width: 400px;
height: 400px;
background: #3b82f6;
animation: float1 20s ease-in-out infinite;
}
&.orb-2 {
right: -150px;
bottom: -160px;
width: 500px;
height: 500px;
background: #8b5cf6;
animation: float2 25s ease-in-out infinite;
}
&.orb-3 {
left: 50%;
top: 50%;
width: 300px;
height: 300px;
background: #ec4899;
animation: float3 18s ease-in-out infinite;
}
&.orb-4 {
right: 20%;
bottom: 30%;
width: 350px;
height: 350px;
background: #f59e0b;
animation: float1 22s ease-in-out infinite reverse;
}
}
.hero-glow {
position: absolute;
border-radius: 50%;
pointer-events: none;
z-index: 1;
&.glow-blue {
top: 90px;
left: 9%;
width: 360px;
height: 360px;
background: rgba(59, 130, 246, 0.18);
filter: blur(120px);
}
&.glow-purple {
right: 8%;
bottom: 120px;
width: 480px;
height: 480px;
background: rgba(168, 85, 247, 0.16);
filter: blur(150px);
}
&.glow-warm {
left: 50%;
top: 43%;
width: 560px;
height: 560px;
background: rgba(245, 158, 11, 0.08);
filter: blur(180px);
transform: translate(-50%, -50%);
}
}
.hero-particles {
position: absolute;
inset: 0;
z-index: 1;
overflow: hidden;
pointer-events: none;
span {
position: absolute;
width: 4px;
height: 4px;
background: rgba(45, 91, 255, 0.12);
border-radius: 50%;
animation: particleFloat 8s linear infinite;
@for $i from 1 through 30 {
&:nth-child(#{$i}) {
left: #{($i * 17) % 100}#{'%'};
top: #{($i * 29) % 100}#{'%'};
width: #{2 + ($i % 4)}px;
height: #{2 + ($i % 4)}px;
animation-delay: #{($i % 8) * 0.45}s;
animation-duration: #{6 + ($i % 6)}s;
}
}
&:nth-child(4n) {
background: rgba(16, 185, 129, 0.16);
}
&:nth-child(4n + 1) {
background: rgba(59, 130, 246, 0.16);
}
&:nth-child(4n + 2) {
background: rgba(139, 92, 246, 0.16);
}
&:nth-child(4n + 3) {
background: rgba(236, 72, 153, 0.14);
}
}
}
@keyframes particleFloat {
0% {
transform: translateY(0) scale(0);
opacity: 0;
}
10% {
transform: translateY(-20px) scale(1);
opacity: 1;
}
90% {
transform: translateY(-200px) scale(1);
opacity: 1;
}
100% {
transform: translateY(-240px) scale(0.5);
opacity: 0;
}
}
.hero-service-list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 72px;
width: 100%;
max-width: 900px;
}
.circle-item {
cursor: pointer;
color: #111827;
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
&:hover {
transform: scale(1.08) translateY(-10px);
}
h3 {
margin: 24px 0 12px;
color: #1a1a1a;
font-size: 24px;
font-weight: 700;
}
p {
min-height: 52px;
max-width: 210px;
margin: 0 auto 18px;
color: #666666;
font-size: 15px;
line-height: 1.7;
}
button {
height: 36px;
padding: 0 24px;
cursor: pointer;
background: rgba(255, 255, 255, 0.76);
border: 1px solid rgba(45, 91, 255, 0.12);
border-radius: 999px;
transition: all 0.25s ease;
}
}
.circle-ring {
display: flex;
align-items: center;
justify-content: center;
width: 192px;
height: 192px;
margin: 0 auto;
border: 2px solid rgba(45, 91, 255, 0.15);
border-radius: 50%;
background: linear-gradient(135deg, rgba(45, 91, 255, 0.06), rgba(45, 91, 255, 0.02));
box-shadow: 0 4px 12px rgba(45, 91, 255, 0.06), 0 0 20px rgba(45, 91, 255, 0.12);
animation: rhythmPulse 2.5s ease-in-out infinite;
}
.circle-core {
display: flex;
align-items: center;
justify-content: center;
width: 156px;
height: 156px;
background: rgba(255, 255, 255, 0.9);
border-radius: 50%;
box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);
svg {
width: 86px;
height: 86px;
}
}
.circle-item.token button {
color: #2d5bff;
border-color: rgba(45, 91, 255, 0.16);
&:hover {
background: rgba(45, 91, 255, 0.06);
}
}
.circle-item.workshop {
.circle-ring {
border-color: rgba(124, 58, 237, 0.15);
background: linear-gradient(135deg, rgba(124, 58, 237, 0.06), rgba(236, 72, 153, 0.02));
box-shadow: 0 4px 12px rgba(124, 58, 237, 0.06), 0 0 20px rgba(139, 92, 246, 0.12);
animation-name: rhythmPulse2;
animation-duration: 2.8s;
}
button {
color: #7c3aed;
border-color: rgba(124, 58, 237, 0.16);
&:hover {
background: rgba(124, 58, 237, 0.06);
}
}
}
.circle-item.base {
.circle-ring {
border-color: rgba(5, 150, 105, 0.15);
background: linear-gradient(135deg, rgba(5, 150, 105, 0.06), rgba(45, 91, 255, 0.02));
box-shadow: 0 4px 12px rgba(5, 150, 105, 0.06), 0 0 20px rgba(16, 185, 129, 0.12);
animation-name: rhythmPulse3;
animation-duration: 3s;
}
button {
color: #059669;
border-color: rgba(5, 150, 105, 0.16);
&:hover {
background: rgba(5, 150, 105, 0.06);
}
}
}
.hero-stat-list {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 24px;
width: 100%;
max-width: 1180px;
margin-top: 72px;
}
.hero-stat-item {
position: relative;
min-height: 118px;
padding: 20px 18px;
overflow: hidden;
background: rgba(255, 255, 255, 0.86);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 18px;
box-shadow: 0 8px 24px rgba(45, 91, 255, 0.08);
backdrop-filter: blur(20px);
&::before,
&::after {
content: "";
position: absolute;
width: 100%;
height: 2px;
pointer-events: none;
}
&::before {
top: 0;
left: -100%;
background: linear-gradient(90deg, transparent, #2d5bff, transparent);
animation: borderMove 3s linear infinite;
}
&::after {
right: -100%;
bottom: 0;
background: linear-gradient(90deg, transparent, #7c3aed, transparent);
animation: borderMoveReverse 3s linear infinite;
}
strong {
display: block;
margin: 8px 0 10px;
background: linear-gradient(135deg, #2d5bff 0%, #7c3aed 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-size: 36px;
line-height: 1;
}
span {
color: #666666;
font-size: 13px;
}
&.highlight strong {
background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
@keyframes float1 {
0%,
100% {
transform: translate(0, 0);
}
33% {
transform: translate(50px, -50px);
}
66% {
transform: translate(-30px, 30px);
}
}
@keyframes float2 {
0%,
100% {
transform: translate(0, 0);
}
33% {
transform: translate(-40px, 40px);
}
66% {
transform: translate(60px, -30px);
}
}
@keyframes float3 {
0%,
100% {
transform: translate(-50%, -50%);
}
33% {
transform: translate(calc(-50% + 40px), calc(-50% - 40px));
}
66% {
transform: translate(calc(-50% - 30px), calc(-50% + 30px));
}
}
@keyframes sloganShine {
0% {
background-position: -200% center;
}
100% {
background-position: 200% center;
}
}
@keyframes rhythmPulse {
0%,
100% {
box-shadow: 0 4px 12px rgba(45, 91, 255, 0.06), 0 0 20px rgba(59, 130, 246, 0.18);
}
50% {
box-shadow: 0 8px 20px rgba(45, 91, 255, 0.1), 0 0 38px rgba(59, 130, 246, 0.25);
}
}
@keyframes rhythmPulse2 {
0%,
100% {
box-shadow: 0 4px 12px rgba(124, 58, 237, 0.06), 0 0 20px rgba(139, 92, 246, 0.18);
}
50% {
box-shadow: 0 8px 20px rgba(124, 58, 237, 0.1), 0 0 38px rgba(139, 92, 246, 0.25);
}
}
@keyframes rhythmPulse3 {
0%,
100% {
box-shadow: 0 4px 12px rgba(5, 150, 105, 0.06), 0 0 20px rgba(16, 185, 129, 0.18);
}
50% {
box-shadow: 0 8px 20px rgba(5, 150, 105, 0.1), 0 0 38px rgba(16, 185, 129, 0.25);
}
}
@keyframes borderMove {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
@keyframes borderMoveReverse {
0% {
right: -100%;
}
100% {
right: 100%;
}
}
@media (max-width: 1100px) {
.public-hero h1 {
font-size: 48px;
}
.hero-service-list {
gap: 34px;
}
.hero-stat-list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 768px) {
.main-content {
padding: 0;
}
.hero-inner {
padding: 56px 24px;
}
.hero-service-list {
grid-template-columns: 1fr;
gap: 48px;
max-width: 420px;
}
}
/* 产品列表区域 */
.productList {
position: relative;
width: 100%;
max-width: 1600px;
margin: -8px auto 0;
padding: 44px 20px 40px;
background: linear-gradient(180deg, rgba(247, 250, 255, 0.92) 0%, rgba(255, 255, 255, 0.98) 42%, rgba(248, 250, 252, 0.96) 100%);
border-radius: 28px 28px 0 0;
@media (max-width: 768px) {
padding: 32px 10px 30px;
}
}
.myTab {
width: 100%;
font-size: 18px;
border-radius: 16px;
background: #f7f8fc;
padding: 10px;
display: flex;
justify-content: center;
align-items: center;
margin-top: 0;
flex-wrap: wrap;
box-shadow: 0 10px 30px rgba(45, 91, 255, 0.06);
@media (max-width: 768px) {
margin-top: 30px;
font-size: 16px;
}
.activeMenu {
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
color: white;
}
li {
transition: all .2s ease-in-out;
z-index: 2;
padding: 10px 100px;
margin: 5px;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
@media (max-width: 768px) {
padding: 8px 15px;
margin: 3px;
}
}
}
/* 分页样式 */
.el-pagination {
padding: 20px 0;
display: flex;
justify-content: center;
@media (max-width: 768px) {
::v-deep .el-pagination__total,
::v-deep .el-pagination__jump {
display: none;
}
}
}
/* 响应式设计 */
@media (max-width: 576px) {
.jd-homepage {
padding-top: 80px;
}
.main-content {
padding: 0;
}
.hero-inner {
padding: 42px 18px;
}
.public-hero {
min-height: auto;
}
.public-hero h1 {
font-size: 34px;
}
.hero-subtitle {
margin-bottom: 32px;
font-size: 16px;
}
.hero-service-list,
.hero-stat-list {
grid-template-columns: 1fr;
gap: 18px;
}
.circle-ring {
width: 156px;
height: 156px;
}
.circle-core {
width: 126px;
height: 126px;
svg {
width: 72px;
height: 72px;
}
}
.myTab {
font-size: 14px;
margin-top: 20px;
}
}
</style>