Fundamental_Analysis/frontend/src/app/docs/page.tsx
xucheng b5a4d2212c feat: 实现动态分析配置并优化前端UI
本次提交引入了一系列重要功能,核心是实现了财务分析模块的动态配置,并对配置和报告页面的用户界面进行了改进。

主要变更:

- **动态配置:**
  - 后端实现了 `ConfigManager` 服务,用于动态管理 `analysis-config.json` 和 `config.json`。
  - 添加了用于读取和更新配置的 API 端点。
  - 开发了前端 `/config` 页面,允许用户实时查看和修改分析配置。

- **后端增强:**
  - 更新了 `AnalysisClient` 和 `CompanyProfileClient` 以使用新的配置系统。
  - 重构了财务数据相关的路由。

- **前端改进:**
  - 新增了可复用的 `Checkbox` UI 组件。
  - 使用更直观和用户友好的界面重新设计了配置页面。
  - 改进了财务报告页面的布局和数据展示。

- **文档与杂务:**
  - 更新了设计和需求文档以反映新功能。
  - 更新了前后端依赖。
  - 修改了开发脚本 `dev.sh`。
2025-10-30 14:50:36 +08:00

69 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { promises as fs } from 'fs';
import path from 'path';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
async function getMarkdownContent() {
// process.cwd() is the root of the Next.js project (the 'frontend' directory)
const mdPath = path.join(process.cwd(), '..', 'docs', 'design.md');
try {
const content = await fs.readFile(mdPath, 'utf8');
return content;
} catch (error) {
console.error("Failed to read design.md:", error);
return "# 文档加载失败\n\n无法读取 `docs/design.md` 文件。请检查文件是否存在以及服务器权限。";
}
}
export default async function DocsPage() {
const content = await getMarkdownContent();
return (
<div className="container mx-auto py-6 space-y-6">
<header className="space-y-2">
<h1 className="text-3xl font-bold"></h1>
<p className="text-muted-foreground">
</p>
</header>
<Card>
<CardContent className="p-6">
<article className="prose prose-zinc max-w-none dark:prose-invert">
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h1: ({node, ...props}) => <h1 className="text-3xl font-bold mb-4 mt-8 border-b pb-2" {...props} />,
h2: ({node, ...props}) => <h2 className="text-2xl font-bold mb-3 mt-6 border-b pb-2" {...props} />,
h3: ({node, ...props}) => <h3 className="text-xl font-semibold mb-2 mt-4" {...props} />,
p: ({node, ...props}) => <p className="mb-4 leading-7" {...props} />,
ul: ({node, ...props}) => <ul className="list-disc list-inside mb-4 space-y-2" {...props} />,
ol: ({node, ...props}) => <ol className="list-decimal list-inside mb-4 space-y-2" {...props} />,
li: ({node, ...props}) => <li className="ml-4" {...props} />,
code: ({node, inline, className, children, ...props}: any) => {
const match = /language-(\w+)/.exec(className || '');
return !inline ? (
<code className={className} {...props}>
{children}
</code>
) : (
<code className="bg-muted px-1.5 py-1 rounded text-sm font-mono" {...props}>
{children}
</code>
);
},
pre: ({children}) => <pre className="bg-muted p-4 rounded my-4 overflow-x-auto">{children}</pre>,
table: ({node, ...props}) => <div className="overflow-x-auto my-4"><table className="border-collapse border border-border w-full" {...props} /></div>,
th: ({node, ...props}) => <th className="border border-border px-4 py-2 bg-muted font-semibold text-left" {...props} />,
td: ({node, ...props}) => <td className="border border-border px-4 py-2" {...props} />,
a: ({node, ...props}) => <a className="text-primary underline hover:text-primary/80" {...props} />,
}}
>
{content}
</ReactMarkdown>
</article>
</CardContent>
</Card>
</div>
);
}