fred-admin 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fred_admin/__init__.py +91 -0
- fred_admin/common/AliyunSms.py +66 -0
- fred_admin/common/Blueprints.py +99 -0
- fred_admin/common/Email.py +23 -0
- fred_admin/common/Extensions.py +319 -0
- fred_admin/common/HandleExcetion.py +204 -0
- fred_admin/common/ImageVerification.py +117 -0
- fred_admin/common/IoTDBClient.py +698 -0
- fred_admin/common/PageSchema.py +65 -0
- fred_admin/common/Response.py +251 -0
- fred_admin/common/Route.py +390 -0
- fred_admin/common/RuntimeHook.py +111 -0
- fred_admin/common/SchedulerLog.py +277 -0
- fred_admin/common/Sqlacodegen.py +170 -0
- fred_admin/common/Swagger.py +77 -0
- fred_admin/common/SystemLog.py +80 -0
- fred_admin/common/Utils.py +1060 -0
- fred_admin/common/WechatLogin.py +97 -0
- fred_admin/common/__init__.py +3 -0
- fred_admin/config/Config.py +104 -0
- fred_admin/config/Logger.py +34 -0
- fred_admin/config/__init__.py +3 -0
- fred_admin/create_module.py +787 -0
- fred_admin/demo/app.py +6 -0
- fred_admin/demo/common/__init__.py +1 -0
- fred_admin/demo/common/config/Config.py +82 -0
- fred_admin/demo/common/config/README.md +8 -0
- fred_admin/demo/common/config/__init__.py +1 -0
- fred_admin/demo/common/config/__pycache__/Config.cpython-312.pyc +0 -0
- fred_admin/demo/common/config/__pycache__/__init__.cpython-312.pyc +0 -0
- fred_admin/demo/common/config/jwt_secret_key +1 -0
- fred_admin/demo/common/config/session_secret_key +1 -0
- fred_admin/demo/common/model/__pycache__/__init__.cpython-312.pyc +0 -0
- fred_admin/demo/common/model/__pycache__/model.cpython-312.pyc +0 -0
- fred_admin/demo/common/model/model.py +274 -0
- fred_admin/demo/demo_.gitignore +42 -0
- fred_admin/demo/modules/__init__.py +1 -0
- fred_admin/demo/modules/admin/README.md +38 -0
- fred_admin/demo/modules/admin/__init__.py +3 -0
- fred_admin/demo/modules/admin/backend/__init__.py +7 -0
- fred_admin/demo/modules/admin/backend/constant/RedisKey.py +10 -0
- fred_admin/demo/modules/admin/backend/controller/AdminAuthController.py +39 -0
- fred_admin/demo/modules/admin/backend/controller/AdminController.py +226 -0
- fred_admin/demo/modules/admin/backend/controller/ApiAuthController.py +93 -0
- fred_admin/demo/modules/admin/backend/controller/ButtonManageController.py +90 -0
- fred_admin/demo/modules/admin/backend/controller/FileController.py +28 -0
- fred_admin/demo/modules/admin/backend/controller/OrganizationController.py +218 -0
- fred_admin/demo/modules/admin/backend/controller/RoleController.py +143 -0
- fred_admin/demo/modules/admin/backend/controller/SystemController.py +112 -0
- fred_admin/demo/modules/admin/backend/controller/SystemLogController.py +63 -0
- fred_admin/demo/modules/admin/backend/controller/TableController.py +175 -0
- fred_admin/demo/modules/admin/backend/controller/__init__.py +55 -0
- fred_admin/demo/modules/admin/backend/schema/AdminSchema.py +356 -0
- fred_admin/demo/modules/admin/backend/schema/ApiAuthSchema.py +72 -0
- fred_admin/demo/modules/admin/backend/schema/AuthMenuSchema.py +79 -0
- fred_admin/demo/modules/admin/backend/schema/ButtonManageSchema.py +98 -0
- fred_admin/demo/modules/admin/backend/schema/OrganizationSchema.py +134 -0
- fred_admin/demo/modules/admin/backend/schema/RoleSchema.py +94 -0
- fred_admin/demo/modules/admin/backend/schema/SystemConfigSchema.py +115 -0
- fred_admin/demo/modules/admin/backend/schema/TableSchema.py +153 -0
- fred_admin/demo/modules/admin/backend/schema/UploadImg.py +35 -0
- fred_admin/demo/modules/admin/backend/schema/__init__.py +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/AdminSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/ApiAuthSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/AuthMenuSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/ButtonManageSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/OrganizationSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/RoleSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/SystemConfigSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/TableSchema.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/UploadImg.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/schema/__pycache__/__init__.cpython-312.pyc +0 -0
- fred_admin/demo/modules/admin/backend/service/AdminService.py +377 -0
- fred_admin/demo/modules/admin/backend/service/ApiAuthService.py +237 -0
- fred_admin/demo/modules/admin/backend/service/AuthButtonsService.py +155 -0
- fred_admin/demo/modules/admin/backend/service/AuthMenuService.py +265 -0
- fred_admin/demo/modules/admin/backend/service/ButtonManageService.py +386 -0
- fred_admin/demo/modules/admin/backend/service/ButtonManageService.py.broken +113 -0
- fred_admin/demo/modules/admin/backend/service/FileService.py +33 -0
- fred_admin/demo/modules/admin/backend/service/OrganizationService.py +465 -0
- fred_admin/demo/modules/admin/backend/service/RoleService.py +445 -0
- fred_admin/demo/modules/admin/backend/service/SystemConfigService.py +89 -0
- fred_admin/demo/modules/admin/backend/service/SystemLogService.py +142 -0
- fred_admin/demo/modules/admin/backend/service/TableService.py +978 -0
- fred_admin/demo/modules/admin/backend/service/__init__.py +1 -0
- fred_admin/demo/modules/admin/backend/sql/app.db +0 -0
- fred_admin/demo/modules/admin/backend/sql/fred.sql +3780 -0
- fred_admin/demo/modules/admin/frontend/LICENSE +21 -0
- fred_admin/demo/modules/admin/frontend/build/getEnv.ts +46 -0
- fred_admin/demo/modules/admin/frontend/build/plugins.ts +118 -0
- fred_admin/demo/modules/admin/frontend/build/proxy.ts +30 -0
- fred_admin/demo/modules/admin/frontend/commitlint.config.cjs +162 -0
- fred_admin/demo/modules/admin/frontend/demo_editorconfig +15 -0
- fred_admin/demo/modules/admin/frontend/demo_env +15 -0
- fred_admin/demo/modules/admin/frontend/demo_env.development +21 -0
- fred_admin/demo/modules/admin/frontend/demo_env.production +25 -0
- fred_admin/demo/modules/admin/frontend/demo_eslintignore +15 -0
- fred_admin/demo/modules/admin/frontend/demo_eslintrc.cjs +61 -0
- fred_admin/demo/modules/admin/frontend/demo_gitignore +27 -0
- fred_admin/demo/modules/admin/frontend/demo_prettierignore +9 -0
- fred_admin/demo/modules/admin/frontend/demo_prettierrc.cjs +41 -0
- fred_admin/demo/modules/admin/frontend/demo_stylelintignore +4 -0
- fred_admin/demo/modules/admin/frontend/demo_stylelintrc.cjs +40 -0
- fred_admin/demo/modules/admin/frontend/index.html +105 -0
- fred_admin/demo/modules/admin/frontend/lint-staged.config.cjs +8 -0
- fred_admin/demo/modules/admin/frontend/package.json +129 -0
- fred_admin/demo/modules/admin/frontend/pnpm-lock.yaml +11150 -0
- fred_admin/demo/modules/admin/frontend/postcss.config.cjs +5 -0
- fred_admin/demo/modules/admin/frontend/public/logo.png +0 -0
- fred_admin/demo/modules/admin/frontend/public/vue.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/App.vue +44 -0
- fred_admin/demo/modules/admin/frontend/src/api/config/servicePort.ts +2 -0
- fred_admin/demo/modules/admin/frontend/src/api/helper/axiosCancel.ts +57 -0
- fred_admin/demo/modules/admin/frontend/src/api/helper/checkStatus.ts +43 -0
- fred_admin/demo/modules/admin/frontend/src/api/index.ts +167 -0
- fred_admin/demo/modules/admin/frontend/src/api/interface/index.ts +179 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/adminModel.ts +135 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/apiAuthModel.ts +72 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/index.ts +24 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/loginModel.ts +79 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/roleModel.ts +68 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/storeModel.ts +80 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/systemModel.ts +162 -0
- fred_admin/demo/modules/admin/frontend/src/api/model/uploadModel.ts +153 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/admin.ts +76 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/apiAuth.ts +53 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/buttonManage.ts +119 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/dataBase.ts +60 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/login.ts +54 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/organization.ts +123 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/role.ts +61 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/store.ts +303 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/system.ts +125 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/upload.ts +132 -0
- fred_admin/demo/modules/admin/frontend/src/api/modules/user.ts +63 -0
- fred_admin/demo/modules/admin/frontend/src/assets/fonts/DIN.otf +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/fonts/MetroDF.ttf +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/fonts/YouSheBiaoTiHei.ttf +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/fonts/font.scss +14 -0
- fred_admin/demo/modules/admin/frontend/src/assets/iconfont/iconfont.scss +51 -0
- fred_admin/demo/modules/admin/frontend/src/assets/iconfont/iconfont.ttf +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingdaoyu.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingdiqiu.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingditu.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingfanchuan.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingfeiji.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxinglvhangriji.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingtianqiyubao.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingxiangjipaizhao.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingxiarilengyin.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingyoulun.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingzijiayou.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/403.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/404.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/500.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/avatar.gif +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_bg.svg +33 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left1.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left2.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left3.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left4.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/login_left5.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/logo.svg +1 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/msg01.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/msg02.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/msg03.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/msg04.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/msg05.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/notData.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/images/welcome.png +0 -0
- fred_admin/demo/modules/admin/frontend/src/assets/json/authButtonList.json +8 -0
- fred_admin/demo/modules/admin/frontend/src/assets/json/authMenuList.json +1075 -0
- fred_admin/demo/modules/admin/frontend/src/assets/mock/Easy-Mock-API.zip +0 -0
- fred_admin/demo/modules/admin/frontend/src/components/ECharts/config/index.ts +72 -0
- fred_admin/demo/modules/admin/frontend/src/components/ECharts/index.vue +104 -0
- fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/403.vue +19 -0
- fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/404.vue +19 -0
- fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/500.vue +19 -0
- fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/index.scss +32 -0
- fred_admin/demo/modules/admin/frontend/src/components/Grid/components/GridItem.vue +68 -0
- fred_admin/demo/modules/admin/frontend/src/components/Grid/index.vue +167 -0
- fred_admin/demo/modules/admin/frontend/src/components/Grid/interface/index.ts +6 -0
- fred_admin/demo/modules/admin/frontend/src/components/ImageCaptcha/index.vue +71 -0
- fred_admin/demo/modules/admin/frontend/src/components/ImportExcel/index.scss +3 -0
- fred_admin/demo/modules/admin/frontend/src/components/ImportExcel/index.vue +151 -0
- fred_admin/demo/modules/admin/frontend/src/components/JsonViewer/index.vue +249 -0
- fred_admin/demo/modules/admin/frontend/src/components/Loading/fullScreen.ts +45 -0
- fred_admin/demo/modules/admin/frontend/src/components/Loading/index.scss +67 -0
- fred_admin/demo/modules/admin/frontend/src/components/Loading/index.vue +13 -0
- fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/ColSetting.vue +45 -0
- fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/Pagination.vue +101 -0
- fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/TableColumn.vue +58 -0
- fred_admin/demo/modules/admin/frontend/src/components/ProTable/index.vue +348 -0
- fred_admin/demo/modules/admin/frontend/src/components/ProTable/interface/index.ts +87 -0
- fred_admin/demo/modules/admin/frontend/src/components/SearchForm/components/SearchFormItem.vue +96 -0
- fred_admin/demo/modules/admin/frontend/src/components/SearchForm/index.vue +98 -0
- fred_admin/demo/modules/admin/frontend/src/components/SelectFilter/index.scss +63 -0
- fred_admin/demo/modules/admin/frontend/src/components/SelectFilter/index.vue +110 -0
- fred_admin/demo/modules/admin/frontend/src/components/SelectIcon/index.scss +39 -0
- fred_admin/demo/modules/admin/frontend/src/components/SelectIcon/index.vue +90 -0
- fred_admin/demo/modules/admin/frontend/src/components/StoreFilter/index.vue +356 -0
- fred_admin/demo/modules/admin/frontend/src/components/SvgIcon/index.vue +22 -0
- fred_admin/demo/modules/admin/frontend/src/components/SwitchDark/index.vue +12 -0
- fred_admin/demo/modules/admin/frontend/src/components/TreeFilter/index.scss +44 -0
- fred_admin/demo/modules/admin/frontend/src/components/TreeFilter/index.vue +165 -0
- fred_admin/demo/modules/admin/frontend/src/components/Upload/Img.vue +304 -0
- fred_admin/demo/modules/admin/frontend/src/components/Upload/Imgs.vue +316 -0
- fred_admin/demo/modules/admin/frontend/src/components/WangEditor/index.scss +28 -0
- fred_admin/demo/modules/admin/frontend/src/components/WangEditor/index.vue +154 -0
- fred_admin/demo/modules/admin/frontend/src/config/amapMap.ts +11 -0
- fred_admin/demo/modules/admin/frontend/src/config/index.ts +16 -0
- fred_admin/demo/modules/admin/frontend/src/config/nprogress.ts +12 -0
- fred_admin/demo/modules/admin/frontend/src/directives/index.ts +28 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/auth.ts +26 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/copy.ts +37 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/debounce.ts +31 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/draggable.ts +49 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/longpress.ts +49 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/throttle.ts +41 -0
- fred_admin/demo/modules/admin/frontend/src/directives/modules/waterMarker.ts +36 -0
- fred_admin/demo/modules/admin/frontend/src/enums/httpEnum.ts +35 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/interface/index.ts +32 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useAuthButtons.ts +22 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useDownload.ts +42 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useHandleData.ts +41 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useI18n.ts +51 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useOnline.ts +31 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useSelection.ts +34 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useTable.ts +150 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useTheme.ts +111 -0
- fred_admin/demo/modules/admin/frontend/src/hooks/useTime.ts +38 -0
- fred_admin/demo/modules/admin/frontend/src/languages/index.ts +32 -0
- fred_admin/demo/modules/admin/frontend/src/languages/modules/en.ts +978 -0
- fred_admin/demo/modules/admin/frontend/src/languages/modules/zh.ts +996 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutClassic/index.scss +60 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutClassic/index.vue +62 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutColumns/index.scss +95 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutColumns/index.vue +103 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutTransverse/index.scss +60 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutTransverse/index.vue +61 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutVertical/index.scss +48 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/LayoutVertical/index.vue +56 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Footer/index.scss +11 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Footer/index.vue +9 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/ToolBarLeft.vue +23 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/ToolBarRight.vue +51 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/AssemblySize.vue +37 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Avatar.vue +79 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Breadcrumb.vue +122 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/CollapseIcon.vue +21 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Fullscreen.vue +25 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/InfoDialog.vue +22 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Language.vue +38 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Message.vue +109 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/PasswordDialog.vue +81 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/SearchMenu.vue +183 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/ThemeSetting.vue +12 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/components/Maximize.vue +39 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/index.scss +10 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/index.vue +88 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Menu/SubMenu.vue +85 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/components/MoreButton.vue +85 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/index.scss +69 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/index.vue +115 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/ThemeDrawer/index.scss +137 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/components/ThemeDrawer/index.vue +191 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/index.vue +42 -0
- fred_admin/demo/modules/admin/frontend/src/layouts/indexAsync.vue +46 -0
- fred_admin/demo/modules/admin/frontend/src/main.ts +45 -0
- fred_admin/demo/modules/admin/frontend/src/routers/index.ts +106 -0
- fred_admin/demo/modules/admin/frontend/src/routers/modules/dynamicRouter.ts +99 -0
- fred_admin/demo/modules/admin/frontend/src/routers/modules/staticRouter.ts +63 -0
- fred_admin/demo/modules/admin/frontend/src/stores/helper/persist.ts +19 -0
- fred_admin/demo/modules/admin/frontend/src/stores/index.ts +8 -0
- fred_admin/demo/modules/admin/frontend/src/stores/interface/index.ts +63 -0
- fred_admin/demo/modules/admin/frontend/src/stores/modules/auth.ts +50 -0
- fred_admin/demo/modules/admin/frontend/src/stores/modules/global.ts +55 -0
- fred_admin/demo/modules/admin/frontend/src/stores/modules/keepAlive.ts +25 -0
- fred_admin/demo/modules/admin/frontend/src/stores/modules/tabs.ts +78 -0
- fred_admin/demo/modules/admin/frontend/src/stores/modules/user.ts +23 -0
- fred_admin/demo/modules/admin/frontend/src/styles/common.scss +129 -0
- fred_admin/demo/modules/admin/frontend/src/styles/element-dark.scss +28 -0
- fred_admin/demo/modules/admin/frontend/src/styles/element.scss +264 -0
- fred_admin/demo/modules/admin/frontend/src/styles/modules/annotation.scss +746 -0
- fred_admin/demo/modules/admin/frontend/src/styles/modules/assembly.scss +714 -0
- fred_admin/demo/modules/admin/frontend/src/styles/modules/device-manager.scss +659 -0
- fred_admin/demo/modules/admin/frontend/src/styles/modules/directives.scss +381 -0
- fred_admin/demo/modules/admin/frontend/src/styles/reset.scss +143 -0
- fred_admin/demo/modules/admin/frontend/src/styles/table-optimization.scss +242 -0
- fred_admin/demo/modules/admin/frontend/src/styles/theme/aside.ts +16 -0
- fred_admin/demo/modules/admin/frontend/src/styles/theme/header.ts +25 -0
- fred_admin/demo/modules/admin/frontend/src/styles/theme/menu.ts +31 -0
- fred_admin/demo/modules/admin/frontend/src/styles/var.scss +2 -0
- fred_admin/demo/modules/admin/frontend/src/typings/global.d.ts +74 -0
- fred_admin/demo/modules/admin/frontend/src/typings/utils.d.ts +17 -0
- fred_admin/demo/modules/admin/frontend/src/typings/window.d.ts +8 -0
- fred_admin/demo/modules/admin/frontend/src/utils/color.ts +59 -0
- fred_admin/demo/modules/admin/frontend/src/utils/dict.ts +17 -0
- fred_admin/demo/modules/admin/frontend/src/utils/eleValidate.ts +14 -0
- fred_admin/demo/modules/admin/frontend/src/utils/errorHandler.ts +28 -0
- fred_admin/demo/modules/admin/frontend/src/utils/index.ts +327 -0
- fred_admin/demo/modules/admin/frontend/src/utils/is/index.ts +125 -0
- fred_admin/demo/modules/admin/frontend/src/utils/mittBus.ts +5 -0
- fred_admin/demo/modules/admin/frontend/src/utils/svg.ts +13 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/fieldType/components/FieldTypeDrawer.vue +89 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/fieldType/index.vue +99 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/DataBaseDrawer.vue +254 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/IndexDrawer.vue +226 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/TableDataDrawer.vue +136 -0
- fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/index.vue +234 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/columnChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/columnChart/index.vue +139 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/lineChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/lineChart/index.vue +123 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/nestedChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/nestedChart/index.vue +97 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/pieChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/pieChart/index.vue +68 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/radarChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/radarChart/index.vue +56 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/waterChart/index.scss +0 -0
- fred_admin/demo/modules/admin/frontend/src/views/echarts/waterChart/index.vue +298 -0
- fred_admin/demo/modules/admin/frontend/src/views/home/index.scss +12 -0
- fred_admin/demo/modules/admin/frontend/src/views/home/index.vue +11 -0
- fred_admin/demo/modules/admin/frontend/src/views/login/components/LoginForm.vue +147 -0
- fred_admin/demo/modules/admin/frontend/src/views/login/index.scss +83 -0
- fred_admin/demo/modules/admin/frontend/src/views/login/index.vue +27 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/complexProTable/index.vue +176 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/components/UserDrawer.vue +152 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/document/index.vue +13 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/treeProTable/index.vue +129 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/useProTable/detail.vue +12 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/useProTable/index.vue +258 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/useSelectFilter/index.vue +184 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/useTreeFilter/detail.vue +12 -0
- fred_admin/demo/modules/admin/frontend/src/views/proTable/useTreeFilter/index.vue +147 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/accountManage/index.vue +244 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/components/ApiDrawer.vue +114 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/components/TokenDrawer.vue +160 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/index.vue +354 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/buttonManage/components/ButtonDrawer.vue +460 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/buttonManage/index.vue +426 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/configManage/components/ConfigDrawer.vue +106 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/configManage/index.vue +116 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/departmentManage/index.vue +7 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/dictManage/index.vue +7 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/menuManage/components/MenuDrawer.vue +262 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/menuManage/index.vue +310 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/CompanyDrawer.vue +72 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/DepartmentDrawer.vue +120 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/TeamDrawer.vue +162 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/TeamMemberDrawer.vue +243 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/index.vue +414 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleButtonDrawer.vue +587 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleDrawer.vue +77 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleMenuDrawer.vue +236 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleUserDrawer.vue +125 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/index.vue +143 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/systemLog/components/SystemLogDrawer.vue +207 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/systemLog/index.vue +219 -0
- fred_admin/demo/modules/admin/frontend/src/views/system/timingTask/index.vue +7 -0
- fred_admin/demo/modules/admin/frontend/src/vite-env.d.ts +7 -0
- fred_admin/demo/modules/admin/frontend/tsconfig.json +42 -0
- fred_admin/demo/modules/admin/frontend/vite.config.ts +91 -0
- fred_admin/demo/modules/admin/frontend//321/205/320/231/320/235/321/207/320/273/320/277/321/204/342/225/227/320/263/321/207/320/260/320/221/321/210/320/277/342/224/244/321/206/320/250/320/236.md +100 -0
- fred_admin/demo/requirements.txt +1 -0
- fred_admin/fonts/NotoSansSC-VariableFont_wght.ttf +0 -0
- fred_admin/install_hook.py +1633 -0
- fred_admin/setup.py +18 -0
- fred_admin-1.0.0.dist-info/METADATA +97 -0
- fred_admin-1.0.0.dist-info/RECORD +376 -0
- fred_admin-1.0.0.dist-info/WHEEL +5 -0
- fred_admin-1.0.0.dist-info/entry_points.txt +3 -0
- fred_admin-1.0.0.dist-info/licenses/LICENSE +21 -0
- fred_admin-1.0.0.dist-info/top_level.txt +1 -0
fred_admin/__init__.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from flask import Flask
|
|
6
|
+
from flask_cors import CORS
|
|
7
|
+
|
|
8
|
+
from fred_admin.common.RuntimeHook import apply_project_hook
|
|
9
|
+
from fred_admin.common.Blueprints import Blueprints
|
|
10
|
+
from fred_admin.common.Extensions import Extensions
|
|
11
|
+
from fred_admin.common.HandleExcetion import HandleException
|
|
12
|
+
from fred_admin.common.Response import Response
|
|
13
|
+
from fred_admin.common.Route import Route
|
|
14
|
+
from fred_admin.common.Swagger import Swagger
|
|
15
|
+
from fred_admin.common.Utils import Utils
|
|
16
|
+
from fred_admin.config.Config import Config
|
|
17
|
+
from fred_admin.config.Logger import Logger
|
|
18
|
+
|
|
19
|
+
def create_app():
|
|
20
|
+
"""
|
|
21
|
+
创建应用
|
|
22
|
+
"""
|
|
23
|
+
apply_project_hook() # 发现项目根并应用 src/modules path + iter_modules patch,便于正确加载蓝图
|
|
24
|
+
app = Flask(__name__)
|
|
25
|
+
|
|
26
|
+
app.config.from_object(Config)
|
|
27
|
+
# 尝试加载自定义配置,支持 config/Config.py 或 common/config/Config.py
|
|
28
|
+
# 优先使用 common.config.Config,因为安装框架后 config.Config 可能解析到框架自身
|
|
29
|
+
config_paths = ['common.config.Config', 'config.Config']
|
|
30
|
+
config_loaded = False
|
|
31
|
+
framework_config_file = str(Path(__file__).parent / 'config' / 'Config.py')
|
|
32
|
+
for config_path in config_paths:
|
|
33
|
+
try:
|
|
34
|
+
config_module = importlib.import_module(config_path)
|
|
35
|
+
Custom_Config = getattr(config_module, 'Config')
|
|
36
|
+
# 检查是否是框架自身的配置文件(避免误加载)
|
|
37
|
+
module_file = getattr(config_module, '__file__', '')
|
|
38
|
+
if module_file and os.path.normpath(module_file) == os.path.normpath(framework_config_file):
|
|
39
|
+
continue # 跳过框架自身的配置
|
|
40
|
+
app.config.from_object(Custom_Config)
|
|
41
|
+
config_msg = f"加载自定义Config ({config_path}),自定义配置会覆盖默认配置"
|
|
42
|
+
config_loaded = True
|
|
43
|
+
break
|
|
44
|
+
except (ImportError, AttributeError):
|
|
45
|
+
continue
|
|
46
|
+
if not config_loaded:
|
|
47
|
+
config_msg = "没有配置自定义Config"
|
|
48
|
+
app.config['SECRET_KEY'] = Utils.get_secret_key('session_secret_key',app)
|
|
49
|
+
if app.config['ENCRYPT_DATA']: # 如果启用数据加密才生成fernet_key
|
|
50
|
+
app.config['FERNET_KEY'] = Utils.get_secret_key('fernet_key',app)
|
|
51
|
+
# 配置app.logger
|
|
52
|
+
Logger.set_logger(app)
|
|
53
|
+
app.logger.info(config_msg)
|
|
54
|
+
|
|
55
|
+
# 初始化组件
|
|
56
|
+
Extensions(app).initialize_extensions()
|
|
57
|
+
|
|
58
|
+
# 注册蓝图
|
|
59
|
+
Blueprints(app).register_blueprints()
|
|
60
|
+
|
|
61
|
+
# Swagger(/docs、/doc 等)必须在 Route 的 SPA 通配符 /<path:path> 之前注册,
|
|
62
|
+
# 否则 /docs 会被首页路由当成前端路由并返回 index.html,而不是 Swagger UI。
|
|
63
|
+
Swagger(app)
|
|
64
|
+
|
|
65
|
+
# 前端静态资源与 SPA 通配路由
|
|
66
|
+
Route(app).set_routes()
|
|
67
|
+
# 全局异常处理
|
|
68
|
+
if app.config.get('ENABLE_GLOBAL_EXCEPTION', True):
|
|
69
|
+
HandleException(app)
|
|
70
|
+
# 重新定义模板文件路径
|
|
71
|
+
|
|
72
|
+
# 自定义输出格式
|
|
73
|
+
Response().custom_response(app)
|
|
74
|
+
|
|
75
|
+
if app.debug:
|
|
76
|
+
app.logger.info("开启debug模式,并允许跨域请求")
|
|
77
|
+
CORS(app, supports_credentials=True)
|
|
78
|
+
|
|
79
|
+
return app
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def main():
|
|
83
|
+
"""
|
|
84
|
+
主函数,用于启动应用
|
|
85
|
+
"""
|
|
86
|
+
app = create_app()
|
|
87
|
+
app.run()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if __name__ == '__main__':
|
|
91
|
+
main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
@author: cyg
|
|
5
|
+
@date: 2024/7/28 下午10:35
|
|
6
|
+
"""
|
|
7
|
+
# -*- coding: utf-8 -*-
|
|
8
|
+
from flask import current_app
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AliyunSms:
|
|
12
|
+
"""
|
|
13
|
+
发送短信
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def create_client():
|
|
18
|
+
"""
|
|
19
|
+
使用AK&SK初始化账号Client
|
|
20
|
+
@param access_key_id:
|
|
21
|
+
@param access_key_secret:
|
|
22
|
+
@return: Client
|
|
23
|
+
@throws Exception
|
|
24
|
+
"""
|
|
25
|
+
key_id = current_app.config.get("ALIBABA_KEY_ID", "")
|
|
26
|
+
if key_id == '':
|
|
27
|
+
return None
|
|
28
|
+
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
|
|
29
|
+
from alibabacloud_tea_openapi import models as open_api_models
|
|
30
|
+
config = open_api_models.Config(
|
|
31
|
+
access_key_id=current_app.config.get("ALIBABA_KEY_ID"),
|
|
32
|
+
access_key_secret=current_app.config.get("ALIBABA_KEY_SECRET")
|
|
33
|
+
)
|
|
34
|
+
# 访问的域名
|
|
35
|
+
config.endpoint = f'dysmsapi.aliyuncs.com'
|
|
36
|
+
return Dysmsapi20170525Client(config)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def send_code(phone, code):
|
|
40
|
+
"""
|
|
41
|
+
发送短信验证码
|
|
42
|
+
:param phone:手机号
|
|
43
|
+
:param code: 验证码 (4位数字)
|
|
44
|
+
:return: bool
|
|
45
|
+
"""
|
|
46
|
+
client = AliyunSms.create_client()
|
|
47
|
+
if client is None:
|
|
48
|
+
raise Exception("请先配置短信配置信息")
|
|
49
|
+
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
|
|
50
|
+
from alibabacloud_tea_util import models as util_models
|
|
51
|
+
from alibabacloud_tea_util.client import Client as UtilClient
|
|
52
|
+
send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
|
|
53
|
+
sign_name=current_app.config.get("ALIBABA_SIGN_NAME"),
|
|
54
|
+
template_code=current_app.config.get("ALIBABA_TEMPLATE_CODE"),
|
|
55
|
+
phone_numbers=phone,
|
|
56
|
+
template_param='{"code":"' + code + '"}'
|
|
57
|
+
)
|
|
58
|
+
try:
|
|
59
|
+
result = client.send_sms_with_options(send_sms_request, util_models.RuntimeOptions())
|
|
60
|
+
code = result.to_map()['body']['Code']
|
|
61
|
+
if code != "OK":
|
|
62
|
+
raise Exception("发送失败!")
|
|
63
|
+
return True
|
|
64
|
+
except Exception as error:
|
|
65
|
+
UtilClient.assert_as_string(str(error))
|
|
66
|
+
return False
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
* @Author:cyg
|
|
3
|
+
* @Package:Blueprints
|
|
4
|
+
* @Project:Default (Template) Project
|
|
5
|
+
* @name:Blueprints
|
|
6
|
+
* @Date:2024/12/16 11:42
|
|
7
|
+
* @Filename:自动注册蓝图
|
|
8
|
+
"""
|
|
9
|
+
import importlib
|
|
10
|
+
import pkgutil
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import flask_smorest
|
|
14
|
+
from flask import Blueprint
|
|
15
|
+
|
|
16
|
+
from fred_admin.common.Response import Response
|
|
17
|
+
from fred_admin.common.Utils import Utils
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Blueprints:
|
|
21
|
+
def __init__(self, app):
|
|
22
|
+
"""
|
|
23
|
+
初始化 BlueprintManager 类
|
|
24
|
+
:param app: Flask 应用对象
|
|
25
|
+
"""
|
|
26
|
+
self.app = app
|
|
27
|
+
self.blp = flask_smorest.Api(app)
|
|
28
|
+
|
|
29
|
+
def register_blueprints(self):
|
|
30
|
+
"""
|
|
31
|
+
自动注册蓝图
|
|
32
|
+
"""
|
|
33
|
+
self.app.logger.info("开始自动加载蓝图...")
|
|
34
|
+
self.blp.spec.components.security_scheme("Authorization", {"type": "http", "scheme": "bearer"})
|
|
35
|
+
self.blp.spec.options["security"] = [{"Authorization": []}]
|
|
36
|
+
self.blp.spec.components.schema('Response', schema=Response)
|
|
37
|
+
registered_blueprints = set()
|
|
38
|
+
self.__method_name("", registered_blueprints)
|
|
39
|
+
# 仅仅优化swagger显示内容
|
|
40
|
+
Response().swagger_responses(self.blp.spec.to_dict(), self.blp.spec.components.schemas)
|
|
41
|
+
|
|
42
|
+
if registered_blueprints:
|
|
43
|
+
self.app.logger.info(f"蓝图加载完成,共注册 {len(registered_blueprints)} 个蓝图:")
|
|
44
|
+
for blueprint_name in sorted(registered_blueprints):
|
|
45
|
+
self.app.logger.info(f" - {blueprint_name}")
|
|
46
|
+
else:
|
|
47
|
+
self.app.logger.warning("未加载任何蓝图")
|
|
48
|
+
return self.blp
|
|
49
|
+
|
|
50
|
+
def __method_name(self, app_directory, registered_blueprints):
|
|
51
|
+
new_app_directory = ""
|
|
52
|
+
if app_directory != "":
|
|
53
|
+
new_app_directory = app_directory + '.'
|
|
54
|
+
modules_found = list(pkgutil.iter_modules([app_directory]))
|
|
55
|
+
for _, module_name, is_pkg in modules_found:
|
|
56
|
+
# 跳过非Python模块文件,例如setup.py
|
|
57
|
+
if module_name in ['setup', 'pyproject']:
|
|
58
|
+
continue
|
|
59
|
+
# 动态导入模块
|
|
60
|
+
try:
|
|
61
|
+
module_path = f'{new_app_directory}{module_name}'.replace('app.', 'fred_admin.')
|
|
62
|
+
module = importlib.import_module(module_path)
|
|
63
|
+
for attr_name in dir(module):
|
|
64
|
+
if attr_name.startswith('__'):
|
|
65
|
+
continue
|
|
66
|
+
attr = getattr(module, attr_name)
|
|
67
|
+
modules = self.app.config.get('LOAD_CUSTOM_MODULES', None)
|
|
68
|
+
if isinstance(modules, list) and len(modules) == 0:
|
|
69
|
+
modules = None
|
|
70
|
+
if new_app_directory == "" and modules != None and attr_name not in modules:
|
|
71
|
+
continue
|
|
72
|
+
if isinstance(attr, Blueprint) and attr.name not in registered_blueprints:
|
|
73
|
+
# 自动导入模块的子模块(service、schema、constant等)
|
|
74
|
+
self.__auto_import_submodules(module)
|
|
75
|
+
controller_path = f'{new_app_directory}{attr.name}.controller'.replace('app.', 'fred_admin.')
|
|
76
|
+
Utils.import_controller(controller_path)
|
|
77
|
+
self.blp.register_blueprint(attr)
|
|
78
|
+
registered_blueprints.add(attr.name)
|
|
79
|
+
self.app.logger.info(f"成功注册蓝图: {attr.name} (模块: {new_app_directory}{module_name})")
|
|
80
|
+
except Exception as e:
|
|
81
|
+
self.app.logger.warning(f"加载模块 {new_app_directory}{module_name} 时出错: {str(e)}")
|
|
82
|
+
|
|
83
|
+
def __auto_import_submodules(self, module):
|
|
84
|
+
"""
|
|
85
|
+
自动导入模块的子模块(排除 controller,由框架单独加载)
|
|
86
|
+
:param module: 父模块对象
|
|
87
|
+
"""
|
|
88
|
+
try:
|
|
89
|
+
module_dir = Path(module.__file__).parent
|
|
90
|
+
for _, submodule_name, is_pkg in pkgutil.iter_modules([str(module_dir)]):
|
|
91
|
+
# 跳过 controller(由框架单独加载)和私有模块
|
|
92
|
+
if submodule_name.startswith('_') or submodule_name == 'controller':
|
|
93
|
+
continue
|
|
94
|
+
try:
|
|
95
|
+
importlib.import_module(f'.{submodule_name}', module.__package__)
|
|
96
|
+
except Exception:
|
|
97
|
+
pass # 子模块导入失败不影响主流程
|
|
98
|
+
except Exception:
|
|
99
|
+
pass # 获取模块路径失败不影响主流程
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
* @Author:cyg
|
|
3
|
+
* @Package:email
|
|
4
|
+
* @Project:Default (Template) Project
|
|
5
|
+
* @name:email
|
|
6
|
+
* @Date:2024/10/22 14:32
|
|
7
|
+
* @Filename:email
|
|
8
|
+
"""
|
|
9
|
+
from fred_admin.common.Extensions import Extensions
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Email:
|
|
13
|
+
|
|
14
|
+
def send_mail(self, mail_address, title, content):
|
|
15
|
+
from flask_mail import Message
|
|
16
|
+
msg = Message(title, recipients=[mail_address])
|
|
17
|
+
msg.body = content
|
|
18
|
+
msg.html = '<b>' + content + '</b>'
|
|
19
|
+
try:
|
|
20
|
+
Extensions().mail.send(msg)
|
|
21
|
+
return 'Email sent!'
|
|
22
|
+
except Exception as e:
|
|
23
|
+
raise Exception(f'Error sending email: {str(e)}')
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"""
|
|
2
|
+
* @Author:cyg
|
|
3
|
+
* @Package:Extensions
|
|
4
|
+
* @Project:Default (Template) Project
|
|
5
|
+
* @name:Extensions
|
|
6
|
+
* @Date:2024/12/16 11:35
|
|
7
|
+
* @Filename:使用的组件
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from flask import request
|
|
11
|
+
import sys
|
|
12
|
+
import importlib
|
|
13
|
+
|
|
14
|
+
from fred_admin.common.Sqlacodegen import Sqlacodegen
|
|
15
|
+
from fred_admin.common.Utils import Utils
|
|
16
|
+
from flask_babelplus import Babel, Domain
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
class Extensions:
|
|
20
|
+
def __init__(self, app=None):
|
|
21
|
+
self.app = app
|
|
22
|
+
|
|
23
|
+
# 加载依赖并初始化扩展
|
|
24
|
+
|
|
25
|
+
def load_requirements(self):
|
|
26
|
+
"""
|
|
27
|
+
加载依赖包列表
|
|
28
|
+
|
|
29
|
+
默认加载所有支持的依赖包,用于扩展检测。
|
|
30
|
+
"""
|
|
31
|
+
# 直接返回默认的依赖列表,不检查 requirements.txt 文件
|
|
32
|
+
default_requirements = [
|
|
33
|
+
'flask',
|
|
34
|
+
'flask_cors',
|
|
35
|
+
'flask_jwt_extended',
|
|
36
|
+
'flask_smorest',
|
|
37
|
+
'flask_swagger_ui',
|
|
38
|
+
'flask_apscheduler',
|
|
39
|
+
'flask_babelplus',
|
|
40
|
+
'flask_sqlalchemy',
|
|
41
|
+
'flask_mail',
|
|
42
|
+
'redis',
|
|
43
|
+
'pymysql',
|
|
44
|
+
'cryptography',
|
|
45
|
+
'pillow',
|
|
46
|
+
'requests',
|
|
47
|
+
'pytz'
|
|
48
|
+
]
|
|
49
|
+
return default_requirements
|
|
50
|
+
|
|
51
|
+
def _extract_package_name(self, requirement: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
从依赖字符串中提取包名
|
|
54
|
+
|
|
55
|
+
支持格式:
|
|
56
|
+
- flask>=3.1.2
|
|
57
|
+
- flask==3.1.2
|
|
58
|
+
- flask~=3.1.2
|
|
59
|
+
- flask
|
|
60
|
+
- flask-cors>=6.0.1
|
|
61
|
+
- flask[extra]>=3.1.2
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
requirement: 依赖字符串
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
str: 提取的包名,如果无法提取则返回空字符串
|
|
68
|
+
"""
|
|
69
|
+
import re
|
|
70
|
+
|
|
71
|
+
# 移除方括号中的额外依赖,如 flask[extra] -> flask
|
|
72
|
+
package = re.sub(r'\[.*?\]', '', requirement)
|
|
73
|
+
|
|
74
|
+
# 使用正则表达式匹配版本操作符
|
|
75
|
+
# 支持 >=, ==, ~=, >, <, <=, != 等操作符
|
|
76
|
+
version_pattern = r'[><=!~]+'
|
|
77
|
+
parts = re.split(version_pattern, package)
|
|
78
|
+
|
|
79
|
+
# 取第一部分作为包名
|
|
80
|
+
package_name = parts[0].strip()
|
|
81
|
+
|
|
82
|
+
return package_name if package_name else ''
|
|
83
|
+
|
|
84
|
+
def initialize_extensions(self):
|
|
85
|
+
"""
|
|
86
|
+
初始化已加载的扩展。
|
|
87
|
+
|
|
88
|
+
根据 requirements.txt 中的依赖包自动初始化对应的扩展。
|
|
89
|
+
使用字典映射方式,提高代码可维护性和可读性。
|
|
90
|
+
"""
|
|
91
|
+
requirements = self.load_requirements()
|
|
92
|
+
|
|
93
|
+
# 扩展初始化映射表:包名 -> 初始化方法
|
|
94
|
+
extension_map = {
|
|
95
|
+
'flask_sqlalchemy': self.__initialize_db,
|
|
96
|
+
'flask_mail': self.__initialize_mail,
|
|
97
|
+
'flask_babelplus': self.__initialize_babel,
|
|
98
|
+
'flask_apscheduler': self.__initialize_scheduler,
|
|
99
|
+
'flask_jwt_extended': self.__initialize_jwt,
|
|
100
|
+
'redis': self.__initialize_redis,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# 遍历映射表,检查依赖并初始化扩展
|
|
104
|
+
for package_name, init_func in extension_map.items():
|
|
105
|
+
if package_name in requirements:
|
|
106
|
+
init_func()
|
|
107
|
+
|
|
108
|
+
def __initialize_models(self):
|
|
109
|
+
Sqlacodegen().create_models(self.app)
|
|
110
|
+
|
|
111
|
+
def __initialize_scheduler(self):
|
|
112
|
+
"""初始化定时任务扩展"""
|
|
113
|
+
from flask_apscheduler import APScheduler
|
|
114
|
+
from fred_admin.common.SchedulerLog import SchedulerLog
|
|
115
|
+
|
|
116
|
+
scheduled = APScheduler()
|
|
117
|
+
if self.app.config.get('JOBS'):
|
|
118
|
+
# 包装所有定时任务函数,添加日志记录功能
|
|
119
|
+
# 注意:必须在 scheduled.init_app() 之前完成包装,否则 APScheduler 会使用原始函数引用
|
|
120
|
+
original_jobs = self.app.config.get('JOBS', [])
|
|
121
|
+
|
|
122
|
+
# 在应用上下文中执行包装,确保能正确访问 current_app
|
|
123
|
+
# 传递 app 实例,确保定时任务执行时能正确获取应用上下文
|
|
124
|
+
with self.app.app_context():
|
|
125
|
+
wrapped_jobs = SchedulerLog.wrap_jobs_in_config(original_jobs, app=self.app)
|
|
126
|
+
|
|
127
|
+
# 更新配置中的任务列表
|
|
128
|
+
self.app.config['JOBS'] = wrapped_jobs
|
|
129
|
+
|
|
130
|
+
# 在包装完成后初始化调度器
|
|
131
|
+
# 这样 APScheduler 会使用包装后的函数
|
|
132
|
+
scheduled.init_app(self.app)
|
|
133
|
+
scheduled.start()
|
|
134
|
+
|
|
135
|
+
def __initialize_jwt(self):
|
|
136
|
+
"""初始化 JWT 扩展"""
|
|
137
|
+
from flask import jsonify
|
|
138
|
+
from flask_jwt_extended import JWTManager
|
|
139
|
+
jwt = JWTManager()
|
|
140
|
+
self.app.config['JWT_SECRET_KEY'] = Utils.get_secret_key('jwt_secret_key', self.app)
|
|
141
|
+
jwt.init_app(self.app)
|
|
142
|
+
|
|
143
|
+
@jwt.invalid_token_loader
|
|
144
|
+
def invalid_token_callback(error_string):
|
|
145
|
+
"""Token 无效(签名错误、格式错误等)→ 401"""
|
|
146
|
+
return jsonify({"message": f"Token 无效:{error_string}"}), 401
|
|
147
|
+
|
|
148
|
+
@jwt.unauthorized_loader
|
|
149
|
+
def unauthorized_callback(error_string):
|
|
150
|
+
"""未提供 Token → 401"""
|
|
151
|
+
return jsonify({"message": f"缺少访问令牌:{error_string}"}), 401
|
|
152
|
+
|
|
153
|
+
@jwt.expired_token_loader
|
|
154
|
+
def expired_token_callback(jwt_header, jwt_payload):
|
|
155
|
+
"""Token 已过期 → 401"""
|
|
156
|
+
return jsonify({"message": "Token 已过期,请重新获取"}), 401
|
|
157
|
+
|
|
158
|
+
@jwt.token_verification_failed_loader
|
|
159
|
+
def token_verification_failed_callback(jwt_header, jwt_payload):
|
|
160
|
+
"""Token 验证失败 → 401"""
|
|
161
|
+
return jsonify({"message": "Token 验证失败"}), 401
|
|
162
|
+
|
|
163
|
+
@jwt.revoked_token_loader
|
|
164
|
+
def revoked_token_callback(jwt_header, jwt_payload):
|
|
165
|
+
"""Token 已被撤销 → 401"""
|
|
166
|
+
return jsonify({"message": "Token 已被撤销"}), 401
|
|
167
|
+
|
|
168
|
+
def __initialize_babel(self):
|
|
169
|
+
"""初始化 Babel 国际化扩展"""
|
|
170
|
+
|
|
171
|
+
# 获取配置的翻译目录
|
|
172
|
+
translation_dir = self.app.config.get('BABEL_TRANSLATION_DIRECTORIES', None)
|
|
173
|
+
|
|
174
|
+
# 如果配置了翻译目录,创建自定义Domain
|
|
175
|
+
default_domain = None
|
|
176
|
+
if translation_dir:
|
|
177
|
+
# 构建绝对路径
|
|
178
|
+
if os.path.isabs(translation_dir):
|
|
179
|
+
# 已经是绝对路径
|
|
180
|
+
translation_path = translation_dir
|
|
181
|
+
else:
|
|
182
|
+
# 相对于 app.root_path
|
|
183
|
+
translation_path = os.path.join(self.app.root_path, translation_dir)
|
|
184
|
+
default_domain = Domain(dirname=translation_path)
|
|
185
|
+
|
|
186
|
+
babel = Babel()
|
|
187
|
+
# 必须配置默认语言
|
|
188
|
+
if self.app.config.get('BABEL_DEFAULT_LOCALE'):
|
|
189
|
+
babel.init_app(self.app, default_domain=default_domain)
|
|
190
|
+
|
|
191
|
+
@babel.localeselector
|
|
192
|
+
def get_locale():
|
|
193
|
+
supported_languages = self.app.config.get('SUPPORTED_LANGUAGES')
|
|
194
|
+
default_locale = self.app.config.get('BABEL_DEFAULT_LOCALE')
|
|
195
|
+
# 如果浏览器发送的是 zh,直接映射到 zh
|
|
196
|
+
locale = request.accept_languages.best_match(supported_languages, default_locale)
|
|
197
|
+
return locale or default_locale
|
|
198
|
+
|
|
199
|
+
def __initialize_db(self):
|
|
200
|
+
"""初始化数据库扩展。仅当配置了 SQLALCHEMY_DATABASE_URI 时自动生成并加载 model/model.py。"""
|
|
201
|
+
# 先确定 PROJECT_ROOT(供 Sqlacodegen 输出路径及 get_secret_key 等使用)
|
|
202
|
+
if "PROJECT_ROOT" not in self.app.config or not self.app.config.get("PROJECT_ROOT"):
|
|
203
|
+
from pathlib import Path
|
|
204
|
+
model_dir = self.app.config.get("MODEL_DIR", "common/model")
|
|
205
|
+
cwd = Path.cwd()
|
|
206
|
+
if (cwd / model_dir / "model.py").exists():
|
|
207
|
+
self.app.config["PROJECT_ROOT"] = str(cwd)
|
|
208
|
+
else:
|
|
209
|
+
potential_root = Path(self.app.root_path).parent
|
|
210
|
+
if (potential_root / model_dir / "model.py").exists():
|
|
211
|
+
self.app.config["PROJECT_ROOT"] = str(potential_root)
|
|
212
|
+
elif (Path(self.app.root_path) / model_dir / "model.py").exists():
|
|
213
|
+
self.app.config["PROJECT_ROOT"] = str(self.app.root_path)
|
|
214
|
+
else:
|
|
215
|
+
self.app.config["PROJECT_ROOT"] = str(cwd)
|
|
216
|
+
|
|
217
|
+
if not self.app.config.get("SQLALCHEMY_DATABASE_URI"):
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
# 有 DB URI:先自动生成 model/model.py,再加载并初始化 db
|
|
221
|
+
self.__initialize_models()
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
Utils.import_project_models("db", app=self.app)
|
|
225
|
+
from model.model import db
|
|
226
|
+
|
|
227
|
+
# 确保在应用上下文中初始化 db
|
|
228
|
+
# 这样可以避免 "The current Flask app is not registered with this 'SQLAlchemy' instance" 错误
|
|
229
|
+
with self.app.app_context():
|
|
230
|
+
# 检查 db 是否已经注册到 Flask app
|
|
231
|
+
if hasattr(db, 'get_app'):
|
|
232
|
+
registered_app = db.get_app()
|
|
233
|
+
if registered_app is not None:
|
|
234
|
+
# 如果已经注册,检查是否是当前 app
|
|
235
|
+
if registered_app is not self.app:
|
|
236
|
+
# 如果注册到了其他 app,重新初始化
|
|
237
|
+
db.init_app(self.app)
|
|
238
|
+
else:
|
|
239
|
+
# 如果 db 没有 get_app 方法,直接初始化
|
|
240
|
+
db.init_app(self.app)
|
|
241
|
+
|
|
242
|
+
# 确保 db 实例被注册到 app.extensions
|
|
243
|
+
# 这样其他地方可以通过 app.extensions['sqlalchemy'] 访问
|
|
244
|
+
if 'sqlalchemy' not in self.app.extensions:
|
|
245
|
+
self.app.extensions['sqlalchemy'] = db
|
|
246
|
+
else:
|
|
247
|
+
existing_db = self.app.extensions['sqlalchemy']
|
|
248
|
+
if existing_db is not db:
|
|
249
|
+
self.app.extensions['sqlalchemy'] = db
|
|
250
|
+
|
|
251
|
+
# 确保标准的 model.model 模块使用已初始化的 db 实例
|
|
252
|
+
# 这样可以避免 "The current Flask app is not registered with this 'SQLAlchemy' instance" 错误
|
|
253
|
+
if 'model.model' in sys.modules:
|
|
254
|
+
standard_model_module = sys.modules['model.model']
|
|
255
|
+
# 如果标准模块中的 db 实例不是当前初始化的实例,则替换
|
|
256
|
+
if hasattr(standard_model_module, 'db') and standard_model_module.db is not db:
|
|
257
|
+
setattr(standard_model_module, 'db', db)
|
|
258
|
+
|
|
259
|
+
# 额外检查:确保所有可能导入 model.model 的地方都能使用已初始化的 db
|
|
260
|
+
# 遍历 sys.modules,查找所有可能包含 db 的模块
|
|
261
|
+
for module_name in list(sys.modules.keys()):
|
|
262
|
+
if 'model' in module_name.lower():
|
|
263
|
+
try:
|
|
264
|
+
module = sys.modules[module_name]
|
|
265
|
+
if hasattr(module, 'db'):
|
|
266
|
+
# 检查是否是 SQLAlchemy 实例
|
|
267
|
+
from flask_sqlalchemy import SQLAlchemy
|
|
268
|
+
if isinstance(module.db, SQLAlchemy):
|
|
269
|
+
# 如果模块中的 db 实例不是当前初始化的实例,则替换
|
|
270
|
+
if module.db is not db:
|
|
271
|
+
setattr(module, 'db', db)
|
|
272
|
+
except Exception:
|
|
273
|
+
# 静默处理异常,避免影响主流程
|
|
274
|
+
pass
|
|
275
|
+
|
|
276
|
+
except ImportError as e:
|
|
277
|
+
self.app.logger.warning(
|
|
278
|
+
"未找到 common/model/model.py,请确认已配置 SQLALCHEMY_DATABASE_URI 后至少运行一次以自动生成: %s",
|
|
279
|
+
e,
|
|
280
|
+
)
|
|
281
|
+
except Exception as e:
|
|
282
|
+
self.app.logger.exception("初始化数据库扩展失败: %s", e)
|
|
283
|
+
|
|
284
|
+
def __initialize_mail(self):
|
|
285
|
+
"""初始化邮件扩展"""
|
|
286
|
+
if self.app.config.get('MAIL_SERVER'):
|
|
287
|
+
from flask_mail import Mail
|
|
288
|
+
mail = Mail()
|
|
289
|
+
mail.init_app(self.app)
|
|
290
|
+
|
|
291
|
+
def __initialize_redis(self):
|
|
292
|
+
"""初始化 Redis 扩展"""
|
|
293
|
+
if self.app.config.get('REDIS_URL'):
|
|
294
|
+
try:
|
|
295
|
+
import redis
|
|
296
|
+
from urllib.parse import urlparse
|
|
297
|
+
|
|
298
|
+
# 解析 Redis URL
|
|
299
|
+
redis_url = self.app.config.get('REDIS_URL')
|
|
300
|
+
parsed = urlparse(redis_url)
|
|
301
|
+
|
|
302
|
+
# 创建 Redis 客户端
|
|
303
|
+
redis_client = redis.from_url(
|
|
304
|
+
redis_url,
|
|
305
|
+
decode_responses=False # 保持字节类型,与现有代码兼容
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# 测试连接
|
|
309
|
+
try:
|
|
310
|
+
redis_client.ping()
|
|
311
|
+
except Exception as e:
|
|
312
|
+
return
|
|
313
|
+
|
|
314
|
+
# 注册到 Flask extensions
|
|
315
|
+
self.app.extensions['redis'] = redis_client
|
|
316
|
+
except ImportError:
|
|
317
|
+
pass
|
|
318
|
+
except Exception as e:
|
|
319
|
+
pass
|