Files
echart/quant/report.php
T
simonandClaude Opus 4.7 eedead0d41 feat: 全面代码更新 - ECharts 5.4.2 重构、新增量化分析模块、前端库升级
- 升级 ECharts 到 5.4.2,重构 lib/ 目录结构
- 新增 DataTables 2.x 和 FixedColumns 插件
- 新增 quant/ 宏观研究报告模块
- 重构图表页面:stock_trend、hkholdbycode 等采用 JS fetch API.doorcome.cn 模式
- 新增 CLAUDE.md 补充页面文档和新数据流说明
- 更新 inc/config.php TuShare API 配置
- 更新新闻联播分析模块 news/ 和相关研究报告 research/
- 新增 api_document/ 参考文档
- 清理 .gitignore,排除 uploads/xls/.mcp.json/ source maps 等非代码文件
- 所有 PHP 文件通过 php -l 语法检查

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 18:01:55 +08:00

139 lines
6.5 KiB
PHP

<?php
include_once __DIR__ . "/../inc/config.php";
$id = intval($_GET['id'] ?? 0);
if ($id <= 0) {
header("Location: index.php");
exit();
}
$mysqli = get_mysqli_connection();
$stmt = $mysqli->prepare("SELECT * FROM mac_report WHERE id = ? AND is_active = 1");
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
$report = $result->fetch_assoc();
$stmt->close();
$mysqli->close();
if (!$report) {
header("Location: index.php");
exit();
}
$date = $report['report_date'];
$title = $report['title'];
$content = $report['content'];
$subject_type = $report['subject_type'];
$subject_code = $report['subject_code'];
$created_at = $report['created_at'] ? date('Y-m-d H:i', strtotime($report['created_at'])) : '';
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($title) ?> - 宏观研究</title>
<script src="/lib/js/tailwindcss-3.4.17.js"></script>
<script src="/lib/js/marked-15.0.12.min.js"></script>
<style type="text/tailwindcss">
@layer utilities {
.prose h1 { @apply text-2xl font-bold text-gray-900 mt-8 mb-4 pb-2 border-b border-gray-200; }
.prose h2 { @apply text-xl font-semibold text-gray-900 mt-6 mb-3; }
.prose h3 { @apply text-lg font-semibold text-gray-800 mt-5 mb-2; }
.prose h4 { @apply text-base font-semibold text-gray-800 mt-4 mb-2; }
.prose p { @apply text-gray-700 leading-relaxed my-3; }
.prose strong { @apply font-semibold text-gray-900; }
.prose a { @apply text-indigo-600 hover:text-indigo-800 underline decoration-indigo-300 hover:decoration-indigo-600 transition-colors; }
.prose blockquote { @apply border-l-4 border-indigo-300 bg-indigo-50 pl-4 pr-2 py-2 my-4 rounded-r text-gray-700 italic; }
.prose ul { @apply list-disc pl-6 my-3 space-y-1; }
.prose ol { @apply list-decimal pl-6 my-3 space-y-1; }
.prose li { @apply text-gray-700 leading-relaxed; }
.prose code { @apply bg-gray-100 text-pink-600 px-1.5 py-0.5 rounded text-sm font-mono; }
.prose pre { @apply bg-gray-900 text-gray-100 rounded-lg p-4 my-4 overflow-x-auto; }
.prose pre code { @apply bg-transparent text-gray-100 px-0 py-0; }
.prose table { @apply w-full border-collapse my-4 text-sm; }
.prose thead { @apply bg-gray-50; }
.prose th { @apply border border-gray-300 px-3 py-2 text-left font-semibold text-gray-700; }
.prose td { @apply border border-gray-300 px-3 py-2 text-gray-600; }
.prose tr:hover td { @apply bg-gray-50; }
.prose hr { @apply border-0 border-t border-gray-200 my-8; }
.prose img { @apply max-w-full rounded-lg my-4; }
.prose em { @apply italic; }
}
</style>
</head>
<body class="bg-gray-50 min-h-screen font-sans text-gray-900 antialiased">
<header class="bg-white shadow-sm sticky top-0 z-50 border-b border-gray-200">
<div class="max-w-3xl mx-auto px-4 py-4 flex justify-between items-center">
<div class="flex items-center space-x-2 min-w-0">
<a href="index.php" class="flex items-center space-x-2 hover:opacity-80 transition-opacity">
<div class="w-8 h-8 bg-indigo-600 rounded-lg flex items-center justify-center flex-shrink-0">
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
<span class="text-lg font-bold hidden sm:inline">宏观研究</span>
</a>
</div>
<div class="flex items-center space-x-4">
<a href="/index-2.php" class="text-sm text-gray-400 hover:text-indigo-600 transition-colors">首页</a>
</div>
</div>
</header>
<main class="max-w-3xl mx-auto px-4 py-8">
<article>
<!-- Report header -->
<div class="mb-8">
<div class="flex items-center space-x-3 mb-3">
<?php if ($subject_type): ?>
<span class="px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-700 uppercase tracking-wide"><?= htmlspecialchars($subject_type) ?></span>
<?php endif; ?>
<time class="text-sm text-gray-400">报告日期:<?= $date ?></time>
<?php if ($created_at): ?>
<span class="text-sm text-gray-400">生成时间:<?= $created_at ?></span>
<?php endif; ?>
</div>
<h1 class="text-2xl md:text-3xl font-bold text-gray-900 leading-tight"><?= htmlspecialchars($title) ?></h1>
<?php if ($subject_code): ?>
<p class="text-sm text-gray-400 mt-2"><?= htmlspecialchars($subject_code) ?></p>
<?php endif; ?>
</div>
<!-- Divider -->
<div class="border-t border-gray-200 my-6"></div>
<!-- Markdown content rendered by marked.js -->
<div id="content" class="prose max-w-none"></div>
</article>
<div class="border-t border-gray-200 mt-10 pt-6 text-center">
<a href="index.php" class="inline-flex items-center space-x-1 text-sm text-indigo-600 hover:text-indigo-800 transition-colors">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
<span>返回列表</span>
</a>
</div>
</main>
<footer class="border-t border-gray-200 py-8 text-center text-sm text-gray-400">
<p>宏观研究 &copy; <?= date('Y') ?></p>
</footer>
<script>
var rawContent = <?= json_encode($content) ?>;
document.addEventListener('DOMContentLoaded', function() {
// Configure marked
marked.setOptions({
breaks: true,
gfm: true,
});
var html = marked.parse(rawContent);
document.getElementById('content').innerHTML = html;
});
</script>
</body>
</html>