的撒法
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
yiqiu
2025-11-22 22:35:44 +08:00
parent 28d2efb4f2
commit 0f9f96c596
3 changed files with 153 additions and 351 deletions

View File

@@ -1,135 +1,47 @@
/* banner */ /* banner */
.banner-cont { .banner-cont {
position: relative;
width: 100%; width: 100%;
overflow: hidden;
/* 确保 3D 地球在竖直方向不会被裁剪,预留更大展示区域 */
min-height: 520px;
}
/* banner 区背景:改为暗色科技感渐变,左侧适合文案,右侧衬托地球与飞行轨迹 */
.section.banner {
background:
radial-gradient(circle at 0% 0%, rgba(56, 189, 248, 0.22) 0%, transparent 40%),
radial-gradient(circle at 80% 20%, rgba(129, 140, 248, 0.35) 0%, transparent 55%),
linear-gradient(135deg, #020617 0%, #020617 40%, #0B1120 60%, #020617 100%);
} }
.banner-cont .swiper-slide { .banner-cont .swiper-slide {
height: 500px;
width: 100%; width: 100%;
background: linear-gradient(0, #f7f9fa, #f9fafb); background: linear-gradient(0, #f7f9fa, #f9fafb);
} }
.banner-cont .swiper-slide .img { .banner-cont .swiper-slide .img {
/* 图片撑开高度,避免被裁切 */ /* position: absolute; */
display: block; z-index: -1;
width: 100%; max-height: 100%;
height: auto;
max-width: 100%; max-width: 100%;
}
/* 文案层:覆盖在轮播上,使用 section-content 控制左右宽度 */
.banner-cont .banner-text {
position: absolute;
left: 0;
top: 0;
width: 100%; width: 100%;
height: 100%; /* object-fit: fill; */
/* 需要盖在 swiper-slide 之上swiper 本身 z-index: 1这里抬高一层 */
z-index: 10;
pointer-events: none;
} }
.banner-cont .banner-text .section-content {
/* 相对定位,便于内部文案块绝对居中定位 */
position: relative;
height: 100%;
padding: 0 20px; /* 左右 20px 内边距,与全站一致 */
margin: 0 auto; /* 保持与其他 section-content 一致的水平布局 */
}
.banner-copy { .banner-cont .banner-desc {
max-width: 560px;
text-align: left;
/* 绝对定位:在整块 banner 内垂直居中,水平方向与下方卡片文案左侧对齐 */
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
/* 与下方 .banner-item 内的文案左对齐section-content padding 20px + item padding 60px */
padding-left: 80px;
}
.banner-copy #bannerTitle {
font-size: 44px;
line-height: 1.2;
color: #F9FAFB;
}
.banner-copy .banner-desc {
font-size: 16px; font-size: 16px;
margin-top: 16px; margin-top: 30px;
margin-bottom: 32px; margin-bottom: 80px;
max-width: 550px; max-width: 550px;
color: rgba(148, 163, 184, 0.95);
} }
.banner-copy #bannerButton { .banner-cont .swiper-pagination-bullet {
pointer-events: auto; width: 36px;
/* 首页主按钮稍大一些,突出主召唤操作 */ height: 4px;
font-size: 16px; background: #D7DCE4;
padding: 12px 48px; opacity: 1;
border-radius: 3px;
} }
/* 轮播文案标签 */ .banner-cont .swiper-pagination-bullet-active {
.banner-tags { background: rgba(255, 103, 57, 1);
margin-bottom: 12px;
}
.banner-tag-pill {
display: inline-block;
margin-right: 8px;
padding: 4px 12px;
font-size: 14px;
border-radius: 999px;
background: rgba(15, 23, 42, 0.8);
color: #E0F2FE;
}
/* 3D 地球容器:与 section-content 右对齐(和下方卡片区域右边保持一致) */
.banner-globe {
position: absolute;
top: 0;
left: 0;
/* 画布充满整个 banner 文案区域,让粒子可以从整个区域四面八方飞入 */
width: 100%;
height: 100%;
z-index: 5; /* 保持在文案层之下 */
pointer-events: none; /* 不影响轮播图滑动与点击 */
}
/* 中等屏幕下稍微缩小地球,避免挡住文案 */
@media (max-width: 1400px) {
.banner-globe {
width: 100%;
height: 100%;
}
}
/* 小屏幕(如窄笔记本)下隐藏 3D 地球,保持可用性 */
@media (max-width: 1100px) {
.banner-globe {
display: none;
}
} }
.banner .banner-s { .banner .banner-s {
/* 首页下半部分 banner 卡片采用毛玻璃 + 阴影效果 */ box-shadow: 0px 0px 16px rgba(52, 52, 52, 0.16);
background: rgba(15, 23, 42, 0.8); border-radius: 3px;
border-radius: 16px;
box-shadow: 0 24px 80px rgba(15, 23, 42, 0.85);
border: 1px solid rgba(148, 163, 184, 0.45);
backdrop-filter: blur(20px);
} }
.banner .banner-s .banner-list { .banner .banner-s .banner-list {
@@ -143,44 +55,24 @@
cursor: pointer; cursor: pointer;
width: 335px; width: 335px;
padding: 30px 60px; padding: 30px 60px;
color: #E5E7EB;
} }
.banner-s .banner-list .banner-item:hover { .banner-s .banner-list .banner-item:hover {
background: rgba(15, 23, 42, 0.75); background: rgba(247, 248, 249, 1);
} }
.banner-s .banner-list .banner-item:hover h5 { .banner-s .banner-list .banner-item:hover h5 {
color: #F9FAFB; color: #FF6739;
} }
.banner-list .banner-item .banner-tag { .banner-list .banner-item .banner-tag {
font-size: 12px; font-size: 12px;
color: #E0F2FE; color: #FF6739;
border: 1px solid rgba(148, 163, 184, 0.55); border: 1px solid #FF6739;
padding: 5px 8px; padding: 5px 8px;
border-radius: 3px; border-radius: 3px;
} }
/* 首页专属 header 科技风样式(仅在 body#\index 上生效,避免影响其他页面) */
body#index .nav-shadow {
background:
linear-gradient(90deg, rgba(15, 23, 42, 0.98) 0%, rgba(15, 23, 42, 0.96) 60%, rgba(8, 47, 73, 0.96) 100%);
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.8);
}
body#index .nav-menu .nav-item {
color: #E5E7EB;
}
body#index .nav-menu .nav-item:hover {
border-bottom-color: #38BDF8;
}
body#index .nav-right .control {
color: #E5E7EB;
}
/* 服务内容 */ /* 服务内容 */
.service-content { .service-content {
display: flex; display: flex;

View File

@@ -3,15 +3,7 @@
<link rel="stylesheet" href="/web/BlackFruit-web/css/index.css"> <link rel="stylesheet" href="/web/BlackFruit-web/css/index.css">
<link rel="stylesheet" href="/web/BlackFruit-web/css/viewer.min.css"> <link rel="stylesheet" href="/web/BlackFruit-web/css/viewer.min.css">
<!-- 首页脚本 -->
<script src="/web/BlackFruit-web/js/index.js"></script> <script src="/web/BlackFruit-web/js/index.js"></script>
<!-- 3D 地球依赖Three.js 和 three-globe顺序不能反 -->
<script src="https://unpkg.com/three@0.155.0/build/three.min.js"></script>
<script src="https://unpkg.com/three-globe@2.45.0/dist/three-globe.min.js"></script>
<!-- TopoJSON 客户端,用于将 land-110m 拓扑数据转换为 GeoJSON 多边形 -->
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3/dist/topojson-client.min.js"></script>
<!-- 3D 地球效果脚本(基于 three-globe -->
<script src="/web/BlackFruit-web/js/globe.js"></script>
<script src="/web/BlackFruit-web/js/viewer.min.js"></script> <script src="/web/BlackFruit-web/js/viewer.min.js"></script>
</head> </head>
@@ -19,64 +11,47 @@
<body id="index"> <body id="index">
<header>{include file="public/header"}</header> <header>{include file="public/header"}</header>
<!-- banner:去掉图片轮播,仅保留文案轮播 + 右侧地球 --> <!-- banner(恢复 Swiper 轮播结构,数据由 $data.banner 提供;未配置时使用静态占位) -->
<section class="section banner"> <section class="section banner">
<div class="banner-cont"> <div class="swiper banner-cont">
<div class="banner-text"> <div class="swiper-wrapper">
<div class="section-content"> {if ( isset($data.banner) ) }
{if isset($data.banner) && !empty($data.banner)} {foreach $data.banner as $key=>$value}
{php}$__firstBanner = $data['banner'][0];{/php} <div class="swiper-slide">
<div class="banner-copy"> <a href="{$value.url|default='javascript:;'}">
<div id="bannerTags" class="banner-tags"> <img class="img-responsive img center-block" src="{$value.img}" alt="">
{if !empty($__firstBanner.tags)}
{php}
$__tags = preg_split('/[,]/', $__firstBanner['tags']);
{/php}
{foreach $__tags as $__t}
{php}$__t_trim = trim($__t);{/php}
{if $__t_trim != ''}
<span class="banner-tag-pill">{$__t_trim}</span>
{/if}
{/foreach}
{/if}
</div>
<h1 id="bannerTitle">{$__firstBanner.title|default=''}</h1>
<p class="banner-desc" id="bannerDesc">{$__firstBanner.description|default=''}</p>
{if !empty($__firstBanner.button_text)}
<a
class="btn btn2 btn-normal"
href="{$__firstBanner.button_link|default=$__firstBanner.url|default='javascript:;'}"
id="bannerButton"
{if !empty($__firstBanner.button_blank)}target="_blank"{else}target="_self"{/if}
>
{$__firstBanner.button_text}
</a> </a>
</div>
{/foreach}
{else /} {else /}
<a <div class="swiper-slide">
class="btn btn2 btn-normal" <img class="img-responsive img center-block" src="/web/BlackFruit-web/assets/img/index/1@2x.png" alt="">
href="javascript:;" <div class="section-content">
id="bannerButton" <h1>中小企业的云计算底座</h1>
style="display: none;" <p class="banner-desc">主题云聚焦中小企业的数智化转型进程,以技术和数据为驱动,以产品和场景为载体,专注于打磨云上业务服务能力,助力中小企业全面业务上云演化。</p>
></a> <div class="btn btn2 btn-normal">立即查看</div>
</div>
</div>
<div class="swiper-slide">
<img class="img-responsive img center-block" src="/web/BlackFruit-web/assets/img/index/1@2x.png" alt="">
<div class="section-content">
<h1>中小企业的云计算底座</h1>
<p class="banner-desc">主题云聚焦中小企业的数智化转型进程,以技术和数据为驱动,以产品和场景为载体,专注于打磨云上业务服务能力,助力中小企业全面业务上云演化。</p>
<div class="btn btn2 btn-normal">立即查看</div>
</div>
</div>
<div class="swiper-slide">
<img class="img-responsive img center-block" src="/web/BlackFruit-web/assets/img/index/1@2x.png" alt="">
<div class="section-content">
<h1>中小企业的云计算底座</h1>
<p class="banner-desc">主题云聚焦中小企业的数智化转型进程,以技术和数据为驱动,以产品和场景为载体,专注于打磨云上业务服务能力,助力中小企业全面业务上云演化。</p>
<div class="btn btn2 btn-normal">立即查看</div>
</div>
</div>
{/if} {/if}
</div> </div>
{else /} <!-- 如果需要分页器 -->
<!-- 兼容未提供 banner 配置时的占位结构,仍由前端 JS 填充 --> <div class="swiper-pagination"></div>
<div class="banner-copy">
<div id="bannerTags" class="banner-tags"></div>
<h1 id="bannerTitle"></h1>
<p class="banner-desc" id="bannerDesc"></p>
<a
class="btn btn2 btn-normal"
href="javascript:;"
id="bannerButton"
style="display: none;"
></a>
</div>
{/if}
<!-- 3D 地球容器Three.js 渲染输出挂载到这里),与下方卡片区域共用 section-content 对齐 -->
<div id="bannerGlobe" class="banner-globe"></div>
</div>
</div> </div>
</div> </div>
<div class="banner-s"> <div class="banner-s">

View File

@@ -32,89 +32,10 @@ $(function () {
} }
} }
isRecommend(); isRecommend();
let bannerData = []; // 设置首页函数
let bannerTextTimer = null;
const updateBannerText = (index) => {
if (!Array.isArray(bannerData) || bannerData.length === 0) {
return;
}
const idx = index >= 0 && index < bannerData.length ? index : 0;
const item = bannerData[idx] || {};
// 标签渲染:标题上方的小块标签
const $tagsWrap = $("#bannerTags");
if ($tagsWrap.length) {
$tagsWrap.empty();
const rawTags = item.tags || "";
const tags = rawTags
.split(/[,]/)
.map((t) => t.trim())
.filter((t) => t);
tags.forEach((tag) => {
$tagsWrap.append(
`<span class="banner-tag-pill">${tag}</span>`
);
});
if (tags.length === 0) {
$tagsWrap.hide();
} else {
$tagsWrap.show();
}
}
$("#bannerTitle").text(item.title || "");
$("#bannerDesc").text(item.description || "");
const $btn = $("#bannerButton");
if (item.button_text) {
const link = item.button_link || item.url || "javascript:;";
const target = item.button_blank ? "_blank" : "_self";
$btn
.text(item.button_text)
.attr("href", link)
.attr("target", target)
.show();
} else {
$btn.hide();
}
};
// 简单的文案轮播(不再使用 Swiper 图片,仅轮播标题/描述/按钮)
const startBannerTextLoop = () => {
if (!Array.isArray(bannerData) || bannerData.length === 0) {
return;
}
let current = 0;
// 初始化先展示第一条
updateBannerText(current);
// 清理旧定时器
if (bannerTextTimer) {
clearInterval(bannerTextTimer);
bannerTextTimer = null;
}
// 只有一条时不需要轮播
if (bannerData.length === 1) {
return;
}
bannerTextTimer = setInterval(() => {
current = (current + 1) % bannerData.length;
// 淡入动画:先让文案透明,再渐显
const $copy = $(".banner-copy");
$copy
.stop(true, true)
.css({ opacity: 0 })
.animate({ opacity: 1 }, 400);
updateBannerText(current);
}, 5000);
};
// 设置首页函数:直接使用服务端注入的 window.__themeCommonSSR 数据),避免再次请求配置
function setIndexData() { function setIndexData() {
const commentObj = window.__themeCommon const commentObj = JSON.parse(sessionStorage.commentData);
? window.__themeCommon if (commentObj.honor.length > 0) {
: (sessionStorage.commentData ? JSON.parse(sessionStorage.commentData) : {});
bannerData = commentObj.banner || [];
// 仅轮播文案
startBannerTextLoop();
if (Array.isArray(commentObj.honor) && commentObj.honor.length > 0) {
commentObj.honor.forEach((item) => { commentObj.honor.forEach((item) => {
$("#certBox").append(`<div class="cert-item"> $("#certBox").append(`<div class="cert-item">
<img src=${item.img} alt=""> <img src=${item.img} alt="">
@@ -122,7 +43,7 @@ $(function () {
</div>`); </div>`);
}); });
} }
if (Array.isArray(commentObj.partner) && commentObj.partner.length > 0 && commentObj.partner.length <= 3) { if (commentObj.partner.length > 0 && commentObj.partner.length <= 3) {
commentObj.partner.forEach((item) => { commentObj.partner.forEach((item) => {
$("#practiceBox").append(`<div class="practice-box"> $("#practiceBox").append(`<div class="practice-box">
<img src="${item.img}" alt=""> <img src="${item.img}" alt="">
@@ -130,7 +51,7 @@ $(function () {
<p class="tr font-grey mt-20 font12">${item.name}</p> <p class="tr font-grey mt-20 font12">${item.name}</p>
</div>`); </div>`);
}); });
} else if (Array.isArray(commentObj.partner) && commentObj.partner.length > 3) { } else if (commentObj.partner.length > 3) {
const arr1 = commentObj.partner.slice(0, 3); const arr1 = commentObj.partner.slice(0, 3);
const arr2 = commentObj.partner.slice(3); const arr2 = commentObj.partner.slice(3);
arr1.forEach((item) => { arr1.forEach((item) => {
@@ -148,8 +69,22 @@ $(function () {
}); });
} }
} }
// 首页直接使用服务端注入的数据渲染SSR不再请求 /console/v1/common 或 /console/v1/theme/config // 获取通用配置信息
function getCommentInfo() {
$.ajax({
url: "/console/v1/common",
method: "get",
headers: {
Authorization: "Bearer" + " " + localStorage.jwt,
},
success: function (res) {
sessionStorage.commentData = JSON.stringify(res.data);
setIndexData(); setIndexData();
},
});
}
// 获取首页数据
getCommentInfo();
var viewer = new Viewer(document.getElementById("viewer"), { var viewer = new Viewer(document.getElementById("viewer"), {
button: true, button: true,
inline: false, inline: false,