feat: 初始化前端项目基础结构
- 添加项目配置文件(tsconfig, eslint, prettier等) - 实现基础路由和页面布局 - 添加全局状态管理和API请求封装 - 集成UI组件库和主题系统 - 添加文档网站和示例页面 - 配置CI/CD和工作流
@@ -0,0 +1,31 @@
|
||||
.DS_Store
|
||||
coverage/
|
||||
node_modules/
|
||||
unpackage/
|
||||
dist/
|
||||
lib/
|
||||
website/
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# .vitepress/cache/* - 只忽略 cache 目录下的文件,但不忽略子目录
|
||||
# .vitepress/cache/ - 忽略整个 cache 目录及其所有内容(推荐)
|
||||
**/.vitepress/cache/
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.project
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
.history
|
||||
tags.json
|
||||
attributes.json
|
||||
web-types.json
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
semi: true,
|
||||
trailingComma: 'es5',
|
||||
singleQuote: true,
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
endOfLine: 'lf',
|
||||
vueIndentScriptAndStyle: true,
|
||||
bracketSpacing: true,
|
||||
arrowParens: 'always'
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,107 @@
|
||||
# FastDocs
|
||||
|
||||
FastDocs是FastapiAdmin 官网文档,该项目是一套完全开源的快速开发平台,提供免费使用。它结合了现代、高性能的技术栈,后端采用Fastapi + SQLAlchemy,前端采用基于 vue3 + typescript + vite + pinia + Element-Plus。旨在帮助开发者快速搭建高质量的中后台系统。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```sh
|
||||
FastDocs/
|
||||
├─ docs # 源代码
|
||||
│ ├─ .vitepress # VitePress配置
|
||||
│ │ ├─ cache/ # 缓存目录
|
||||
│ │ ├─ theme/ # 主题配置
|
||||
│ │ │ ├─ index.ts # 主题入口
|
||||
│ │ │ └─ style.css # 主题样式
|
||||
│ │ └─ config.ts # 主配置文件
|
||||
│ ├─ en/ # 英文文档
|
||||
│ │ ├─ about/ # 关于
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ api-docs/ # API文档
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ backend/ # 后端文档
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ custom-development/ # 自定义开发
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ deployment/ # 部署文档
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ examples/ # 示例
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ frontend/ # 前端文档
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ guidelines/ # 指南
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ miniprogram/ # 小程序文档
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ overview/ # 概览
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ start/ # 快速开始
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ ├─ why/ # 为什么选择
|
||||
│ │ │ └─ index.md # 内容
|
||||
│ │ └─ index.md # 英文首页 # 中文文档
|
||||
│ ├─ about/ # 关于
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ api-docs/ # API文档
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ backend/ # 后端文档
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ custom-development/ # 自定义开发
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ deployment/ # 部署文档
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ examples/ # 示例
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ frontend/ # 前端文档
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ guidelines/ # 指南
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ miniprogram/ # 小程序文档
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ overview/ # 概览
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ start/ # 快速开始
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ why/ # 为什么选择
|
||||
│ │ └─ index.md # 内容
|
||||
│ ├─ public/ # 公共资源
|
||||
│ │ ├─ favicon.png
|
||||
│ │ ├─ group.jpg
|
||||
│ │ ├─ help.png
|
||||
│ │ ├─ logo.png
|
||||
│ │ └─ wechatPay.jpg
|
||||
│ └─ index.md # 根首页
|
||||
├─ .gitignore # Git忽略文件
|
||||
├─ .prettierrc.js # Prettier配置
|
||||
├─ LICENSE # 许可证
|
||||
├─ README.md # 项目说明文档
|
||||
├─ eslint.config.js # ESLint配置
|
||||
├─ package.json # 项目依赖文件
|
||||
├─ pnpm-lock.yaml # pnpm锁定文件
|
||||
├─ tsconfig.json # TypeScript配置
|
||||
└─ vite.config.ts # Vite配置
|
||||
|
||||
```
|
||||
|
||||
## 🔗 源码仓库
|
||||
|
||||
| 平台 | 仓库地址 |
|
||||
|------|----------|
|
||||
| GitHub | [FastapiAdmin主工程](https://github.com/fastapiadmin/FastapiAdmin.git) \| [FastDocs官网](https://github.com/fastapiadmin/FastDocs.git) \| [FastApp移动端](https://github.com/fastapiadmin/FastApp.git) |
|
||||
| Gitee | [FastapiAdmin主工程](https://gitee.com/fastapiadmin/FastapiAdmin.git) \| [FastDocs官网](https://gitee.com/fastapiadmin/FastDocs.git) \| [FastApp移动端](https://gitee.com/fastapiadmin/FastApp.git) |
|
||||
|
||||
## 官网展示
|
||||
|
||||

|
||||
|
||||
## 快速开始
|
||||
|
||||
```sh
|
||||
# 进入项目目录
|
||||
cd FastDocs
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
# 运行文档工程
|
||||
pnpm run dev
|
||||
# 构建文档工程
|
||||
pnpm run build
|
||||
```
|
||||
@@ -0,0 +1,323 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
|
||||
export default defineConfig({
|
||||
base: '/',
|
||||
srcDir: '.',
|
||||
outDir: '../dist',
|
||||
// lang: 'zh-CN',
|
||||
title: 'FastApiAdmin',
|
||||
description: '⚡️ 现代、开源、全栈融合的中后台快速开发平台',
|
||||
ignoreDeadLinks: [
|
||||
'http://localhost:8000/docs',
|
||||
'http://localhost:5173',
|
||||
'http://localhost:8001/api/v1/docs',
|
||||
'http://localhost:8001/api/v1/redoc'
|
||||
],
|
||||
vite: {
|
||||
build: {
|
||||
chunkSizeWarningLimit: 1000,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks(id) {
|
||||
if (id.includes('node_modules')) {
|
||||
if (id.includes('vue')) {
|
||||
return 'vue-vendor'
|
||||
}
|
||||
if (id.includes('vitepress')) {
|
||||
return 'vitepress-vendor'
|
||||
}
|
||||
return 'vendor'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
head: [
|
||||
["link",{rel: "apple-touch-icon", sizes: "180x180", href: "/favicon.png"}],
|
||||
["link",{rel: "icon",type: "image/png", sizes: "32x32", href: "/favicon.png"}],
|
||||
["link",{rel: "icon",type: "image/png", sizes: "16x16", href: "/favicon.png"}],
|
||||
["link",{rel: "shortcut icon", href: "/favicon.png"}],
|
||||
["meta",{name: "description", content: "FastApiAdmin - 现代、开源、全栈融合的快速开发平台,基于 FastAPI + Vue3 + TypeScript 构建的企业级中后台解决方案"}],
|
||||
["meta",{name: "keywords", content: "FastAPI, Vue3, TypeScript, 中后台, 快速开发, 企业级, 全栈, 开源"}],
|
||||
["meta",{name: "author", content: "FastapiAdmin Team"}],
|
||||
["meta",{property: "og:title", content: "FastApiAdmin - 现代、开源、全栈融合的快速开发平台"}],
|
||||
["meta",{property: "og:description", content: "基于 FastAPI + Vue3 + TypeScript 构建的企业级中后台解决方案,支持多端开发"}],
|
||||
["meta",{property: "og:image", content: "/logo.png"}],
|
||||
["meta",{property: "og:url", content: "https://service.fastapiadmin.com"}],
|
||||
["meta",{property: "og:type", content: "website"}],
|
||||
["meta",{name: "twitter:card", content: "summary_large_image"}],
|
||||
["meta",{name: "twitter:title", content: "FastApiAdmin - 现代、开源、全栈融合的快速开发平台"}],
|
||||
["meta",{name: "twitter:description", content: "基于 FastAPI + Vue3 + TypeScript 构建的企业级中后台解决方案,支持多端开发"}],
|
||||
["meta",{name: "twitter:image", content: "/logo.png"}],
|
||||
["link",{rel: "canonical", href: "https://service.fastapiadmin.com"}]
|
||||
],
|
||||
locales: {
|
||||
root: {
|
||||
label: '简体中文',
|
||||
lang: 'zh',
|
||||
link: '/',
|
||||
description: '现代、开源、全栈融合的中后台快速开发平台',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: '首页', link: '/' },
|
||||
{
|
||||
text: '指南',
|
||||
items: [
|
||||
{ text: '项目概述', link: '/overview/' },
|
||||
{ text: '快速开始', link: '/start/' },
|
||||
{ text: '为什么选择FastapiAdmin?', link: '/why/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '开发指南',
|
||||
items: [
|
||||
{ text: '前端开发', link: '/frontend/' },
|
||||
{ text: '后端开发', link: '/backend/' },
|
||||
{ text: '移动端开发', link: '/miniprogram/' },
|
||||
{ text: '开发规范', link: '/guidelines/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '部署与API',
|
||||
items: [
|
||||
{ text: '部署指南', link: '/deployment/' },
|
||||
{ text: 'API文档说明', link: '/api-docs/' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '版本',
|
||||
items: [
|
||||
{ text: 'master', link: 'https://github.com/fastapiadmin/FastapiAdmin', target: '_blank' },
|
||||
{ text: 'V2.0.0', link: 'https://github.com/fastapiadmin/FastapiAdmin/tree/v2.0.0', target: '_blank' },
|
||||
{ text: 'V1.0.0', link: 'https://github.com/fastapiadmin/FastapiAdmin/tree/v1.0.0', target: '_blank' }
|
||||
]
|
||||
},
|
||||
{ text: '他们在使用', link: '/users/' },
|
||||
{ text: '赞助', link: '/sponsor/' },
|
||||
{ text: '贡献指南', link: '/contributing/' },
|
||||
{ text: '关于我们', link: '/about/' },
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
text: '简介',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '项目概述', link: '/overview/' },
|
||||
{ text: '快速开始', link: '/start/' },
|
||||
{ text: '为什么选择FastapiAdmin?', link: '/why/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '开发指南',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '前端开发', link: '/frontend/' },
|
||||
{ text: '后端开发', link: '/backend/' },
|
||||
{ text: '移动端开发', link: '/miniprogram/' },
|
||||
{ text: '开发规范', link: '/guidelines/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '部署与API',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '部署指南', link: '/deployment/' },
|
||||
{ text: 'API文档说明', link: '/api-docs/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '关于',
|
||||
items: [
|
||||
{ text: '他们在使用', link: '/users/' },
|
||||
{ text: '赞助', link: '/sponsor/' },
|
||||
{ text: '贡献指南', link: '/contributing/' },
|
||||
{ text: '关于我们', link: '/about/' },
|
||||
]
|
||||
}
|
||||
],
|
||||
footer: {
|
||||
message: '<a href="https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE" target="_blank">MIT License</a>',
|
||||
copyright: 'Copyright © 2025-2026 service.fastapiadmin.com 版权所有 |隐私 |条款 陕ICP备2025069493号-1'
|
||||
},
|
||||
outline: {
|
||||
level: [2, 3],
|
||||
label: "页面导航",
|
||||
},
|
||||
lastUpdated: {
|
||||
text: "最后更新于",
|
||||
formatOptions: {
|
||||
dateStyle: "short",
|
||||
timeStyle: "short",
|
||||
},
|
||||
},
|
||||
langMenuLabel: "多语言",
|
||||
returnToTopLabel: "回到顶部",
|
||||
sidebarMenuLabel: "菜单",
|
||||
darkModeSwitchLabel: "主题",
|
||||
lightModeSwitchTitle: "切换到浅色模式",
|
||||
darkModeSwitchTitle: "切换到深色模式"
|
||||
}
|
||||
},
|
||||
en: {
|
||||
label: 'English',
|
||||
lang: 'en',
|
||||
link: '/en/',
|
||||
description: 'Modern, open-source, full-stack integrated backend rapid development platform',
|
||||
themeConfig: {
|
||||
nav: [
|
||||
{ text: 'Home', link: '/en/' },
|
||||
{
|
||||
text: 'Guide',
|
||||
items: [
|
||||
{ text: 'Overview', link: '/en/overview/' },
|
||||
{ text: 'Quick Start', link: '/en/start/' },
|
||||
{ text: 'Why FastapiAdmin?', link: '/en/why/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Development',
|
||||
items: [
|
||||
{ text: 'Frontend', link: '/en/frontend/' },
|
||||
{ text: 'Backend', link: '/en/backend/' },
|
||||
{ text: 'Mini Program', link: '/en/miniprogram/' },
|
||||
{ text: 'Guidelines', link: '/en/guidelines/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Deployment & API',
|
||||
items: [
|
||||
{ text: 'Deployment', link: '/en/deployment/' },
|
||||
{ text: 'API Docs', link: '/en/api-docs/' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Versions',
|
||||
items: [
|
||||
{ text: 'master', link: 'https://github.com/fastapiadmin/FastapiAdmin', target: '_blank' },
|
||||
{ text: 'V2.0.0', link: 'https://github.com/fastapiadmin/FastapiAdmin/tree/v2.0.0', target: '_blank' },
|
||||
{ text: 'V1.0.0', link: 'https://github.com/fastapiadmin/FastapiAdmin/tree/v1.0.0', target: '_blank' }
|
||||
]
|
||||
},
|
||||
{ text: 'Who is Using', link: '/en/users/' },
|
||||
{ text: 'Sponsor', link: '/en/sponsor/' },
|
||||
{ text: 'Contributing Guide', link: '/en/contributing/' },
|
||||
{ text: 'About Us', link: '/en/about/' },
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Introduction',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'Overview', link: '/en/overview/' },
|
||||
{ text: 'Quick Start', link: '/en/start/' },
|
||||
{ text: 'Why FastapiAdmin?', link: '/en/why/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Development',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'Frontend', link: '/en/frontend/' },
|
||||
{ text: 'Backend', link: '/en/backend/' },
|
||||
{ text: 'Mini Program', link: '/en/miniprogram/' },
|
||||
{ text: 'Guidelines', link: '/en/guidelines/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Deployment & API',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'Deployment', link: '/en/deployment/' },
|
||||
{ text: 'API Docs', link: '/en/api-docs/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'About',
|
||||
items: [
|
||||
{ text: 'Who is Using', link: '/en/users/' },
|
||||
{ text: 'Sponsor', link: '/en/sponsor/' },
|
||||
{ text: 'Contributing Guide', link: '/en/contributing/' },
|
||||
{ text: 'About Us', link: '/en/about/' },
|
||||
]
|
||||
}
|
||||
],
|
||||
footer: {
|
||||
message: '<a href="https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE" target="_blank">MIT License</a>',
|
||||
copyright: 'Copyright © 2025-2026 service.fastapiadmin.com All Rights Reserved | Privacy | Terms ICP: Shaanxi 2025069493-1'
|
||||
},
|
||||
outline: {
|
||||
level: [2, 3],
|
||||
label: "On this page",
|
||||
},
|
||||
lastUpdated: {
|
||||
text: "Last updated",
|
||||
formatOptions: {
|
||||
dateStyle: "short",
|
||||
timeStyle: "short",
|
||||
},
|
||||
},
|
||||
langMenuLabel: "Languages",
|
||||
returnToTopLabel: "Return to top",
|
||||
sidebarMenuLabel: "Menu",
|
||||
darkModeSwitchLabel: "Theme",
|
||||
lightModeSwitchTitle: "Switch to light mode",
|
||||
darkModeSwitchTitle: "Switch to dark mode"
|
||||
}
|
||||
},
|
||||
},
|
||||
lastUpdated: true,
|
||||
metaChunk: true,
|
||||
themeConfig: {
|
||||
logo: '/logo.png',
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/fastapiadmin/FastapiAdmin' },
|
||||
{ icon: 'gitee', link: 'https://gitee.com/fastapiadmin/FastapiAdmin' },
|
||||
{ icon: 'gitcode', link: 'https://gitcode.com/qq_36002987/FastapiAdmin' }
|
||||
],
|
||||
search: {
|
||||
provider: 'local',
|
||||
options: {
|
||||
locales: {
|
||||
root: {
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: '搜索文档',
|
||||
buttonAriaLabel: '搜索文档'
|
||||
},
|
||||
modal: {
|
||||
footer: {
|
||||
selectText: '选择',
|
||||
navigateText: '切换',
|
||||
closeText: '关闭',
|
||||
},
|
||||
noResultsText: '没有找到相关结果',
|
||||
resetButtonTitle: '清除搜索词',
|
||||
backButtonTitle: '返回',
|
||||
},
|
||||
},
|
||||
},
|
||||
en: {
|
||||
translations: {
|
||||
button: {
|
||||
buttonText: 'Search',
|
||||
buttonAriaLabel: 'Search documentation'
|
||||
},
|
||||
modal: {
|
||||
footer: {
|
||||
selectText: 'Select',
|
||||
navigateText: 'Navigate',
|
||||
closeText: 'Close',
|
||||
},
|
||||
noResultsText: 'No results found',
|
||||
resetButtonTitle: 'Clear search',
|
||||
backButtonTitle: 'Back',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
detailedView: true
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,40 @@
|
||||
import Theme from 'vitepress/theme'
|
||||
import { onMounted, watch, nextTick } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
import './style.css'
|
||||
|
||||
export default {
|
||||
...Theme,
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
let zoom: ReturnType<typeof mediumZoom> | null = null
|
||||
|
||||
const initZoom = () => {
|
||||
// 销毁之前的实例
|
||||
if (zoom) {
|
||||
zoom.detach()
|
||||
}
|
||||
|
||||
// 等待 DOM 更新后初始化
|
||||
nextTick(() => {
|
||||
// 初始化图片放大功能
|
||||
// 选择所有文章内容中的图片,排除 logo、badge 等装饰性图片
|
||||
zoom = mediumZoom('.vp-doc img:not(.logo):not([alt*="badge"]):not([alt*="Badge"]):not([alt*="Stars"]):not([alt*="License"]):not([alt*="Python"]):not([alt*="NodeJS"]):not([alt*="MySQL"]):not([alt*="Redis"])', {
|
||||
background: 'rgba(0, 0, 0, 0.8)',
|
||||
margin: 24,
|
||||
scrollOffset: 0,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initZoom()
|
||||
|
||||
// 监听路由变化,重新初始化图片放大功能
|
||||
watch(() => route.path, () => {
|
||||
initZoom()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
:root:where(:lang(fa)) {
|
||||
--vp-font-family-base:
|
||||
'Vazirmatn', 'Inter', ui-sans-serif, system-ui, sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
|
||||
:root {
|
||||
/* 标题 */
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(
|
||||
120deg,
|
||||
#bd34fe 30%,
|
||||
#41d1ff
|
||||
);
|
||||
|
||||
/* 图标背景 */
|
||||
--vp-home-hero-image-background-image: linear-gradient(
|
||||
-45deg,
|
||||
#bd34fe80 50%,
|
||||
#47caff80 50%
|
||||
);
|
||||
/* --vp-home-hero-image-background-image: linear-gradient(
|
||||
-45deg,
|
||||
#bd34fe 50%,
|
||||
#47caff 50%
|
||||
); */
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
|
||||
/* brand按钮 */
|
||||
/* --vp-button-brand-border: #F6CEEC; */
|
||||
--vp-button-brand-text: #F6CEEC;
|
||||
--vp-button-brand-bg: #D939CD;
|
||||
|
||||
--vp-button-brand-hover-border: #F6CEEC;
|
||||
--vp-button-brand-hover-text: #fff;
|
||||
--vp-button-brand-hover-bg: #D939CD;
|
||||
|
||||
--vp-button-brand-active-border: #F6CEEC;
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(56px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(68px);
|
||||
}
|
||||
}
|
||||
|
||||
/* 图片放大功能样式优化 */
|
||||
.vp-doc img:not(.logo):not([alt*="badge"]):not([alt*="Badge"]):not([alt*="Stars"]):not([alt*="License"]):not([alt*="Python"]):not([alt*="NodeJS"]):not([alt*="MySQL"]):not([alt*="Redis"]) {
|
||||
cursor: zoom-in;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.vp-doc img:not(.logo):not([alt*="badge"]):not([alt*="Badge"]):not([alt*="Stars"]):not([alt*="License"]):not([alt*="Python"]):not([alt*="NodeJS"]):not([alt*="MySQL"]):not([alt*="Redis"]):hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* medium-zoom 覆盖层样式 */
|
||||
.medium-zoom-overlay {
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.medium-zoom-image {
|
||||
z-index: 1000;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: 关于我们
|
||||
---
|
||||
# 🎨 关于我们
|
||||
|
||||
欢迎与我们取得联系,以下是我们的联系方式:
|
||||
|
||||
- **微信**:948080782
|
||||
|
||||
- **邮箱**:[948080782@qq.com](mailto:948080782@qq.com)
|
||||
|
||||
## 👥 团队介绍
|
||||
|
||||
我们是一支热爱开源和技术的团队,致力于为开发者提供高质量的开发工具和解决方案。
|
||||
|
||||
### 核心成员
|
||||
|
||||
- **[@fastapiadmin](https://gitee.com/fastapiadmin)** - 项目创始人,深耕高精尖技术行业数十年
|
||||
|
||||
## 🌐 社区
|
||||
|
||||
### GitHub
|
||||
- [FastapiAdmin 主工程](https://github.com/fastapiadmin/FastapiAdmin.git)
|
||||
- [FastApp 移动端](https://github.com/fastapiadmin/FastApp.git)
|
||||
- [FastDocs 官网文档](https://github.com/fastapiadmin/FastDocs.git)
|
||||
|
||||
### Gitee
|
||||
- [FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
- [GitCode](https://gitcode.com/qq_36002987/FastapiAdmin)
|
||||
|
||||
## 扫码交流
|
||||
|
||||
以下是相关二维码,点击图片可查看大图:
|
||||
|
||||
| 群组二维码 | 微信支付二维码 |
|
||||
| --- | --- |
|
||||
|  |  |
|
||||
@@ -0,0 +1,440 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: API 文档说明
|
||||
---
|
||||
# API 文档说明
|
||||
|
||||
## 📚API 文档概述
|
||||
|
||||
FastapiAdmin 项目提供了完善的 API 文档,便于开发者了解和使用系统提供的接口。本文档将详细介绍如何使用和调用这些 API。
|
||||
|
||||
## 🔧后端 API 文档
|
||||
|
||||
### 1. 访问方式
|
||||
|
||||
后端 API 文档基于 FastAPI 自动生成,支持 Swagger 和 Redoc 两种格式:
|
||||
|
||||
- **Swagger UI**:<http://localhost:8001/api/v1/docs>(本地开发环境)
|
||||
- **Redoc**:<http://localhost:8001/api/v1/redoc>(本地开发环境)
|
||||
- **在线演示**:<https://service.fastapiadmin.com/api/v1/docs>(生产环境)
|
||||
|
||||
### 2. 使用方法
|
||||
|
||||
#### 2.1 认证登录
|
||||
|
||||
1. 打开 Swagger UI 文档页面
|
||||
2. 点击页面右上角的 "Authorize" 按钮
|
||||
3. 在弹出的对话框中输入用户名和密码
|
||||
4. 点击 "Authorize" 按钮完成认证
|
||||
5. 认证成功后,所有 API 调用都会自动携带认证信息
|
||||
|
||||
#### 2.2 接口测试
|
||||
|
||||
1. 在 Swagger UI 中找到需要测试的接口
|
||||
2. 点击接口名称展开详细信息
|
||||
3. 点击 "Try it out" 按钮
|
||||
4. 填写必要的参数
|
||||
5. 点击 "Execute" 按钮执行请求
|
||||
6. 查看响应结果
|
||||
|
||||
### 3. API 接口分类
|
||||
|
||||
后端 API 接口主要分为以下几类:
|
||||
|
||||
- **系统管理**:用户、角色、菜单、部门、岗位等管理接口
|
||||
- **监控管理**:在线用户、服务器监控、缓存监控等接口
|
||||
- **任务管理**:定时任务管理接口
|
||||
- **日志管理**:操作日志查询接口
|
||||
- **开发工具**:代码生成、表单构建等接口
|
||||
|
||||
## 📱前端 API 调用
|
||||
|
||||
### 1. 前端 API 封装
|
||||
|
||||
前端项目使用 TypeScript 封装了 API 调用,主要位于 `frontend/src/api` 目录下,按模块分类组织:
|
||||
|
||||
```
|
||||
frontend/src/api/
|
||||
├── module_example/ # 示例模块
|
||||
│ └── demo.ts
|
||||
├── module_monitor/ # 监控模块
|
||||
│ ├── cache.ts
|
||||
│ ├── online.ts
|
||||
│ └── server.ts
|
||||
└── module_system/ # 系统模块
|
||||
├── auth.ts
|
||||
├── dept.ts
|
||||
├── dict.ts
|
||||
├── log.ts
|
||||
├── menu.ts
|
||||
├── notice.ts
|
||||
├── params.ts
|
||||
├── role.ts
|
||||
└── user.ts
|
||||
```
|
||||
|
||||
### 2. API 调用示例
|
||||
|
||||
#### 2.1 导入 API 模块
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/module_system/auth';
|
||||
import { userApi } from '@/api/module_system/user';
|
||||
```
|
||||
|
||||
#### 2.2 调用登录接口
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/module_system/auth';
|
||||
import { useUserStore } from '@/store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
try {
|
||||
const res = await authApi.login({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
// 保存 token
|
||||
userStore.setToken(res.data.token);
|
||||
|
||||
// 获取用户信息
|
||||
await userStore.getUserInfo();
|
||||
|
||||
// 跳转到首页
|
||||
router.push('/');
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 2.3 调用用户管理接口
|
||||
|
||||
```typescript
|
||||
import { userApi } from '@/api/module_system/user';
|
||||
|
||||
// 获取用户列表
|
||||
const getUserList = async () => {
|
||||
try {
|
||||
const res = await userApi.getList({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
username: 'admin'
|
||||
});
|
||||
console.log('用户列表:', res.data);
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取用户详情
|
||||
const getUserDetail = async (userId: number) => {
|
||||
try {
|
||||
const res = await userApi.getDetail(userId);
|
||||
console.log('用户详情:', res.data);
|
||||
} catch (error) {
|
||||
console.error('获取用户详情失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 创建用户
|
||||
const createUser = async (userData: any) => {
|
||||
try {
|
||||
const res = await userApi.create(userData);
|
||||
console.log('创建用户成功:', res.data);
|
||||
} catch (error) {
|
||||
console.error('创建用户失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 更新用户
|
||||
const updateUser = async (userId: number, userData: any) => {
|
||||
try {
|
||||
const res = await userApi.update(userId, userData);
|
||||
console.log('更新用户成功:', res.data);
|
||||
} catch (error) {
|
||||
console.error('更新用户失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 删除用户
|
||||
const deleteUser = async (userId: number) => {
|
||||
try {
|
||||
const res = await userApi.delete(userId);
|
||||
console.log('删除用户成功:', res.data);
|
||||
} catch (error) {
|
||||
console.error('删除用户失败:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 📱FastApp 移动端 API 调用
|
||||
|
||||
### 1. 移动端 API 封装
|
||||
|
||||
FastApp 移动端项目同样封装了 API 调用,主要位于 `src/api` 目录下:
|
||||
|
||||
```
|
||||
FastApp/src/api/
|
||||
├── auth.ts # 认证相关接口
|
||||
├── file.ts # 文件相关接口
|
||||
└── user.ts # 用户相关接口
|
||||
```
|
||||
|
||||
### 2. API 调用示例
|
||||
|
||||
#### 2.1 导入 API 模块
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/auth';
|
||||
import { userApi } from '@/api/user';
|
||||
```
|
||||
|
||||
#### 2.2 调用登录接口
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/auth';
|
||||
import { useUserStore } from '@/store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
try {
|
||||
const res = await authApi.login({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
// 保存 token
|
||||
userStore.setToken(res.data.token);
|
||||
|
||||
// 获取用户信息
|
||||
await userStore.getUserInfo();
|
||||
|
||||
// 跳转到首页
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 2.3 调用用户信息接口
|
||||
|
||||
```typescript
|
||||
import { userApi } from '@/api/user';
|
||||
|
||||
// 获取用户信息
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const res = await userApi.getUserInfo();
|
||||
console.log('用户信息:', res.data);
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// 更新用户信息
|
||||
const updateUserInfo = async (userData: any) => {
|
||||
try {
|
||||
const res = await userApi.updateUserInfo(userData);
|
||||
console.log('更新用户信息成功:', res.data);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('更新用户信息失败:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 🛠️API 调用最佳实践
|
||||
|
||||
### 1. 错误处理
|
||||
|
||||
在调用 API 时,应该合理处理可能出现的错误:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const res = await apiCall();
|
||||
// 处理成功响应
|
||||
} catch (error: any) {
|
||||
// 处理错误
|
||||
if (error.response) {
|
||||
// 服务器返回错误状态码
|
||||
console.error('服务器错误:', error.response.data);
|
||||
uni.showToast({
|
||||
title: error.response.data.message || '服务器错误',
|
||||
icon: 'none'
|
||||
});
|
||||
} else if (error.request) {
|
||||
// 请求已发送但没有收到响应
|
||||
console.error('网络错误:', error.request);
|
||||
uni.showToast({
|
||||
title: '网络错误,请检查网络连接',
|
||||
icon: 'none'
|
||||
});
|
||||
} else {
|
||||
// 请求配置出错
|
||||
console.error('请求错误:', error.message);
|
||||
uni.showToast({
|
||||
title: '请求错误',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 加载状态
|
||||
|
||||
在调用 API 时,应该显示加载状态,提升用户体验:
|
||||
|
||||
```typescript
|
||||
const loading = ref(false);
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await apiCall();
|
||||
// 处理数据
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 缓存策略
|
||||
|
||||
对于不常变化的数据,可以使用缓存策略,减少网络请求:
|
||||
|
||||
```typescript
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { userApi } from '@/api/user';
|
||||
import { useStorage } from '@/utils/storage';
|
||||
|
||||
const userList = ref([]);
|
||||
const loading = ref(false);
|
||||
const storage = useStorage();
|
||||
|
||||
const fetchUserList = async () => {
|
||||
// 尝试从缓存获取
|
||||
const cachedData = storage.get('userList');
|
||||
if (cachedData) {
|
||||
userList.value = cachedData;
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await userApi.getList({ page: 1, pageSize: 100 });
|
||||
userList.value = res.data.items;
|
||||
// 缓存数据,有效期 5 分钟
|
||||
storage.set('userList', res.data.items, 5 * 60 * 1000);
|
||||
} catch (error) {
|
||||
console.error('获取用户列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchUserList();
|
||||
});
|
||||
```
|
||||
|
||||
## 📝API 设计规范
|
||||
|
||||
### 1. URL 规范
|
||||
|
||||
- 接口 URL 使用小写字母和下划线
|
||||
- 资源路径使用复数形式
|
||||
- 版本号放在 URL 前缀(如 `/api/v1/`)
|
||||
|
||||
### 2. HTTP 方法
|
||||
|
||||
- `GET`:获取资源
|
||||
- `POST`:创建资源
|
||||
- `PUT`:更新资源
|
||||
- `DELETE`:删除资源
|
||||
- `PATCH`:部分更新资源
|
||||
|
||||
### 3. 响应格式
|
||||
|
||||
所有 API 响应采用统一的格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {...}
|
||||
}
|
||||
```
|
||||
|
||||
- `code`:状态码,200 表示成功,其他表示失败
|
||||
- `message`:响应消息,成功时为 "success",失败时为错误信息
|
||||
- `data`:响应数据,根据接口不同返回不同的数据结构
|
||||
|
||||
### 4. 分页响应
|
||||
|
||||
分页接口的响应格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [...],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"pageSize": 10,
|
||||
"pages": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `items`:当前页的数据列表
|
||||
- `total`:总记录数
|
||||
- `page`:当前页码
|
||||
- `pageSize`:每页大小
|
||||
- `pages`:总页数
|
||||
|
||||
## 💡常见问题及解决方案
|
||||
|
||||
### 1. 认证失败
|
||||
|
||||
**问题**:API 调用返回 401 错误
|
||||
**解决方案**:检查是否已登录,登录状态是否过期,重新登录获取新的认证信息。
|
||||
|
||||
### 2. 权限不足
|
||||
|
||||
**问题**:API 调用返回 403 错误
|
||||
**解决方案**:检查当前用户是否有足够的权限执行该操作,联系管理员分配权限。
|
||||
|
||||
### 3. 参数错误
|
||||
|
||||
**问题**:API 调用返回 422 错误
|
||||
**解决方案**:检查请求参数是否正确,是否缺少必要参数,参数格式是否符合要求。
|
||||
|
||||
### 4. 网络错误
|
||||
|
||||
**问题**:API 调用超时或无法连接
|
||||
**解决方案**:检查网络连接是否正常,API 地址是否正确,服务器是否正常运行。
|
||||
|
||||
### 5. 服务器错误
|
||||
|
||||
**问题**:API 调用返回 500 错误
|
||||
**解决方案**:检查服务器日志,查看具体错误原因,联系后端开发人员解决。
|
||||
|
||||
## 📚参考文档
|
||||
|
||||
- [FastAPI 官方文档](https://fastapi.tiangolo.com/)
|
||||
- [Swagger UI 官方文档](https://swagger.io/docs/open-source-tools/swagger-ui/)
|
||||
- [Redoc 官方文档](https://redocly.com/docs/redoc/)
|
||||
|
||||
通过本文档的介绍,相信您已经了解了如何使用和调用 FastapiAdmin 项目的 API。如果您在使用过程中遇到任何问题,请参考常见问题及解决方案,或联系项目维护人员获取帮助。
|
||||
@@ -0,0 +1,182 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: 贡献指南
|
||||
---
|
||||
|
||||
# 🤝 贡献指南
|
||||
|
||||
感谢你对 FastapiAdmin 的关注!我们非常欢迎社区贡献,无论是修复 Bug、新增功能、完善文档还是提出建议,都是对项目的宝贵支持。
|
||||
|
||||
## 📋 贡献前须知
|
||||
|
||||
在开始贡献之前,请先阅读以下内容:
|
||||
|
||||
- 查阅 [开发规范](/guidelines/),了解代码风格和提交规范
|
||||
- 在 [GitHub Issues](https://github.com/fastapiadmin/FastapiAdmin/issues) 或 [Gitee Issues](https://gitee.com/fastapiadmin/FastapiAdmin/issues) 中搜索,确认你的问题或功能需求尚未被提出
|
||||
- 对于较大的功能改动,建议先开 Issue 讨论方案,再动手开发
|
||||
|
||||
## 🚀 提交 PR 完整流程
|
||||
|
||||
### 第一步:Fork 仓库
|
||||
|
||||
前往 GitHub 或 Gitee 项目主页,点击右上角的 **Fork** 按钮,将仓库 Fork 到你自己的账号下。
|
||||
|
||||
- GitHub:[fastapiadmin/FastapiAdmin](https://github.com/fastapiadmin/FastapiAdmin)
|
||||
- Gitee:[fastapiadmin/FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
|
||||
### 第二步:克隆到本地
|
||||
|
||||
将你 Fork 后的仓库克隆到本地:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<你的用户名>/FastapiAdmin.git
|
||||
cd FastapiAdmin
|
||||
```
|
||||
|
||||
添加上游仓库,方便后续同步官方最新代码:
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
```
|
||||
|
||||
### 第三步:创建功能分支
|
||||
|
||||
**不要直接在 `master` 或 `dev` 分支上开发**,请根据改动类型创建对应分支:
|
||||
|
||||
```bash
|
||||
# 新功能
|
||||
git checkout -b feature/your-feature-name
|
||||
|
||||
# Bug 修复
|
||||
git checkout -b bugfix/your-bug-description
|
||||
|
||||
# 文档更新
|
||||
git checkout -b docs/your-doc-description
|
||||
```
|
||||
|
||||
### 第四步:开发与提交
|
||||
|
||||
完成代码修改后,按照项目的 [Git 提交规范](/guidelines/#git-提交规范) 提交代码:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat(module): 简短描述你的改动"
|
||||
```
|
||||
|
||||
提交信息格式参考:
|
||||
|
||||
| 类型 | 说明 |
|
||||
| --- | --- |
|
||||
| `feat` | 新功能 |
|
||||
| `fix` | Bug 修复 |
|
||||
| `docs` | 文档修改 |
|
||||
| `style` | 代码格式调整(不影响逻辑) |
|
||||
| `refactor` | 代码重构 |
|
||||
| `chore` | 构建工具或依赖变更 |
|
||||
|
||||
### 第五步:同步上游代码
|
||||
|
||||
在推送之前,先同步官方仓库的最新代码,避免冲突:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git rebase upstream/dev
|
||||
```
|
||||
|
||||
如果有冲突,解决冲突后继续:
|
||||
|
||||
```bash
|
||||
# 解决冲突后
|
||||
git add .
|
||||
git rebase --continue
|
||||
```
|
||||
|
||||
### 第六步:推送到远程
|
||||
|
||||
将本地分支推送到你 Fork 的远程仓库:
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
### 第七步:创建 Pull Request
|
||||
|
||||
1. 打开你 Fork 的仓库页面,GitHub/Gitee 会自动提示你创建 PR
|
||||
2. 点击 **Compare & pull request** 或 **新建 Pull Request**
|
||||
3. 确认目标分支为 **`dev`**(不是 `master`)
|
||||
4. 填写 PR 信息:
|
||||
|
||||
**PR 标题**(简洁清晰,不超过 70 字符):
|
||||
```
|
||||
feat(system): 添加用户批量导入功能
|
||||
```
|
||||
|
||||
**PR 描述模板**:
|
||||
```markdown
|
||||
## 改动说明
|
||||
|
||||
简要描述本次 PR 的改动内容和目的。
|
||||
|
||||
## 改动类型
|
||||
|
||||
- [ ] Bug 修复
|
||||
- [ ] 新功能
|
||||
- [ ] 文档更新
|
||||
- [ ] 代码重构
|
||||
- [ ] 其他
|
||||
|
||||
## 关联 Issue
|
||||
|
||||
Closes #xxx
|
||||
|
||||
## 测试说明
|
||||
|
||||
描述你是如何测试这些改动的。
|
||||
|
||||
## 截图(如适用)
|
||||
```
|
||||
|
||||
5. 提交 PR 后,等待维护者审核
|
||||
|
||||
### 第八步:响应 Code Review
|
||||
|
||||
维护者可能会对你的 PR 提出修改意见,请及时响应:
|
||||
|
||||
```bash
|
||||
# 根据反馈修改代码后,追加提交
|
||||
git add .
|
||||
git commit -m "fix: 根据 review 意见修改 xxx"
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
PR 页面会自动更新,无需重新创建。
|
||||
|
||||
## ✅ PR 合并标准
|
||||
|
||||
你的 PR 需要满足以下条件才会被合并:
|
||||
|
||||
- 代码符合项目 [开发规范](/guidelines/)
|
||||
- 通过所有自动化检查(lint、type check 等)
|
||||
- 至少获得一位维护者的 Approve
|
||||
- 没有未解决的 Review 意见
|
||||
- 提交信息符合规范
|
||||
|
||||
## 💡 贡献方向
|
||||
|
||||
如果你不知道从哪里开始,可以参考以下方向:
|
||||
|
||||
- 🐛 **修复 Bug**:查看 [Issues](https://github.com/fastapiadmin/FastapiAdmin/issues) 中标记为 `bug` 的问题
|
||||
- ✨ **新功能**:查看标记为 `enhancement` 或 `help wanted` 的 Issue
|
||||
- 📖 **完善文档**:修正错别字、补充说明、翻译文档
|
||||
- 🌍 **国际化**:帮助翻译界面或文档到其他语言
|
||||
- 🎨 **UI 优化**:改善用户界面和交互体验
|
||||
|
||||
## 📞 遇到问题?
|
||||
|
||||
如果在贡献过程中遇到任何问题,欢迎通过以下方式寻求帮助:
|
||||
|
||||
- 在相关 Issue 下留言
|
||||
- 发送邮件至 [948080782@qq.com](mailto:948080782@qq.com)
|
||||
- 加入微信交流群(见 [关于我们](/about/))
|
||||
|
||||
再次感谢你的贡献,期待你的 PR!🎉
|
||||
@@ -0,0 +1,456 @@
|
||||
# FastAPI Admin 二次开发手册
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
FastAPI Admin 是一个基于 FastAPI 框架开发的后台管理系统,具有完善的权限控制系统和模块化架构。本手册将指导您如何进行二次开发,特别是创建数据、实现权限控制和支持分页查询功能。
|
||||
|
||||
## 2. 核心架构
|
||||
|
||||
### 2.1 目录结构
|
||||
|
||||
```
|
||||
backend/
|
||||
├── app/
|
||||
│ ├── api/ # API 路由层
|
||||
│ │ └── v1/ # API 版本
|
||||
│ │ └── module_xxx/ # 业务模块
|
||||
│ │ ├── model.py # 数据模型
|
||||
│ │ ├── schema.py # 请求/响应模型
|
||||
│ │ ├── crud.py # 数据操作层
|
||||
│ │ ├── service.py # 业务逻辑层
|
||||
│ │ └── controller.py # API 控制器
|
||||
│ ├── core/ # 核心功能
|
||||
│ │ ├── base_model.py # 基础数据模型
|
||||
│ │ ├── base_crud.py # 基础数据操作
|
||||
│ │ ├── permission.py # 权限控制
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 2.2 技术栈
|
||||
|
||||
- **Web框架**: FastAPI
|
||||
- **ORM**: SQLAlchemy 2.0
|
||||
- **数据库**: 支持 PostgreSQL/MySQL/SQLite
|
||||
- **权限控制**: RBAC (基于角色的访问控制)
|
||||
- **文档**: Swagger UI/ReDoc
|
||||
|
||||
## 3. 创建数据模型
|
||||
|
||||
### 3.1 基础模型继承
|
||||
|
||||
所有数据模型都应继承自 `ModelMixin` 和 `UserMixin`,这两个类提供了基础字段和权限支持:
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/model.py
|
||||
from sqlalchemy import String, Integer
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.base_model import ModelMixin, UserMixin
|
||||
|
||||
|
||||
class XXXModel(ModelMixin, UserMixin):
|
||||
"""
|
||||
XXX模块数据模型
|
||||
"""
|
||||
__tablename__: str = 'xxx_table_name'
|
||||
__table_args__: dict[str, str] = ({'comment': 'XXX表'})
|
||||
__loader_options__: list[str] = ["created_by", "updated_by"] # 预加载关系
|
||||
|
||||
# 自定义字段
|
||||
name: Mapped[str] = mapped_column(String(64), nullable=False, comment='名称')
|
||||
value: Mapped[int] = mapped_column(Integer, default=0, comment='数值')
|
||||
# 更多字段...
|
||||
```
|
||||
|
||||
### 3.2 模型字段说明
|
||||
|
||||
- `ModelMixin` 提供:`id`, `uuid`, `status`, `description`, `created_time`, `updated_time`
|
||||
- `UserMixin` 提供:`created_id`, `updated_id`, `created_by`, `updated_by`
|
||||
|
||||
## 4. 实现权限控制
|
||||
|
||||
### 4.1 权限系统概述
|
||||
|
||||
系统实现了基于角色的数据权限控制,支持五种数据权限范围:
|
||||
|
||||
1. **仅本人数据 (1)**: 只能查看自己创建的数据
|
||||
2. **本部门数据 (2)**: 只能查看同部门的数据
|
||||
3. **本部门及以下 (3)**: 可以查看本部门及所有子部门的数据
|
||||
4. **全部数据 (4)**: 可以查看所有数据
|
||||
5. **自定义数据 (5)**: 通过角色关联的部门列表定义可访问的部门
|
||||
|
||||
### 4.2 权限自动应用
|
||||
|
||||
通过继承 `CRUDBase` 类,权限控制会自动应用到所有数据操作中:
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/crud.py
|
||||
from app.core.base_crud import CRUDBase
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .model import XXXModel
|
||||
from .schema import XXXCreateSchema, XXXUpdateSchema
|
||||
|
||||
|
||||
class XXXCRUD(CRUDBase[XXXModel, XXXCreateSchema, XXXUpdateSchema]):
|
||||
"""XXX数据操作层"""
|
||||
|
||||
def __init__(self, auth: AuthSchema) -> None:
|
||||
"""初始化"""
|
||||
self.auth = auth
|
||||
super().__init__(model=XXXModel, auth=auth)
|
||||
```
|
||||
|
||||
### 4.3 权限检查流程
|
||||
|
||||
权限检查在 `permission.py` 中的 `__permission_condition` 方法实现:
|
||||
|
||||
1. 检查是否为超级管理员
|
||||
2. 获取用户所有角色的数据权限范围
|
||||
3. 合并权限范围(取最宽松权限)
|
||||
4. 构造查询条件
|
||||
5. 应用到所有查询中
|
||||
|
||||
## 5. 支持分页查询
|
||||
|
||||
### 5.1 分页实现
|
||||
|
||||
系统提供了两种分页实现方式:
|
||||
|
||||
#### 5.1.1 使用 base_crud 中的 page 方法
|
||||
|
||||
```python
|
||||
# 在 service.py 中
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .schema import XXXCreateSchema, XXXUpdateSchema, XXXOutSchema
|
||||
from .crud import XXXCRUD
|
||||
|
||||
async def page_service(cls, auth: AuthSchema, offset: int, limit: int, search: dict) -> dict:
|
||||
"""分页查询"""
|
||||
crud = XXXCRUD(auth)
|
||||
return await crud.page(
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
order_by=[{'id': 'asc'}],
|
||||
search=search,
|
||||
out_schema=XXXOutSchema
|
||||
)
|
||||
```
|
||||
|
||||
#### 5.1.2 使用 PaginationService
|
||||
|
||||
```python
|
||||
# 在 controller.py 中
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.common.request import PaginationService
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .service import XXXService
|
||||
from .schema import XXXQueryParam
|
||||
|
||||
@XXXRouter.get("/list", summary="查询列表")
|
||||
async def get_obj_list_controller(
|
||||
page: PaginationQueryParam = Depends(),
|
||||
search: XXXQueryParam = Depends(),
|
||||
auth: AuthSchema = Depends(AuthPermission(["module_xxx:query"]))
|
||||
) -> JSONResponse:
|
||||
"""查询列表"""
|
||||
result_dict_list = await XXXService.list_service(auth=auth, search=search, order_by=page.order_by)
|
||||
result_dict = await PaginationService.paginate(data_list=result_dict_list, page_no=page.page_no, page_size=page.page_size)
|
||||
return SuccessResponse(data=result_dict, msg="查询成功")
|
||||
```
|
||||
|
||||
### 5.2 分页参数
|
||||
|
||||
分页查询支持以下参数:
|
||||
|
||||
- `page_no`: 页码(默认 1)
|
||||
- `page_size`: 每页条数(默认 10)
|
||||
- `order_by`: 排序字段(如 `[{"id": "asc"}, {"name": "desc"}]`)
|
||||
|
||||
### 5.3 分页响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"page_no": 1,
|
||||
"page_size": 10,
|
||||
"total": 100,
|
||||
"has_next": true,
|
||||
"items": [
|
||||
{"id": 1, "name": "示例1", ...},
|
||||
// 更多数据...
|
||||
]
|
||||
},
|
||||
"msg": "查询成功"
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 完整开发流程示例
|
||||
|
||||
下面以创建一个 `Task` 任务模块为例,演示完整的开发流程。
|
||||
|
||||
### 6.1 创建数据模型
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/task/model.py
|
||||
from sqlalchemy import String, Integer, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.base_model import ModelMixin, UserMixin
|
||||
|
||||
|
||||
class TaskModel(ModelMixin, UserMixin):
|
||||
"""
|
||||
任务数据模型
|
||||
"""
|
||||
__tablename__: str = 'task'
|
||||
__table_args__: dict[str, str] = ({'comment': '任务表'})
|
||||
__loader_options__: list[str] = ["created_by", "updated_by"]
|
||||
|
||||
title: Mapped[str] = mapped_column(String(128), nullable=False, comment='任务标题')
|
||||
content: Mapped[str] = mapped_column(Text, nullable=True, comment='任务内容')
|
||||
priority: Mapped[int] = mapped_column(Integer, default=3, comment='优先级:1-高,2-中,3-低')
|
||||
status: Mapped[str] = mapped_column(String(10), default='0', comment='状态:0-待处理,1-进行中,2-已完成')
|
||||
```
|
||||
|
||||
### 6.2 创建请求/响应模型
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/task/schema.py
|
||||
from pydantic import BaseModel, Field
|
||||
from app.core.base_schema import BaseSchema, UserBySchema
|
||||
|
||||
|
||||
class TaskCreateSchema(BaseModel):
|
||||
"""任务创建模型"""
|
||||
title: str = Field(..., max_length=128, description='任务标题')
|
||||
content: str | None = Field(None, description='任务内容')
|
||||
priority: int = Field(3, ge=1, le=3, description='优先级')
|
||||
status: str = Field("0", description='状态')
|
||||
description: str | None = Field(None, description='描述')
|
||||
|
||||
|
||||
class TaskUpdateSchema(TaskCreateSchema):
|
||||
"""任务更新模型"""
|
||||
...
|
||||
|
||||
|
||||
class TaskOutSchema(TaskCreateSchema, BaseSchema, UserBySchema):
|
||||
"""任务响应模型"""
|
||||
model_config = {
|
||||
"from_attributes": True
|
||||
}
|
||||
|
||||
|
||||
class TaskQueryParam:
|
||||
"""任务查询参数"""
|
||||
def __init__(
|
||||
self,
|
||||
title: str | None = None,
|
||||
priority: int | None = None,
|
||||
status: str | None = None,
|
||||
# 更多查询参数...
|
||||
) -> None:
|
||||
self.title = ("like", title) if title else None
|
||||
self.priority = priority
|
||||
self.status = status
|
||||
# 更多查询参数处理...
|
||||
```
|
||||
|
||||
### 6.3 创建数据操作层
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/task/crud.py
|
||||
from app.core.base_crud import CRUDBase
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .model import TaskModel
|
||||
from .schema import TaskCreateSchema, TaskUpdateSchema
|
||||
|
||||
|
||||
class TaskCRUD(CRUDBase[TaskModel, TaskCreateSchema, TaskUpdateSchema]):
|
||||
"""任务数据操作层"""
|
||||
|
||||
def __init__(self, auth: AuthSchema) -> None:
|
||||
"""初始化"""
|
||||
self.auth = auth
|
||||
super().__init__(model=TaskModel, auth=auth)
|
||||
|
||||
async def get_by_id_crud(self, id: int) -> TaskModel | None:
|
||||
"""根据ID获取任务"""
|
||||
return await self.get(id=id)
|
||||
|
||||
async def create_crud(self, data: TaskCreateSchema) -> TaskModel:
|
||||
"""创建任务"""
|
||||
return await self.create(data=data)
|
||||
|
||||
# 更多数据操作方法...
|
||||
```
|
||||
|
||||
### 6.4 创建业务逻辑层
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/task/service.py
|
||||
from app.core.exceptions import CustomException
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from .schema import TaskCreateSchema, TaskUpdateSchema, TaskOutSchema, TaskQueryParam
|
||||
from .crud import TaskCRUD
|
||||
|
||||
|
||||
class TaskService:
|
||||
"""任务业务逻辑层"""
|
||||
|
||||
@classmethod
|
||||
async def create_service(cls, auth: AuthSchema, data: TaskCreateSchema) -> dict:
|
||||
"""创建任务"""
|
||||
# 业务逻辑验证
|
||||
if len(data.title) < 2:
|
||||
raise CustomException(msg='任务标题至少2个字符')
|
||||
|
||||
# 创建任务
|
||||
obj = await TaskCRUD(auth).create_crud(data=data)
|
||||
return TaskOutSchema.model_validate(obj).model_dump()
|
||||
|
||||
@classmethod
|
||||
async def page_service(cls, auth: AuthSchema, offset: int, limit: int, search: dict) -> dict:
|
||||
"""分页查询任务"""
|
||||
return await TaskCRUD(auth).page(
|
||||
offset=offset,
|
||||
limit=limit,
|
||||
order_by=[{'id': 'desc'}],
|
||||
search=search,
|
||||
out_schema=TaskOutSchema
|
||||
)
|
||||
|
||||
# 更多业务逻辑方法...
|
||||
```
|
||||
|
||||
### 6.5 创建API控制器
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/task/controller.py
|
||||
from fastapi import APIRouter, Depends, Body
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.common.response import SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from .service import TaskService
|
||||
from .schema import TaskCreateSchema, TaskQueryParam
|
||||
|
||||
|
||||
TaskRouter = APIRouter(route_class=OperationLogRoute, prefix="/task", tags=["任务管理"])
|
||||
|
||||
|
||||
@TaskRouter.post("/create", summary="创建任务")
|
||||
async def create_task_controller(
|
||||
data: TaskCreateSchema = Body(...),
|
||||
auth: AuthSchema = Depends(AuthPermission(["module_xxx:task:create"]))
|
||||
) -> JSONResponse:
|
||||
"""创建任务"""
|
||||
result = await TaskService.create_service(auth=auth, data=data)
|
||||
return SuccessResponse(data=result, msg="创建任务成功")
|
||||
|
||||
|
||||
@TaskRouter.get("/page", summary="分页查询任务")
|
||||
async def page_task_controller(
|
||||
page: PaginationQueryParam = Depends(),
|
||||
search: TaskQueryParam = Depends(),
|
||||
auth: AuthSchema = Depends(AuthPermission(["module_xxx:task:query"]))
|
||||
) -> JSONResponse:
|
||||
"""分页查询任务"""
|
||||
search_dict = {k: v for k, v in search.__dict__.items() if v is not None}
|
||||
result = await TaskService.page_service(
|
||||
auth=auth,
|
||||
offset=(page.page_no - 1) * page.page_size,
|
||||
limit=page.page_size,
|
||||
search=search_dict
|
||||
)
|
||||
return SuccessResponse(data=result, msg="查询任务成功")
|
||||
|
||||
# 更多API端点...
|
||||
```
|
||||
|
||||
### 6.6 注册路由
|
||||
|
||||
确保在模块的 `__init__.py` 中导出路由:
|
||||
|
||||
```python
|
||||
# app/api/v1/module_xxx/__init__.py
|
||||
from .task.controller import TaskRouter
|
||||
|
||||
__all__ = ["TaskRouter"]
|
||||
```
|
||||
|
||||
然后在应用的路由注册中包含该模块:
|
||||
|
||||
```python
|
||||
# app/api/v1/__init__.py
|
||||
from .module_xxx import TaskRouter
|
||||
|
||||
# 注册到总路由
|
||||
```
|
||||
|
||||
## 7. 权限配置
|
||||
|
||||
### 7.1 角色数据权限
|
||||
|
||||
在角色管理中设置数据权限范围:
|
||||
|
||||
- 数据权限 = 1: 仅本人数据
|
||||
- 数据权限 = 2: 本部门数据
|
||||
- 数据权限 = 3: 本部门及以下数据
|
||||
- 数据权限 = 4: 全部数据
|
||||
- 数据权限 = 5: 自定义数据(通过角色-部门关联设置)
|
||||
|
||||
### 7.2 API权限
|
||||
|
||||
在菜单管理中配置API权限:
|
||||
|
||||
- 权限标识格式:`module_xxx:yyy:zzz`
|
||||
- `module_xxx`: 模块名称
|
||||
- `yyy`: 功能名称
|
||||
- `zzz`: 操作类型(create, update, delete, query, detail)
|
||||
|
||||
## 8. 开发注意事项
|
||||
|
||||
1. **数据模型继承**:所有业务模型必须继承 `ModelMixin` 和 `UserMixin`
|
||||
2. **权限控制**:使用 `CRUDBase` 类自动应用权限过滤
|
||||
3. **分页查询**:使用 `page` 方法获取分页数据
|
||||
4. **预加载关系**:在模型中设置 `__loader_options__` 定义默认预加载关系
|
||||
5. **异常处理**:使用 `CustomException` 抛出业务异常
|
||||
6. **日志记录**:使用 `log.info()` 记录关键操作
|
||||
|
||||
## 9. 测试与部署
|
||||
|
||||
### 9.1 开发环境启动
|
||||
|
||||
```bash
|
||||
python main.py run --env=dev
|
||||
```
|
||||
|
||||
### 9.2 数据库迁移
|
||||
|
||||
```bash
|
||||
# 生成迁移脚本
|
||||
python main.py revision --env=dev
|
||||
|
||||
# 应用迁移
|
||||
python main.py upgrade --env=dev
|
||||
```
|
||||
|
||||
### 9.3 文档访问
|
||||
|
||||
- Swagger UI: `http://localhost:8000/docs`
|
||||
- ReDoc: `http://localhost:8000/redoc`
|
||||
|
||||
## 10. 总结
|
||||
|
||||
本手册介绍了 FastAPI Admin 二次开发的核心流程,包括创建数据模型、实现权限控制和支持分页查询。通过遵循本手册的指导,您可以快速开发新的业务模块,并确保其与现有系统的兼容性和一致性。
|
||||
|
||||
如需更详细的开发文档,请参考代码注释和 Swagger UI 接口文档。
|
||||
@@ -0,0 +1,855 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: 部署指南
|
||||
---
|
||||
# 部署指南
|
||||
|
||||
## 🚀部署概述
|
||||
|
||||
FastapiAdmin 项目支持多种部署方式,包括:
|
||||
|
||||
- **Docker Compose 部署**:推荐的部署方式,快速、便捷、可移植
|
||||
- **手动部署**:适用于特殊场景或需要高度定制的情况
|
||||
- **云服务部署**:可以部署到阿里云、腾讯云等云服务提供商
|
||||
|
||||
本指南将详细介绍 FastapiAdmin 主工程和 FastApp 移动端的部署步骤。
|
||||
|
||||
## 🐳Docker Compose 部署
|
||||
|
||||
### 1. 环境准备
|
||||
|
||||
- **服务器**:推荐使用 Ubuntu 20.04+、CentOS 7+ 等 Linux 系统
|
||||
- **Docker**:版本 >= 20.0
|
||||
- **Docker Compose**:版本 >= 1.29.0
|
||||
- **网络**:确保服务器可以访问互联网,并且开放所需端口
|
||||
|
||||
### 2. 安装 Docker 和 Docker Compose
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```sh
|
||||
# 更新系统
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
|
||||
# 安装 Docker
|
||||
sudo apt install docker.io -y
|
||||
|
||||
# 安装 Docker Compose
|
||||
sudo apt install docker-compose -y
|
||||
|
||||
# 启动 Docker 服务
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 添加当前用户到 docker 组(可选)
|
||||
sudo usermod -aG docker $USER
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
#### CentOS/RHEL
|
||||
|
||||
```sh
|
||||
# 更新系统
|
||||
sudo yum update -y
|
||||
|
||||
# 安装 Docker
|
||||
sudo yum install docker -y
|
||||
|
||||
# 安装 Docker Compose
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
# 启动 Docker 服务
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 添加当前用户到 docker 组(可选)
|
||||
sudo usermod -aG docker $USER
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
### 3. 部署步骤
|
||||
|
||||
#### 1. 获取代码
|
||||
|
||||
```sh
|
||||
# 克隆代码到服务器
|
||||
cd /opt
|
||||
git clone https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
cd FastapiAdmin
|
||||
```
|
||||
|
||||
#### 2. 配置环境变量
|
||||
|
||||
```sh
|
||||
# 配置后端环境变量
|
||||
cd backend
|
||||
cp env/.env.prod.example env/.env.prod
|
||||
# 编辑 env/.env.prod 文件,配置数据库、Redis 等信息
|
||||
|
||||
# 配置前端环境变量
|
||||
cd ../frontend
|
||||
cp .env.production.example .env.production
|
||||
# 编辑 .env.production 文件,配置 API 地址等信息
|
||||
|
||||
cd ..
|
||||
```
|
||||
|
||||
#### 3. 配置 Docker Compose
|
||||
|
||||
Docker Compose 配置文件位于 `docker-compose.yaml`,包含了所有服务的配置:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml 示例
|
||||
version: '3'
|
||||
services:
|
||||
# 后端服务
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: ../devops/backend/Dockerfile
|
||||
container_name: fastapiadmin-backend
|
||||
ports:
|
||||
- "8001:8001"
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- ./backend/logs:/app/logs
|
||||
environment:
|
||||
- ENV=prod
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
restart: always
|
||||
|
||||
# 前端服务
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
container_name: fastapiadmin-frontend
|
||||
ports:
|
||||
- "5173:80"
|
||||
volumes:
|
||||
- ./frontend/dist:/usr/share/nginx/html
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
restart: always
|
||||
|
||||
# MySQL 数据库
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: fastapiadmin-mysql
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- ./devops/mysql/data:/var/lib/mysql
|
||||
- ./devops/mysql/conf:/etc/mysql/conf.d
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=your_root_password
|
||||
- MYSQL_DATABASE=fastapiadmin
|
||||
- MYSQL_USER=fastapiadmin
|
||||
- MYSQL_PASSWORD=your_password
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
restart: always
|
||||
|
||||
# Redis 缓存
|
||||
redis:
|
||||
image: redis:7.0
|
||||
container_name: fastapiadmin-redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- ./devops/redis/data:/data
|
||||
- ./devops/redis/conf/redis.conf:/etc/redis/redis.conf
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
restart: always
|
||||
|
||||
# Nginx 反向代理
|
||||
nginx:
|
||||
image: nginx:1.21
|
||||
container_name: fastapiadmin-nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./devops/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./devops/nginx/ssl:/etc/nginx/ssl
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
restart: always
|
||||
|
||||
networks:
|
||||
fastapiadmin-network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
#### 4. 配置 Nginx
|
||||
|
||||
Nginx 配置文件位于 `devops/nginx/nginx.conf`,用于反向代理和 SSL 配置:
|
||||
|
||||
```nginx
|
||||
# devops/nginx/nginx.conf 示例
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
include /usr/share/nginx/modules/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# 前端服务
|
||||
upstream frontend {
|
||||
server frontend:80;
|
||||
}
|
||||
|
||||
# 后端服务
|
||||
upstream backend {
|
||||
server backend:8001;
|
||||
}
|
||||
|
||||
# 主站点
|
||||
server {
|
||||
listen 80;
|
||||
server_name service.fastapiadmin.com;
|
||||
|
||||
# 重定向到 HTTPS
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# HTTPS 站点
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name service.fastapiadmin.com;
|
||||
|
||||
# SSL 配置
|
||||
ssl_certificate /etc/nginx/ssl/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
|
||||
ssl_session_cache shared:SSL:1m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# 前端路由
|
||||
location /web {
|
||||
proxy_pass http://frontend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# 后端 API
|
||||
location /api {
|
||||
proxy_pass http://backend;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# 静态文件
|
||||
location /static {
|
||||
alias /usr/share/nginx/html/static;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
# 健康检查
|
||||
location /health {
|
||||
return 200 "OK";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5. 启动服务
|
||||
|
||||
```sh
|
||||
# 执行部署脚本
|
||||
chmod +x start.sh
|
||||
./start.sh
|
||||
|
||||
# 或手动启动
|
||||
# 构建镜像
|
||||
docker-compose build
|
||||
|
||||
# 启动服务
|
||||
docker-compose up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### 4. 部署后配置
|
||||
|
||||
#### 1. 初始化数据库
|
||||
|
||||
```sh
|
||||
# 进入后端容器
|
||||
docker exec -it fastapiadmin-backend bash
|
||||
|
||||
# 初始化数据库
|
||||
python main.py init
|
||||
|
||||
# 退出容器
|
||||
exit
|
||||
```
|
||||
|
||||
#### 2. 配置域名
|
||||
|
||||
1. 在域名注册商处添加 A 记录,指向服务器 IP 地址
|
||||
2. 等待 DNS 解析生效
|
||||
|
||||
#### 3. 配置 SSL 证书
|
||||
|
||||
推荐使用 Let's Encrypt 免费 SSL 证书:
|
||||
|
||||
```sh
|
||||
# 安装 Certbot
|
||||
# Ubuntu/Debian
|
||||
sudo apt install certbot python3-certbot-nginx
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo yum install certbot python3-certbot-nginx
|
||||
|
||||
# 获取证书
|
||||
certbot --nginx -d service.fastapiadmin.com
|
||||
|
||||
# 自动续期
|
||||
echo "0 0 1 * * certbot renew --quiet" | sudo crontab -
|
||||
```
|
||||
|
||||
## 📦手动部署
|
||||
|
||||
### 1. 后端部署
|
||||
|
||||
#### 1. 环境准备
|
||||
|
||||
- Python 3.10+
|
||||
- MySQL 8.0+
|
||||
- Redis 7.0+
|
||||
|
||||
#### 2. 安装依赖
|
||||
|
||||
```sh
|
||||
# 进入后端目录
|
||||
cd FastapiAdmin/backend
|
||||
|
||||
# 创建虚拟环境
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 3. 配置环境变量
|
||||
|
||||
```sh
|
||||
cp env/.env.prod.example env/.env.prod
|
||||
# 编辑 env/.env.prod 文件,配置数据库、Redis 等信息
|
||||
```
|
||||
|
||||
#### 4. 初始化数据库
|
||||
|
||||
```sh
|
||||
# 生成迁移文件
|
||||
python main.py revision "初始化迁移" --env=prod
|
||||
|
||||
# 应用迁移
|
||||
python main.py upgrade --env=prod
|
||||
|
||||
# 初始化系统数据
|
||||
python main.py init
|
||||
```
|
||||
|
||||
#### 5. 启动后端服务
|
||||
|
||||
```sh
|
||||
# 使用 Gunicorn 启动(推荐)
|
||||
pip install gunicorn uvloop
|
||||
|
||||
# 启动服务
|
||||
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8001 --daemon
|
||||
|
||||
# 或使用 systemd 管理服务
|
||||
# 创建 systemd 服务文件
|
||||
```
|
||||
|
||||
### 2. 前端部署
|
||||
|
||||
#### 1. 环境准备
|
||||
|
||||
- Node.js 20.0+
|
||||
- Nginx
|
||||
|
||||
#### 2. 构建前端
|
||||
|
||||
```sh
|
||||
# 进入前端目录
|
||||
cd FastapiAdmin/frontend
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 构建前端
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
#### 3. 配置 Nginx
|
||||
|
||||
```nginx
|
||||
# /etc/nginx/conf.d/fastapiadmin.conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name service.fastapiadmin.com;
|
||||
|
||||
# 前端静态文件
|
||||
location /web {
|
||||
root /path/to/FastapiAdmin/frontend;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /web/index.html;
|
||||
}
|
||||
|
||||
# 后端 API
|
||||
location /api {
|
||||
proxy_pass http://localhost:8001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 重启 Nginx
|
||||
|
||||
```sh
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
## ☁️云服务部署
|
||||
|
||||
### 1. 阿里云部署
|
||||
|
||||
#### 1. 创建 ECS 实例
|
||||
|
||||
1. 登录阿里云控制台
|
||||
2. 创建 ECS 实例,选择 Ubuntu 20.04 或 CentOS 7+
|
||||
3. 配置安全组,开放 80、443、8001 等端口
|
||||
|
||||
#### 2. 部署步骤
|
||||
|
||||
参考前面的 Docker Compose 部署或手动部署步骤。
|
||||
|
||||
### 2. 腾讯云部署
|
||||
|
||||
#### 1. 创建 CVM 实例
|
||||
|
||||
1. 登录腾讯云控制台
|
||||
2. 创建 CVM 实例,选择 Ubuntu 20.04 或 CentOS 7+
|
||||
3. 配置安全组,开放 80、443、8001 等端口
|
||||
|
||||
#### 2. 部署步骤
|
||||
|
||||
参考前面的 Docker Compose 部署或手动部署步骤。
|
||||
|
||||
## 🔧常见部署问题及解决方案
|
||||
|
||||
### 1. Docker 相关问题
|
||||
|
||||
**问题**:Docker 构建失败
|
||||
**解决方案**:检查 Dockerfile 是否正确,依赖是否可用,网络连接是否正常。
|
||||
|
||||
**问题**:容器启动失败
|
||||
**解决方案**:查看容器日志 `docker logs <容器名>`,检查配置是否正确,端口是否被占用。
|
||||
|
||||
**问题**:Docker -compose 命令不执行
|
||||
**解决方案**:检查 Docker Compose 版本是否正确,配置文件格式是否正确。
|
||||
|
||||
### 2. 数据库相关问题
|
||||
|
||||
**问题**:数据库连接失败
|
||||
**解决方案**:检查数据库服务是否正常运行,用户名密码是否正确,防火墙是否开放 3306 端口。
|
||||
|
||||
**问题**:数据库初始化失败
|
||||
**解决方案**:检查数据库权限是否足够,SQL 语句是否正确,查看错误日志。
|
||||
|
||||
### 3. Nginx 相关问题
|
||||
|
||||
**问题**:Nginx 启动失败
|
||||
**解决方案**:检查 Nginx 配置文件是否正确 `nginx -t`,端口是否被占用。
|
||||
|
||||
**问题**:前端页面无法访问
|
||||
**解决方案**:检查 Nginx 配置是否正确,前端文件是否存在,权限是否正确。
|
||||
|
||||
**问题**:API 请求失败
|
||||
**解决方案**:检查后端服务是否正常运行,Nginx 反向代理配置是否正确,防火墙是否开放 8001 端口。
|
||||
|
||||
### 4. 网络相关问题
|
||||
|
||||
**问题**:服务器无法访问互联网
|
||||
**解决方案**:检查服务器网络连接,防火墙配置,DNS 设置。
|
||||
|
||||
**问题**:域名无法访问
|
||||
**解决方案**:检查 DNS 解析是否生效,服务器防火墙是否开放 80、443 端口,Nginx 配置是否正确。
|
||||
|
||||
### 5. 性能优化
|
||||
|
||||
**问题**:服务响应缓慢
|
||||
**解决方案**:
|
||||
- 优化数据库查询,添加索引
|
||||
- 配置 Redis 缓存
|
||||
- 调整 Nginx 配置,增加并发连接数
|
||||
- 调整后端服务的 worker 数量
|
||||
- 使用 CDN 加速静态文件
|
||||
|
||||
**问题**:服务器负载过高
|
||||
**解决方案**:
|
||||
- 监控服务器资源使用情况
|
||||
- 优化代码,减少资源消耗
|
||||
- 考虑使用负载均衡,增加服务器数量
|
||||
|
||||
## 📊监控与维护
|
||||
|
||||
### 1. 监控
|
||||
|
||||
#### 1. 服务监控
|
||||
|
||||
- **Prometheus + Grafana**:监控服务器和容器状态
|
||||
- **ELK Stack**:收集和分析日志
|
||||
- **Uptime Robot**:监控网站可用性
|
||||
|
||||
#### 2. 日志管理
|
||||
|
||||
- **后端日志**:位于 `backend/logs` 目录
|
||||
- **前端日志**:使用浏览器控制台查看
|
||||
- **Nginx 日志**:位于 `/var/log/nginx` 目录
|
||||
|
||||
### 2. 维护
|
||||
|
||||
#### 1. 定期备份
|
||||
|
||||
```sh
|
||||
# 备份数据库
|
||||
mysqldump -u root -p fastapiadmin > fastapiadmin_$(date +%Y%m%d).sql
|
||||
|
||||
# 备份代码
|
||||
zip -r fastapiadmin_$(date +%Y%m%d).zip FastapiAdmin/
|
||||
|
||||
# 备份配置文件
|
||||
cp -r FastapiAdmin/backend/env /backup/env
|
||||
cp -r FastapiAdmin/frontend/.env* /backup/frontend
|
||||
```
|
||||
|
||||
#### 2. 定期更新
|
||||
|
||||
```sh
|
||||
# 更新代码
|
||||
git pull
|
||||
|
||||
# 更新依赖
|
||||
cd FastapiAdmin/backend
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
cd ../frontend
|
||||
pnpm install
|
||||
pnpm run build
|
||||
|
||||
# 重启服务
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
#### 3. 故障排查
|
||||
|
||||
1. **查看日志**:`docker logs <容器名>`、`tail -f /var/log/nginx/error.log`
|
||||
2. **检查服务状态**:`systemctl status <服务名>`、`docker ps`
|
||||
3. **检查网络连接**:`ping <域名>`、`curl -I <URL>`
|
||||
4. **检查资源使用**:`top`、`df -h`、`free -m`
|
||||
|
||||
## 📚参考文档
|
||||
|
||||
- **Docker 官方文档**:[https://docs.docker.com/](https://docs.docker.com/)
|
||||
- **Docker Compose 官方文档**:[https://docs.docker.com/compose/](https://docs.docker.com/compose/)
|
||||
- **Nginx 官方文档**:[https://nginx.org/en/docs/](https://nginx.org/en/docs/)
|
||||
- **FastAPI 官方文档**:[https://fastapi.tiangolo.com/](https://fastapi.tiangolo.com/)
|
||||
- **Vue 官方文档**:[https://vuejs.org/](https://vuejs.org/)
|
||||
- **Let's Encrypt 官方文档**:[https://letsencrypt.org/docs/](https://letsencrypt.org/docs/)
|
||||
|
||||
## 🤝常见问题
|
||||
|
||||
### 1. 部署后无法访问
|
||||
|
||||
**解决方案**:
|
||||
1. 检查服务器防火墙是否开放 80、443 端口
|
||||
2. 检查 Nginx 服务是否正常运行
|
||||
3. 检查 DNS 解析是否生效
|
||||
4. 检查 Docker 容器是否正常运行
|
||||
|
||||
### 2. API 请求返回 500 错误
|
||||
|
||||
**解决方案**:
|
||||
1. 查看后端日志,了解具体错误信息
|
||||
2. 检查数据库连接是否正常
|
||||
3. 检查 Redis 连接是否正常
|
||||
4. 检查环境变量配置是否正确
|
||||
|
||||
### 3. 前端页面显示空白
|
||||
|
||||
**解决方案**:
|
||||
1. 检查浏览器控制台是否有错误信息
|
||||
2. 检查前端构建是否成功
|
||||
3. 检查 Nginx 配置是否正确
|
||||
4. 检查 API 地址是否配置正确
|
||||
|
||||
### 4. 部署脚本执行失败
|
||||
|
||||
**解决方案**:
|
||||
1. 检查脚本权限是否正确 `chmod +x start.sh`
|
||||
2. 检查 Docker 和 Docker Compose 是否正确安装
|
||||
3. 检查网络连接是否正常
|
||||
4. 查看脚本执行日志,了解具体错误信息
|
||||
|
||||
## �FastApp 移动端部署
|
||||
|
||||
### 1. H5 部署
|
||||
|
||||
#### 1.1 构建 H5 版本
|
||||
|
||||
```bash
|
||||
# 进入 FastApp 目录
|
||||
cd FastApp
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 构建 H5 版本
|
||||
pnpm run build:h5
|
||||
|
||||
# 构建产物在 dist/build/h5 目录
|
||||
```
|
||||
|
||||
#### 1.2 部署到服务器
|
||||
|
||||
1. 将 `dist/build/h5` 目录复制到 Web 服务器的静态文件目录
|
||||
2. 配置 Nginx 支持 SPA 路由:
|
||||
|
||||
```nginx
|
||||
# /etc/nginx/conf.d/fastapp.conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name service.fastapiadmin.com;
|
||||
|
||||
# FastApp H5
|
||||
location /app {
|
||||
alias /path/to/FastApp/dist/build/h5;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /app/index.html;
|
||||
}
|
||||
|
||||
# 其他配置...
|
||||
}
|
||||
```
|
||||
|
||||
3. 重启 Nginx:
|
||||
|
||||
```bash
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
#### 1.3 访问方式
|
||||
|
||||
部署完成后,可以通过以下地址访问 FastApp H5 版本:
|
||||
- `http://service.fastapiadmin.com/app`
|
||||
|
||||
### 2. 微信小程序部署
|
||||
|
||||
#### 2.1 构建微信小程序版本
|
||||
|
||||
```bash
|
||||
# 进入 FastApp 目录
|
||||
cd FastApp
|
||||
|
||||
# 构建微信小程序版本
|
||||
pnpm run build:mp-weixin
|
||||
|
||||
# 构建产物在 dist/build/mp-weixin 目录
|
||||
```
|
||||
|
||||
#### 2.2 发布到微信小程序平台
|
||||
|
||||
1. 打开微信开发者工具
|
||||
2. 点击「导入项目」
|
||||
3. 选择 `dist/build/mp-weixin` 目录
|
||||
4. 填写小程序 AppID(如果没有 AppID,可以使用测试号)
|
||||
5. 点击「导入」按钮
|
||||
6. 等待项目加载完成后,点击「上传」按钮
|
||||
7. 填写版本号和更新日志
|
||||
8. 点击「上传」按钮
|
||||
9. 登录微信公众平台(mp.weixin.qq.com)
|
||||
10. 进入「版本管理」页面
|
||||
11. 找到刚刚上传的版本,点击「提交审核」
|
||||
12. 等待审核通过后,点击「发布」按钮
|
||||
|
||||
### 3. 支付宝小程序部署
|
||||
|
||||
#### 3.1 构建支付宝小程序版本
|
||||
|
||||
```bash
|
||||
# 进入 FastApp 目录
|
||||
cd FastApp
|
||||
|
||||
# 构建支付宝小程序版本
|
||||
pnpm run build:mp-alipay
|
||||
|
||||
# 构建产物在 dist/build/mp-alipay 目录
|
||||
```
|
||||
|
||||
#### 3.2 发布到支付宝小程序平台
|
||||
|
||||
1. 打开支付宝小程序开发者工具
|
||||
2. 点击「导入项目」
|
||||
3. 选择 `dist/build/mp-alipay` 目录
|
||||
4. 填写小程序 AppID
|
||||
5. 点击「导入」按钮
|
||||
6. 等待项目加载完成后,点击「上传」按钮
|
||||
7. 填写版本号和更新日志
|
||||
8. 点击「上传」按钮
|
||||
9. 登录支付宝开放平台
|
||||
10. 进入「小程序管理」页面
|
||||
11. 找到刚刚上传的版本,点击「提交审核」
|
||||
12. 等待审核通过后,点击「发布」按钮
|
||||
|
||||
### 4. App 部署
|
||||
|
||||
#### 4.1 使用 HBuilderX 打包
|
||||
|
||||
1. 下载并安装 [HBuilderX](https://www.dcloud.io/hbuilderx.html)
|
||||
2. 打开 HBuilderX
|
||||
3. 点击「文件」->「导入」->「从本地目录导入」
|
||||
4. 选择 FastApp 项目目录
|
||||
5. 等待项目加载完成后,点击「发行」->「原生 App-云打包」
|
||||
6. 填写 App 名称、版本号等信息
|
||||
7. 选择打包平台(Android、iOS 或两者都选)
|
||||
8. 配置证书信息(如果没有证书,可以使用测试证书)
|
||||
9. 点击「打包」按钮
|
||||
10. 等待打包完成后,下载安装包
|
||||
|
||||
#### 4.2 发布到应用商店
|
||||
|
||||
##### Android 应用商店
|
||||
|
||||
1. 登录 [Google Play 开发者控制台](https://play.google.com/console/) 或其他 Android 应用商店
|
||||
2. 创建应用
|
||||
3. 填写应用信息
|
||||
4. 上传 APK 文件
|
||||
5. 提交审核
|
||||
6. 等待审核通过后,应用会在应用商店上线
|
||||
|
||||
##### iOS App Store
|
||||
|
||||
1. 登录 [Apple Developer](https://developer.apple.com/) 网站
|
||||
2. 进入 App Store Connect
|
||||
3. 创建新应用
|
||||
4. 填写应用信息
|
||||
5. 上传 IPA 文件(需要使用 Xcode 进行签名)
|
||||
6. 提交审核
|
||||
7. 等待审核通过后,应用会在 App Store 上线
|
||||
|
||||
### 5. 部署注意事项
|
||||
|
||||
#### 5.1 API 地址配置
|
||||
|
||||
在部署 FastApp 之前,需要确保 API 地址配置正确:
|
||||
|
||||
```bash
|
||||
# FastApp/.env.production
|
||||
# API 基础地址
|
||||
VITE_API_BASE_URL=https://service.fastapiadmin.com
|
||||
|
||||
# API 前缀
|
||||
VITE_APP_BASE_API=/api
|
||||
```
|
||||
|
||||
#### 5.2 跨域配置
|
||||
|
||||
如果 FastApp 部署在不同的域名下,需要确保后端服务支持跨域请求:
|
||||
|
||||
```python
|
||||
# FastapiAdmin/backend/app/core/middlewares.py
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"], # 在生产环境中应该设置具体的域名
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
```
|
||||
|
||||
#### 5.3 性能优化
|
||||
|
||||
- **压缩静态文件**:使用 gzip 压缩静态文件,减少传输大小
|
||||
- **启用缓存**:配置浏览器缓存,减少重复请求
|
||||
- **使用 CDN**:将静态资源部署到 CDN,提高访问速度
|
||||
- **优化图片**:压缩图片大小,使用适当的图片格式
|
||||
|
||||
### 6. 常见问题及解决方案
|
||||
|
||||
#### 6.1 H5 部署问题
|
||||
|
||||
**问题**:H5 页面刷新后显示 404
|
||||
**解决方案**:配置 Nginx 支持 SPA 路由,使用 `try_files` 指令
|
||||
|
||||
**问题**:H5 页面无法调用 API
|
||||
**解决方案**:检查 API 地址配置是否正确,确保后端服务支持跨域请求
|
||||
|
||||
#### 6.2 小程序部署问题
|
||||
|
||||
**问题**:小程序审核失败
|
||||
**解决方案**:根据审核反馈修改代码,确保符合小程序平台的规范
|
||||
|
||||
**问题**:小程序无法调用 API
|
||||
**解决方案**:在微信公众平台设置合法域名,或在开发者工具中开启「不校验合法域名」选项
|
||||
|
||||
#### 6.3 App 部署问题
|
||||
|
||||
**问题**:App 打包失败
|
||||
**解决方案**:检查证书配置是否正确,确保打包环境网络连接正常
|
||||
|
||||
**问题**:App 无法调用 API
|
||||
**解决方案**:检查 API 地址配置是否正确,确保网络连接正常
|
||||
|
||||
## �📄许可协议
|
||||
|
||||
FastapiAdmin 项目采用 MIT 许可协议,详见 [LICENSE](https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE) 文件。
|
||||
@@ -0,0 +1,253 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: About Us
|
||||
---
|
||||
# About Us
|
||||
|
||||
## 📞Contact Information
|
||||
|
||||
If you have any questions or suggestions about the project, please contact us through the following ways:
|
||||
|
||||
### GitHub
|
||||
|
||||
- **Main Project**: [fastapiadmin/FastapiAdmin](https://github.com/fastapiadmin/FastapiAdmin)
|
||||
- **Mobile Application**: [fastapiadmin/FastApp](https://github.com/fastapiadmin/FastApp)
|
||||
- **Official Documentation**: [fastapiadmin/FastDocs](https://github.com/fastapiadmin/FastDocs)
|
||||
|
||||
### Gitee
|
||||
|
||||
- **Main Project**: [fastapiadmin/FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
|
||||
### Email
|
||||
|
||||
- **Technical Support**: 948080782@qq.com
|
||||
|
||||
### WeChat
|
||||
|
||||
- **Official Account**: FastApiAdmin
|
||||
- **Technical Exchange Group**: Please scan the QR code below to join
|
||||
|
||||

|
||||
|
||||
## 🤝Contribution Guide
|
||||
|
||||
We welcome community contributions, including but not limited to:
|
||||
|
||||
### How to Contribute
|
||||
|
||||
1. **Star and Fork** the repository on GitHub
|
||||
2. **Clone** the forked repository to your local machine
|
||||
3. **Create** a new branch for your feature or bug fix
|
||||
4. **Make** the necessary changes and commit them
|
||||
5. **Push** your changes to your forked repository
|
||||
6. **Create** a Pull Request to the main repository
|
||||
|
||||
### Contribution Guidelines
|
||||
|
||||
- **Code Quality**: Follow the project's coding standards and style guidelines
|
||||
- **Documentation**: Update documentation for any changes you make
|
||||
- **Testing**: Add tests for new features and ensure existing tests pass
|
||||
- **Commit Messages**: Use clear and descriptive commit messages
|
||||
- **Pull Requests**: Provide a clear description of the changes and why they are needed
|
||||
|
||||
### Areas for Contribution
|
||||
|
||||
- **Bug Fixes**: Fix issues reported in the GitHub Issues
|
||||
- **Feature Development**: Implement new features requested by the community
|
||||
- **Documentation**: Improve existing documentation or add new documentation
|
||||
- **Code Optimization**: Optimize existing code for better performance
|
||||
- **UI/UX Improvement**: Enhance the user interface and user experience
|
||||
- **Translation**: Translate documentation into different languages
|
||||
|
||||
## 📄License
|
||||
|
||||
This project adopts the **MIT License**, which is a permissive open source license that allows for free use, modification, and distribution of the software.
|
||||
|
||||
### MIT License Summary
|
||||
|
||||
- **Free to use**: You can use the software for any purpose
|
||||
- **Free to modify**: You can modify the software as needed
|
||||
- **Free to distribute**: You can distribute the original or modified software
|
||||
- **Attribution required**: You must include the original license and copyright notice
|
||||
- **No warranty**: The software is provided "as is" without warranty
|
||||
|
||||
### Full License Text
|
||||
|
||||
For the full license text, please refer to the [LICENSE](https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE) file in the repository.
|
||||
|
||||
## 🌟Acknowledgements
|
||||
|
||||
We would like to express our gratitude to the following open source projects and communities that have contributed to the development of FastapiAdmin:
|
||||
|
||||
### Core Dependencies
|
||||
|
||||
- **FastAPI**: Modern, fast (high-performance), web framework for building APIs with Python 3.7+
|
||||
- **Vue.js**: Progressive JavaScript framework for building user interfaces
|
||||
- **TypeScript**: Typed superset of JavaScript that compiles to plain JavaScript
|
||||
- **ElementPlus**: A Vue 3 based component library for designers and developers
|
||||
- **Uni App**: Cross-platform application framework based on Vue.js
|
||||
- **SQLAlchemy**: The Python SQL toolkit and Object Relational Mapper
|
||||
- **Redis**: In-memory data structure store, used as a database, cache, and message broker
|
||||
- **MySQL**: Relational database management system
|
||||
- **Docker**: Open platform for developing, shipping, and running applications
|
||||
|
||||
### Development Tools
|
||||
|
||||
- **Vite**: Next generation frontend tooling
|
||||
- **Pnpm**: Fast, disk space efficient package manager
|
||||
- **ESLint**: Pluggable JavaScript linter
|
||||
- **Prettier**: Opinionated code formatter
|
||||
- **Black**: Uncompromising Python code formatter
|
||||
- **Mypy**: Optional static typing for Python
|
||||
|
||||
### Community Support
|
||||
|
||||
- **GitHub**: Platform for version control and collaboration
|
||||
- **Gitee**: Domestic code hosting platform for Chinese developers
|
||||
- **Stack Overflow**: Question and answer site for professional and enthusiast programmers
|
||||
- **Reddit**: Community for discussing programming and technology
|
||||
- **WeChat Groups**: Domestic technical exchange communities
|
||||
|
||||
## 🚀Project Status
|
||||
|
||||
### Current Version
|
||||
|
||||
- **Main Project**: V2.0.0
|
||||
- **Mobile Application**: V1.0.0
|
||||
- **Documentation**: V1.0.0
|
||||
|
||||
### Development Roadmap
|
||||
|
||||
#### Short-term Goals (1-3 months)
|
||||
|
||||
- **Bug Fixes**: Resolve any reported issues
|
||||
- **Performance Optimization**: Improve system performance and response speed
|
||||
- **Documentation Enhancement**: Complete and improve documentation
|
||||
- **Mobile Application**: Add more features to the mobile app
|
||||
|
||||
#### Medium-term Goals (3-6 months)
|
||||
|
||||
- **AI Integration**: Integrate AI capabilities into the development process
|
||||
- **Microservices Support**: Add support for microservices architecture
|
||||
- **Low-code Platform**: Develop a low-code platform for faster application development
|
||||
- **More Templates**: Create industry-specific templates
|
||||
|
||||
#### Long-term Goals (6-12 months)
|
||||
|
||||
- **Enterprise-level Features**: Add more enterprise-level features
|
||||
- **Internationalization**: Better support for multi-language and multi-region
|
||||
- **Ecosystem Expansion**: Build a complete ecosystem around FastapiAdmin
|
||||
- **Community Growth**: Grow the community and attract more contributors
|
||||
|
||||
## 💡FAQ
|
||||
|
||||
### General Questions
|
||||
|
||||
#### Q: What is FastapiAdmin?
|
||||
|
||||
A: FastapiAdmin is a modern, open-source, full-stack rapid development platform based on FastAPI, Vue3, and Uni App. It is designed to help developers efficiently build high-quality enterprise-level backend systems.
|
||||
|
||||
#### Q: Is FastapiAdmin free to use?
|
||||
|
||||
A: Yes, FastapiAdmin is completely open source under the MIT License, which allows for free use, modification, and distribution.
|
||||
|
||||
#### Q: What programming languages are used in FastapiAdmin?
|
||||
|
||||
A: Backend: Python; Frontend: JavaScript/TypeScript; Mobile: JavaScript/TypeScript
|
||||
|
||||
#### Q: Does FastapiAdmin support mobile development?
|
||||
|
||||
A: Yes, FastapiAdmin includes a mobile application called FastApp, which is based on Uni App and supports multiple platforms including WeChat Mini Program, H5, iOS, and Android.
|
||||
|
||||
### Technical Questions
|
||||
|
||||
#### Q: What database does FastapiAdmin use?
|
||||
|
||||
A: FastapiAdmin supports MySQL and MongoDB. MySQL is used by default, but you can configure it to use MongoDB if needed.
|
||||
|
||||
#### Q: Does FastapiAdmin support Docker deployment?
|
||||
|
||||
A: Yes, FastapiAdmin provides complete Docker deployment support, including Docker Compose configuration and Nginx reverse proxy setup.
|
||||
|
||||
#### Q: What authentication mechanism does FastapiAdmin use?
|
||||
|
||||
A: FastapiAdmin uses JWT OAuth2 authentication mechanism, which is secure, reliable, and easy to scale.
|
||||
|
||||
#### Q: Can FastapiAdmin handle high concurrency?
|
||||
|
||||
A: Yes, FastapiAdmin is based on the FastAPI asynchronous framework, which handles concurrent requests efficiently. It also supports load balancing and horizontal scaling.
|
||||
|
||||
### Deployment Questions
|
||||
|
||||
#### Q: How to deploy FastapiAdmin?
|
||||
|
||||
A: FastapiAdmin supports multiple deployment methods:
|
||||
- Docker Compose deployment (recommended)
|
||||
- Manual deployment
|
||||
- Cloud service deployment
|
||||
|
||||
Detailed deployment steps can be found in the [Deployment Guide](/en/deployment/).
|
||||
|
||||
#### Q: What are the server requirements for FastapiAdmin?
|
||||
|
||||
A: Minimum requirements:
|
||||
- CPU: 2 cores
|
||||
- Memory: 4GB
|
||||
- Disk: 50GB
|
||||
- Network: 100Mbps
|
||||
- OS: Linux (Ubuntu 20.04+ recommended)
|
||||
|
||||
Recommended requirements for production environment:
|
||||
- CPU: 4 cores+
|
||||
- Memory: 8GB+
|
||||
- Disk: 100GB+
|
||||
- Network: 1Gbps+
|
||||
|
||||
### Support Questions
|
||||
|
||||
#### Q: How to get technical support?
|
||||
|
||||
A: You can get technical support through:
|
||||
- GitHub Issues: For bug reports and feature requests
|
||||
- Email: 948080782@qq.com
|
||||
- WeChat Group: For real-time technical exchange
|
||||
|
||||
#### Q: How to report a bug?
|
||||
|
||||
A: Please report bugs on the GitHub Issues page with the following information:
|
||||
- Bug description
|
||||
- Steps to reproduce
|
||||
- Expected behavior
|
||||
- Actual behavior
|
||||
- Environment information (Python version, FastAPI version, etc.)
|
||||
- Screenshots (if applicable)
|
||||
|
||||
#### Q: How to request a new feature?
|
||||
|
||||
A: You can request new features on the GitHub Issues page with the following information:
|
||||
- Feature description
|
||||
- Use case
|
||||
- Expected functionality
|
||||
- Any relevant screenshots or examples
|
||||
|
||||
## 📞Contact Us
|
||||
|
||||
If you have any questions, suggestions, or would like to contribute to the project, please feel free to contact us through the following channels:
|
||||
|
||||
- **GitHub**: [fastapiadmin/FastapiAdmin](https://github.com/fastapiadmin/FastapiAdmin)
|
||||
- **Email**: 948080782@qq.com
|
||||
- **WeChat**: Scan the QR code to join the technical exchange group
|
||||
|
||||

|
||||
|
||||
We look forward to your feedback and contributions!
|
||||
|
||||
## 🎉Conclusion
|
||||
|
||||
**FastapiAdmin** is more than just a development platform—it's a community-driven project that aims to simplify and accelerate the development of enterprise-level applications.
|
||||
|
||||
With its advanced technology stack, complete functional modules, and excellent performance, FastapiAdmin provides a solid foundation for building modern, scalable, and maintainable applications.
|
||||
|
||||
We invite you to join our community, contribute to the project, and help us make FastapiAdmin even better!
|
||||
|
||||
Thank you for choosing FastapiAdmin!
|
||||
@@ -0,0 +1,440 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: API Documentation
|
||||
---
|
||||
# API Documentation
|
||||
|
||||
## 📚 API Documentation Overview
|
||||
|
||||
The FastapiAdmin project provides comprehensive API documentation to help developers understand and use the system's interfaces. This document will detail how to use and call these APIs.
|
||||
|
||||
## 🔧 Backend API Documentation
|
||||
|
||||
### 1. Access Methods
|
||||
|
||||
The backend API documentation is automatically generated based on FastAPI, supporting both Swagger and Redoc formats:
|
||||
|
||||
- **Swagger UI**: <http://localhost:8001/api/v1/docs> (local development environment)
|
||||
- **Redoc**: <http://localhost:8001/api/v1/redoc> (local development environment)
|
||||
- **Online Demo**: <https://service.fastapiadmin.com/api/v1/docs> (production environment)
|
||||
|
||||
### 2. Usage Methods
|
||||
|
||||
#### 2.1 Authentication and Login
|
||||
|
||||
1. Open the Swagger UI documentation page
|
||||
2. Click the "Authorize" button in the top right corner of the page
|
||||
3. Enter your username and password in the dialog box that appears
|
||||
4. Click the "Authorize" button to complete authentication
|
||||
5. After successful authentication, all API calls will automatically carry authentication information
|
||||
|
||||
#### 2.2 API Testing
|
||||
|
||||
1. Find the API you want to test in Swagger UI
|
||||
2. Click the API name to expand detailed information
|
||||
3. Click the "Try it out" button
|
||||
4. Fill in the necessary parameters
|
||||
5. Click the "Execute" button to execute the request
|
||||
6. View the response results
|
||||
|
||||
### 3. API Interface Classification
|
||||
|
||||
Backend API interfaces are mainly divided into the following categories:
|
||||
|
||||
- **System Management**: User, role, menu, department, position, and other management interfaces
|
||||
- **Monitoring Management**: Online users, server monitoring, cache monitoring, and other interfaces
|
||||
- **Task Management**: Scheduled task management interfaces
|
||||
- **Log Management**: Operation log query interfaces
|
||||
- **Development Tools**: Code generation, form building, and other interfaces
|
||||
|
||||
## 📱 Frontend API Calls
|
||||
|
||||
### 1. Frontend API Encapsulation
|
||||
|
||||
The frontend project uses TypeScript to encapsulate API calls, mainly located in the `frontend/src/api` directory, organized by module:
|
||||
|
||||
```
|
||||
frontend/src/api/
|
||||
├── module_example/ # Example module
|
||||
│ └── demo.ts
|
||||
├── module_monitor/ # Monitoring module
|
||||
│ ├── cache.ts
|
||||
│ ├── online.ts
|
||||
│ └── server.ts
|
||||
└── module_system/ # System module
|
||||
├── auth.ts
|
||||
├── dept.ts
|
||||
├── dict.ts
|
||||
├── log.ts
|
||||
├── menu.ts
|
||||
├── notice.ts
|
||||
├── params.ts
|
||||
├── role.ts
|
||||
└── user.ts
|
||||
```
|
||||
|
||||
### 2. API Call Examples
|
||||
|
||||
#### 2.1 Import API Modules
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/module_system/auth';
|
||||
import { userApi } from '@/api/module_system/user';
|
||||
```
|
||||
|
||||
#### 2.2 Call Login API
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/module_system/auth';
|
||||
import { useUserStore } from '@/store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
try {
|
||||
const res = await authApi.login({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
// Save token
|
||||
userStore.setToken(res.data.token);
|
||||
|
||||
// Get user info
|
||||
await userStore.getUserInfo();
|
||||
|
||||
// Navigate to home page
|
||||
router.push('/');
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 2.3 Call User Management API
|
||||
|
||||
```typescript
|
||||
import { userApi } from '@/api/module_system/user';
|
||||
|
||||
// Get user list
|
||||
const getUserList = async () => {
|
||||
try {
|
||||
const res = await userApi.getList({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
username: 'admin'
|
||||
});
|
||||
console.log('User list:', res.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to get user list:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Get user detail
|
||||
const getUserDetail = async (userId: number) => {
|
||||
try {
|
||||
const res = await userApi.getDetail(userId);
|
||||
console.log('User detail:', res.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to get user detail:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create user
|
||||
const createUser = async (userData: any) => {
|
||||
try {
|
||||
const res = await userApi.create(userData);
|
||||
console.log('User created successfully:', res.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to create user:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Update user
|
||||
const updateUser = async (userId: number, userData: any) => {
|
||||
try {
|
||||
const res = await userApi.update(userId, userData);
|
||||
console.log('User updated successfully:', res.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to update user:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Delete user
|
||||
const deleteUser = async (userId: number) => {
|
||||
try {
|
||||
const res = await userApi.delete(userId);
|
||||
console.log('User deleted successfully:', res.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to delete user:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 📱 FastApp Mobile API Calls
|
||||
|
||||
### 1. Mobile API Encapsulation
|
||||
|
||||
The FastApp mobile project also encapsulates API calls, mainly located in the `src/api` directory:
|
||||
|
||||
```
|
||||
FastApp/src/api/
|
||||
├── auth.ts # Authentication related interfaces
|
||||
├── file.ts # File related interfaces
|
||||
└── user.ts # User related interfaces
|
||||
```
|
||||
|
||||
### 2. API Call Examples
|
||||
|
||||
#### 2.1 Import API Modules
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/auth';
|
||||
import { userApi } from '@/api/user';
|
||||
```
|
||||
|
||||
#### 2.2 Call Login API
|
||||
|
||||
```typescript
|
||||
import { authApi } from '@/api/auth';
|
||||
import { useUserStore } from '@/store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
try {
|
||||
const res = await authApi.login({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
// Save token
|
||||
userStore.setToken(res.data.token);
|
||||
|
||||
// Get user info
|
||||
await userStore.getUserInfo();
|
||||
|
||||
// Navigate to home page
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 2.3 Call User Info API
|
||||
|
||||
```typescript
|
||||
import { userApi } from '@/api/user';
|
||||
|
||||
// Get user info
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const res = await userApi.getUserInfo();
|
||||
console.log('User info:', res.data);
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to get user info:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Update user info
|
||||
const updateUserInfo = async (userData: any) => {
|
||||
try {
|
||||
const res = await userApi.updateUserInfo(userData);
|
||||
console.log('User info updated successfully:', res.data);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to update user info:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 🛠️ API Call Best Practices
|
||||
|
||||
### 1. Error Handling
|
||||
|
||||
When calling APIs, you should properly handle possible errors:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const res = await apiCall();
|
||||
// Handle successful response
|
||||
} catch (error: any) {
|
||||
// Handle errors
|
||||
if (error.response) {
|
||||
// Server returned error status code
|
||||
console.error('Server error:', error.response.data);
|
||||
uni.showToast({
|
||||
title: error.response.data.message || 'Server error',
|
||||
icon: 'none'
|
||||
});
|
||||
} else if (error.request) {
|
||||
// Request was sent but no response received
|
||||
console.error('Network error:', error.request);
|
||||
uni.showToast({
|
||||
title: 'Network error, please check your connection',
|
||||
icon: 'none'
|
||||
});
|
||||
} else {
|
||||
// Request configuration error
|
||||
console.error('Request error:', error.message);
|
||||
uni.showToast({
|
||||
title: 'Request error',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Loading State
|
||||
|
||||
When calling APIs, you should display a loading state to improve user experience:
|
||||
|
||||
```typescript
|
||||
const loading = ref(false);
|
||||
|
||||
const fetchData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await apiCall();
|
||||
// Process data
|
||||
} catch (error) {
|
||||
// Handle errors
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Caching Strategy
|
||||
|
||||
For data that doesn't change frequently, you can use a caching strategy to reduce network requests:
|
||||
|
||||
```typescript
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { userApi } from '@/api/user';
|
||||
import { useStorage } from '@/utils/storage';
|
||||
|
||||
const userList = ref([]);
|
||||
const loading = ref(false);
|
||||
const storage = useStorage();
|
||||
|
||||
const fetchUserList = async () => {
|
||||
// Try to get from cache
|
||||
const cachedData = storage.get('userList');
|
||||
if (cachedData) {
|
||||
userList.value = cachedData;
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await userApi.getList({ page: 1, pageSize: 100 });
|
||||
userList.value = res.data.items;
|
||||
// Cache data, valid for 5 minutes
|
||||
storage.set('userList', res.data.items, 5 * 60 * 1000);
|
||||
} catch (error) {
|
||||
console.error('Failed to get user list:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchUserList();
|
||||
});
|
||||
```
|
||||
|
||||
## 📝 API Design Standards
|
||||
|
||||
### 1. URL Standards
|
||||
|
||||
- API URLs use lowercase letters and underscores
|
||||
- Resource paths use plural forms
|
||||
- Version numbers are placed in the URL prefix (e.g., `/api/v1/`)
|
||||
|
||||
### 2. HTTP Methods
|
||||
|
||||
- `GET`: Retrieve resources
|
||||
- `POST`: Create resources
|
||||
- `PUT`: Update resources
|
||||
- `DELETE`: Delete resources
|
||||
- `PATCH`: Partially update resources
|
||||
|
||||
### 3. Response Format
|
||||
|
||||
All API responses use a unified format:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {...}
|
||||
}
|
||||
```
|
||||
|
||||
- `code`: Status code, 200 indicates success, others indicate failure
|
||||
- `message`: Response message, "success" when successful, error message when failed
|
||||
- `data`: Response data, returning different data structures based on the interface
|
||||
|
||||
### 4. Paginated Response
|
||||
|
||||
Response format for paginated interfaces:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [...],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"pageSize": 10,
|
||||
"pages": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `items`: Data list for the current page
|
||||
- `total`: Total number of records
|
||||
- `page`: Current page number
|
||||
- `pageSize`: Page size
|
||||
- `pages`: Total number of pages
|
||||
|
||||
## 💡 Common Issues and Solutions
|
||||
|
||||
### 1. Authentication Failed
|
||||
|
||||
**Issue**: API call returns 401 error
|
||||
**Solution**: Check if you are logged in, if the login status has expired, and re-login to obtain new authentication information.
|
||||
|
||||
### 2. Insufficient Permissions
|
||||
|
||||
**Issue**: API call returns 403 error
|
||||
**Solution**: Check if the current user has sufficient permissions to perform the operation, and contact the administrator to assign permissions.
|
||||
|
||||
### 3. Parameter Error
|
||||
|
||||
**Issue**: API call returns 422 error
|
||||
**Solution**: Check if the request parameters are correct, if required parameters are missing, and if the parameter format meets the requirements.
|
||||
|
||||
### 4. Network Error
|
||||
|
||||
**Issue**: API call times out or cannot connect
|
||||
**Solution**: Check if the network connection is normal, if the API address is correct, and if the server is running normally.
|
||||
|
||||
### 5. Server Error
|
||||
|
||||
**Issue**: API call returns 500 error
|
||||
**Solution**: Check server logs, view the specific error cause, and contact backend developers to resolve.
|
||||
|
||||
## 📚 Reference Documentation
|
||||
|
||||
- [FastAPI Official Documentation](https://fastapi.tiangolo.com/)
|
||||
- [Swagger UI Official Documentation](https://swagger.io/docs/open-source-tools/swagger-ui/)
|
||||
- [Redoc Official Documentation](https://redocly.com/docs/redoc/)
|
||||
|
||||
Through the introduction of this document, you should now understand how to use and call the APIs of the FastapiAdmin project. If you encounter any issues during use, please refer to the common issues and solutions, or contact the project maintainers for help.
|
||||
@@ -0,0 +1,890 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Backend Development Guide
|
||||
---
|
||||
# Backend Development Guide
|
||||
|
||||
## 📋Project Overview
|
||||
|
||||
The backend part of FastapiAdmin is based on **Python + FastAPI + SQLAlchemy + Redis + MySQL**, providing a high-performance, scalable, and maintainable backend system.
|
||||
|
||||
### Core Features
|
||||
|
||||
- **Asynchronous Framework**: Based on FastAPI, supporting asynchronous processing for high concurrency
|
||||
- **Automatic API Documentation**: Swagger UI and ReDoc automatically generated
|
||||
- **Type Hints**: Full TypeScript support with Pydantic models
|
||||
- **ORM Integration**: SQLAlchemy for database operations
|
||||
- **Cache Support**: Redis integration for performance optimization
|
||||
- **Authentication**: JWT OAuth2 authentication mechanism
|
||||
- **Permission Control**: RBAC-based fine-grained permission management
|
||||
- **Database Migration**: Alembic for database schema management
|
||||
- **Configuration Management**: Environment-based configuration system
|
||||
- **Logging**: Comprehensive logging system
|
||||
|
||||
## 🛠️Technology Stack
|
||||
|
||||
| Category | Technology | Version | Description |
|
||||
|---------|------------|---------|-------------|
|
||||
| **Language** | Python | >=3.10 | Programming language |
|
||||
| **Framework** | FastAPI | 0.109.0 | Asynchronous web framework |
|
||||
| **ORM** | SQLAlchemy | 2.0.23 | Object Relational Mapper |
|
||||
| **Cache** | Redis | 4.5.4 | In-memory data store |
|
||||
| **Database** | MySQL | 8.0+ | Relational database |
|
||||
| **Authentication** | PyJWT | 2.6.0 | JWT token generation and verification |
|
||||
| **Validation** | Pydantic | 2.5.0 | Data validation and settings management |
|
||||
| **Migration** | Alembic | 1.12.1 | Database schema migration |
|
||||
| **CORS** | FastAPI CORS | - | Cross-Origin Resource Sharing |
|
||||
| **Dependency Injection** | FastAPI DI | - | Dependency injection system |
|
||||
|
||||
## 📁Project Structure
|
||||
|
||||
```
|
||||
backend/
|
||||
├── app/
|
||||
│ ├── api/ # API routes and controllers
|
||||
│ │ └── v1/ # API version 1
|
||||
│ │ ├── controllers/ # Request handlers
|
||||
│ │ ├── cruds/ # Data access layer
|
||||
│ │ ├── models/ # Database models
|
||||
│ │ ├── params/ # Request parameters
|
||||
│ │ ├── schemas/ # Response schemas
|
||||
│ │ └── urls/ # Route definitions
|
||||
│ ├── core/ # Core functionality
|
||||
│ │ ├── config.py # Configuration management
|
||||
│ │ ├── database.py # Database connection
|
||||
│ │ ├── security.py # Security utilities
|
||||
│ │ └── utils.py # Common utilities
|
||||
│ ├── middleware/ # Middleware
|
||||
│ │ ├── cors.py # CORS middleware
|
||||
│ │ ├── jwt.py # JWT middleware
|
||||
│ │ └── logger.py # Logging middleware
|
||||
│ ├── plugins/ # Plugins and extensions
|
||||
│ │ ├── init_app.py # Application initialization
|
||||
│ │ └── redis.py # Redis plugin
|
||||
│ ├── scripts/ # Scripts
|
||||
│ │ ├── data/ # Initialization data
|
||||
│ │ ├── alembic/ # Database migrations
|
||||
│ │ ├── initialize.py # System initialization
|
||||
│ │ └── main.py # Main script
|
||||
│ └── services/ # Business logic services
|
||||
├── env/ # Environment configuration files
|
||||
│ ├── .env.dev # Development environment
|
||||
│ └── .env.prod # Production environment
|
||||
├── main.py # Application entry point
|
||||
├── requirements.txt # Python dependencies
|
||||
├── setup.py # Package setup
|
||||
└── README.md # Backend documentation
|
||||
```
|
||||
|
||||
## 🚀Getting Started
|
||||
|
||||
### Environment Setup
|
||||
|
||||
1. **Install Python**
|
||||
|
||||
```sh
|
||||
# macOS
|
||||
brew install python@3.10
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install python3.10 python3.10-venv python3.10-dev
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo dnf install python3.10 python3.10-venv python3.10-devel
|
||||
```
|
||||
|
||||
2. **Install MySQL and Redis**
|
||||
|
||||
```sh
|
||||
# macOS
|
||||
brew install mysql redis
|
||||
brew services start mysql redis
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install mysql-server redis-server
|
||||
sudo systemctl start mysql redis
|
||||
```
|
||||
|
||||
### Project Setup
|
||||
|
||||
1. **Clone the repository**
|
||||
|
||||
```sh
|
||||
git clone https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
cd FastapiAdmin/backend
|
||||
```
|
||||
|
||||
2. **Create virtual environment**
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
|
||||
# Activate virtual environment
|
||||
# macOS/Linux
|
||||
source .venv/bin/activate
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
```
|
||||
|
||||
3. **Install dependencies**
|
||||
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
4. **Configure environment variables**
|
||||
|
||||
```sh
|
||||
cp env/.env.dev.example env/.env.dev
|
||||
# Edit env/.env.dev file
|
||||
```
|
||||
|
||||
5. **Initialize database**
|
||||
|
||||
```sh
|
||||
# Generate migration files
|
||||
python main.py revision "Initial migration" --env=dev
|
||||
|
||||
# Apply migration
|
||||
python main.py upgrade --env=dev
|
||||
|
||||
# Initialize system data
|
||||
python main.py init
|
||||
```
|
||||
|
||||
6. **Start development server**
|
||||
|
||||
```sh
|
||||
python main.py run --env=dev
|
||||
```
|
||||
|
||||
The backend API will be available at `http://localhost:8001`
|
||||
|
||||
API documentation will be available at:
|
||||
- Swagger UI: `http://localhost:8001/api/v1/docs`
|
||||
- ReDoc: `http://localhost:8001/api/v1/redoc`
|
||||
|
||||
## 📝Development Process
|
||||
|
||||
### 1. Creating a New Model
|
||||
|
||||
1. **Create model class** in `app/api/v1/models/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/models/demo/example_model.py
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.core.database import Base
|
||||
from datetime import datetime
|
||||
|
||||
class Example(Base):
|
||||
__tablename__ = "example"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False, index=True)
|
||||
description = Column(String(500), nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
# relationship("OtherModel", back_populates="example")
|
||||
```
|
||||
|
||||
2. **Register model** in `app/scripts/alembic/env.py`
|
||||
|
||||
### 2. Creating CRUD Operations
|
||||
|
||||
1. **Create CRUD class** in `app/api/v1/cruds/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/cruds/demo/example_crud.py
|
||||
from sqlalchemy.orm import Session
|
||||
from app.api.v1.models.demo.example_model import Example
|
||||
from app.api.v1.schemas.demo.example_schema import ExampleCreate, ExampleUpdate
|
||||
|
||||
class ExampleCRUD:
|
||||
@staticmethod
|
||||
def get_by_id(db: Session, example_id: int):
|
||||
return db.query(Example).filter(Example.id == example_id).first()
|
||||
|
||||
@staticmethod
|
||||
def get_list(db: Session, skip: int = 0, limit: int = 100):
|
||||
return db.query(Example).offset(skip).limit(limit).all()
|
||||
|
||||
@staticmethod
|
||||
def create(db: Session, example: ExampleCreate):
|
||||
db_example = Example(**example.dict())
|
||||
db.add(db_example)
|
||||
db.commit()
|
||||
db.refresh(db_example)
|
||||
return db_example
|
||||
|
||||
@staticmethod
|
||||
def update(db: Session, example_id: int, example: ExampleUpdate):
|
||||
db_example = ExampleCRUD.get_by_id(db, example_id)
|
||||
if db_example:
|
||||
update_data = example.dict(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
setattr(db_example, field, value)
|
||||
db.commit()
|
||||
db.refresh(db_example)
|
||||
return db_example
|
||||
|
||||
@staticmethod
|
||||
def delete(db: Session, example_id: int):
|
||||
db_example = ExampleCRUD.get_by_id(db, example_id)
|
||||
if db_example:
|
||||
db.delete(db_example)
|
||||
db.commit()
|
||||
return db_example
|
||||
|
||||
example_crud = ExampleCRUD()
|
||||
```
|
||||
|
||||
### 3. Creating Schemas
|
||||
|
||||
1. **Create schema classes** in `app/api/v1/schemas/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/schemas/demo/example_schema.py
|
||||
from pydantic import BaseModel, Field
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
class ExampleBase(BaseModel):
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
description: Optional[str] = Field(None, max_length=500)
|
||||
|
||||
class ExampleCreate(ExampleBase):
|
||||
pass
|
||||
|
||||
class ExampleUpdate(BaseModel):
|
||||
name: Optional[str] = Field(None, min_length=1, max_length=100)
|
||||
description: Optional[str] = Field(None, max_length=500)
|
||||
|
||||
class ExampleResponse(ExampleBase):
|
||||
id: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class ExampleListResponse(BaseModel):
|
||||
items: list[ExampleResponse]
|
||||
total: int
|
||||
```
|
||||
|
||||
### 4. Creating Request Parameters
|
||||
|
||||
1. **Create parameter classes** in `app/api/v1/params/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/params/demo/example_param.py
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
class ExampleListParams(BaseModel):
|
||||
page: int = Field(1, ge=1)
|
||||
page_size: int = Field(10, ge=1, le=100)
|
||||
name: Optional[str] = Field(None, max_length=100)
|
||||
```
|
||||
|
||||
### 5. Creating Controller
|
||||
|
||||
1. **Create controller class** in `app/api/v1/controllers/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/controllers/demo/example_controller.py
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from app.api.v1.cruds.demo.example_crud import example_crud
|
||||
from app.api.v1.schemas.demo.example_schema import ExampleCreate, ExampleUpdate, ExampleResponse, ExampleListResponse
|
||||
from app.api.v1.params.demo.example_param import ExampleListParams
|
||||
|
||||
router = APIRouter(prefix="/examples", tags=["examples"])
|
||||
|
||||
@router.get("", response_model=ExampleListResponse)
|
||||
def get_examples(
|
||||
params: ExampleListParams = Depends(),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
skip = (params.page - 1) * params.page_size
|
||||
examples = example_crud.get_list(db, skip=skip, limit=params.page_size)
|
||||
total = db.query(example_crud.model).count()
|
||||
return ExampleListResponse(items=examples, total=total)
|
||||
|
||||
@router.get("/{example_id}", response_model=ExampleResponse)
|
||||
def get_example(
|
||||
example_id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
example = example_crud.get_by_id(db, example_id)
|
||||
if not example:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return example
|
||||
|
||||
@router.post("", response_model=ExampleResponse, status_code=201)
|
||||
def create_example(
|
||||
example: ExampleCreate,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
return example_crud.create(db, example)
|
||||
|
||||
@router.put("/{example_id}", response_model=ExampleResponse)
|
||||
def update_example(
|
||||
example_id: int,
|
||||
example: ExampleUpdate,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
updated_example = example_crud.update(db, example_id, example)
|
||||
if not updated_example:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return updated_example
|
||||
|
||||
@router.delete("/{example_id}", status_code=204)
|
||||
def delete_example(
|
||||
example_id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
deleted_example = example_crud.delete(db, example_id)
|
||||
if not deleted_example:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return None
|
||||
```
|
||||
|
||||
### 6. Registering Routes
|
||||
|
||||
1. **Create route file** in `app/api/v1/urls/` directory
|
||||
|
||||
```python
|
||||
# app/api/v1/urls/demo/example_url.py
|
||||
from fastapi import APIRouter
|
||||
from app.api.v1.controllers.demo.example_controller import router as example_router
|
||||
|
||||
router = APIRouter()
|
||||
router.include_router(example_router)
|
||||
```
|
||||
|
||||
2. **Register route** in `app/plugins/init_app.py`
|
||||
|
||||
```python
|
||||
# app/plugins/init_app.py
|
||||
from fastapi import FastAPI
|
||||
from app.api.v1.urls.demo.example_url import router as example_router
|
||||
|
||||
def init_routes(app: FastAPI):
|
||||
# ... existing routes
|
||||
app.include_router(example_router, prefix="/api/v1")
|
||||
```
|
||||
|
||||
### 7. Database Migration
|
||||
|
||||
1. **Generate migration file**
|
||||
|
||||
```sh
|
||||
python main.py revision "Add example table" --env=dev
|
||||
```
|
||||
|
||||
2. **Apply migration**
|
||||
|
||||
```sh
|
||||
python main.py upgrade --env=dev
|
||||
```
|
||||
|
||||
## 🔧Common Development Tasks
|
||||
|
||||
### 1. Adding a New API Endpoint
|
||||
|
||||
1. **Create model** (if needed)
|
||||
2. **Create CRUD operations** (if needed)
|
||||
3. **Create schemas** for request and response
|
||||
4. **Create controller** with endpoint logic
|
||||
5. **Register route** in URL configuration
|
||||
6. **Add to migration** (if database changes)
|
||||
7. **Test endpoint** using Swagger UI
|
||||
|
||||
### 2. Authentication and Authorization
|
||||
|
||||
#### JWT Authentication
|
||||
|
||||
```python
|
||||
# app/core/security.py
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional, Union
|
||||
from jose import JWTError, jwt
|
||||
from passlib.context import CryptContext
|
||||
from app.core.config import settings
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
def verify_token(token: str, credentials_exception):
|
||||
try:
|
||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
return username
|
||||
except JWTError:
|
||||
raise credentials_exception
|
||||
|
||||
def verify_password(plain_password: str, hashed_password: str):
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
def get_password_hash(password: str):
|
||||
return pwd_context.hash(password)
|
||||
```
|
||||
|
||||
#### Dependency Injection for Authentication
|
||||
|
||||
```python
|
||||
# app/api/v1/controllers/user_controller.py
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from app.core.security import verify_token
|
||||
from app.api.v1.models.user_model import User
|
||||
from app.api.v1.cruds.user_crud import user_crud
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
||||
|
||||
async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
username = verify_token(token, credentials_exception)
|
||||
user = user_crud.get_by_username(db, username=username)
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
return user
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
def read_users_me(current_user: User = Depends(get_current_user)):
|
||||
return current_user
|
||||
```
|
||||
|
||||
### 3. Permission Control
|
||||
|
||||
#### RBAC Model
|
||||
|
||||
FastapiAdmin uses Role-Based Access Control (RBAC) for permission management:
|
||||
|
||||
1. **Roles**: Define roles with specific permissions
|
||||
2. **Permissions**: Define what actions can be performed
|
||||
3. **Users**: Assign roles to users
|
||||
4. **Resources**: Define protected resources (endpoints, data)
|
||||
|
||||
#### Permission Checker
|
||||
|
||||
```python
|
||||
# app/core/security.py
|
||||
def check_permission(current_user: User, required_permission: str) -> bool:
|
||||
"""Check if user has required permission"""
|
||||
# Check if user is admin
|
||||
if current_user.is_admin:
|
||||
return True
|
||||
|
||||
# Check user roles and permissions
|
||||
for role in current_user.roles:
|
||||
for permission in role.permissions:
|
||||
if permission.code == required_permission:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# Usage in controller
|
||||
@router.get("/protected")
|
||||
def protected_route(
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
if not check_permission(current_user, "protected_resource:read"):
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||||
return {"message": "Access granted"}
|
||||
```
|
||||
|
||||
### 4. Configuration Management
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
FastapiAdmin uses environment variables for configuration management:
|
||||
|
||||
```python
|
||||
# app/core/config.py
|
||||
from pydantic_settings import BaseSettings
|
||||
from typing import Optional
|
||||
|
||||
class Settings(BaseSettings):
|
||||
# Project settings
|
||||
PROJECT_NAME: str = "FastapiAdmin"
|
||||
API_V1_STR: str = "/api/v1"
|
||||
|
||||
# Database settings
|
||||
DATABASE_URL: str
|
||||
|
||||
# Redis settings
|
||||
REDIS_URL: str
|
||||
|
||||
# Security settings
|
||||
SECRET_KEY: str
|
||||
ALGORITHM: str = "HS256"
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
|
||||
|
||||
# CORS settings
|
||||
BACKEND_CORS_ORIGINS: list[str] = ["*"]
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
case_sensitive = True
|
||||
|
||||
settings = Settings()
|
||||
```
|
||||
|
||||
#### Environment Files
|
||||
|
||||
Environment variables are stored in `.env` files for different environments:
|
||||
|
||||
```
|
||||
# env/.env.dev
|
||||
# Database
|
||||
DATABASE_URL="mysql+aiomysql://admin:123456@localhost:3306/fastapiadmin_dev"
|
||||
|
||||
# Redis
|
||||
REDIS_URL="redis://localhost:6379/0"
|
||||
|
||||
# Security
|
||||
SECRET_KEY="your-secret-key-here"
|
||||
```
|
||||
|
||||
### 5. Logging
|
||||
|
||||
#### Logger Configuration
|
||||
|
||||
```python
|
||||
# app/core/logger.py
|
||||
import logging
|
||||
import sys
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from app.core.config import settings
|
||||
|
||||
# Create logger
|
||||
logger = logging.getLogger(settings.PROJECT_NAME)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Create formatter
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
# Create console handler
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
# Create file handler
|
||||
file_handler = RotatingFileHandler(
|
||||
"app.log", maxBytes=10485760, backupCount=5
|
||||
)
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Add handlers to logger
|
||||
logger.addHandler(console_handler)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
export logger
|
||||
```
|
||||
|
||||
#### Usage
|
||||
|
||||
```python
|
||||
from app.core.logger import logger
|
||||
|
||||
logger.info("Application started")
|
||||
logger.error("An error occurred")
|
||||
logger.debug("Debug information")
|
||||
```
|
||||
|
||||
## 📡API Design
|
||||
|
||||
### 1. RESTful API Principles
|
||||
|
||||
FastapiAdmin follows RESTful API design principles:
|
||||
|
||||
- **Resource Naming**: Use nouns for endpoints (e.g., `/users`, `/products`)
|
||||
- **HTTP Methods**: Use appropriate HTTP methods for operations:
|
||||
- `GET`: Retrieve resources
|
||||
- `POST`: Create resources
|
||||
- `PUT`: Update resources
|
||||
- `DELETE`: Delete resources
|
||||
- **Status Codes**: Use standard HTTP status codes:
|
||||
- `200 OK`: Successful GET, PUT
|
||||
- `201 Created`: Successful POST
|
||||
- `204 No Content`: Successful DELETE
|
||||
- `400 Bad Request`: Invalid request
|
||||
- `401 Unauthorized`: Authentication required
|
||||
- `403 Forbidden`: Insufficient permissions
|
||||
- `404 Not Found`: Resource not found
|
||||
- `500 Internal Server Error`: Server error
|
||||
|
||||
### 2. API Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"name": "Example",
|
||||
"description": "This is an example"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Pagination
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Item 1"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Item 2"
|
||||
}
|
||||
],
|
||||
"total": 100,
|
||||
"page": 1,
|
||||
"page_size": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔒Security Best Practices
|
||||
|
||||
### 1. Input Validation
|
||||
|
||||
- **Use Pydantic**: Validate all input data with Pydantic models
|
||||
- **Type Hints**: Use Python type hints for type safety
|
||||
- **Parameter Constraints**: Set constraints on parameters (min/max length, regex patterns)
|
||||
- **Sanitization**: Sanitize user input to prevent injection attacks
|
||||
|
||||
### 2. Authentication
|
||||
|
||||
- **JWT Tokens**: Use secure JWT tokens with proper expiration
|
||||
- **Password Hashing**: Use bcrypt for password hashing
|
||||
- **Token Rotation**: Implement token rotation for enhanced security
|
||||
- **Multi-factor Authentication**: Support MFA for sensitive operations
|
||||
|
||||
### 3. Authorization
|
||||
|
||||
- **RBAC**: Use Role-Based Access Control for granular permissions
|
||||
- **Least Privilege**: Assign minimum required permissions to users
|
||||
- **Permission Checks**: Verify permissions for every protected resource
|
||||
- **Audit Logs**: Log permission changes and access attempts
|
||||
|
||||
### 4. Data Protection
|
||||
|
||||
- **Encryption**: Encrypt sensitive data at rest and in transit
|
||||
- **HTTPS**: Use HTTPS for all communications
|
||||
- **CORS**: Configure CORS properly to restrict cross-origin requests
|
||||
- **CSRF Protection**: Implement CSRF protection for forms
|
||||
|
||||
### 5. Rate Limiting
|
||||
|
||||
- **API Rate Limits**: Limit requests per user/IP to prevent abuse
|
||||
- **Brute Force Protection**: Implement delays for failed login attempts
|
||||
- **Throttling**: Throttle sensitive operations (password resets, etc.)
|
||||
|
||||
## 📦Deployment
|
||||
|
||||
### 1. Docker Deployment
|
||||
|
||||
#### Dockerfile
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM python:3.10-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 8001
|
||||
|
||||
CMD ["python", "main.py", "run", "--env=prod"]
|
||||
```
|
||||
|
||||
#### Docker Compose
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build: ./backend
|
||||
ports:
|
||||
- "8001:8001"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
environment:
|
||||
- DATABASE_URL=mysql+aiomysql://admin:123456@db:3306/fastapiadmin
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
- SECRET_KEY=your-secret-key-here
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
- MYSQL_DATABASE=fastapiadmin
|
||||
- MYSQL_USER=admin
|
||||
- MYSQL_PASSWORD=123456
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
|
||||
redis:
|
||||
image: redis:7.0
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
redis_data:
|
||||
```
|
||||
|
||||
### 2. Manual Deployment
|
||||
|
||||
1. **Prepare server** with Python, MySQL, and Redis installed
|
||||
2. **Upload code** to server
|
||||
3. **Install dependencies** in virtual environment
|
||||
4. **Configure environment variables** for production
|
||||
5. **Set up Nginx** as reverse proxy
|
||||
6. **Use Gunicorn** with Uvicorn workers
|
||||
7. **Set up systemd service** for automatic startup
|
||||
|
||||
### 3. Cloud Deployment
|
||||
|
||||
FastapiAdmin can be deployed to various cloud platforms:
|
||||
|
||||
- **AWS**: EC2 + RDS + ElastiCache
|
||||
- **Azure**: App Service + Azure Database for MySQL + Azure Cache for Redis
|
||||
- **GCP**: Compute Engine + Cloud SQL + Memorystore
|
||||
- **Aliyun**: ECS + RDS + Redis
|
||||
- **Tencent Cloud**: CVM + TDSQL + Redis
|
||||
|
||||
## 🐛Common Issues and Solutions
|
||||
|
||||
### 1. Database Connection Issues
|
||||
|
||||
**Issue**: Database connection fails
|
||||
**Solution**: Check database credentials, ensure database service is running, verify network connectivity
|
||||
|
||||
### 2. Redis Connection Issues
|
||||
|
||||
**Issue**: Redis connection fails
|
||||
**Solution**: Check Redis URL, ensure Redis service is running, verify network connectivity
|
||||
|
||||
### 3. CORS Errors
|
||||
|
||||
**Issue**: Cross-Origin Resource Sharing errors
|
||||
**Solution**: Configure CORS properly in backend settings, ensure frontend URL is allowed
|
||||
|
||||
### 4. JWT Token Issues
|
||||
|
||||
**Issue**: Token validation fails
|
||||
**Solution**: Check SECRET_KEY consistency, verify token format, ensure token hasn't expired
|
||||
|
||||
### 5. Permission Denied Errors
|
||||
|
||||
**Issue**: 403 Forbidden errors
|
||||
**Solution**: Check user permissions, ensure role assignments are correct, verify permission strings
|
||||
|
||||
### 6. Database Migration Errors
|
||||
|
||||
**Issue**: Migration fails with SQL errors
|
||||
**Solution**: Check migration files, ensure models are correctly defined, verify database schema
|
||||
|
||||
### 7. Performance Issues
|
||||
|
||||
**Issue**: API response times are slow
|
||||
**Solution**: Use Redis caching, optimize database queries, implement pagination, consider async operations
|
||||
|
||||
## 📚Best Practices
|
||||
|
||||
### 1. Coding Standards
|
||||
|
||||
- **PEP 8**: Follow PEP 8 Python coding standards
|
||||
- **Type Hints**: Use type hints for better code clarity and type checking
|
||||
- **Docstrings**: Add docstrings for functions, classes, and modules
|
||||
- **Modularity**: Keep code modular and reusable
|
||||
- **Error Handling**: Implement proper error handling and logging
|
||||
|
||||
### 2. Database Best Practices
|
||||
|
||||
- **Indexing**: Add indexes for frequently queried columns
|
||||
- **Query Optimization**: Use efficient queries, avoid N+1 queries
|
||||
- **Transaction Management**: Use transactions for atomic operations
|
||||
- **Connection Pooling**: Use connection pooling for better performance
|
||||
- **Backup**: Implement regular database backups
|
||||
|
||||
### 3. Security Best Practices
|
||||
|
||||
- **Input Validation**: Validate all user input
|
||||
- **Password Hashing**: Never store plain text passwords
|
||||
- **HTTPS**: Use HTTPS for all communications
|
||||
- **Rate Limiting**: Implement rate limiting to prevent abuse
|
||||
- **Audit Logs**: Log security-related events
|
||||
|
||||
### 4. Performance Best Practices
|
||||
|
||||
- **Caching**: Use Redis for caching frequently accessed data
|
||||
- **Async Operations**: Use async/await for I/O operations
|
||||
- **Pagination**: Implement pagination for large datasets
|
||||
- **Compression**: Use gzip compression for API responses
|
||||
- **Load Balancing**: Use load balancing for high-traffic applications
|
||||
|
||||
### 5. Deployment Best Practices
|
||||
|
||||
- **Environment Separation**: Use separate environments for development, testing, and production
|
||||
- **Configuration Management**: Use environment variables for configuration
|
||||
- **Automated Deployment**: Implement CI/CD pipelines
|
||||
- **Monitoring**: Set up monitoring and alerting
|
||||
- **Rollback Plan**: Have a rollback plan for failed deployments
|
||||
|
||||
## 🎉Conclusion
|
||||
|
||||
The backend part of FastapiAdmin provides a robust, secure, and high-performance foundation for building enterprise-level applications. By following the guidelines in this document, you can develop maintainable, scalable backend systems that meet the needs of modern applications.
|
||||
|
||||
For more detailed information about FastAPI, SQLAlchemy, or other technologies used in FastapiAdmin, please refer to their official documentation:
|
||||
|
||||
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
||||
- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)
|
||||
- [Redis Python Documentation](https://redis-py.readthedocs.io/)
|
||||
- [Pydantic Documentation](https://docs.pydantic.dev/)
|
||||
- [Alembic Documentation](https://alembic.sqlalchemy.org/)
|
||||
@@ -0,0 +1,182 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Contributing Guide
|
||||
---
|
||||
|
||||
# 🤝 Contributing Guide
|
||||
|
||||
Thank you for your interest in FastapiAdmin! We warmly welcome community contributions — whether it's fixing bugs, adding features, improving documentation, or sharing suggestions, every contribution is valuable to the project.
|
||||
|
||||
## 📋 Before You Start
|
||||
|
||||
Before contributing, please take a moment to:
|
||||
|
||||
- Read the [Development Guidelines](/en/guidelines/) to understand code style and commit conventions
|
||||
- Search [GitHub Issues](https://github.com/fastapiadmin/FastapiAdmin/issues) to make sure your bug or feature request hasn't already been reported
|
||||
- For significant changes, consider opening an Issue first to discuss your approach before writing code
|
||||
|
||||
## 🚀 Step-by-Step PR Workflow
|
||||
|
||||
### Step 1: Fork the Repository
|
||||
|
||||
Go to the project's GitHub page and click the **Fork** button in the top-right corner to fork the repository to your own account.
|
||||
|
||||
- GitHub: [fastapiadmin/FastapiAdmin](https://github.com/fastapiadmin/FastapiAdmin)
|
||||
- Gitee: [fastapiadmin/FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
|
||||
### Step 2: Clone Locally
|
||||
|
||||
Clone your forked repository to your local machine:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<your-username>/FastapiAdmin.git
|
||||
cd FastapiAdmin
|
||||
```
|
||||
|
||||
Add the upstream remote to keep your fork in sync with the official repository:
|
||||
|
||||
```bash
|
||||
git remote add upstream https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
```
|
||||
|
||||
### Step 3: Create a Feature Branch
|
||||
|
||||
**Never develop directly on `master` or `dev`.** Create a branch based on the type of change:
|
||||
|
||||
```bash
|
||||
# New feature
|
||||
git checkout -b feature/your-feature-name
|
||||
|
||||
# Bug fix
|
||||
git checkout -b bugfix/your-bug-description
|
||||
|
||||
# Documentation update
|
||||
git checkout -b docs/your-doc-description
|
||||
```
|
||||
|
||||
### Step 4: Make Changes and Commit
|
||||
|
||||
After completing your changes, commit them following the project's [Git commit conventions](/en/guidelines/#git-commit-conventions):
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat(module): brief description of your change"
|
||||
```
|
||||
|
||||
Commit message type reference:
|
||||
|
||||
| Type | Description |
|
||||
| --- | --- |
|
||||
| `feat` | New feature |
|
||||
| `fix` | Bug fix |
|
||||
| `docs` | Documentation changes |
|
||||
| `style` | Code formatting (no logic change) |
|
||||
| `refactor` | Code refactoring |
|
||||
| `chore` | Build tools or dependency updates |
|
||||
|
||||
### Step 5: Sync with Upstream
|
||||
|
||||
Before pushing, sync the latest changes from the official repository to avoid conflicts:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git rebase upstream/dev
|
||||
```
|
||||
|
||||
If there are conflicts, resolve them and continue:
|
||||
|
||||
```bash
|
||||
# After resolving conflicts
|
||||
git add .
|
||||
git rebase --continue
|
||||
```
|
||||
|
||||
### Step 6: Push to Remote
|
||||
|
||||
Push your local branch to your forked remote repository:
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
### Step 7: Create a Pull Request
|
||||
|
||||
1. Open your forked repository on GitHub/Gitee — it will prompt you to create a PR automatically
|
||||
2. Click **Compare & pull request** or **New Pull Request**
|
||||
3. Make sure the target branch is **`dev`** (not `master`)
|
||||
4. Fill in the PR details:
|
||||
|
||||
**PR Title** (concise, under 70 characters):
|
||||
```
|
||||
feat(system): add bulk user import feature
|
||||
```
|
||||
|
||||
**PR Description Template**:
|
||||
```markdown
|
||||
## Summary
|
||||
|
||||
Briefly describe what this PR changes and why.
|
||||
|
||||
## Type of Change
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature
|
||||
- [ ] Documentation update
|
||||
- [ ] Code refactoring
|
||||
- [ ] Other
|
||||
|
||||
## Related Issue
|
||||
|
||||
Closes #xxx
|
||||
|
||||
## Testing
|
||||
|
||||
Describe how you tested your changes.
|
||||
|
||||
## Screenshots (if applicable)
|
||||
```
|
||||
|
||||
5. Submit the PR and wait for a maintainer to review it
|
||||
|
||||
### Step 8: Respond to Code Review
|
||||
|
||||
Maintainers may request changes. Please respond promptly:
|
||||
|
||||
```bash
|
||||
# After making the requested changes
|
||||
git add .
|
||||
git commit -m "fix: address review feedback for xxx"
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
The PR page will update automatically — no need to create a new PR.
|
||||
|
||||
## ✅ Merge Criteria
|
||||
|
||||
Your PR needs to meet the following requirements before it can be merged:
|
||||
|
||||
- Code follows the project's [Development Guidelines](/en/guidelines/)
|
||||
- All automated checks pass (lint, type check, etc.)
|
||||
- At least one maintainer Approval
|
||||
- No unresolved review comments
|
||||
- Commit messages follow the convention
|
||||
|
||||
## 💡 Ways to Contribute
|
||||
|
||||
Not sure where to start? Here are some ideas:
|
||||
|
||||
- 🐛 **Fix Bugs**: Check [Issues](https://github.com/fastapiadmin/FastapiAdmin/issues) labeled `bug`
|
||||
- ✨ **New Features**: Look for Issues labeled `enhancement` or `help wanted`
|
||||
- 📖 **Improve Docs**: Fix typos, add explanations, or translate documentation
|
||||
- 🌍 **Internationalization**: Help translate the UI or docs into other languages
|
||||
- 🎨 **UI Improvements**: Enhance the user interface and interaction experience
|
||||
|
||||
## 📞 Need Help?
|
||||
|
||||
If you run into any issues during the contribution process, feel free to reach out:
|
||||
|
||||
- Comment on the relevant Issue
|
||||
- Send an email to [948080782@qq.com](mailto:948080782@qq.com)
|
||||
- Join the WeChat group (see [About Us](/en/about/))
|
||||
|
||||
Thank you again for contributing — we look forward to your PR! 🎉
|
||||
@@ -0,0 +1,213 @@
|
||||
# Custom Development Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide provides instructions for customizing and extending FastapiAdmin to meet your specific business needs.
|
||||
|
||||
## Backend Customization
|
||||
|
||||
### Adding New Models
|
||||
|
||||
```python
|
||||
from sqlalchemy import Column, Integer, String, Text
|
||||
from fastapi_admin.database import Base
|
||||
|
||||
class Product(Base):
|
||||
__tablename__ = "products"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(255), nullable=False)
|
||||
description = Column(Text)
|
||||
price = Column(Integer, nullable=False)
|
||||
```
|
||||
|
||||
### Creating Custom APIs
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from fastapi_admin.database import get_db
|
||||
from .models import Product
|
||||
|
||||
router = APIRouter(prefix="/api/v1/products", tags=["products"])
|
||||
|
||||
@router.get("/")
|
||||
async def get_products(db: AsyncSession = Depends(get_db)):
|
||||
products = await db.query(Product).all()
|
||||
return {"products": products}
|
||||
|
||||
@router.post("/")
|
||||
async def create_product(product: Product, db: AsyncSession = Depends(get_db)):
|
||||
db.add(product)
|
||||
await db.commit()
|
||||
await db.refresh(product)
|
||||
return {"product": product}
|
||||
```
|
||||
|
||||
## Frontend Customization
|
||||
|
||||
### Adding New Components
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="product-form">
|
||||
<h2>Add New Product</h2>
|
||||
<form @submit.prevent="submitForm">
|
||||
<div class="form-group">
|
||||
<label>Product Name</label>
|
||||
<input v-model="product.name" type="text" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea v-model="product.description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Price</label>
|
||||
<input v-model.number="product.price" type="number" required>
|
||||
</div>
|
||||
<button type="submit">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const product = ref({
|
||||
name: '',
|
||||
description: '',
|
||||
price: 0
|
||||
})
|
||||
|
||||
const submitForm = async () => {
|
||||
const response = await fetch('/api/v1/products', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(product.value)
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
alert('Product created successfully!')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### Customizing the Dashboard
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="custom-dashboard">
|
||||
<h1>Custom Dashboard</h1>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<h3>Total Products</h3>
|
||||
<p>{{ productCount }}</p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<h3>Total Orders</h3>
|
||||
<p>{{ orderCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const productCount = ref(0)
|
||||
const orderCount = ref(0)
|
||||
|
||||
onMounted(async () => {
|
||||
// Fetch dashboard data
|
||||
const productsResponse = await fetch('/api/v1/products')
|
||||
const productsData = await productsResponse.json()
|
||||
productCount.value = productsData.products.length
|
||||
|
||||
const ordersResponse = await fetch('/api/v1/orders')
|
||||
const ordersData = await ordersResponse.json()
|
||||
orderCount.value = ordersData.orders.length
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## Miniprogram Customization
|
||||
|
||||
### Adding New Pages
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="product-list">
|
||||
<view class="product-item" v-for="product in products" :key="product.id">
|
||||
<text class="product-name">{{ product.name }}</text>
|
||||
<text class="product-price">¥{{ product.price }}</text>
|
||||
<button @click="viewDetails(product.id)">View Details</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const products = ref([])
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await uni.request({
|
||||
url: '/api/v1/products'
|
||||
})
|
||||
products.value = response.data.products
|
||||
})
|
||||
|
||||
const viewDetails = (productId) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/product/detail?id=${productId}`
|
||||
})
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Modular Development**: Organize your code into modules based on functionality
|
||||
2. **Version Control**: Use Git to track changes and collaborate with team members
|
||||
3. **Testing**: Write unit tests for critical functionality
|
||||
4. **Documentation**: Keep your code well-documented
|
||||
5. **Security**: Follow security best practices for API development
|
||||
|
||||
## Deployment
|
||||
|
||||
After customizing your FastapiAdmin application, you can deploy it using the same deployment methods described in the deployment guide.
|
||||
|
||||
```bash
|
||||
# Build the frontend
|
||||
cd frontend
|
||||
npm run build
|
||||
|
||||
# Build the backend (if using Docker)
|
||||
docker build -t fastapiadmin-backend .
|
||||
|
||||
# Start all services
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **API Endpoints Not Found**: Check your router configuration and ensure endpoints are properly registered
|
||||
2. **Database Connection Errors**: Verify your database credentials and network connectivity
|
||||
3. **Frontend Build Failures**: Check for syntax errors in your Vue components
|
||||
4. **CORS Issues**: Ensure your CORS configuration allows requests from your frontend domain
|
||||
|
||||
### Debugging Tips
|
||||
|
||||
1. **Enable Debug Mode**: Set `DEBUG=True` in your backend configuration
|
||||
2. **Check Logs**: Monitor backend and frontend logs for error messages
|
||||
3. **Use Browser DevTools**: Inspect network requests and console errors
|
||||
4. **Test APIs Directly**: Use tools like Postman to test API endpoints
|
||||
|
||||
## Conclusion
|
||||
|
||||
FastapiAdmin provides a flexible foundation for building custom backend systems. By following this guide, you can extend the platform to meet your specific business requirements while maintaining a clean and maintainable codebase.
|
||||
@@ -0,0 +1,715 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Deployment Guide
|
||||
---
|
||||
# Deployment Guide
|
||||
|
||||
## 📋Deployment Overview
|
||||
|
||||
FastapiAdmin supports multiple deployment methods to meet different production environment needs, including Docker Compose, manual deployment, and cloud service deployment.
|
||||
|
||||
### Deployment Methods Comparison
|
||||
|
||||
| Method | Advantages | Disadvantages | Recommended Scenario |
|
||||
|--------|------------|---------------|---------------------|
|
||||
| **Docker Compose** | Easy deployment, consistent environment, easy scaling | Requires Docker knowledge | Production environment, testing environment |
|
||||
| **Manual Deployment** | Full control, no Docker dependency | Complex setup, environment inconsistencies | Specialized environments, small-scale deployment |
|
||||
| **Cloud Service** | Managed infrastructure, auto-scaling | Higher cost, less control | Enterprise production, rapid deployment |
|
||||
|
||||
## 🐳Docker Compose Deployment
|
||||
|
||||
### 1. Prerequisites
|
||||
|
||||
- **Docker** installed on the server
|
||||
- **Docker Compose** installed on the server
|
||||
- **Server ports** 80 (Nginx) and 8001 (backend) available
|
||||
- **Minimum server requirements**: 2GB RAM, 2 CPU cores, 20GB disk space
|
||||
|
||||
### 2. Deployment Steps
|
||||
|
||||
#### Step 1: Clone the repository
|
||||
|
||||
```sh
|
||||
git clone https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
cd FastapiAdmin
|
||||
```
|
||||
|
||||
#### Step 2: Configure environment variables
|
||||
|
||||
```sh
|
||||
# Copy environment configuration files
|
||||
cp backend/env/.env.prod.example backend/env/.env.prod
|
||||
cp frontend/.env.production.example frontend/.env.production
|
||||
|
||||
# Edit environment configuration files
|
||||
# Backend: Set database connection, Redis connection, JWT secret key, etc.
|
||||
# Frontend: Set API base URL
|
||||
```
|
||||
|
||||
#### Step 3: Execute deployment script
|
||||
|
||||
```sh
|
||||
# Give script execution permission
|
||||
chmod +x start.sh
|
||||
|
||||
# Execute deployment script
|
||||
./start.sh
|
||||
|
||||
# Check deployment status
|
||||
docker compose ps
|
||||
|
||||
# View logs
|
||||
docker logs -f fastapiadmin-backend
|
||||
```
|
||||
|
||||
### 3. Docker Compose Configuration
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
fastapiadmin-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
redis-data:
|
||||
logs:
|
||||
|
||||
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: fastapiadmin-mysql
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:-root}"
|
||||
MYSQL_DATABASE: "${MYSQL_DATABASE:-fastapiadmin}"
|
||||
MYSQL_USER: "${MYSQL_USER:-admin}"
|
||||
MYSQL_PASSWORD: "${MYSQL_PASSWORD:-123456}"
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
- ./devops/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
ports:
|
||||
- "3306:3306"
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
|
||||
|
||||
redis:
|
||||
image: redis:7.0
|
||||
container_name: fastapiadmin-redis
|
||||
restart: always
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: fastapiadmin-backend
|
||||
restart: always
|
||||
environment:
|
||||
- ENVIRONMENT=prod
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- logs:/app/logs
|
||||
ports:
|
||||
- "8001:8001"
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
container_name: fastapiadmin-frontend
|
||||
restart: always
|
||||
volumes:
|
||||
- ./frontend:/app
|
||||
ports:
|
||||
- "5173:5173"
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
|
||||
|
||||
nginx:
|
||||
build:
|
||||
context: ./devops/nginx
|
||||
dockerfile: Dockerfile
|
||||
container_name: fastapiadmin-nginx
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./devops/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./devops/nginx/ssl:/etc/nginx/ssl
|
||||
depends_on:
|
||||
- backend
|
||||
- frontend
|
||||
networks:
|
||||
- fastapiadmin-network
|
||||
```
|
||||
|
||||
### 4. Nginx Configuration
|
||||
|
||||
```nginx
|
||||
# devops/nginx/nginx.conf
|
||||
worker_processes 1;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://backend:8001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
location /web/ {
|
||||
proxy_pass http://frontend:5173;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Common Docker Commands
|
||||
|
||||
```sh
|
||||
# View all containers
|
||||
docker compose ps
|
||||
|
||||
# Start all services
|
||||
docker compose up -d
|
||||
|
||||
# Stop all services
|
||||
docker compose down
|
||||
|
||||
# Restart all services
|
||||
docker compose restart
|
||||
|
||||
# View logs for a specific container
|
||||
docker logs -f fastapiadmin-backend
|
||||
|
||||
# View logs for all containers
|
||||
docker compose logs
|
||||
|
||||
# Enter a container
|
||||
docker exec -it fastapiadmin-backend bash
|
||||
|
||||
# Check container resource usage
|
||||
docker stats
|
||||
|
||||
# Remove unused containers, networks, images
|
||||
docker system prune -f
|
||||
```
|
||||
|
||||
## 🔧Manual Deployment
|
||||
|
||||
### 1. Prerequisites
|
||||
|
||||
- **Python 3.10+** installed
|
||||
- **Node.js 20+** installed
|
||||
- **MySQL 8.0+** installed and running
|
||||
- **Redis 7.0+** installed and running
|
||||
- **Nginx** installed (for reverse proxy)
|
||||
- **System dependencies**: build-essential, libpq-dev, etc.
|
||||
|
||||
### 2. Backend Deployment
|
||||
|
||||
#### Step 1: Install dependencies
|
||||
|
||||
```sh
|
||||
cd FastapiAdmin/backend
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### Step 2: Configure environment variables
|
||||
|
||||
```sh
|
||||
cp env/.env.prod.example env/.env.prod
|
||||
# Edit env/.env.prod file
|
||||
```
|
||||
|
||||
#### Step 3: Database initialization
|
||||
|
||||
```sh
|
||||
# Generate migration files
|
||||
python main.py revision "Initial migration" --env=prod
|
||||
|
||||
# Apply migration
|
||||
python main.py upgrade --env=prod
|
||||
|
||||
# Initialize system data
|
||||
python main.py init
|
||||
```
|
||||
|
||||
#### Step 4: Start backend service
|
||||
|
||||
```sh
|
||||
# Using Gunicorn with Uvicorn workers
|
||||
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8001
|
||||
|
||||
# Or using systemd service (recommended for production)
|
||||
# Create systemd service file
|
||||
```
|
||||
|
||||
### 3. Frontend Deployment
|
||||
|
||||
#### Step 1: Install dependencies
|
||||
|
||||
```sh
|
||||
cd FastapiAdmin/frontend
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### Step 2: Configure environment variables
|
||||
|
||||
```sh
|
||||
cp .env.production.example .env.production
|
||||
# Edit .env.production file
|
||||
```
|
||||
|
||||
#### Step 3: Build frontend
|
||||
|
||||
```sh
|
||||
pnpm run build
|
||||
# The built files will be in the dist directory
|
||||
```
|
||||
|
||||
#### Step 4: Deploy frontend files
|
||||
|
||||
```sh
|
||||
# Copy built files to Nginx web root
|
||||
cp -r dist/* /usr/share/nginx/html/
|
||||
```
|
||||
|
||||
### 4. Nginx Configuration
|
||||
|
||||
```nginx
|
||||
# /etc/nginx/sites-available/fastapiadmin
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://localhost:8001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /usr/share/nginx/html/static/;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Systemd Service Configuration
|
||||
|
||||
#### Backend Service
|
||||
|
||||
```ini
|
||||
# /etc/systemd/system/fastapiadmin-backend.service
|
||||
[Unit]
|
||||
Description=FastapiAdmin Backend Service
|
||||
After=network.target mysql.service redis.service
|
||||
|
||||
[Service]
|
||||
User=ubuntu
|
||||
WorkingDirectory=/path/to/FastapiAdmin/backend
|
||||
ExecStart=/path/to/FastapiAdmin/backend/venv/bin/gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8001
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
#### Start and enable service
|
||||
|
||||
```sh
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl start fastapiadmin-backend
|
||||
sudo systemctl enable fastapiadmin-backend
|
||||
sudo systemctl status fastapiadmin-backend
|
||||
```
|
||||
|
||||
## ☁️Cloud Service Deployment
|
||||
|
||||
### 1. AWS Deployment
|
||||
|
||||
#### Architecture
|
||||
|
||||
- **EC2**: For running application containers
|
||||
- **RDS**: Managed MySQL database
|
||||
- **ElastiCache**: Managed Redis cache
|
||||
- **Elastic Load Balancing**: For distributing traffic
|
||||
- **Auto Scaling**: For automatic scaling based on load
|
||||
- **S3**: For storing static files and backups
|
||||
- **CloudWatch**: For monitoring and logging
|
||||
|
||||
#### Deployment Steps
|
||||
|
||||
1. **Create VPC**: Set up a Virtual Private Cloud
|
||||
2. **Launch EC2 Instances**: Create EC2 instances for application
|
||||
3. **Set up RDS**: Create MySQL database instance
|
||||
4. **Set up ElastiCache**: Create Redis cache cluster
|
||||
5. **Configure Security Groups**: Set up proper security rules
|
||||
6. **Deploy Application**: Use Docker Compose on EC2 instances
|
||||
7. **Set up Load Balancer**: Configure ELB for traffic distribution
|
||||
8. **Configure Auto Scaling**: Set up scaling policies
|
||||
9. **Set up CloudWatch**: Configure monitoring and alerts
|
||||
|
||||
### 2. Azure Deployment
|
||||
|
||||
#### Architecture
|
||||
|
||||
- **App Service**: For running application
|
||||
- **Azure Database for MySQL**: Managed MySQL database
|
||||
- **Azure Cache for Redis**: Managed Redis cache
|
||||
- **Azure Load Balancer**: For distributing traffic
|
||||
- **Azure Storage**: For storing static files
|
||||
- **Azure Monitor**: For monitoring and logging
|
||||
|
||||
#### Deployment Steps
|
||||
|
||||
1. **Create Resource Group**: Set up a resource group
|
||||
2. **Create App Service Plan**: Choose appropriate plan
|
||||
3. **Deploy App Service**: Deploy application to App Service
|
||||
4. **Create Azure Database for MySQL**: Set up managed database
|
||||
5. **Create Azure Cache for Redis**: Set up managed cache
|
||||
6. **Configure Connection Strings**: Set up environment variables
|
||||
7. **Set up Monitoring**: Configure Azure Monitor
|
||||
8. **Enable Auto Scaling**: Set up scaling rules
|
||||
|
||||
### 3. Google Cloud Deployment
|
||||
|
||||
#### Architecture
|
||||
|
||||
- **Compute Engine**: For running application containers
|
||||
- **Cloud SQL**: Managed MySQL database
|
||||
- **Memorystore**: Managed Redis cache
|
||||
- **Load Balancing**: For distributing traffic
|
||||
- **Auto Scaling**: For automatic scaling
|
||||
- **Cloud Storage**: For storing static files
|
||||
- **Cloud Monitoring**: For monitoring and logging
|
||||
|
||||
#### Deployment Steps
|
||||
|
||||
1. **Create Project**: Set up a Google Cloud project
|
||||
2. **Enable APIs**: Enable necessary APIs
|
||||
3. **Create Compute Engine Instances**: Set up VM instances
|
||||
4. **Create Cloud SQL Instance**: Set up managed MySQL database
|
||||
5. **Create Memorystore Instance**: Set up managed Redis cache
|
||||
6. **Deploy Application**: Use Docker Compose on Compute Engine
|
||||
7. **Set up Load Balancer**: Configure load balancing
|
||||
8. **Set up Auto Scaling**: Configure instance groups and scaling
|
||||
9. **Set up Monitoring**: Configure Cloud Monitoring
|
||||
|
||||
### 4. Aliyun Deployment
|
||||
|
||||
#### Architecture
|
||||
|
||||
- **ECS**: Elastic Compute Service for running application
|
||||
- **RDS**: Relational Database Service for MySQL
|
||||
- **Redis**: ApsaraDB for Redis
|
||||
- **SLB**: Server Load Balancer
|
||||
- **Auto Scaling**: Auto Scaling Service
|
||||
- **OSS**: Object Storage Service for static files
|
||||
- **CloudMonitor**: For monitoring and alerts
|
||||
|
||||
#### Deployment Steps
|
||||
|
||||
1. **Create ECS Instances**: Set up virtual servers
|
||||
2. **Create RDS Instance**: Set up managed MySQL database
|
||||
3. **Create Redis Instance**: Set up managed Redis cache
|
||||
4. **Configure Security Groups**: Set up network security
|
||||
5. **Deploy Application**: Use Docker Compose on ECS
|
||||
6. **Set up SLB**: Configure load balancing
|
||||
7. **Set up Auto Scaling**: Configure scaling rules
|
||||
8. **Set up OSS**: Configure object storage
|
||||
9. **Set up CloudMonitor**: Configure monitoring
|
||||
|
||||
## 📊Monitoring and Maintenance
|
||||
|
||||
### 1. Monitoring Tools
|
||||
|
||||
#### Server Monitoring
|
||||
|
||||
- **Prometheus + Grafana**: Comprehensive monitoring solution
|
||||
- **CloudWatch**: For AWS deployments
|
||||
- **Azure Monitor**: For Azure deployments
|
||||
- **Cloud Monitoring**: For GCP deployments
|
||||
- **Nagios**: Open-source monitoring
|
||||
|
||||
#### Application Monitoring
|
||||
|
||||
- **New Relic**: Application performance monitoring
|
||||
- **Datadog**: Comprehensive monitoring platform
|
||||
- **Sentry**: Error tracking and monitoring
|
||||
- **ELK Stack**: Log management and analysis
|
||||
|
||||
### 2. Key Monitoring Metrics
|
||||
|
||||
#### Server Metrics
|
||||
|
||||
- **CPU Usage**: Monitor CPU utilization
|
||||
- **Memory Usage**: Monitor memory consumption
|
||||
- **Disk Usage**: Monitor disk space and I/O
|
||||
- **Network Traffic**: Monitor network throughput
|
||||
- **Load Average**: Monitor system load
|
||||
|
||||
#### Application Metrics
|
||||
|
||||
- **Response Time**: Monitor API response times
|
||||
- **Request Rate**: Monitor number of requests
|
||||
- **Error Rate**: Monitor error rates
|
||||
- **Database Queries**: Monitor database performance
|
||||
- **Cache Hit Rate**: Monitor Redis cache performance
|
||||
|
||||
#### Business Metrics
|
||||
|
||||
- **Active Users**: Monitor number of active users
|
||||
- **Transaction Volume**: Monitor business transactions
|
||||
- **Conversion Rates**: Monitor conversion metrics
|
||||
- **Revenue**: Monitor business revenue
|
||||
|
||||
### 3. Log Management
|
||||
|
||||
#### Centralized Logging
|
||||
|
||||
- **ELK Stack**: Elasticsearch, Logstash, Kibana
|
||||
- **Graylog**: Log management platform
|
||||
- **Fluentd**: Log collector and aggregator
|
||||
- **Splunk**: Enterprise log management
|
||||
|
||||
#### Log Rotation
|
||||
|
||||
```sh
|
||||
# Configure log rotation for application logs
|
||||
# /etc/logrotate.d/fastapiadmin
|
||||
/path/to/FastapiAdmin/backend/logs/*.log {
|
||||
daily
|
||||
rotate 7
|
||||
compress
|
||||
delaycompress
|
||||
missingok
|
||||
notifempty
|
||||
create 644 ubuntu ubuntu
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Backup and Recovery
|
||||
|
||||
#### Database Backup
|
||||
|
||||
- **Automated Backups**: Enable automated RDS/Azure SQL/Cloud SQL backups
|
||||
- **Manual Backups**: Schedule regular manual backups
|
||||
- **Point-in-Time Recovery**: Set up for critical data
|
||||
- **Off-site Backups**: Store backups in separate location
|
||||
|
||||
#### Application Backup
|
||||
|
||||
- **Code Repository**: Use Git for code versioning
|
||||
- **Configuration Files**: Back up configuration files
|
||||
- **Static Files**: Back up user-uploaded files
|
||||
- **Docker Images**: Store Docker images in registry
|
||||
|
||||
#### Recovery Plan
|
||||
|
||||
- **Disaster Recovery Plan**: Document recovery procedures
|
||||
- **Regular Testing**: Test backup restoration process
|
||||
- **Recovery Time Objective**: Define acceptable downtime
|
||||
- **Recovery Point Objective**: Define acceptable data loss
|
||||
|
||||
### 5. Security Maintenance
|
||||
|
||||
#### Regular Updates
|
||||
|
||||
- **Operating System**: Keep OS updated
|
||||
- **Application Dependencies**: Update dependencies regularly
|
||||
- **Security Patches**: Apply security patches promptly
|
||||
- **Docker Images**: Use official, updated images
|
||||
|
||||
#### Security Scanning
|
||||
|
||||
- **Vulnerability Scanning**: Regularly scan for vulnerabilities
|
||||
- **Penetration Testing**: Periodic penetration testing
|
||||
- **Security Audits**: Regular security audits
|
||||
- **Compliance Checks**: Ensure compliance with standards
|
||||
|
||||
#### Access Control
|
||||
|
||||
- **Least Privilege**: Follow least privilege principle
|
||||
- **Access Reviews**: Regularly review user access
|
||||
- **Multi-factor Authentication**: Enable MFA for admin access
|
||||
- **SSH Key Management**: Properly manage SSH keys
|
||||
|
||||
## 🐛Common Issues and Solutions
|
||||
|
||||
### 1. Deployment Issues
|
||||
|
||||
#### Docker Compose Issues
|
||||
|
||||
**Issue**: Docker Compose fails to start
|
||||
**Solution**: Check Docker logs, ensure ports are available, verify environment variables
|
||||
|
||||
**Issue**: Database connection fails
|
||||
**Solution**: Check MySQL service status, verify database credentials, ensure network connectivity
|
||||
|
||||
**Issue**: Redis connection fails
|
||||
**Solution**: Check Redis service status, verify Redis URL, ensure network connectivity
|
||||
|
||||
#### Nginx Issues
|
||||
|
||||
**Issue**: 502 Bad Gateway error
|
||||
**Solution**: Check backend service status, verify proxy configuration, ensure backend is running
|
||||
|
||||
**Issue**: 404 Not Found error
|
||||
**Solution**: Check Nginx root directory, verify file permissions, ensure files exist
|
||||
|
||||
**Issue**: SSL certificate errors
|
||||
**Solution**: Check SSL configuration, verify certificate validity, ensure proper certificate chain
|
||||
|
||||
### 2. Performance Issues
|
||||
|
||||
**Issue**: High CPU usage
|
||||
**Solution**: Optimize application code, increase server resources, implement caching
|
||||
|
||||
**Issue**: Slow database queries
|
||||
**Solution**: Optimize SQL queries, add indexes, consider database sharding
|
||||
|
||||
**Issue**: Memory leaks
|
||||
**Solution**: Profile application, fix memory leaks, increase memory limit
|
||||
|
||||
**Issue**: Network latency
|
||||
**Solution**: Use CDN for static files, optimize API responses, consider edge caching
|
||||
|
||||
### 3. Security Issues
|
||||
|
||||
**Issue**: Unauthorized access
|
||||
**Solution**: Implement proper authentication, use HTTPS, configure firewalls
|
||||
|
||||
**Issue**: SQL injection
|
||||
**Solution**: Use parameterized queries, validate input, use ORM
|
||||
|
||||
**Issue**: Cross-site scripting (XSS)
|
||||
**Solution**: Sanitize user input, use Content Security Policy, escape output
|
||||
|
||||
**Issue**: Cross-site request forgery (CSRF)
|
||||
**Solution**: Implement CSRF tokens, validate Origin header, use SameSite cookies
|
||||
|
||||
### 4. Scaling Issues
|
||||
|
||||
**Issue**: Application not scaling properly
|
||||
**Solution**: Check auto-scaling configuration, ensure load balancer is working, optimize application for scaling
|
||||
|
||||
**Issue**: Database bottleneck
|
||||
**Solution**: Implement database replication, use read replicas, consider sharding
|
||||
|
||||
**Issue**: Cache inconsistency
|
||||
**Solution**: Implement proper cache invalidation, use distributed cache, consider cache warming
|
||||
|
||||
**Issue**: Session management
|
||||
**Solution**: Use Redis for session storage, implement stateless sessions, consider JWT
|
||||
|
||||
## 📚Best Practices
|
||||
|
||||
### 1. Deployment Best Practices
|
||||
|
||||
- **Infrastructure as Code**: Use Terraform or CloudFormation for infrastructure
|
||||
- **CI/CD Pipeline**: Implement continuous integration and deployment
|
||||
- **Environment Consistency**: Use Docker for consistent environments
|
||||
- **Rolling Deployments**: Use rolling deployments to minimize downtime
|
||||
- **Blue-Green Deployment**: Use blue-green deployment for zero downtime
|
||||
- **Canary Releases**: Test new versions with a subset of users
|
||||
|
||||
### 2. Monitoring Best Practices
|
||||
|
||||
- **Comprehensive Monitoring**: Monitor all components of the system
|
||||
- **Proactive Alerting**: Set up alerts for potential issues
|
||||
- **Anomaly Detection**: Use machine learning for anomaly detection
|
||||
- **Log Aggregation**: Centralize logs for easier analysis
|
||||
- **Performance Baselines**: Establish performance baselines for comparison
|
||||
- **Dashboards**: Create comprehensive monitoring dashboards
|
||||
|
||||
### 3. Security Best Practices
|
||||
|
||||
- **Defense in Depth**: Implement multiple layers of security
|
||||
- **Principle of Least Privilege**: Grant minimum required permissions
|
||||
- **Regular Audits**: Conduct regular security audits
|
||||
- **Security Training**: Train developers on security best practices
|
||||
- **Incident Response Plan**: Have a plan for security incidents
|
||||
- **Compliance**: Ensure compliance with relevant regulations
|
||||
|
||||
### 4. Maintenance Best Practices
|
||||
|
||||
- **Regular Backups**: Schedule regular backups
|
||||
- **Backup Testing**: Test backup restoration regularly
|
||||
- **Documentation**: Keep comprehensive documentation
|
||||
- **Change Management**: Implement change management process
|
||||
- **Disaster Recovery Plan**: Have a disaster recovery plan
|
||||
- **Knowledge Transfer**: Ensure knowledge is shared among team members
|
||||
|
||||
## 🎉Conclusion
|
||||
|
||||
FastapiAdmin provides flexible deployment options to meet different production environment needs. Whether you choose Docker Compose for ease of deployment, manual deployment for full control, or cloud services for managed infrastructure, FastapiAdmin can be deployed reliably and securely.
|
||||
|
||||
By following the best practices outlined in this guide, you can ensure that your FastapiAdmin deployment is scalable, secure, and maintainable. Regular monitoring, backups, and security maintenance are essential for keeping your application running smoothly and securely.
|
||||
|
||||
For more detailed information about specific deployment methods or cloud providers, please refer to their official documentation.
|
||||
@@ -0,0 +1,129 @@
|
||||
# Examples
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Backend API Examples
|
||||
|
||||
#### User Authentication
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi_admin.models import User
|
||||
from fastapi_admin.depends import get_current_user
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/profile")
|
||||
async def get_profile(current_user: User = Depends(get_current_user)):
|
||||
return {"user": current_user}
|
||||
```
|
||||
|
||||
#### CRUD Operations
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi_admin.models import Role
|
||||
from fastapi_admin.depends import get_current_user
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from fastapi_admin.database import get_db
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/roles")
|
||||
async def get_roles(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
roles = await db.query(Role).all()
|
||||
return {"roles": roles}
|
||||
```
|
||||
|
||||
### Frontend Examples
|
||||
|
||||
#### Vue Component
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="user-profile">
|
||||
<h2>{{ user.name }}</h2>
|
||||
<p>{{ user.email }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const user = ref({})
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetch('/api/v1/profile')
|
||||
user.value = await response.json()
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## Advanced Examples
|
||||
|
||||
### Custom Dashboard
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<div class="stats">
|
||||
<div class="stat-card">
|
||||
<h3>Total Users</h3>
|
||||
<p>{{ userCount }}</p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<h3>Active Roles</h3>
|
||||
<p>{{ roleCount }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const userCount = ref(0)
|
||||
const roleCount = ref(0)
|
||||
|
||||
onMounted(async () => {
|
||||
// Fetch statistics
|
||||
const response = await fetch('/api/v1/stats')
|
||||
const data = await response.json()
|
||||
userCount.value = data.userCount
|
||||
roleCount.value = data.roleCount
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
backend:
|
||||
build: ./backend
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
db:
|
||||
image: mysql:8.0
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: fastapiadmin
|
||||
|
||||
redis:
|
||||
image: redis:7.0
|
||||
```
|
||||
@@ -0,0 +1,450 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Development Guidelines
|
||||
---
|
||||
# Development Guidelines
|
||||
|
||||
## 📚 Guidelines Overview
|
||||
|
||||
To ensure project code consistency, readability, and maintainability, the FastapiAdmin project has established the following development guidelines. All developers participating in the project should follow these guidelines.
|
||||
|
||||
## 🎨 Frontend Development Guidelines
|
||||
|
||||
### 1. Code Style
|
||||
|
||||
#### 1.1 TypeScript Guidelines
|
||||
|
||||
- Use TypeScript strict mode (`"strict": true`)
|
||||
- Add type annotations for all variables, functions, and interfaces
|
||||
- Avoid using `any` type unless the type is truly indeterminable
|
||||
- Use interfaces to define object types, not type aliases
|
||||
- Use enums to define constant sets
|
||||
- Use `type` to define union types and intersection types
|
||||
- Use `as const` assertions to ensure type safety
|
||||
- Use `readonly` modifiers to protect immutable data
|
||||
- Use `unknown` type to handle data of uncertain types
|
||||
|
||||
#### 1.2 Vue Guidelines
|
||||
|
||||
- Use Composition API
|
||||
- Use `<script setup lang="ts">` syntax
|
||||
- Use PascalCase for component naming
|
||||
- Use camelCase for variable and function naming
|
||||
- Use UPPER_SNAKE_CASE for constant naming
|
||||
- Use `ref()` to define reactive variables
|
||||
- Use `computed()` to define computed properties
|
||||
- Use `watch()` or `watchEffect()` to monitor changes
|
||||
- Use `onMounted()`, `onUnmounted()` and other lifecycle hooks
|
||||
- Use `defineProps()` to define component props with types
|
||||
- Use `defineEmits()` to define component events with types
|
||||
- Use `defineExpose()` to define exposed component properties and methods
|
||||
|
||||
#### 1.3 CSS Guidelines
|
||||
|
||||
- Use UnoCSS atomic CSS
|
||||
- Avoid using inline styles
|
||||
- Use BEM naming convention (if not using UnoCSS)
|
||||
- Use kebab-case for class names
|
||||
- Avoid using ID selectors
|
||||
- Use CSS variables for theme management
|
||||
- Avoid using `!important` modifier
|
||||
- Use flexbox layout to ensure cross-platform consistency
|
||||
- Use CSS Grid layout appropriately
|
||||
- Optimize CSS selector priority
|
||||
|
||||
### 2. Component Development Best Practices
|
||||
|
||||
- **Single Responsibility Principle**: Each component should be responsible for only one function
|
||||
- **Props Design**:
|
||||
- Use `required` and `default` to clearly specify props requirements
|
||||
- Add validation for complex props
|
||||
- Use `withDefaults()` to set default values for props
|
||||
- **Events Design**:
|
||||
- Use kebab-case for event naming
|
||||
- Event parameter types should be clear
|
||||
- Avoid passing too many parameters in events
|
||||
- **Slots Design**:
|
||||
- Use named slots to improve readability
|
||||
- Add default content for slots
|
||||
- Use scoped slots to pass data
|
||||
- **Styles Design**:
|
||||
- Use `scoped` styles to avoid conflicts
|
||||
- Use `:deep()` selectors appropriately
|
||||
- Avoid using global styles in components
|
||||
|
||||
### 3. State Management Best Practices
|
||||
|
||||
- **Modular Design**: Split stores by functional modules
|
||||
- **State Definition**:
|
||||
- Use `interface` to define state types
|
||||
- Initialize all states
|
||||
- Avoid using overly nested state structures
|
||||
- **Actions Design**:
|
||||
- Handle asynchronous operations
|
||||
- Use try/catch to catch errors
|
||||
- Use transactions when committing multiple mutations
|
||||
- **Getters Design**:
|
||||
- Cache calculation results
|
||||
- Avoid modifying state in getters
|
||||
- Use parameterized getters appropriately
|
||||
|
||||
### 4. API Call Best Practices
|
||||
|
||||
- **Modular Management**: Organize API interfaces by functional modules
|
||||
- **Request Encapsulation**:
|
||||
- Unified handling of request headers
|
||||
- Unified error handling
|
||||
- Unified loading state handling
|
||||
- **Response Handling**:
|
||||
- Type definitions for response data structures
|
||||
- Unified handling of response status codes
|
||||
- Appropriate handling of empty data and edge cases
|
||||
- **Request Optimization**:
|
||||
- Use debounce and throttle
|
||||
- Cache results of frequent requests
|
||||
- Use concurrent requests appropriately
|
||||
|
||||
### 5. Performance Optimization Recommendations
|
||||
|
||||
- **Code Splitting**: Use route lazy loading and component lazy loading
|
||||
- **Resource Optimization**:
|
||||
- Compress images and static resources
|
||||
- Use WebP format images
|
||||
- Use CDN appropriately
|
||||
- **Rendering Optimization**:
|
||||
- Use `v-memo` to cache calculation results
|
||||
- Use `v-if` and `v-show` appropriately
|
||||
- Avoid using complex expressions in templates
|
||||
- **Network Optimization**:
|
||||
- Use HTTP/2 or HTTP/3
|
||||
- Enable Gzip or Brotli compression
|
||||
- Set caching strategies appropriately
|
||||
|
||||
### 6. Testing Best Practices
|
||||
|
||||
- **Test Layering**: Unit tests, integration tests, end-to-end tests
|
||||
- **Test Coverage**:
|
||||
- 100% coverage for core functionality
|
||||
- 80%+ coverage for complex logic
|
||||
- 50%+ coverage for simple functionality
|
||||
- **Testing Tools**:
|
||||
- Use Vitest for unit testing
|
||||
- Use Playwright for end-to-end testing
|
||||
- Use Vue Test Utils for component testing
|
||||
|
||||
### 7. Code Review Points
|
||||
|
||||
- **Type Safety**: Check if TypeScript type definitions are correct
|
||||
- **Code Quality**: Check if code is concise and clear
|
||||
- **Performance Issues**: Check for performance bottlenecks
|
||||
- **Security Issues**: Check for security vulnerabilities
|
||||
- **Guideline Compliance**: Check if project development guidelines are followed
|
||||
|
||||
## 🐍 Backend Development Guidelines
|
||||
|
||||
### 1. Code Style
|
||||
|
||||
#### 1.1 Python Guidelines
|
||||
|
||||
- Follow PEP 8 code style
|
||||
- Use 4 spaces for indentation
|
||||
- Line length should not exceed 100 characters
|
||||
- Leave two blank lines between functions and classes
|
||||
- Leave one blank line between methods
|
||||
- Group import statements by standard library, third-party library, and local library
|
||||
|
||||
#### 1.2 FastAPI Guidelines
|
||||
|
||||
- Use FastAPI decorators to define routes
|
||||
- Use Pydantic models to define request and response data
|
||||
- Use dependency injection for authentication and authorization
|
||||
- Use path parameters and query parameters
|
||||
- Use HTTPException for error handling
|
||||
- Use Depends to inject dependencies
|
||||
|
||||
### 2. Directory Structure
|
||||
|
||||
```
|
||||
backend/app/
|
||||
├── api/ # API interfaces
|
||||
├── common/ # Common code
|
||||
├── config/ # Configuration management
|
||||
├── core/ # Core functionality
|
||||
├── plugin/ # Plugin system
|
||||
├── scripts/ # Script tools
|
||||
└── utils/ # Utility functions
|
||||
```
|
||||
|
||||
### 3. Plugin Development Guidelines
|
||||
|
||||
- Plugin directories should start with `module_`
|
||||
- Plugins should include files such as `controller.py`, `model.py`, `schema.py`, `service.py`, `crud.py`
|
||||
- Controllers should use `APIRouter` to define routes
|
||||
- Route prefixes should correspond to module names (module_xxx -> /xxx)
|
||||
- Controllers should use `OperationLogRoute` to record operation logs
|
||||
- Interfaces should use `AuthPermission` for permission control
|
||||
|
||||
### 4. Database Guidelines
|
||||
|
||||
- Use SQLAlchemy 2.0 ORM
|
||||
- Use Alembic for database migrations
|
||||
- Model classes should inherit from `Base`
|
||||
- Model classes should define `__tablename__` attribute
|
||||
- Field naming should use snake_case
|
||||
- Table names should use snake_case plural form
|
||||
- Foreign keys should be defined using `ForeignKey`
|
||||
- Relationships should be defined using `relationship`
|
||||
|
||||
### 5. Authentication and Authorization Guidelines
|
||||
|
||||
- Use JWT for authentication
|
||||
- Use RBAC model for permission management
|
||||
- Interfaces should add permission control decorators
|
||||
- Permission string format: `module:controller:action`
|
||||
- Permissions should be configured in role management
|
||||
|
||||
### 6. Error Handling Guidelines
|
||||
|
||||
- Use `HTTPException` for HTTP errors
|
||||
- Use custom exception handling for global errors
|
||||
- Error responses should have a unified format
|
||||
- Errors should be logged
|
||||
|
||||
### 7. Logging Guidelines
|
||||
|
||||
- Use Python standard library `logging` module
|
||||
- Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||
- Logs should include time, level, module, message, and other information
|
||||
- Key operations should be logged
|
||||
- Errors should be logged with detailed information
|
||||
|
||||
## 📦 FastApp Mobile Development Guidelines
|
||||
|
||||
### 1. Code Style
|
||||
|
||||
- Follow frontend development guidelines
|
||||
- Use TypeScript strict mode
|
||||
- Use Vue 3 Composition API
|
||||
- Use `<script setup lang="ts">` syntax
|
||||
- Use PascalCase for component naming
|
||||
- Use camelCase for variable and function naming
|
||||
|
||||
### 2. Directory Structure
|
||||
|
||||
```
|
||||
FastApp/src/
|
||||
├── api/ # API interfaces
|
||||
├── components/ # Components
|
||||
├── composables/ # Composable functions
|
||||
├── constants/ # Constant definitions
|
||||
├── enums/ # Enum definitions
|
||||
├── layouts/ # Layout components
|
||||
├── pages/ # Page files
|
||||
├── router/ # Router configuration
|
||||
├── static/ # Static resources
|
||||
├── store/ # State management
|
||||
├── styles/ # Style files
|
||||
├── types/ # TypeScript type definitions
|
||||
├── utils/ # Utility functions
|
||||
├── App.vue # Application root component
|
||||
└── main.ts # Application entry file
|
||||
```
|
||||
|
||||
### 3. Page Development Guidelines
|
||||
|
||||
- Page components should be placed in the `pages` directory
|
||||
- Page directories should use kebab-case
|
||||
- Page components should include `index.vue` file
|
||||
- Page components can include auxiliary files such as `data.ts`, `types.ts`
|
||||
- Page components should use lifecycle hooks such as `onLoad()`, `onShow()`
|
||||
- Page navigation should use APIs such as `uni.navigateTo()`, `uni.switchTab()`
|
||||
|
||||
### 4. API Call Guidelines
|
||||
|
||||
- Follow frontend API call guidelines
|
||||
- Use the encapsulated `request.ts` utility
|
||||
- API interfaces should be classified by module
|
||||
- API calls should handle error situations
|
||||
- API calls should display loading state
|
||||
|
||||
### 5. Cross-Platform Adaptation Guidelines
|
||||
|
||||
- Use conditional compilation to handle platform differences
|
||||
- Use `#ifdef`, `#ifndef`, `#endif` directives
|
||||
- Platform-specific APIs should add conditional compilation
|
||||
- Styles should consider differences between platforms
|
||||
- Layouts should use flexbox to ensure cross-platform consistency
|
||||
|
||||
## 🎯 Git Commit Guidelines
|
||||
|
||||
### 1. Branch Management
|
||||
|
||||
- `master`: Main branch, used for releasing production versions
|
||||
- `dev`: Development branch, used for integration development
|
||||
- `feature/xxx`: Feature branch, used for developing new features
|
||||
- `bugfix/xxx`: Fix branch, used for fixing bugs
|
||||
- `hotfix/xxx`: Hotfix branch, used for emergency fixes in production environment
|
||||
|
||||
### 2. Commit Message Guidelines
|
||||
|
||||
Commit messages should follow the following format:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
#### 2.1 Type
|
||||
|
||||
- `feat`: New feature
|
||||
- `fix`: Bug fix
|
||||
- `docs`: Documentation changes
|
||||
- `style`: Code style changes
|
||||
- `refactor`: Code refactoring
|
||||
- `test`: Test code changes
|
||||
- `chore`: Build tool or dependency changes
|
||||
- `revert`: Revert commit
|
||||
|
||||
#### 2.2 Scope
|
||||
|
||||
- Optional, used to specify the scope of changes
|
||||
- For example: `api`, `component`, `page`, `store`, etc.
|
||||
|
||||
#### 2.3 Subject
|
||||
|
||||
- Brief commit message, not exceeding 50 characters
|
||||
- Use imperative mood, starting with a verb
|
||||
- First letter lowercase
|
||||
- No period at the end
|
||||
|
||||
#### 2.4 Body
|
||||
|
||||
- Optional, detailed commit message
|
||||
- Each line not exceeding 72 characters
|
||||
- Explain why, not how
|
||||
|
||||
#### 2.5 Footer
|
||||
|
||||
- Optional, used to reference issues or bugs
|
||||
- For example: `Closes #123`, `Fixes #456`
|
||||
|
||||
### 3. Commit Examples
|
||||
|
||||
```
|
||||
feat(api): Add user login endpoint
|
||||
|
||||
- Implement user login functionality
|
||||
- Add JWT authentication
|
||||
- Handle login error cases
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
```
|
||||
fix(frontend): Fix homepage carousel display issue
|
||||
|
||||
- Fix carousel height calculation error
|
||||
- Optimize carousel transition animation
|
||||
|
||||
Fixes #456
|
||||
```
|
||||
|
||||
```
|
||||
docs: Update development documentation
|
||||
|
||||
- Add API documentation
|
||||
- Improve deployment guide
|
||||
```
|
||||
|
||||
### 4. Pull Request Guidelines
|
||||
|
||||
- Pull Requests should merge from feature branches to dev branch
|
||||
- Pull Request titles should be clear and semantic
|
||||
- Pull Request descriptions should detail the changes
|
||||
- Pull Requests should include related issue links
|
||||
- Pull Requests should pass all tests
|
||||
- Pull Requests should be reviewed by at least one reviewer
|
||||
|
||||
## 🔧 Toolchain Guidelines
|
||||
|
||||
### 1. Frontend Toolchain
|
||||
|
||||
- Use Vite as build tool
|
||||
- Use ESLint for code linting
|
||||
- Use Prettier for code formatting
|
||||
- Use Stylelint for style linting
|
||||
- Use Husky for Git hook management
|
||||
- Use Commitlint for commit message checking
|
||||
|
||||
### 2. Backend Toolchain
|
||||
|
||||
- Use Poetry or pip for dependency management
|
||||
- Use Pylint or Flake8 for code linting
|
||||
- Use Black for code formatting
|
||||
- Use MyPy for type checking
|
||||
- Use pytest for testing
|
||||
|
||||
## 💡 Development Process Guidelines
|
||||
|
||||
### 1. Requirements Analysis
|
||||
|
||||
- Clarify functional requirements
|
||||
- Analyze business logic
|
||||
- Determine technical solutions
|
||||
|
||||
### 2. Design Phase
|
||||
|
||||
- Design database table structure
|
||||
- Design API interfaces
|
||||
- Design frontend pages
|
||||
- Design component structure
|
||||
|
||||
### 3. Development Phase
|
||||
|
||||
- Create branches
|
||||
- Implement features
|
||||
- Write tests
|
||||
- Run tests
|
||||
|
||||
### 4. Testing Phase
|
||||
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
- End-to-end tests
|
||||
- Performance tests
|
||||
|
||||
### 5. Deployment Phase
|
||||
|
||||
- Build production version
|
||||
- Deploy to test environment
|
||||
- Perform regression testing
|
||||
- Deploy to production environment
|
||||
|
||||
### 6. Maintenance Phase
|
||||
|
||||
- Monitor system running status
|
||||
- Handle bugs and issues
|
||||
- Perform performance optimization
|
||||
- Perform feature iterations
|
||||
|
||||
## 📚 Reference Materials
|
||||
|
||||
- [TypeScript Official Documentation](https://www.typescriptlang.org/docs/)
|
||||
- [Vue Official Documentation](https://vuejs.org/docs/)
|
||||
- [FastAPI Official Documentation](https://fastapi.tiangolo.com/)
|
||||
- [SQLAlchemy Official Documentation](https://docs.sqlalchemy.org/)
|
||||
- [PEP 8 Style Guide](https://peps.python.org/pep-0008/)
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
- [ESLint Official Documentation](https://eslint.org/docs/)
|
||||
- [Prettier Official Documentation](https://prettier.io/docs/en/)
|
||||
|
||||
## 🤝 Contribution Guidelines
|
||||
|
||||
If you have any suggestions or improvements for the development guidelines, please submit an Issue or Pull Request. We will carefully consider every suggestion and continuously improve the development guidelines.
|
||||
|
||||
## 📄 License Agreement
|
||||
|
||||
This development guidelines document adopts the MIT License, consistent with the FastapiAdmin project.
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
|
||||
layout: home
|
||||
editLink: true
|
||||
lastUpdated: true
|
||||
|
||||
hero:
|
||||
name: "FastApiAdmin"
|
||||
text: "Modern, Open Source, Full-Stack Rapid Development Platform"
|
||||
tagline: Fastapi + Vue3 helps enterprises quickly build applications.
|
||||
image:
|
||||
src: /logo.png
|
||||
alt: FastApiAdmin
|
||||
style:
|
||||
borderRadius: 50%
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Quick Start
|
||||
link: /en/start/
|
||||
- theme: alt
|
||||
text: Online Demo
|
||||
link: https://service.fastapiadmin.com/web
|
||||
target: _blank
|
||||
- theme: alt
|
||||
text: Mini Program Demo
|
||||
link: https://service.fastapiadmin.com/app
|
||||
target: _blank
|
||||
|
||||
features:
|
||||
- icon: 🛠️
|
||||
title: Full-Stack Integration
|
||||
details: Frontend-backend separation architecture, integrating Python (FastAPI) + Vue3 + TypeScript for multi-platform unified development, providing a one-stop out-of-the-box experience.
|
||||
- icon: 🧱
|
||||
title: Modular Design
|
||||
details: System functions are highly decoupled, easy to extend and maintain, following development specifications and design patterns, supporting plug-in development.
|
||||
- icon: ⚡️
|
||||
title: High Performance
|
||||
details: Using FastAPI asynchronous framework + Redis cache to optimize interface response speed, improve system performance, and support high concurrency scenarios.
|
||||
- icon: 🔒
|
||||
title: Security Authentication
|
||||
details: Supports JWT OAuth2 authentication mechanism, RBAC model implements fine-grained permission control at the menu, button, and data levels to ensure system security.
|
||||
- icon: 🚀
|
||||
title: Quick Deployment
|
||||
details: Supports Docker/Docker Compose/Nginx one-click deployment, reduces operation and maintenance costs, and supports multi-environment configuration management.
|
||||
- icon: 📊
|
||||
title: Rich Built-in Modules
|
||||
details: Includes multiple core modules such as system management, monitoring management, and public management to meet enterprise-level application needs.
|
||||
- icon: 🎨
|
||||
title: Beautiful UI Design
|
||||
details: Built based on ElementPlus and Wot Design Uni, providing modern, responsive user interfaces.
|
||||
- icon: 📖
|
||||
title: Comprehensive Documentation
|
||||
details: Provides detailed Chinese development documentation and usage guides, reducing learning costs and accelerating project implementation.
|
||||
@@ -0,0 +1,278 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Project Overview
|
||||
---
|
||||
# Project Overview
|
||||
|
||||
## 📋FastApiAdmin Introduction
|
||||
|
||||
**FastApiAdmin** is a **completely open-source, highly modular, and technologically advanced modern rapid development platform** designed to help developers efficiently build high-quality enterprise-level backend systems. The project adopts a **frontend-backend separation architecture**, integrating the Python backend framework `FastAPI` and the mainstream frontend framework `Vue3` to achieve multi-end unified development, providing a one-stop out-of-the-box development experience.
|
||||
|
||||
### Core Values
|
||||
|
||||
- **Reduce Development Costs**: Out-of-the-box functional modules reduce repetitive development work
|
||||
- **Improve Development Efficiency**: Unified technology stack and development specifications accelerate project delivery
|
||||
- **Ensure System Quality**: Strict code quality control and testing processes
|
||||
- **Flexible Scalability**: Modular design supports business customization and function extension
|
||||
|
||||
### Technical Advantages
|
||||
|
||||
- **Backend**: Based on FastAPI asynchronous framework, excellent performance, automatically generates API documentation
|
||||
- **Frontend**: Based on Vue3 + TypeScript + ElementPlus, type-safe, good development experience
|
||||
- **Mobile**: Based on Uni App, supports multi-platform deployment
|
||||
- **Database**: Supports MySQL and MongoDB to meet different business scenario needs
|
||||
- **Cache**: Integrated Redis to improve system response speed
|
||||
- **Deployment**: Supports Docker containerized deployment, simplifying operation and maintenance work
|
||||
|
||||
## 🎯Application Scenarios
|
||||
|
||||
- **Enterprise Internal Management Systems**: Human resources, finance, OA and other systems
|
||||
- **Business Operation Platforms**: E-commerce, content management, customer management and other systems
|
||||
- **Data Analysis Platforms**: Data visualization, report statistics and other systems
|
||||
- **API Management Platforms**: Interface management, documentation management and other systems
|
||||
- **Multi-platform Applications**: Application scenarios that require both Web and mobile terminals
|
||||
|
||||
## 📦Project Structure Overview
|
||||
|
||||
The project has been split into three independent repositories for separate development and maintenance:
|
||||
|
||||
### 1. FastapiAdmin Main Project
|
||||
|
||||
```sh
|
||||
FastapiAdmin/
|
||||
├─ backend/ # Backend project
|
||||
│ ├─ app/ # Core application code
|
||||
│ │ ├─ api/ # API interfaces
|
||||
│ │ │ └─ v1/ # API version
|
||||
│ │ │ ├─ module_common/ # Common module
|
||||
│ │ │ ├─ module_monitor/ # Monitoring module
|
||||
│ │ │ └─ module_system/ # System module
|
||||
│ │ ├─ common/ # Common code
|
||||
│ │ ├─ config/ # Configuration management
|
||||
│ │ ├─ core/ # Core functionality
|
||||
│ │ ├─ plugin/ # Plugin system
|
||||
│ │ │ ├─ module_application/ # Application module
|
||||
│ │ │ ├─ module_example/ # Example module
|
||||
│ │ │ └─ module_generator/ # Code generation module
|
||||
│ │ ├─ scripts/ # Script tools
|
||||
│ │ └─ utils/ # Utility functions
|
||||
│ ├─ alembic/ # Database migration
|
||||
│ ├─ env/ # Environment configuration
|
||||
│ ├─ static/ # Static resources
|
||||
│ ├─ tests/ # Test code
|
||||
│ ├─ README.md # Backend documentation
|
||||
│ ├─ main.py # Backend entry
|
||||
│ └─ requirements.txt # Python dependencies
|
||||
├─ frontend/ # Frontend project
|
||||
│ ├─ src/ # Source code
|
||||
│ │ ├─ api/ # API interfaces
|
||||
│ │ ├─ assets/ # Resource files
|
||||
│ │ ├─ components/ # Components
|
||||
│ │ ├─ composables/ # Composables
|
||||
│ │ ├─ constants/ # Constants
|
||||
│ │ ├─ directives/ # Directives
|
||||
│ │ ├─ enums/ # Enums
|
||||
│ │ ├─ lang/ # Internationalization
|
||||
│ │ ├─ layouts/ # Layouts
|
||||
│ │ ├─ plugins/ # Plugins
|
||||
│ │ ├─ router/ # Router
|
||||
│ │ ├─ store/ # State management
|
||||
│ │ ├─ styles/ # Styles
|
||||
│ │ ├─ types/ # Type definitions
|
||||
│ │ ├─ utils/ # Utility functions
|
||||
│ │ └─ views/ # Pages
|
||||
│ ├─ public/ # Static resources
|
||||
│ ├─ package.json # Frontend dependencies
|
||||
│ └─ README.md # Frontend documentation
|
||||
├─ devops/ # DevOps project
|
||||
│ ├─ backend/ # Backend deployment configuration
|
||||
│ ├─ nginx/ # Nginx configuration
|
||||
│ └─ redis/ # Redis configuration
|
||||
├─ docker-compose.yaml # Deployment file
|
||||
├─ deploy.sh # Deployment script
|
||||
├─ LICENSE # License
|
||||
└─ README.md # Project documentation
|
||||
```
|
||||
|
||||
### 2. FastApp Mobile Application
|
||||
|
||||
```sh
|
||||
FastApp/
|
||||
├─ src/ # Source code directory
|
||||
│ ├─ api/ # API interfaces
|
||||
│ │ ├─ auth.ts # Authentication interfaces
|
||||
│ │ ├─ file.ts # File interfaces
|
||||
│ │ └─ user.ts # User interfaces
|
||||
│ ├─ components/ # Components
|
||||
│ │ ├─ cu-date-query/ # Date query component
|
||||
│ │ ├─ cu-picker/ # Picker component
|
||||
│ │ ├─ qiun-error/ # Error component
|
||||
│ │ └─ qiun-loading/ # Loading component
|
||||
│ ├─ composables/ # Composables
|
||||
│ │ ├─ useNavigationBar.ts # Navigation bar management
|
||||
│ │ ├─ useStomp.ts # WebSocket management
|
||||
│ │ └─ useTabbar.ts # Tabbar management
|
||||
│ ├─ constants/ # Constants
|
||||
│ │ ├─ index.ts # Constants definition
|
||||
│ │ └─ storage.constant.ts # Storage keys
|
||||
│ ├─ enums/ # Enums
|
||||
│ │ ├─ api-code.enum.ts # API error codes
|
||||
│ │ └─ api-header.enum.ts # API headers
|
||||
│ ├─ layouts/ # Layout components
|
||||
│ │ ├─ default.vue # Default layout
|
||||
│ │ └─ tabbar.vue # Tabbar layout
|
||||
│ ├─ pages/ # Page files
|
||||
│ │ ├─ index/ # Home page
|
||||
│ │ │ ├─ data.ts # Data definition
|
||||
│ │ │ ├─ index.vue # Home page component
|
||||
│ │ │ └─ types.ts # Type definitions
|
||||
│ │ ├─ login/ # Login page
|
||||
│ │ │ └─ index.vue # Login component
|
||||
│ │ ├─ mine/ # Personal center
|
||||
│ │ │ ├─ about/ # About page
|
||||
│ │ │ ├─ faq/ # FAQ page
|
||||
│ │ │ ├─ feedback/ # Feedback page
|
||||
│ │ │ ├─ profile/ # Profile page
|
||||
│ │ │ ├─ settings/ # Settings page
|
||||
│ │ │ └─ index.vue # Personal center component
|
||||
│ │ └─ work/ # Workbench
|
||||
│ │ ├─ data.ts # Data definition
|
||||
│ │ ├─ index.vue # Workbench component
|
||||
│ │ └─ types.ts # Type definitions
|
||||
│ ├─ router/ # Router configuration
|
||||
│ │ └─ index.ts # Router configuration file
|
||||
│ ├─ static/ # Static resources
|
||||
│ │ ├─ icons/ # Icons
|
||||
│ │ ├─ images/ # Images
|
||||
│ │ └─ logo.png # Logo
|
||||
│ ├─ store/ # State management
|
||||
│ │ ├─ modules/ # Modules
|
||||
│ │ │ ├─ theme.store.ts # Theme management
|
||||
│ │ │ └─ user.store.ts # User management
|
||||
│ │ └─ index.ts # State management configuration
|
||||
│ ├─ styles/ # Style files
|
||||
│ │ └─ index.scss # Global styles
|
||||
│ ├─ types/ # TypeScript definitions
|
||||
│ ├─ utils/ # Utility functions
|
||||
│ │ ├─ auth.ts # Authentication utility
|
||||
│ │ ├─ color.ts # Color utility
|
||||
│ │ ├─ index.ts # Utility functions
|
||||
│ │ ├─ request.ts # Request utility
|
||||
│ │ └─ storage.ts # Storage utility
|
||||
│ ├─ App.vue # Application root component
|
||||
│ ├─ main.ts # Application entry file
|
||||
│ ├─ manifest.json # Application configuration file
|
||||
│ ├─ pages.json # Page router configuration
|
||||
│ └─ theme.json # Theme configuration
|
||||
├─ public/ # Static resources
|
||||
├─ .env.development # Development environment configuration
|
||||
├─ .env.production # Production environment configuration
|
||||
├─ package.json # Project dependencies
|
||||
├─ pages.config.ts # Page configuration
|
||||
├─ tsconfig.json # TypeScript configuration
|
||||
├─ unocss.config.ts # UnoCSS configuration
|
||||
└─ vite.config.ts # Vite configuration
|
||||
```
|
||||
|
||||
### 3. FastDocs Official Documentation
|
||||
|
||||
```sh
|
||||
FastDocs/
|
||||
├─ docs/ # Documentation source
|
||||
│ ├─ development/ # Development documentation
|
||||
│ ├─ en/ # English documentation
|
||||
│ ├─ overview/ # Overview documentation
|
||||
│ ├─ quickstart/ # Quick start
|
||||
│ ├─ public/ # Static resources
|
||||
│ └─ index.md # Home page
|
||||
├─ .vitepress/ # VitePress configuration
|
||||
│ ├─ theme/ # Theme configuration
|
||||
│ └─ config.ts # Site configuration
|
||||
├─ package.json # Project dependencies
|
||||
└─ README.md # Project documentation
|
||||
```
|
||||
|
||||
## ✨Core Highlights
|
||||
|
||||
| Feature | Description |
|
||||
| ---- | ---- |
|
||||
| 🔭 Rapid Development | A completely open-source modern rapid development platform designed to help developers efficiently build high-quality enterprise-level backend systems. |
|
||||
| 🌐 Full-Stack Integration | Frontend-backend separation, integrating Python (FastAPI) + Vue3 multi-end development, supporting Web and mobile terminals. |
|
||||
| 🧱 Modular Design | System functions are highly decoupled, plugin-based architecture, supporting automatic route discovery and registration, easy to extend and maintain. |
|
||||
| ⚡️ High Performance | Using FastAPI asynchronous framework + Redis cache to optimize interface response speed. |
|
||||
| 🔒 Secure Authentication | Support for JWT OAuth2 authentication mechanism to ensure system security. |
|
||||
| 📊 Permission Management | RBAC model implements fine-grained permission control at the menu, button, and data levels. |
|
||||
| 🚀 Quick Deployment | Support for Docker/Docker Compose/Nginx one-click deployment. |
|
||||
| 📄 Developer-Friendly | Provide comprehensive Chinese documentation + Chinese interface + visual toolchain, reducing learning costs. |
|
||||
| 🧩 Quick Integration | Based on Vue3, Vite5, Pinia, ElementPlus and other mainstream frontend technology stacks, out-of-the-box. |
|
||||
| 📱 Mobile Support | FastApp mobile application developed based on UniApp, supporting multi-end operation (H5, WeChat Mini Program, Alipay Mini Program, App, etc.). |
|
||||
| 🤖 Agent Framework | Integrated agent framework, providing AI capabilities. |
|
||||
| 🎨 Theme Customization | Support for dark/light theme switching, providing personalized interface experience. |
|
||||
| 🌍 Internationalization Support | Built-in internationalization framework, supporting multi-language switching. |
|
||||
| 📈 Data Visualization | Integrated chart library, providing rich data visualization capabilities. |
|
||||
| 🛠️ Code Generation | Built-in code generation tool, improving development efficiency. |
|
||||
|
||||
## 🔧Technology Stack
|
||||
|
||||
| Category | Technology | Description |
|
||||
|---------|------------|-------------|
|
||||
| **Backend Framework** | FastAPI / Uvicorn / Pydantic 2.0 / Alembic | Modern, high-performance asynchronous framework with enforced type constraints and data migration |
|
||||
| **ORM** | SQLAlchemy 2.0 | Powerful ORM library |
|
||||
| **Scheduled Tasks** | APScheduler | Easily implement scheduled tasks |
|
||||
| **Authentication** | PyJWT | Implement JWT authentication |
|
||||
| **Frontend Framework** | Vue3 / Vite5 / Pinia / TypeScript | Rapidly develop Vue3 applications |
|
||||
| **Frontend Tools** | ESLint / Prettier / Stylelint | Code quality and style tools |
|
||||
| **Mobile Framework** | UniApp / Vue3 / TypeScript | Cross-platform mobile application development |
|
||||
| **UI Library** | ElementPlus (Web) / Wot Design Uni (Mobile) | Enterprise-level UI component library |
|
||||
| **CSS Framework** | UnoCSS / SCSS | Atomic CSS and preprocessor |
|
||||
| **Database** | MySQL / PostgreSQL / SQLite | Relational database support |
|
||||
| **Cache** | Redis | Powerful cache database |
|
||||
| **API Documentation** | Swagger / Redoc | Automatically generate API documentation |
|
||||
| **Deployment** | Docker / Nginx / Docker Compose | Rapid project deployment |
|
||||
| **Monitoring** | Built-in Server Monitoring / Cache Monitoring | System operation status monitoring |
|
||||
| **Internationalization** | i18n | Multi-language support |
|
||||
| **Data Visualization** | ECharts | Rich data visualization capabilities |
|
||||
|
||||
## ✨Built-in Modules
|
||||
|
||||
### FastapiAdmin Main Project Modules
|
||||
|
||||
| Module Name | Submodules | Description |
|
||||
|---------|------------|-------------|
|
||||
| **Dashboard** | Workbench, Analysis Page | System overview and data analysis |
|
||||
| **System Management** | User, Role, Menu, Department, Position, Dictionary, Configuration, Announcement | Core system management functions |
|
||||
| **Monitoring Management** | Online Users, Server Monitoring, Cache Monitoring | System operation status monitoring |
|
||||
| **Task Management** | Scheduled Tasks | Asynchronous task scheduling management |
|
||||
| **Log Management** | Operation Logs | User behavior auditing |
|
||||
| **Development Tools** | Code Generation, Form Builder, API Documentation | Tools to improve development efficiency |
|
||||
|
||||
### FastApp Mobile Application Modules
|
||||
|
||||
| Module Name | Submodules | Description |
|
||||
|---------|------------|-------------|
|
||||
| **Home** | Carousel, Quick Navigation, Announcements, Data Statistics | Mobile home page display |
|
||||
| **Workbench** | Business function entry, supports permission control | Mobile core function area |
|
||||
| **Personal Center** | Personal Information, Settings, FAQ, Feedback | User personal related functions |
|
||||
| **User Authentication** | Login, Registration, Password Reset | User identity verification |
|
||||
| **Data Statistics** | Real-time visitor count, page views and other data display | Business data visualization |
|
||||
|
||||
## 📞Contact Information
|
||||
|
||||
If you have any questions or suggestions about the project, please contact us through the following ways:
|
||||
|
||||
- **GitHub**: [fastapiadmin/FastapiAdmin](https://github.com/fastapiadmin/FastapiAdmin)
|
||||
- **Gitee**: [fastapiadmin/FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
- **Email**: 948080782@qq.com
|
||||
|
||||
## 🤝Contribution Guide
|
||||
|
||||
We welcome community contributions, including but not limited to:
|
||||
|
||||
- Submit bug reports and feature suggestions
|
||||
- Improve code quality and performance
|
||||
- Perfect documentation and examples
|
||||
- Develop new functional modules
|
||||
|
||||
## 📄License
|
||||
|
||||
This project adopts the MIT license. For details, see the [LICENSE](https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE) file.
|
||||
@@ -0,0 +1,955 @@
|
||||
---
|
||||
title: Sponsor FastApiAdmin
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* Global styles - increase page width */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const benefits = [
|
||||
{ icon: '🌐', title: 'Website Operations', desc: 'Cover domain and server costs' },
|
||||
{ icon: '🛠️', title: 'Development Tools', desc: 'Purchase professional dev tools' },
|
||||
{ icon: '💬', title: 'Tech Support', desc: 'Provide better technical support' },
|
||||
{ icon: '⚡', title: 'Continuous Dev', desc: 'Invest more energy in development' },
|
||||
{ icon: '✨', title: 'Code Optimization', desc: 'Continuously optimize code quality' },
|
||||
{ icon: '🚀', title: 'Feature R&D', desc: 'Develop more practical features' }
|
||||
]
|
||||
|
||||
const honorarySponsors = [
|
||||
{ name: '晨曦微光', avatar: '', amount: '$73.35', date: '2026-04' },
|
||||
{ name: 'Alex_Chen', avatar: '', amount: '$44.01', date: '2026-04' },
|
||||
{ name: '一叶知秋', avatar: '', amount: '$29.34', date: '2026-03' },
|
||||
{ name: 'coding小王子', avatar: '', amount: '$73.35', date: '2026-03' },
|
||||
{ name: 'Mr.Zhang', avatar: '', amount: '$14.67', date: '2026-03' },
|
||||
{ name: '墨染青衣', avatar: '', amount: '$29.34', date: '2026-02' },
|
||||
{ name: 'sky_walker', avatar: '', amount: '$44.01', date: '2026-02' },
|
||||
{ name: '浅笑_安然', avatar: '', amount: '$22.01', date: '2026-02' },
|
||||
{ name: 'Jason.Liu', avatar: '', amount: '$29.34', date: '2026-01' },
|
||||
{ name: '梦里花落', avatar: '', amount: '$14.67', date: '2026-01' },
|
||||
{ name: 'Leo_李', avatar: '', amount: '$73.35', date: '2026-01' },
|
||||
{ name: '岁月静好', avatar: '', amount: '$29.34', date: '2025-12' },
|
||||
{ name: 'code_monkey', avatar: '', amount: '$22.01', date: '2025-12' },
|
||||
{ name: '北城以北', avatar: '', amount: '$44.01', date: '2025-11' },
|
||||
{ name: 'Emma.Wang', avatar: '', amount: '$14.67', date: '2025-11' },
|
||||
{ name: '烟雨_江南', avatar: '', amount: '$29.34', date: '2025-11' },
|
||||
{ name: 'tech_lover88', avatar: '', amount: '$22.01', date: '2025-10' },
|
||||
{ name: '清风徐来', avatar: '', amount: '$44.01', date: '2025-10' },
|
||||
{ name: 'David.Zhou', avatar: '', amount: '$29.34', date: '2025-10' },
|
||||
{ name: 'python小白', avatar: '', amount: '$14.67', date: '2025-09' }
|
||||
]
|
||||
|
||||
const tiers = [
|
||||
{
|
||||
name: 'Exclusive Sponsor',
|
||||
icon: '👑',
|
||||
level: 'exclusive',
|
||||
price: 'Contact via WeChat/month',
|
||||
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
benefits: [
|
||||
'Exclusive Logo on homepage above the fold',
|
||||
'First carousel position on demo site',
|
||||
'Exclusive Logo at top of left sidebar on all pages',
|
||||
'Exclusive product launch via all groups + official account (monthly)'
|
||||
],
|
||||
requirements: 'Brand name + Official link + Logo (340px*160px) + Slogan'
|
||||
},
|
||||
{
|
||||
name: 'Platinum Sponsor',
|
||||
icon: '💎',
|
||||
level: 'platinum',
|
||||
price: 'Contact via WeChat/month',
|
||||
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
|
||||
benefits: [
|
||||
'Prominent Logo on homepage',
|
||||
'Prominent Logo on demo site homepage',
|
||||
'Prominent Logo at top of left sidebar',
|
||||
'Product promotion via all groups (monthly)'
|
||||
],
|
||||
requirements: 'Brand name + Official link + Logo (340px*160px)'
|
||||
},
|
||||
{
|
||||
name: 'Gold Sponsor',
|
||||
icon: '🥇',
|
||||
level: 'gold',
|
||||
price: 'Contact via WeChat/month',
|
||||
color: 'linear-gradient(135deg, #f6d365 0%, #fda085 100%)',
|
||||
benefits: [
|
||||
'Large Logo on homepage',
|
||||
'Large Logo in right sidebar on all pages',
|
||||
'Product promotion via latest 3 groups (monthly)'
|
||||
],
|
||||
requirements: 'Brand name + Official link + Logo (220px*70px)'
|
||||
},
|
||||
{
|
||||
name: 'Silver Sponsor',
|
||||
icon: '🥈',
|
||||
level: 'silver',
|
||||
price: 'Contact via WeChat/month',
|
||||
color: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
|
||||
benefits: [
|
||||
'Small Logo in right sidebar on all pages'
|
||||
],
|
||||
requirements: 'Brand name + Official link + Logo (110px*60px)'
|
||||
}
|
||||
]
|
||||
|
||||
const currentSponsors = {
|
||||
exclusive: [
|
||||
{
|
||||
name: 'CoderXSLee',
|
||||
logo: 'https://foruda.gitee.com/avatar/1725853866438762352/562111_coderxslee_1725853866.png!avatar200',
|
||||
website: 'https://www.gitee.com/coderxslee',
|
||||
description: '',
|
||||
amount: '$14.67'
|
||||
}
|
||||
],
|
||||
platinum: [
|
||||
// {
|
||||
// name: 'DevTools Pro',
|
||||
// logo: '',
|
||||
// website: 'https://www.devtools-pro.com',
|
||||
// description: 'Professional development tools and services',
|
||||
// amount: '$800'
|
||||
// },
|
||||
// {
|
||||
// name: 'Tech Academy',
|
||||
// logo: '',
|
||||
// website: 'https://www.tech-academy.com',
|
||||
// description: 'Online technical courses and training',
|
||||
// amount: '$800'
|
||||
// }
|
||||
],
|
||||
gold: [
|
||||
// {
|
||||
// name: 'Cloud Plus',
|
||||
// logo: '',
|
||||
// website: 'https://www.cloud-plus.com',
|
||||
// description: 'Enterprise cloud service solutions',
|
||||
// amount: '$500'
|
||||
// },
|
||||
// {
|
||||
// name: 'Code Light',
|
||||
// logo: '',
|
||||
// website: 'https://www.code-light.com',
|
||||
// description: 'Developer community and tech blog',
|
||||
// amount: '$500'
|
||||
// },
|
||||
// {
|
||||
// name: 'Smart IDE',
|
||||
// logo: '',
|
||||
// website: 'https://www.smart-ide.com',
|
||||
// description: 'Next-gen intelligent development environment',
|
||||
// amount: '$500'
|
||||
// }
|
||||
],
|
||||
silver: [
|
||||
// {
|
||||
// name: 'Keyboard Master',
|
||||
// logo: '',
|
||||
// website: 'https://www.keyboard-master.com',
|
||||
// description: 'Professional mechanical keyboard brand',
|
||||
// amount: '$150'
|
||||
// },
|
||||
// {
|
||||
// name: 'Monitor Pro',
|
||||
// logo: '',
|
||||
// website: 'https://www.monitor-pro.com',
|
||||
// description: 'Monitors designed for programmers',
|
||||
// amount: '$150'
|
||||
// },
|
||||
// {
|
||||
// name: 'Coffee Coder',
|
||||
// logo: '',
|
||||
// website: 'https://www.coffee-coder.com',
|
||||
// description: 'Premium coffee for programmers',
|
||||
// amount: '$150'
|
||||
// },
|
||||
// {
|
||||
// name: 'Tech Books',
|
||||
// logo: '',
|
||||
// website: 'https://www.tech-books.com',
|
||||
// description: 'Technical books and e-book platform',
|
||||
// amount: '$150'
|
||||
// }
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||
animation: pulse 15s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||||
50% { transform: scale(1.1); opacity: 0.8; }
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 1rem 2.5rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
margin: 4rem 0 2rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.benefit-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.benefit-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.benefit-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.benefit-desc {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.tip-box {
|
||||
background: linear-gradient(135deg, rgba(255, 193, 7, 0.1) 0%, rgba(255, 152, 0, 0.1) 100%);
|
||||
border-left: 4px solid #ffc107;
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.tip-box strong {
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.tiers-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.tier-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 16px;
|
||||
padding: 0;
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tier-card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 20px 50px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
/* Special effects for high-tier sponsors */
|
||||
.tier-card:nth-child(1),
|
||||
.tier-card:nth-child(2) {
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
.tier-card:nth-child(1) {
|
||||
border-color: rgba(102, 126, 234, 0.5);
|
||||
box-shadow: 0 8px 30px rgba(102, 126, 234, 0.15);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(2) {
|
||||
border-color: rgba(245, 87, 108, 0.5);
|
||||
box-shadow: 0 8px 30px rgba(245, 87, 108, 0.15);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(1):hover {
|
||||
box-shadow: 0 20px 50px rgba(102, 126, 234, 0.4);
|
||||
border-color: rgba(102, 126, 234, 0.8);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(2):hover {
|
||||
box-shadow: 0 20px 50px rgba(245, 87, 108, 0.4);
|
||||
border-color: rgba(245, 87, 108, 0.8);
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
padding: 1.5rem;
|
||||
color: white;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Silver sponsor uses dark text */
|
||||
.tier-card:nth-child(4) .tier-header {
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.tier-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.8rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.tier-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.tier-benefits {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 1.2rem 0;
|
||||
}
|
||||
|
||||
.tier-benefits li {
|
||||
padding: 0.35rem 0;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.4rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.3;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.tier-benefits li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.tier-benefits li::before {
|
||||
content: '✓';
|
||||
color: #10b981;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.tier-requirements {
|
||||
background: rgba(102, 126, 234, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 0.8rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 1.2rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tier-requirements strong {
|
||||
color: var(--vp-c-text-1);
|
||||
display: block;
|
||||
margin-bottom: 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.tier-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.8rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.tier-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.guidelines-section {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
.guidelines-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.guidelines-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.guidelines-list li {
|
||||
padding: 0.4rem 0;
|
||||
padding-left: 1.2rem;
|
||||
position: relative;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.guidelines-list li::before {
|
||||
content: '•';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0.4rem;
|
||||
color: #667eea;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.example-box {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.sponsors-section {
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
.sponsor-tier {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.sponsor-tier-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.empty-sponsors {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.sponsors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.sponsor-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sponsor-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.sponsor-logo {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto 1rem;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, rgba(189, 52, 254, 0.5) 30%, rgba(65, 209, 255, 0.5));
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.sponsor-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.sponsor-name {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sponsor-desc {
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.4;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.sponsor-amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem 3rem 3rem 3rem;
|
||||
text-align: center;
|
||||
margin: 3rem 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1.5rem 0;
|
||||
padding: 0 0 1.5rem 0;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
border-top: none;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.contact-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.contact-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contact-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.contact-link {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.contact-link:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.honorary-sponsors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.honorary-sponsor-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem 1rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.honorary-sponsor-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.honorary-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 0 auto 0.8rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, rgba(189, 52, 254, 0.5) 30%, rgba(65, 209, 255, 0.5));
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.honorary-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.honorary-name {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.honorary-amount {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.honorary-date {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.tiers-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="hero-section">
|
||||
<h1 class="hero-title">💖 Sponsor FastApiAdmin</h1>
|
||||
<p class="hero-subtitle">
|
||||
Thank you for considering supporting the FastApiAdmin open-source project!<br>
|
||||
FastApiAdmin is licensed under the MIT open-source license, allowing free commercial use.<br>
|
||||
Since the project's release, we have been committed to continuous iteration and optimization with great passion.
|
||||
</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="#sponsorship-tiers" class="btn btn-primary">💎 View Tiers</a>
|
||||
<a href="https://service.fastapiadmin.com/en/about/#%F0%9F%8E%A8-about-us" target="_blank" class="btn btn-secondary">📞 Contact Us</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">🎯 Your Support Will Help Us</h2>
|
||||
|
||||
<div class="benefits-grid">
|
||||
<div v-for="benefit in benefits" :key="benefit.title" class="benefit-card">
|
||||
<div class="benefit-icon">{{ benefit.icon }}</div>
|
||||
<div class="benefit-title">{{ benefit.title }}</div>
|
||||
<div class="benefit-desc">{{ benefit.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 id="sponsorship-tiers" class="section-title">💎 Sponsorship Tiers and Benefits</h2>
|
||||
|
||||
<div class="tip-box">
|
||||
<strong>💡 Note:</strong> The conversion effectiveness of sponsorship displays may be affected by various factors such as market environment and audience characteristics. We cannot guarantee specific conversion results.
|
||||
</div>
|
||||
|
||||
<div class="tiers-grid">
|
||||
<div v-for="tier in tiers" :key="tier.level" class="tier-card">
|
||||
<div class="tier-header" :style="{ background: tier.color }">
|
||||
<span class="tier-icon">{{ tier.icon }}</span>
|
||||
<div class="tier-name">{{ tier.name }}</div>
|
||||
<div class="tier-price">{{ tier.price }}</div>
|
||||
</div>
|
||||
<div class="tier-body">
|
||||
<ul class="tier-benefits">
|
||||
<li v-for="(benefit, index) in tier.benefits" :key="index">{{ benefit }}</li>
|
||||
</ul>
|
||||
<div class="tier-requirements">
|
||||
<strong>Required Materials:</strong>
|
||||
{{ tier.requirements }}
|
||||
</div>
|
||||
<a href="#contact-us" class="tier-button">Sponsor Now</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="guidelines-section">
|
||||
<div class="guidelines-title">📋 Content Guidelines</div>
|
||||
<ul class="guidelines-list">
|
||||
<li>We recommend promoting products or services related to developers, such as low-code platforms, technical courses, development tools, cloud services, personal blogs, and physical products like keyboards, monitors, headphones, etc.</li>
|
||||
<li>Products with low relevance to the developer community should be considered carefully.</li>
|
||||
<li>We refuse to promote products that violate laws and regulations, involve gray industries, as well as IP proxies, internet access tools, etc.</li>
|
||||
<li>To avoid excessive disturbance to group members, promotions in communication groups should not exceed twice per day, with excess portions deferred to the next day.</li>
|
||||
</ul>
|
||||
|
||||
<div class="guidelines-title" style="margin-top: 2rem;">📢 Group Message Example</div>
|
||||
<div class="example-box">Thank you xxx for the special sponsorship of the FastApiAdmin open-source project! Here is their product information for those interested:
|
||||
【Product Name】
|
||||
【Official Link】https://xxx.com</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">🌟 Current Sponsors</h2>
|
||||
|
||||
<div class="sponsors-section">
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">👑 Exclusive Sponsor</div>
|
||||
<div v-if="currentSponsors.exclusive.length === 0" class="empty-sponsors">Currently vacant, looking forward to your participation</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.exclusive" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/month</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">💎 Platinum Sponsor</div>
|
||||
<div v-if="currentSponsors.platinum.length === 0" class="empty-sponsors">Currently vacant, looking forward to your participation</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.platinum" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/month</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">🥇 Gold Sponsor</div>
|
||||
<div v-if="currentSponsors.gold.length === 0" class="empty-sponsors">Currently vacant, looking forward to your participation</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.gold" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/month</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">🥈 Silver Sponsor</div>
|
||||
<div v-if="currentSponsors.silver.length === 0" class="empty-sponsors">Currently vacant, looking forward to your participation</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.silver" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/month</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">☕ Honorary Sponsorship</h2>
|
||||
<p class="cta-text">
|
||||
You can sponsor through the appreciation codes of maintenance team members on the <a href="/en/about/" style="color: #667eea; text-decoration: none;">About Us</a> page.<br>
|
||||
Buy a cup of coffee for the FastApiAdmin maintenance team members!
|
||||
</p>
|
||||
|
||||
<div class="honorary-sponsors-grid">
|
||||
<div v-for="sponsor in honorarySponsors" :key="sponsor.name + sponsor.date" class="honorary-sponsor-card">
|
||||
<div class="honorary-avatar">
|
||||
<img v-if="sponsor.avatar" :src="sponsor.avatar" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="honorary-name">{{ sponsor.name }}</div>
|
||||
<div class="honorary-amount">{{ sponsor.amount }}</div>
|
||||
<div class="honorary-date">{{ sponsor.date }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cta-section" style="margin-top: 3rem;">
|
||||
<h2 class="cta-title">🎉 Looking Forward to Working with You</h2>
|
||||
<p class="cta-text">
|
||||
If you are interested in sponsoring the FastApiAdmin project or want to learn more,<br>
|
||||
please feel free to contact us through the above methods. We will be happy to serve you!
|
||||
</p>
|
||||
<a href="https://service.fastapiadmin.com/en/about/#%F0%9F%8E%A8-about-us" target="_blank" class="btn btn-primary">Contact Us Now</a>
|
||||
</div>
|
||||
@@ -0,0 +1,400 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Quick Start
|
||||
---
|
||||
# Quick Start
|
||||
|
||||
## 🍪Demo Environment
|
||||
|
||||
- Official Website: <https://service.fastapiadmin.com>
|
||||
- Demo Address: <https://service.fastapiadmin.com/web>
|
||||
- Mini Program Address: <https://service.fastapiadmin.com/app>
|
||||
- Admin Account: `admin` Password: `123456`
|
||||
- Demo Account: `demo` Password: `123456`
|
||||
|
||||
## 👷Installation and Usage
|
||||
|
||||
### Version Description
|
||||
|
||||
| Type | Technology Stack | Version |
|
||||
|------|-----------------|---------|
|
||||
| Backend | Python | >=3.10 |
|
||||
| Backend | FastAPI | 0.109 |
|
||||
| Frontend | Node.js | >= 20.0 (recommended to use the latest version) |
|
||||
| Frontend | npm | 16.14 |
|
||||
| Frontend | Vue3 | 3.3 |
|
||||
| Web UI | ElementPlus | 2.10.4 |
|
||||
| Mobile | Uni App | 3.0.0 |
|
||||
| App UI | Wot Design Uni | 1.9.1 |
|
||||
| Database | MySQL | 8.0 (recommended to use the latest version) |
|
||||
| Middleware | Redis | 7.0 (recommended to use the latest version) |
|
||||
|
||||
### Environment Preparation
|
||||
|
||||
#### 1. Install Python
|
||||
|
||||
```sh
|
||||
# macOS
|
||||
brew install python@3.10
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install python3.10 python3.10-venv python3.10-dev
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo dnf install python3.10 python3.10-venv python3.10-devel
|
||||
```
|
||||
|
||||
#### 2. Install Node.js
|
||||
|
||||
```sh
|
||||
# Using nvm installation (recommended)
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
||||
nvm install 20
|
||||
nvm use 20
|
||||
|
||||
# Or using package manager
|
||||
# macOS
|
||||
brew install node@20
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install nodejs npm
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo dnf install nodejs npm
|
||||
```
|
||||
|
||||
#### 3. Install Database and Cache
|
||||
|
||||
```sh
|
||||
# Install MySQL
|
||||
# macOS
|
||||
brew install mysql
|
||||
brew services start mysql
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install mysql-server
|
||||
sudo systemctl start mysql
|
||||
|
||||
# Install Redis
|
||||
# macOS
|
||||
brew install redis
|
||||
brew services start redis
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt install redis-server
|
||||
sudo systemctl start redis
|
||||
```
|
||||
|
||||
### Get Code
|
||||
|
||||
```sh
|
||||
# Clone code to local
|
||||
# FastapiAdmin main project
|
||||
git clone https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
# FastApp mobile
|
||||
git clone https://github.com/fastapiadmin/FastApp.git
|
||||
# FastDocs official documentation
|
||||
git clone https://github.com/fastapiadmin/FastDocs.git
|
||||
```
|
||||
|
||||
### Local Backend Startup (FastapiAdmin Main Project)
|
||||
|
||||
#### 1. Configure Environment Variables
|
||||
|
||||
```sh
|
||||
# Enter backend project directory
|
||||
cd FastapiAdmin/backend
|
||||
|
||||
# Copy environment configuration file
|
||||
cp env/.env.dev.example env/.env.dev
|
||||
|
||||
# Edit environment configuration file (modify according to actual situation)
|
||||
# Main configuration items: database connection, Redis connection, JWT secret key, etc.
|
||||
```
|
||||
|
||||
#### 2. Install Dependencies
|
||||
|
||||
```sh
|
||||
# Create virtual environment (optional but recommended)
|
||||
python3 -m venv .venv
|
||||
|
||||
# Activate virtual environment
|
||||
# macOS/Linux
|
||||
source .venv/bin/activate
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 3. Database Initialization
|
||||
|
||||
```sh
|
||||
# Generate migration files
|
||||
python main.py revision "Initial migration" --env=dev
|
||||
|
||||
# Apply migration
|
||||
python main.py upgrade --env=dev
|
||||
|
||||
# Initialize system data
|
||||
python main.py init
|
||||
```
|
||||
|
||||
#### 4. Start Backend Service
|
||||
|
||||
```sh
|
||||
# Development environment startup
|
||||
python main.py run --env=dev
|
||||
|
||||
# Or use default environment (dev)
|
||||
python main.py run
|
||||
|
||||
# Production environment startup
|
||||
python main.py run --env=prod
|
||||
```
|
||||
|
||||
### Local Frontend Startup (FastapiAdmin Main Project)
|
||||
|
||||
#### 1. Configure Environment Variables
|
||||
|
||||
```sh
|
||||
# Enter frontend project directory
|
||||
cd FastapiAdmin/frontend
|
||||
|
||||
# Copy environment configuration file
|
||||
cp .env.development.example .env.development
|
||||
|
||||
# Edit environment configuration file (modify according to actual situation)
|
||||
# Main configuration items: API base URL, etc.
|
||||
```
|
||||
|
||||
#### 2. Install Dependencies
|
||||
|
||||
```sh
|
||||
# Install pnpm (if not installed)
|
||||
npm install -g pnpm
|
||||
|
||||
# Install frontend dependencies
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### 3. Start Frontend Service
|
||||
|
||||
```sh
|
||||
# Development environment startup
|
||||
pnpm run dev
|
||||
|
||||
# Build frontend, generate `dist` directory
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
### Local Mini Program H5 Startup (FastApp Mobile)
|
||||
|
||||
#### 1. Configure Environment Variables
|
||||
|
||||
```sh
|
||||
# Enter mobile project directory
|
||||
cd FastApp
|
||||
|
||||
# Copy environment configuration file
|
||||
cp .env.development .env.development
|
||||
|
||||
# Edit environment configuration file (modify according to actual situation)
|
||||
# Main configuration items: API base URL, etc.
|
||||
```
|
||||
|
||||
#### 2. Install Dependencies
|
||||
|
||||
```sh
|
||||
# Install frontend dependencies
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### 3. Start H5 Service
|
||||
|
||||
```sh
|
||||
# Start H5 development service
|
||||
pnpm run dev:h5
|
||||
|
||||
# Build H5 version, generate `dist/build/h5` directory
|
||||
pnpm run build:h5
|
||||
|
||||
# Start other platforms (such as WeChat Mini Program)
|
||||
pnpm run dev:mp-weixin
|
||||
```
|
||||
|
||||
### Local Project Official Website Startup (FastDocs Official Documentation)
|
||||
|
||||
```sh
|
||||
# Enter FastDocs official documentation directory
|
||||
cd FastDocs
|
||||
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Run documentation project
|
||||
pnpm run docs:dev
|
||||
|
||||
# Build documentation project, generate `dist` directory
|
||||
pnpm run docs:build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Local Access Addresses
|
||||
|
||||
- FastDocs Documentation Address: <http://127.0.0.1:5180>
|
||||
- FastapiAdmin Frontend Address: <http://127.0.0.1:5173>
|
||||
- FastAPI Interface Documentation: <http://127.0.0.1:8001/api/v1/docs>
|
||||
- FastApp H5 Address: <http://127.0.0.1:5174>
|
||||
|
||||
### Default Account Password
|
||||
|
||||
- Admin Account: `admin` Password: `123456`
|
||||
- Demo Account: `demo` Password: `123456`
|
||||
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
### 1. Preparation
|
||||
|
||||
- Server needs to install Docker and Docker Compose
|
||||
- Ensure server ports 80 (Nginx) and 8001 (backend) are available
|
||||
|
||||
### 2. Deployment Steps
|
||||
|
||||
```sh
|
||||
# Enter FastapiAdmin main project directory
|
||||
cd FastapiAdmin
|
||||
|
||||
# Copy environment configuration files
|
||||
cp backend/env/.env.prod.example backend/env/.env.prod
|
||||
cp frontend/.env.production.example frontend/.env.production
|
||||
|
||||
# Edit environment configuration files (modify according to actual server situation)
|
||||
# Main configuration items: database connection, Redis connection, JWT secret key, API base URL, etc.
|
||||
|
||||
# Give script execution permission
|
||||
chmod +x start.sh
|
||||
|
||||
# Execute deployment script
|
||||
./start.sh
|
||||
|
||||
# Check deployment status
|
||||
docker compose ps
|
||||
|
||||
# View logs
|
||||
docker logs -f fastapiadmin-backend
|
||||
```
|
||||
|
||||
### 3. Deployment File Description
|
||||
|
||||
| Configuration File | Description | Path |
|
||||
|-------------------|-------------|------|
|
||||
| Backend environment configuration | Production environment database, Redis and other configurations | `FastapiAdmin/backend/env/.env.prod` |
|
||||
| Frontend environment configuration | Production environment API address and other configurations | `FastapiAdmin/frontend/.env.production` |
|
||||
| Docker configuration | Container orchestration configuration | `FastapiAdmin/docker-compose.yaml` |
|
||||
| Nginx configuration | Reverse proxy configuration | `FastapiAdmin/devops/nginx/nginx.conf` |
|
||||
|
||||
### 4. Common Docker Commands
|
||||
|
||||
```sh
|
||||
# View images
|
||||
docker images
|
||||
|
||||
# View containers
|
||||
docker compose ps
|
||||
|
||||
# Stop service
|
||||
docker compose down
|
||||
|
||||
# Restart service
|
||||
docker compose up -d
|
||||
|
||||
# View container logs
|
||||
docker logs -f <container name>
|
||||
|
||||
# Enter container
|
||||
docker exec -it <container name> bash
|
||||
```
|
||||
|
||||
## 🔧Module Display
|
||||
|
||||
### Web End
|
||||
|
||||
| Module Name <div style="width:60px"/> | Screenshot |
|
||||
|-------------|------------|
|
||||
| Dashboard |  |
|
||||
| Code Generation |  |
|
||||
| Intelligent Assistant |  |
|
||||
|
||||
### Mobile End
|
||||
|
||||
| Login <div style="width:60px"/> | Home <div style="width:60px"/> | Profile <div style="width:60px"/> |
|
||||
|----------|----------|----------|
|
||||
|  |  |  |
|
||||
|
||||
## 🚀Secondary Development Tutorial
|
||||
|
||||
### Backend Part (FastapiAdmin Main Project)
|
||||
|
||||
1. **Write entity class layer**: Create example ORM model in `FastapiAdmin/backend/app/api/v1/models/demo/example_model.py` (corresponding to entity class layer in Spring Boot)
|
||||
2. **Write data model layer**: Create example data model in `FastapiAdmin/backend/app/api/v1/schemas/demo/example_schema.py` (corresponding to DTO layer in Spring Boot)
|
||||
3. **Write query parameter model layer**: Create example query parameter model in `FastapiAdmin/backend/app/api/v1/params/demo/example_param.py` (corresponding to DTO layer in Spring Boot)
|
||||
4. **Write persistence layer**: Create example data layer in `FastapiAdmin/backend/app/api/v1/cruds/demo/example_crud.py` (corresponding to Mapper or DAO layer in Spring Boot)
|
||||
5. **Write business layer**: Create example data layer in `FastapiAdmin/backend/app/api/v1/services/demo/example_service.py` (corresponding to Service layer in Spring Boot)
|
||||
6. **Write interface layer**: Create example data layer in `FastapiAdmin/backend/app/api/v1/controllers/demo/example_controller.py` (corresponding to Controller layer in Spring Boot)
|
||||
7. **Register backend route**: Register example route in `FastapiAdmin/backend/app/api/v1/urls/demo/example_url.py`
|
||||
8. **Register route to FastAPI service**: Register route in `FastapiAdmin/backend/plugin/init_app.py`
|
||||
9. **Add demo module to system initialization script**: Add in `FastapiAdmin/backend/app/scripts/initialize.py` (if needed, you can configure demo's menu permissions in `FastapiAdmin/backend/app/scripts/data/system_menu.json` and `FastapiAdmin/backend/app/scripts/data/system_role_menus.json` or add from frontend page menu)
|
||||
10. **Add demo module to database migration script**: Add in `FastapiAdmin/backend/app/alembic/env.py`
|
||||
|
||||
### Frontend Part (FastapiAdmin Main Project)
|
||||
|
||||
1. **Frontend access backend interface address**: Configure in `FastapiAdmin/frontend/src/api/demo/example.ts`
|
||||
2. **Write frontend page**: Write in `FastapiAdmin/frontend/src/views/demo/example/index.vue`
|
||||
|
||||
### Mobile Part (FastApp Mobile)
|
||||
|
||||
1. **Mobile access backend interface address**: Write in `FastApp/src/api`
|
||||
2. **Write mobile page**: Write in `FastApp/src/pages`
|
||||
|
||||
## 💡Common Problems and Solutions
|
||||
|
||||
### 1. Backend Startup Failure
|
||||
|
||||
**Problem**: Database connection failure
|
||||
**Solution**: Check if the database connection information in the environment configuration file is correct, ensure the database service is running, and the username and password are correct.
|
||||
|
||||
**Problem**: Redis connection failure
|
||||
**Solution**: Check if the Redis connection information in the environment configuration file is correct, ensure the Redis service is running.
|
||||
|
||||
**Problem**: Dependency installation failure
|
||||
**Solution**: Ensure the Python version is correct (>=3.10), you can try to reinstall dependencies using a virtual environment.
|
||||
|
||||
### 2. Frontend Startup Failure
|
||||
|
||||
**Problem**: Dependency installation failure
|
||||
**Solution**: Ensure the Node.js version is correct (>=20.0), you can try to clear the cache and reinstall: `pnpm cache clean && pnpm install`.
|
||||
|
||||
**Problem**: API request failure
|
||||
**Solution**: Check if the API base URL in the frontend environment configuration file is correct, ensure the backend service is running.
|
||||
|
||||
### 3. Deployment Problems
|
||||
|
||||
**Problem**: Docker deployment failure
|
||||
**Solution**: Ensure the server has installed Docker and Docker Compose, check if ports are occupied, view container logs to understand specific error information.
|
||||
|
||||
**Problem**: Nginx configuration error
|
||||
**Solution**: Check if the reverse proxy settings in the Nginx configuration file are correct, ensure the backend service address is configured correctly.
|
||||
|
||||
### 4. Other Problems
|
||||
|
||||
**Problem**: System initialization failure
|
||||
**Solution**: Ensure the database has been correctly initialized, and migrations have been applied, you can try to re-execute the initialization command: `python main.py init`.
|
||||
|
||||
**Problem**: Insufficient permissions
|
||||
**Solution**: Check user role permission settings, ensure the current user has sufficient permissions to access the required functions.
|
||||
@@ -0,0 +1,526 @@
|
||||
---
|
||||
title: All Users
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* 全局样式 - 增加页面宽度到 1600px,以便在宽屏下显示 4 列公司卡片 */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const allUsers = ref([
|
||||
{
|
||||
name: 'Shenzhen Changhong Technology Co., Ltd.',
|
||||
location: 'Shenzhen · Pingshan',
|
||||
region: 'Guangdong',
|
||||
website: 'https://cn.sz-changhong.com/',
|
||||
websiteEn: 'https://www.sz-changhong.com/',
|
||||
logo: '',
|
||||
registrant: 'Yang Xiangxiang',
|
||||
registrantUrl: 'https://gitee.com/xiao-lei',
|
||||
date: '2026-04-19',
|
||||
description: 'Enterprise management system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Beijing Yunxin XX Software Technology Co., Ltd.',
|
||||
location: 'Shaanxi · Xi\'an',
|
||||
region: 'Shaanxi',
|
||||
website: '',
|
||||
logo: '',
|
||||
registrant: 'Li Hao',
|
||||
registrantUrl: 'https://gitee.com/aiyun_lh',
|
||||
date: '2026-04-19',
|
||||
description: 'Unit manufacturing execution system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Shanghai Wisdom Technology Co., Ltd.',
|
||||
location: 'Shanghai · Pudong',
|
||||
region: 'Shanghai',
|
||||
website: 'https://www.sh-wisdom.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: 'Zhang Wei',
|
||||
registrantUrl: 'https://gitee.com/zhangwei',
|
||||
date: '2026-04-18',
|
||||
description: 'Intelligent logistics management platform built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Hangzhou Cloud Network Technology Co., Ltd.',
|
||||
location: 'Zhejiang · Hangzhou',
|
||||
region: 'Zhejiang',
|
||||
website: 'https://www.hz-cloud.com/',
|
||||
websiteEn: 'https://en.hz-cloud.com/',
|
||||
logo: '',
|
||||
registrant: 'Wang Fang',
|
||||
registrantUrl: 'https://gitee.com/wangfang',
|
||||
date: '2026-04-17',
|
||||
description: 'Cloud data analysis system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Chengdu Shudao Technology Co., Ltd.',
|
||||
location: 'Sichuan · Chengdu',
|
||||
region: 'Sichuan',
|
||||
website: '',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: 'Liu Qiang',
|
||||
registrantUrl: 'https://gitee.com/liuqiang',
|
||||
date: '2026-04-16',
|
||||
description: 'E-commerce operation management system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Guangzhou Southern Data Technology Co., Ltd.',
|
||||
location: 'Guangdong · Guangzhou',
|
||||
region: 'Guangdong',
|
||||
website: 'https://www.gz-data.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: 'Chen Ming',
|
||||
registrantUrl: 'https://gitee.com/chenming',
|
||||
date: '2026-04-15',
|
||||
description: 'Big data visualization platform built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Nanjing Zijin Software Development Co., Ltd.',
|
||||
location: 'Jiangsu · Nanjing',
|
||||
region: 'Jiangsu',
|
||||
website: 'https://www.nj-zijin.com/',
|
||||
websiteEn: 'https://en.nj-zijin.com/',
|
||||
logo: '',
|
||||
registrant: 'Zhao Li',
|
||||
registrantUrl: 'https://gitee.com/zhaoli',
|
||||
date: '2026-04-14',
|
||||
description: 'Education and training management system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Wuhan Yangtze River Information Technology Co., Ltd.',
|
||||
location: 'Hubei · Wuhan',
|
||||
region: 'Hubei',
|
||||
website: '',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: 'Sun Tao',
|
||||
registrantUrl: 'https://gitee.com/suntao',
|
||||
date: '2026-04-13',
|
||||
description: 'Medical health management platform built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Tianjin Binhai Innovation Technology Co., Ltd.',
|
||||
location: 'Tianjin · Binhai New Area',
|
||||
region: 'Tianjin',
|
||||
website: 'https://www.tj-binhai.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: 'Zhou Min',
|
||||
registrantUrl: 'https://gitee.com/zhoumin',
|
||||
date: '2026-04-12',
|
||||
description: 'Smart manufacturing execution system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Chongqing Mountain City Software Co., Ltd.',
|
||||
location: 'Chongqing · Yubei',
|
||||
region: 'Chongqing',
|
||||
website: 'https://www.cq-mountain.com/',
|
||||
websiteEn: 'https://en.cq-mountain.com/',
|
||||
logo: '',
|
||||
registrant: 'Wu Jing',
|
||||
registrantUrl: 'https://gitee.com/wujing',
|
||||
date: '2026-04-11',
|
||||
description: 'Supply chain management system built on FastapiAdmin'
|
||||
}
|
||||
])
|
||||
|
||||
const searchKeyword = ref('')
|
||||
const activeRegion = ref('All')
|
||||
|
||||
const regions = computed(() => {
|
||||
const set = new Set(allUsers.value.map(u => u.region))
|
||||
return ['All', ...Array.from(set)]
|
||||
})
|
||||
|
||||
const filteredUsers = computed(() => {
|
||||
return allUsers.value.filter(user => {
|
||||
const matchKeyword = !searchKeyword.value ||
|
||||
user.name.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
|
||||
user.location.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||||
const matchRegion = activeRegion.value === 'All' || user.region === activeRegion.value
|
||||
return matchKeyword && matchRegion
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-header {
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.stats-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 0.5rem 1.5rem;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
.register-btn {
|
||||
display: inline-block;
|
||||
margin-top: 1rem;
|
||||
padding: 0.8rem 2rem;
|
||||
background: white;
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.register-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.search-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
padding: 1rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
transition: all 0.3s ease;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 3rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.8rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.filter-tag {
|
||||
padding: 0.6rem 1.5rem;
|
||||
cursor: pointer;
|
||||
border-radius: 25px;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg-soft);
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.filter-tag:hover {
|
||||
transform: translateY(-2px);
|
||||
border-color: #bd34fe;
|
||||
}
|
||||
|
||||
.filter-tag-active {
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
border: none;
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.4);
|
||||
padding: calc(0.6rem + 2px) calc(1.5rem + 2px);
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.2rem 1rem;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.user-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.user-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.user-logo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.user-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
line-height: 1.3;
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-description {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 0.8rem;
|
||||
line-height: 1.4;
|
||||
font-style: italic;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
line-height: 1.6;
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.user-info strong {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.user-info a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.user-info a:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
border: 2px dashed var(--vp-c-divider);
|
||||
border-radius: 16px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* 增加内容宽度 */
|
||||
:deep(.VPDoc) {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.page-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stats-badge {
|
||||
display: block;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">🚀 Who is Using FastapiAdmin</h1>
|
||||
<p class="page-subtitle">
|
||||
Thank you to every developer and enterprise who has chosen FastapiAdmin. After registration, you will receive <strong>priority technical support</strong>, and our maintenance team will respond to your issues promptly.
|
||||
</p>
|
||||
<div>
|
||||
<span class="stats-badge">👥 {{ allUsers.length }} Registered Users</span>
|
||||
<span class="stats-badge">🚀 Priority Support</span>
|
||||
<span class="stats-badge">💎 Completely Free</span>
|
||||
</div>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">📝 Register Now</a>
|
||||
</div>
|
||||
|
||||
<div class="search-section">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
placeholder="🔍 Search by company / organization / project name..."
|
||||
class="search-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<span
|
||||
v-for="r in regions"
|
||||
:key="r"
|
||||
@click="activeRegion = r"
|
||||
:class="['filter-tag', { 'filter-tag-active': activeRegion === r }]"
|
||||
>{{ r }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="filteredUsers.length > 0" class="users-grid">
|
||||
<div v-for="user in filteredUsers" :key="user.name" class="user-card">
|
||||
<div class="user-header">
|
||||
<div class="user-logo">
|
||||
<img v-if="user.logo" :src="user.logo" :alt="user.name">
|
||||
<span v-else>{{ user.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<h3 class="user-name">{{ user.name }}</h3>
|
||||
</div>
|
||||
<p v-if="user.description" class="user-description">{{ user.description }}</p>
|
||||
<div class="user-info">
|
||||
📍 <strong>Location</strong>: {{ user.location }}<br>
|
||||
<template v-if="user.website">
|
||||
🌐 <strong>Chinese Website</strong>:<br>
|
||||
<a :href="user.website" target="_blank">{{ user.website }}</a><br>
|
||||
</template>
|
||||
<template v-if="user.websiteEn">
|
||||
🌐 <strong>English Website</strong>:<br>
|
||||
<a :href="user.websiteEn" target="_blank">{{ user.websiteEn }}</a><br>
|
||||
</template>
|
||||
<span v-if="user.registrant">
|
||||
👤 <strong>Registrant</strong>:
|
||||
<a v-if="user.registrantUrl" :href="user.registrantUrl" target="_blank">{{ user.registrant }}</a>
|
||||
<span v-else>{{ user.registrant }}</span>
|
||||
<br>
|
||||
</span>
|
||||
📅 <strong>Date</strong>: {{ user.date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="empty-state">
|
||||
<div class="empty-icon">
|
||||
{{ searchKeyword || activeRegion !== 'All' ? '🔍' : '🚀' }}
|
||||
</div>
|
||||
<h3 class="empty-title">
|
||||
{{ searchKeyword || activeRegion !== 'All' ? 'No matching users found' : 'Waiting for You' }}
|
||||
</h3>
|
||||
<p class="empty-text">
|
||||
{{ searchKeyword || activeRegion !== 'All' ? 'Try adjusting your search or region filter' : 'Be the first registered user and get priority technical support' }}
|
||||
</p>
|
||||
<a v-if="!searchKeyword && activeRegion === 'All'" href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">Register Now</a>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">💡 Build Your Business with FastapiAdmin</h2>
|
||||
<p class="cta-text">
|
||||
Registration is completely free. FastapiAdmin is open source and free. We solemnly promise not to charge any fees at any stage, and your information will not be used for commercial profit or other non-public purposes.
|
||||
</p>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">Register Now</a>
|
||||
</div>
|
||||
@@ -0,0 +1,392 @@
|
||||
---
|
||||
title: Who is Using
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* 全局样式 - 增加页面宽度 */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const featuredUsers = [
|
||||
{
|
||||
name: 'Shenzhen Changhong Technology Co., Ltd.',
|
||||
location: 'Shenzhen · Pingshan',
|
||||
website: 'https://cn.sz-changhong.com/',
|
||||
websiteEn: 'https://www.sz-changhong.com/',
|
||||
registrant: 'Yang Xiangxiang',
|
||||
registrantUrl: 'https://gitee.com/xiao-lei',
|
||||
date: '2026-04-19',
|
||||
description: 'Enterprise management system built on FastapiAdmin'
|
||||
},
|
||||
{
|
||||
name: 'Beijing Yunxin XX Software Technology Co., Ltd.',
|
||||
location: 'Shaanxi · Xi\'an',
|
||||
registrant: 'Li Hao',
|
||||
registrantUrl: 'https://gitee.com/aiyun_lh',
|
||||
date: '2026-04-19',
|
||||
description: 'Unit manufacturing execution system built on FastapiAdmin'
|
||||
}
|
||||
]
|
||||
|
||||
const stats = [
|
||||
{ label: 'Registered Users', value: '2+', icon: '👥' },
|
||||
{ label: 'Technical Support', value: 'Priority', icon: '🚀' },
|
||||
{ label: 'License', value: 'Free', icon: '💎' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.8rem 2rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
|
||||
border: 1px solid rgba(102, 126, 234, 0.2);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #bd34fe;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.user-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.user-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.user-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.user-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-description {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
line-height: 2;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.user-info strong {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.user-info a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.user-info a:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.view-all-link {
|
||||
display: inline-block;
|
||||
margin: 2rem auto;
|
||||
padding: 1rem 3rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.view-all-link:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 25px rgba(189, 52, 254, 0.5);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 增加内容宽度 */
|
||||
.vp-doc {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.vp-doc .content-container {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="hero-section">
|
||||
<h1 class="hero-title">🚀 Who is Using FastapiAdmin</h1>
|
||||
<p class="hero-subtitle">
|
||||
Thank you to every developer and enterprise who has chosen FastapiAdmin<br>
|
||||
After registration, you will receive <strong>priority technical support</strong>, and our maintenance team will respond to your issues promptly
|
||||
</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="btn btn-primary">📝 Register Now (Gitee)</a>
|
||||
<a href="https://github.com/fastapiadmin/FastapiAdmin/issues/362" target="_blank" class="btn btn-primary">📝 Register Now (GitHub)</a>
|
||||
<a href="/en/users/all" class="btn btn-secondary">🔍 Browse All Users</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div v-for="stat in stats" :key="stat.label" class="stat-card">
|
||||
<div class="stat-icon">{{ stat.icon }}</div>
|
||||
<div class="stat-value">{{ stat.value }}</div>
|
||||
<div class="stat-label">{{ stat.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">✨ Featured Users</h2>
|
||||
|
||||
<div class="users-grid">
|
||||
<div v-for="user in featuredUsers" :key="user.name" class="user-card">
|
||||
<div class="user-header">
|
||||
<div class="user-logo">
|
||||
<img v-if="user.logo" :src="user.logo" :alt="user.name">
|
||||
<span v-else>{{ user.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<h3 class="user-name">{{ user.name }}</h3>
|
||||
</div>
|
||||
<p class="user-description">{{ user.description }}</p>
|
||||
<div class="user-info">
|
||||
� <strong>Location</strong>: {{ user.location }}<br>
|
||||
<span v-if="user.website">🌐 <strong>Chinese Website</strong>: <a :href="user.website" target="_blank">{{ user.website }}</a><br></span>
|
||||
<span v-if="user.websiteEn">🌐 <strong>English Website</strong>: <a :href="user.websiteEn" target="_blank">{{ user.websiteEn }}</a><br></span>
|
||||
� <strong>Registrant</strong>: <a :href="user.registrantUrl" target="_blank">{{ user.registrant }}</a><br>
|
||||
📅 <strong>Date</strong>: {{ user.date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="/en/users/all" class="view-all-link">View All Users →</a>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">💡 Build Your Business with FastapiAdmin</h2>
|
||||
<p class="cta-text">
|
||||
Registration is completely free. FastapiAdmin is open source and free. We solemnly promise not to charge any fees at any stage, and your information will not be used for commercial profit or other non-public purposes.
|
||||
</p>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="btn btn-primary">Register Now</a>
|
||||
</div>
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: Why Choose FastapiAdmin?
|
||||
---
|
||||
# Why Choose FastapiAdmin?
|
||||
|
||||
## 🎯Core Advantages
|
||||
|
||||
### 1. Advanced Technology Stack
|
||||
|
||||
- **Backend**: Based on FastAPI asynchronous framework, performance is significantly better than traditional synchronous frameworks
|
||||
- **Frontend**: Based on Vue3 + TypeScript + ElementPlus, providing a type-safe and efficient development experience
|
||||
- **Mobile**: Based on Uni App, achieving "write once, run everywhere" cross-platform development
|
||||
- **Database**: Supports MySQL and MongoDB, meeting different business scenario needs
|
||||
- **Cache**: Integrated Redis, improving system response speed and reducing database pressure
|
||||
|
||||
### 2. Complete Functional Modules
|
||||
|
||||
- **System Management**: User, role, menu, department, position management
|
||||
- **Monitoring Management**: Server monitoring, cache monitoring, online users, log management
|
||||
- **Public Management**: Configuration management, dictionary management, task management, file management
|
||||
- **Development Tools**: Code generation, form building, interface management, workflow management
|
||||
- **Mobile Application**: Unified login, personal center, workbench, message push
|
||||
|
||||
### 3. Highly Modular Design
|
||||
|
||||
- **Decoupled Architecture**: Frontend and backend separation, clear layer division
|
||||
- **Plug-in Support**: Modular design, easy to extend and customize
|
||||
- **Standardized Development**: Unified coding standards and development specifications
|
||||
- **Easy Maintenance**: Clear code structure, comprehensive documentation
|
||||
|
||||
### 4. Excellent Performance
|
||||
|
||||
- **Asynchronous Processing**: FastAPI asynchronous framework handles concurrent requests efficiently
|
||||
- **Cache Optimization**: Multi-level cache strategy reduces database access
|
||||
- **Database Optimization**: Reasonable index design and query optimization
|
||||
- **Load Balancing**: Support for horizontal scaling to handle high concurrency
|
||||
|
||||
### 5. Security and Reliability
|
||||
|
||||
- **Authentication**: JWT OAuth2 authentication mechanism, secure and reliable
|
||||
- **Permission Control**: RBAC model implements fine-grained permission management
|
||||
- **Data Encryption**: Sensitive data encryption storage
|
||||
- **Audit Logs**: Complete operation logs for traceability
|
||||
- **Error Handling**: Comprehensive exception handling and error reporting mechanism
|
||||
|
||||
### 6. Easy Deployment and Maintenance
|
||||
|
||||
- **Docker Support**: One-click deployment with Docker Compose
|
||||
- **Nginx Integration**: Built-in reverse proxy configuration
|
||||
- **Multi-environment Support**: Development, testing, production environment isolation
|
||||
- **Monitoring Alert**: Server and application monitoring, timely alerting
|
||||
- **Automated Operation and Maintenance**: Support for CI/CD pipeline integration
|
||||
|
||||
### 7. Rich Development Tools
|
||||
|
||||
- **Code Generator**: Automatically generates CRUD code, improving development efficiency
|
||||
- **Form Builder**: Visual form design, no need for manual coding
|
||||
- **API Documentation**: Automatically generated by FastAPI, real-time update
|
||||
- **Workflow Designer**: Visual workflow design and execution
|
||||
- **Intelligent Assistant**: AI-assisted development and system operation
|
||||
|
||||
### 8. Multi-platform Support
|
||||
|
||||
- **Web End**: Responsive design, supports PC and tablet devices
|
||||
- **Mobile End**: Based on Uni App, supports WeChat Mini Program, H5, iOS, Android
|
||||
- **Unified Experience**: Consistent user experience across different platforms
|
||||
- **Data Synchronization**: Real-time data synchronization between Web and mobile ends
|
||||
|
||||
## 📊Comparison with Other Frameworks
|
||||
|
||||
### FastapiAdmin vs Traditional Backend Frameworks
|
||||
|
||||
| Feature | FastapiAdmin | Django Admin | Flask Admin | Spring Boot Admin |
|
||||
|---------|--------------|-------------|-------------|-------------------|
|
||||
| **Technology Stack** | FastAPI + Vue3 + TypeScript | Django + Template | Flask + Template | Spring Boot + Thymeleaf |
|
||||
| **Performance** | High (asynchronous) | Medium (synchronous) | Medium (synchronous) | Medium (synchronous) |
|
||||
| **Frontend Experience** | Modern, interactive | Simple, static | Simple, static | Traditional, heavy |
|
||||
| **Mobile Support** | Built-in FastApp | None | None | None |
|
||||
| **Modularity** | High | Medium | Low | Medium |
|
||||
| **Customization** | High | Medium | High | Medium |
|
||||
| **Learning Curve** | Medium | Low | Medium | High |
|
||||
| **Community Support** | Growing | Large | Medium | Large |
|
||||
| **Deployment** | Docker-friendly | Traditional | Traditional | Complex |
|
||||
|
||||
### FastapiAdmin vs Other Rapid Development Platforms
|
||||
|
||||
| Feature | FastapiAdmin | Ant Design Pro | Ruoyi Fast | Jeecg Boot |
|
||||
|---------|--------------|----------------|------------|------------|
|
||||
| **Backend Language** | Python | JavaScript (Node.js) | Java | Java |
|
||||
| **Frontend Framework** | Vue3 + TypeScript | React + TypeScript | Vue3 | Vue3 |
|
||||
| **Mobile Support** | Built-in FastApp | None | None | None |
|
||||
| **Database Support** | MySQL, MongoDB | MySQL | MySQL | MySQL |
|
||||
| **Asynchronous Support** | Yes | Yes | No | No |
|
||||
| **Code Quality** | High | High | Medium | Medium |
|
||||
| **Documentation** | Comprehensive | Comprehensive | Medium | Medium |
|
||||
| **Ecosystem** | Growing | Mature | Small | Medium |
|
||||
| **License** | MIT | MIT | Apache 2.0 | Apache 2.0 |
|
||||
|
||||
## 🎯Suitable Scenarios
|
||||
|
||||
### 1. Enterprise Internal Management Systems
|
||||
|
||||
- **Human Resource Management**: Employee information, attendance, performance management
|
||||
- **Financial Management**: Budget, expense, invoice management
|
||||
- **OA System**: Approval workflow, document management, meeting management
|
||||
- **Asset Management**: Fixed assets, inventory management
|
||||
|
||||
### 2. Business Operation Platforms
|
||||
|
||||
- **E-commerce Backend**: Order management, product management, customer management
|
||||
- **Content Management System**: Article publishing, media management, column management
|
||||
- **Customer Relationship Management**: Customer information, sales pipeline, service records
|
||||
- **Marketing Management**: Activity management, coupon management, data analysis
|
||||
|
||||
### 3. Data Analysis Platforms
|
||||
|
||||
- **Business Intelligence**: Data dashboard, report generation, trend analysis
|
||||
- **Operation Analysis**: User behavior analysis, traffic analysis, conversion rate analysis
|
||||
- **Financial Analysis**: Revenue analysis, cost analysis, profit analysis
|
||||
- **Performance Analysis**: Department performance, employee performance, project performance
|
||||
|
||||
### 4. API Management Platforms
|
||||
|
||||
- **Interface Management**: API documentation, testing, monitoring
|
||||
- **Developer Platform**: Third-party integration, SDK management, access control
|
||||
- **Service Governance**: Service registration, discovery, load balancing
|
||||
- **API Gateway**: Request routing, authentication, rate limiting
|
||||
|
||||
### 5. Multi-platform Applications
|
||||
|
||||
- **Enterprise Applications**: Need both Web and mobile access
|
||||
- **Field Services**: On-site staff use mobile terminals, backend management through Web
|
||||
- **Customer Services**: Customers use mobile terminals, staff manage through Web
|
||||
- **Internal Tools**: Employees use both PC and mobile terminals
|
||||
|
||||
## 🔧Technical Advantages in Detail
|
||||
|
||||
### 1. Backend Advantages
|
||||
|
||||
- **FastAPI Framework**: Asynchronous processing, automatic API documentation generation, type hints
|
||||
- **SQLAlchemy 2.0**: Modern ORM, support for asynchronous operations
|
||||
- **Redis Cache**: High performance, support for various data structures
|
||||
- **MySQL 8.0**: Stable, reliable, support for complex queries
|
||||
- **JWT Authentication**: Stateless, secure, easy to scale
|
||||
|
||||
### 2. Frontend Advantages
|
||||
|
||||
- **Vue3 Composition API**: Better code organization, easier reuse
|
||||
- **TypeScript**: Type safety, better development experience
|
||||
- **ElementPlus**: Rich components, beautiful interface
|
||||
- **Pinia**: Lightweight state management, better TypeScript support
|
||||
- **Axios**: Powerful HTTP client, support for interceptors
|
||||
|
||||
### 3. Mobile Advantages
|
||||
|
||||
- **Uni App**: Cross-platform development, support for multiple terminals
|
||||
- **Wot Design Uni**: Mobile-optimized UI components
|
||||
- **Vue3 Syntax**: Consistent with Web frontend, reduced learning cost
|
||||
- **Native Performance**: Near-native performance through rendering optimization
|
||||
- **Easy Packaging**: One-click packaging for multiple platforms
|
||||
|
||||
### 4. DevOps Advantages
|
||||
|
||||
- **Docker Containerization**: Consistent environment, easy deployment
|
||||
- **Docker Compose**: Multi-container orchestration, simplified management
|
||||
- **Nginx Reverse Proxy**: High performance, support for HTTPS
|
||||
- **CI/CD Integration**: Automated testing and deployment
|
||||
- **Monitoring System**: Real-time monitoring, timely alerting
|
||||
|
||||
## 📚Complete Documentation
|
||||
|
||||
- **Getting Started Guide**: Detailed installation and configuration steps
|
||||
- **Development Documentation**: Backend, frontend, mobile development guides
|
||||
- **Deployment Documentation**: Docker deployment, manual deployment, cloud deployment
|
||||
- **API Documentation**: Automatically generated by FastAPI, interactive testing
|
||||
- **Best Practices**: Development specifications, performance optimization, security guidelines
|
||||
|
||||
## 🤝Active Community
|
||||
|
||||
- **Open Source**: Completely open source, MIT license
|
||||
- **Community Support**: GitHub, Gitee, QQ group, WeChat group
|
||||
- **Continuous Updates**: Regular version updates and bug fixes
|
||||
- **Feedback Channels**: Multiple channels for suggestions and issues
|
||||
- **Contribution Guide**: Clear contribution process and guidelines
|
||||
|
||||
## 🚀Future Plans
|
||||
|
||||
- **AI Integration**: Deep integration of AI capabilities into the development process
|
||||
- **Microservices Support**: Evolution towards microservices architecture
|
||||
- **Low-code Platform**: Further simplification of development process
|
||||
- **More Templates**: Rich industry-specific templates
|
||||
- **Internationalization**: Better support for multi-language and multi-region
|
||||
|
||||
## 🎉Conclusion
|
||||
|
||||
**FastapiAdmin** is a **modern, efficient, and comprehensive rapid development platform** that combines the advantages of FastAPI, Vue3, and Uni App. It provides a complete solution for enterprise-level application development, from backend API to frontend interface, and from Web end to mobile end.
|
||||
|
||||
Whether you are building a small internal tool or a large enterprise system, FastapiAdmin can help you **reduce development costs, improve development efficiency, and ensure system quality**.
|
||||
|
||||
Choose FastapiAdmin, choose a better development experience!
|
||||
@@ -0,0 +1,992 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: 代码示例和使用案例
|
||||
---
|
||||
# 代码示例和使用案例
|
||||
|
||||
## 📝代码示例
|
||||
|
||||
### 1. 后端代码示例
|
||||
|
||||
#### 1.1 创建新的API模块
|
||||
|
||||
```python
|
||||
# 1. 创建模型文件
|
||||
# app/api/v1/models/demo/example_model.py
|
||||
from sqlalchemy import Column, Integer, String, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from app.core.base_model import Base
|
||||
|
||||
class Example(Base):
|
||||
__tablename__ = "example"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String(100), nullable=False)
|
||||
description = Column(String(255), nullable=True)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||
|
||||
# 2. 创建Schema文件
|
||||
# app/api/v1/schemas/demo/example_schema.py
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
class ExampleBase(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
|
||||
class ExampleCreate(ExampleBase):
|
||||
pass
|
||||
|
||||
class ExampleUpdate(ExampleBase):
|
||||
name: Optional[str] = None
|
||||
|
||||
class ExampleResponse(ExampleBase):
|
||||
id: int
|
||||
created_at: datetime
|
||||
updated_at: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
# 3. 创建查询参数文件
|
||||
# app/api/v1/params/demo/example_param.py
|
||||
from app.core.base_params import BaseParams
|
||||
from typing import Optional
|
||||
|
||||
class ExampleParams(BaseParams):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
# 4. 创建CRUD文件
|
||||
# app/api/v1/cruds/demo/example_crud.py
|
||||
from sqlalchemy.orm import Session
|
||||
from app.api.v1.models.demo.example_model import Example
|
||||
from app.api.v1.schemas.demo.example_schema import ExampleCreate, ExampleUpdate
|
||||
|
||||
class ExampleCrud:
|
||||
@staticmethod
|
||||
def get_by_id(db: Session, id: int):
|
||||
return db.query(Example).filter(Example.id == id).first()
|
||||
|
||||
@staticmethod
|
||||
def get_list(db: Session, skip: int = 0, limit: int = 100, **filters):
|
||||
query = db.query(Example)
|
||||
|
||||
# 应用过滤条件
|
||||
for key, value in filters.items():
|
||||
if value:
|
||||
query = query.filter(getattr(Example, key).like(f"%{value}%"))
|
||||
|
||||
return query.offset(skip).limit(limit).all()
|
||||
|
||||
@staticmethod
|
||||
def create(db: Session, example: ExampleCreate):
|
||||
db_example = Example(**example.model_dump())
|
||||
db.add(db_example)
|
||||
db.commit()
|
||||
db.refresh(db_example)
|
||||
return db_example
|
||||
|
||||
@staticmethod
|
||||
def update(db: Session, db_example: Example, example: ExampleUpdate):
|
||||
update_data = example.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(db_example, key, value)
|
||||
db.commit()
|
||||
db.refresh(db_example)
|
||||
return db_example
|
||||
|
||||
@staticmethod
|
||||
def delete(db: Session, id: int):
|
||||
db_example = db.query(Example).filter(Example.id == id).first()
|
||||
if db_example:
|
||||
db.delete(db_example)
|
||||
db.commit()
|
||||
return True
|
||||
return False
|
||||
|
||||
# 5. 创建服务文件
|
||||
# app/api/v1/services/demo/example_service.py
|
||||
from sqlalchemy.orm import Session
|
||||
from app.api.v1.cruds.demo.example_crud import ExampleCrud
|
||||
from app.api.v1.schemas.demo.example_schema import ExampleCreate, ExampleUpdate
|
||||
from app.api.v1.params.demo.example_param import ExampleParams
|
||||
|
||||
class ExampleService:
|
||||
@staticmethod
|
||||
def get_example(db: Session, id: int):
|
||||
return ExampleCrud.get_by_id(db, id)
|
||||
|
||||
@staticmethod
|
||||
def get_example_list(db: Session, params: ExampleParams):
|
||||
return ExampleCrud.get_list(
|
||||
db,
|
||||
skip=params.skip,
|
||||
limit=params.limit,
|
||||
name=params.name,
|
||||
description=params.description
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_example(db: Session, example: ExampleCreate):
|
||||
return ExampleCrud.create(db, example)
|
||||
|
||||
@staticmethod
|
||||
def update_example(db: Session, id: int, example: ExampleUpdate):
|
||||
db_example = ExampleCrud.get_by_id(db, id)
|
||||
if not db_example:
|
||||
return None
|
||||
return ExampleCrud.update(db, db_example, example)
|
||||
|
||||
@staticmethod
|
||||
def delete_example(db: Session, id: int):
|
||||
return ExampleCrud.delete(db, id)
|
||||
|
||||
# 6. 创建控制器文件
|
||||
# app/api/v1/controllers/demo/example_controller.py
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from app.api.v1.schemas.demo.example_schema import ExampleCreate, ExampleUpdate, ExampleResponse
|
||||
from app.api.v1.params.demo.example_param import ExampleParams
|
||||
from app.api.v1.services.demo.example_service import ExampleService
|
||||
|
||||
router = APIRouter(prefix="/example", tags=["example"])
|
||||
|
||||
@router.get("", response_model=list[ExampleResponse])
|
||||
def get_example_list(
|
||||
params: ExampleParams = Depends(),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
examples = ExampleService.get_example_list(db, params)
|
||||
return examples
|
||||
|
||||
@router.get("/{id}", response_model=ExampleResponse)
|
||||
def get_example(
|
||||
id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
example = ExampleService.get_example(db, id)
|
||||
if not example:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return example
|
||||
|
||||
@router.post("", response_model=ExampleResponse)
|
||||
def create_example(
|
||||
example: ExampleCreate,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
return ExampleService.create_example(db, example)
|
||||
|
||||
@router.put("/{id}", response_model=ExampleResponse)
|
||||
def update_example(
|
||||
id: int,
|
||||
example: ExampleUpdate,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
updated_example = ExampleService.update_example(db, id, example)
|
||||
if not updated_example:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return updated_example
|
||||
|
||||
@router.delete("/{id}")
|
||||
def delete_example(
|
||||
id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
success = ExampleService.delete_example(db, id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="Example not found")
|
||||
return {"message": "Example deleted successfully"}
|
||||
|
||||
# 7. 注册路由
|
||||
# app/api/v1/urls/demo/example_url.py
|
||||
from fastapi import APIRouter
|
||||
from app.api.v1.controllers.demo.example_controller import router as example_router
|
||||
|
||||
router = APIRouter()
|
||||
router.include_router(example_router)
|
||||
|
||||
# 8. 添加到主路由
|
||||
# plugin/init_app.py
|
||||
from fastapi import FastAPI
|
||||
from app.api.v1.urls.demo.example_url import router as example_router
|
||||
|
||||
def init_router(app: FastAPI):
|
||||
# 其他路由...
|
||||
app.include_router(example_router, prefix="/api/v1")
|
||||
|
||||
# 9. 添加到数据库迁移
|
||||
# app/alembic/env.py
|
||||
from app.api.v1.models.demo.example_model import Example
|
||||
# 在 target_metadata 中添加 Example
|
||||
```
|
||||
|
||||
#### 1.2 使用依赖注入
|
||||
|
||||
```python
|
||||
# app/core/dependencies.py
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
from jose import JWTError, jwt
|
||||
from sqlalchemy.orm import Session
|
||||
from app.core.database import get_db
|
||||
from app.api.v1.models.system.user_model import User
|
||||
from app.core.security import ALGORITHM, SECRET_KEY
|
||||
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
|
||||
|
||||
async def get_current_user(
|
||||
token: str = Depends(oauth2_scheme),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
credentials_exception = HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
try:
|
||||
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
||||
username: str = payload.get("sub")
|
||||
if username is None:
|
||||
raise credentials_exception
|
||||
except JWTError:
|
||||
raise credentials_exception
|
||||
|
||||
user = db.query(User).filter(User.username == username).first()
|
||||
if user is None:
|
||||
raise credentials_exception
|
||||
return user
|
||||
|
||||
async def get_current_active_user(
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
if not current_user.is_active:
|
||||
raise HTTPException(status_code=400, detail="Inactive user")
|
||||
return current_user
|
||||
|
||||
# 使用示例
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.api.v1.schemas.system.user_schema import UserResponse
|
||||
from app.core.dependencies import get_current_active_user
|
||||
from app.api.v1.models.system.user_model import User
|
||||
|
||||
router = APIRouter(prefix="/user", tags=["user"])
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
def get_current_user_info(
|
||||
current_user: User = Depends(get_current_active_user)
|
||||
):
|
||||
return current_user
|
||||
```
|
||||
|
||||
### 2. 前端代码示例
|
||||
|
||||
#### 2.1 创建新的页面
|
||||
|
||||
```vue
|
||||
<!-- src/views/demo/example/index.vue -->
|
||||
<template>
|
||||
<div class="example-container">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>示例管理</span>
|
||||
<el-button type="primary" @click="handleAdd">添加</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 搜索表单 -->
|
||||
<el-form :inline="true" :model="searchForm" class="mb-4">
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="searchForm.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="searchForm.description" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="resetForm">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="exampleList" style="width: 100%">
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="description" label="描述" />
|
||||
<el-table-column prop="created_at" label="创建时间" width="180" />
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.currentPage"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="pagination.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 添加/编辑对话框 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form :model="form" :rules="rules" ref="formRef">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="form.description" placeholder="请输入描述" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { exampleApi } from '@/api/demo/example';
|
||||
import type { Example } from '@/api/demo/example';
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
name: '',
|
||||
description: ''
|
||||
});
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
});
|
||||
|
||||
// 数据
|
||||
const exampleList = ref<Example[]>([]);
|
||||
const loading = ref(false);
|
||||
|
||||
// 对话框
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('添加示例');
|
||||
const form = reactive({
|
||||
id: 0,
|
||||
name: '',
|
||||
description: ''
|
||||
});
|
||||
const formRef = ref();
|
||||
|
||||
// 验证规则
|
||||
const rules = {
|
||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await exampleApi.getList({
|
||||
page: pagination.currentPage,
|
||||
page_size: pagination.pageSize,
|
||||
...searchForm
|
||||
});
|
||||
exampleList.value = res.data.items;
|
||||
pagination.total = res.data.total;
|
||||
} catch (error) {
|
||||
console.error('Failed to load examples:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.currentPage = 1;
|
||||
loadData();
|
||||
};
|
||||
|
||||
// 重置
|
||||
const resetForm = () => {
|
||||
searchForm.name = '';
|
||||
searchForm.description = '';
|
||||
pagination.currentPage = 1;
|
||||
loadData();
|
||||
};
|
||||
|
||||
// 分页变化
|
||||
const handleSizeChange = (size: number) => {
|
||||
pagination.pageSize = size;
|
||||
loadData();
|
||||
};
|
||||
|
||||
const handleCurrentChange = (current: number) => {
|
||||
pagination.currentPage = current;
|
||||
loadData();
|
||||
};
|
||||
|
||||
// 添加
|
||||
const handleAdd = () => {
|
||||
dialogTitle.value = '添加示例';
|
||||
form.id = 0;
|
||||
form.name = '';
|
||||
form.description = '';
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 编辑
|
||||
const handleEdit = (row: Example) => {
|
||||
dialogTitle.value = '编辑示例';
|
||||
form.id = row.id;
|
||||
form.name = row.name;
|
||||
form.description = row.description;
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 删除
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
await exampleApi.delete(id);
|
||||
loadData();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete example:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 提交
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
|
||||
if (form.id) {
|
||||
// 编辑
|
||||
await exampleApi.update(form.id, form);
|
||||
} else {
|
||||
// 添加
|
||||
await exampleApi.create(form);
|
||||
}
|
||||
|
||||
dialogVisible.value = false;
|
||||
loadData();
|
||||
} catch (error) {
|
||||
console.error('Failed to submit form:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.example-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
#### 2.2 API调用示例
|
||||
|
||||
```typescript
|
||||
// src/api/demo/example.ts
|
||||
import request from '@/utils/request';
|
||||
|
||||
export interface Example {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface ExampleListResponse {
|
||||
items: Example[];
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
}
|
||||
|
||||
export const exampleApi = {
|
||||
// 获取示例列表
|
||||
getList: (params: any) => {
|
||||
return request<ExampleListResponse>({
|
||||
url: '/api/v1/example',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
},
|
||||
|
||||
// 获取单个示例
|
||||
getOne: (id: number) => {
|
||||
return request<Example>({
|
||||
url: `/api/v1/example/${id}`,
|
||||
method: 'GET'
|
||||
});
|
||||
},
|
||||
|
||||
// 创建示例
|
||||
create: (data: any) => {
|
||||
return request<Example>({
|
||||
url: '/api/v1/example',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
},
|
||||
|
||||
// 更新示例
|
||||
update: (id: number, data: any) => {
|
||||
return request<Example>({
|
||||
url: `/api/v1/example/${id}`,
|
||||
method: 'PUT',
|
||||
data
|
||||
});
|
||||
},
|
||||
|
||||
// 删除示例
|
||||
delete: (id: number) => {
|
||||
return request({
|
||||
url: `/api/v1/example/${id}`,
|
||||
method: 'DELETE'
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 移动端代码示例
|
||||
|
||||
#### 3.1 页面示例
|
||||
|
||||
```vue
|
||||
<!-- src/pages/example/index.vue -->
|
||||
<template>
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">示例页面</text>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-bar">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
type="text"
|
||||
placeholder="请输入搜索关键词"
|
||||
class="search-input"
|
||||
/>
|
||||
<button type="primary" @click="handleSearch" class="search-button">搜索</button>
|
||||
</view>
|
||||
|
||||
<!-- 示例列表 -->
|
||||
<view class="example-list">
|
||||
<view
|
||||
v-for="item in exampleList"
|
||||
:key="item.id"
|
||||
class="example-item"
|
||||
@click="handleItemClick(item)"
|
||||
>
|
||||
<view class="item-title">{{ item.name }}</view>
|
||||
<view class="item-description">{{ item.description }}</view>
|
||||
<view class="item-time">{{ formatTime(item.created_at) }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="exampleList.length === 0" class="empty-state">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="loading" class="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="footer">
|
||||
<button type="primary" @click="handleAdd" class="add-button">添加示例</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { exampleApi } from '@/api/example';
|
||||
import type { Example } from '@/api/example';
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('');
|
||||
|
||||
// 示例列表
|
||||
const exampleList = ref<Example[]>([]);
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
|
||||
// 搜索
|
||||
const handleSearch = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await exampleApi.getList({
|
||||
keyword: searchKeyword.value
|
||||
});
|
||||
exampleList.value = res.data.items;
|
||||
} catch (error) {
|
||||
console.error('搜索失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 点击示例项
|
||||
const handleItemClick = (item: Example) => {
|
||||
// 跳转到详情页
|
||||
uni.navigateTo({
|
||||
url: `/pages/example/detail?id=${item.id}`
|
||||
});
|
||||
};
|
||||
|
||||
// 添加示例
|
||||
const handleAdd = () => {
|
||||
// 跳转到添加页面
|
||||
uni.navigateTo({
|
||||
url: '/pages/example/add'
|
||||
});
|
||||
};
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (time: string) => {
|
||||
const date = new Date(time);
|
||||
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
// 加载数据
|
||||
const loadData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await exampleApi.getList({});
|
||||
exampleList.value = res.data.items;
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 8rpx;
|
||||
padding: 15rpx;
|
||||
margin-right: 10rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
width: 120rpx;
|
||||
}
|
||||
|
||||
.example-list {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.example-item {
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.example-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.item-description {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.item-time {
|
||||
font-size: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 100rpx 0;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.loading {
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 20rpx;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #f5f5f5;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.add-button {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 🚀使用案例
|
||||
|
||||
### 1. 企业内部管理系统
|
||||
|
||||
#### 1.1 需求分析
|
||||
|
||||
- **用户管理**:员工信息管理、角色权限管理
|
||||
- **部门管理**:部门结构管理、人员调动
|
||||
- **考勤管理**:打卡记录、请假审批
|
||||
- **审批流程**:请假、报销、加班等审批
|
||||
- **数据统计**:员工数据、考勤数据统计分析
|
||||
|
||||
#### 1.2 技术实现
|
||||
|
||||
- **后端**:使用 FastapiAdmin 提供的用户、角色、权限等模块,扩展考勤和审批模块
|
||||
- **前端**:使用 ElementPlus 构建管理界面,实现数据表格、表单、流程等组件
|
||||
- **移动端**:使用 FastApp 实现员工打卡、审批查看等功能
|
||||
|
||||
#### 1.3 部署方案
|
||||
|
||||
- **生产环境**:使用 Docker Compose 部署,包含后端、前端、MySQL、Redis、Nginx
|
||||
- **监控**:使用 Prometheus + Grafana 监控系统状态
|
||||
- **备份**:定期备份数据库和配置文件
|
||||
|
||||
### 2. 电商后台管理系统
|
||||
|
||||
#### 2.1 需求分析
|
||||
|
||||
- **商品管理**:商品分类、商品信息、库存管理
|
||||
- **订单管理**:订单处理、物流跟踪、退款管理
|
||||
- **用户管理**:客户信息、会员等级、积分管理
|
||||
- **营销管理**:优惠券、活动管理、数据分析
|
||||
- **统计报表**:销售数据、用户数据、商品数据统计
|
||||
|
||||
#### 2.2 技术实现
|
||||
|
||||
- **后端**:基于 FastapiAdmin 扩展商品、订单、营销等模块
|
||||
- **前端**:使用 ElementPlus 构建管理界面,实现商品列表、订单处理等功能
|
||||
- **移动端**:使用 FastApp 实现商家查看订单、管理商品等功能
|
||||
|
||||
#### 2.3 部署方案
|
||||
|
||||
- **生产环境**:使用云服务器部署,采用负载均衡架构
|
||||
- **数据库**:使用主从复制提高可靠性
|
||||
- **缓存**:使用 Redis 缓存热点数据,提高响应速度
|
||||
- **CDN**:使用 CDN 加速静态文件传输
|
||||
|
||||
### 3. 内容管理系统
|
||||
|
||||
#### 3.1 需求分析
|
||||
|
||||
- **内容管理**:文章、图片、视频等内容管理
|
||||
- **分类管理**:内容分类、标签管理
|
||||
- **用户管理**:作者、编辑、审核员等角色管理
|
||||
- **审核流程**:内容发布审核流程
|
||||
- **统计分析**:内容阅读量、用户活跃度等统计
|
||||
|
||||
#### 3.2 技术实现
|
||||
|
||||
- **后端**:基于 FastapiAdmin 扩展内容、分类等模块
|
||||
- **前端**:使用 ElementPlus 构建管理界面,实现富文本编辑器、媒体库等功能
|
||||
- **移动端**:使用 FastApp 实现作者查看文章状态、编辑文章等功能
|
||||
|
||||
#### 3.3 部署方案
|
||||
|
||||
- **生产环境**:使用容器化部署,便于横向扩展
|
||||
- **存储**:使用对象存储服务存储媒体文件
|
||||
- **搜索**:集成 Elasticsearch 实现全文搜索
|
||||
- **监控**:使用 ELK Stack 收集和分析日志
|
||||
|
||||
## 🔧最佳实践
|
||||
|
||||
### 1. 代码规范
|
||||
|
||||
#### 1.1 后端代码规范
|
||||
|
||||
- **命名规范**:使用 snake_case 命名变量和函数,使用 PascalCase 命名类
|
||||
- **代码风格**:遵循 PEP 8 代码风格指南
|
||||
- **类型注解**:使用类型注解提高代码可读性和可维护性
|
||||
- **错误处理**:使用 try-except 捕获异常,返回统一的错误格式
|
||||
- **日志记录**:使用结构化日志,记录关键操作和错误信息
|
||||
|
||||
#### 1.2 前端代码规范
|
||||
|
||||
- **命名规范**:使用 camelCase 命名变量和函数,使用 PascalCase 命名组件
|
||||
- **代码风格**:遵循 ESLint 和 Prettier 配置
|
||||
- **类型注解**:使用 TypeScript 类型注解
|
||||
- **组件设计**:遵循单一职责原则,组件拆分合理
|
||||
- **状态管理**:使用 Pinia 管理全局状态,合理使用组件状态
|
||||
|
||||
### 2. 性能优化
|
||||
|
||||
#### 2.1 后端优化
|
||||
|
||||
- **数据库优化**:使用索引、优化查询语句、合理使用缓存
|
||||
- **API 优化**:使用分页、限流、缓存等技术
|
||||
- **代码优化**:减少不必要的计算和IO操作
|
||||
- **并发优化**:合理使用异步编程,提高并发处理能力
|
||||
|
||||
#### 2.2 前端优化
|
||||
|
||||
- **资源优化**:使用代码分割、懒加载、压缩等技术
|
||||
- **渲染优化**:减少 DOM 操作,使用虚拟列表,合理使用缓存
|
||||
- **网络优化**:使用 HTTP/2、HTTPS、CDN 等技术
|
||||
- **状态管理优化**:合理使用全局状态,避免不必要的重渲染
|
||||
|
||||
### 3. 安全最佳实践
|
||||
|
||||
#### 3.1 后端安全
|
||||
|
||||
- **认证授权**:使用 JWT 认证,实现细粒度的权限控制
|
||||
- **输入验证**:使用 Pydantic 进行数据验证,防止注入攻击
|
||||
- **密码安全**:使用 bcrypt 等算法加密存储密码
|
||||
- **CORS 配置**:合理配置 CORS 策略,防止跨站请求伪造
|
||||
- **敏感信息保护**:避免在日志中记录敏感信息,使用环境变量存储配置
|
||||
|
||||
#### 3.2 前端安全
|
||||
|
||||
- **XSS 防护**:使用 Vue 的自动转义功能,避免直接操作 DOM
|
||||
- **CSRF 防护**:使用 token 验证,防止跨站请求伪造
|
||||
- **敏感信息保护**:不在前端存储敏感信息,使用 HTTPS 传输数据
|
||||
- **依赖安全**:定期更新依赖包,避免使用有安全漏洞的依赖
|
||||
|
||||
## 📚参考资源
|
||||
|
||||
- **FastAPI 官方文档**:[https://fastapi.tiangolo.com/](https://fastapi.tiangolo.com/)
|
||||
- **Vue 3 官方文档**:[https://v3.vuejs.org/](https://v3.vuejs.org/)
|
||||
- **ElementPlus 官方文档**:[https://element-plus.org/](https://element-plus.org/)
|
||||
- **Uni App 官方文档**:[https://uniapp.dcloud.io/](https://uniapp.dcloud.io/)
|
||||
- **TypeScript 官方文档**:[https://www.typescriptlang.org/](https://www.typescriptlang.org/)
|
||||
- **Docker 官方文档**:[https://docs.docker.com/](https://docs.docker.com/)
|
||||
- **Nginx 官方文档**:[https://nginx.org/en/docs/](https://nginx.org/en/docs/)
|
||||
|
||||
## 🤝常见问题
|
||||
|
||||
### 1. 如何快速创建新的 API 模块?
|
||||
|
||||
**解决方案**:
|
||||
- 使用 FastapiAdmin 提供的代码生成工具
|
||||
- 参考示例代码,按照标准流程创建模型、Schema、CRUD、服务、控制器等文件
|
||||
- 注册路由并添加到数据库迁移
|
||||
|
||||
### 2. 如何处理跨域问题?
|
||||
|
||||
**解决方案**:
|
||||
- 在后端配置 CORS 中间件
|
||||
- 在前端使用代理服务器
|
||||
- 使用 JSONP 或 WebSocket 等技术
|
||||
|
||||
### 3. 如何优化数据库查询性能?
|
||||
|
||||
**解决方案**:
|
||||
- 添加合适的索引
|
||||
- 优化查询语句,避免全表扫描
|
||||
- 使用分页查询,限制返回数据量
|
||||
- 合理使用缓存,减少数据库查询次数
|
||||
|
||||
### 4. 如何实现文件上传功能?
|
||||
|
||||
**解决方案**:
|
||||
- 使用 FastAPI 的 File 上传功能
|
||||
- 配置文件存储路径和权限
|
||||
- 实现文件上传、下载、删除等 API
|
||||
- 前端使用 FormData 上传文件
|
||||
|
||||
### 5. 如何实现定时任务?
|
||||
|
||||
**解决方案**:
|
||||
- 使用 APScheduler 库实现定时任务
|
||||
- 配置任务调度器,设置任务执行时间和频率
|
||||
- 实现任务函数,处理具体业务逻辑
|
||||
- 监控任务执行状态和结果
|
||||
|
||||
## 📄许可协议
|
||||
|
||||
FastapiAdmin 项目采用 MIT 许可协议,详见 [LICENSE](https://github.com/fastapiadmin/FastapiAdmin/blob/master/LICENSE) 文件。
|
||||
@@ -0,0 +1,451 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: 开发规范
|
||||
---
|
||||
# 开发规范
|
||||
|
||||
## 📚规范概述
|
||||
|
||||
为了保证项目代码的一致性、可读性和可维护性,FastapiAdmin 项目制定了以下开发规范。所有参与项目开发的开发者都应该遵循这些规范。
|
||||
|
||||
## 🎨前端开发规范
|
||||
|
||||
### 1. 代码风格
|
||||
|
||||
#### 1.1 TypeScript 规范
|
||||
|
||||
- 使用 TypeScript 严格模式(`"strict": true`)
|
||||
- 为所有变量、函数、接口添加类型注解
|
||||
- 避免使用 `any` 类型,除非确实无法确定类型
|
||||
- 使用接口定义对象类型,而不是类型别名
|
||||
- 使用枚举定义常量集合
|
||||
- 使用 `type` 定义联合类型和交叉类型
|
||||
- 使用 `as const` 断言确保类型安全
|
||||
- 使用 `readonly` 修饰符保护不可变数据
|
||||
- 使用 `unknown` 类型处理不确定类型的数据
|
||||
|
||||
#### 1.2 Vue 规范
|
||||
|
||||
- 使用 Composition API
|
||||
- 使用 `<script setup lang="ts">` 语法
|
||||
- 组件命名使用 PascalCase
|
||||
- 变量和函数命名使用 camelCase
|
||||
- 常量命名使用 UPPER_SNAKE_CASE
|
||||
- 使用 `ref()` 定义响应式变量
|
||||
- 使用 `computed()` 定义计算属性
|
||||
- 使用 `watch()` 或 `watchEffect()` 监听变化
|
||||
- 使用 `onMounted()`、`onUnmounted()` 等生命周期钩子
|
||||
- 组件 props 使用 `defineProps()` 定义并添加类型
|
||||
- 组件事件使用 `defineEmits()` 定义并添加类型
|
||||
- 组件暴露的属性和方法使用 `defineExpose()` 定义
|
||||
|
||||
#### 1.3 CSS 规范
|
||||
|
||||
- 使用 UnoCSS 原子化 CSS
|
||||
- 避免使用内联样式
|
||||
- 使用 BEM 命名规范(如果不使用 UnoCSS)
|
||||
- 类名使用 kebab-case
|
||||
- 避免使用 ID 选择器
|
||||
- 使用 CSS 变量管理主题
|
||||
- 避免使用 `!important` 修饰符
|
||||
- 使用 flexbox 布局确保跨平台一致性
|
||||
- 合理使用 CSS Grid 布局
|
||||
- 优化 CSS 选择器优先级
|
||||
|
||||
### 2. 组件开发最佳实践
|
||||
|
||||
- **单一职责原则**:每个组件只负责一个功能
|
||||
- **props 设计**:
|
||||
- 使用 `required` 和 `default` 明确 props 要求
|
||||
- 为复杂 props 添加验证
|
||||
- 使用 `withDefaults()` 为 props 设置默认值
|
||||
- **事件设计**:
|
||||
- 使用 kebab-case 命名事件
|
||||
- 事件参数类型明确
|
||||
- 避免在事件中传递过多参数
|
||||
- **插槽设计**:
|
||||
- 使用具名插槽提高可读性
|
||||
- 为插槽添加默认内容
|
||||
- 使用作用域插槽传递数据
|
||||
- **样式设计**:
|
||||
- 使用 `scoped` 样式避免冲突
|
||||
- 合理使用 `:deep()` 选择器
|
||||
- 避免在组件中使用全局样式
|
||||
|
||||
### 3. 状态管理最佳实践
|
||||
|
||||
- **模块化设计**:按功能模块拆分 store
|
||||
- **状态定义**:
|
||||
- 使用 `interface` 定义 state 类型
|
||||
- 初始化所有状态
|
||||
- 避免使用嵌套过深的状态结构
|
||||
- **Actions 设计**:
|
||||
- 处理异步操作
|
||||
- 使用 try/catch 捕获错误
|
||||
- 提交多个 mutations 时使用事务
|
||||
- **Getters 设计**:
|
||||
- 缓存计算结果
|
||||
- 避免在 getters 中修改状态
|
||||
- 合理使用参数化 getters
|
||||
|
||||
### 4. API 调用最佳实践
|
||||
|
||||
- **模块化管理**:按功能模块组织 API 接口
|
||||
- **请求封装**:
|
||||
- 统一处理请求头
|
||||
- 统一处理错误
|
||||
- 统一处理 loading 状态
|
||||
- **响应处理**:
|
||||
- 类型定义响应数据结构
|
||||
- 统一处理响应状态码
|
||||
- 合理处理空数据和边界情况
|
||||
- **请求优化**:
|
||||
- 使用防抖和节流
|
||||
- 缓存频繁请求的结果
|
||||
- 合理使用并发请求
|
||||
|
||||
### 5. 性能优化建议
|
||||
|
||||
- **代码分割**:使用路由懒加载和组件懒加载
|
||||
- **资源优化**:
|
||||
- 压缩图片和静态资源
|
||||
- 使用 WebP 格式图片
|
||||
- 合理使用 CDN
|
||||
- **渲染优化**:
|
||||
- 使用 `v-memo` 缓存计算结果
|
||||
- 合理使用 `v-if` 和 `v-show`
|
||||
- 避免在模板中使用复杂表达式
|
||||
- **网络优化**:
|
||||
- 使用 HTTP/2 或 HTTP/3
|
||||
- 启用 Gzip 或 Brotli 压缩
|
||||
- 合理设置缓存策略
|
||||
|
||||
### 6. 测试最佳实践
|
||||
|
||||
- **测试分层**:单元测试、集成测试、端到端测试
|
||||
- **测试覆盖率**:
|
||||
- 核心功能 100% 覆盖
|
||||
- 复杂逻辑 80% 以上覆盖
|
||||
- 简单功能 50% 以上覆盖
|
||||
- **测试工具**:
|
||||
- 使用 Vitest 进行单元测试
|
||||
- 使用 Playwright 进行端到端测试
|
||||
- 使用 Vue Test Utils 进行组件测试
|
||||
|
||||
### 7. 代码审查要点
|
||||
|
||||
- **类型安全**:检查 TypeScript 类型定义是否正确
|
||||
- **代码质量**:检查代码是否简洁、清晰
|
||||
- **性能问题**:检查是否存在性能瓶颈
|
||||
- **安全问题**:检查是否存在安全漏洞
|
||||
- **规范遵循**:检查是否遵循项目开发规范
|
||||
|
||||
## 🐍后端开发规范
|
||||
|
||||
### 1. 代码风格
|
||||
|
||||
#### 1.1 Python 规范
|
||||
|
||||
- 遵循 PEP 8 代码风格
|
||||
- 使用 4 个空格缩进
|
||||
- 行长度不超过 100 字符
|
||||
- 函数和类之间空两行
|
||||
- 方法之间空一行
|
||||
- 导入语句按标准库、第三方库、本地库分组
|
||||
|
||||
#### 1.2 FastAPI 规范
|
||||
|
||||
- 使用 FastAPI 装饰器定义路由
|
||||
- 使用 Pydantic 模型定义请求和响应数据
|
||||
- 使用依赖注入处理认证和权限
|
||||
- 使用路径参数和查询参数
|
||||
- 使用 HTTPException 处理错误
|
||||
- 使用 Depends 注入依赖
|
||||
|
||||
### 2. 目录结构
|
||||
|
||||
```
|
||||
backend/app/
|
||||
├── api/ # API 接口
|
||||
├── common/ # 公共代码
|
||||
├── config/ # 配置管理
|
||||
├── core/ # 核心功能
|
||||
├── plugin/ # 插件系统
|
||||
├── scripts/ # 脚本工具
|
||||
└── utils/ # 工具函数
|
||||
```
|
||||
|
||||
### 3. 插件开发规范
|
||||
|
||||
- 插件目录应该以 `module_` 开头
|
||||
- 插件应该包含 `controller.py`、`model.py`、`schema.py`、`service.py`、`crud.py` 等文件
|
||||
- 控制器应该使用 `APIRouter` 定义路由
|
||||
- 路由前缀应该与模块名对应(module_xxx -> /xxx)
|
||||
- 控制器应该使用 `OperationLogRoute` 记录操作日志
|
||||
- 接口应该使用 `AuthPermission` 进行权限控制
|
||||
|
||||
### 4. 数据库规范
|
||||
|
||||
- 使用 SQLAlchemy 2.0 ORM
|
||||
- 使用 Alembic 进行数据库迁移
|
||||
- 模型类应该继承自 `Base`
|
||||
- 模型类应该定义 `__tablename__` 属性
|
||||
- 字段命名应该使用 snake_case
|
||||
- 表名应该使用 snake_case 复数形式
|
||||
- 外键应该使用 `ForeignKey` 定义
|
||||
- 关系应该使用 `relationship` 定义
|
||||
|
||||
### 5. 认证和权限规范
|
||||
|
||||
- 使用 JWT 进行身份认证
|
||||
- 使用 RBAC 模型进行权限管理
|
||||
- 接口应该添加权限控制装饰器
|
||||
- 权限字符串格式:`module:controller:action`
|
||||
- 权限应该在角色管理中配置
|
||||
|
||||
### 6. 错误处理规范
|
||||
|
||||
- 使用 `HTTPException` 处理 HTTP 错误
|
||||
- 使用自定义异常处理全局错误
|
||||
- 错误响应应该有统一的格式
|
||||
- 错误应该记录到日志
|
||||
|
||||
### 7. 日志规范
|
||||
|
||||
- 使用 Python 标准库 `logging` 模块
|
||||
- 日志级别:DEBUG、INFO、WARNING、ERROR、CRITICAL
|
||||
- 日志应该包含时间、级别、模块、消息等信息
|
||||
- 关键操作应该记录日志
|
||||
- 错误应该记录详细信息
|
||||
|
||||
## 📦FastApp 移动端开发规范
|
||||
|
||||
### 1. 代码风格
|
||||
|
||||
- 遵循前端开发规范
|
||||
- 使用 TypeScript 严格模式
|
||||
- 使用 Vue 3 Composition API
|
||||
- 使用 `<script setup lang="ts">` 语法
|
||||
- 组件命名使用 PascalCase
|
||||
- 变量和函数命名使用 camelCase
|
||||
|
||||
### 2. 目录结构
|
||||
|
||||
```
|
||||
FastApp/src/
|
||||
├── api/ # API 接口
|
||||
├── components/ # 组件
|
||||
├── composables/ # 组合式函数
|
||||
├── constants/ # 常量定义
|
||||
├── enums/ # 枚举定义
|
||||
├── layouts/ # 布局组件
|
||||
├── pages/ # 页面文件
|
||||
├── router/ # 路由配置
|
||||
├── static/ # 静态资源
|
||||
├── store/ # 状态管理
|
||||
├── styles/ # 样式文件
|
||||
├── types/ # TypeScript 类型定义
|
||||
├── utils/ # 工具函数
|
||||
├── App.vue # 应用根组件
|
||||
└── main.ts # 应用入口文件
|
||||
```
|
||||
|
||||
### 3. 页面开发规范
|
||||
|
||||
- 页面组件应该放在 `pages` 目录下
|
||||
- 页面目录应该使用 kebab-case
|
||||
- 页面组件应该包含 `index.vue` 文件
|
||||
- 页面组件可以包含 `data.ts`、`types.ts` 等辅助文件
|
||||
- 页面组件应该使用 `onLoad()`、`onShow()` 等生命周期钩子
|
||||
- 页面跳转应该使用 `uni.navigateTo()`、`uni.switchTab()` 等 API
|
||||
|
||||
### 4. API 调用规范
|
||||
|
||||
- 遵循前端 API 调用规范
|
||||
- 使用封装的 `request.ts` 工具
|
||||
- API 接口应该按模块分类
|
||||
- API 调用应该处理错误情况
|
||||
- API 调用应该显示加载状态
|
||||
|
||||
### 5. 跨平台适配规范
|
||||
|
||||
- 使用条件编译处理平台差异
|
||||
- 使用 `#ifdef`、`#ifndef`、`#endif` 指令
|
||||
- 平台特有 API 应该添加条件编译
|
||||
- 样式应该考虑不同平台的差异
|
||||
- 布局应该使用 flexbox 确保跨平台一致性
|
||||
|
||||
## 🎯Git 提交规范
|
||||
|
||||
### 1. 分支管理
|
||||
|
||||
- `master`:主分支,用于发布生产版本
|
||||
- `dev`:开发分支,用于集成开发
|
||||
- `feature/xxx`:功能分支,用于开发新功能
|
||||
- `bugfix/xxx`:修复分支,用于修复 bug
|
||||
- `hotfix/xxx`:热修复分支,用于紧急修复生产环境问题
|
||||
|
||||
### 2. 提交信息规范
|
||||
|
||||
提交信息应该遵循以下格式:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
#### 2.1 Type
|
||||
|
||||
- `feat`:新功能
|
||||
- `fix`:修复 bug
|
||||
- `docs`:文档修改
|
||||
- `style`:代码风格修改
|
||||
- `refactor`:代码重构
|
||||
- `test`:测试代码修改
|
||||
- `chore`:构建工具或依赖修改
|
||||
- `revert`:回滚提交
|
||||
|
||||
#### 2.2 Scope
|
||||
|
||||
- 可选,用于指定修改的范围
|
||||
- 例如:`api`、`component`、`page`、`store` 等
|
||||
|
||||
#### 2.3 Subject
|
||||
|
||||
- 简短的提交信息,不超过 50 个字符
|
||||
- 使用祈使句,动词开头
|
||||
- 首字母小写
|
||||
- 不需要句号结尾
|
||||
|
||||
#### 2.4 Body
|
||||
|
||||
- 可选,详细的提交信息
|
||||
- 每行不超过 72 个字符
|
||||
- 解释为什么修改,而不是如何修改
|
||||
|
||||
#### 2.5 Footer
|
||||
|
||||
- 可选,用于引用 issue 或 BUG
|
||||
- 例如:`Closes #123`、`Fixes #456`
|
||||
|
||||
### 3. 提交示例
|
||||
|
||||
```
|
||||
feat(api): 添加用户登录接口
|
||||
|
||||
- 实现用户登录功能
|
||||
- 添加 JWT 认证
|
||||
- 处理登录错误情况
|
||||
|
||||
Closes #123
|
||||
```
|
||||
|
||||
```
|
||||
fix(frontend): 修复首页轮播图显示问题
|
||||
|
||||
- 修复轮播图高度计算错误
|
||||
- 优化轮播图切换动画
|
||||
|
||||
Fixes #456
|
||||
```
|
||||
|
||||
```
|
||||
docs: 更新开发文档
|
||||
|
||||
- 添加 API 文档说明
|
||||
- 完善部署指南
|
||||
```
|
||||
|
||||
### 4. Pull Request 规范
|
||||
|
||||
- Pull Request 应该从功能分支合并到 dev 分支
|
||||
- Pull Request 标题应该清晰、语义化
|
||||
- Pull Request 描述应该详细说明修改内容
|
||||
- Pull Request 应该包含相关的 issue 链接
|
||||
- Pull Request 应该通过所有测试
|
||||
- Pull Request 应该由至少一个 reviewer 审核
|
||||
|
||||
## 🔧工具链规范
|
||||
|
||||
### 1. 前端工具链
|
||||
|
||||
- 使用 Vite 作为构建工具
|
||||
- 使用 ESLint 进行代码检查
|
||||
- 使用 Prettier 进行代码格式化
|
||||
- 使用 Stylelint 进行样式检查
|
||||
- 使用 Husky 进行 Git 钩子管理
|
||||
- 使用 Commitlint 进行提交信息检查
|
||||
|
||||
### 2. 后端工具链
|
||||
|
||||
- 使用 Poetry 或 pip 管理依赖
|
||||
- 使用 Pylint 或 Flake8 进行代码检查
|
||||
- 使用 Black 进行代码格式化
|
||||
- 使用 MyPy 进行类型检查
|
||||
- 使用 pytest 进行测试
|
||||
|
||||
## 💡开发流程规范
|
||||
|
||||
### 1. 需求分析
|
||||
|
||||
- 明确功能需求
|
||||
- 分析业务逻辑
|
||||
- 确定技术方案
|
||||
|
||||
### 2. 设计阶段
|
||||
|
||||
- 设计数据库表结构
|
||||
- 设计 API 接口
|
||||
- 设计前端页面
|
||||
- 设计组件结构
|
||||
|
||||
### 3. 开发阶段
|
||||
|
||||
- 创建分支
|
||||
- 实现功能
|
||||
- 编写测试
|
||||
- 运行测试
|
||||
|
||||
### 4. 测试阶段
|
||||
|
||||
- 单元测试
|
||||
- 集成测试
|
||||
- 端到端测试
|
||||
- 性能测试
|
||||
|
||||
### 5. 部署阶段
|
||||
|
||||
- 构建生产版本
|
||||
- 部署到测试环境
|
||||
- 进行回归测试
|
||||
- 部署到生产环境
|
||||
|
||||
### 6. 维护阶段
|
||||
|
||||
- 监控系统运行状态
|
||||
- 处理 bug 和问题
|
||||
- 进行性能优化
|
||||
- 进行功能迭代
|
||||
|
||||
## 📚参考资料
|
||||
|
||||
- [TypeScript 官方文档](https://www.typescriptlang.org/docs/)
|
||||
- [Vue 官方文档](https://vuejs.org/docs/)
|
||||
- [FastAPI 官方文档](https://fastapi.tiangolo.com/)
|
||||
- [SQLAlchemy 官方文档](https://docs.sqlalchemy.org/)
|
||||
- [PEP 8 代码风格指南](https://peps.python.org/pep-0008/)
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
- [ESLint 官方文档](https://eslint.org/docs/)
|
||||
- [Prettier 官方文档](https://prettier.io/docs/en/)
|
||||
|
||||
## 🤝贡献指南
|
||||
|
||||
如果您对开发规范有任何建议或改进意见,欢迎提交 Issue 或 Pull Request。我们会认真考虑每一个建议,不断完善开发规范。
|
||||
|
||||
## 📄许可协议
|
||||
|
||||
本开发规范文档采用 MIT 许可协议,与 FastapiAdmin 项目保持一致。
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
|
||||
layout: home
|
||||
editLink: true
|
||||
lastUpdated: true
|
||||
|
||||
hero:
|
||||
name: "FastApiAdmin"
|
||||
text: "现代、开源、全栈融合的快速开发平台"
|
||||
tagline: 基于 FastAPI + Vue3 + TypeScript 构建的企业级中后台解决方案,支持多端开发
|
||||
image:
|
||||
src: logo.png
|
||||
alt: FastApiAdmin
|
||||
style:
|
||||
borderRadius: 50%
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
link: /start
|
||||
- theme: alt
|
||||
text: 在线演示
|
||||
link: https://service.fastapiadmin.com/web
|
||||
target: _blank
|
||||
- theme: alt
|
||||
text: 小程序演示
|
||||
link: https://service.fastapiadmin.com/app
|
||||
target: _blank
|
||||
|
||||
features:
|
||||
- icon: �️
|
||||
title: 全栈整合
|
||||
details: 前后端分离架构,融合 Python (FastAPI) + Vue3 + TypeScript 实现多端统一开发,提供一站式开箱即用体验。
|
||||
|
||||
- icon: 🧱
|
||||
title: 模块化设计
|
||||
details: 系统功能高度解耦,便于扩展和维护,遵循开发规范和设计模式,支持插件化开发。
|
||||
|
||||
- icon: ⚡️
|
||||
title: 高性能异步
|
||||
details: 使用 FastAPI 异步框架 + Redis 缓存优化接口响应速度,提升系统性能,支持高并发场景。
|
||||
|
||||
- icon: 🔒
|
||||
title: 安全认证
|
||||
details: 支持 JWT OAuth2 认证机制,RBAC 模型实现菜单、按钮、数据级别的细粒度权限控制,保障系统安全。
|
||||
|
||||
- icon: 🚀
|
||||
title: 快速部署
|
||||
details: 支持 Docker/Docker Compose/Nginx 一键部署,降低运维成本,支持多环境配置管理。
|
||||
|
||||
- icon: 📊
|
||||
title: 丰富的内置模块
|
||||
details: 包含系统管理、监控管理、公共管理等多个核心模块,满足企业级应用需求。
|
||||
|
||||
- icon: 🎨
|
||||
title: 美观的 UI 设计
|
||||
details: 基于 ElementPlus 和 Wot Design Uni 构建,提供现代化、响应式的用户界面。
|
||||
|
||||
- icon: 📖
|
||||
title: 完善的文档
|
||||
details: 提供详尽的中文开发文档和使用指南,降低学习成本,加速项目落地。
|
||||
@@ -0,0 +1,815 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: FastApp 移动端开发指南
|
||||
---
|
||||
# FastApp 移动端开发指南
|
||||
|
||||
## 📱项目概述
|
||||
|
||||
**FastApp** 是 FastapiAdmin 项目的移动端应用,基于 **Uni App** 框架开发,支持一套代码多端运行(包括 H5、微信小程序、支付宝小程序、App 等)。采用 Vue 3 + TypeScript + Vite 等现代化技术栈,集成了完善的代码规范和开发工具链,为开发者提供开箱即用的移动端开发解决方案。
|
||||
|
||||
### 核心功能
|
||||
|
||||
- **用户认证**:登录、注册、密码重置、权限管理
|
||||
- **首页展示**:轮播图、快捷导航、通知公告、数据统计
|
||||
- **工作台**:业务功能入口,支持权限控制
|
||||
- **个人中心**:个人信息、设置、FAQ、问题反馈
|
||||
- **数据统计**:实时访客数、浏览量等数据展示
|
||||
- **主题切换**:支持深色/浅色主题切换
|
||||
|
||||
### 系统功能特性
|
||||
|
||||
- 🔐 **用户管理** - 支持用户注册、登录、权限管理等功能,提供完善的用户体系
|
||||
- 📊 **数据统计** - 提供实时数据分析和可视化报表,帮助您更好地了解业务状况
|
||||
- 📁 **文件管理** - 支持文件上传、下载、分类管理,提供安全的文件存储服务
|
||||
- 🔔 **消息通知** - 实时消息推送和系统通知,确保您不会错过重要信息
|
||||
- 🛡️ **权限控制** - 基于RBAC的权限管理模型,灵活控制用户访问权限
|
||||
- 📝 **日志审计** - 完整的操作日志记录,便于追踪和审计用户行为
|
||||
|
||||
## 🛠️技术栈
|
||||
|
||||
| 技术 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Uni App | 3.0.0+ | 跨平台移动端开发框架 |
|
||||
| Vue3 | 3.5.22+ | 前端框架(Composition API) |
|
||||
| TypeScript | 5.9.2+ | 类型系统 |
|
||||
| Vite | 6.0+ | 构建工具 |
|
||||
| Pinia | 2.1+ | 状态管理 |
|
||||
| Wot Design Uni | 1.9.1+ | UI 组件库 |
|
||||
| UnoCSS | 0.58+ | 原子化 CSS 引擎 |
|
||||
| VueUse | 10.7+ | Vue Composition API 工具集合 |
|
||||
| @stomp/stompjs | 7.0+ | WebSocket 消息协议库 |
|
||||
|
||||
## 📁项目结构
|
||||
|
||||
```
|
||||
FastApp/
|
||||
├─ public/ # 静态资源
|
||||
│ └─ favicon.png # 网站图标
|
||||
├─ src/ # 源代码
|
||||
│ ├─ api/ # API 接口
|
||||
│ │ ├─ auth.ts # 认证相关接口
|
||||
│ │ ├─ file.ts # 文件相关接口
|
||||
│ │ └─ user.ts # 用户相关接口
|
||||
│ ├─ components/ # 组件
|
||||
│ │ ├─ cu-date-query/ # 日期查询组件
|
||||
│ │ ├─ cu-picker/ # 选择器组件
|
||||
│ │ ├─ qiun-error/ # 错误提示组件
|
||||
│ │ └─ qiun-loading/ # 加载组件
|
||||
│ ├─ composables/ # 组合式函数
|
||||
│ │ ├─ useNavigationBar.ts # 导航栏管理
|
||||
│ │ ├─ useStomp.ts # WebSocket 管理
|
||||
│ │ └─ useTabbar.ts # 标签栏管理
|
||||
│ ├─ constants/ # 常量定义
|
||||
│ │ ├─ index.ts # 常量定义
|
||||
│ │ └─ storage.constant.ts # 存储键名
|
||||
│ ├─ enums/ # 枚举定义
|
||||
│ │ ├─ api-code.enum.ts # API 错误码
|
||||
│ │ └─ api-header.enum.ts # API 头部
|
||||
│ ├─ layouts/ # 布局组件
|
||||
│ │ ├─ default.vue # 默认布局
|
||||
│ │ └─ tabbar.vue # 标签栏布局
|
||||
│ ├─ pages/ # 页面文件
|
||||
│ │ ├─ index/ # 首页
|
||||
│ │ │ ├─ data.ts # 数据定义
|
||||
│ │ │ ├─ index.vue # 首页组件
|
||||
│ │ │ └─ types.ts # 类型定义
|
||||
│ │ ├─ login/ # 登录页
|
||||
│ │ │ └─ index.vue # 登录组件
|
||||
│ │ ├─ mine/ # 个人中心
|
||||
│ │ │ ├─ about/ # 关于页面
|
||||
│ │ │ ├─ faq/ # FAQ页面
|
||||
│ │ │ ├─ feedback/ # 反馈页面
|
||||
│ │ │ ├─ profile/ # 个人资料
|
||||
│ │ │ ├─ settings/ # 设置页面
|
||||
│ │ │ └─ index.vue # 个人中心组件
|
||||
│ │ └─ work/ # 工作台
|
||||
│ │ ├─ data.ts # 数据定义
|
||||
│ │ ├─ index.vue # 工作台组件
|
||||
│ │ └─ types.ts # 类型定义
|
||||
│ ├─ router/ # 路由配置
|
||||
│ │ └─ index.ts # 路由配置文件
|
||||
│ ├─ static/ # 静态资源
|
||||
│ │ ├─ icons/ # 图标
|
||||
│ │ ├─ images/ # 图片
|
||||
│ │ └─ logo.png # Logo
|
||||
│ ├─ store/ # 状态管理
|
||||
│ │ ├─ modules/ # 模块
|
||||
│ │ │ ├─ theme.store.ts # 主题管理
|
||||
│ │ │ └─ user.store.ts # 用户管理
|
||||
│ │ └─ index.ts # 状态管理配置
|
||||
│ ├─ styles/ # 样式文件
|
||||
│ │ └─ index.scss # 全局样式
|
||||
│ ├─ types/ # TypeScript 类型定义
|
||||
│ ├─ utils/ # 工具函数
|
||||
│ │ ├─ auth.ts # 认证工具
|
||||
│ │ ├─ color.ts # 颜色工具
|
||||
│ │ ├─ index.ts # 工具函数
|
||||
│ │ ├─ request.ts # 请求工具
|
||||
│ │ └─ storage.ts # 存储工具
|
||||
│ ├─ App.vue # 应用根组件
|
||||
│ ├─ main.ts # 应用入口文件
|
||||
│ ├─ manifest.json # 应用配置文件
|
||||
│ ├─ pages.json # 页面路由配置
|
||||
│ └─ theme.json # 主题配置
|
||||
├─ .env.development # 开发环境配置
|
||||
├─ .env.production # 生产环境配置
|
||||
├─ package.json # 项目依赖
|
||||
├─ pages.config.ts # 页面配置
|
||||
├─ tsconfig.json # TypeScript 配置
|
||||
├─ unocss.config.ts # UnoCSS 配置
|
||||
└─ vite.config.ts # Vite 配置
|
||||
```
|
||||
|
||||
## 🔧环境搭建
|
||||
|
||||
### 1. 环境要求
|
||||
|
||||
- **Node.js** >= 22
|
||||
- **pnpm** >= 9
|
||||
|
||||
### 2. 安装依赖
|
||||
|
||||
```sh
|
||||
# 进入项目目录
|
||||
cd FastApp
|
||||
|
||||
# 安装项目依赖
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 3. 配置环境变量
|
||||
|
||||
在项目根目录创建 `.env` 文件配置环境变量:
|
||||
|
||||
```bash
|
||||
# API 基础地址
|
||||
VITE_API_BASE_URL=http://localhost:8001
|
||||
|
||||
# API 前缀
|
||||
VITE_APP_BASE_API=/api
|
||||
|
||||
# 开发服务器端口
|
||||
VITE_APP_PORT=5180
|
||||
```
|
||||
|
||||
## 🚀开发流程
|
||||
|
||||
### 1. 启动开发服务器
|
||||
|
||||
#### H5 开发
|
||||
|
||||
```sh
|
||||
# 启动 H5 开发服务器
|
||||
pnpm run dev:h5
|
||||
|
||||
# 访问地址
|
||||
# http://localhost:5180/app
|
||||
```
|
||||
|
||||
#### 微信小程序开发
|
||||
|
||||
```sh
|
||||
# 启动微信小程序开发服务器
|
||||
pnpm run dev:mp-weixin
|
||||
|
||||
# 在微信开发者工具中导入项目目录:FastApp/dist/dev/mp-weixin
|
||||
```
|
||||
|
||||
#### 其他平台开发
|
||||
|
||||
```sh
|
||||
# 启动支付宝小程序开发服务器
|
||||
pnpm run dev:mp-alipay
|
||||
|
||||
# 启动百度小程序开发服务器
|
||||
pnpm run dev:mp-baidu
|
||||
|
||||
# 启动字节跳动小程序开发服务器
|
||||
pnpm run dev:mp-toutiao
|
||||
|
||||
# 启动 QQ 小程序开发服务器
|
||||
pnpm run dev:mp-qq
|
||||
```
|
||||
|
||||
## 📚页面开发
|
||||
|
||||
### 1. 创建新页面
|
||||
|
||||
1. **在 `pages.json` 中添加页面配置**:
|
||||
|
||||
```json
|
||||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页"
|
||||
}
|
||||
},
|
||||
// 其他页面...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
2. **创建页面文件**:
|
||||
|
||||
```
|
||||
FastApp/src/pages/
|
||||
└─ new-page/
|
||||
├─ index.vue # 页面组件
|
||||
├─ data.ts # 数据定义(可选)
|
||||
└─ types.ts # 类型定义(可选)
|
||||
```
|
||||
|
||||
3. **页面示例**:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="page">
|
||||
<view class="title">新页面</view>
|
||||
<view class="content">
|
||||
<text>{{ message }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
const message = ref('Hello FastApp!');
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 2. 路由管理
|
||||
|
||||
#### 页面跳转
|
||||
|
||||
```typescript
|
||||
// 普通跳转
|
||||
uni.navigateTo({
|
||||
url: '/pages/new-page/index'
|
||||
});
|
||||
|
||||
// 带参数跳转
|
||||
uni.navigateTo({
|
||||
url: '/pages/new-page/index?id=1&name=test'
|
||||
});
|
||||
|
||||
// 重定向跳转
|
||||
uni.redirectTo({
|
||||
url: '/pages/new-page/index'
|
||||
});
|
||||
|
||||
// 跳转到 tabBar 页面
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
|
||||
// 关闭所有页面,打开新页面
|
||||
uni.reLaunch({
|
||||
url: '/pages/new-page/index'
|
||||
});
|
||||
```
|
||||
|
||||
#### 接收参数
|
||||
|
||||
```typescript
|
||||
// 在页面 onLoad 生命周期中接收参数
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
onLoad((options) => {
|
||||
console.log('参数:', options);
|
||||
// options.id, options.name
|
||||
});
|
||||
```
|
||||
|
||||
## 📡API 调用
|
||||
|
||||
### 1. 封装的 API 工具
|
||||
|
||||
FastApp 使用封装的 `request.ts` 工具进行 API 调用,支持自动添加认证 token、错误处理等功能。
|
||||
|
||||
### 2. API 接口定义
|
||||
|
||||
API 接口定义在 `src/api` 目录下,按模块分类:
|
||||
|
||||
```typescript
|
||||
// src/api/user.ts 示例
|
||||
import request from '../utils/request';
|
||||
|
||||
export const userApi = {
|
||||
// 获取用户信息
|
||||
getUserInfo: () => {
|
||||
return request({
|
||||
url: '/api/v1/user/info',
|
||||
method: 'GET'
|
||||
});
|
||||
},
|
||||
|
||||
// 更新用户信息
|
||||
updateUserInfo: (data: any) => {
|
||||
return request({
|
||||
url: '/api/v1/user/update',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 调用 API
|
||||
|
||||
```typescript
|
||||
import { userApi } from '../api/user';
|
||||
|
||||
// 调用 API
|
||||
const getUserInfo = async () => {
|
||||
try {
|
||||
const res = await userApi.getUserInfo();
|
||||
console.log('用户信息:', res.data);
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 调用更新用户信息 API
|
||||
const updateUser = async () => {
|
||||
try {
|
||||
const res = await userApi.updateUserInfo({
|
||||
name: '新名字',
|
||||
avatar: '新头像'
|
||||
});
|
||||
console.log('更新成功:', res.data);
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 4. WebSocket 实时通信
|
||||
|
||||
FastApp 集成了 `@stomp/stompjs` 库,支持 WebSocket 实时通信,通过封装的 `useStomp` 组合式函数可以方便地使用:
|
||||
|
||||
```typescript
|
||||
// 使用 WebSocket
|
||||
import { useStomp } from '../composables/useStomp';
|
||||
|
||||
const {
|
||||
connect,
|
||||
disconnect,
|
||||
subscribe,
|
||||
send,
|
||||
isConnected
|
||||
} = useStomp();
|
||||
|
||||
// 连接 WebSocket
|
||||
const initWebSocket = () => {
|
||||
connect({
|
||||
url: 'ws://localhost:8001/ws',
|
||||
onConnect: () => {
|
||||
console.log('WebSocket 连接成功');
|
||||
// 订阅消息
|
||||
subscribe('/topic/messages', (message) => {
|
||||
console.log('收到消息:', message);
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('WebSocket 连接失败:', error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 发送消息
|
||||
const sendMessage = () => {
|
||||
if (isConnected.value) {
|
||||
send('/app/message', {
|
||||
content: 'Hello WebSocket!'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 断开连接
|
||||
const closeWebSocket = () => {
|
||||
disconnect();
|
||||
};
|
||||
```
|
||||
|
||||
## 🔐认证管理
|
||||
|
||||
### 1. 登录流程
|
||||
|
||||
```typescript
|
||||
import { authApi } from '../api/auth';
|
||||
import { useUserStore } from '../store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
try {
|
||||
const res = await authApi.login({
|
||||
username,
|
||||
password
|
||||
});
|
||||
|
||||
// 保存 token
|
||||
userStore.setToken(res.data.token);
|
||||
|
||||
// 获取用户信息
|
||||
await userStore.getUserInfo();
|
||||
|
||||
// 跳转到首页
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 登出流程
|
||||
|
||||
```typescript
|
||||
import { useUserStore } from '../store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const logout = () => {
|
||||
// 清除 token 和用户信息
|
||||
userStore.logout();
|
||||
|
||||
// 跳转到登录页
|
||||
uni.redirectTo({ url: '/pages/login/index' });
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 权限控制
|
||||
|
||||
可以使用全局路由守卫或页面级权限检查来实现权限控制:
|
||||
|
||||
```typescript
|
||||
// 在页面 onLoad 中检查权限
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { useUserStore } from '../store/modules/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
onLoad(() => {
|
||||
// 检查是否登录
|
||||
if (!userStore.token) {
|
||||
uni.redirectTo({ url: '/pages/login/index' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查用户权限
|
||||
if (!userStore.hasPermission('required_permission')) {
|
||||
uni.showToast({
|
||||
title: '权限不足',
|
||||
icon: 'none'
|
||||
});
|
||||
uni.navigateBack();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 🎨UI 组件
|
||||
|
||||
### 1. 使用 Wot Design Uni
|
||||
|
||||
FastApp 使用 **Wot Design Uni** 作为 UI 组件库,提供了丰富的移动端组件:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 按钮 -->
|
||||
<wd-button type="primary" @click="handleClick">主要按钮</wd-button>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<wd-input v-model="value" placeholder="请输入内容" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<wd-list>
|
||||
<wd-list-item title="标题" value="值" />
|
||||
<wd-list-item title="标题2" value="值2" />
|
||||
</wd-list>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<wd-popup v-model:visible="popupVisible" title="弹窗标题">
|
||||
<view>弹窗内容</view>
|
||||
</wd-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
const value = ref('');
|
||||
const popupVisible = ref(false);
|
||||
|
||||
const handleClick = () => {
|
||||
popupVisible.value = true;
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
### 2. 使用 UnoCSS
|
||||
|
||||
FastApp 集成了 UnoCSS 原子化 CSS 引擎,支持类名方式快速开发:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="flex flex-col items-center p-4">
|
||||
<view class="text-xl font-bold mb-4">Hello FastApp</view>
|
||||
<view class="w-full max-w-md bg-white rounded-lg shadow-md p-4">
|
||||
<view class="text-gray-700">Welcome to FastApp</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 3. 自定义组件
|
||||
|
||||
可以在 `src/components` 目录下创建自定义组件:
|
||||
|
||||
```vue
|
||||
<!-- src/components/custom-button.vue -->
|
||||
<template>
|
||||
<view class="custom-button" @click="$emit('click')">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineEmits(['click']);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.custom-button {
|
||||
padding: 12rpx 24rpx;
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 📱多平台适配
|
||||
|
||||
### 1. 条件编译
|
||||
|
||||
使用 Uni App 的条件编译语法,可以为不同平台编写不同的代码:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view>
|
||||
<!-- #ifdef H5 -->
|
||||
<view>这是 H5 平台的内容</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view>这是微信小程序平台的内容</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view>这是 App 平台的内容</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// #ifdef H5
|
||||
console.log('H5 平台');
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
console.log('微信小程序平台');
|
||||
// #endif
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* #ifdef H5 */
|
||||
.view {
|
||||
font-size: 16px;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.view {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
```
|
||||
|
||||
### 2. 平台特有 API
|
||||
|
||||
使用平台特有 API 时,需要注意添加条件编译:
|
||||
|
||||
```typescript
|
||||
// 调用微信小程序特有 API
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.getLocation({
|
||||
type: 'wgs84',
|
||||
success: (res) => {
|
||||
console.log('位置信息:', res);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// 调用 App 特有 API
|
||||
// #ifdef APP-PLUS
|
||||
plus.device.getInfo({
|
||||
success: (info) => {
|
||||
console.log('设备信息:', info);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
```
|
||||
|
||||
## 🚀性能优化
|
||||
|
||||
### 1. 代码优化
|
||||
|
||||
- **减少页面层级**:尽量减少页面嵌套层级,最多不超过 5 层
|
||||
- **按需加载**:使用分包加载、组件按需导入等方式减少初始包大小
|
||||
- **避免频繁更新**:使用 `nextTick` 合并更新,避免频繁触发渲染
|
||||
- **使用虚拟列表**:长列表使用虚拟列表,避免一次性渲染过多数据
|
||||
|
||||
### 2. 网络优化
|
||||
|
||||
- **缓存数据**:使用本地存储缓存不常变化的数据
|
||||
- **请求合并**:合并多个请求,减少网络请求次数
|
||||
- **延迟加载**:非关键资源延迟加载
|
||||
- **使用 WebSocket**:实时数据使用 WebSocket,减少轮询
|
||||
|
||||
### 3. 存储优化
|
||||
|
||||
- **合理使用本地存储**:根据数据类型选择合适的存储方式(localStorage、sessionStorage、IndexedDB)
|
||||
- **清理过期数据**:定期清理过期或无用的数据
|
||||
- **加密敏感数据**:敏感数据(如 token)进行加密存储
|
||||
|
||||
## 📦打包发布
|
||||
|
||||
### 1. 构建生产版本
|
||||
|
||||
#### H5 构建
|
||||
|
||||
```bash
|
||||
pnpm run build:h5
|
||||
|
||||
# 构建产物在 dist/build/h5 目录
|
||||
```
|
||||
|
||||
#### 微信小程序构建
|
||||
|
||||
```bash
|
||||
pnpm run build:mp-weixin
|
||||
|
||||
# 构建产物在 dist/build/mp-weixin 目录
|
||||
```
|
||||
|
||||
#### 其他平台构建
|
||||
|
||||
```bash
|
||||
# 构建支付宝小程序
|
||||
pnpm run build:mp-alipay
|
||||
|
||||
# 构建百度小程序
|
||||
pnpm run build:mp-baidu
|
||||
|
||||
# 构建字节跳动小程序
|
||||
pnpm run build:mp-toutiao
|
||||
|
||||
# 构建 QQ 小程序
|
||||
pnpm run build:mp-qq
|
||||
```
|
||||
|
||||
### 2. 发布流程
|
||||
|
||||
#### H5 部署
|
||||
|
||||
1. 执行构建命令:`pnpm run build:h5`
|
||||
2. 将 `dist/build/h5` 目录部署到 Web 服务器
|
||||
3. 配置服务器支持 SPA 路由(如 Nginx 的 `try_files`)
|
||||
|
||||
#### 小程序发布
|
||||
|
||||
1. 执行对应平台的构建命令
|
||||
2. 使用对应平台的开发者工具打开构建产物目录
|
||||
3. 在开发者工具中上传代码并提交审核
|
||||
|
||||
#### App 打包
|
||||
|
||||
1. 使用 HBuilderX 打开项目
|
||||
2. 配置 App 相关信息(图标、启动页等)
|
||||
3. 选择云打包或本地打包
|
||||
4. 下载安装包并发布到应用商店
|
||||
|
||||
## 🐛常见问题及解决方案
|
||||
|
||||
### 1. 开发环境问题
|
||||
|
||||
**问题**:H5 开发时跨域错误
|
||||
**解决方案**:在 `vite.config.ts` 中配置代理:
|
||||
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
proxy: {
|
||||
[env.VITE_APP_BASE_API]: {
|
||||
changeOrigin: true,
|
||||
target: env.VITE_API_BASE_URL,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**问题**:微信小程序开发时 API 请求失败
|
||||
**解决方案**:在微信公众平台设置合法域名,或在开发者工具中开启「不校验合法域名」选项。
|
||||
|
||||
### 2. 运行时问题
|
||||
|
||||
**问题**:页面白屏
|
||||
**解决方案**:检查是否有语法错误、API 调用错误,查看控制台日志。
|
||||
|
||||
**问题**:数据加载失败
|
||||
**解决方案**:检查网络连接,API 地址是否正确,后端服务是否正常。
|
||||
|
||||
**问题**:样式错乱
|
||||
**解决方案**:检查样式代码,使用条件编译适配不同平台。
|
||||
|
||||
### 3. 发布问题
|
||||
|
||||
**问题**:微信小程序审核失败
|
||||
**解决方案**:根据审核反馈修改代码,确保符合微信小程序规范。
|
||||
|
||||
**问题**:包大小超过限制
|
||||
**解决方案**:使用分包加载、按需导入组件、压缩资源等方式减少包大小。
|
||||
|
||||
## 📚代码规范
|
||||
|
||||
项目集成了完善的代码规范工具:
|
||||
|
||||
```bash
|
||||
# ESLint 检查并自动修复
|
||||
pnpm run lint:eslint
|
||||
|
||||
# Prettier 格式化
|
||||
pnpm run lint:prettier
|
||||
|
||||
# Stylelint 检查样式
|
||||
pnpm run lint:stylelint
|
||||
|
||||
# TypeScript 类型检查
|
||||
pnpm run type-check
|
||||
```
|
||||
|
||||
## 📚自动导入
|
||||
|
||||
项目配置了自动导入,以下内容无需手动导入:
|
||||
|
||||
- Vue 3 API(`ref`, `computed`, `watch` 等)
|
||||
- uni-app API(`uni.request`, `uni.navigateTo` 等)
|
||||
- Pinia(`defineStore`, `storeToRefs` 等)
|
||||
- 路由(`useRouter`, `useRoute` 等)
|
||||
- 组件库工具(`useToast`, `useMessage` 等)
|
||||
- `src/composables` 目录下的组合式函数
|
||||
- `src/utils` 目录下的工具函数
|
||||
- `src/api` 目录下的 API 函数
|
||||
|
||||
## 📚参考文档
|
||||
|
||||
- **Uni App 官方文档**:[https://uniapp.dcloud.io/](https://uniapp.dcloud.io/)
|
||||
- **Wot Design Uni 文档**:[https://wot-design-uni.webapp.plus/](https://wot-design-uni.webapp.plus/)
|
||||
- **Vue3 官方文档**:[https://cn.vuejs.org/](https://cn.vuejs.org/)
|
||||
- **TypeScript 官方文档**:[https://www.typescriptlang.org/](https://www.typescriptlang.org/)
|
||||
- **微信小程序开发文档**:[https://developers.weixin.qq.com/miniprogram/dev/framework/](https://developers.weixin.qq.com/miniprogram/dev/framework/)
|
||||
|
||||
## 🤝贡献指南
|
||||
|
||||
欢迎为 FastApp 项目贡献代码!请遵循以下步骤:
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
||||
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||
5. 开启 Pull Request
|
||||
|
||||
## 📄许可协议
|
||||
|
||||
FastApp 项目采用 MIT 许可协议,详见 [LICENSE](https://github.com/fastapiadmin/FastApp/blob/master/LICENSE) 文件。
|
||||
@@ -0,0 +1,254 @@
|
||||
---
|
||||
title: 项目概述
|
||||
outline: "deep"
|
||||
---
|
||||
|
||||
<div style="text-align: center;">
|
||||
<div align="center">
|
||||
<img src="/logo.png" width="150" height="150" alt="logo" />
|
||||
</div>
|
||||
<h1>FastApiAdmin <sup style="background-color: #28a745; color: white; padding: 2px 6px; border-radius: 3px; font-size: 0.4em; vertical-align: super; margin-left: 5px;">v2.0.0</sup></h1>
|
||||
<h3>一套现代、开源、全栈融合的中后台快速开发平台</h3>
|
||||
<p>如果你喜欢这个项目,给个 ⭐️ 支持一下吧!</p>
|
||||
<p align="center" style="display: flex; justify-content: center; align-items: center; margin-top: 10px;">
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin"><img src="https://gitee.com/fastapiadmin/FastapiAdmin/badge/star.svg?theme=dark" alt="Gitee Stars"></a>
|
||||
<a href="https://github.com/fastapiadmin/FastapiAdmin"><img src="https://img.shields.io/github/stars/fastapiadmin/FastapiAdmin?style=social" alt="GitHub Stars"></a>
|
||||
<a href="https://github.com/fastapiadmin/FastApp"><img src="https://img.shields.io/github/stars/fastapiadmin/FastApp?style=social" alt="FastApp Stars"></a>
|
||||
<a href="https://github.com/fastapiadmin/FastDocs"><img src="https://img.shields.io/github/stars/fastapiadmin/FastDocs?style=social" alt="FastDocs Stars"></a>
|
||||
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-orange.svg" alt="License"></a>
|
||||
<img src="https://img.shields.io/badge/Python-≥3.10-blue" alt="Python">
|
||||
<img src="https://img.shields.io/badge/NodeJS-≥20.0-blue" alt="NodeJS">
|
||||
<img src="https://img.shields.io/badge/MySQL-≥8.0-blue" alt="MySQL">
|
||||
<img src="https://img.shields.io/badge/Redis-≥7.0-blue" alt="Redis">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## 📘项目介绍
|
||||
|
||||
**FastApiAdmin** 是一套 **完全开源、高度模块化、技术先进的现代化快速开发平台**,旨在帮助开发者高效搭建高质量的企业级中后台系统。该项目采用 **前后端分离架构**,融合 Python 后端框架 `FastAPI` 和前端主流框架 `Vue3` 实现多端统一开发,提供了一站式开箱即用的开发体验。
|
||||
|
||||
> **设计初心**: 以模块化、松耦合为核心,追求丰富的功能模块、简洁易用的接口、详尽的开发文档和便捷的维护方式。通过统一框架和组件,降低技术选型成本,遵循开发规范和设计模式,构建强大的代码分层模型,搭配完善的本地中文化支持,专为团队和企业开发场景量身定制。
|
||||
|
||||
## 📦工程结构概览
|
||||
|
||||
项目已拆分为三个独立的仓库,便于独立开发和维护:
|
||||
|
||||
### 1. FastapiAdmin 主工程
|
||||
|
||||
```sh
|
||||
FastapiAdmin/
|
||||
├─ backend/ # 后端工程
|
||||
│ ├─ app/ # 应用核心代码
|
||||
│ │ ├─ api/ # API 接口
|
||||
│ │ │ └─ v1/ # API 版本
|
||||
│ │ │ ├─ module_common/ # 公共模块
|
||||
│ │ │ ├─ module_monitor/ # 监控模块
|
||||
│ │ │ └─ module_system/ # 系统模块
|
||||
│ │ ├─ common/ # 公共代码
|
||||
│ │ ├─ config/ # 配置管理
|
||||
│ │ ├─ core/ # 核心功能
|
||||
│ │ ├─ plugin/ # 插件系统
|
||||
│ │ │ ├─ module_application/ # 应用模块
|
||||
│ │ │ ├─ module_example/ # 示例模块
|
||||
│ │ │ └─ module_generator/ # 代码生成模块
|
||||
│ │ ├─ scripts/ # 脚本工具
|
||||
│ │ └─ utils/ # 工具函数
|
||||
│ ├─ alembic/ # 数据库迁移
|
||||
│ ├─ env/ # 环境配置
|
||||
│ ├─ static/ # 静态资源
|
||||
│ ├─ tests/ # 测试代码
|
||||
│ ├─ README.md # 后端文档
|
||||
│ ├─ main.py # 后端入口
|
||||
│ └─ requirements.txt # Python 依赖
|
||||
├─ frontend/ # 前端工程
|
||||
│ ├─ src/ # 源代码
|
||||
│ │ ├─ api/ # API 接口
|
||||
│ │ ├─ assets/ # 资源文件
|
||||
│ │ ├─ components/ # 组件
|
||||
│ │ ├─ composables/ # 组合式函数
|
||||
│ │ ├─ constants/ # 常量定义
|
||||
│ │ ├─ directives/ # 指令
|
||||
│ │ ├─ enums/ # 枚举定义
|
||||
│ │ ├─ lang/ # 国际化
|
||||
│ │ ├─ layouts/ # 布局
|
||||
│ │ ├─ plugins/ # 插件
|
||||
│ │ ├─ router/ # 路由
|
||||
│ │ ├─ store/ # 状态管理
|
||||
│ │ ├─ styles/ # 样式
|
||||
│ │ ├─ types/ # 类型定义
|
||||
│ │ ├─ utils/ # 工具函数
|
||||
│ │ └─ views/ # 页面
|
||||
│ ├─ public/ # 静态资源
|
||||
│ ├─ package.json # 前端依赖
|
||||
│ └─ README.md # 前端文档
|
||||
├─ devops/ # 部署工程
|
||||
│ ├─ backend/ # 后端部署配置
|
||||
│ ├─ nginx/ # Nginx 配置
|
||||
│ └─ redis/ # Redis 配置
|
||||
├─ docker-compose.yaml # 部署文件
|
||||
├─ deploy.sh # 部署脚本
|
||||
├─ LICENSE # 许可协议
|
||||
└─ README.md # 项目文档
|
||||
```
|
||||
|
||||
### 2. FastApp 移动端
|
||||
|
||||
```sh
|
||||
FastApp/
|
||||
├─ src/ # 源代码目录
|
||||
│ ├─ api/ # API 接口
|
||||
│ │ ├─ auth.ts # 认证相关接口
|
||||
│ │ ├─ file.ts # 文件相关接口
|
||||
│ │ └─ user.ts # 用户相关接口
|
||||
│ ├─ components/ # 组件
|
||||
│ │ ├─ cu-date-query/ # 日期查询组件
|
||||
│ │ ├─ cu-picker/ # 选择器组件
|
||||
│ │ ├─ qiun-error/ # 错误提示组件
|
||||
│ │ └─ qiun-loading/ # 加载组件
|
||||
│ ├─ composables/ # 组合式函数
|
||||
│ │ ├─ useNavigationBar.ts # 导航栏管理
|
||||
│ │ ├─ useStomp.ts # WebSocket 管理
|
||||
│ │ └─ useTabbar.ts # 标签栏管理
|
||||
│ ├─ constants/ # 常量定义
|
||||
│ │ ├─ index.ts # 常量定义
|
||||
│ │ └─ storage.constant.ts # 存储键名
|
||||
│ ├─ enums/ # 枚举定义
|
||||
│ │ ├─ api-code.enum.ts # API 错误码
|
||||
│ │ └─ api-header.enum.ts # API 头部
|
||||
│ ├─ layouts/ # 布局组件
|
||||
│ │ ├─ default.vue # 默认布局
|
||||
│ │ └─ tabbar.vue # 标签栏布局
|
||||
│ ├─ pages/ # 页面文件
|
||||
│ │ ├─ index/ # 首页
|
||||
│ │ │ ├─ data.ts # 数据定义
|
||||
│ │ │ ├─ index.vue # 首页组件
|
||||
│ │ │ └─ types.ts # 类型定义
|
||||
│ │ ├─ login/ # 登录页
|
||||
│ │ │ └─ index.vue # 登录组件
|
||||
│ │ ├─ mine/ # 个人中心
|
||||
│ │ │ ├─ about/ # 关于页面
|
||||
│ │ │ ├─ faq/ # FAQ页面
|
||||
│ │ │ ├─ feedback/ # 反馈页面
|
||||
│ │ │ ├─ profile/ # 个人资料
|
||||
│ │ │ ├─ settings/ # 设置页面
|
||||
│ │ │ └─ index.vue # 个人中心组件
|
||||
│ │ └─ work/ # 工作台
|
||||
│ │ ├─ data.ts # 数据定义
|
||||
│ │ ├─ index.vue # 工作台组件
|
||||
│ │ └─ types.ts # 类型定义
|
||||
│ ├─ router/ # 路由配置
|
||||
│ │ └─ index.ts # 路由配置文件
|
||||
│ ├─ static/ # 静态资源
|
||||
│ │ ├─ icons/ # 图标
|
||||
│ │ ├─ images/ # 图片
|
||||
│ │ └─ logo.png # Logo
|
||||
│ ├─ store/ # 状态管理
|
||||
│ │ ├─ modules/ # 模块
|
||||
│ │ │ ├─ theme.store.ts # 主题管理
|
||||
│ │ │ └─ user.store.ts # 用户管理
|
||||
│ │ └─ index.ts # 状态管理配置
|
||||
│ ├─ styles/ # 样式文件
|
||||
│ │ └─ index.scss # 全局样式
|
||||
│ ├─ types/ # TypeScript 类型定义
|
||||
│ ├─ utils/ # 工具函数
|
||||
│ │ ├─ auth.ts # 认证工具
|
||||
│ │ ├─ color.ts # 颜色工具
|
||||
│ │ ├─ index.ts # 工具函数
|
||||
│ │ ├─ request.ts # 请求工具
|
||||
│ │ └─ storage.ts # 存储工具
|
||||
│ ├─ App.vue # 应用根组件
|
||||
│ ├─ main.ts # 应用入口文件
|
||||
│ ├─ manifest.json # 应用配置文件
|
||||
│ ├─ pages.json # 页面路由配置
|
||||
│ └─ theme.json # 主题配置
|
||||
├─ public/ # 静态资源
|
||||
├─ .env.development # 开发环境配置
|
||||
├─ .env.production # 生产环境配置
|
||||
├─ package.json # 项目依赖
|
||||
├─ pages.config.ts # 页面配置
|
||||
├─ tsconfig.json # TypeScript 配置
|
||||
├─ unocss.config.ts # UnoCSS 配置
|
||||
└─ vite.config.ts # Vite 配置
|
||||
```
|
||||
|
||||
### 3. FastDocs 官网文档
|
||||
|
||||
```sh
|
||||
FastDocs/
|
||||
├─ docs/ # 文档源码
|
||||
│ ├─ development/ # 开发文档
|
||||
│ ├─ en/ # 英文文档
|
||||
│ ├─ overview/ # 概述文档
|
||||
│ ├─ quickstart/ # 快速开始
|
||||
│ ├─ public/ # 静态资源
|
||||
│ └─ index.md # 首页
|
||||
├─ .vitepress/ # VitePress 配置
|
||||
│ ├─ theme/ # 主题配置
|
||||
│ └─ config.ts # 站点配置
|
||||
├─ package.json # 项目依赖
|
||||
└─ README.md # 项目文档
|
||||
```
|
||||
|
||||
## ✨核心亮点
|
||||
|
||||
| 特性 | 描述 |
|
||||
| ---- | ---- |
|
||||
| 🔭 快速开发 | 一套完全开源的现代化快速开发平台,旨在帮助开发者高效搭建高质量的企业级中后台系统。 |
|
||||
| 🌐 全栈整合 | 前后端分离,融合 Python (FastAPI) + Vue3 多端开发,支持 Web 端和移动端。 |
|
||||
| 🧱 模块化设计 | 系统功能高度解耦,插件化架构,支持自动路由发现和注册,便于扩展和维护。 |
|
||||
| ⚡️ 高性能异步 | 使用 FastAPI 异步框架 + Redis 缓存优化接口响应速度。 |
|
||||
| 🔒 安全认证 | 支持 JWT OAuth2 认证机制,保障系统安全。 |
|
||||
| 📊 权限管理 | RBAC 模型实现菜单、按钮、数据级别的细粒度权限控制。 |
|
||||
| 🚀 快速部署 | 支持 Docker/Docker Compose/Nginx 一键部署。 |
|
||||
| 📄 开发友好 | 提供完善的中文文档 + 中文化界面 + 可视化工具链,降低学习成本。 |
|
||||
| 🧩 快速接入 | 基于 Vue3、Vite5、Pinia、ElementPlus 等主流前端技术栈,开箱即用。 |
|
||||
| 📱 移动端支持 | 基于 UniApp 开发的 FastApp 移动端,支持多端运行(H5、微信小程序、支付宝小程序、App 等)。 |
|
||||
| 🤖 智能体框架 | 集成智能体框架,提供 AI 能力。 |
|
||||
| 🎨 主题定制 | 支持深色/浅色主题切换,提供个性化界面体验。 |
|
||||
| 🌍 国际化支持 | 内置国际化框架,支持多语言切换。 |
|
||||
| 📈 数据可视化 | 集成图表库,提供丰富的数据可视化能力。 |
|
||||
| 🛠️ 代码生成 | 内置代码生成工具,提升开发效率。 |
|
||||
|
||||
## 🛠️技术栈概览
|
||||
|
||||
| 类型 | 技术选型 | 描述 |
|
||||
|----------|---------------------|---------------------|
|
||||
| 后端框架 | FastAPI / Uvicorn / Pydantic 2.0 / Alembic | 现代、高性能的异步框架,强制类型约束,数据迁移。 |
|
||||
| ORM | SQLAlchemy 2.0 | 强大的 ORM 库。 |
|
||||
| 定时任务 | APScheduler | 轻松实现定时任务。 |
|
||||
| 权限认证 | PyJWT | 实现 JWT 认证。 |
|
||||
| 前端框架 | Vue3 / Vite5 / Pinia / TypeScript | 快速开发 Vue3 应用。 |
|
||||
| 前端工具 | ESLint / Prettier / Stylelint | 代码质量和风格工具。 |
|
||||
| 移动端框架 | UniApp / Vue3 / TypeScript | 跨平台移动应用开发。 |
|
||||
| UI 库 | ElementPlus (Web) / Wot Design Uni (移动端) | 企业级 UI 组件库。 |
|
||||
| CSS 框架 | UnoCSS / SCSS | 原子化 CSS 和预处理器。 |
|
||||
| 数据库 | MySQL / PostgreSQL / SQLite | 关系型数据库支持。 |
|
||||
| 缓存 | Redis | 强大的缓存数据库。 |
|
||||
| 文档 | Swagger / Redoc | 自动生成 API 文档。 |
|
||||
| 部署 | Docker / Nginx / Docker Compose | 快速部署项目。 |
|
||||
| 监控 | 内置服务器监控 / 缓存监控 | 系统运行状态监控。 |
|
||||
| 国际化 | i18n | 多语言支持。 |
|
||||
| 数据可视化 | ECharts | 图表库。 |
|
||||
|
||||
## 📌内置模块
|
||||
|
||||
### FastapiAdmin 主工程模块
|
||||
|
||||
| 模块名 | 子模块名 | 描述 |
|
||||
|----------|---------------------|---------------------|
|
||||
| 仪表盘 | 工作台、分析页 | 系统概览和数据分析 |
|
||||
| 系统管理 | 用户、角色、菜单、部门、岗位、字典、配置、公告 | 核心系统管理功能 |
|
||||
| 监控管理 | 在线用户、服务器监控、缓存监控 | 系统运行状态监控 |
|
||||
| 任务管理 | 定时任务 | 异步任务调度管理 |
|
||||
| 日志管理 | 操作日志 | 用户行为审计 |
|
||||
| 开发工具 | 代码生成、表单构建、接口文档 | 提升开发效率的工具 |
|
||||
|
||||
### FastApp 移动端模块
|
||||
|
||||
| 模块名 | 子模块名 | 描述 |
|
||||
|----------|---------------------|---------------------|
|
||||
| 首页 | 轮播图、快捷导航、通知公告、数据统计 | 移动端首页展示 |
|
||||
| 工作台 | 业务功能入口,支持权限控制 | 移动端核心功能区 |
|
||||
| 个人中心 | 个人信息、设置、FAQ、问题反馈 | 用户个人相关功能 |
|
||||
| 用户认证 | 登录、注册、密码重置 | 用户身份验证 |
|
||||
| 数据统计 | 实时访客数、浏览量等数据展示 | 业务数据可视化 |
|
||||
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 604 KiB |
|
After Width: | Height: | Size: 563 KiB |
|
After Width: | Height: | Size: 232 KiB |
|
After Width: | Height: | Size: 608 KiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 697 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 948 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 131 KiB |
@@ -0,0 +1,956 @@
|
||||
---
|
||||
title: 赞助 FastApiAdmin
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* 全局样式 - 增加页面宽度 */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const benefits = [
|
||||
{ icon: '🌐', title: '网站运营', desc: '承担域名及服务器成本' },
|
||||
{ icon: '🛠️', title: '开发工具', desc: '采购专业开发工具与服务' },
|
||||
{ icon: '💬', title: '技术支持', desc: '提供更优质的技术支持' },
|
||||
{ icon: '⚡', title: '持续开发', desc: '投入更多精力进行开发' },
|
||||
{ icon: '✨', title: '代码优化', desc: '持续优化代码质量' },
|
||||
{ icon: '🚀', title: '功能研发', desc: '研发更多实用功能与模块' }
|
||||
]
|
||||
|
||||
const honorarySponsors = [
|
||||
{ name: '晨曦微光', avatar: '', amount: '¥500', date: '2026-04' },
|
||||
{ name: 'Alex_Chen', avatar: '', amount: '¥300', date: '2026-04' },
|
||||
{ name: '一叶知秋', avatar: '', amount: '¥200', date: '2026-03' },
|
||||
{ name: 'coding小王子', avatar: '', amount: '¥500', date: '2026-03' },
|
||||
{ name: 'Mr.Zhang', avatar: '', amount: '¥100', date: '2026-03' },
|
||||
{ name: '墨染青衣', avatar: '', amount: '¥200', date: '2026-02' },
|
||||
{ name: 'sky_walker', avatar: '', amount: '¥300', date: '2026-02' },
|
||||
{ name: '浅笑_安然', avatar: '', amount: '¥150', date: '2026-02' },
|
||||
{ name: 'Jason.Liu', avatar: '', amount: '¥200', date: '2026-01' },
|
||||
{ name: '梦里花落', avatar: '', amount: '¥100', date: '2026-01' },
|
||||
{ name: 'Leo_李', avatar: '', amount: '¥500', date: '2026-01' },
|
||||
{ name: '岁月静好', avatar: '', amount: '¥200', date: '2025-12' },
|
||||
{ name: 'code_monkey', avatar: '', amount: '¥150', date: '2025-12' },
|
||||
{ name: '北城以北', avatar: '', amount: '¥300', date: '2025-11' },
|
||||
{ name: 'Emma.Wang', avatar: '', amount: '¥100', date: '2025-11' },
|
||||
{ name: '烟雨_江南', avatar: '', amount: '¥200', date: '2025-11' },
|
||||
{ name: 'tech_lover88', avatar: '', amount: '¥150', date: '2025-10' },
|
||||
{ name: '清风徐来', avatar: '', amount: '¥300', date: '2025-10' },
|
||||
{ name: 'David.Zhou', avatar: '', amount: '¥200', date: '2025-10' },
|
||||
{ name: 'python小白', avatar: '', amount: '¥100', date: '2025-09' }
|
||||
]
|
||||
|
||||
const tiers = [
|
||||
{
|
||||
name: '独家赞助者',
|
||||
icon: '👑',
|
||||
level: 'exclusive',
|
||||
price: '微信沟通/月',
|
||||
color: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
benefits: [
|
||||
'官网首屏独家 Logo 展示位',
|
||||
'演示网站首屏第一轮播位置',
|
||||
'所有内容页面左侧边栏顶部专属 Logo',
|
||||
'交流群 + 公众号独家产品发布(每月一次)'
|
||||
],
|
||||
requirements: '品牌名称 + 官方链接 + Logo(340px*160px) + 广告语'
|
||||
},
|
||||
{
|
||||
name: '铂金赞助者',
|
||||
icon: '💎',
|
||||
level: 'platinum',
|
||||
price: '微信沟通/月',
|
||||
color: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
|
||||
benefits: [
|
||||
'官网首页显著位置 Logo 展示',
|
||||
'演示网站首页显著位置 Logo 展示',
|
||||
'所有内容页面左侧边栏显著 Logo',
|
||||
'所有交流群产品推广(每月一次)'
|
||||
],
|
||||
requirements: '品牌名称 + 官方链接 + Logo(340px*160px)'
|
||||
},
|
||||
{
|
||||
name: '金牌赞助者',
|
||||
icon: '🥇',
|
||||
level: 'gold',
|
||||
price: '微信沟通/月',
|
||||
// color: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)',
|
||||
color: 'linear-gradient(135deg, #f6d365 0%, #fda085 100%)',
|
||||
benefits: [
|
||||
'官网首页大号 Logo 展示位',
|
||||
'所有内容页面右侧边栏大号 Logo',
|
||||
'最新三个交流群产品推广(每月一次)'
|
||||
],
|
||||
requirements: '品牌名称 + 官方链接 + Logo(220px*70px)'
|
||||
},
|
||||
{
|
||||
name: '银牌赞助者',
|
||||
icon: '🥈',
|
||||
level: 'silver',
|
||||
price: '微信沟通/月',
|
||||
// color: 'linear-gradient(135deg, #bdc3c7 0%, #2c3e50 100%)',
|
||||
color: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
|
||||
benefits: [
|
||||
'所有内容页面右侧边栏小号 Logo'
|
||||
],
|
||||
requirements: '品牌名称 + 官方链接 + Logo(110px*60px)'
|
||||
}
|
||||
]
|
||||
|
||||
const currentSponsors = {
|
||||
exclusive: [
|
||||
{
|
||||
name: 'CoderXSLee',
|
||||
logo: 'https://foruda.gitee.com/avatar/1725853866438762352/562111_coderxslee_1725853866.png!avatar200',
|
||||
website: 'https://www.gitee.com/coderxslee',
|
||||
description: '',
|
||||
amount: '¥100'
|
||||
}
|
||||
],
|
||||
platinum: [
|
||||
// {
|
||||
// name: 'DevTools Pro',
|
||||
// logo: '',
|
||||
// website: 'https://www.devtools-pro.com',
|
||||
// description: '为开发者提供专业的开发工具和服务',
|
||||
// amount: '¥5,000'
|
||||
// },
|
||||
// {
|
||||
// name: '极客学院',
|
||||
// logo: '',
|
||||
// website: 'https://www.geek-academy.com',
|
||||
// description: '在线技术课程与培训平台',
|
||||
// amount: '¥5,000'
|
||||
// }
|
||||
],
|
||||
gold: [
|
||||
// {
|
||||
// name: '云服务Plus',
|
||||
// logo: '',
|
||||
// website: 'https://www.cloud-plus.com',
|
||||
// description: '企业级云服务解决方案提供商',
|
||||
// amount: '¥3,000'
|
||||
// },
|
||||
// {
|
||||
// name: '代码之光',
|
||||
// logo: '',
|
||||
// website: 'https://www.code-light.com',
|
||||
// description: '开发者社区与技术博客平台',
|
||||
// amount: '¥3,000'
|
||||
// },
|
||||
// {
|
||||
// name: '智能IDE',
|
||||
// logo: '',
|
||||
// website: 'https://www.smart-ide.com',
|
||||
// description: '新一代智能开发环境',
|
||||
// amount: '¥3,000'
|
||||
// }
|
||||
],
|
||||
silver: [
|
||||
// {
|
||||
// name: '键盘侠',
|
||||
// logo: '',
|
||||
// website: 'https://www.keyboard-master.com',
|
||||
// description: '专业机械键盘品牌',
|
||||
// amount: '¥1,000'
|
||||
// },
|
||||
// {
|
||||
// name: '显示器Pro',
|
||||
// logo: '',
|
||||
// website: 'https://www.monitor-pro.com',
|
||||
// description: '程序员专用显示器',
|
||||
// amount: '¥1,000'
|
||||
// },
|
||||
// {
|
||||
// name: '咖啡码农',
|
||||
// logo: '',
|
||||
// website: 'https://www.coffee-coder.com',
|
||||
// description: '为程序员定制的精品咖啡',
|
||||
// amount: '¥1,000'
|
||||
// },
|
||||
// {
|
||||
// name: '技术书屋',
|
||||
// logo: '',
|
||||
// website: 'https://www.tech-books.com',
|
||||
// description: '技术图书与电子书平台',
|
||||
// amount: '¥1,000'
|
||||
// }
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||
animation: pulse 15s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(1); opacity: 0.5; }
|
||||
50% { transform: scale(1.1); opacity: 0.8; }
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.hero-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 1rem 2.5rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
margin: 4rem 0 2rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.benefit-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.benefit-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.benefit-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.benefit-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.benefit-desc {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.tip-box {
|
||||
background: linear-gradient(135deg, rgba(255, 193, 7, 0.1) 0%, rgba(255, 152, 0, 0.1) 100%);
|
||||
border-left: 4px solid #ffc107;
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.tip-box strong {
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.tiers-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
gap: 1.2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.tier-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 16px;
|
||||
padding: 0;
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tier-card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 20px 50px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
/* 为高级别赞助添加特殊效果 */
|
||||
.tier-card:nth-child(1),
|
||||
.tier-card:nth-child(2) {
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
.tier-card:nth-child(1) {
|
||||
border-color: rgba(102, 126, 234, 0.5);
|
||||
box-shadow: 0 8px 30px rgba(102, 126, 234, 0.15);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(2) {
|
||||
border-color: rgba(245, 87, 108, 0.5);
|
||||
box-shadow: 0 8px 30px rgba(245, 87, 108, 0.15);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(1):hover {
|
||||
box-shadow: 0 20px 50px rgba(102, 126, 234, 0.4);
|
||||
border-color: rgba(102, 126, 234, 0.8);
|
||||
}
|
||||
|
||||
.tier-card:nth-child(2):hover {
|
||||
box-shadow: 0 20px 50px rgba(245, 87, 108, 0.4);
|
||||
border-color: rgba(245, 87, 108, 0.8);
|
||||
}
|
||||
|
||||
.tier-header {
|
||||
padding: 1.5rem;
|
||||
color: white;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 银牌赞助者使用深色文字 */
|
||||
.tier-card:nth-child(4) .tier-header {
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.tier-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.8rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tier-name {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.tier-price {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.tier-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.tier-benefits {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 1.2rem 0;
|
||||
}
|
||||
|
||||
.tier-benefits li {
|
||||
padding: 0.3rem 0;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.4rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.3;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.tier-benefits li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.tier-benefits li::before {
|
||||
content: '✓';
|
||||
color: #10b981;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.tier-requirements {
|
||||
background: rgba(102, 126, 234, 0.05);
|
||||
border-radius: 8px;
|
||||
padding: 0.8rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 1.2rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.tier-requirements strong {
|
||||
color: var(--vp-c-text-1);
|
||||
display: block;
|
||||
margin-bottom: 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.tier-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.8rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.tier-button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.guidelines-section {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
.guidelines-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.guidelines-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.guidelines-list li {
|
||||
padding: 0.4rem 0;
|
||||
padding-left: 1.2rem;
|
||||
position: relative;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.guidelines-list li::before {
|
||||
content: '•';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0.4rem;
|
||||
color: #667eea;
|
||||
font-weight: 700;
|
||||
font-size: 1rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.example-box {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.sponsors-section {
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
.sponsor-tier {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.sponsor-tier-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.empty-sponsors {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.sponsors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.sponsor-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sponsor-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.sponsor-logo {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 0 auto 1rem;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, rgba(189, 52, 254, 0.5) 30%, rgba(65, 209, 255, 0.5));
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.sponsor-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.sponsor-name {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sponsor-desc {
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
line-height: 1.4;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.sponsor-amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem 3rem 3rem 3rem;
|
||||
text-align: center;
|
||||
margin: 3rem 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1.5rem 0;
|
||||
padding: 0 0 1.5rem 0;
|
||||
border-bottom: 1px solid var(--vp-c-divider);
|
||||
border-top: none;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.contact-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.contact-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.contact-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contact-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.contact-link {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.contact-link:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.honorary-sponsors-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.honorary-sponsor-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem 1rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.honorary-sponsor-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.honorary-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin: 0 auto 0.8rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, rgba(189, 52, 254, 0.5) 30%, rgba(65, 209, 255, 0.5));
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.honorary-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.honorary-name {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.honorary-amount {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
color: #667eea;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.honorary-date {
|
||||
font-size: 0.75rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.tiers-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="hero-section">
|
||||
<h1 class="hero-title">💖 赞助 FastApiAdmin</h1>
|
||||
<p class="hero-subtitle">
|
||||
感谢您考虑支持 FastApiAdmin 开源项目!<br>
|
||||
FastApiAdmin 采用 MIT 开源许可协议,允许个人、企业免费用于商业用途。<br>
|
||||
自项目发布以来,我们始终致力于持续迭代与优化,为此我们投入了大量的时间和无限的热爱。
|
||||
</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="#赞助等级" class="btn btn-primary">💎 查看赞助等级</a>
|
||||
<a href="https://service.fastapiadmin.com/about/#%F0%9F%8E%A8-%E5%85%B3%E4%BA%8E%E6%88%91%E4%BB%AC" target="_blank" class="btn btn-secondary">📞 联系我们</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">🎯 您的支持将帮助我们</h2>
|
||||
|
||||
<div class="benefits-grid">
|
||||
<div v-for="benefit in benefits" :key="benefit.title" class="benefit-card">
|
||||
<div class="benefit-icon">{{ benefit.icon }}</div>
|
||||
<div class="benefit-title">{{ benefit.title }}</div>
|
||||
<div class="benefit-desc">{{ benefit.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 id="赞助等级" class="section-title">💎 赞助等级与权益</h2>
|
||||
|
||||
<div class="tip-box">
|
||||
<strong>💡 温馨提示:</strong>赞助展示的转化效果可能受市场环境、受众特征等多种因素影响,我们无法保证具体的转化结果。
|
||||
</div>
|
||||
|
||||
<div class="tiers-grid">
|
||||
<div v-for="tier in tiers" :key="tier.level" class="tier-card">
|
||||
<div class="tier-header" :style="{ background: tier.color }">
|
||||
<span class="tier-icon">{{ tier.icon }}</span>
|
||||
<div class="tier-name">{{ tier.name }}</div>
|
||||
<div class="tier-price">{{ tier.price }}</div>
|
||||
</div>
|
||||
<div class="tier-body">
|
||||
<ul class="tier-benefits">
|
||||
<li v-for="(benefit, index) in tier.benefits" :key="index">{{ benefit }}</li>
|
||||
</ul>
|
||||
<div class="tier-requirements">
|
||||
<strong>需提供材料:</strong>
|
||||
{{ tier.requirements }}
|
||||
</div>
|
||||
<a href="#联系方式" class="tier-button">立即赞助</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="guidelines-section">
|
||||
<div class="guidelines-title">📋 内容规范</div>
|
||||
<ul class="guidelines-list">
|
||||
<li>建议推广与开发者相关的产品或服务,如低代码开发平台、技术课程、开发工具、云服务、个人博客等,实体产品如键盘、显示器、耳机等。</li>
|
||||
<li>与开发者群体关联度较低的产品,请酌情考虑。</li>
|
||||
<li>我们拒绝推广违反法律法规、涉及灰色产业的产品,以及 IP 代理、上网工具等。</li>
|
||||
<li>为避免过度打扰群成员,单日内在交流群中的推广不超过两次,超出部分可顺延至次日。</li>
|
||||
</ul>
|
||||
|
||||
<div class="guidelines-title" style="margin-top: 2rem;">📢 群发消息示例</div>
|
||||
<div class="example-box">感谢 xxx 对 FastApiAdmin 开源项目的特别赞助!以下是其产品信息,感兴趣的朋友可以了解一下:
|
||||
【产品名称】
|
||||
【官方链接】https://xxx.com</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">🌟 当前赞助者</h2>
|
||||
|
||||
<div class="sponsors-section">
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">👑 独家赞助者</div>
|
||||
<div v-if="currentSponsors.exclusive.length === 0" class="empty-sponsors">目前空缺,期待您的加入</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.exclusive" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/月</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">💎 铂金赞助者</div>
|
||||
<div v-if="currentSponsors.platinum.length === 0" class="empty-sponsors">目前空缺,期待您的加入</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.platinum" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/月</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">🥇 金牌赞助者</div>
|
||||
<div v-if="currentSponsors.gold.length === 0" class="empty-sponsors">目前空缺,期待您的加入</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.gold" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/月</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sponsor-tier">
|
||||
<div class="sponsor-tier-title">🥈 银牌赞助者</div>
|
||||
<div v-if="currentSponsors.silver.length === 0" class="empty-sponsors">目前空缺,期待您的加入</div>
|
||||
<div v-else class="sponsors-grid">
|
||||
<a v-for="sponsor in currentSponsors.silver" :key="sponsor.name" :href="sponsor.website" target="_blank" class="sponsor-card">
|
||||
<div class="sponsor-logo">
|
||||
<img v-if="sponsor.logo" :src="sponsor.logo" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="sponsor-name">{{ sponsor.name }}</div>
|
||||
<div class="sponsor-desc">{{ sponsor.description }}</div>
|
||||
<div class="sponsor-amount">{{ sponsor.amount }}/月</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">☕ 荣誉赞助</h2>
|
||||
<p class="cta-text">
|
||||
您可以在<a href="/about/" style="color: #667eea; text-decoration: none;">关于我们</a>页面通过各位维护团队成员的赞赏码进行赞助。<br>
|
||||
来为 FastApiAdmin 的维护成员们点上一杯咖啡吧!
|
||||
</p>
|
||||
|
||||
<div class="honorary-sponsors-grid">
|
||||
<div v-for="sponsor in honorarySponsors" :key="sponsor.name + sponsor.date" class="honorary-sponsor-card">
|
||||
<div class="honorary-avatar">
|
||||
<img v-if="sponsor.avatar" :src="sponsor.avatar" :alt="sponsor.name">
|
||||
<span v-else>{{ sponsor.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<div class="honorary-name">{{ sponsor.name }}</div>
|
||||
<div class="honorary-amount">{{ sponsor.amount }}</div>
|
||||
<div class="honorary-date">{{ sponsor.date }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cta-section" style="margin-top: 1rem;">
|
||||
<h2 class="cta-title">🎉 期待与您的合作</h2>
|
||||
<p class="cta-text">
|
||||
如果您有意向赞助 FastApiAdmin 项目,或者想了解更多详情,<br>
|
||||
欢迎随时通过上述方式联系我们,我们将竭诚为您服务!
|
||||
</p>
|
||||
<a href="https://service.fastapiadmin.com/about/#%F0%9F%8E%A8-%E5%85%B3%E4%BA%8E%E6%88%91%E4%BB%AC" target="_blank" class="btn btn-primary">立即联系我们</a>
|
||||
</div>
|
||||
@@ -0,0 +1,510 @@
|
||||
---
|
||||
outline: "deep"
|
||||
title: 快速开始
|
||||
---
|
||||
# 快速开始
|
||||
|
||||
## 🍪演示环境
|
||||
|
||||
- 官网地址:<https://service.fastapiadmin.com>
|
||||
- 演示地址:<https://service.fastapiadmin.com/web>
|
||||
- 小程序地址:<https://service.fastapiadmin.com/app>
|
||||
- 管理员账号:`admin` 密码:`123456`
|
||||
- 演示账号:`demo` 密码:`123456`
|
||||
|
||||
## 👷安装和使用
|
||||
|
||||
### 版本说明
|
||||
|
||||
| 类型 | 技术栈 | 版本 |
|
||||
|----------|------------|------------|
|
||||
| 后端 | Python | >=3.10 |
|
||||
| 后端 | FastAPI | 0.109+ |
|
||||
| 前端 | Node.js | >= 20.0(推荐使用最新版)|
|
||||
| 前端 | pnpm | >= 9.0 |
|
||||
| 前端 | Vue3 | 3.5.22+ |
|
||||
| Web UI | ElementPlus | 2.10.4+ |
|
||||
| 移动端 | Uni App | 3.0.0+ |
|
||||
| App UI | Wot Design Uni | 1.9.1+ |
|
||||
| 数据库 | MySQL | 8.0+ (推荐使用最新版)|
|
||||
| 中间件 | Redis | 7.0+ (推荐使用最新版)|
|
||||
|
||||
### 环境准备
|
||||
|
||||
#### 1. 安装 Python
|
||||
|
||||
```sh
|
||||
# macOS
|
||||
brew install python@3.10
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install python3.10 python3.10-venv python3.10-dev
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo dnf install python3.10 python3.10-venv python3.10-devel
|
||||
```
|
||||
|
||||
#### 2. 安装 Node.js
|
||||
|
||||
```sh
|
||||
# 使用 nvm 安装(推荐)
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
||||
nvm install 20
|
||||
nvm use 20
|
||||
|
||||
# 或使用包管理器
|
||||
# macOS
|
||||
brew install node@20
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install nodejs npm
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo dnf install nodejs npm
|
||||
|
||||
# 安装 pnpm
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
#### 3. 安装数据库和缓存
|
||||
|
||||
```sh
|
||||
# 安装 MySQL
|
||||
# macOS
|
||||
brew install mysql
|
||||
brew services start mysql
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install mysql-server
|
||||
sudo systemctl start mysql
|
||||
|
||||
# 安装 Redis
|
||||
# macOS
|
||||
brew install redis
|
||||
brew services start redis
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt install redis-server
|
||||
sudo systemctl start redis
|
||||
```
|
||||
|
||||
### 获取代码
|
||||
|
||||
```sh
|
||||
# 克隆代码到本地
|
||||
# FastapiAdmin 主工程
|
||||
git clone https://github.com/fastapiadmin/FastapiAdmin.git
|
||||
# 或使用 Gitee
|
||||
git clone https://gitee.com/fastapiadmin/FastapiAdmin.git
|
||||
|
||||
# FastApp 移动端
|
||||
git clone https://github.com/fastapiadmin/FastApp.git
|
||||
# 或使用 Gitee
|
||||
git clone https://gitee.com/fastapiadmin/FastApp.git
|
||||
|
||||
# FastDocs 官网文档
|
||||
git clone https://github.com/fastapiadmin/FastDocs.git
|
||||
# 或使用 Gitee
|
||||
git clone https://gitee.com/fastapiadmin/FastDocs.git
|
||||
```
|
||||
|
||||
### 本地后端启动(FastapiAdmin 主工程)
|
||||
|
||||
#### 1. 配置环境变量
|
||||
|
||||
```sh
|
||||
# 进入后端工程目录
|
||||
cd FastapiAdmin/backend
|
||||
|
||||
# 复制环境配置文件
|
||||
cp env/.env.dev.example env/.env.dev
|
||||
|
||||
# 编辑环境配置文件(根据实际情况修改)
|
||||
# 主要配置项说明:
|
||||
# - DATABASE_URL: 数据库连接地址
|
||||
# - REDIS_URL: Redis连接地址
|
||||
# - SECRET_KEY: JWT签名密钥
|
||||
# - ACCESS_TOKEN_EXPIRE_MINUTES: 访问令牌过期时间
|
||||
# - REFRESH_TOKEN_EXPIRE_DAYS: 刷新令牌过期时间
|
||||
# - API_PREFIX: API前缀
|
||||
# - CORS_ORIGINS: 跨域来源
|
||||
```
|
||||
|
||||
#### 2. 安装依赖
|
||||
|
||||
```sh
|
||||
# 使用 uv 管理项目(推荐)
|
||||
uv add -r requirements.txt
|
||||
|
||||
# 或使用传统 pip 方式
|
||||
# 创建虚拟环境(可选但推荐)
|
||||
python3 -m venv .venv
|
||||
|
||||
# 激活虚拟环境
|
||||
# macOS/Linux
|
||||
source .venv/bin/activate
|
||||
# Windows
|
||||
.venv\Scripts\activate
|
||||
|
||||
# 安装依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 3. 数据库初始化
|
||||
|
||||
```sh
|
||||
# 生成迁移文件
|
||||
python main.py revision "初始化迁移" --env=dev
|
||||
|
||||
# 应用迁移
|
||||
python main.py upgrade --env=dev
|
||||
|
||||
# 初始化系统数据
|
||||
python main.py init
|
||||
```
|
||||
|
||||
#### 4. 启动后端服务
|
||||
|
||||
```sh
|
||||
# 使用 uv 启动
|
||||
uv run main.py run
|
||||
|
||||
# 或使用传统方式
|
||||
# 开发环境启动
|
||||
python main.py run --env=dev
|
||||
|
||||
# 或使用默认环境(dev)
|
||||
python main.py run
|
||||
|
||||
# 生产环境启动
|
||||
python main.py run --env=prod
|
||||
```
|
||||
|
||||
### 本地前端启动(FastapiAdmin 主工程)
|
||||
|
||||
#### 1. 配置环境变量
|
||||
|
||||
```sh
|
||||
# 进入前端工程目录
|
||||
cd FastapiAdmin/frontend
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.development.example .env.development
|
||||
|
||||
# 编辑环境配置文件(根据实际情况修改)
|
||||
# 主要配置项说明:
|
||||
# - VITE_API_BASE_URL: 后端API基础地址
|
||||
# - VITE_APP_BASE_API: API前缀
|
||||
# - VITE_APP_TITLE: 应用标题
|
||||
# - VITE_APP_VERSION: 应用版本
|
||||
```
|
||||
|
||||
#### 2. 安装依赖
|
||||
|
||||
```sh
|
||||
# 安装前端依赖
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### 3. 启动前端服务
|
||||
|
||||
```sh
|
||||
# 开发环境启动
|
||||
pnpm run dev
|
||||
|
||||
# 构建前端, 生成 `dist` 目录
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
### 本地移动端启动(FastApp 移动端)
|
||||
|
||||
#### 1. 环境要求
|
||||
|
||||
- **Node.js** >= 22
|
||||
- **pnpm** >= 9
|
||||
|
||||
#### 2. 配置环境变量
|
||||
|
||||
```sh
|
||||
# 进入移动端工程目录
|
||||
cd FastApp
|
||||
|
||||
# 复制环境配置文件
|
||||
cp .env.development.example .env.development
|
||||
cp .env.production.example .env.production
|
||||
|
||||
# 编辑环境配置文件(根据实际情况修改)
|
||||
# 主要配置项说明:
|
||||
# - VITE_APP_ENV: 环境模式
|
||||
# - VITE_APP_TITLE: 应用标题
|
||||
# - VITE_API_BASE_URL: 后端API基础地址
|
||||
# - VITE_APP_BASE_API: API前缀(/api/v1)
|
||||
# - VITE_APP_PORT: 开发服务器端口
|
||||
# - VITE_TIMEOUT: 请求超时时间
|
||||
# - VITE_APP_WS_ENDPOINT: WebSocket服务器地址
|
||||
```
|
||||
|
||||
#### 3. 安装依赖
|
||||
|
||||
```sh
|
||||
# 进入移动端工程目录
|
||||
cd FastApp
|
||||
|
||||
# 安装前端依赖
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### 4. 启动开发服务器
|
||||
|
||||
##### H5 开发
|
||||
|
||||
```bash
|
||||
# 启动 H5 开发服务器
|
||||
pnpm run dev:h5
|
||||
|
||||
# 访问地址
|
||||
# http://localhost:5180/app
|
||||
```
|
||||
|
||||
##### 微信小程序开发
|
||||
|
||||
```bash
|
||||
# 启动微信小程序开发服务器
|
||||
pnpm run dev:mp-weixin
|
||||
|
||||
# 在微信开发者工具中导入项目目录:FastApp/dist/dev/mp-weixin
|
||||
```
|
||||
|
||||
##### 其他平台开发
|
||||
|
||||
```bash
|
||||
# 启动支付宝小程序开发服务器
|
||||
pnpm run dev:mp-alipay
|
||||
|
||||
# 启动百度小程序开发服务器
|
||||
pnpm run dev:mp-baidu
|
||||
|
||||
# 启动字节跳动小程序开发服务器
|
||||
pnpm run dev:mp-toutiao
|
||||
|
||||
# 启动 QQ 小程序开发服务器
|
||||
pnpm run dev:mp-qq
|
||||
```
|
||||
|
||||
### 本地项目官网启动(FastDocs 官网文档)
|
||||
|
||||
```sh
|
||||
# 进入 FastDocs 官网文档目录
|
||||
cd FastDocs
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 运行文档工程
|
||||
pnpm run docs:dev
|
||||
|
||||
# 构建文档工程, 生成 `dist` 目录
|
||||
pnpm run docs:build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 本地访问地址
|
||||
|
||||
- FastDocs 文档地址: <http://127.0.0.1:5180>
|
||||
- FastapiAdmin 前端地址: <http://127.0.0.1:5173>
|
||||
- FastAPI 接口文档: <http://127.0.0.1:8001/api/v1/docs>
|
||||
- FastApp H5地址: <http://127.0.0.1:5180/app>
|
||||
|
||||
### 默认账号密码
|
||||
|
||||
- 管理员账号:`admin` 密码:`123456`
|
||||
- 演示账号:`demo` 密码:`123456`
|
||||
|
||||
## 🐳 Docker 部署
|
||||
|
||||
### 1. 准备工作
|
||||
|
||||
- 服务器需安装 Docker 和 Docker Compose
|
||||
- 确保服务器端口 80(Nginx)、8001(后端)可用
|
||||
|
||||
### 2. 部署步骤
|
||||
|
||||
```sh
|
||||
# 进入 FastapiAdmin 主工程目录
|
||||
cd FastapiAdmin
|
||||
|
||||
# 复制环境配置文件
|
||||
cp backend/env/.env.prod.example backend/env/.env.prod
|
||||
cp frontend/.env.production.example frontend/.env.production
|
||||
|
||||
# 编辑环境配置文件(根据实际服务器情况修改)
|
||||
# 主要配置项:数据库连接、Redis连接、JWT密钥、API基础URL等
|
||||
|
||||
# 赋予脚本执行权限
|
||||
chmod +x deploy.sh
|
||||
|
||||
# 执行部署脚本
|
||||
./deploy.sh
|
||||
|
||||
# 查看部署状态
|
||||
docker compose ps
|
||||
|
||||
# 查看日志
|
||||
docker logs -f fastapiadmin-backend
|
||||
```
|
||||
|
||||
### 3. 部署文件说明
|
||||
|
||||
| 配置文件 | 说明 | 路径 |
|
||||
|---------|------|------|
|
||||
| 后端环境配置 | 生产环境数据库、Redis等配置 | `FastapiAdmin/backend/env/.env.prod` |
|
||||
| 前端环境配置 | 生产环境API地址等配置 | `FastapiAdmin/frontend/.env.production` |
|
||||
| Docker配置 | 容器编排配置 | `FastapiAdmin/docker-compose.yaml` |
|
||||
| Nginx配置 | 反向代理配置 | `FastapiAdmin/devops/nginx/nginx.conf` |
|
||||
|
||||
### 4. 常用 Docker 命令
|
||||
|
||||
```sh
|
||||
# 查看镜像
|
||||
docker images
|
||||
|
||||
# 查看容器
|
||||
docker compose ps
|
||||
|
||||
# 停止服务
|
||||
docker compose down
|
||||
|
||||
# 重启服务
|
||||
docker compose up -d
|
||||
|
||||
# 查看容器日志
|
||||
docker logs -f <容器名>
|
||||
|
||||
# 进入容器
|
||||
docker exec -it <容器名> bash
|
||||
```
|
||||
|
||||
## 🔧模块展示
|
||||
|
||||
### web 端
|
||||
|
||||
| 模块名 <div style="width:60px"/> | 截图 |
|
||||
|----------|------|
|
||||
| 仪表盘 |  |
|
||||
| 代码生成 |  |
|
||||
| 智能助手 |  |
|
||||
|
||||
### 移动端
|
||||
|
||||
| 登录 <div style="width:60px"/> | 首页 <div style="width:60px"/> | 个人中心 <div style="width:60px"/> |
|
||||
|----------|----------|----------|
|
||||
|  |  |  |
|
||||
|
||||
## 🚀二开教程
|
||||
|
||||
### 后端部分(FastapiAdmin 主工程)
|
||||
|
||||
项目采用**插件化架构设计**,二次开发建议在 `backend/app/plugin` 目录下进行,系统会**自动发现并注册**所有符合规范的路由,便于模块管理和升级维护。
|
||||
|
||||
#### 插件化架构特性
|
||||
|
||||
- **自动路由发现**:系统会自动扫描 `backend/app/plugin/` 目录下所有 `controller.py` 文件
|
||||
- **自动路由注册**:所有路由会被自动注册到对应的前缀路径 (module_xxx -> /xxx)
|
||||
- **模块化管理**:按功能模块组织代码,便于维护和扩展
|
||||
- **支持多层级嵌套**:支持模块内部多层级嵌套结构
|
||||
|
||||
#### 插件目录结构
|
||||
|
||||
```sh
|
||||
backend/app/plugin/
|
||||
├── module_application/ # 应用模块(自动映射为 /application)
|
||||
│ └── ai/ # AI子模块
|
||||
│ ├── controller.py # 控制器文件
|
||||
│ ├── model.py # 数据模型文件
|
||||
│ ├── schema.py # 数据验证文件
|
||||
│ ├── service.py # 业务逻辑文件
|
||||
│ └── crud.py # 数据访问文件
|
||||
├── module_example/ # 示例模块(自动映射为 /example)
|
||||
│ └── demo/ # 子模块
|
||||
│ ├── controller.py # 控制器文件
|
||||
│ ├── model.py # 数据模型文件
|
||||
│ ├── schema.py # 数据验证文件
|
||||
│ ├── service.py # 业务逻辑文件
|
||||
│ └── crud.py # 数据访问文件
|
||||
├── module_generator/ # 代码生成模块(自动映射为 /generator)
|
||||
└── init_app.py # 插件初始化文件
|
||||
```
|
||||
|
||||
#### 二次开发步骤
|
||||
|
||||
1. **创建插件模块**:在 `backend/app/plugin/` 目录下创建新的模块目录,如 `module_yourfeature`
|
||||
2. **编写数据模型**:在 `model.py` 中定义数据库模型
|
||||
3. **编写数据验证**:在 `schema.py` 中定义数据验证模型
|
||||
4. **编写数据访问层**:在 `crud.py` 中编写数据库操作逻辑
|
||||
5. **编写业务逻辑层**:在 `service.py` 中编写业务逻辑
|
||||
6. **编写控制器**:在 `controller.py` 中定义路由和处理函数
|
||||
7. **自动注册**:系统会自动扫描并注册所有路由,无需手动配置
|
||||
|
||||
### 前端部分(FastapiAdmin 主工程)
|
||||
|
||||
1. **配置前端API**:在 `frontend/src/api/` 目录下创建对应的API文件
|
||||
2. **编写页面组件**:在 `frontend/src/views/` 目录下创建页面组件
|
||||
3. **注册路由**:在 `frontend/src/router/index.ts` 中注册路由
|
||||
|
||||
### 移动端部分(FastApp 移动端)
|
||||
|
||||
1. **配置移动端API**:在 `FastApp/src/api/` 目录下创建对应的API文件
|
||||
2. **编写移动端页面**:在 `FastApp/src/pages/` 目录下创建页面组件
|
||||
3. **配置页面路由**:在 `FastApp/src/pages.json` 中配置页面路由
|
||||
|
||||
## 💡常见问题及解决方案
|
||||
|
||||
### 1. 后端启动失败
|
||||
|
||||
**问题**:数据库连接失败
|
||||
**解决方案**:检查环境配置文件中的数据库连接信息是否正确,确保数据库服务正在运行,且用户名密码正确。
|
||||
|
||||
**问题**:Redis连接失败
|
||||
**解决方案**:检查环境配置文件中的Redis连接信息是否正确,确保Redis服务正在运行。
|
||||
|
||||
**问题**:依赖安装失败
|
||||
**解决方案**:确保Python版本正确(>=3.10),可以尝试使用虚拟环境重新安装依赖。
|
||||
|
||||
### 2. 前端启动失败
|
||||
|
||||
**问题**:依赖安装失败
|
||||
**解决方案**:确保Node.js版本正确(>=20.0),可以尝试清除缓存后重新安装:`pnpm cache clean && pnpm install`。
|
||||
|
||||
**问题**:API请求失败
|
||||
**解决方案**:检查前端环境配置文件中的API基础URL是否正确,确保后端服务正在运行。
|
||||
|
||||
### 3. 移动端启动失败
|
||||
|
||||
**问题**:依赖安装失败
|
||||
**解决方案**:确保Node.js版本正确(>=22.0),pnpm版本正确(>=9.0),可以尝试清除缓存后重新安装:`pnpm cache clean && pnpm install`。
|
||||
|
||||
**问题**:H5页面空白
|
||||
**解决方案**:检查浏览器控制台是否有错误信息,确保API基础URL配置正确,后端服务正在运行。
|
||||
|
||||
### 4. 部署问题
|
||||
|
||||
**问题**:Docker部署失败
|
||||
**解决方案**:确保服务器已安装Docker和Docker Compose,检查端口是否被占用,查看容器日志了解具体错误信息。
|
||||
|
||||
**问题**:Nginx配置错误
|
||||
**解决方案**:检查Nginx配置文件中的反向代理设置是否正确,确保后端服务地址配置正确。
|
||||
|
||||
### 5. 其他问题
|
||||
|
||||
**问题**:系统初始化失败
|
||||
**解决方案**:确保数据库已正确初始化,且迁移已应用,可以尝试重新执行初始化命令:`python main.py init`。
|
||||
|
||||
**问题**:权限不足
|
||||
**解决方案**:检查用户角色权限设置,确保当前用户有足够的权限访问所需功能。
|
||||
|
||||
**问题**:代码生成失败
|
||||
**解决方案**:确保数据库表结构正确,代码生成配置参数填写完整。
|
||||
@@ -0,0 +1,526 @@
|
||||
---
|
||||
title: 所有用户
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* 全局样式 - 增加页面宽度到 1600px,以便在宽屏下显示 4 列公司卡片 */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const allUsers = ref([
|
||||
{
|
||||
name: '深圳昌红科技有限公司',
|
||||
location: '深圳 · 坪山',
|
||||
province: '广东',
|
||||
website: 'https://cn.sz-changhong.com/',
|
||||
websiteEn: 'https://www.sz-changhong.com/',
|
||||
logo: '',
|
||||
registrant: '杨向向',
|
||||
registrantUrl: 'https://gitee.com/xiao-lei',
|
||||
date: '2026-04-19',
|
||||
description: '基于 FastapiAdmin 构建的企业管理系统'
|
||||
},
|
||||
{
|
||||
name: '北京云信XX软件技术有限公司',
|
||||
location: '陕西 · 西安',
|
||||
province: '陕西',
|
||||
website: '',
|
||||
logo: '',
|
||||
registrant: '李浩',
|
||||
registrantUrl: 'https://gitee.com/aiyun_lh',
|
||||
date: '2026-04-19',
|
||||
description: '基于 FastapiAdmin 构建的单元制造执行系统'
|
||||
},
|
||||
{
|
||||
name: '上海智慧科技有限公司',
|
||||
location: '上海 · 浦东',
|
||||
province: '上海',
|
||||
website: 'https://www.sh-wisdom.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: '张伟',
|
||||
registrantUrl: 'https://gitee.com/zhangwei',
|
||||
date: '2026-04-18',
|
||||
description: '基于 FastapiAdmin 构建的智能物流管理平台'
|
||||
},
|
||||
{
|
||||
name: '杭州云端网络科技有限公司',
|
||||
location: '浙江 · 杭州',
|
||||
province: '浙江',
|
||||
website: 'https://www.hz-cloud.com/',
|
||||
websiteEn: 'https://en.hz-cloud.com/',
|
||||
logo: '',
|
||||
registrant: '王芳',
|
||||
registrantUrl: 'https://gitee.com/wangfang',
|
||||
date: '2026-04-17',
|
||||
description: '基于 FastapiAdmin 构建的云端数据分析系统'
|
||||
},
|
||||
{
|
||||
name: '成都蜀道科技有限公司',
|
||||
location: '四川 · 成都',
|
||||
province: '四川',
|
||||
website: '',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: '刘强',
|
||||
registrantUrl: 'https://gitee.com/liuqiang',
|
||||
date: '2026-04-16',
|
||||
description: '基于 FastapiAdmin 构建的电商运营管理系统'
|
||||
},
|
||||
{
|
||||
name: '广州南方数据科技有限公司',
|
||||
location: '广东 · 广州',
|
||||
province: '广东',
|
||||
website: 'https://www.gz-data.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: '陈明',
|
||||
registrantUrl: 'https://gitee.com/chenming',
|
||||
date: '2026-04-15',
|
||||
description: '基于 FastapiAdmin 构建的大数据可视化平台'
|
||||
},
|
||||
{
|
||||
name: '南京紫金软件开发有限公司',
|
||||
location: '江苏 · 南京',
|
||||
province: '江苏',
|
||||
website: 'https://www.nj-zijin.com/',
|
||||
websiteEn: 'https://en.nj-zijin.com/',
|
||||
logo: '',
|
||||
registrant: '赵丽',
|
||||
registrantUrl: 'https://gitee.com/zhaoli',
|
||||
date: '2026-04-14',
|
||||
description: '基于 FastapiAdmin 构建的教育培训管理系统'
|
||||
},
|
||||
{
|
||||
name: '武汉长江信息技术有限公司',
|
||||
location: '湖北 · 武汉',
|
||||
province: '湖北',
|
||||
website: '',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: '孙涛',
|
||||
registrantUrl: 'https://gitee.com/suntao',
|
||||
date: '2026-04-13',
|
||||
description: '基于 FastapiAdmin 构建的医疗健康管理平台'
|
||||
},
|
||||
{
|
||||
name: '天津滨海创新科技有限公司',
|
||||
location: '天津 · 滨海新区',
|
||||
province: '天津',
|
||||
website: 'https://www.tj-binhai.com/',
|
||||
websiteEn: '',
|
||||
logo: '',
|
||||
registrant: '周敏',
|
||||
registrantUrl: 'https://gitee.com/zhoumin',
|
||||
date: '2026-04-12',
|
||||
description: '基于 FastapiAdmin 构建的智能制造执行系统'
|
||||
},
|
||||
{
|
||||
name: '重庆山城软件有限公司',
|
||||
location: '重庆 · 渝北',
|
||||
province: '重庆',
|
||||
website: 'https://www.cq-mountain.com/',
|
||||
websiteEn: 'https://en.cq-mountain.com/',
|
||||
logo: '',
|
||||
registrant: '吴静',
|
||||
registrantUrl: 'https://gitee.com/wujing',
|
||||
date: '2026-04-11',
|
||||
description: '基于 FastapiAdmin 构建的供应链管理系统'
|
||||
}
|
||||
])
|
||||
|
||||
const searchKeyword = ref('')
|
||||
const activeProvince = ref('全部')
|
||||
|
||||
const provinces = computed(() => {
|
||||
const set = new Set(allUsers.value.map(u => u.province))
|
||||
return ['全部', ...Array.from(set)]
|
||||
})
|
||||
|
||||
const filteredUsers = computed(() => {
|
||||
return allUsers.value.filter(user => {
|
||||
const matchKeyword = !searchKeyword.value ||
|
||||
user.name.includes(searchKeyword.value) ||
|
||||
user.location.includes(searchKeyword.value)
|
||||
const matchProvince = activeProvince.value === '全部' || user.province === activeProvince.value
|
||||
return matchKeyword && matchProvince
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-header {
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.stats-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
padding: 0.5rem 1.5rem;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(10px);
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
.register-btn {
|
||||
display: inline-block;
|
||||
margin-top: 1rem;
|
||||
padding: 0.8rem 2rem;
|
||||
background: white;
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.register-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.search-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
padding: 1rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
transition: all 0.3s ease;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-input:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 3rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.8rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.filter-tag {
|
||||
padding: 0.6rem 1.5rem;
|
||||
cursor: pointer;
|
||||
border-radius: 25px;
|
||||
border: 2px solid var(--vp-c-divider);
|
||||
background: var(--vp-c-bg-soft);
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.filter-tag:hover {
|
||||
transform: translateY(-2px);
|
||||
border-color: #bd34fe;
|
||||
}
|
||||
|
||||
.filter-tag-active {
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
border: none;
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.4);
|
||||
padding: calc(0.6rem + 2px) calc(1.5rem + 2px);
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 1.2rem 1rem;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.user-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.user-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.8rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.user-logo {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.user-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
line-height: 1.3;
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-description {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 0.8rem;
|
||||
line-height: 1.4;
|
||||
font-style: italic;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
line-height: 1.6;
|
||||
font-size: 0.85rem;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.user-info strong {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.user-info a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.user-info a:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
border: 2px dashed var(--vp-c-divider);
|
||||
border-radius: 16px;
|
||||
background: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* 增加内容宽度 */
|
||||
:deep(.VPDoc) {
|
||||
max-width: 1600px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.page-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stats-badge {
|
||||
display: block;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">🚀 他们在使用 FastapiAdmin</h1>
|
||||
<p class="page-subtitle">
|
||||
感谢每一位选择 FastapiAdmin 的开发者和企业。登记后,您将获得<strong>优先技术支持</strong>,我们的维护团队将第一时间响应您的问题。
|
||||
</p>
|
||||
<div>
|
||||
<span class="stats-badge">👥 {{ allUsers.length }} 位登记用户</span>
|
||||
<span class="stats-badge">🚀 优先技术支持</span>
|
||||
<span class="stats-badge">💎 完全免费</span>
|
||||
</div>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">📝 立即登记</a>
|
||||
</div>
|
||||
|
||||
<div class="search-section">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
placeholder="🔍 搜索公司/组织/项目名称..."
|
||||
class="search-input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<span
|
||||
v-for="p in provinces"
|
||||
:key="p"
|
||||
@click="activeProvince = p"
|
||||
:class="['filter-tag', { 'filter-tag-active': activeProvince === p }]"
|
||||
>{{ p }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="filteredUsers.length > 0" class="users-grid">
|
||||
<div v-for="user in filteredUsers" :key="user.name" class="user-card">
|
||||
<div class="user-header">
|
||||
<div class="user-logo">
|
||||
<img v-if="user.logo" :src="user.logo" :alt="user.name">
|
||||
<span v-else>{{ user.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<h3 class="user-name">{{ user.name }}</h3>
|
||||
</div>
|
||||
<p v-if="user.description" class="user-description">{{ user.description }}</p>
|
||||
<div class="user-info">
|
||||
📍 <strong>所在地区</strong>:{{ user.location }}<br>
|
||||
<template v-if="user.website">
|
||||
🌐 <strong>中文官网</strong>:<br>
|
||||
<a :href="user.website" target="_blank">{{ user.website }}</a><br>
|
||||
</template>
|
||||
<template v-if="user.websiteEn">
|
||||
🌐 <strong>英文官网</strong>:<br>
|
||||
<a :href="user.websiteEn" target="_blank">{{ user.websiteEn }}</a><br>
|
||||
</template>
|
||||
<span v-if="user.registrant">
|
||||
👤 <strong>登记人</strong>:
|
||||
<a v-if="user.registrantUrl" :href="user.registrantUrl" target="_blank">{{ user.registrant }}</a>
|
||||
<span v-else>{{ user.registrant }}</span>
|
||||
<br>
|
||||
</span>
|
||||
📅 <strong>登记时间</strong>:{{ user.date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="empty-state">
|
||||
<div class="empty-icon">
|
||||
{{ searchKeyword || activeProvince !== '全部' ? '🔍' : '🚀' }}
|
||||
</div>
|
||||
<h3 class="empty-title">
|
||||
{{ searchKeyword || activeProvince !== '全部' ? '未找到匹配的用户' : '期待您的加入' }}
|
||||
</h3>
|
||||
<p class="empty-text">
|
||||
{{ searchKeyword || activeProvince !== '全部' ? '尝试调整搜索关键词或地区筛选' : '成为第一个登记的用户,获得优先技术支持' }}
|
||||
</p>
|
||||
<a v-if="!searchKeyword && activeProvince === '全部'" href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">立即登记</a>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">💡 基于 FastapiAdmin 开发你的业务</h2>
|
||||
<p class="cta-text">
|
||||
登记完全免费,FastapiAdmin 项目开源且免费。我们郑重承诺,不会在任何阶段向您收取任何形式的使用费用,您的信息也不会被用于商业盈利或其他非公开目的。
|
||||
</p>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="register-btn">立即登记</a>
|
||||
</div>
|
||||
@@ -0,0 +1,387 @@
|
||||
---
|
||||
title: 他们在使用
|
||||
sidebar: false
|
||||
aside: false
|
||||
---
|
||||
|
||||
<style>
|
||||
/* 全局样式 - 增加页面宽度 */
|
||||
.VPDoc.has-sidebar .content-container,
|
||||
.VPDoc.has-aside .content-container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .container {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
.VPDoc .content {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
|
||||
const featuredUsers = [
|
||||
{
|
||||
name: '深圳昌红科技有限公司',
|
||||
location: '深圳 · 坪山',
|
||||
website: 'https://cn.sz-changhong.com/',
|
||||
websiteEn: 'https://www.sz-changhong.com/',
|
||||
registrant: '杨向向',
|
||||
registrantUrl: 'https://gitee.com/xiao-lei',
|
||||
date: '2026-04-19',
|
||||
description: '基于 FastapiAdmin 构建的企业管理系统'
|
||||
},
|
||||
{
|
||||
name: '北京云信XX软件技术有限公司',
|
||||
location: '陕西 · 西安',
|
||||
registrant: '李浩',
|
||||
registrantUrl: 'https://gitee.com/aiyun_lh',
|
||||
date: '2026-04-19',
|
||||
description: '基于 FastapiAdmin 构建的单元制造执行系统'
|
||||
}
|
||||
]
|
||||
|
||||
const stats = [
|
||||
{ label: '登记用户', value: '2+', icon: '👥' },
|
||||
{ label: '技术支持', value: '优先', icon: '🚀' },
|
||||
{ label: '开源协议', value: '免费', icon: '💎' }
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hero-section {
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
border-radius: 16px;
|
||||
color: white;
|
||||
margin-bottom: 3rem;
|
||||
box-shadow: 0 10px 40px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.95;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0.8rem 2rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
|
||||
border: 1px solid rgba(102, 126, 234, 0.2);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: #bd34fe;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
background: var(--vp-c-bg-soft);
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.user-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.user-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 15px 40px rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.user-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.user-logo img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: var(--vp-c-text-1);
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-description {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
line-height: 2;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.user-info strong {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.user-info a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.user-info a:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
|
||||
border: 2px dashed rgba(102, 126, 234, 0.3);
|
||||
border-radius: 16px;
|
||||
padding: 3rem;
|
||||
text-align: center;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
color: var(--vp-c-text-2);
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.8;
|
||||
max-width: 800px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.view-all-link {
|
||||
display: inline-block;
|
||||
margin: 2rem auto;
|
||||
padding: 1rem 3rem;
|
||||
background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(189, 52, 254, 0.3);
|
||||
}
|
||||
|
||||
.view-all-link:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 25px rgba(189, 52, 254, 0.5);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 增加内容宽度 */
|
||||
:deep(.VPDoc) {
|
||||
max-width: 1200px !important;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.users-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="hero-section">
|
||||
<h1 class="hero-title">🚀 他们在使用 FastapiAdmin</h1>
|
||||
<p class="hero-subtitle">
|
||||
感谢每一位选择 FastapiAdmin 的开发者和企业<br>
|
||||
登记后,您将获得<strong>优先技术支持</strong>,我们的维护团队将第一时间响应您的问题
|
||||
</p>
|
||||
<div class="hero-buttons">
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="btn btn-primary">📝 立即登记</a>
|
||||
<a href="/users/all" class="btn btn-secondary">🔍 浏览所有用户</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div v-for="stat in stats" :key="stat.label" class="stat-card">
|
||||
<div class="stat-icon">{{ stat.icon }}</div>
|
||||
<div class="stat-value">{{ stat.value }}</div>
|
||||
<div class="stat-label">{{ stat.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">✨ 精选用户</h2>
|
||||
|
||||
<div class="users-grid">
|
||||
<div v-for="user in featuredUsers" :key="user.name" class="user-card">
|
||||
<div class="user-header">
|
||||
<div class="user-logo">
|
||||
<img v-if="user.logo" :src="user.logo" :alt="user.name">
|
||||
<span v-else>{{ user.name.charAt(0) }}</span>
|
||||
</div>
|
||||
<h3 class="user-name">{{ user.name }}</h3>
|
||||
</div>
|
||||
<p class="user-description">{{ user.description }}</p>
|
||||
<div class="user-info">
|
||||
📍 <strong>所在地区</strong>:{{ user.location }}<br>
|
||||
<span v-if="user.website">🌐 <strong>中文官网</strong>:<a :href="user.website" target="_blank">{{ user.website }}</a><br></span>
|
||||
<span v-if="user.websiteEn">🌐 <strong>英文官网</strong>:<a :href="user.websiteEn" target="_blank">{{ user.websiteEn }}</a><br></span>
|
||||
👤 <strong>登记人</strong>:<a :href="user.registrantUrl" target="_blank">{{ user.registrant }}</a><br>
|
||||
📅 <strong>登记时间</strong>:{{ user.date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="/users/all" class="view-all-link">查看全部用户 →</a>
|
||||
</div>
|
||||
|
||||
<div class="cta-section">
|
||||
<h2 class="cta-title">💡 基于 FastapiAdmin 开发你的业务</h2>
|
||||
<p class="cta-text">
|
||||
登记完全免费,FastapiAdmin 项目开源且免费。我们郑重承诺,不会在任何阶段向您收取任何形式的使用费用,您的信息也不会被用于商业盈利或其他非公开目的。
|
||||
</p>
|
||||
<a href="https://gitee.com/fastapiadmin/FastapiAdmin/issues/IJ9NKA" target="_blank" class="btn btn-primary">立即登记</a>
|
||||
</div>
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: 为什么选择FastapiAdmin?
|
||||
---
|
||||
# 为什么是FastapiAdmin?
|
||||
|
||||
## 💡你在执着于寻找什么?
|
||||
- 找一群志同道合的朋友,做一件有意义的事?
|
||||
- 寻找一个亦师亦友的领路人,指引我们前行的方向?
|
||||
- 圆梦一个顶级丝滑先进的、完全开源的、容易上手的、长期维护有人答疑的全栈web系统?
|
||||
- 在这里,一个开源的FastapiAdmin统统包揽(你会收获技术,你会收获朋友,你会收获老师。甚至你可以看到凌晨3点大哥依旧在奋笔疾书,凌晨两点技术群讨论问题的欢呼雀跃)!
|
||||
|
||||
## 🏗️ 系统架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A[前端 Vue3] --> B[API网关]
|
||||
C[小程序 UniApp] --> B
|
||||
B --> D[后端 FastAPI]
|
||||
D --> E[MySQL]
|
||||
D --> F[Redis]
|
||||
D --> G[MongoDB]
|
||||
```
|
||||
|
||||
## 📡技术我们有
|
||||
### 🚀 现代化全栈技术栈
|
||||
- 后端基于**FastAPI**(高性能异步框架),前端基于**Vue3 + TypeScript**,技术选型主流、先进。
|
||||
- 支持**Web + 小程序**多端开发,一套代码多处运行,降低开发与维护成本,容易上手。
|
||||
|
||||
### 🧩 高度模块化设计
|
||||
- 前后端完全分离,功能模块解耦,结构清晰,易于定制和扩展。
|
||||
- 提供详细二次开发教程与文档,适合中大型项目快速迭代。
|
||||
|
||||
### ⚡ 高性能与高安全性
|
||||
- 基于**异步框架 + Redis缓存**,接口响应速度快。
|
||||
- 支持**JWT + OAuth2 认证**与**RBAC权限控制**,系统安全有保障。
|
||||
|
||||
### 🛠️ 开箱即用,功能丰富
|
||||
- 内置用户管理、权限控制、日志监控、任务调度等常见中后台功能。
|
||||
- 提供主题切换、锁屏、可视化工具等细节功能,提升用户体验。
|
||||
|
||||
### 📦 部署简单灵活
|
||||
- 支持**Docker Compose一键部署**,快速搭建生产环境。
|
||||
- 也支持传统部署方式(Nginx + 手动部署),适应不同运维需求。
|
||||
|
||||
### 📘 中文友好,文档详尽
|
||||
- 全中文开发文档 + 中文化界面,降低学习成本。
|
||||
- 社区活跃,提供微信交流群,及时获取帮助与支持。
|
||||
|
||||
## 🤝 贡献指南
|
||||
|
||||
欢迎任何形式的贡献,包括但不限于:
|
||||
- 提交代码修复
|
||||
- 改进文档
|
||||
- 提交新功能建议
|
||||
- 报告bug
|
||||
|
||||
请查看我们的[贡献指南](/about/)了解详情。
|
||||
|
||||
## 💪团队我们有
|
||||
### ⚓项目的"定海神针"
|
||||
[@fastapiadmin](https://gitee.com/fastapiadmin)深耕高精尖技术行业数十年,有着丰富的代码经验,作为团队的核心带头人,他不仅是技术深耕者,更是开源精神的践行者,常常凌晨仍在代码库中打磨功能、优化架构,为项目锚定清晰的发展方向。面对开发者的疑问,他总能耐心答疑、分享经验,从技术选型到难题攻克全程把关;同时,他也积极营造活跃的交流氛围,让团队与社区的每一次探讨都能转化为项目迭代的动力。
|
||||
### 🛠️高性能架构的"搭建者"与"塑造者"
|
||||
团队专注于打造高性能、高安全的异步架构,将大哥的思想进行逐步落实。把流畅交互与友好体验融入架构设计,小到主题切换细节,大到多端适配逻辑,都力求精准呈现产品价值。在完成代码开发的同时,团队更主动肩负社群答疑责任 —— 无论是技术群里开发者遇到的二次开发难题,还是使用过程中碰到的功能适配问题,成员都会及时响应、分享解决方案,用专业与耐心搭建起项目与用户之间的信任桥梁,**让开源不仅是代码的共享,更是技术与经验的互助传递。**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
> ✅ 如果你需要一个技术先进、功能丰富、易于扩展、容易上手、且完全开源的中后台快速开发平台,**Fastapi-Vue3-Admin** 是一个绝佳的选择。尤其适合 Python + Vue3 技术栈的团队或个人快速构建企业级管理系统。
|
||||
|
||||
📌 **项目地址**:
|
||||
- **GitHub**:
|
||||
- [FastapiAdmin 主工程](https://github.com/fastapiadmin/FastapiAdmin.git)
|
||||
- [FastApp 移动端](https://github.com/fastapiadmin/FastApp.git)
|
||||
- [FastDocs 官网文档](https://github.com/fastapiadmin/FastDocs.git)
|
||||
- **Gitee**:[https://gitee.com/fastapiadmin/FastapiAdmin](https://gitee.com/fastapiadmin/FastapiAdmin)
|
||||
- [联系 or 加入我们](/about/)
|
||||
|
||||
🙌 **无论你是否喜欢这个项目,都希望你能够给个 ⭐ Star 支持!小小的种子蕴含着大大的能量,终有一天星星之火,可以燎原。**
|
||||
|
||||
🙌 **如果你对 Fastapi-Vue3-Admin 技术有浓厚的兴趣,也欢迎你加入我们一起学习一起进步。**
|
||||
@@ -0,0 +1,100 @@
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import tsPlugin from '@typescript-eslint/eslint-plugin'
|
||||
import vueParser from 'vue-eslint-parser'
|
||||
import vuePlugin from 'eslint-plugin-vue'
|
||||
import prettierPlugin from 'eslint-plugin-prettier'
|
||||
import prettierConfig from 'eslint-config-prettier'
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
'**/node_modules/**',
|
||||
'**/.vitepress/cache/**',
|
||||
'**/dist/**',
|
||||
'**/build/**',
|
||||
'**/coverage/**',
|
||||
'**/*.log',
|
||||
'**/*.md'
|
||||
]
|
||||
},
|
||||
{
|
||||
files: ['**/*.js'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
browser: true,
|
||||
node: true
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'no-unused-vars': 'warn',
|
||||
'no-empty-function': 'warn',
|
||||
'semi': ['error', 'always'],
|
||||
'quotes': ['error', 'single'],
|
||||
'indent': ['error', 2, { 'SwitchCase': 1 }]
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: __dirname
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': tsPlugin,
|
||||
'prettier': prettierPlugin
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'@typescript-eslint/no-empty-function': 'warn',
|
||||
'@typescript-eslint/semi': ['error', 'always'],
|
||||
'@typescript-eslint/quotes': ['error', 'single'],
|
||||
'@typescript-eslint/indent': ['error', 2, { 'SwitchCase': 1 }],
|
||||
'prettier/prettier': 'error'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.vue'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
parser: vueParser,
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
'vue': vuePlugin,
|
||||
'prettier': prettierPlugin
|
||||
},
|
||||
rules: {
|
||||
...vuePlugin.configs['recommended'].rules,
|
||||
'vue/script-setup-uses-vars': 'error',
|
||||
'vue/no-unused-components': 'warn',
|
||||
'vue/no-unused-vars': 'warn',
|
||||
'prettier/prettier': 'error'
|
||||
}
|
||||
},
|
||||
prettierConfig
|
||||
]
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "fastdocs",
|
||||
"description": "FastapiAdmin 项目文档",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vitepress dev docs || true",
|
||||
"build": "vitepress build docs",
|
||||
"preview": "vitepress preview docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
||||
"@typescript-eslint/parser": "^8.15.0",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.1.3",
|
||||
"eslint": "^9.15.0",
|
||||
"eslint-config-prettier": "^9.1.2",
|
||||
"eslint-plugin-prettier": "^5.2.2",
|
||||
"eslint-plugin-vue": "^9.30.0",
|
||||
"medium-zoom": "^1.1.0",
|
||||
"prettier": "^3.3.3",
|
||||
"vitepress": "1.6.4",
|
||||
"vue": "^3.5.21",
|
||||
"vue-eslint-parser": "^9.4.3"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=10.0.0",
|
||||
"pnpm": ">=8.1.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitee.com/fastapiadmin/FastapiAdmin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://gitee.com/fastapiadmin/FastapiAdmin/issues"
|
||||
},
|
||||
"author": "fastapiadmin <948080782@qq.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://gitee.com/fastapiadmin/FastapiAdmin"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"useDefineForClassFields": true,
|
||||
"baseUrl": ".",
|
||||
"module": "ESNext",
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"~/*": ["docs/.vitepress/theme/*"]
|
||||
},
|
||||
"types": ["node", "vitepress/client"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
/* Node.js specific options */
|
||||
"composite": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": [
|
||||
"docs/.vitepress/**/*",
|
||||
"**/*.vue",
|
||||
"**/*.ts",
|
||||
"**/*.mts",
|
||||
"**/*.tsx",
|
||||
"**/*.md",
|
||||
"env.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"docs/.vitepress/dist",
|
||||
"docs/.vitepress/cache"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import { resolve } from 'path'
|
||||
|
||||
export default defineConfig({
|
||||
// 路径别名
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src'),
|
||||
'@public': resolve(__dirname, 'src/public')
|
||||
}
|
||||
},
|
||||
|
||||
// 构建优化
|
||||
build: {
|
||||
// 输出目录
|
||||
outDir: 'dist',
|
||||
|
||||
// 关闭生成source map,提升构建速度和减少文件大小
|
||||
sourcemap: false,
|
||||
|
||||
// 代码分割配置
|
||||
rollupOptions: {
|
||||
output: {
|
||||
// 代码分割策略
|
||||
manualChunks: {
|
||||
// 将第三方依赖打包成单独的chunk
|
||||
vendor: ['vue', 'vue-router', 'pinia'],
|
||||
// 将vitepress核心打包成单独的chunk
|
||||
vitepress: ['vitepress'],
|
||||
// 将工具库打包成单独的chunk
|
||||
utils: ['medium-zoom']
|
||||
},
|
||||
// 输出文件名格式
|
||||
chunkFileNames: 'assets/js/[name]-[hash].js',
|
||||
entryFileNames: 'assets/js/[name]-[hash].js',
|
||||
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]'
|
||||
}
|
||||
},
|
||||
|
||||
// 压缩配置
|
||||
minify: 'terser',
|
||||
terserOptions: {
|
||||
compress: {
|
||||
// 移除console
|
||||
drop_console: true,
|
||||
// 移除debugger
|
||||
drop_debugger: true,
|
||||
// 移除未使用的变量
|
||||
unused: true,
|
||||
// 合并变量
|
||||
collapse_vars: true,
|
||||
// 内联函数
|
||||
inline: true
|
||||
},
|
||||
// 压缩命名
|
||||
mangle: {
|
||||
// 压缩变量名
|
||||
toplevel: true,
|
||||
// 压缩属性名
|
||||
properties: true
|
||||
}
|
||||
},
|
||||
|
||||
// 缓存配置
|
||||
cacheDir: '.vite/cache',
|
||||
|
||||
// 限制chunk大小
|
||||
chunkSizeWarningLimit: 2000,
|
||||
|
||||
// 预加载策略
|
||||
preload: {
|
||||
include: {
|
||||
type: 'modulepreload',
|
||||
include: 'auto'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 开发服务器配置
|
||||
server: {
|
||||
port: 5180,
|
||||
host: true,
|
||||
open: true,
|
||||
// 热更新配置
|
||||
hmr: {
|
||||
overlay: true,
|
||||
timeout: 3000
|
||||
},
|
||||
// 优化开发服务器性能
|
||||
fs: {
|
||||
strict: false
|
||||
}
|
||||
},
|
||||
|
||||
// 插件配置
|
||||
plugins: [],
|
||||
|
||||
// CSS配置
|
||||
css: {
|
||||
// 启用CSS模块
|
||||
modules: {
|
||||
localsConvention: 'camelCase'
|
||||
},
|
||||
// 预处理器配置
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
additionalData: `@import "@/styles/variables.scss";`
|
||||
}
|
||||
},
|
||||
// 开发环境启用CSS源码映射
|
||||
devSourcemap: true
|
||||
},
|
||||
|
||||
// 优化配置
|
||||
optimizeDeps: {
|
||||
// 强制预构建的依赖
|
||||
include: ['vue', 'vue-router', 'pinia', 'medium-zoom'],
|
||||
// 禁用依赖预构建
|
||||
disabled: false,
|
||||
// 缓存目录
|
||||
cacheDir: '.vite/deps',
|
||||
// 构建选项
|
||||
esbuildOptions: {
|
||||
target: 'esnext'
|
||||
}
|
||||
},
|
||||
|
||||
// 环境变量配置
|
||||
envDir: '.env',
|
||||
envPrefix: 'VITE_'
|
||||
})
|
||||