427 lines
12 KiB
PHP
427 lines
12 KiB
PHP
<?php
|
|
// 1. 引入 ThinkPHP 环境
|
|
$rootPath = dirname(__DIR__, 3) . DIRECTORY_SEPARATOR;
|
|
require_once $rootPath . 'vendor/autoload.php';
|
|
|
|
use think\facade\Db;
|
|
use think\App;
|
|
|
|
// 初始化应用
|
|
$app = new App($rootPath);
|
|
$app->initialize();
|
|
|
|
// 获取基础环境信息
|
|
$host = $_SERVER['HTTP_HOST'] ?? '';
|
|
$scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http';
|
|
$baseUrl = $scheme . '://' . $host;
|
|
$themeBase = '/themes/default';
|
|
|
|
// 获取文章 ID
|
|
$articleId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
|
|
|
// 辅助处理函数
|
|
function formatImageUrl($path, $baseUrl)
|
|
{
|
|
if (empty($path)) return '';
|
|
if (preg_match('/^https?:\/\//', $path)) return $path;
|
|
return $baseUrl . (strpos($path, '/') === 0 ? '' : '/') . $path;
|
|
}
|
|
|
|
try {
|
|
// 1. 获取租户 ID
|
|
$tenantDomain = Db::name('mete_tenant_domain')
|
|
->where('full_domain', $host)
|
|
->where('status', 1)
|
|
->whereNull('delete_time')
|
|
->find();
|
|
$tid = $tenantDomain ? (int)$tenantDomain['tid'] : 0;
|
|
|
|
if ($tid === 0 || $articleId === 0) {
|
|
die("未找到相关内容");
|
|
}
|
|
|
|
// 2. 获取站点基础信息
|
|
$setting = Db::name('mete_system_site_setting')->where('tid', $tid)->whereNull('delete_time')->find();
|
|
$tenant = Db::name('mete_tenant')->where('id', $tid)->whereNull('delete_time')->find();
|
|
$siteInfo = array_merge($tenant ?: [], $setting ?: []);
|
|
|
|
// 3. 获取文章详细数据
|
|
$article = Db::name('mete_articles')
|
|
->where('id', $articleId)
|
|
->where('tid', $tid)
|
|
->whereNull('delete_time')
|
|
->find();
|
|
|
|
if (!$article) {
|
|
die("文章不存在或已删除");
|
|
}
|
|
|
|
// 更新阅读数 (可选)
|
|
Db::name('mete_articles')->where('id', $articleId)->inc('views')->update();
|
|
} catch (\Exception $e) {
|
|
die("系统错误: " . $e->getMessage());
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html class="no-js" lang="zh-CN">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
|
<title><?php echo htmlspecialchars($article['title']); ?> - <?php echo $siteInfo['sitename']; ?></title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
|
|
<link rel="stylesheet" href="<?php echo $themeBase; ?>/assets/css/bootstrap-5.0.0-beta1.min.css" />
|
|
<link rel="stylesheet" href="<?php echo $themeBase; ?>/assets/css/LineIcons.2.0.css" />
|
|
<link rel="stylesheet" href="<?php echo $themeBase; ?>/assets/css/animate.css" />
|
|
<link rel="stylesheet" href="<?php echo $themeBase; ?>/assets/css/lindy-uikit.css" />
|
|
<link rel="stylesheet" href="<?php echo $themeBase; ?>/assets/css/all.min.css" />
|
|
|
|
<style>
|
|
:root {
|
|
--ink: #0f172a;
|
|
--muted: #475569;
|
|
--line: rgba(15, 23, 42, 0.10);
|
|
--card: rgba(255, 255, 255, 0.86);
|
|
--accent: #5864FF;
|
|
--accent2: #22c55e;
|
|
--shadow: 0 16px 50px rgba(2, 6, 23, 0.12);
|
|
}
|
|
|
|
body {
|
|
color: var(--ink);
|
|
background:
|
|
radial-gradient(1100px 420px at 12% 0%, rgba(88, 100, 255, 0.20), transparent 55%),
|
|
radial-gradient(900px 380px at 86% 10%, rgba(34, 197, 94, 0.12), transparent 55%),
|
|
linear-gradient(180deg, #fbfdff 0%, #f6f8ff 100%);
|
|
}
|
|
|
|
/* 顶部简洁导航 */
|
|
.navbar-brand img {
|
|
max-width: 260px;
|
|
}
|
|
|
|
.article-topbar {
|
|
margin-top: 18px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 16px;
|
|
background: var(--card);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: 0 10px 30px rgba(2, 6, 23, 0.06);
|
|
}
|
|
|
|
.article-topbar .navbar {
|
|
padding: 12px 14px;
|
|
}
|
|
|
|
.article-topbar .back-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 12px;
|
|
border-radius: 999px;
|
|
border: 1px solid var(--line);
|
|
color: var(--ink);
|
|
background: rgba(255, 255, 255, 0.55);
|
|
text-decoration: none;
|
|
transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
|
|
}
|
|
|
|
.article-topbar .back-link:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 10px 25px rgba(2, 6, 23, 0.10);
|
|
background: rgba(255, 255, 255, 0.75);
|
|
}
|
|
|
|
.article-topbar .back-link i {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.breadcrumb-area {
|
|
padding: 18px 0;
|
|
background: transparent;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.breadcrumb {
|
|
margin: 0;
|
|
padding: 12px 16px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 14px;
|
|
background: var(--card);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: 0 10px 30px rgba(2, 6, 23, 0.06);
|
|
}
|
|
|
|
.breadcrumb-area a {
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.breadcrumb-area a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.article-header {
|
|
padding: 46px 0 18px;
|
|
background: transparent;
|
|
}
|
|
|
|
.article-title {
|
|
font-size: 34px;
|
|
font-weight: 800;
|
|
color: var(--ink);
|
|
line-height: 1.25;
|
|
letter-spacing: -0.02em;
|
|
margin: 0 0 16px;
|
|
}
|
|
|
|
.article-meta {
|
|
display: flex;
|
|
gap: 14px;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
color: var(--muted);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.article-meta span {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 8px 12px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.70);
|
|
backdrop-filter: blur(8px);
|
|
}
|
|
|
|
.article-meta i {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.article-content {
|
|
padding: 22px 0 70px;
|
|
line-height: 1.85;
|
|
font-size: 16px;
|
|
color: var(--ink);
|
|
}
|
|
|
|
.article-content .col-lg-10 {
|
|
background: var(--card);
|
|
border: 1px solid var(--line);
|
|
border-radius: 18px;
|
|
box-shadow: var(--shadow);
|
|
padding: 26px 22px;
|
|
backdrop-filter: blur(12px);
|
|
}
|
|
|
|
.article-content img {
|
|
max-width: 100% !important;
|
|
height: auto !important;
|
|
border-radius: 14px;
|
|
margin: 18px 0;
|
|
box-shadow: 0 14px 40px rgba(2, 6, 23, 0.10);
|
|
}
|
|
|
|
/* 富文本排版:标题/段落/链接/列表/引用/代码 */
|
|
.content-text {
|
|
color: var(--ink);
|
|
/* border-top: 1px solid #efefef; */
|
|
padding: 60px;
|
|
}
|
|
|
|
.content-text p {
|
|
margin: 0 0 14px;
|
|
color: #1f2937;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.content-text a {
|
|
color: var(--accent);
|
|
text-decoration: underline;
|
|
text-underline-offset: 3px;
|
|
}
|
|
|
|
.content-text a:hover {
|
|
color: #3b49ff;
|
|
}
|
|
|
|
.content-text h1,
|
|
.content-text h2,
|
|
.content-text h3,
|
|
.content-text h4 {
|
|
color: var(--ink);
|
|
font-weight: 800;
|
|
margin: 26px 0 12px;
|
|
line-height: 1.25;
|
|
}
|
|
|
|
.content-text h2 {
|
|
font-size: 22px;
|
|
}
|
|
|
|
.content-text h3 {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.content-text ul,
|
|
.content-text ol {
|
|
margin: 10px 0 18px 1.1rem;
|
|
}
|
|
|
|
.content-text li {
|
|
margin: 6px 0;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.content-text blockquote {
|
|
margin: 18px 0;
|
|
padding: 14px 16px;
|
|
border-left: 4px solid var(--accent);
|
|
background: rgba(88, 100, 255, 0.07);
|
|
border-radius: 12px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.content-text hr {
|
|
border: 0;
|
|
border-top: 1px solid var(--line);
|
|
margin: 24px 0;
|
|
}
|
|
|
|
.content-text code {
|
|
padding: 2px 6px;
|
|
border-radius: 8px;
|
|
background: rgba(15, 23, 42, 0.06);
|
|
color: #0b1220;
|
|
font-size: 0.92em;
|
|
}
|
|
|
|
.content-text pre {
|
|
margin: 16px 0 22px;
|
|
padding: 16px 16px;
|
|
border-radius: 14px;
|
|
background: #0b1220;
|
|
color: #e5e7eb;
|
|
overflow: auto;
|
|
box-shadow: 0 18px 60px rgba(2, 6, 23, 0.25);
|
|
}
|
|
|
|
.content-text pre code {
|
|
background: transparent;
|
|
color: inherit;
|
|
padding: 0;
|
|
font-size: 0.92em;
|
|
}
|
|
|
|
.content-text p img {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
footer {
|
|
background: rgba(2, 6, 23, 0.92);
|
|
padding: 44px 0;
|
|
color: rgba(226, 232, 240, 0.86);
|
|
}
|
|
|
|
footer p {
|
|
margin: 0;
|
|
}
|
|
|
|
@media (max-width: 576px) {
|
|
.article-title {
|
|
font-size: 26px;
|
|
}
|
|
|
|
.article-content .col-lg-10 {
|
|
padding: 18px 14px;
|
|
border-radius: 16px;
|
|
}
|
|
|
|
.breadcrumb {
|
|
border-radius: 12px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="container">
|
|
<div class="article-topbar">
|
|
<nav class="navbar navbar-expand-lg">
|
|
<a class="navbar-brand" href="/">
|
|
<img src="<?php echo formatImageUrl($siteInfo['logo'] ?? '', $baseUrl); ?>" alt="Logo" />
|
|
</a>
|
|
<div class="ms-auto">
|
|
<a class="back-link" href="/">
|
|
<i class="lni lni-arrow-left"></i>
|
|
返回首页
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="breadcrumb-area">
|
|
<div class="container">
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="/">首页</a></li>
|
|
<li class="breadcrumb-item active" aria-current="page">文章详情</li>
|
|
</ol>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<section class="article-header">
|
|
<div class="container">
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-10 text-center">
|
|
<h1 class="article-title"><?php echo htmlspecialchars($article['title']); ?></h1>
|
|
<div class="article-meta">
|
|
<span><i class="lni lni-calendar"></i> <?php echo date('Y-m-d', strtotime($article['publish_date'])); ?></span>
|
|
<span><i class="lni lni-eye"></i> 阅读: <?php echo $article['views']; ?></span>
|
|
<span><i class="lni lni-user"></i> 管理员</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="article-content">
|
|
<div class="container">
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-10">
|
|
<!-- <?php if (!empty($article['image'])): ?>
|
|
<div class="text-center mb-40">
|
|
<img src="<?php echo formatImageUrl($article['image'], $baseUrl); ?>" style="width: 100%;">
|
|
</div>
|
|
<?php endif; ?> -->
|
|
|
|
<div class="content-text">
|
|
<?php
|
|
// 替换内容中的相对图片路径为绝对路径
|
|
$content = $article['content'];
|
|
$content = str_replace('src="/uploads/', 'src="' . $baseUrl . '/uploads/', $content);
|
|
echo $content;
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<footer>
|
|
<div class="container text-center">
|
|
<p>Copyright © 2026 <?php echo $siteInfo['companyname']; ?> | <?php echo $siteInfo['icp']; ?></p>
|
|
</div>
|
|
</footer>
|
|
|
|
<script src="<?php echo $themeBase; ?>/assets/js/bootstrap-5.0.0-beta1.min.js"></script>
|
|
</body>
|
|
|
|
</html>
|