本次提交引入了一系列重要功能,核心是实现了财务分析模块的动态配置,并对配置和报告页面的用户界面进行了改进。 主要变更: - **动态配置:** - 后端实现了 `ConfigManager` 服务,用于动态管理 `analysis-config.json` 和 `config.json`。 - 添加了用于读取和更新配置的 API 端点。 - 开发了前端 `/config` 页面,允许用户实时查看和修改分析配置。 - **后端增强:** - 更新了 `AnalysisClient` 和 `CompanyProfileClient` 以使用新的配置系统。 - 重构了财务数据相关的路由。 - **前端改进:** - 新增了可复用的 `Checkbox` UI 组件。 - 使用更直观和用户友好的界面重新设计了配置页面。 - 改进了财务报告页面的布局和数据展示。 - **文档与杂务:** - 更新了设计和需求文档以反映新功能。 - 更新了前后端依赖。 - 修改了开发脚本 `dev.sh`。
69 lines
3.3 KiB
TypeScript
69 lines
3.3 KiB
TypeScript
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>
|
||
);
|
||
} |