From 004f32dce18081785909cdcad7b2a254b47c3769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=9A=82=E8=9A=81=E4=BA=91?= Date: Wed, 16 Sep 2026 11:28:28 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AD=BE=E5=85=A5=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- README.en.md | 36 -- README.md | 325 ++++++++++++------ src/common/middleware/login_log.py | 6 +- src/common/middleware/operation_log.py | 6 +- src/common/utils/ip.py | 91 +++++ src/modules/article/handlers.py | 10 +- src/modules/category/handlers.py | 6 +- src/modules/city/handlers.py | 8 +- src/modules/configuration/config/handlers.py | 8 +- .../configuration/config_item/handlers.py | 10 +- src/modules/dept/handlers.py | 6 +- src/modules/dictionary/dict/handlers.py | 8 +- src/modules/dictionary/dict_item/handlers.py | 8 +- src/modules/example/handlers.py | 10 +- src/modules/file_template/handlers.py | 8 +- src/modules/generator/handlers.py | 4 +- .../generator/templates/handlers.py.tpl | 10 +- src/modules/job/handlers.py | 18 +- src/modules/job_log/handlers.py | 2 +- src/modules/level/handlers.py | 12 +- src/modules/link/handlers.py | 10 +- src/modules/login_log/handlers.py | 4 +- src/modules/menu/handlers.py | 6 +- src/modules/notice/handlers.py | 8 +- src/modules/operation_log/handlers.py | 4 +- src/modules/param/handlers.py | 10 +- src/modules/position/handlers.py | 10 +- src/modules/role/handlers.py | 8 +- src/modules/role_menu/handlers.py | 2 +- src/modules/user/handlers.py | 18 +- src/modules/user_role/handlers.py | 6 +- 32 files changed, 427 insertions(+), 253 deletions(-) create mode 100644 src/common/utils/ip.py diff --git a/.env b/.env index fa8d038..1279366 100644 --- a/.env +++ b/.env @@ -28,7 +28,7 @@ TORNADO_DEMO = False # 应用文件上传路径(留空使用项目内 uploads 目录) TORNADO_UPLOAD_DIR = # 应用文件域名 -TORNADO_FILE_URL = http://file.tornado.elevue +TORNADO_FILE_URL = http://images.tornado.elevue.djangoadmin.cn # ============================================================ # 上传配置 diff --git a/README.en.md b/README.en.md index dcbe1a1..e69de29 100644 --- a/README.en.md +++ b/README.en.md @@ -1,36 +0,0 @@ -# DjangoAdmin_Tornado_EleVue - -#### Description -一款 Python 语言基于Tornado、Vue2.x、ElementUI、MySQL等框架精心打造的一款模块化、高性能、企业级的敏捷开发框架,本着简化开发、提升开发效率的初衷触发,框架自研了一套个性化的组件,实现了可插拔的组件式开发方式:单图上传、多图上传、下拉选择、开关按钮、单选按钮、多选按钮、图片裁剪等等一系列个性化、轻量级的组件,是一款真正意义上实现组件化开发的敏捷开发框架。 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 071cac4..4c50891 100644 --- a/README.md +++ b/README.md @@ -1,125 +1,240 @@ +

DjangoAdmin 数据中台解决方案(FastAPI + ElementPlus 版本)

+ +

DjangoAdmin Logo

