diff --git a/README.md b/README.md index af8d28b..06459e7 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,11 @@ docker run --rm -i \ And then you can configure the access. +## 中文文档 + +- [入门指南](docs/zh-CN/getting-started-zh.md) +- [前端集成指南](docs/zh-CN/frontend-integration-zh.md) + ## For Developers ### Quick Start Guides diff --git a/docs/zh-CN/frontend-integration-zh.md b/docs/zh-CN/frontend-integration-zh.md new file mode 100644 index 0000000..9f33a36 --- /dev/null +++ b/docs/zh-CN/frontend-integration-zh.md @@ -0,0 +1,370 @@ +# WebLedger 前端集成指南 + +本文档介绍如何将前端应用程序与 WebLedger 后端 API 集成。 + +## API 基础 + +### 基础 URL +- **开发环境**: `http://localhost:5000` +- **生产环境**: `https://your-domain.com` + +所有 API 端点都以 `/api` 为前缀。 + +### 身份验证 + +WebLedger 使用基于 JWT(JSON Web Tokens)的身份验证。 + +#### 1. 登录获取令牌 + +```http +POST /api/auth/login +Content-Type: application/json + +{ + "username": "your-username", + "password": "your-password" +} +``` + +成功响应: +```json +{ + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "expiresIn": 3600, + "user": { + "id": 1, + "username": "your-username" + } +} +``` + +#### 2. 在请求中使用令牌 + +```http +GET /api/ledger/entries +Authorization: Bearer +``` + +## React 集成示例 + +### 项目设置 + +```bash +# 创建新的 React 应用(TypeScript 模板) +npx create-react-app my-ledger-app --template typescript +cd my-ledger-app + +# 安装必要的依赖 +npm install axios +npm install @mui/material @emotion/react @emotion/styled +npm install @mui/icons-material +``` + +### 创建 API 服务 + +`src/services/api.ts`: +```typescript +import axios from 'axios'; + +const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:5000'; + +const api = axios.create({ + baseURL: API_BASE_URL, + timeout: 10000, +}); + +// 请求拦截器:添加认证令牌 +api.interceptors.request.use( + (config) => { + const token = localStorage.getItem('auth_token'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +// 响应拦截器:处理错误 + return Promise.reject(error); + } +); + +// API 方法 +export const authAPI = { + login: (username: string, password: string) => + api.post('/api/auth/login', { username, password }), + }, +}; + +export const ledgerAPI = { + getEntries: (params?: { startDate?: string; endDate?: string; category?: string }) => + api.get('/api/ledger/entries', { params }), + + createEntry: (entry: { + date: string; + description: string; + amount: number; + category: string; + notes?: string; + }) => api.post('/api/ledger/entries', entry), + + getCategories: () => api.get('/api/ledger/categories'), + + getSummary: (params?: { startDate?: string; endDate?: string }) => + api.get('/api/ledger/summary', { params }), +}; + +export default api; +``` + +### 登录组件示例 + +`src/components/Login.tsx`: +```typescript +import React, { useState } from 'react'; +import { TextField, Button, Box, Alert } from '@mui/material'; +import { authAPI } from '../services/api'; + +const Login: React.FC<{ onLoginSuccess: () => void }> = ({ onLoginSuccess }) => { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + try { + const response = await authAPI.login(username, password); + localStorage.setItem('auth_token', response.data.token); + onLoginSuccess(); + } catch (err) { + setError('登录失败,请检查用户名和密码'); + } + }; + + return ( + + {error && {error}} + setUsername(e.target.value)} + margin="normal" + required + /> + setPassword(e.target.value)} + margin="normal" + required + /> + + + ); +}; + +export default Login; +``` + +### 账目列表组件 + +`src/components/LedgerList.tsx`: +```typescript +import React, { useState, useEffect } from 'react'; +import { + Table, TableBody, TableCell, TableContainer, + TableHead, TableRow, Paper, Typography +} from '@mui/material'; +import { ledgerAPI } from '../services/api'; + +interface LedgerEntry { + id: number; + date: string; + description: string; + amount: number; + category: string; + balance: number; +} + +const LedgerList: React.FC = () => { + const [entries, setEntries] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchEntries(); + }, []); + + const fetchEntries = async () => { + try { + const response = await ledgerAPI.getEntries(); + setEntries(response.data); + } catch (error) { + console.error('获取账目失败:', error); + } finally { + setLoading(false); + } + }; + + if (loading) return 加载中...; + + return ( + + + + + 日期 + 描述 + 类别 + 金额 + 余额 + + + + {entries.map((entry) => ( + + {new Date(entry.date).toLocaleDateString()} + {entry.description} + {entry.category} + = 0 ? 'green' : 'red' }}> + {entry.amount >= 0 ? '+' : ''}{entry.amount.toFixed(2)} + + {entry.balance.toFixed(2)} + + ))} + +
+ + logout: () => { +
+ ); +}; + +export default LedgerList; +``` + +## Vue.js 集成示例 + +### Vue 3 + Composition API + +```javascript +// src/composables/useLedgerApi.js +import { ref } from 'vue'; +import axios from 'axios'; + +const API_BASE_URL = 'http://localhost:5000'; + + localStorage.removeItem('auth_token'); +api.interceptors.response.use( + window.location.href = '/login'; +export function useLedgerApi() { + const api = axios.create({ + baseURL: API_BASE_URL, + }); + + // 设置请求拦截器添加令牌 + api.interceptors.request.use(config => { + const token = localStorage.getItem('auth_token'); + if (token) { + } + (response) => response, + (error) => { + config.headers.Authorization = `Bearer ${token}`; + if (error.response?.status === 401) { + } + return config; + + }); + + const entries = ref([]); + const loading = ref(false); + + const fetchEntries = async () => { + loading.value = true; + try { + const response = await api.get('/api/ledger/entries'); + entries.value = response.data; + } catch (error) { + console.error('获取数据失败:', error); + } finally { + loading.value = false; + } + }; + + return { + entries, + loading, + fetchEntries, + }; +} +``` + +## 环境变量配置 + +在 React/Vue 项目根目录创建 `.env` 文件: + +```env +REACT_APP_API_URL=http://localhost:5000 +REACT_APP_APP_NAME=WebLedger Frontend +``` + +## 安全最佳实践 + +1. **令牌存储**: 使用 `localStorage` 或 `sessionStorage` 存储 JWT 令牌 +2. **HTTPS**: 生产环境始终使用 HTTPS +3. **输入验证**: 前端和后端都要验证用户输入 +4. **错误处理**: 优雅地处理 API 错误 +5. **加载状态**: 显示加载指示器 + +## 测试 API 连接 + +使用以下命令测试 API 是否可用: + +```bash +# 测试健康检查端点 +curl http://localhost:5000/health + +# 测试 API 端点(需要认证) +curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:5000/api/ledger/entries +``` + +## 故障排除 + +### CORS 问题 +如果遇到 CORS 错误,确保后端已正确配置 CORS: + +```csharp +// 在 .NET 后端 Program.cs 中 +builder.Services.AddCors(options => +{ + options.AddPolicy("AllowFrontend", + policy => policy.WithOrigins("http://localhost:3000") + .AllowAnyHeader() + .AllowAnyMethod()); +}); +``` + +### 连接超时 +- 检查后端服务是否正在运行 +- 验证端口号是否正确 +- 检查防火墙设置 + + +## 更多资源 + +- [React 官方文档](https://reactjs.org/docs/getting-started.html) +- [Vue.js 官方文档](https://vuejs.org/guide/introduction.html) +- [Axios 文档](https://axios-http.com/docs/intro) +- [Material-UI 组件库](https://mui.com/material-ui/getting-started/) + +如需更多帮助,请查阅 [WebLedger GitHub 仓库](https://github.com/HIT-ReFreSH/WebLedger) 或提交 Issue。 + +--- + diff --git a/docs/zh-CN/getting-started-zh.md b/docs/zh-CN/getting-started-zh.md new file mode 100644 index 0000000..e05eff6 --- /dev/null +++ b/docs/zh-CN/getting-started-zh.md @@ -0,0 +1,153 @@ +# WebLedger 入门指南 + +本指南将帮助您快速搭建并开始使用 WebLedger 进行开发。 + +## 环境要求 + +- .NET 8 SDK ([下载](https://dotnet.microsoft.com/download/dotnet/8.0)) +- MySQL 8.0+ 数据库服务器 +- 您喜欢的 IDE(Visual Studio、VS Code、Rider 等) + +## 快速开始:运行后端服务 + +### 选项 1:本地开发(推荐用于开发环境) + +#### 1. 准备 MySQL 数据库 + +为 WebLedger 创建新的数据库和用户: + +```sql +CREATE DATABASE ledger; +CREATE USER 'ledger-bot'@'localhost' IDENTIFIED BY 'your-password'; +GRANT ALL PRIVILEGES ON ledger.* TO 'ledger-bot'@'localhost'; +FLUSH PRIVILEGES; +``` + +#### 2. 配置应用程序 + +在 `web/` 目录下创建开发环境配置文件: + +```bash +# 从基础配置复制 +cp appsettings.json appsettings.Development.json + +# 编辑配置文件(使用你喜欢的编辑器) +nano appsettings.Development.json +``` + +添加以下数据库连接和 JWT 配置: + +```json +{ + "ConnectionStrings": { + "DefaultConnection": "Server=localhost;Database=ledger;User=ledger-bot;Password=your-password;" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "Jwt": { + "Key": "your-secret-key-at-least-32-characters-long", + "Issuer": "WebLedger", + "Audience": "WebLedgerUsers" + } +} +``` + +#### 3. 还原依赖并运行 + +```bash +# 进入后端项目目录 +cd web + +# 还原 NuGet 包 +dotnet restore + +# 运行应用程序 +dotnet run +``` + +应用程序将在 `https://localhost:5001` 和 `http://localhost:5000` 启动。 + +### 选项 2:使用 Docker 运行 + +#### 1. 启动所有服务 + +```bash +# 在项目根目录运行 +docker-compose up -d +``` + +这将启动: +- MySQL 数据库(端口 3306) +- WebLedger 后端 API(端口 5000) +- 管理界面(如果配置了) + +#### 2. 检查服务状态 + +```bash +docker-compose ps +``` + +#### 3. 查看日志 + +```bash +docker-compose logs -f web +``` + +## 验证安装 + +### 1. 检查健康状态 + +```bash +curl http://localhost:5000/health +``` + +应该返回:`{"status":"Healthy"}` + +### 2. 获取 API 文档 + +访问 `http://localhost:5000/swagger` 查看 Swagger UI 界面。 + +## 前端开发 + +前端项目位于 `frontend/` 目录。请参考 [前端集成指南](frontend-integration-zh.md) 了解如何设置和运行前端。 + +## 故障排除 + +### 常见问题 + +#### 数据库连接失败 +- 确保 MySQL 服务正在运行 +- 检查连接字符串中的密码是否正确 +- 验证用户权限 + +#### 端口已被占用 +- 检查 5000 和 5001 端口是否被其他程序占用 +- 修改 `appsettings.json` 中的 URL 设置 + +#### .NET SDK 版本不匹配 +```bash +# 检查已安装的 .NET 版本 +dotnet --list-sdks + +# 如果未安装 .NET 8,请从官网下载 +``` + +## 下一步 + +- 阅读 [API 文档](../api/) 了解可用端点 +- 查看 [前端集成指南](frontend-integration-zh.md) 学习如何连接前端 +- 探索 [贡献指南](../CONTRIBUTING.md) 参与项目开发 +- 查看 [示例项目](../examples/) 获取更多使用示例 + +## 获取帮助 + +- 查看 [GitHub Issues](https://github.com/HIT-ReFreSH/WebLedger/issues) +- 查阅项目 Wiki +- 联系维护团队 + +--- +