# docker-test **Repository Path**: qxin905/docker-td ## Basic Information - **Project Name**: docker-test - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-09 - **Last Updated**: 2026-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 艾编程文章后台管理系统 一个前后端分离的文章管理练习项目。前端基于 React 19 + React Router 8(Data 模式),后端基于 Express 4,数据存放在本地 JSON 文件中,不依赖数据库。 ## 目录结构 ``` docker-project/ ├── article-admin-client/ # 前端(Vite + React) │ ├── src/ │ │ ├── main.jsx # 入口,挂载 RouterProvider │ │ ├── router/ │ │ │ ├── index.jsx # 路由表(懒加载、loader/action、handle) │ │ │ └── middleware/authMiddleware.js # 登录校验与 token 刷新 │ │ ├── pages/ │ │ │ ├── root-layout/ # 公共布局:顶栏、侧边栏、面包屑、加载状态 │ │ │ ├── home/ # 首页 │ │ │ ├── login/ # 登录页 │ │ │ ├── articles/ # 文章列表 / 详情 / 创建 / 更新 │ │ │ └── not-found/ # 404 页 │ │ └── components/ │ │ ├── Breadcrumbs.jsx # 面包屑 │ │ ├── ErrorBoundary.jsx# 路由错误页(antd Result) │ │ └── ShareButton.jsx # 复制文章链接 │ └── vite.config.js # 开发服务器,/api 代理到 3000 端口 └── article-admin-server/ # 后端(Express) ├── app.js # 全部接口实现 └── data.json # 数据文件(users / articles / comments) ``` ## 技术栈 | 端 | 主要依赖 | | --- | --- | | 前端 | React 19、React Router 8、Ant Design 6、axios、Vite 8、ESLint | | 后端 | Express 4、jsonwebtoken、bcryptjs、cors、nodemon(开发) | ## 快速开始 需要 Node.js(当前开发环境为 v24)。 ```bash # 1. 启动后端,监听 http://localhost:3000 cd article-admin-server npm install npm run start # 或 npm run dev(nodemon,已忽略 data.json 的变更) # 2. 启动前端,默认 http://localhost:5173 cd article-admin-client npm install npm run dev ``` 前端请求统一以 `/api` 开头,由 Vite 代理转发到后端,所以开发时两个服务都要启动。 前端其他脚本:`npm run build` 打包,`npm run preview` 预览打包结果,`npm run lint` 代码检查。 登录账号需要已存在于 `data.json` 的 `users` 中(密码为 bcrypt 哈希)。前端没有注册页面,如需新账号可以直接调用注册接口: ```bash curl -X POST http://localhost:3000/api/register \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"123456"}' ``` ## 前端 ### 页面路由 | 路径 | 页面 | 数据处理 | | --- | --- | --- | | `/login` | 登录 | `loginAction`:校验用户名 ≥ 4 位、密码 ≥ 6 位,登录成功后保存双 token | | `/` | 首页 | — | | `/articles` | 文章列表 | `getArticlesLoader`:按 `page`、`keyword` 查询,每页 10 条 | | `/articles/:id` | 文章详情 | `getrticleDetailLoader`,出错时由 `ErrorBoundary` 展示 | | `/articles/create` | 创建文章 | `CreateArticleAction` | | `/articles/:id/update` | 更新文章 | `getArticleByIdLoader` + `updateArticleAction` | | `/articles/:id/delete` | 无页面 | 仅 action,列表页通过 `useFetcher` 提交删除 | | `*` | 404 | — | 除 `/login` 和 404 外,其余页面都挂在 `RootLayout` 下,并经过 `authMiddleware`。 ### 主要功能 - 路由懒加载:页面组件和 loader/action 通过 `lazy` 按需加载。 - 登录拦截与无感刷新:`authMiddleware` 先用短 token 调 `/api/auth/verify`,失败后用长 token 调 `/api/auth/refresh` 换新 token;都失败则清除 token 并跳转登录页。 - 列表搜索与分页:搜索用 `
` 写入 URL 参数,分页用 antd `Pagination` 修改 `page` 参数。翻页时列表半透明,跳转到其他页面时显示“数据正在加载中”。 - 删除状态:删除中的条目半透明,按钮显示“删除中...”。 - 浏览器标题与面包屑:读取路由 `handle.title` 和 `handle.crumb` 生成,详情页标题取文章标题。 - 离开拦截:更新页表单修改后,用 `useBlocker` 拦截离开并弹窗确认。 - 分享:详情页显示分享按钮,把文章链接复制到剪贴板。 - 错误页:详情页按 404 / 401 / 403 / 500 显示不同的 antd `Result`,并提供返回、回首页、重试按钮。 ## 后端 服务端口 `3000`,数据读写都直接操作 `data.json`。 ### 接口列表 | 方法 | 路径 | 说明 | 鉴权 | | --- | --- | --- | --- | | POST | `/api/register` | 注册,参数 `username`、`password` | 否 | | POST | `/api/login` | 登录,返回 `token`(5 分钟)、`refreshToken`(30 分钟)、`user` | 否 | | GET | `/api/auth/verify` | 校验 token,返回 token 中的用户信息 | 是 | | POST | `/api/auth/refresh` | 参数 `refreshToken`,返回一对新 token | 否 | | GET | `/api/articles` | 文章列表,可选 `page`、`pageSize`、`keyword`(按标题模糊匹配)。不带分页参数时返回完整数组 | 否 | | GET | `/api/articles/:id` | 文章详情 | 否 | | POST | `/api/articles` | 创建文章,参数 `title`、`content`、`published` | 否 | | PUT | `/api/articles/:id` | 更新文章,只更新传入的字段 | 否 | | DELETE | `/api/articles/:id` | 删除文章,成功返回 204 | 否 | | GET | `/api/articles/:id/comments` | 文章评论列表 | 否 | | POST | `/api/articles/:id/comments` | 新增评论,参数 `content` | 否 | 鉴权接口需要请求头 `Authorization: Bearer `,缺少 token 返回 401,token 无效或过期返回 403。 带分页参数的列表接口返回: ```json { "items": [], "total": 50, "page": 1, "pageSize": 10, "totalPages": 5 } ``` 为了演示加载状态,文章列表接口会随机延迟 500 / 1000 / 2000 毫秒再返回。 ### 数据结构 ```json { "users": [{ "id": 1, "username": "...", "password": "" }], "articles": [{ "id": 1, "title": "...", "content": "...", "published": true, "createdAt": "ISO 时间", "updatedAt": "ISO 时间" }], "comments": [{ "id": 1, "articleId": 1, "content": "...", "createdAt": "ISO 时间" }] } ``` ## 已知问题 - 文章接口没有鉴权:后端只有 `/api/auth/verify` 校验 token,文章和评论的增删改接口任何人都能直接调用。前端的登录拦截只限制页面访问。 - 密钥写死在代码里:`SECRET_KEY` 和 `REFRESH_SECRET_KEY` 写在 `app.js` 中,部署前应改为环境变量。 - id 可能重复:新建用户、文章、评论都用 `数组长度 + 1` 作为 id,删除数据后会和已有 id 冲突。当前 `data.json` 的 50 篇文章中已经出现了重复 id。 - `ShareButton.jsx` 用到的 `@ant-design/icons` 没有写进前端 `package.json`,目前是作为 antd 的间接依赖装上的,建议显式安装。 - `npm run dev` 启动后端时,nodemon 已经忽略了 `data.json`。如果去掉这个配置,写入数据会触发服务重启,导致紧接着的请求失败。