+ ## 📚 项目介绍 -一款 Python 语言基于Tornado、Vue2.x、ElementUI、MySQL等框架精心打造的一款模块化、高性能、企业级的敏捷开发框架,本着简化开发、提升开发效率的初衷触发,框架自研了一套个性化的组件,实现了可插拔的组件式开发方式:单图上传、多图上传、下拉选择、开关按钮、单选按钮、多选按钮、图片裁剪等等一系列个性化、轻量级的组件,是一款真正意义上实现组件化开发的敏捷开发框架。 +DjangoAdmin 数据中台解决方案是一套面向企业级应用场景的一站式敏捷开发平台。后端以 Python + FastAPI 为核心,前端采用 Vue3 + TypeScript + ElementPlus + Vite 构建,并通过 Vue Router 与 Pinia 实现路由和状态管理。全栈技术体系成熟稳定,可快速支撑中后台管理系统、数据中台、业务运营平台等多类项目落地。 + +框架以“简化开发、提升效率”为设计初衷,自研了一套个性化、可插拔的组件式开发体系,涵盖单图上传、多图上传、下拉选择、开关按钮、单选按钮、多选按钮等常用交互组件。开发者只需按需组合,即可完成业务页面搭建,真正实现低代码开发。 + +在工程化层面,框架内置代码生成器,可根据数据库表结构自动生成完整的 CRUD 模块,包括后端代码、前端页面以及菜单权限记录,将重复性的增删改查工作一键自动化,让开发者能够将精力聚焦于核心业务逻辑与差异化功能。 + +在架构层面,框架采用前后端分离设计:后端提供标准 API,前端独立部署并支持多端适配。权限体系基于 RBAC 模型构建,覆盖菜单权限、按钮权限、数据权限三级控制;认证采用 JWT 无状态方案,使前后端协作更加高效顺畅。代码分层清晰、职责明确,配合完善的开发规范与工具链,为团队协作与长期维护提供坚实保障。 ## 🍻 项目特点 -+ 模块化、松耦合 -+ 模块丰富、开箱即用 -+ 简洁易用、快速接入 -+ 文档详尽、易于维护 -+ 自顶向下、体系化设计 -+ 统一框架、统一组件、降低选择成本 -+ 开发规范、设计模式、代码分层模型 -+ 强大便捷的开发工具链 -+ 完善的本地中文化支持 -+ 设计为团队及企业使用 +- **高性能异步**:原生异步支持,配合 ASGI 服务器,性能卓越 +- **模块化、松耦合**:每个业务模块独立封装,互不干扰,支持按需加载 +- **模块丰富、开箱即用**:内置用户、角色、菜单、部门、字典、日志等十余个基础模块 +- **前后端分离**:前后端独立开发与部署,接口规范统一,支持多端适配 +- **权限体系完善**:基于 RBAC 模型,支持菜单权限、按钮权限二级控制 +- **认证安全可靠**:采用无状态认证方案,支持令牌刷新与黑名单,适配分布式场景 +- **统一响应规范**:接口返回格式统一,前后端协作更高效 +- **跨库数据迁移**:内置数据迁移脚本,支持 MySQL 到其他数据库的结构 + 数据全量迁移 +- **完善的数据验证**:请求参数自动校验,错误信息自动格式化 +- **完善的本地中文化支持**:错误提示、表单验证、操作日志全面中文化 +- **设计为团队及企业使用**:规范统一,便于多人协作与长期维护 ## 🍪 内置模块 -+ 用户管理:用于维护管理系统的用户,常规信息的维护与账号设置。 -+ 角色管理:角色菜单管理与权限分配、设置角色所拥有的菜单权限。 -+ 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 -+ 职级管理:主要管理用户的职级。 -+ 岗位管理:主要管理用户担任职务。 -+ 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 -+ 字典管理:对系统中常用的较为固定的数据进行统一维护。 -+ 配置管理:对系统的常规配置信息进行维护,网站配置管理功能进行统一维护。 -+ 通知公告:系统通知公告信息发布维护。 +- 用户管理:维护管理系统的用户,常规信息的维护与账号设置 +- 角色管理:角色菜单管理与权限分配,设置角色所拥有的菜单权限 +- 菜单管理:配置系统菜单、操作权限、按钮权限标识,支持动态路由生成 +- 职级管理:主要管理用户的职级信息 +- 岗位管理:主要管理用户担任的职务 +- 部门管理:配置系统组织机构,树结构展现支持数据权限 +- 字典管理:对系统中常用的较为固定的数据进行统一维护 +- 字典项管理:字典数据的明细项管理 +- 配置管理:对系统的常规配置信息进行维护,网站配置管理功能统一维护 +- 配置项管理:配置数据的明细项管理 +- 通知公告:系统通知公告信息发布维护 +- 文章管理:文章分类与内容管理 +- 城市管理:城市数据维护,支持树形层级结构 +- 友情链接:友情链接管理 +- 参数管理:系统参数配置管理 +- 文件模板:文件模板管理与导出 +- 操作日志:记录用户关键操作,支持日志查询与审计 +- 登录日志:记录用户登录信息,支持 IP 归属地解析 +- 定时任务:基于 APScheduler 的任务调度,支持任务管理与执行日志 +- 文件上传:通用文件上传接口 +- 代码生成器:根据数据库表结构自动生成前后端模块代码 + +## 🚀 快速开始 + +### 环境要求 + +- **Python** >= 3.12 +- **Node.js** >= 22(前端项目) +- **pnpm** >= 7(前端项目) +- **MySQL** >= 8.0(默认,可切换其他数据库) +- **Redis** >= 6.0 + +## 🗄️ 数据库支持 + +框架默认支持 **MySQL** 数据库,同时也支持多种数据库,可根据实际业务场景灵活切换。 + +| 数据库 | 驱动 | DB_DRIVER 值 | 支持情况 | +| --- | --- | --- | --- | +| MySQL | PyMySQL 1.2.0 | `mysql`(默认) | ✅ 默认支持 | +| PostgreSQL | psycopg[binary] 3.x | `postgresql` | ✅ 支持 | +| SQL Server | pymssql 2.3.x | `mssql` | ✅ 支持 | +| SQLite | Python 内置 | `sqlite` | ✅ 支持 | +| Oracle | oracledb 2.x | `oracle` | ✅ 支持 | + +## 📁 项目结构 + +``` +├── src/ # 后端源码目录 +│ ├── main.py # 应用入口 +│ ├── api/ # API 路由层 +│ │ ├── __init__.py # 路由注册 +│ │ ├── deps.py # 全局依赖 +│ │ └── v1/ +│ │ ├── router.py # 路由集中注册 +│ │ └── endpoints/ # 各模块端点定义 +│ │ ├── auth.py # 登录/登出/验证码 +│ │ ├── user.py # 用户管理 +│ │ ├── role.py # 角色管理 +│ │ ├── menu.py # 菜单管理 +│ │ ├── dept.py # 部门管理 +│ │ ├── level.py # 职级管理 +│ │ ├── position.py # 岗位管理 +│ │ ├── dict.py # 字典管理 +│ │ ├── dict_item.py # 字典项管理 +│ │ ├── config.py # 配置管理 +│ │ ├── config_item.py # 配置项管理 +│ │ ├── notice.py # 通知公告 +│ │ ├── article.py # 文章管理 +│ │ ├── category.py # 分类管理 +│ │ ├── city.py # 城市管理 +│ │ ├── link.py # 友情链接 +│ │ ├── param.py # 参数管理 +│ │ ├── job.py # 定时任务 +│ │ ├── job_log.py # 任务日志 +│ │ ├── file_template.py # 文件模板 +│ │ ├── login_log.py # 登录日志 +│ │ ├── operation_log.py # 操作日志 +│ │ ├── upload.py # 文件上传 +│ │ └── generator.py # 代码生成器 +│ ├── core/ # 核心基础设施 +│ │ ├── config/ # 配置模块 +│ │ ├── app.py # 应用工厂 +│ │ ├── database.py # 数据库引擎/会话管理 +│ │ ├── redis_client.py # Redis 异步客户端 +│ │ ├── jwt.py # 令牌处理 +│ │ ├── password.py # 密码加密 +│ │ ├── response.py # 统一响应封装 +│ │ ├── exceptions.py # 全局异常处理 +│ │ ├── security.py # 安全工具 +│ │ ├── access_decorators.py # 权限装饰器 +│ │ ├── base_model.py # 基础模型 +│ │ ├── base_db.py # 数据库操作基类 +│ │ ├── base_repository.py # 仓储基类 +│ │ ├── base_service.py # 服务基类 +│ │ └── logger.py # 日志配置 +│ ├── modules/ # 业务模块(数据模型 + 仓储 + 服务) +│ │ ├── auth/ # 认证模块 +│ │ ├── system/ # 系统管理 +│ │ ├── dictionary/ # 字典模块 +│ │ ├── configuration/ # 配置模块 +│ │ ├── article/ # 文章模块 +│ │ ├── category/ # 分类模块 +│ │ ├── city/ # 城市模块 +│ │ ├── notice/ # 通知公告模块 +│ │ ├── link/ # 友情链接模块 +│ │ ├── param/ # 参数模块 +│ │ ├── job/ # 定时任务模块 +│ │ ├── job_log/ # 任务日志模块 +│ │ ├── file_template/ # 文件模板模块 +│ │ ├── login_log/ # 登录日志模块 +│ │ ├── operation_log/ # 操作日志模块 +│ │ ├── upload/ # 文件上传模块 +│ │ ├── generator/ # 代码生成器模块 +│ │ └── example/ # 示例模块 +│ ├── middleware/ # HTTP 中间件 +│ │ ├── cors.py # 跨域配置 +│ │ ├── rate_limit.py # 请求限流 +│ │ ├── db_session.py # 请求级数据库会话管理 +│ │ ├── operation_log.py # 操作日志自动记录 +│ │ └── logger.py # 请求日志 +│ ├── constants/ # 常量与枚举 +│ │ ├── constants.py # 业务常量 +│ │ ├── enums.py # 枚举定义 +│ │ └── pagination.py # 分页参数 +│ └── utils/ # 工具函数 +│ ├── request.py # 请求解析工具 +│ ├── captcha/ # 验证码生成 +│ ├── file/ # 文件处理 +│ ├── ip/ # IP 归属地查询 +│ └── perm_cache/ # 权限缓存 +├── scripts/ # 运维脚本 +│ ├── init_db.py # 数据库初始化 +│ ├── seed_dict.py # 字典数据初始化 +│ ├── seed.py # 通用数据填充 +│ ├── migrate_db.py # 跨库数据迁移工具 +│ └── demo_job_loop.py # 定时任务演示脚本 +├── tests/ # 测试目录 +│ ├── contract/ # 契约快照测试 +│ ├── unit/ # 单元测试 +│ └── integration/ # 集成测试 +├── migrations/ # 数据库迁移 +│ ├── alembic.ini # 迁移配置 +│ ├── env.py # 迁移环境 +│ └── versions/ # 迁移版本 +├── deploy/ # 部署配置 +│ ├── nginx.conf # Nginx 配置 +│ └── supervisor.conf # Supervisor 配置 +├── document/ # 项目文档 +├── docker-compose.yml # Docker 编排 +├── Dockerfile # 镜像构建 +├── Makefile # 常用命令快捷入口 +├── alembic.ini # 迁移配置 +├── requirements.txt # Python 依赖清单 +├── pytest.ini # 测试配置 +└── .env # 环境变量配置 +``` ## 👷 软件信息 -* 软件名称:DjangoAdmin敏捷开发框架Tornado+EleVue版本 -* 软件作者:@小蚂蚁云 团队荣誉出品 -* 软件出处:小蚂蚁云团队 -* 软件协议:Apache-2.0 -* 官网网址:[https://www.djangoadmin.cn](https://www.djangoadmin.cn) -* 文档网址:[http://docs.tornado.elevue.djangoadmin.cn](http://docs.tornado.elevue.djangoadmin.cn) - -## 🎨 系统演示 - -+ 演示地址:http://manage.tornado.elevue.djangoadmin.cn - -账号 | 密码| 操作权限 ----|---|--- -admin | 123456| 演示环境无法进行修改删除操作 +- 软件名称:DjangoAdmin 敏捷开发框架 FastAPI + ElementPlus 版本 +- 软件作者:@小蚂蚁云 团队荣誉出品 +- 软件出处:小蚂蚁云团队 +- 软件协议:Apache-2.0 +- 官网网址: +- 文档网址: +- 演示地址: ## 📌 版本说明 -版本名称 | 版本说明 | 版本地址 ----|---|--- -Django+Layui混编版 | 采用Django、Layui等框架研发 | https://gitee.com/djangoadmin/DjangoAdmin_Django_Layui -Flask+Layui混编版 | 采用Flask、Layui等框架研发 | https://gitee.com/djangoadmin/DjangoAdmin_Flask_Layui -FastAPI+Layui混编版 | 采用FastAPI、Layui等框架研发 | https://gitee.com/djangoadmin/DjangoAdmin_Fastapi_Layui -Tornado+Layui混编版 | 采用Tornado、Layui等框架研发 | https://gitee.com/djangoadmin/DjangoAdmin_Tornado_Layui -Django+EleVue前后端分离版 | 采用Django、Vue2.x、ElementUI等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Django_EleVue -Flask+EleVue前后端分离版 | 采用Flask、Vue2.x、ElementUI等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Flask_EleVue -FastAPI+EleVue前后端分离版 | 采用FastAPI、Vue2.x、ElementUI等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Fastapi_EleVue -Tornado+EleVue前后端分离版 | 采用Tornado、Vue2.x、ElementUI等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Tornado_EleVue -Django+AntdVue前后端分离版 | 采用Django、Vue3.x、AntDesign等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Django_AntdVue -Flask+AntdVue前后端分离版 | 采用Flask、Vue3.x、AntDesign等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Flask_AntdVue -FastAPI+AntdVue前后端分离版 | 采用FastAPI、Vue3.x、AntDesign等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Fastapi_AntdVue -Tornado+AntdVue前后端分离版 | 采用Tornado、Vue、AntDesign等框架研发前后端分离版本 | https://gitee.com/djangoadmin/DjangoAdmin_Tornado_AntdVue +| 版本名称 | 版本说明 | 版本地址 | +| --- | --- | --- | +| Django + Layui 混编版 | 采用 Django、Layui 等框架研发 | | +| Flask + Layui 混编版 | 采用 Flask、Layui 等框架研发 | | +| FastAPI + Layui 混编版 | 采用 FastAPI、Layui 等框架研发 | | +| Tornado + Layui 混编版 | 采用 Tornado、Layui 等框架研发 | | +| Django + EleVue 前后端分离版 | 采用 Django、Vue3、TypeScript、ElementPlus 等框架研发前后端分离版本 | | +| Flask + EleVue 前后端分离版 | 采用 Flask、Vue3、TypeScript、ElementPlus 等框架研发前后端分离版本 | | +| FastAPI + EleVue 前后端分离版 | 采用 FastAPI、Vue3、TypeScript、ElementPlus 等框架研发前后端分离版本 | | +| Tornado + EleVue 前后端分离版 | 采用 Tornado、Vue3、TypeScript、ElementPlus 等框架研发前后端分离版本 | | +| Django + AntdVue 前后端分离版 | 采用 Django、Vue3、AntDesign 等框架研发前后端分离版本 | | +| Flask + AntdVue 前后端分离版 | 采用 Flask、Vue3、AntDesign 等框架研发前后端分离版本 | | +| FastAPI + AntdVue 前后端分离版 | 采用 FastAPI、Vue3、AntDesign 等框架研发前后端分离版本 | | +| Tornado + AntdVue 前后端分离版 | 采用 Tornado、Vue3、AntDesign 等框架研发前后端分离版本 | | +| Django + NaiveUI 前后端分离版 | 采用 Django、Vue3、TypeScript、NaiveUI 等框架研发前后端分离版本 | | +| Flask + NaiveUI 前后端分离版 | 采用 Flask、Vue3、TypeScript、NaiveUI 等框架研发前后端分离版本 | | +| FastAPI + NaiveUI 前后端分离版 | 采用 FastAPI、Vue3、TypeScript、NaiveUI 等框架研发前后端分离版本 | | +| Tornado + NaiveUI 前后端分离版 | 采用 Tornado、Vue3、TypeScript、NaiveUI 等框架研发前后端分离版本 | | ## 🔧 模块展示 -![效果图](./uploads/demo/1.png) - -![效果图](./uploads/demo/2.png) - -![效果图](./uploads/demo/3.png) - -![效果图](./uploads/demo/4.png) - -![效果图](./uploads/demo/5.png) - -![效果图](./uploads/demo/6.png) - -![效果图](./uploads/demo/7.png) - -![效果图](./uploads/demo/8.png) - -![效果图](./uploads/demo/9.png) - -![效果图](./uploads/demo/10.png) - -![效果图](./uploads/demo/11.png) - -![效果图](./uploads/demo/12.png) - -![效果图](./uploads/demo/13.png) - -![效果图](./uploads/demo/14.png) - -![效果图](./uploads/demo/15.png) - -![效果图](./uploads/demo/16.png) - -![效果图](./uploads/demo/17.png) - -![效果图](./uploads/demo/18.png) - -![效果图](./uploads/demo/19.png) - -![效果图](./uploads/demo/20.png) - -![效果图](./uploads/demo/21.png) - -![效果图](./uploads/demo/22.png) +| | | +| --- | --- | +| ![模块展示1](./uploads/demo/1.png) | ![模块展示2](./uploads/demo/2.png) | +| ![模块展示3](./uploads/demo/3.png) | ![模块展示4](./uploads/demo/4.png) | +| ![模块展示5](./uploads/demo/5.png) | ![模块展示6](./uploads/demo/6.png) | +| ![模块展示7](./uploads/demo/7.png) | ![模块展示8](./uploads/demo/8.png) | +| ![模块展示9](./uploads/demo/9.png) | ![模块展示10](./uploads/demo/10.png) | +| ![模块展示11](./uploads/demo/11.png) | ![模块展示12](./uploads/demo/12.png) | +| ![模块展示13](./uploads/demo/13.png) | ![模块展示14](./uploads/demo/14.png) | +| ![模块展示15](./uploads/demo/15.png) | ![模块展示16](./uploads/demo/16.png) | +| ![模块展示17](./uploads/demo/17.png) | ![模块展示18](./uploads/demo/18.png) | +| ![模块展示19](./uploads/demo/19.png) | ![模块展示20](./uploads/demo/20.png) | +| ![模块展示21](./uploads/demo/21.png) | ![模块展示22](./uploads/demo/22.png) | +| ![模块展示23](./uploads/demo/23.png) | ![模块展示24](./uploads/demo/24.png) | +| ![模块展示25](./uploads/demo/25.png) | ![模块展示26](./uploads/demo/26.png) | +| ![模块展示27](./uploads/demo/27.png) | ![模块展示28](./uploads/demo/28.png) | ## ✨ 特别鸣谢 -感谢[Tornado](https://www.tornadoweb.org/en/stable/)、[Vue](https://cn.vuejs.org/)、[ElementUI](https://element.eleme.cn/#/)等优秀开源项目。 - -## 📚 版权信息 - -商业版使用需授权,未授权禁止恶意传播和用于商业用途,任何个人、单位、组织授权所获取的框架源码禁止分享、转售、恶意传播、开源(包括框架源码及二次开发后的产品)、禁止简单更改包装声称是自己的产品,否则将追究相关人的法律责任。 - -本软件框架禁止任何单位和个人用于任何违法、侵害他人合法利益等恶意的行为,禁止用于任何违反我国法律法规的一切平台研发,任何单位和个人使用本软件框架用于产品研发而产生的任何意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 ( -包括但不限于直接、间接、附带或衍生的损失等),本团队不承担任何法律责任。本软件框架只能用于公司和个人内部的法律所允许的合法合规的软件产品研发,详细声明内容请阅读《框架免责声明》附件; - -本项目包含的第三方源码和二进制文件之版权信息另行标注。 - -版权所有Copyright © 2021~2026 [djangoadmin.cn](https://www.djangoadmin.cn) All rights reserved。 - -更多细节参阅 [LICENSE](LICENSE) \ No newline at end of file +感谢 [FastAPI](https://fastapi.tiangolo.com/)、[SQLAlchemy](https://www.sqlalchemy.org/)、[Vue](https://cn.vuejs.org/)、[ElementPlus](https://element-plus.org/)、[Uvicorn](https://www.uvicorn.org/)、[Pydantic](https://docs.pydantic.dev/) 等优秀开源项目。 \ No newline at end of file diff --git a/src/common/middleware/login_log.py b/src/common/middleware/login_log.py index 7b9c34b..f1054ac 100644 --- a/src/common/middleware/login_log.py +++ b/src/common/middleware/login_log.py @@ -26,6 +26,7 @@ import time from functools import wraps from common.utils.helpers import detect_browser, detect_os, redact_params +from common.utils.ip import get_client_ip from common.utils.ip2region import get_ip_location from core.context import current_username from core.logger import logger @@ -84,6 +85,7 @@ def _record(self, username: str, log_type: int, status: int, ua = self.request.headers.get("User-Agent", "") body = self.request.body or b"" + client_ip = get_client_ip(self) # 延迟到响应写出后异步落库,不阻塞主流程 tornado.ioloop.IOLoop.current().spawn_callback( record_login_log, @@ -95,8 +97,8 @@ def _record(self, username: str, log_type: int, status: int, url=self.request.uri, param=redact_params(body.decode("utf-8", errors="replace"), _PARAM_MAX_LEN), result=result[:_RESULT_MAX_LEN], - ip=self.request.remote_ip, - location=get_ip_location(self.request.remote_ip), + ip=client_ip, + location=get_ip_location(client_ip), os=detect_os(ua), browser=detect_browser(ua), consume_time=consume_time, diff --git a/src/common/middleware/operation_log.py b/src/common/middleware/operation_log.py index 9992ed3..c5f1b79 100644 --- a/src/common/middleware/operation_log.py +++ b/src/common/middleware/operation_log.py @@ -30,6 +30,7 @@ from functools import wraps from typing import Any from common.utils.helpers import detect_browser, detect_os, detect_source, redact_params +from common.utils.ip import get_client_ip from common.utils.ip2region import get_ip_location from core.context import current_realname from core.logger import logger @@ -96,6 +97,7 @@ def _record(self: Any, module: str, action: str, status: int, ua = self.request.headers.get("User-Agent", "") body = self.request.body or b"" + client_ip = get_client_ip(self) # 延迟到响应写出后异步落库,不阻塞主流程 tornado.ioloop.IOLoop.current().spawn_callback( record_operation_log, @@ -108,8 +110,8 @@ def _record(self: Any, module: str, action: str, status: int, url=self.request.uri, param=redact_params(body.decode("utf-8", errors="replace"), _PARAM_MAX_LEN), result=result[:_RESULT_MAX_LEN], - ip=self.request.remote_ip, - location=get_ip_location(self.request.remote_ip), + ip=client_ip, + location=get_ip_location(client_ip), os=detect_os(ua), browser=detect_browser(ua), consume_time=consume_time, diff --git a/src/common/utils/ip.py b/src/common/utils/ip.py new file mode 100644 index 0000000..2469ff9 --- /dev/null +++ b/src/common/utils/ip.py @@ -0,0 +1,91 @@ +# +====================================================================== +# | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ] +# +---------------------------------------------------------------------- +# | Copyright (c) 2021-2026 小蚂蚁云团队 版权所有 +# +---------------------------------------------------------------------- +# | 开源协议: Apache-2.0 +# | 重要声明: 未经书面许可,不得移除或修改本框架相关版权标识。 +# +---------------------------------------------------------------------- +# | 官方网站: https://www.djangoadmin.cn +# +---------------------------------------------------------------------- +# | 研发团队: 小蚂蚁云团队 荣誉出品 +# +====================================================================== +# | 版权和免责声明: +# | 一、知识产权声明 +# | 本团队对该软件框架产品(以下简称"本产品")拥有完整知识产权,包括但不限于商标权、专利权、 +# | 著作权、商业秘密等。前述权利均受中华人民共和国及相关国际法律法规保护。未经本团队书面授权, +# | 任何个人或单位不得基于本产品本身申请任何形式的知识产权。 +# | 二、使用限制与禁止条款 +# | 您理解并同意,禁止将本产品用于以下任何行为: +# | 1. 任何违反中华人民共和国法律法规的用途; +# | 2. 任何侵害他人合法权益(包括但不限于人身权、财产权、知识产权等)的行为; +# | 3. 任何危害国家安全、公共利益及社会道德风尚的行为。 +# | 三、责任豁免 +# | 因使用本产品而产生的任何损失或法律纠纷(包括但不限于直接损失、间接损失、附带损失、衍生损失 +# | 以及因违约、侵权等引发的责任),本团队均不承担任何法律责任。若因违规使用本产品导致任何第三 +# | 方提起索赔或行政机关进行调查,您应独立承担全部责任。 +# | 四、违约与法律责任 +# | 如发现任何违反本声明的行为,本团队有权: +# | 1. 无条件配合公安机关及其他有权机关的调查取证工作; +# | 2. 依法追究相关方的民事责任,并要求赔偿全部损失; +# | 3. 保留进一步采取刑事控告等法律措施的权利。 +# | 五、许可范围说明 +# | 1、被授权方应视本产品源代码为核心机密信息,负有最高标准的保密与保管义务。禁止以任何形式(包 +# | 括但不限于直接或间接的分享、复制、传播、分发、转售、出租、开源、反向工程、反编译、反汇编或通 +# | 过网络服务提供给任何第三方)泄露、披露或处置源代码的全部或部分内容。任何未经授权的复制、使用、 +# | 传播行为均构成对本团队知识产权的严重侵权,本团队有权依法追究其全部法律责任,并要求赔偿因此造 +# | 成的一切经济损失及商誉损害。 +# | 2、本产品仅限于公司或个人在法律允许范围内,用于内部且合规的软件产品研发。具体权利义务以《软件 +# | 许可协议》附件为准。 +# +====================================================================== + +# +====================================================================== +# | 模块: IP地址工具 +# | 说明: 从 Tornado RequestHandler 获取客户端真实IP,支持代理透传 +# +====================================================================== + +""" +IP地址工具模块 +============================================================= + +提供客户端IP获取: +- get_client_ip: 从 Tornado RequestHandler 获取客户端真实IP + +(IP地理位置查询已迁移至 utils/ip2region 离线库) +""" + +from typing import Optional + +import tornado.web + + +# ============================================================ +# 获取客户端IP +# ============================================================ +def get_client_ip(handler: tornado.web.RequestHandler) -> str: + """ + 获取客户端真实IP地址(Tornado 版本) + + 优先级: + 1. X-Forwarded-For 最左侧IP(CDN/反代追加的真实客户端IP) + 2. X-Real-IP(Nginx proxy_set_header 常用方案) + 3. Tornado remote_ip(直连时的 socket 对端IP) + + Args: + handler: Tornado 请求处理器 + + Returns: + 客户端IP地址 + """ + # 优先从 X-Forwarded-For 取最左侧IP(由CDN/反代追加的真实客户端IP,右侧为代理节点IP) + forwarded = handler.request.headers.get("X-Forwarded-For", "") + if forwarded: + return forwarded.split(",")[0].strip() + + # 其次从 X-Real-IP 获取(Nginx proxy_set_header X-Real-IP $remote_addr) + real_ip = handler.request.headers.get("X-Real-IP", "") + if real_ip: + return real_ip.strip() + + # 最后回退到 Tornado remote_ip(直连场景) + return handler.request.remote_ip or "127.0.0.1" diff --git a/src/modules/article/handlers.py b/src/modules/article/handlers.py index f362eed..bc80b59 100644 --- a/src/modules/article/handlers.py +++ b/src/modules/article/handlers.py @@ -51,8 +51,8 @@ class ArticleAddHandler(BaseHandler): """添加文章。""" @permission_required("sys:article:add") - @check_demo @operation_log("文章管理", "添加") + @check_demo async def post(self): """POST 请求:新增文章。""" return await article_service.add(self) @@ -65,8 +65,8 @@ class ArticleUpdateHandler(BaseHandler): """更新文章。""" @permission_required("sys:article:update") - @check_demo @operation_log("文章管理", "更新") + @check_demo async def put(self): """PUT 请求:更新文章信息。""" return await article_service.update(self) @@ -79,8 +79,8 @@ class ArticleDeleteHandler(BaseHandler): """删除文章。""" @permission_required("sys:article:delete") - @check_demo @operation_log("文章管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除文章(软删除)。 @@ -96,8 +96,8 @@ class ArticleBatchDeleteHandler(BaseHandler): """批量删除文章。""" @permission_required("sys:article:delete") - @check_demo @operation_log("文章管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除文章(软删除)。""" return await article_service.batch_delete(self) @@ -110,8 +110,8 @@ class ArticleStatusHandler(BaseHandler): """设置文章状态。""" @permission_required("sys:article:status") - @check_demo @operation_log("文章管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改文章状态(如上架 / 下架)。""" return await article_service.update_status(self) diff --git a/src/modules/category/handlers.py b/src/modules/category/handlers.py index 8c78a7e..cc83e51 100644 --- a/src/modules/category/handlers.py +++ b/src/modules/category/handlers.py @@ -51,8 +51,8 @@ class CategoryAddHandler(BaseHandler): """添加文章分类。""" @permission_required("sys:category:add") - @check_demo @operation_log("文章分类", "添加") + @check_demo async def post(self): """POST 请求:新增文章分类。""" return await category_service.add(self) @@ -65,8 +65,8 @@ class CategoryUpdateHandler(BaseHandler): """更新文章分类。""" @permission_required("sys:category:update") - @check_demo @operation_log("文章分类", "更新") + @check_demo async def put(self): """PUT 请求:更新文章分类信息。""" return await category_service.update(self) @@ -79,8 +79,8 @@ class CategoryDeleteHandler(BaseHandler): """删除文章分类。""" @permission_required("sys:category:delete") - @check_demo @operation_log("文章分类", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除文章分类(软删除)。 diff --git a/src/modules/city/handlers.py b/src/modules/city/handlers.py index 74df8fe..e85a14e 100644 --- a/src/modules/city/handlers.py +++ b/src/modules/city/handlers.py @@ -53,8 +53,8 @@ class CityAddHandler(BaseHandler): """添加城市。""" @permission_required("sys:city:add") - @check_demo @operation_log("城市管理", "添加") + @check_demo async def post(self): """POST 请求:新增城市。""" return await city_service.add(self) @@ -67,8 +67,8 @@ class CityUpdateHandler(BaseHandler): """更新城市。""" @permission_required("sys:city:update") - @check_demo @operation_log("城市管理", "更新") + @check_demo async def put(self): """PUT 请求:更新城市信息。""" return await city_service.update(self) @@ -81,8 +81,8 @@ class CityDeleteHandler(BaseHandler): """删除城市。""" @permission_required("sys:city:delete") - @check_demo @operation_log("城市管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除城市(软删除)。 @@ -98,8 +98,8 @@ class CityBatchDeleteHandler(BaseHandler): """批量删除城市。""" @permission_required("sys:city:delete") - @check_demo @operation_log("城市管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除城市(软删除)。""" return await city_service.batch_delete(self) diff --git a/src/modules/configuration/config/handlers.py b/src/modules/configuration/config/handlers.py index 60e3feb..aef7360 100644 --- a/src/modules/configuration/config/handlers.py +++ b/src/modules/configuration/config/handlers.py @@ -51,8 +51,8 @@ class ConfigAddHandler(BaseHandler): """添加配置。""" @permission_required("sys:config:add") - @check_demo @operation_log("配置管理", "添加") + @check_demo async def post(self): """POST 请求:新增配置。""" return await config_service.add(self) @@ -65,8 +65,8 @@ class ConfigUpdateHandler(BaseHandler): """更新配置。""" @permission_required("sys:config:update") - @check_demo @operation_log("配置管理", "更新") + @check_demo async def put(self): """PUT 请求:更新配置信息。""" return await config_service.update(self) @@ -79,8 +79,8 @@ class ConfigDeleteHandler(BaseHandler): """删除配置。""" @permission_required("sys:config:delete") - @check_demo @operation_log("配置管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除配置(软删除)。 @@ -96,8 +96,8 @@ class ConfigBatchDeleteHandler(BaseHandler): """批量删除配置。""" @permission_required("sys:config:delete") - @check_demo @operation_log("配置管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除配置(软删除)。""" return await config_service.batch_delete(self) diff --git a/src/modules/configuration/config_item/handlers.py b/src/modules/configuration/config_item/handlers.py index 485285d..d9c19be 100644 --- a/src/modules/configuration/config_item/handlers.py +++ b/src/modules/configuration/config_item/handlers.py @@ -51,8 +51,8 @@ class ConfigItemAddHandler(BaseHandler): """添加配置项。""" @permission_required("sys:config:add") - @check_demo @operation_log("配置管理", "添加配置项") + @check_demo async def post(self): """POST 请求:新增配置项。""" return await config_item_service.add(self) @@ -65,8 +65,8 @@ class ConfigItemUpdateHandler(BaseHandler): """更新配置项。""" @permission_required("sys:config:update") - @check_demo @operation_log("配置管理", "更新配置项") + @check_demo async def put(self): """PUT 请求:更新配置项信息。""" return await config_item_service.update(self) @@ -79,8 +79,8 @@ class ConfigItemDeleteHandler(BaseHandler): """删除配置项。""" @permission_required("sys:config:delete") - @check_demo @operation_log("配置管理", "删除配置项") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除配置项(软删除)。 @@ -96,8 +96,8 @@ class ConfigItemStatusHandler(BaseHandler): """设置配置项状态。""" @permission_required("sys:config:status") - @check_demo @operation_log("配置管理", "设置配置项状态") + @check_demo async def put(self): """PUT 请求:修改配置项状态(如启用 / 禁用)。""" return await config_item_service.update_status(self) @@ -110,8 +110,8 @@ class ConfigItemBatchDeleteHandler(BaseHandler): """批量删除配置项。""" @permission_required("sys:config:delete") - @check_demo @operation_log("配置项管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除配置项(软删除)。""" return await config_item_service.batch_delete(self) diff --git a/src/modules/dept/handlers.py b/src/modules/dept/handlers.py index f0c61dc..861c295 100644 --- a/src/modules/dept/handlers.py +++ b/src/modules/dept/handlers.py @@ -51,8 +51,8 @@ class DeptAddHandler(BaseHandler): """添加部门。""" @permission_required("sys:dept:add") - @check_demo @operation_log("部门管理", "添加") + @check_demo async def post(self): """POST 请求:新增部门。""" return await dept_service.add(self) @@ -65,8 +65,8 @@ class DeptUpdateHandler(BaseHandler): """更新部门。""" @permission_required("sys:dept:update") - @check_demo @operation_log("部门管理", "更新") + @check_demo async def put(self): """PUT 请求:更新部门信息。""" return await dept_service.update(self) @@ -79,8 +79,8 @@ class DeptDeleteHandler(BaseHandler): """删除部门。""" @permission_required("sys:dept:delete") - @check_demo @operation_log("部门管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除部门(软删除)。 diff --git a/src/modules/dictionary/dict/handlers.py b/src/modules/dictionary/dict/handlers.py index 6bd1f32..5ba00d7 100644 --- a/src/modules/dictionary/dict/handlers.py +++ b/src/modules/dictionary/dict/handlers.py @@ -52,8 +52,8 @@ class DictAddHandler(BaseHandler): """添加字典。""" @permission_required("sys:dict:add") - @check_demo @operation_log("字典管理", "添加") + @check_demo async def post(self): """POST 请求:新增字典。""" return await dict_service.add(self) @@ -66,8 +66,8 @@ class DictUpdateHandler(BaseHandler): """更新字典。""" @permission_required("sys:dict:update") - @check_demo @operation_log("字典管理", "更新") + @check_demo async def put(self): """PUT 请求:更新字典信息。""" return await dict_service.update(self) @@ -80,8 +80,8 @@ class DictDeleteHandler(BaseHandler): """删除字典。""" @permission_required("sys:dict:delete") - @check_demo @operation_log("字典管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除字典(软删除)。 @@ -113,8 +113,8 @@ class DictBatchDeleteHandler(BaseHandler): """批量删除字典。""" @permission_required("sys:dict:delete") - @check_demo @operation_log("字典管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除字典(软删除)。""" return await dict_service.batch_delete(self) diff --git a/src/modules/dictionary/dict_item/handlers.py b/src/modules/dictionary/dict_item/handlers.py index f6f14db..aefcc52 100644 --- a/src/modules/dictionary/dict_item/handlers.py +++ b/src/modules/dictionary/dict_item/handlers.py @@ -51,8 +51,8 @@ class DictItemAddHandler(BaseHandler): """添加字典项。""" @permission_required("sys:dict:add") - @check_demo @operation_log("字典管理", "添加字典项") + @check_demo async def post(self): """POST 请求:新增字典项。""" return await dict_item_service.add(self) @@ -65,8 +65,8 @@ class DictItemUpdateHandler(BaseHandler): """更新字典项。""" @permission_required("sys:dict:update") - @check_demo @operation_log("字典管理", "更新字典项") + @check_demo async def put(self): """PUT 请求:更新字典项信息。""" return await dict_item_service.update(self) @@ -79,8 +79,8 @@ class DictItemDeleteHandler(BaseHandler): """删除字典项。""" @permission_required("sys:dict:delete") - @check_demo @operation_log("字典管理", "删除字典项") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除字典项(软删除)。 @@ -96,8 +96,8 @@ class DictItemBatchDeleteHandler(BaseHandler): """批量删除字典项。""" @permission_required("sys:dict:delete") - @check_demo @operation_log("字典项管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除字典项(软删除)。""" return await dict_item_service.batch_delete(self) diff --git a/src/modules/example/handlers.py b/src/modules/example/handlers.py index 701554d..74c8892 100644 --- a/src/modules/example/handlers.py +++ b/src/modules/example/handlers.py @@ -52,8 +52,8 @@ class ExampleAddHandler(BaseHandler): """添加案例演示。""" @permission_required("sys:example:add") - @check_demo @operation_log("案例演示", "添加") + @check_demo async def post(self): """POST 请求:新增案例演示。""" return await example_service.add(self) @@ -66,8 +66,8 @@ class ExampleUpdateHandler(BaseHandler): """更新案例演示。""" @permission_required("sys:example:update") - @check_demo @operation_log("案例演示", "更新") + @check_demo async def put(self): """PUT 请求:更新案例演示信息。""" return await example_service.update(self) @@ -80,8 +80,8 @@ class ExampleDeleteHandler(BaseHandler): """删除案例演示。""" @permission_required("sys:example:delete") - @check_demo @operation_log("案例演示", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除案例演示(软删除)。 @@ -97,8 +97,8 @@ class ExampleBatchDeleteHandler(BaseHandler): """批量删除案例演示。""" @permission_required("sys:example:delete") - @check_demo @operation_log("案例演示", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除案例演示(软删除)。""" return await example_service.batch_delete(self) @@ -111,8 +111,8 @@ class ExampleStatusHandler(BaseHandler): """设置案例演示状态。""" @permission_required("sys:example:status") - @check_demo @operation_log("案例演示", "设置状态") + @check_demo async def put(self): """PUT 请求:修改案例演示状态(如启用 / 禁用)。""" return await example_service.update_status(self) diff --git a/src/modules/file_template/handlers.py b/src/modules/file_template/handlers.py index 5e3bf6a..41c7d51 100644 --- a/src/modules/file_template/handlers.py +++ b/src/modules/file_template/handlers.py @@ -54,8 +54,8 @@ class FileTemplateAddHandler(BaseHandler): """添加文件模板。""" @permission_required("sys:filetemplate:add") - @check_demo @operation_log("文件模板", "添加") + @check_demo async def post(self): """POST 请求:新增文件模板。""" return await file_template_service.add(self) @@ -68,8 +68,8 @@ class FileTemplateUpdateHandler(BaseHandler): """更新文件模板。""" @permission_required("sys:filetemplate:update") - @check_demo @operation_log("文件模板", "更新") + @check_demo async def put(self): """PUT 请求:更新文件模板信息。""" return await file_template_service.update(self) @@ -82,8 +82,8 @@ class FileTemplateDeleteHandler(BaseHandler): """删除文件模板。""" @permission_required("sys:filetemplate:delete") - @check_demo @operation_log("文件模板", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除文件模板(软删除)。 @@ -99,8 +99,8 @@ class FileTemplateBatchDeleteHandler(BaseHandler): """批量删除文件模板。""" @permission_required("sys:filetemplate:delete") - @check_demo @operation_log("文件模板管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除文件模板(软删除)。""" return await file_template_service.batch_delete(self) diff --git a/src/modules/generator/handlers.py b/src/modules/generator/handlers.py index 4e01379..8ac6858 100644 --- a/src/modules/generator/handlers.py +++ b/src/modules/generator/handlers.py @@ -74,8 +74,8 @@ class GeneratorGenerateHandler(BaseHandler): """代码生成。""" @permission_required("sys:generator:generate") - @check_demo @operation_log("代码生成器", "生成代码") + @check_demo async def post(self): """POST 请求:单表/批量代码生成。 @@ -96,8 +96,8 @@ class GeneratorBatchGenerateHandler(BaseHandler): """批量代码生成。""" @permission_required("sys:generator:batchGenerate") - @check_demo @operation_log("代码生成器", "批量生成代码") + @check_demo async def post(self): """POST 请求:批量代码生成。 diff --git a/src/modules/generator/templates/handlers.py.tpl b/src/modules/generator/templates/handlers.py.tpl index febf585..5ece281 100644 --- a/src/modules/generator/templates/handlers.py.tpl +++ b/src/modules/generator/templates/handlers.py.tpl @@ -52,8 +52,8 @@ class {{ model_class_name }}AddHandler(BaseHandler): """添加{{ module_comment }}。""" @permission_required("{{ permission_prefix }}:add") - @check_demo @operation_log("{{ module_comment }}", "添加") + @check_demo async def post(self): """POST 请求:新增{{ module_comment }}。""" return await {{ app_name }}_service.add(self) @@ -66,8 +66,8 @@ class {{ model_class_name }}UpdateHandler(BaseHandler): """更新{{ module_comment }}。""" @permission_required("{{ permission_prefix }}:update") - @check_demo @operation_log("{{ module_comment }}", "更新") + @check_demo async def put(self): """PUT 请求:更新{{ module_comment }}信息。""" return await {{ app_name }}_service.update(self) @@ -80,8 +80,8 @@ class {{ model_class_name }}DeleteHandler(BaseHandler): """删除{{ module_comment }}。""" @permission_required("{{ permission_prefix }}:delete") - @check_demo @operation_log("{{ module_comment }}", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除{{ module_comment }}(软删除)。 @@ -97,8 +97,8 @@ class {{ model_class_name }}BatchDeleteHandler(BaseHandler): """批量删除{{ module_comment }}。""" @permission_required("{{ permission_prefix }}:delete") - @check_demo @operation_log("{{ module_comment }}", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除{{ module_comment }}(软删除)。""" return await {{ app_name }}_service.batch_delete(self) @@ -112,8 +112,8 @@ class {{ model_class_name }}StatusHandler(BaseHandler): """设置{{ module_comment }}状态。""" @permission_required("{{ permission_prefix }}:status") - @check_demo @operation_log("{{ module_comment }}", "设置状态") + @check_demo async def put(self): """PUT 请求:修改{{ module_comment }}状态(如启用 / 禁用)。""" return await {{ app_name }}_service.update_status(self) diff --git a/src/modules/job/handlers.py b/src/modules/job/handlers.py index d53817c..a0d9bef 100644 --- a/src/modules/job/handlers.py +++ b/src/modules/job/handlers.py @@ -57,8 +57,8 @@ class JobAddHandler(BaseHandler): """添加任务。""" @permission_required("sys:job:add") - @check_demo @operation_log("任务调度", "添加") + @check_demo async def post(self): """POST 请求:新增任务。""" return await job_service.add(self) @@ -71,8 +71,8 @@ class JobUpdateHandler(BaseHandler): """更新任务。""" @permission_required("sys:job:update") - @check_demo @operation_log("任务调度", "更新") + @check_demo async def put(self): """PUT 请求:更新任务信息。""" return await job_service.update(self) @@ -85,8 +85,8 @@ class JobDeleteHandler(BaseHandler): """删除任务。""" @permission_required("sys:job:delete") - @check_demo @operation_log("任务调度", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除任务(软删除)。 @@ -102,8 +102,8 @@ class JobStatusHandler(BaseHandler): """设置任务状态。""" @permission_required("sys:job:status") - @check_demo @operation_log("任务调度", "设置状态") + @check_demo async def post(self): """PUT 请求:修改任务状态(如启用 / 暂停)。""" return await job_service.update_status(self) @@ -116,8 +116,8 @@ class JobRunOnceHandler(BaseHandler): """立即执行任务。""" @permission_required("sys:job:runOnce") - @check_demo @operation_log("任务调度", "立即执行") + @check_demo async def post(self, id): """POST 请求:立即执行指定任务。 @@ -133,8 +133,8 @@ class JobBatchDeleteHandler(BaseHandler): """批量删除任务。""" @permission_required("sys:job:delete") - @check_demo @operation_log("任务管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除任务(软删除)。""" return await job_service.batch_delete(self) @@ -147,8 +147,8 @@ class JobPauseHandler(BaseHandler): """暂停任务。""" @permission_required("sys:job:status") - @check_demo @operation_log("任务调度", "暂停任务") + @check_demo async def put(self, id): """PUT 请求:暂停指定任务。 @@ -164,8 +164,8 @@ class JobResumeHandler(BaseHandler): """恢复任务。""" @permission_required("sys:job:status") - @check_demo @operation_log("任务调度", "恢复任务") + @check_demo async def put(self, id): """PUT 请求:恢复指定任务。 @@ -181,8 +181,8 @@ class JobReloadHandler(BaseHandler): """重新加载任务。""" @permission_required("sys:job:reload") - @check_demo @operation_log("任务调度", "重新加载任务") + @check_demo async def post(self): """POST 请求:重新加载所有任务。""" return await job_service.reload(self) diff --git a/src/modules/job_log/handlers.py b/src/modules/job_log/handlers.py index 86ee5e3..9051e42 100644 --- a/src/modules/job_log/handlers.py +++ b/src/modules/job_log/handlers.py @@ -68,8 +68,8 @@ class JobLogBatchDeleteHandler(BaseHandler): """批量删除任务日志。""" @permission_required("sys:joblog:delete") - @check_demo @operation_log("任务日志管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除任务日志(软删除)。""" return await job_log_service.batch_delete(self) diff --git a/src/modules/level/handlers.py b/src/modules/level/handlers.py index 1bf2f09..22ce8a3 100644 --- a/src/modules/level/handlers.py +++ b/src/modules/level/handlers.py @@ -51,8 +51,8 @@ class LevelAddHandler(BaseHandler): """添加职级。""" @permission_required("sys:level:add") - @check_demo @operation_log("职级管理", "添加") + @check_demo async def post(self): """POST 请求:新增职级。""" return await level_service.add(self) @@ -65,8 +65,8 @@ class LevelUpdateHandler(BaseHandler): """更新职级。""" @permission_required("sys:level:update") - @check_demo @operation_log("职级管理", "更新") + @check_demo async def put(self): """PUT 请求:更新职级信息。""" return await level_service.update(self) @@ -79,8 +79,8 @@ class LevelDeleteHandler(BaseHandler): """删除职级。""" @permission_required("sys:level:delete") - @check_demo @operation_log("职级管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除职级(软删除)。 @@ -96,8 +96,8 @@ class LevelStatusHandler(BaseHandler): """设置职级状态。""" @permission_required("sys:level:status") - @check_demo @operation_log("职级管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改职级状态(如启用 / 禁用)。""" return await level_service.update_status(self) @@ -110,8 +110,8 @@ class LevelImportHandler(BaseHandler): """导入职级 Excel。""" @permission_required("sys:level:import") - @check_demo @operation_log("职级管理", "导入") + @check_demo async def post(self): """POST 请求:从 Excel 导入职级数据。""" return level_service.level_import(self) @@ -148,8 +148,8 @@ class LevelBatchDeleteHandler(BaseHandler): """批量删除职级。""" @permission_required("sys:level:delete") - @check_demo @operation_log("职级管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除职级(软删除)。""" return await level_service.batch_delete(self) diff --git a/src/modules/link/handlers.py b/src/modules/link/handlers.py index 6d1bca2..7836e71 100644 --- a/src/modules/link/handlers.py +++ b/src/modules/link/handlers.py @@ -51,8 +51,8 @@ class LinkAddHandler(BaseHandler): """添加友链。""" @permission_required("sys:link:add") - @check_demo @operation_log("友链管理", "添加") + @check_demo async def post(self): """POST 请求:新增友链。""" return await link_service.add(self) @@ -65,8 +65,8 @@ class LinkUpdateHandler(BaseHandler): """更新友链。""" @permission_required("sys:link:update") - @check_demo @operation_log("友链管理", "更新") + @check_demo async def put(self): """PUT 请求:更新友链信息。""" return await link_service.update(self) @@ -79,8 +79,8 @@ class LinkDeleteHandler(BaseHandler): """删除友链。""" @permission_required("sys:link:delete") - @check_demo @operation_log("友链管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除友链(软删除)。 @@ -96,8 +96,8 @@ class LinkStatusHandler(BaseHandler): """设置友链状态。""" @permission_required("sys:link:status") - @check_demo @operation_log("友链管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改友链状态(如显示 / 隐藏)。""" return await link_service.update_status(self) @@ -110,8 +110,8 @@ class LinkBatchDeleteHandler(BaseHandler): """批量删除友链。""" @permission_required("sys:link:delete") - @check_demo @operation_log("友链管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除友链(软删除)。""" return await link_service.batch_delete(self) diff --git a/src/modules/login_log/handlers.py b/src/modules/login_log/handlers.py index 4f9d7bc..ddb2eae 100644 --- a/src/modules/login_log/handlers.py +++ b/src/modules/login_log/handlers.py @@ -58,8 +58,8 @@ class LoginLogDeleteHandler(BaseHandler): """删除登录日志。""" @permission_required("sys:loginLog:delete") - @check_demo @operation_log("登录日志管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除登录日志(软删除)。 @@ -75,8 +75,8 @@ class LoginLogBatchDeleteHandler(BaseHandler): """批量删除登录日志。""" @permission_required("sys:loginLog:delete") - @check_demo @operation_log("登录日志管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除登录日志(软删除)。""" return await login_log_service.batch_delete(self) diff --git a/src/modules/menu/handlers.py b/src/modules/menu/handlers.py index e48b7d6..cf25821 100644 --- a/src/modules/menu/handlers.py +++ b/src/modules/menu/handlers.py @@ -57,8 +57,8 @@ class MenuAddHandler(BaseHandler): """添加菜单。""" @permission_required("sys:menu:add") - @check_demo @operation_log("菜单管理", "添加") + @check_demo async def post(self): """POST 请求:新增菜单。""" return await menu_service.add(self) @@ -71,8 +71,8 @@ class MenuUpdateHandler(BaseHandler): """更新菜单。""" @permission_required("sys:menu:update") - @check_demo @operation_log("菜单管理", "更新") + @check_demo async def put(self): """PUT 请求:更新菜单信息。""" return await menu_service.update(self) @@ -85,8 +85,8 @@ class MenuDeleteHandler(BaseHandler): """删除菜单。""" @permission_required("sys:menu:delete") - @check_demo @operation_log("菜单管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除菜单(软删除)。 diff --git a/src/modules/notice/handlers.py b/src/modules/notice/handlers.py index 2917654..22c5def 100644 --- a/src/modules/notice/handlers.py +++ b/src/modules/notice/handlers.py @@ -51,8 +51,8 @@ class NoticeAddHandler(BaseHandler): """添加通知公告。""" @permission_required("sys:notice:add") - @check_demo @operation_log("通知公告", "添加") + @check_demo async def post(self): """POST 请求:新增通知公告。""" return await notice_service.add(self) @@ -65,8 +65,8 @@ class NoticeUpdateHandler(BaseHandler): """更新通知公告。""" @permission_required("sys:notice:update") - @check_demo @operation_log("通知公告", "更新") + @check_demo async def put(self): """PUT 请求:更新通知公告信息。""" return await notice_service.update(self) @@ -79,8 +79,8 @@ class NoticeDeleteHandler(BaseHandler): """删除通知公告。""" @permission_required("sys:notice:delete") - @check_demo @operation_log("通知公告", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除通知公告(软删除)。 @@ -96,8 +96,8 @@ class NoticeBatchDeleteHandler(BaseHandler): """批量删除通知公告。""" @permission_required("sys:notice:delete") - @check_demo @operation_log("通知公告管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除通知公告(软删除)。""" return await notice_service.batch_delete(self) diff --git a/src/modules/operation_log/handlers.py b/src/modules/operation_log/handlers.py index e3c8d41..502f1c3 100644 --- a/src/modules/operation_log/handlers.py +++ b/src/modules/operation_log/handlers.py @@ -58,8 +58,8 @@ class OperationLogDeleteHandler(BaseHandler): """删除操作日志。""" @permission_required("sys:operationLog:delete") - @check_demo @operation_log("操作日志管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除操作日志(软删除)。 @@ -75,8 +75,8 @@ class OperationLogBatchDeleteHandler(BaseHandler): """批量删除操作日志。""" @permission_required("sys:operationLog:delete") - @check_demo @operation_log("操作日志管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除操作日志(软删除)。""" return await operation_log_service.batch_delete(self) diff --git a/src/modules/param/handlers.py b/src/modules/param/handlers.py index 2960747..b7cf2d5 100644 --- a/src/modules/param/handlers.py +++ b/src/modules/param/handlers.py @@ -51,8 +51,8 @@ class ParamAddHandler(BaseHandler): """添加参数。""" @permission_required("sys:param:add") - @check_demo @operation_log("参数管理", "添加") + @check_demo async def post(self): """POST 请求:新增参数。""" return await param_service.add(self) @@ -65,8 +65,8 @@ class ParamUpdateHandler(BaseHandler): """更新参数。""" @permission_required("sys:param:update") - @check_demo @operation_log("参数管理", "更新") + @check_demo async def put(self): """PUT 请求:更新参数信息。""" return await param_service.update(self) @@ -79,8 +79,8 @@ class ParamDeleteHandler(BaseHandler): """删除参数。""" @permission_required("sys:param:delete") - @check_demo @operation_log("参数管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除参数(软删除)。 @@ -96,8 +96,8 @@ class ParamStatusHandler(BaseHandler): """设置参数状态。""" @permission_required("sys:param:status") - @check_demo @operation_log("参数管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改参数状态(如启用 / 禁用)。""" return await param_service.update_status(self) @@ -110,8 +110,8 @@ class ParamBatchDeleteHandler(BaseHandler): """批量删除参数。""" @permission_required("sys:param:delete") - @check_demo @operation_log("参数管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除参数(软删除)。""" return await param_service.batch_delete(self) diff --git a/src/modules/position/handlers.py b/src/modules/position/handlers.py index cf2e200..9c96555 100644 --- a/src/modules/position/handlers.py +++ b/src/modules/position/handlers.py @@ -51,8 +51,8 @@ class PositionAddHandler(BaseHandler): """添加岗位。""" @permission_required("sys:position:add") - @check_demo @operation_log("岗位管理", "添加") + @check_demo async def post(self): """POST 请求:新增岗位。""" return await position_service.add(self) @@ -65,8 +65,8 @@ class PositionUpdateHandler(BaseHandler): """更新岗位。""" @permission_required("sys:position:update") - @check_demo @operation_log("岗位管理", "更新") + @check_demo async def put(self): """PUT 请求:更新岗位信息。""" return await position_service.update(self) @@ -79,8 +79,8 @@ class PositionDeleteHandler(BaseHandler): """删除岗位。""" @permission_required("sys:position:delete") - @check_demo @operation_log("岗位管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除岗位(软删除)。 @@ -96,8 +96,8 @@ class PositionStatusHandler(BaseHandler): """设置岗位状态。""" @permission_required("sys:position:status") - @check_demo @operation_log("岗位管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改岗位状态(如启用 / 禁用)。""" return await position_service.update_status(self) @@ -121,8 +121,8 @@ class PositionBatchDeleteHandler(BaseHandler): """批量删除岗位。""" @permission_required("sys:position:delete") - @check_demo @operation_log("岗位管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除岗位(软删除)。""" return await position_service.batch_delete(self) diff --git a/src/modules/role/handlers.py b/src/modules/role/handlers.py index c3af09d..b7780df 100644 --- a/src/modules/role/handlers.py +++ b/src/modules/role/handlers.py @@ -57,8 +57,8 @@ class RoleAddHandler(BaseHandler): """添加角色。""" @permission_required("sys:role:add") - @check_demo @operation_log("角色管理", "添加") + @check_demo async def post(self): """POST 请求:新增角色。""" return await role_service.add(self) @@ -71,8 +71,8 @@ class RoleUpdateHandler(BaseHandler): """更新角色。""" @permission_required("sys:role:update") - @check_demo @operation_log("角色管理", "更新") + @check_demo async def put(self): """PUT 请求:更新角色信息。""" return await role_service.update(self) @@ -85,8 +85,8 @@ class RoleDeleteHandler(BaseHandler): """删除角色。""" @permission_required("sys:role:delete") - @check_demo @operation_log("角色管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除角色(软删除)。 @@ -113,8 +113,8 @@ class RoleBatchDeleteHandler(BaseHandler): """批量删除角色。""" @permission_required("sys:role:delete") - @check_demo @operation_log("角色管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除角色(软删除)。""" return await role_service.batch_delete(self) diff --git a/src/modules/role_menu/handlers.py b/src/modules/role_menu/handlers.py index a673df8..e7765b2 100644 --- a/src/modules/role_menu/handlers.py +++ b/src/modules/role_menu/handlers.py @@ -40,8 +40,8 @@ class RoleMenuSaveHandler(BaseHandler): """保存角色菜单数据。""" @permission_required("sys:role:savePermission") - @check_demo @operation_log("角色管理", "保存角色菜单") + @check_demo async def post(self): """POST 请求:保存角色菜单分配。""" # 局部导入,避免顶层依赖 diff --git a/src/modules/user/handlers.py b/src/modules/user/handlers.py index 06ffbfe..8f1556c 100644 --- a/src/modules/user/handlers.py +++ b/src/modules/user/handlers.py @@ -62,8 +62,8 @@ class UserAddHandler(BaseHandler): """添加用户。""" @permission_required("sys:user:add") - @check_demo @operation_log("用户管理", "添加") + @check_demo async def post(self): """POST 请求:新增用户。""" return await user_service.add(self) @@ -76,8 +76,8 @@ class UserUpdateHandler(BaseHandler): """更新用户。""" @permission_required("sys:user:update") - @check_demo @operation_log("用户管理", "更新") + @check_demo async def put(self): """PUT 请求:更新用户信息。""" return await user_service.update(self) @@ -90,8 +90,8 @@ class UserDeleteHandler(BaseHandler): """删除用户。""" @permission_required("sys:user:delete") - @check_demo @operation_log("用户管理", "删除") + @check_demo async def delete(self, id): """DELETE 请求:按 ID 删除用户(软删除)。 @@ -107,8 +107,8 @@ class UserStatusHandler(BaseHandler): """设置用户状态。""" @permission_required("sys:user:status") - @check_demo @operation_log("用户管理", "设置状态") + @check_demo async def put(self): """PUT 请求:修改用户状态(如启用 / 禁用)。""" return await user_service.update_status(self) @@ -121,8 +121,8 @@ class UserResetPwdHandler(BaseHandler): """重置用户密码。""" @permission_required("sys:user:resetPwd") - @check_demo @operation_log("用户管理", "重置密码") + @check_demo async def put(self): """PUT 请求:重置指定用户的密码。""" return await user_service.user_reset_pwd(self) @@ -193,8 +193,8 @@ class ProfileHandler(BaseHandler): class ProfileUpdateHandler(BaseHandler): """修改个人信息。""" - @check_demo @operation_log("用户管理", "修改个人信息") + @check_demo async def put(self): """PUT 请求:更新当前登录用户的个人资料。""" return await user_service.update_profile(self) @@ -206,8 +206,8 @@ class ProfileUpdateHandler(BaseHandler): class PasswordUpdateHandler(BaseHandler): """修改密码。""" - @check_demo @operation_log("用户管理", "修改密码") + @check_demo async def put(self): """PUT 请求:修改当前登录用户的密码。""" return await user_service.update_password(self) @@ -220,8 +220,8 @@ class UserBatchDeleteHandler(BaseHandler): """批量删除用户。""" @permission_required("sys:user:delete") - @check_demo @operation_log("用户管理", "批量删除") + @check_demo async def post(self): """POST 请求:批量删除用户(软删除)。""" return await user_service.batch_delete(self) @@ -234,8 +234,8 @@ class UserImportHandler(BaseHandler): """导入 Excel。""" @permission_required("sys:user:import") - @check_demo @operation_log("用户管理", "导入") + @check_demo async def post(self): """POST 请求:通过 Excel 文件批量导入用户数据。""" return import_users(self) diff --git a/src/modules/user_role/handlers.py b/src/modules/user_role/handlers.py index dcd1d9c..f42731f 100644 --- a/src/modules/user_role/handlers.py +++ b/src/modules/user_role/handlers.py @@ -40,8 +40,8 @@ class UserRoleSaveHandler(BaseHandler): """设置用户角色。""" @permission_required("sys:user:role:save") - @check_demo @operation_log("用户管理", "设置用户角色") + @check_demo async def post(self): """POST 请求:设置用户角色(全量替换)。 @@ -61,8 +61,8 @@ class UserRoleDeleteHandler(BaseHandler): """删除用户角色。""" @permission_required("sys:user:role:delete") - @check_demo @operation_log("用户管理", "删除用户角色") + @check_demo async def delete(self, userId, roleId): """DELETE 请求:删除指定用户的角色关联。 @@ -79,8 +79,8 @@ class UserRoleClearHandler(BaseHandler): """清空用户角色。""" @permission_required("sys:user:role:delete") - @check_demo @operation_log("用户管理", "清空用户角色") + @check_demo async def delete(self, userId): """DELETE 请求:清空指定用户的所有角色。