的撒法
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-cont {
position: relative;
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 {
height: 500px;
width: 100%;
background: linear-gradient(0, #f7f9fa, #f9fafb);
}
.banner-cont .swiper-slide .img {
/* 图片撑开高度,避免被裁切 */
display: block;
width: 100%;
height: auto;
/* position: absolute; */
z-index: -1;
max-height: 100%;
max-width: 100%;
}
/* 文案层:覆盖在轮播上,使用 section-content 控制左右宽度 */
.banner-cont .banner-text {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
/* 需要盖在 swiper-slide 之上swiper 本身 z-index: 1这里抬高一层 */
z-index: 10;
pointer-events: none;
/* object-fit: fill; */
}
.banner-cont .banner-text .section-content {
/* 相对定位,便于内部文案块绝对居中定位 */
position: relative;
height: 100%;
padding: 0 20px; /* 左右 20px 内边距,与全站一致 */
margin: 0 auto; /* 保持与其他 section-content 一致的水平布局 */
}
.banner-copy {
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 {
.banner-cont .banner-desc {
font-size: 16px;
margin-top: 16px;
margin-bottom: 32px;
margin-top: 30px;
margin-bottom: 80px;
max-width: 550px;
color: rgba(148, 163, 184, 0.95);
}
.banner-copy #bannerButton {
pointer-events: auto;
/* 首页主按钮稍大一些,突出主召唤操作 */
font-size: 16px;
padding: 12px 48px;
.banner-cont .swiper-pagination-bullet {
width: 36px;
height: 4px;
background: #D7DCE4;
opacity: 1;
border-radius: 3px;
}
/* 轮播文案标签 */
.banner-tags {
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-cont .swiper-pagination-bullet-active {
background: rgba(255, 103, 57, 1);
}
.banner .banner-s {
/* 首页下半部分 banner 卡片采用毛玻璃 + 阴影效果 */
background: rgba(15, 23, 42, 0.8);
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);
box-shadow: 0px 0px 16px rgba(52, 52, 52, 0.16);
border-radius: 3px;
}
.banner .banner-s .banner-list {
@@ -143,43 +55,23 @@
cursor: pointer;
width: 335px;
padding: 30px 60px;
color: #E5E7EB;
}
.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 {
color: #F9FAFB;
color: #FF6739;
}
.banner-list .banner-item .banner-tag {
font-size: 12px;
color: #E0F2FE;
border: 1px solid rgba(148, 163, 184, 0.55);
color: #FF6739;
border: 1px solid #FF6739;
padding: 5px 8px;
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 {

View File

@@ -1,83 +1,58 @@
{include file="header"}
<!-- 当前页面 -->
<link rel="stylesheet" href="/web/BlackFruit-web/css/index.css">
<link rel="stylesheet" href="/web/BlackFruit-web/css/viewer.min.css">
<!-- 首页脚本 -->
{include file="header"}
<!-- 当前页面 -->
<link rel="stylesheet" href="/web/BlackFruit-web/css/index.css">
<link rel="stylesheet" href="/web/BlackFruit-web/css/viewer.min.css">
<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>
</head>
<body id="index">
</head>
<body id="index">
<header>{include file="public/header"}</header>
<!-- banner:去掉图片轮播,仅保留文案轮播 + 右侧地球 -->
<!-- banner(恢复 Swiper 轮播结构,数据由 $data.banner 提供;未配置时使用静态占位) -->
<section class="section banner">
<div class="banner-cont">
<div class="banner-text">
<div class="section-content">
{if isset($data.banner) && !empty($data.banner)}
{php}$__firstBanner = $data['banner'][0];{/php}
<div class="banner-copy">
<div id="bannerTags" class="banner-tags">
{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>
{else /}
<a
class="btn btn2 btn-normal"
href="javascript:;"
id="bannerButton"
style="display: none;"
></a>
{/if}
</div>
{else /}
<!-- 兼容未提供 banner 配置时的占位结构,仍由前端 JS 填充 -->
<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 class="swiper banner-cont">
<div class="swiper-wrapper">
{if ( isset($data.banner) ) }
{foreach $data.banner as $key=>$value}
<div class="swiper-slide">
<a href="{$value.url|default='javascript:;'}">
<img class="img-responsive img center-block" src="{$value.img}" alt="">
</a>
</div>
{/foreach}
{else /}
<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>
<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}
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
<div class="banner-s">
<div class="section-content banner-list">

View File

@@ -1,155 +1,90 @@
$(function () {
// 获取url地址栏参数函数
function getUrlParams() {
const url = window.location.href;
// 判断是否有参数
if (url.indexOf("?") === -1) {
return {};
}
const params = url.split("?")[1];
const paramsArr = params.split("&");
const paramsObj = {};
paramsArr.forEach((item) => {
const key = item.split("=")[0];
const value = item.split("=")[1];
// 解析中文
paramsObj[key] = decodeURI(value);
});
return paramsObj;
}
//设置cookie
function setCookie(c_name, value, expiredays = 1) {
const exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie =
c_name + "=" + value + (";expires=" + exdate.toGMTString());
}
// 判断首页是否为推荐页面
function isRecommend() {
const urlParams = getUrlParams();
if (urlParams.recommend_c) {
setCookie("recommend_c", urlParams.recommend_c);
}
$(function () {
// 获取url地址栏参数函数
function getUrlParams() {
const url = window.location.href;
// 判断是否有参数
if (url.indexOf("?") === -1) {
return {};
}
const params = url.split("?")[1];
const paramsArr = params.split("&");
const paramsObj = {};
paramsArr.forEach((item) => {
const key = item.split("=")[0];
const value = item.split("=")[1];
// 解析中文
paramsObj[key] = decodeURI(value);
});
return paramsObj;
}
//设置cookie
function setCookie(c_name, value, expiredays = 1) {
const exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie =
c_name + "=" + value + (";expires=" + exdate.toGMTString());
}
// 判断首页是否为推荐页面
function isRecommend() {
const urlParams = getUrlParams();
if (urlParams.recommend_c) {
setCookie("recommend_c", urlParams.recommend_c);
}
}
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() {
const commentObj = window.__themeCommon
? window.__themeCommon
: (sessionStorage.commentData ? JSON.parse(sessionStorage.commentData) : {});
bannerData = commentObj.banner || [];
// 仅轮播文案
startBannerTextLoop();
if (Array.isArray(commentObj.honor) && commentObj.honor.length > 0) {
const commentObj = JSON.parse(sessionStorage.commentData);
if (commentObj.honor.length > 0) {
commentObj.honor.forEach((item) => {
$("#certBox").append(`<div class="cert-item">
<img src=${item.img} alt="">
<p class="mt-20">${item.name}</p>
</div>`);
});
}
if (Array.isArray(commentObj.partner) && commentObj.partner.length > 0 && commentObj.partner.length <= 3) {
commentObj.partner.forEach((item) => {
$("#practiceBox").append(`<div class="practice-box">
<img src="${item.img}" alt="">
<div class="mt-10">${item.description}</div>
<p class="tr font-grey mt-20 font12">${item.name}</p>
</div>`);
});
} else if (Array.isArray(commentObj.partner) && commentObj.partner.length > 3) {
const arr1 = commentObj.partner.slice(0, 3);
const arr2 = commentObj.partner.slice(3);
arr1.forEach((item) => {
$("#practiceBox").append(`<div class="practice-box">
<img src="${item.img}" alt="">
<div class="mt-10">${item.description}</div>
<p class="tr font-grey mt-20 font12">${item.name}</p>
</div>`);
});
$("#morPracticeBox").attr("style", "display: flex;");
arr2.forEach((item) => {
$("#morPracticeBox").append(` <div class="brand-box">
<img src="${item.img}" alt="">
</div>`);
});
}
<img src=${item.img} alt="">
<p class="mt-20">${item.name}</p>
</div>`);
});
}
if (commentObj.partner.length > 0 && commentObj.partner.length <= 3) {
commentObj.partner.forEach((item) => {
$("#practiceBox").append(`<div class="practice-box">
<img src="${item.img}" alt="">
<div class="mt-10">${item.description}</div>
<p class="tr font-grey mt-20 font12">${item.name}</p>
</div>`);
});
} else if (commentObj.partner.length > 3) {
const arr1 = commentObj.partner.slice(0, 3);
const arr2 = commentObj.partner.slice(3);
arr1.forEach((item) => {
$("#practiceBox").append(`<div class="practice-box">
<img src="${item.img}" alt="">
<div class="mt-10">${item.description}</div>
<p class="tr font-grey mt-20 font12">${item.name}</p>
</div>`);
});
$("#morPracticeBox").attr("style", "display: flex;");
arr2.forEach((item) => {
$("#morPracticeBox").append(` <div class="brand-box">
<img src="${item.img}" alt="">
</div>`);
});
}
}
// 首页直接使用服务端注入的数据渲染SSR不再请求 /console/v1/common 或 /console/v1/theme/config
setIndexData();
// 获取通用配置信息
function getCommentInfo() {
$.ajax({
url: "/console/v1/common",
method: "get",
headers: {
Authorization: "Bearer" + " " + localStorage.jwt,
},
success: function (res) {
sessionStorage.commentData = JSON.stringify(res.data);
setIndexData();
},
});
}
// 获取首页数据
getCommentInfo();
var viewer = new Viewer(document.getElementById("viewer"), {
button: true,
inline: false,
@@ -180,7 +115,7 @@ $(function () {
D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
return Y + M + D;
}
// 公告列表
// 公告列表
function getAnnounceList() {
$.ajax({
url: "/console/v1/announcement",