增加特色服务

This commit is contained in:
李志强 2026-03-20 09:12:57 +08:00
parent a7908e0677
commit 14c305f518
13 changed files with 896 additions and 333 deletions

View File

@ -0,0 +1,251 @@
<?php
declare(strict_types=1);
namespace app\admin\controller\Cms\Services;
use app\admin\BaseController;
use think\response\Json;
use app\model\Cms\Services;
use think\exception\ValidateException;
/**
* 特色服务管理控制器
*/
class ServicesController extends BaseController
{
/**
* 获取特色服务列表
* @return Json
*/
public function getList(): Json
{
try {
$page = (int)$this->request->param('page', 1);
$limit = (int)$this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$status = $this->request->param('status', '');
$query = Services::where('delete_time', null)
->where('tid', $this->getTenantId());
// 关键词搜索
if (!empty($keyword)) {
$query->where('name', 'like', '%' . $keyword . '%');
}
// 状态筛选
if ($status !== '') {
$query->where('status', (int)$status);
}
$total = $query->count();
$list = $query->order('sort', 'asc')
->order('id', 'desc')
->page($page, $limit)
->select()
->toArray();
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'list' => $list,
'total' => $total
]
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取失败:' . $e->getMessage(),
'data' => []
]);
}
}
/**
* 添加特色服务
* @return Json
*/
public function add(): Json
{
try {
$data = $this->request->param();
// 验证参数
$this->validate($data, [
'name|服务名称' => 'require|max:100',
'url|服务地址' => 'require|url|max:255',
'sort|排序' => 'integer',
'status|状态' => 'in:0,1'
]);
$service = new Services();
$service->tid = $this->getTenantId();
$service->title = $data['title'];
$service->url = $data['url'];
$service->thumb = $data['thumb'] ?? '';
$service->desc = $data['desc'] ?? '';
$service->sort = $data['sort'] ?? 0;
$service->status = $data['status'] ?? 1;
$service->create_time = date('Y-m-d H:i:s');
$service->save();
$this->logSuccess('特色服务', '添加服务', ['id' => $service->id]);
return json([
'code' => 200,
'msg' => '添加成功',
'data' => $service->toArray()
]);
} catch (ValidateException $e) {
return json([
'code' => 400,
'msg' => $e->getError()
]);
} catch (\Exception $e) {
$this->logFail('特色服务', '添加服务', $e->getMessage());
return json([
'code' => 500,
'msg' => '添加失败:' . $e->getMessage()
]);
}
}
/**
* 更新特色服务
* @param int $id
* @return Json
*/
public function update(int $id): Json
{
try {
$data = $this->request->param();
$service = Services::where('id', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->find();
if (!$service) {
return json([
'code' => 404,
'msg' => '服务不存在'
]);
}
// 验证参数
if (isset($data['name'])) {
$this->validate($data, [
'name|服务名称' => 'require|max:100'
]);
}
if (isset($data['url'])) {
$this->validate($data, [
'url|服务地址' => 'require|url|max:255'
]);
}
if (isset($data['title'])) $service->title = $data['title'];
if (isset($data['url'])) $service->url = $data['url'];
if (isset($data['thumb'])) $service->thumb = $data['thumb'];
if (isset($data['desc'])) $service->desc = $data['desc'];
if (isset($data['sort'])) $service->sort = $data['sort'];
if (isset($data['status'])) $service->status = $data['status'];
$service->update_time = date('Y-m-d H:i:s');
$service->save();
$this->logSuccess('特色服务', '更新服务', ['id' => $id]);
return json([
'code' => 200,
'msg' => '更新成功',
'data' => $service->toArray()
]);
} catch (ValidateException $e) {
return json([
'code' => 400,
'msg' => $e->getError()
]);
} catch (\Exception $e) {
$this->logFail('特色服务', '更新服务', $e->getMessage());
return json([
'code' => 500,
'msg' => '更新失败:' . $e->getMessage()
]);
}
}
/**
* 删除特色服务
* @param int $id
* @return Json
*/
public function delete(int $id): Json
{
try {
$service = Services::where('id', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->find();
if (!$service) {
return json([
'code' => 404,
'msg' => '服务不存在'
]);
}
$service->delete();
$this->logSuccess('特色服务', '删除服务', ['id' => $id]);
return json([
'code' => 200,
'msg' => '删除成功'
]);
} catch (\Exception $e) {
$this->logFail('特色服务', '删除服务', $e->getMessage());
return json([
'code' => 500,
'msg' => '删除失败:' . $e->getMessage()
]);
}
}
/**
* 批量删除特色服务
* @return Json
*/
public function batchDelete(): Json
{
try {
$ids = $this->request->param('ids', []);
if (empty($ids)) {
return json([
'code' => 400,
'msg' => '请选择要删除的服务'
]);
}
Services::whereIn('id', $ids)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->update(['delete_time' => date('Y-m-d H:i:s')]);
$this->logSuccess('特色服务', '批量删除服务', ['ids' => $ids]);
return json([
'code' => 200,
'msg' => '批量删除成功'
]);
} catch (\Exception $e) {
$this->logFail('特色服务', '批量删除服务', $e->getMessage());
return json([
'code' => 500,
'msg' => '批量删除失败:' . $e->getMessage()
]);
}
}
}

View File

@ -0,0 +1,8 @@
<?php
use think\facade\Route;
// 特色服务路由
Route::get('services', 'app\admin\controller\Cms\Services\ServicesController@getList');
Route::post('services', 'app\admin\controller\Cms\Services\ServicesController@add');
Route::put('services/:id', 'app\admin\controller\Cms\Services\ServicesController@update');
Route::delete('services/:id', 'app\admin\controller\Cms\Services\ServicesController@delete');

View File

@ -113,22 +113,12 @@ abstract class BaseController
* 根据域名获取租户ID静态方法方便全局调用
* @return int
*/
public static function getTenantIdByDomain(): int
public static function getTenantIdByDomain(string $baseUrl): int
{
$request = request();
// 优先从 Referer 获取来源域名(跨域调用场景)
$referer = $request->header('Referer');
if ($referer) {
$host = parse_url($referer, PHP_URL_HOST);
} else {
// 否则使用当前访问域名
$host = $request->host(true);
}
// 查询域名对应的租户ID
$tenantDomain = Db::name('mete_tenant_domain')
->where('full_domain', $host)
->where('full_domain', $baseUrl)
->where('status', 1)
->whereNull('delete_time')
->find();

View File

@ -24,7 +24,12 @@ class NewsCenterController extends BaseController
*/
public function getCenterNews(): Json
{
// 从 BaseController 获取当前租户ID
$baseUrl = $this->request->get('baseUrl', '');
if (!empty($baseUrl)) {
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
}
$tid = $this->getTenantId();
if (empty($tid)) {

View File

@ -17,9 +17,14 @@ class BannerController extends BaseController
* 获取 Banner 列表
* @return Json
*/
public function getBanners(): Json
public function getBanners()
{
// 从 BaseController 获取当前租户ID
$baseUrl = $this->request->get('baseUrl', '');
if (!empty($baseUrl)) {
$this->tenantId = BaseController::getTenantIdByDomain($baseUrl);
}
$tid = $this->getTenantId();
if (empty($tid)) {

View File

@ -15,6 +15,7 @@ use think\facade\Env;
use think\facade\Request;
use app\model\Cms\TemplateSiteConfig;
use app\model\Cms\Friendlink;
use app\model\Tenant\Tenant;
class Index extends BaseController
{
@ -444,9 +445,15 @@ class Index extends BaseController
*/
public function getHomeData()
{
$baseUrl = Request::param('baseUrl', '');
if (empty($baseUrl)) {
return json(['code' => 400, 'msg' => '缺少 baseUrl 参数']);
}
try {
// 1. 通过域名获取租户ID
$tid = BaseController::getTenantIdByDomain();
$tid = BaseController::getTenantIdByDomain($baseUrl);
if (empty($tid)) {
return json([
@ -470,12 +477,20 @@ class Index extends BaseController
->select()
->toArray();
// 获取联系方式
$contact = Tenant::where('id', $tid)
->where('status', 1)
->where('delete_time', null)
->field('contact_phone,contact_email,address,worktime')
->find();
// 4. 合并返回
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'normal' => $normalInfos ?: (object) [],
'contact' => $contact ?: (object) [],
'links' => $friendlinkList
]
]);

View File

@ -0,0 +1,43 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app\model\Cms;
use think\Model;
use think\model\concern\SoftDelete;
/**
* 特色服务模型
*/
class Services extends Model
{
// 启用软删除
use SoftDelete;
// 数据库表名
protected $name = 'mete_apps_cms_services';
// 字段类型转换
protected $type = [
'id' => 'integer',
'tid' => 'integer',
'title' => 'string',
'desc' => 'string',
'thumb' => 'string',
'url' => 'string',
'sort' => 'integer',
'create_time' => 'datetime',
'update_time' => 'datetime',
'delete_time' => 'datetime',
];
}

View File

@ -15,10 +15,10 @@ $app = new App(__DIR__ . '/../../../');
$app->initialize();
// 获取当前域名
$host = $_SERVER['HTTP_HOST'] ?? '';
$baseUrl = $_SERVER['HTTP_HOST'];
// 查询域名对应的租户ID
$tenantDomain = TenantDomain::where('full_domain', $host)
$tenantDomain = TenantDomain::where('full_domain', $baseUrl)
->where('status', 1)
->whereNull('delete_time')
->find();
@ -40,7 +40,7 @@ if ($tid > 0) {
if (!empty($banner['image'])) {
if (!preg_match('/^https?:\/\//', $banner['image'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$banner['image'] = $scheme . '://' . $host .
$banner['image'] = $scheme . '://' . $baseUrl .
(strpos($banner['image'], '/') === 0 ? '' : '/') . $banner['image'];
}
}
@ -71,12 +71,12 @@ if ($tid > 0) {
// 处理图片路径
if (!empty($article['image']) && !preg_match('/^https?:\/\//', $article['image'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$article['image'] = $scheme . '://' . $host .
$article['image'] = $scheme . '://' . $baseUrl .
(strpos($article['image'], '/') === 0 ? '' : '/') . $article['image'];
}
if (!empty($article['thumb']) && !preg_match('/^https?:\/\//', $article['thumb'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$article['thumb'] = $scheme . '://' . $host .
$article['thumb'] = $scheme . '://' . $baseUrl .
(strpos($article['thumb'], '/') === 0 ? '' : '/') . $article['thumb'];
}
}
@ -117,17 +117,17 @@ if ($tid > 0) {
// 处理图片路径
if (!empty($companyInfo['logo']) && !preg_match('/^https?:\/\//', $companyInfo['logo'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$companyInfo['logo'] = $scheme . '://' . $host .
$companyInfo['logo'] = $scheme . '://' . $baseUrl .
(strpos($companyInfo['logo'], '/') === 0 ? '' : '/') . $companyInfo['logo'];
}
if (!empty($companyInfo['logow']) && !preg_match('/^https?:\/\//', $companyInfo['logow'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$companyInfo['logow'] = $scheme . '://' . $host .
$companyInfo['logow'] = $scheme . '://' . $baseUrl .
(strpos($companyInfo['logow'], '/') === 0 ? '' : '/') . $companyInfo['logow'];
}
if (!empty($companyInfo['ico']) && !preg_match('/^https?:\/\//', $companyInfo['ico'])) {
$scheme = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$companyInfo['ico'] = $scheme . '://' . $host .
$companyInfo['ico'] = $scheme . '://' . $baseUrl .
(strpos($companyInfo['ico'], '/') === 0 ? '' : '/') . $companyInfo['ico'];
}
@ -615,7 +615,7 @@ function stripHtml($html)
const bannerContainer = document.getElementById('banner-container');
if (!bannerContainer) return;
fetch(API_BASE_URL + '/getBanners')
fetch(API_BASE_URL + '/getBanners?baseUrl=' + window.location.hostname)
.then(res => res.json())
.then(result => {
if (result.code !== 200 || !result.list || result.list.length === 0) {
@ -710,7 +710,7 @@ function stripHtml($html)
const container = document.getElementById('friendlink-container');
if (!container) return;
fetch(API_BASE_URL + '/homeData')
fetch(API_BASE_URL + '/homeData?baseUrl=' + window.location.hostname)
.then(res => res.json())
.then(result => {
if (result.code !== 200 || !result.data || !result.data.links || result.data.links.length === 0) {

View File

@ -767,9 +767,84 @@ section,
}
.hero h1 {
margin: 0;
font-size: 3rem;
font-weight: 700;
font-size: 52px;
font-weight: 800;
line-height: 1.2;
margin-bottom: 20px;
}
.hero-desc {
font-size: 18px;
line-height: 1.6;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 30px;
max-width: 600px;
}
.hero-bg-img {
position: absolute !important;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
.hero-container {
position: relative;
z-index: 2;
}
.hero-content {
position: relative;
z-index: 3;
}
.hero-image {
position: relative;
z-index: 3;
}
.hero-image img {
position: relative !important;
width: 100%;
height: auto;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.hero-nav {
margin-top: 30px;
display: flex;
align-items: center;
gap: 15px;
}
.hero-prev,
.hero-next {
width: 40px;
height: 40px;
border: 2px solid rgba(255, 255, 255, 0.5);
background: rgba(0, 0, 0, 0.3);
color: #fff;
border-radius: 50%;
cursor: pointer;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
}
.hero-prev:hover,
.hero-next:hover {
background: #fff;
color: #333;
}
.hero-indicator {
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
}
.hero blockquote {
@ -1156,7 +1231,7 @@ section,
.recent-posts .post-box .post-title {
color: var(--heading-color);
font-size: 18px;
font-size: 17px;
font-weight: 700;
margin: 15px 0 0 0;
position: relative;

View File

@ -0,0 +1,32 @@
.post-title {
height: 40px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
}
.post-img {
width: 330px;
height: 160px;
object-fit: cover;
}
.recent-posts {
background-color: #f9f9f9 !important;
}
.feature-box {
display: flex;
flex-direction: column;
align-items: center;
}
.feature-box img {
width: 150px;
object-fit: cover;
}
.feature-box img:hover {
transform: scale(1.1);
transition: all 0.3s ease-in-out;
}

View File

@ -1,9 +1,21 @@
<!-- Scroll Top -->
<!-- footer.php -->
<!-- Scroll Top -->
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i class="bi bi-arrow-up-short"></i></a>
<!-- Preloader -->
<div id="preloader"></div>
<!-- Footer -->
<footer id="footer" class="footer">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<p>Design and Developed by 云泽网 <?php echo $homeInfo['normal']['copyright']; ?> <?php echo $homeInfo['normal']['sitename']; ?> All Rights Reserved.</p>
</div>
</div>
</div>
</footer>
<!-- Vendor JS Files -->
<script src="<?php echo $baseUrl; ?>/themes/template3/assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="<?php echo $baseUrl; ?>/themes/template3/assets/vendor/php-email-form/validate.js"></script>

View File

@ -1,7 +1,65 @@
<!-- header.php -->
<?php
// #########默认头部开始#########
// 引入 ThinkPHP 应用
require_once __DIR__ . '/../../../vendor/autoload.php';
use think\facade\Db;
use think\App;
$host = $_SERVER['HTTP_HOST'] ?? '';
$scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http';
$baseUrl = $scheme . '://' . $host;
$baseUrl = $baseUrl ?? ($scheme . '://' . $host);
$apiUrl = $apiUrl ?? 'https://api.yunzer.cn';
/**
* 核心请求函数fetchApiData
* 用于发送 GET 请求并解析 JSON
*/
function fetchApiData($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
// 如果是 HTTPS 接口且本地环境没配置证书,可以临时跳过验证(生产环境建议配置)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['error' => $error];
}
return json_decode($response, true);
}
// #########默认头部结束#########
// 调用 banner 接口
$bannerUrl = $apiUrl . '/getBanners?baseUrl=' . urlencode($host);
$bannersRes = fetchApiData($bannerUrl);
$bannersList = $bannersRes['list'] ?? [];
// 调用 homeData 接口获取全局数据
$homeDataUrl = $apiUrl . '/homeData?baseUrl=' . urlencode($host);
$homeDataRes = fetchApiData($homeDataUrl);
$homeInfo = $homeDataRes['data'] ?? [];
// 调用 getCenterNews 接口获取新闻数据
$newsUrl = $apiUrl . '/getCenterNews?baseUrl=' . urlencode($host);
$newsRes = fetchApiData($newsUrl);
$newsList = $newsRes['list'] ?? [];
// 获取友链数据
$friendlinkList = $homeInfo['links'] ?? [];
// 动态设置 SEO 变量
$seoTitle = $pageTitle ?? ($homeInfo['normal']['sitename'] ?? '云泽网 默认标题');
$seoDescription = $pageDescription ?? ($homeInfo['normal']['description'] ?? '');
$seoKeywords = $pageKeywords ?? ($homeInfo['normal']['keywords'] ?? '');
?>
<!DOCTYPE html>
<html lang="zh-CN">
@ -10,10 +68,10 @@ $baseUrl = $scheme . '://' . $host;
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<base href="/themes/template3/">
<title><?php echo isset($pageTitle) ? $pageTitle : 'Nova'; ?></title>
<meta name="description" content="<?php echo isset($pageDescription) ? $pageDescription : ''; ?>">
<meta name="keywords" content="<?php echo isset($pageKeywords) ? $pageKeywords : ''; ?>">
<title><?php echo htmlspecialchars($homeInfo['normal']['sitename']); ?></title>
<meta name="description" content="<?php echo $homeInfo['normal']['description']; ?>">
<meta name="keywords" content="<?php echo $seoKeywords; ?>">
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/img/favicon.png" rel="icon">
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/img/apple-touch-icon.png" rel="apple-touch-icon">
@ -23,6 +81,7 @@ $baseUrl = $scheme . '://' . $host;
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/css/style.css" rel="stylesheet">
<link href="<?php echo $baseUrl; ?>/themes/template3/assets/css/main.css" rel="stylesheet">
</head>
@ -32,7 +91,7 @@ $baseUrl = $scheme . '://' . $host;
<div class="container-fluid container-xl position-relative d-flex align-items-center justify-content-between">
<a href="<?php echo $baseUrl; ?>/" class="logo d-flex align-items-center">
<h1 class="sitename">Nova</h1>
<img src="<?php echo $baseUrl . $homeInfo['normal']['logow']; ?>" alt="">
</a>
<nav id="navmenu" class="navmenu">

View File

@ -1,41 +1,153 @@
<!-- index.php -->
<?php
$pageTitle = '首页 - Nova';
$pageDescription = 'Nova Bootstrap Template 的首页';
$pageKeywords = 'home, nova';
require_once __DIR__ . '/header.php';
?>
<!-- Hero Section -->
<section id="hero" class="hero section dark-background">
<img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/hero-bg.jpg" alt="" data-aos="fade-in">
<!-- Hero Section -->
<section id="hero" class="hero-section">
<?php if (!empty($bannersList)): ?>
<div class="hero-banner">
<div class="container">
<div class="row">
<div class="col-xl-4">
<h1 data-aos="fade-up">专注于重要的事情</h1>
<blockquote data-aos="fade-up" data-aos-delay="100">
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Perspiciatis cum recusandae eum laboriosam voluptatem repudiandae odio, vel exercitationem officiis provident minima. </p>
</blockquote>
<div class="d-flex" data-aos="fade-up" data-aos-delay="200">
<a href="#about" class="btn-get-started">开始使用</a>
<a href="https://www.youtube.com/watch?v=Y7f98aduVJ8" class="glightbox btn-watch-video d-flex align-items-center"><i class="bi bi-play-circle"></i><span>观看视频</span></a>
<div class="row align-items-center">
<div class="col-lg-6">
<h1 id="hero-title"><?php echo htmlspecialchars($bannersList[0]['title'] ?? ''); ?></h1>
<p id="hero-desc"><?php echo htmlspecialchars($bannersList[0]['desc'] ?? ''); ?></p>
<?php if (!empty($bannersList[0]['url'])): ?>
<a href="<?php echo htmlspecialchars($bannersList[0]['url']); ?>" class="btn-hero" id="hero-link">查看详情</a>
<?php endif; ?>
<?php if (count($bannersList) > 1): ?>
<div class="hero-nav">
<button onclick="switchBanner(-1)">&#10094;</button>
<span id="hero-indicator">1 / <?php echo count($bannersList); ?></span>
<button onclick="switchBanner(1)">&#10095;</button>
</div>
<?php endif; ?>
</div>
<div class="col-lg-6">
<img src="<?php echo htmlspecialchars($bannersList[0]['image'] ?? ''); ?>" alt="" id="hero-img">
</div>
</div>
</div>
</div>
<?php if (count($bannersList) > 1): ?>
<script>
var banners = <?php echo json_encode($bannersList); ?>;
var currentIndex = 0;
function switchBanner(direction) {
currentIndex = (currentIndex + direction + banners.length) % banners.length;
var banner = banners[currentIndex];
document.getElementById('hero-img').src = banner.image || '';
document.getElementById('hero-title').textContent = banner.title || '';
document.getElementById('hero-desc').textContent = banner.desc || '';
var linkBtn = document.getElementById('hero-link');
if (banner.url) {
linkBtn.href = banner.url;
linkBtn.style.display = 'inline-block';
} else {
linkBtn.style.display = 'none';
}
document.getElementById('hero-indicator').textContent = (currentIndex + 1) + ' / ' + banners.length;
}
</script>
<?php endif; ?>
<?php else: ?>
<div class="hero-banner">
<div class="container">
<div class="row align-items-center">
<div class="col-lg-6">
<h1>专注为您提供优质服务</h1>
<p>致力于成为您最信赖的合作伙伴</p>
<a href="#about" class="btn-hero">了解更多</a>
</div>
<div class="col-lg-6">
<img src="<?php echo $apiUrl; ?>/themes/template3/assets/img/hero-bg.jpg" alt="">
</div>
</div>
</div>
</div>
</section><!-- /Hero Section -->
<?php endif; ?>
<!-- Why Us Section -->
<section id="why-us" class="why-us section">
<style>
.hero-section {
background: #1a1a2e;
padding: 120px 0 60px;
min-height: 100vh;
}
.hero-banner {
max-width: 1200px;
margin: 0 auto;
}
.hero-section .row {
align-items: center;
}
.hero-section h1 {
color: #fff;
font-size: 42px;
font-weight: 700;
margin-bottom: 20px;
}
.hero-section p {
color: rgba(255,255,255,0.8);
font-size: 18px;
margin-bottom: 30px;
line-height: 1.6;
}
.hero-section img {
width: 100%;
border-radius: 10px;
}
.btn-hero {
display: inline-block;
padding: 12px 30px;
background: #e94560;
color: #fff;
text-decoration: none;
border-radius: 5px;
font-weight: 600;
transition: background 0.3s;
}
.btn-hero:hover {
background: #d63d56;
}
.hero-nav {
margin-top: 30px;
display: flex;
align-items: center;
gap: 15px;
}
.hero-nav button {
width: 40px;
height: 40px;
border: 1px solid rgba(255,255,255,0.3);
background: rgba(255,255,255,0.1);
color: #fff;
border-radius: 50%;
cursor: pointer;
font-size: 18px;
}
.hero-nav button:hover {
background: #e94560;
border-color: #e94560;
}
.hero-nav span {
color: rgba(255,255,255,0.7);
font-size: 14px;
}
</style>
</section>
<section id="why-us" class="why-us section">
<div class="container">
<div class="row g-0">
<div class="col-xl-5 img-bg" data-aos="fade-up" data-aos-delay="100">
<img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/why-us-bg.jpg" alt="">
<img src="<?php echo $apiUrl; ?>/themes/template3/assets/img/why-us-bg.jpg" alt="">
</div>
<div class="col-xl-7 slides position-relative" data-aos="fade-up" data-aos-delay="200">
@ -66,8 +178,12 @@ require_once __DIR__ . '/header.php';
<div class="swiper-slide">
<div class="item">
<h3 class="mb-3">让我们一起成长</h3>
<h4 class="mb-3">Optio reiciendis accusantium iusto architecto at quia minima maiores quidem, dolorum.</h4>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellendus, ipsam perferendis asperiores explicabo vel tempore velit totam, natus nesciunt accusantium dicta quod quibusdam ipsum maiores nobis non, eum. Ullam reiciendis dignissimos laborum aut, magni voluptatem velit doloribus quas sapiente optio.</p>
<h4 class="mb-3">Optio reiciendis accusantium iusto architecto at quia minima maiores quidem, dolorum.
</h4>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Repellendus, ipsam perferendis asperiores
explicabo vel tempore velit totam, natus nesciunt accusantium dicta quod quibusdam ipsum maiores nobis
non, eum. Ullam reiciendis dignissimos laborum aut, magni voluptatem velit doloribus quas sapiente
optio.</p>
</div>
</div><!-- End slide item -->
@ -75,7 +191,9 @@ require_once __DIR__ . '/header.php';
<div class="item">
<h3 class="mb-3">Unde perspiciatis ut repellat dolorem</h3>
<h4 class="mb-3">Amet cumque nam sed voluptas doloribus iusto. Dolorem eos aliquam quis.</h4>
<p>Dolorem quia fuga consectetur voluptatem. Earum consequatur nulla maxime necessitatibus cum accusamus. Voluptatem dolorem ut numquam dolorum delectus autem veritatis facilis. Et ea ut repellat ea. Facere est dolores fugiat dolor.</p>
<p>Dolorem quia fuga consectetur voluptatem. Earum consequatur nulla maxime necessitatibus cum
accusamus. Voluptatem dolorem ut numquam dolorum delectus autem veritatis facilis. Et ea ut repellat
ea. Facere est dolores fugiat dolor.</p>
</div>
</div><!-- End slide item -->
@ -83,15 +201,18 @@ require_once __DIR__ . '/header.php';
<div class="item">
<h3 class="mb-3">Aliquid non alias minus</h3>
<h4 class="mb-3">Necessitatibus voluptatibus explicabo dolores a vitae voluptatum.</h4>
<p>Neque voluptates aut. Soluta aut perspiciatis porro deserunt. Voluptate ut itaque velit. Aut consectetur voluptatem aspernatur sequi sit laborum. Voluptas enim dolorum fugiat aut.</p>
<p>Neque voluptates aut. Soluta aut perspiciatis porro deserunt. Voluptate ut itaque velit. Aut
consectetur voluptatem aspernatur sequi sit laborum. Voluptas enim dolorum fugiat aut.</p>
</div>
</div><!-- End slide item -->
<div class="swiper-slide">
<div class="item">
<h3 class="mb-3">Necessitatibus suscipit non voluptatem quibusdam</h3>
<h4 class="mb-3">Tempora quos est ut quia adipisci ut voluptas. Deleniti laborum soluta nihil est. Eum similique neque autem ut.</h4>
<p>Ut rerum et autem vel. Et rerum molestiae aut sit vel incidunt sit at voluptatem. Saepe dolorem et sed voluptate impedit. Ad et qui sint at qui animi animi rerum.</p>
<h4 class="mb-3">Tempora quos est ut quia adipisci ut voluptas. Deleniti laborum soluta nihil est. Eum
similique neque autem ut.</h4>
<p>Ut rerum et autem vel. Et rerum molestiae aut sit vel incidunt sit at voluptatem. Saepe dolorem et
sed voluptate impedit. Ad et qui sint at qui animi animi rerum.</p>
</div>
</div><!-- End slide item -->
@ -107,10 +228,10 @@ require_once __DIR__ . '/header.php';
</div>
</section><!-- /Why Us Section -->
</section><!-- /Why Us Section -->
<!-- Services Section -->
<section id="services" class="services section">
<!-- Services Section -->
<section id="services" class="services section">
<!-- Section Title -->
<div class="container section-title" data-aos="fade-up">
@ -126,7 +247,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-briefcase" style="color: #f57813;"></i></div>
<div>
<h4 class="title">Lorem Ipsum</h4>
<p class="description">Voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident</p>
<p class="description">Voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint
occaecati cupiditate non provident</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div>
@ -136,7 +258,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-card-checklist" style="color: #15a04a;"></i></div>
<div>
<h4 class="title">Dolor Sitema</h4>
<p class="description">Minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat tarad limino ata</p>
<p class="description">Minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat tarad limino ata</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div><!-- End Service Item -->
@ -145,7 +268,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-bar-chart" style="color: #d90769;"></i></div>
<div>
<h4 class="title">Sed ut perspiciatis</h4>
<p class="description">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur</p>
<p class="description">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div><!-- End Service Item -->
@ -154,7 +278,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-binoculars" style="color: #15bfbc;"></i></div>
<div>
<h4 class="title">Magni Dolores</h4>
<p class="description">Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
<p class="description">Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div><!-- End Service Item -->
@ -163,7 +288,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-brightness-high" style="color: #f5cf13;"></i></div>
<div>
<h4 class="title">Nemo Enim</h4>
<p class="description">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque</p>
<p class="description">At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium
voluptatum deleniti atque</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div><!-- End Service Item -->
@ -172,7 +298,8 @@ require_once __DIR__ . '/header.php';
<div class="icon flex-shrink-0"><i class="bi bi-calendar4-week" style="color: #1335f5;"></i></div>
<div>
<h4 class="title">Eiusmod Tempor</h4>
<p class="description">Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi</p>
<p class="description">Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum
soluta nobis est eligendi</p>
<a href="#" class="readmore stretched-link"><span>了解更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div><!-- End Service Item -->
@ -181,189 +308,130 @@ require_once __DIR__ . '/header.php';
</div>
</section><!-- /Services Section -->
</section>
<!-- Call To Action Section -->
<section id="call-to-action" class="call-to-action section dark-background">
<section id="recent-posts" class="recent-posts section">
<img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/cta-bg.jpg" alt="">
<div class="container section-title" data-aos="fade-up">
<h2>最新新闻</h2>
</div>
<div class="container">
<div class="row gy-5">
<?php if (!empty($newsList)): ?>
<?php foreach ($newsList as $i => $item): ?>
<?php
// 处理新闻数据
$title = $item['title'] ?? '无标题';
$summary = $item['summary'] ?? $item['description'] ?? '';
// 截取摘要长度
$displaySummary = mb_strlen($summary) > 80 ? mb_substr($summary, 0, 80) . '...' : $summary;
// 格式化日期
$postDate = !empty($item['publish_date']) ? date('Y年m月d日', strtotime($item['publish_date'])) : '';
// 处理图片地址:如果接口返回的是相对路径,需要拼接 $apiUrl
$thumbUrl = $item['thumb'] ?? $item['image'] ?? '';
if ($thumbUrl) {
$imgSrc = (strpos($thumbUrl, 'http') === 0) ? $thumbUrl : ($apiUrl . $thumbUrl);
} else {
// 默认占位图
$imgIndex = ($i % 4) + 1;
$imgSrc = $baseUrl . "/themes/template3/assets/img/blog/blog-{$imgIndex}.jpg";
}
// 文章详情链接
$articleUrl = $apiUrl . '/article_detail/' . ($item['id'] ?? 0);
// 计算 AOS 动画延迟
$delay = ($i % 4) * 200;
?>
<div class="col-xl-3 col-md-6" data-aos="fade-up" data-aos-delay="<?php echo $delay; ?>">
<div class="post-box">
<div class="post-img">
<img src="<?php echo $imgSrc; ?>" class="img-fluid" alt="<?php echo htmlspecialchars($title); ?>">
</div>
<div class="meta">
<!-- <span class="post-date"><?php echo $postDate; ?></span> -->
<!-- <?php if (!empty($item['author'])): ?>
<span class="post-author"> / <?php echo htmlspecialchars($item['author']); ?></span>
<?php endif; ?> -->
</div>
<h3 class="post-title"><?php echo htmlspecialchars($title); ?></h3>
<p><?php echo htmlspecialchars($displaySummary); ?></p>
<a href="<?php echo $articleUrl; ?>" class="readmore stretched-link">
<span>阅读更多</span><i class="bi bi-arrow-right"></i>
</a>
</div>
</div><?php endforeach; ?>
<?php else: ?>
<div class="col-12 text-center">
<p>暂无新闻数据</p>
</div>
<?php endif; ?>
</div>
</div>
</section>
<section id="call-to-action" class="call-to-action section dark-background">
<img src="<?php echo $apiUrl; ?>/themes/template3/assets/img/cta-bg.jpg" alt="">
<div class="container">
<div class="row justify-content-center" data-aos="zoom-in" data-aos-delay="100">
<div class="col-xl-10">
<div class="text-center">
<h3>联系我们</h3>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<a class="cta-btn" href="#">联系我们</a>
<p><?php echo $homeInfo['contact']['contact_phone']; ?></p>
<p><?php echo $homeInfo['contact']['contact_email']; ?></p>
<p><?php echo $homeInfo['contact']['address']; ?></p>
<p><?php echo $homeInfo['contact']['worktime']; ?></p>
<a class="cta-btn" href="/">联系我们</a>
</div>
</div>
</div>
</div>
</section><!-- /Call To Action Section -->
</section>
<!-- Features Section -->
<section id="features" class="features section">
<section id="features" class="features section">
<div class="container section-title" data-aos="fade-up">
<h2>合作伙伴</h2>
</div>
<div class="container">
<div class="row">
<div class="col-lg-7" data-aos="fade-up" data-aos-delay="100">
<h3 class="mb-0">强大的功能</h3>
<h3>为您的企业</h3>
<div class="row gy-4">
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-eye" style="color: #ff8b2c;"></i>
<span>Easy Cart Features</span>
<?php if (!empty($friendlinkList)): ?>
<?php foreach ($friendlinkList as $link): ?>
<div class="col-xl-3 col-md-6" data-aos="zoom-out" data-aos-delay="200">
<div class="feature-box">
<a href="<?php echo htmlspecialchars($link['link_url'] ?? '#'); ?>" target="_blank" rel="noopener noreferrer">
<?php if (!empty($link['link_logo'])): ?>
<img src="<?php echo htmlspecialchars($link['link_logo']); ?>"
alt="<?php echo htmlspecialchars($link['link_name'] ?? ''); ?>" class="img-fluid">
<?php endif; ?>
</a>
</div>
</div><!-- End Icon List Item-->
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col-12 text-center">
<p>暂无合作伙伴</p>
</div>
<?php endif; ?>
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-infinity" style="color: #5578ff;"></i>
<span>Sit amet consectetur adipisicing</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-mortarboard" style="color: #e80368;"></i>
<span>Ipsum Rerum Explicabo</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-star" style="color: #ffa76e;"></i>
<span>Easy Cart Features</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-x-diamond" style="color: #11dbcf;"></i>
<span>Easy Cart Features</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-camera-video" style="color: #4233ff;"></i>
<span>Sit amet consectetur adipisicing</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-brightness-high" style="color: #29cc61;"></i>
<span>Ipsum Rerum Explicabo</span>
</div>
</div><!-- End Icon List Item-->
<div class="col-md-6">
<div class="icon-list d-flex">
<i class="bi bi-activity" style="color: #ff5828;"></i>
<span>Easy Cart Features</span>
</div>
</div><!-- End Icon List Item-->
</div>
</div>
<div class="col-lg-5 position-relative" data-aos="zoom-out" data-aos-delay="200">
<div class="phone-wrap">
<img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/iphone.png" alt="Image" class="img-fluid">
</div>
</div>
</div>
</div>
</section>
<div class="details">
<div class="container">
<div class="row">
<div class="col-md-6" data-aos="fade-up" data-aos-delay="300">
<h4>Labore Sdio Lidui<br>Bonde Naruto</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam nostrum molestias doloremque quae delectus odit minima corrupti blanditiis quo animi!</p>
<a href="#about" class="btn-get-started">开始使用</a>
</div>
</div>
</div>
</div>
</section><!-- /Features Section -->
<!-- Recent Posts Section -->
<section id="recent-posts" class="recent-posts section">
<!-- Section Title -->
<div class="container section-title" data-aos="fade-up">
<h2>最新博客文章</h2>
</div><!-- End Section Title -->
<div class="container">
<div class="row gy-5">
<div class="col-xl-3 col-md-6" data-aos="fade-up" data-aos-delay="200">
<div class="post-box">
<div class="post-img"><img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/blog/blog-1.jpg" class="img-fluid" alt=""></div>
<div class="meta">
<span class="post-date">Tue, December 12</span>
<span class="post-author"> / Julia Parker</span>
</div>
<h3 class="post-title">Eum ad dolor et. Autem aut fugiat debitis</h3>
<p>Illum voluptas ab enim placeat. Adipisci enim velit nulla. Vel omnis laudantium. Asperiores eum ipsa est officiis. Modi qui magni est...</p>
<a href="<?php echo $baseUrl; ?>/blog-details.php" class="readmore stretched-link"><span>阅读更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div>
<div class="col-xl-3 col-md-6" data-aos="fade-up" data-aos-delay="400">
<div class="post-box">
<div class="post-img"><img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/blog/blog-2.jpg" class="img-fluid" alt=""></div>
<div class="meta">
<span class="post-date">Fri, September 05</span>
<span class="post-author"> / Mario Douglas</span>
</div>
<h3 class="post-title">Et repellendus molestiae qui est sed omnis</h3>
<p>Voluptatem nesciunt omnis libero autem tempora enim ut ipsam id. Odit quia ab eum assumenda. Quisquam omnis doloribus...</p>
<a href="<?php echo $baseUrl; ?>/blog-details.php" class="readmore stretched-link"><span>阅读更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div>
<div class="col-xl-3 col-md-6" data-aos="fade-up" data-aos-delay="600">
<div class="post-box">
<div class="post-img"><img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/blog/blog-3.jpg" class="img-fluid" alt=""></div>
<div class="meta">
<span class="post-date">Tue, July 27</span>
<span class="post-author"> / Lisa Hunter</span>
</div>
<h3 class="post-title">Quia assumenda est et veritati</h3>
<p>Quia nam eaque omnis explicabo similique eum quaerat similique laboriosam. Quis omnis repellat sed quae consectetur magnam...</p>
<a href="<?php echo $baseUrl; ?>/blog-details.php" class="readmore stretched-link"><span>阅读更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div>
<div class="col-xl-3 col-md-6" data-aos="fade-up" data-aos-delay="600">
<div class="post-box">
<div class="post-img"><img src="<?php echo $baseUrl; ?>/themes/template3/assets/img/blog/blog-4.jpg" class="img-fluid" alt=""></div>
<div class="meta">
<span class="post-date">Tue, Sep 16</span>
<span class="post-author"> / Mario Douglas</span>
</div>
<h3 class="post-title">Pariatur quia facilis similique deleniti</h3>
<p>Et consequatur eveniet nam voluptas commodi cumque ea est ex. Aut quis omnis sint ipsum earum quia eligendi...</p>
<a href="<?php echo $baseUrl; ?>/blog-details.php" class="readmore stretched-link"><span>阅读更多</span><i class="bi bi-arrow-right"></i></a>
</div>
</div>
</div>
</div>
</section><!-- /Recent Posts Section -->
</main>
</main>
<?php require_once __DIR__ . '/footer.php'; ?>