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.
Files changed (376) hide show
  1. fred_admin/__init__.py +91 -0
  2. fred_admin/common/AliyunSms.py +66 -0
  3. fred_admin/common/Blueprints.py +99 -0
  4. fred_admin/common/Email.py +23 -0
  5. fred_admin/common/Extensions.py +319 -0
  6. fred_admin/common/HandleExcetion.py +204 -0
  7. fred_admin/common/ImageVerification.py +117 -0
  8. fred_admin/common/IoTDBClient.py +698 -0
  9. fred_admin/common/PageSchema.py +65 -0
  10. fred_admin/common/Response.py +251 -0
  11. fred_admin/common/Route.py +390 -0
  12. fred_admin/common/RuntimeHook.py +111 -0
  13. fred_admin/common/SchedulerLog.py +277 -0
  14. fred_admin/common/Sqlacodegen.py +170 -0
  15. fred_admin/common/Swagger.py +77 -0
  16. fred_admin/common/SystemLog.py +80 -0
  17. fred_admin/common/Utils.py +1060 -0
  18. fred_admin/common/WechatLogin.py +97 -0
  19. fred_admin/common/__init__.py +3 -0
  20. fred_admin/config/Config.py +104 -0
  21. fred_admin/config/Logger.py +34 -0
  22. fred_admin/config/__init__.py +3 -0
  23. fred_admin/create_module.py +787 -0
  24. fred_admin/demo/app.py +6 -0
  25. fred_admin/demo/common/__init__.py +1 -0
  26. fred_admin/demo/common/config/Config.py +82 -0
  27. fred_admin/demo/common/config/README.md +8 -0
  28. fred_admin/demo/common/config/__init__.py +1 -0
  29. fred_admin/demo/common/config/__pycache__/Config.cpython-312.pyc +0 -0
  30. fred_admin/demo/common/config/__pycache__/__init__.cpython-312.pyc +0 -0
  31. fred_admin/demo/common/config/jwt_secret_key +1 -0
  32. fred_admin/demo/common/config/session_secret_key +1 -0
  33. fred_admin/demo/common/model/__pycache__/__init__.cpython-312.pyc +0 -0
  34. fred_admin/demo/common/model/__pycache__/model.cpython-312.pyc +0 -0
  35. fred_admin/demo/common/model/model.py +274 -0
  36. fred_admin/demo/demo_.gitignore +42 -0
  37. fred_admin/demo/modules/__init__.py +1 -0
  38. fred_admin/demo/modules/admin/README.md +38 -0
  39. fred_admin/demo/modules/admin/__init__.py +3 -0
  40. fred_admin/demo/modules/admin/backend/__init__.py +7 -0
  41. fred_admin/demo/modules/admin/backend/constant/RedisKey.py +10 -0
  42. fred_admin/demo/modules/admin/backend/controller/AdminAuthController.py +39 -0
  43. fred_admin/demo/modules/admin/backend/controller/AdminController.py +226 -0
  44. fred_admin/demo/modules/admin/backend/controller/ApiAuthController.py +93 -0
  45. fred_admin/demo/modules/admin/backend/controller/ButtonManageController.py +90 -0
  46. fred_admin/demo/modules/admin/backend/controller/FileController.py +28 -0
  47. fred_admin/demo/modules/admin/backend/controller/OrganizationController.py +218 -0
  48. fred_admin/demo/modules/admin/backend/controller/RoleController.py +143 -0
  49. fred_admin/demo/modules/admin/backend/controller/SystemController.py +112 -0
  50. fred_admin/demo/modules/admin/backend/controller/SystemLogController.py +63 -0
  51. fred_admin/demo/modules/admin/backend/controller/TableController.py +175 -0
  52. fred_admin/demo/modules/admin/backend/controller/__init__.py +55 -0
  53. fred_admin/demo/modules/admin/backend/schema/AdminSchema.py +356 -0
  54. fred_admin/demo/modules/admin/backend/schema/ApiAuthSchema.py +72 -0
  55. fred_admin/demo/modules/admin/backend/schema/AuthMenuSchema.py +79 -0
  56. fred_admin/demo/modules/admin/backend/schema/ButtonManageSchema.py +98 -0
  57. fred_admin/demo/modules/admin/backend/schema/OrganizationSchema.py +134 -0
  58. fred_admin/demo/modules/admin/backend/schema/RoleSchema.py +94 -0
  59. fred_admin/demo/modules/admin/backend/schema/SystemConfigSchema.py +115 -0
  60. fred_admin/demo/modules/admin/backend/schema/TableSchema.py +153 -0
  61. fred_admin/demo/modules/admin/backend/schema/UploadImg.py +35 -0
  62. fred_admin/demo/modules/admin/backend/schema/__init__.py +0 -0
  63. fred_admin/demo/modules/admin/backend/schema/__pycache__/AdminSchema.cpython-312.pyc +0 -0
  64. fred_admin/demo/modules/admin/backend/schema/__pycache__/ApiAuthSchema.cpython-312.pyc +0 -0
  65. fred_admin/demo/modules/admin/backend/schema/__pycache__/AuthMenuSchema.cpython-312.pyc +0 -0
  66. fred_admin/demo/modules/admin/backend/schema/__pycache__/ButtonManageSchema.cpython-312.pyc +0 -0
  67. fred_admin/demo/modules/admin/backend/schema/__pycache__/OrganizationSchema.cpython-312.pyc +0 -0
  68. fred_admin/demo/modules/admin/backend/schema/__pycache__/RoleSchema.cpython-312.pyc +0 -0
  69. fred_admin/demo/modules/admin/backend/schema/__pycache__/SystemConfigSchema.cpython-312.pyc +0 -0
  70. fred_admin/demo/modules/admin/backend/schema/__pycache__/TableSchema.cpython-312.pyc +0 -0
  71. fred_admin/demo/modules/admin/backend/schema/__pycache__/UploadImg.cpython-312.pyc +0 -0
  72. fred_admin/demo/modules/admin/backend/schema/__pycache__/__init__.cpython-312.pyc +0 -0
  73. fred_admin/demo/modules/admin/backend/service/AdminService.py +377 -0
  74. fred_admin/demo/modules/admin/backend/service/ApiAuthService.py +237 -0
  75. fred_admin/demo/modules/admin/backend/service/AuthButtonsService.py +155 -0
  76. fred_admin/demo/modules/admin/backend/service/AuthMenuService.py +265 -0
  77. fred_admin/demo/modules/admin/backend/service/ButtonManageService.py +386 -0
  78. fred_admin/demo/modules/admin/backend/service/ButtonManageService.py.broken +113 -0
  79. fred_admin/demo/modules/admin/backend/service/FileService.py +33 -0
  80. fred_admin/demo/modules/admin/backend/service/OrganizationService.py +465 -0
  81. fred_admin/demo/modules/admin/backend/service/RoleService.py +445 -0
  82. fred_admin/demo/modules/admin/backend/service/SystemConfigService.py +89 -0
  83. fred_admin/demo/modules/admin/backend/service/SystemLogService.py +142 -0
  84. fred_admin/demo/modules/admin/backend/service/TableService.py +978 -0
  85. fred_admin/demo/modules/admin/backend/service/__init__.py +1 -0
  86. fred_admin/demo/modules/admin/backend/sql/app.db +0 -0
  87. fred_admin/demo/modules/admin/backend/sql/fred.sql +3780 -0
  88. fred_admin/demo/modules/admin/frontend/LICENSE +21 -0
  89. fred_admin/demo/modules/admin/frontend/build/getEnv.ts +46 -0
  90. fred_admin/demo/modules/admin/frontend/build/plugins.ts +118 -0
  91. fred_admin/demo/modules/admin/frontend/build/proxy.ts +30 -0
  92. fred_admin/demo/modules/admin/frontend/commitlint.config.cjs +162 -0
  93. fred_admin/demo/modules/admin/frontend/demo_editorconfig +15 -0
  94. fred_admin/demo/modules/admin/frontend/demo_env +15 -0
  95. fred_admin/demo/modules/admin/frontend/demo_env.development +21 -0
  96. fred_admin/demo/modules/admin/frontend/demo_env.production +25 -0
  97. fred_admin/demo/modules/admin/frontend/demo_eslintignore +15 -0
  98. fred_admin/demo/modules/admin/frontend/demo_eslintrc.cjs +61 -0
  99. fred_admin/demo/modules/admin/frontend/demo_gitignore +27 -0
  100. fred_admin/demo/modules/admin/frontend/demo_prettierignore +9 -0
  101. fred_admin/demo/modules/admin/frontend/demo_prettierrc.cjs +41 -0
  102. fred_admin/demo/modules/admin/frontend/demo_stylelintignore +4 -0
  103. fred_admin/demo/modules/admin/frontend/demo_stylelintrc.cjs +40 -0
  104. fred_admin/demo/modules/admin/frontend/index.html +105 -0
  105. fred_admin/demo/modules/admin/frontend/lint-staged.config.cjs +8 -0
  106. fred_admin/demo/modules/admin/frontend/package.json +129 -0
  107. fred_admin/demo/modules/admin/frontend/pnpm-lock.yaml +11150 -0
  108. fred_admin/demo/modules/admin/frontend/postcss.config.cjs +5 -0
  109. fred_admin/demo/modules/admin/frontend/public/logo.png +0 -0
  110. fred_admin/demo/modules/admin/frontend/public/vue.svg +1 -0
  111. fred_admin/demo/modules/admin/frontend/src/App.vue +44 -0
  112. fred_admin/demo/modules/admin/frontend/src/api/config/servicePort.ts +2 -0
  113. fred_admin/demo/modules/admin/frontend/src/api/helper/axiosCancel.ts +57 -0
  114. fred_admin/demo/modules/admin/frontend/src/api/helper/checkStatus.ts +43 -0
  115. fred_admin/demo/modules/admin/frontend/src/api/index.ts +167 -0
  116. fred_admin/demo/modules/admin/frontend/src/api/interface/index.ts +179 -0
  117. fred_admin/demo/modules/admin/frontend/src/api/model/adminModel.ts +135 -0
  118. fred_admin/demo/modules/admin/frontend/src/api/model/apiAuthModel.ts +72 -0
  119. fred_admin/demo/modules/admin/frontend/src/api/model/index.ts +24 -0
  120. fred_admin/demo/modules/admin/frontend/src/api/model/loginModel.ts +79 -0
  121. fred_admin/demo/modules/admin/frontend/src/api/model/roleModel.ts +68 -0
  122. fred_admin/demo/modules/admin/frontend/src/api/model/storeModel.ts +80 -0
  123. fred_admin/demo/modules/admin/frontend/src/api/model/systemModel.ts +162 -0
  124. fred_admin/demo/modules/admin/frontend/src/api/model/uploadModel.ts +153 -0
  125. fred_admin/demo/modules/admin/frontend/src/api/modules/admin.ts +76 -0
  126. fred_admin/demo/modules/admin/frontend/src/api/modules/apiAuth.ts +53 -0
  127. fred_admin/demo/modules/admin/frontend/src/api/modules/buttonManage.ts +119 -0
  128. fred_admin/demo/modules/admin/frontend/src/api/modules/dataBase.ts +60 -0
  129. fred_admin/demo/modules/admin/frontend/src/api/modules/login.ts +54 -0
  130. fred_admin/demo/modules/admin/frontend/src/api/modules/organization.ts +123 -0
  131. fred_admin/demo/modules/admin/frontend/src/api/modules/role.ts +61 -0
  132. fred_admin/demo/modules/admin/frontend/src/api/modules/store.ts +303 -0
  133. fred_admin/demo/modules/admin/frontend/src/api/modules/system.ts +125 -0
  134. fred_admin/demo/modules/admin/frontend/src/api/modules/upload.ts +132 -0
  135. fred_admin/demo/modules/admin/frontend/src/api/modules/user.ts +63 -0
  136. fred_admin/demo/modules/admin/frontend/src/assets/fonts/DIN.otf +0 -0
  137. fred_admin/demo/modules/admin/frontend/src/assets/fonts/MetroDF.ttf +0 -0
  138. fred_admin/demo/modules/admin/frontend/src/assets/fonts/YouSheBiaoTiHei.ttf +0 -0
  139. fred_admin/demo/modules/admin/frontend/src/assets/fonts/font.scss +14 -0
  140. fred_admin/demo/modules/admin/frontend/src/assets/iconfont/iconfont.scss +51 -0
  141. fred_admin/demo/modules/admin/frontend/src/assets/iconfont/iconfont.ttf +0 -0
  142. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingdaoyu.svg +1 -0
  143. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingdiqiu.svg +1 -0
  144. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingditu.svg +1 -0
  145. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingfanchuan.svg +1 -0
  146. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingfeiji.svg +1 -0
  147. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxinglvhangriji.svg +1 -0
  148. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingtianqiyubao.svg +1 -0
  149. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingxiangjipaizhao.svg +1 -0
  150. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingxiarilengyin.svg +1 -0
  151. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingyoulun.svg +1 -0
  152. fred_admin/demo/modules/admin/frontend/src/assets/icons/xianxingzijiayou.svg +1 -0
  153. fred_admin/demo/modules/admin/frontend/src/assets/images/403.png +0 -0
  154. fred_admin/demo/modules/admin/frontend/src/assets/images/404.png +0 -0
  155. fred_admin/demo/modules/admin/frontend/src/assets/images/500.png +0 -0
  156. fred_admin/demo/modules/admin/frontend/src/assets/images/avatar.gif +0 -0
  157. fred_admin/demo/modules/admin/frontend/src/assets/images/login_bg.svg +33 -0
  158. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left.png +0 -0
  159. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left1.png +0 -0
  160. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left2.png +0 -0
  161. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left3.png +0 -0
  162. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left4.png +0 -0
  163. fred_admin/demo/modules/admin/frontend/src/assets/images/login_left5.png +0 -0
  164. fred_admin/demo/modules/admin/frontend/src/assets/images/logo.svg +1 -0
  165. fred_admin/demo/modules/admin/frontend/src/assets/images/msg01.png +0 -0
  166. fred_admin/demo/modules/admin/frontend/src/assets/images/msg02.png +0 -0
  167. fred_admin/demo/modules/admin/frontend/src/assets/images/msg03.png +0 -0
  168. fred_admin/demo/modules/admin/frontend/src/assets/images/msg04.png +0 -0
  169. fred_admin/demo/modules/admin/frontend/src/assets/images/msg05.png +0 -0
  170. fred_admin/demo/modules/admin/frontend/src/assets/images/notData.png +0 -0
  171. fred_admin/demo/modules/admin/frontend/src/assets/images/welcome.png +0 -0
  172. fred_admin/demo/modules/admin/frontend/src/assets/json/authButtonList.json +8 -0
  173. fred_admin/demo/modules/admin/frontend/src/assets/json/authMenuList.json +1075 -0
  174. fred_admin/demo/modules/admin/frontend/src/assets/mock/Easy-Mock-API.zip +0 -0
  175. fred_admin/demo/modules/admin/frontend/src/components/ECharts/config/index.ts +72 -0
  176. fred_admin/demo/modules/admin/frontend/src/components/ECharts/index.vue +104 -0
  177. fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/403.vue +19 -0
  178. fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/404.vue +19 -0
  179. fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/500.vue +19 -0
  180. fred_admin/demo/modules/admin/frontend/src/components/ErrorMessage/index.scss +32 -0
  181. fred_admin/demo/modules/admin/frontend/src/components/Grid/components/GridItem.vue +68 -0
  182. fred_admin/demo/modules/admin/frontend/src/components/Grid/index.vue +167 -0
  183. fred_admin/demo/modules/admin/frontend/src/components/Grid/interface/index.ts +6 -0
  184. fred_admin/demo/modules/admin/frontend/src/components/ImageCaptcha/index.vue +71 -0
  185. fred_admin/demo/modules/admin/frontend/src/components/ImportExcel/index.scss +3 -0
  186. fred_admin/demo/modules/admin/frontend/src/components/ImportExcel/index.vue +151 -0
  187. fred_admin/demo/modules/admin/frontend/src/components/JsonViewer/index.vue +249 -0
  188. fred_admin/demo/modules/admin/frontend/src/components/Loading/fullScreen.ts +45 -0
  189. fred_admin/demo/modules/admin/frontend/src/components/Loading/index.scss +67 -0
  190. fred_admin/demo/modules/admin/frontend/src/components/Loading/index.vue +13 -0
  191. fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/ColSetting.vue +45 -0
  192. fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/Pagination.vue +101 -0
  193. fred_admin/demo/modules/admin/frontend/src/components/ProTable/components/TableColumn.vue +58 -0
  194. fred_admin/demo/modules/admin/frontend/src/components/ProTable/index.vue +348 -0
  195. fred_admin/demo/modules/admin/frontend/src/components/ProTable/interface/index.ts +87 -0
  196. fred_admin/demo/modules/admin/frontend/src/components/SearchForm/components/SearchFormItem.vue +96 -0
  197. fred_admin/demo/modules/admin/frontend/src/components/SearchForm/index.vue +98 -0
  198. fred_admin/demo/modules/admin/frontend/src/components/SelectFilter/index.scss +63 -0
  199. fred_admin/demo/modules/admin/frontend/src/components/SelectFilter/index.vue +110 -0
  200. fred_admin/demo/modules/admin/frontend/src/components/SelectIcon/index.scss +39 -0
  201. fred_admin/demo/modules/admin/frontend/src/components/SelectIcon/index.vue +90 -0
  202. fred_admin/demo/modules/admin/frontend/src/components/StoreFilter/index.vue +356 -0
  203. fred_admin/demo/modules/admin/frontend/src/components/SvgIcon/index.vue +22 -0
  204. fred_admin/demo/modules/admin/frontend/src/components/SwitchDark/index.vue +12 -0
  205. fred_admin/demo/modules/admin/frontend/src/components/TreeFilter/index.scss +44 -0
  206. fred_admin/demo/modules/admin/frontend/src/components/TreeFilter/index.vue +165 -0
  207. fred_admin/demo/modules/admin/frontend/src/components/Upload/Img.vue +304 -0
  208. fred_admin/demo/modules/admin/frontend/src/components/Upload/Imgs.vue +316 -0
  209. fred_admin/demo/modules/admin/frontend/src/components/WangEditor/index.scss +28 -0
  210. fred_admin/demo/modules/admin/frontend/src/components/WangEditor/index.vue +154 -0
  211. fred_admin/demo/modules/admin/frontend/src/config/amapMap.ts +11 -0
  212. fred_admin/demo/modules/admin/frontend/src/config/index.ts +16 -0
  213. fred_admin/demo/modules/admin/frontend/src/config/nprogress.ts +12 -0
  214. fred_admin/demo/modules/admin/frontend/src/directives/index.ts +28 -0
  215. fred_admin/demo/modules/admin/frontend/src/directives/modules/auth.ts +26 -0
  216. fred_admin/demo/modules/admin/frontend/src/directives/modules/copy.ts +37 -0
  217. fred_admin/demo/modules/admin/frontend/src/directives/modules/debounce.ts +31 -0
  218. fred_admin/demo/modules/admin/frontend/src/directives/modules/draggable.ts +49 -0
  219. fred_admin/demo/modules/admin/frontend/src/directives/modules/longpress.ts +49 -0
  220. fred_admin/demo/modules/admin/frontend/src/directives/modules/throttle.ts +41 -0
  221. fred_admin/demo/modules/admin/frontend/src/directives/modules/waterMarker.ts +36 -0
  222. fred_admin/demo/modules/admin/frontend/src/enums/httpEnum.ts +35 -0
  223. fred_admin/demo/modules/admin/frontend/src/hooks/interface/index.ts +32 -0
  224. fred_admin/demo/modules/admin/frontend/src/hooks/useAuthButtons.ts +22 -0
  225. fred_admin/demo/modules/admin/frontend/src/hooks/useDownload.ts +42 -0
  226. fred_admin/demo/modules/admin/frontend/src/hooks/useHandleData.ts +41 -0
  227. fred_admin/demo/modules/admin/frontend/src/hooks/useI18n.ts +51 -0
  228. fred_admin/demo/modules/admin/frontend/src/hooks/useOnline.ts +31 -0
  229. fred_admin/demo/modules/admin/frontend/src/hooks/useSelection.ts +34 -0
  230. fred_admin/demo/modules/admin/frontend/src/hooks/useTable.ts +150 -0
  231. fred_admin/demo/modules/admin/frontend/src/hooks/useTheme.ts +111 -0
  232. fred_admin/demo/modules/admin/frontend/src/hooks/useTime.ts +38 -0
  233. fred_admin/demo/modules/admin/frontend/src/languages/index.ts +32 -0
  234. fred_admin/demo/modules/admin/frontend/src/languages/modules/en.ts +978 -0
  235. fred_admin/demo/modules/admin/frontend/src/languages/modules/zh.ts +996 -0
  236. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutClassic/index.scss +60 -0
  237. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutClassic/index.vue +62 -0
  238. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutColumns/index.scss +95 -0
  239. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutColumns/index.vue +103 -0
  240. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutTransverse/index.scss +60 -0
  241. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutTransverse/index.vue +61 -0
  242. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutVertical/index.scss +48 -0
  243. fred_admin/demo/modules/admin/frontend/src/layouts/LayoutVertical/index.vue +56 -0
  244. fred_admin/demo/modules/admin/frontend/src/layouts/components/Footer/index.scss +11 -0
  245. fred_admin/demo/modules/admin/frontend/src/layouts/components/Footer/index.vue +9 -0
  246. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/ToolBarLeft.vue +23 -0
  247. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/ToolBarRight.vue +51 -0
  248. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/AssemblySize.vue +37 -0
  249. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Avatar.vue +79 -0
  250. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Breadcrumb.vue +122 -0
  251. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/CollapseIcon.vue +21 -0
  252. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Fullscreen.vue +25 -0
  253. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/InfoDialog.vue +22 -0
  254. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Language.vue +38 -0
  255. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/Message.vue +109 -0
  256. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/PasswordDialog.vue +81 -0
  257. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/SearchMenu.vue +183 -0
  258. fred_admin/demo/modules/admin/frontend/src/layouts/components/Header/components/ThemeSetting.vue +12 -0
  259. fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/components/Maximize.vue +39 -0
  260. fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/index.scss +10 -0
  261. fred_admin/demo/modules/admin/frontend/src/layouts/components/Main/index.vue +88 -0
  262. fred_admin/demo/modules/admin/frontend/src/layouts/components/Menu/SubMenu.vue +85 -0
  263. fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/components/MoreButton.vue +85 -0
  264. fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/index.scss +69 -0
  265. fred_admin/demo/modules/admin/frontend/src/layouts/components/Tabs/index.vue +115 -0
  266. fred_admin/demo/modules/admin/frontend/src/layouts/components/ThemeDrawer/index.scss +137 -0
  267. fred_admin/demo/modules/admin/frontend/src/layouts/components/ThemeDrawer/index.vue +191 -0
  268. fred_admin/demo/modules/admin/frontend/src/layouts/index.vue +42 -0
  269. fred_admin/demo/modules/admin/frontend/src/layouts/indexAsync.vue +46 -0
  270. fred_admin/demo/modules/admin/frontend/src/main.ts +45 -0
  271. fred_admin/demo/modules/admin/frontend/src/routers/index.ts +106 -0
  272. fred_admin/demo/modules/admin/frontend/src/routers/modules/dynamicRouter.ts +99 -0
  273. fred_admin/demo/modules/admin/frontend/src/routers/modules/staticRouter.ts +63 -0
  274. fred_admin/demo/modules/admin/frontend/src/stores/helper/persist.ts +19 -0
  275. fred_admin/demo/modules/admin/frontend/src/stores/index.ts +8 -0
  276. fred_admin/demo/modules/admin/frontend/src/stores/interface/index.ts +63 -0
  277. fred_admin/demo/modules/admin/frontend/src/stores/modules/auth.ts +50 -0
  278. fred_admin/demo/modules/admin/frontend/src/stores/modules/global.ts +55 -0
  279. fred_admin/demo/modules/admin/frontend/src/stores/modules/keepAlive.ts +25 -0
  280. fred_admin/demo/modules/admin/frontend/src/stores/modules/tabs.ts +78 -0
  281. fred_admin/demo/modules/admin/frontend/src/stores/modules/user.ts +23 -0
  282. fred_admin/demo/modules/admin/frontend/src/styles/common.scss +129 -0
  283. fred_admin/demo/modules/admin/frontend/src/styles/element-dark.scss +28 -0
  284. fred_admin/demo/modules/admin/frontend/src/styles/element.scss +264 -0
  285. fred_admin/demo/modules/admin/frontend/src/styles/modules/annotation.scss +746 -0
  286. fred_admin/demo/modules/admin/frontend/src/styles/modules/assembly.scss +714 -0
  287. fred_admin/demo/modules/admin/frontend/src/styles/modules/device-manager.scss +659 -0
  288. fred_admin/demo/modules/admin/frontend/src/styles/modules/directives.scss +381 -0
  289. fred_admin/demo/modules/admin/frontend/src/styles/reset.scss +143 -0
  290. fred_admin/demo/modules/admin/frontend/src/styles/table-optimization.scss +242 -0
  291. fred_admin/demo/modules/admin/frontend/src/styles/theme/aside.ts +16 -0
  292. fred_admin/demo/modules/admin/frontend/src/styles/theme/header.ts +25 -0
  293. fred_admin/demo/modules/admin/frontend/src/styles/theme/menu.ts +31 -0
  294. fred_admin/demo/modules/admin/frontend/src/styles/var.scss +2 -0
  295. fred_admin/demo/modules/admin/frontend/src/typings/global.d.ts +74 -0
  296. fred_admin/demo/modules/admin/frontend/src/typings/utils.d.ts +17 -0
  297. fred_admin/demo/modules/admin/frontend/src/typings/window.d.ts +8 -0
  298. fred_admin/demo/modules/admin/frontend/src/utils/color.ts +59 -0
  299. fred_admin/demo/modules/admin/frontend/src/utils/dict.ts +17 -0
  300. fred_admin/demo/modules/admin/frontend/src/utils/eleValidate.ts +14 -0
  301. fred_admin/demo/modules/admin/frontend/src/utils/errorHandler.ts +28 -0
  302. fred_admin/demo/modules/admin/frontend/src/utils/index.ts +327 -0
  303. fred_admin/demo/modules/admin/frontend/src/utils/is/index.ts +125 -0
  304. fred_admin/demo/modules/admin/frontend/src/utils/mittBus.ts +5 -0
  305. fred_admin/demo/modules/admin/frontend/src/utils/svg.ts +13 -0
  306. fred_admin/demo/modules/admin/frontend/src/views/dataBase/fieldType/components/FieldTypeDrawer.vue +89 -0
  307. fred_admin/demo/modules/admin/frontend/src/views/dataBase/fieldType/index.vue +99 -0
  308. fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/DataBaseDrawer.vue +254 -0
  309. fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/IndexDrawer.vue +226 -0
  310. fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/components/TableDataDrawer.vue +136 -0
  311. fred_admin/demo/modules/admin/frontend/src/views/dataBase/tableManage/index.vue +234 -0
  312. fred_admin/demo/modules/admin/frontend/src/views/echarts/columnChart/index.scss +0 -0
  313. fred_admin/demo/modules/admin/frontend/src/views/echarts/columnChart/index.vue +139 -0
  314. fred_admin/demo/modules/admin/frontend/src/views/echarts/lineChart/index.scss +0 -0
  315. fred_admin/demo/modules/admin/frontend/src/views/echarts/lineChart/index.vue +123 -0
  316. fred_admin/demo/modules/admin/frontend/src/views/echarts/nestedChart/index.scss +0 -0
  317. fred_admin/demo/modules/admin/frontend/src/views/echarts/nestedChart/index.vue +97 -0
  318. fred_admin/demo/modules/admin/frontend/src/views/echarts/pieChart/index.scss +0 -0
  319. fred_admin/demo/modules/admin/frontend/src/views/echarts/pieChart/index.vue +68 -0
  320. fred_admin/demo/modules/admin/frontend/src/views/echarts/radarChart/index.scss +0 -0
  321. fred_admin/demo/modules/admin/frontend/src/views/echarts/radarChart/index.vue +56 -0
  322. fred_admin/demo/modules/admin/frontend/src/views/echarts/waterChart/index.scss +0 -0
  323. fred_admin/demo/modules/admin/frontend/src/views/echarts/waterChart/index.vue +298 -0
  324. fred_admin/demo/modules/admin/frontend/src/views/home/index.scss +12 -0
  325. fred_admin/demo/modules/admin/frontend/src/views/home/index.vue +11 -0
  326. fred_admin/demo/modules/admin/frontend/src/views/login/components/LoginForm.vue +147 -0
  327. fred_admin/demo/modules/admin/frontend/src/views/login/index.scss +83 -0
  328. fred_admin/demo/modules/admin/frontend/src/views/login/index.vue +27 -0
  329. fred_admin/demo/modules/admin/frontend/src/views/proTable/complexProTable/index.vue +176 -0
  330. fred_admin/demo/modules/admin/frontend/src/views/proTable/components/UserDrawer.vue +152 -0
  331. fred_admin/demo/modules/admin/frontend/src/views/proTable/document/index.vue +13 -0
  332. fred_admin/demo/modules/admin/frontend/src/views/proTable/treeProTable/index.vue +129 -0
  333. fred_admin/demo/modules/admin/frontend/src/views/proTable/useProTable/detail.vue +12 -0
  334. fred_admin/demo/modules/admin/frontend/src/views/proTable/useProTable/index.vue +258 -0
  335. fred_admin/demo/modules/admin/frontend/src/views/proTable/useSelectFilter/index.vue +184 -0
  336. fred_admin/demo/modules/admin/frontend/src/views/proTable/useTreeFilter/detail.vue +12 -0
  337. fred_admin/demo/modules/admin/frontend/src/views/proTable/useTreeFilter/index.vue +147 -0
  338. fred_admin/demo/modules/admin/frontend/src/views/system/accountManage/index.vue +244 -0
  339. fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/components/ApiDrawer.vue +114 -0
  340. fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/components/TokenDrawer.vue +160 -0
  341. fred_admin/demo/modules/admin/frontend/src/views/system/apiAuth/index.vue +354 -0
  342. fred_admin/demo/modules/admin/frontend/src/views/system/buttonManage/components/ButtonDrawer.vue +460 -0
  343. fred_admin/demo/modules/admin/frontend/src/views/system/buttonManage/index.vue +426 -0
  344. fred_admin/demo/modules/admin/frontend/src/views/system/configManage/components/ConfigDrawer.vue +106 -0
  345. fred_admin/demo/modules/admin/frontend/src/views/system/configManage/index.vue +116 -0
  346. fred_admin/demo/modules/admin/frontend/src/views/system/departmentManage/index.vue +7 -0
  347. fred_admin/demo/modules/admin/frontend/src/views/system/dictManage/index.vue +7 -0
  348. fred_admin/demo/modules/admin/frontend/src/views/system/menuManage/components/MenuDrawer.vue +262 -0
  349. fred_admin/demo/modules/admin/frontend/src/views/system/menuManage/index.vue +310 -0
  350. fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/CompanyDrawer.vue +72 -0
  351. fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/DepartmentDrawer.vue +120 -0
  352. fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/TeamDrawer.vue +162 -0
  353. fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/components/TeamMemberDrawer.vue +243 -0
  354. fred_admin/demo/modules/admin/frontend/src/views/system/organizationManage/index.vue +414 -0
  355. fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleButtonDrawer.vue +587 -0
  356. fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleDrawer.vue +77 -0
  357. fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleMenuDrawer.vue +236 -0
  358. fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/components/RoleUserDrawer.vue +125 -0
  359. fred_admin/demo/modules/admin/frontend/src/views/system/roleManage/index.vue +143 -0
  360. fred_admin/demo/modules/admin/frontend/src/views/system/systemLog/components/SystemLogDrawer.vue +207 -0
  361. fred_admin/demo/modules/admin/frontend/src/views/system/systemLog/index.vue +219 -0
  362. fred_admin/demo/modules/admin/frontend/src/views/system/timingTask/index.vue +7 -0
  363. fred_admin/demo/modules/admin/frontend/src/vite-env.d.ts +7 -0
  364. fred_admin/demo/modules/admin/frontend/tsconfig.json +42 -0
  365. fred_admin/demo/modules/admin/frontend/vite.config.ts +91 -0
  366. 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
  367. fred_admin/demo/requirements.txt +1 -0
  368. fred_admin/fonts/NotoSansSC-VariableFont_wght.ttf +0 -0
  369. fred_admin/install_hook.py +1633 -0
  370. fred_admin/setup.py +18 -0
  371. fred_admin-1.0.0.dist-info/METADATA +97 -0
  372. fred_admin-1.0.0.dist-info/RECORD +376 -0
  373. fred_admin-1.0.0.dist-info/WHEEL +5 -0
  374. fred_admin-1.0.0.dist-info/entry_points.txt +3 -0
  375. fred_admin-1.0.0.dist-info/licenses/LICENSE +21 -0
  376. fred_admin-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,390 @@
1
+ # coding: utf-8
2
+ """
3
+ * @Author:cyg
4
+ * @Package:Route
5
+ * @Project:Default (Template) Project
6
+ * @name:Route
7
+ * @Date:2025/6/1 11:25
8
+ * @Filename:Route
9
+ """
10
+
11
+ import os
12
+ import re
13
+
14
+ from flask import send_from_directory, render_template, abort, Response
15
+ from jinja2 import ChoiceLoader, FileSystemLoader
16
+
17
+ from fred_admin.common.RuntimeHook import get_modules_dir
18
+
19
+
20
+ # 常见的 Service Worker 文件名模式(支持多框架)
21
+ SW_FILE_PATTERNS = ['sw.js', 'service-worker.js', 'sw.min.js', 'worker.js', 'serviceWorker.js']
22
+
23
+
24
+ def _find_service_worker_files(templates_dir):
25
+ """
26
+ 查找 templates 目录下的所有 Service Worker 文件
27
+
28
+ 支持:Vue (Vite PWA)、React (Workbox)、Angular、Next.js 等
29
+ """
30
+ sw_files = []
31
+ if not os.path.isdir(templates_dir):
32
+ return sw_files
33
+
34
+ # 1. 检查常见 SW 文件名
35
+ for sw_name in SW_FILE_PATTERNS:
36
+ sw_path = os.path.join(templates_dir, sw_name)
37
+ if os.path.isfile(sw_path):
38
+ sw_files.append(sw_path)
39
+
40
+ # 2. 扫描所有 JS 文件,查找包含 NavigationRoute 的文件
41
+ for root, dirs, files in os.walk(templates_dir):
42
+ for file in files:
43
+ if file.endswith('.js'):
44
+ file_path = os.path.join(root, file)
45
+ if file_path not in sw_files:
46
+ try:
47
+ with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
48
+ content = f.read()
49
+ if 'NavigationRoute' in content:
50
+ sw_files.append(file_path)
51
+ except Exception:
52
+ continue
53
+
54
+ return sw_files
55
+
56
+
57
+ def _fix_pwa_sw_file(sw_file_path, swagger_paths):
58
+ """
59
+ 修复 PWA Service Worker 文件,在 NavigationRoute 中添加 denylist
60
+
61
+ 支持多种框架和 Workbox 版本:
62
+ - Vite PWA (Vue)
63
+ - Workbox (React, Angular, Next.js)
64
+ - 自定义 Service Worker
65
+ """
66
+ if not os.path.isfile(sw_file_path):
67
+ return False
68
+
69
+ try:
70
+ with open(sw_file_path, 'r', encoding='utf-8', errors='ignore') as f:
71
+ content = f.read()
72
+
73
+ # 检查是否包含 NavigationRoute
74
+ if 'NavigationRoute' not in content:
75
+ return False
76
+
77
+ # 检查是否已修复过
78
+ if 'denylist:[' in content and '/docs' in content:
79
+ return False
80
+
81
+ # 构建 denylist 正则表达式字符串
82
+ denylist_items = [f"/^\\/{p.lstrip('/')}/" for p in swagger_paths if p]
83
+ if not denylist_items:
84
+ return False
85
+ denylist_str = ','.join(denylist_items)
86
+
87
+ new_content = content
88
+
89
+ # 模式1: new X.NavigationRoute(X.createHandlerBoundToURL("index.html"))
90
+ # 匹配 Workbox 各种写法:s., e., workbox., etc.
91
+ pattern1 = r'(new\s+[a-zA-Z_][a-zA-Z0-9_]*\.NavigationRoute\s*\([a-zA-Z_][a-zA-Z0-9_]*\.createHandlerBoundToURL\s*\(["\']index\.html["\']\)\s*\))'
92
+ replacement1 = f'new s.NavigationRoute(s.createHandlerBoundToURL("index.html"),{{denylist:[{denylist_str}]}})'
93
+ new_content = re.sub(pattern1, replacement1, new_content)
94
+
95
+ # 模式2: new NavigationRoute(createHandlerBoundToURL("index.html"))
96
+ pattern2 = r'(new\s+NavigationRoute\s*\([a-zA-Z_][a-zA-Z0-9_]*\.createHandlerBoundToURL\s*\(["\']index\.html["\']\)\s*\))'
97
+ replacement2 = f'new NavigationRoute(s.createHandlerBoundToURL("index.html"),{{denylist:[{denylist_str}]}})'
98
+ new_content = re.sub(pattern2, replacement2, new_content)
99
+
100
+ # 模式3: registerRoute(new NavigationRoute(handler, { ... }))
101
+ # 已有配置的情况,添加 denylist 到现有配置中
102
+ if new_content == content and 'NavigationRoute' in content:
103
+ # 查找 NavigationRoute 中已有的配置对象,添加 denylist
104
+ # 匹配: NavigationRoute(..., { ... }) 的情况
105
+ pattern3 = r'(NavigationRoute\s*\([^)]+,\s*\{)([^}]*)(\}))'
106
+ def add_denylist(match):
107
+ existing = match.group(2).strip()
108
+ if 'denylist' not in existing:
109
+ if existing:
110
+ return f"{match.group(1)}{existing},denylist:[{denylist_str}]{match.group(3)}"
111
+ else:
112
+ return f"{match.group(1)}denylist:[{denylist_str}]{match.group(3)}"
113
+ return match.group(0)
114
+ new_content = re.sub(pattern3, add_denylist, new_content)
115
+
116
+
117
+ if new_content != content:
118
+ with open(sw_file_path, 'w', encoding='utf-8') as f:
119
+ f.write(new_content)
120
+ return True
121
+ return False
122
+ except Exception:
123
+ return False
124
+
125
+
126
+ def _inject_sw_update_script(index_file_path):
127
+ """
128
+ 在 index.html 中注入 Service Worker 强制更新脚本
129
+
130
+ 通用于所有前端框架:Vue、React、Angular、Next.js 等
131
+ """
132
+ if not os.path.isfile(index_file_path):
133
+ return False
134
+
135
+ try:
136
+ with open(index_file_path, 'r', encoding='utf-8', errors='ignore') as f:
137
+ content = f.read()
138
+
139
+ # 检查是否已注入过
140
+ if 'fred-pwa-swagger-fix' in content:
141
+ return False
142
+
143
+ # 通用的 Service Worker 更新脚本
144
+ sw_update_script = '''<script id="fred-pwa-swagger-fix">(function(){if('serviceWorker'in navigator){navigator.serviceWorker.getRegistration().then(function(reg){if(reg){reg.update();if(reg.installing)reg.installing.postMessage({type:'SKIP_WAITING'});if(reg.waiting)reg.waiting.postMessage({type:'SKIP_WAITING'});}});navigator.serviceWorker.addEventListener('controllerchange',function(){location.reload();});}})();</script>'''
145
+
146
+ # 在 </head> 前插入(优先)
147
+ if '</head>' in content:
148
+ new_content = content.replace('</head>', sw_update_script + '</head>', 1)
149
+ # 或在 </body> 前
150
+ elif '</body>' in content:
151
+ new_content = content.replace('</body>', sw_update_script + '</body>', 1)
152
+ # 或在文件末尾
153
+ else:
154
+ new_content = content + sw_update_script
155
+
156
+ if new_content != content:
157
+ with open(index_file_path, 'w', encoding='utf-8') as f:
158
+ f.write(new_content)
159
+ return True
160
+ return False
161
+ except Exception:
162
+ return False
163
+
164
+
165
+ def _auto_fix_pwa_swagger_conflict(app, modules_dir):
166
+ """
167
+ 自动修复所有模块的 PWA Service Worker 与 Swagger 的冲突
168
+
169
+ 支持任意前端框架:Vue、React、Angular、Next.js、Svelte 等
170
+ 框架会在应用启动时自动扫描并修复 Service Worker 文件。
171
+
172
+ 仅当 ENABLE_SWAGGER = True 时才执行注入,否则跳过。
173
+ """
174
+ # 未启用 Swagger 时,不做任何处理
175
+ if not app.config.get('ENABLE_SWAGGER', False):
176
+ return
177
+
178
+ # 获取需要排除的路径
179
+ swagger_path = app.config.get('OPENAPI_SWAGGER_UI_PATH', '/docs') or '/docs'
180
+ swagger_paths = [swagger_path.strip('/'), 'doc', 'openapi.json', 'openapi']
181
+ swagger_paths = list(set([p.strip('/') for p in swagger_paths if p.strip('/')]))
182
+
183
+ # 如果没有有效的排除路径,跳过
184
+ if not swagger_paths:
185
+ return
186
+
187
+ fixed_modules = []
188
+
189
+ # 遍历所有模块
190
+ if modules_dir and os.path.isdir(modules_dir):
191
+ for module_name in os.listdir(modules_dir):
192
+ module_path = os.path.join(modules_dir, module_name)
193
+ if not os.path.isdir(module_path):
194
+ continue
195
+
196
+ templates_dir = os.path.join(module_path, 'templates')
197
+ if not os.path.isdir(templates_dir):
198
+ continue
199
+
200
+ module_fixed = False
201
+
202
+ # 1. 查找并修复所有 Service Worker 文件
203
+ sw_files = _find_service_worker_files(templates_dir)
204
+ for sw_file in sw_files:
205
+ if _fix_pwa_sw_file(sw_file, swagger_paths):
206
+ module_fixed = True
207
+
208
+ # 2. 修复 index.html(注入 SW 更新脚本)
209
+ index_file = os.path.join(templates_dir, 'index.html')
210
+ if _inject_sw_update_script(index_file):
211
+ module_fixed = True
212
+
213
+ if module_fixed:
214
+ fixed_modules.append(module_name)
215
+
216
+ if fixed_modules:
217
+ app.logger.info(f"PWA Service Worker 已自动配置 denylist 排除 Swagger 路径,影响模块: {', '.join(fixed_modules)}")
218
+
219
+
220
+ class Route:
221
+
222
+ def _delegate_swagger_ui_if_needed(self, path):
223
+ """
224
+ 首页 SPA 通配 /<path:path> 可能与 /docs 竞争匹配顺序。
225
+ 一旦本视图收到 OPENAPI_SWAGGER_UI_PATH 下的路径,直接交给 swagger_ui.show,
226
+ 避免返回后台 index.html 后出现 /docs#/login。
227
+ """
228
+ if not self.app.config.get('ENABLE_SWAGGER', False):
229
+ return None
230
+ raw = (self.app.config.get('OPENAPI_SWAGGER_UI_PATH') or '').strip()
231
+ if not raw:
232
+ return None
233
+ segment = raw.strip('/')
234
+ if not segment:
235
+ return None
236
+ if not (
237
+ path == segment
238
+ or path == segment + '/'
239
+ or path.startswith(segment + '/')
240
+ ):
241
+ return None
242
+ show = self.app.view_functions.get('swagger_ui.show')
243
+ if not show:
244
+ return None
245
+ if path == segment or path == segment + '/':
246
+ return show()
247
+ rest = path[len(segment) :].lstrip('/')
248
+ return show(rest or None)
249
+
250
+ @staticmethod
251
+ def _get_project_root():
252
+ """
253
+ 获取项目根目录(使用当前工作目录)
254
+
255
+ :return: 项目根目录路径
256
+ """
257
+ return os.getcwd()
258
+
259
+ def __init__(self, app):
260
+ self.app = app
261
+
262
+ def set_routes(self):
263
+ # 0. 自动修复 PWA Service Worker 与 Swagger 的冲突
264
+ modules_dir = get_modules_dir()
265
+ _auto_fix_pwa_swagger_conflict(self.app, modules_dir)
266
+
267
+ # 1. 自动注册 ROUTE_CONFIG 中的文件服务路由
268
+ route_config = self.app.config.get('ROUTE_CONFIG', {})
269
+ for route_prefix, folder in route_config.items():
270
+ if not route_prefix or not folder:
271
+ continue
272
+ endpoint_name = f"path_route_{route_prefix}"
273
+
274
+ def make_handler(folder_path):
275
+ def handler(path):
276
+ folder_dir = os.path.join(self._get_project_root(), folder_path)
277
+ return send_from_directory(folder_dir, path)
278
+ return handler
279
+
280
+ self.app.add_url_rule(
281
+ f'/{route_prefix}/<path:path>',
282
+ endpoint=endpoint_name,
283
+ view_func=make_handler(folder)
284
+ )
285
+
286
+ # 2. 蓝图路由配置
287
+ sys_blueprints = ['api-docs', 'swagger_ui']
288
+ i = 0
289
+ project_root = self._get_project_root()
290
+ modules_dir = get_modules_dir() # 获取模块目录
291
+ jinja_loader_arr = [self.app.jinja_loader]
292
+ home_modules = self.app.config.get('HOME_MODULES', None)
293
+ for blueprint_name in self.app.blueprints:
294
+ if blueprint_name in sys_blueprints:
295
+ continue
296
+
297
+ # 支持 modules/*/templates 目录结构(前端打包目录放在模块根目录下)
298
+ if modules_dir:
299
+ module_templates = os.path.join(modules_dir, blueprint_name, 'templates')
300
+ if os.path.isdir(module_templates):
301
+ jinja_loader_arr.append(FileSystemLoader(module_templates))
302
+ web_path = module_templates
303
+ index_path = os.path.join(web_path, 'index.html')
304
+ else:
305
+ jinja_loader_arr.append(FileSystemLoader(f'{blueprint_name}/templates'))
306
+ web_path = os.path.join(project_root, f'{blueprint_name}/templates/{blueprint_name}')
307
+ index_path = os.path.join(web_path, 'index.html')
308
+ else:
309
+ jinja_loader_arr.append(FileSystemLoader(f'{blueprint_name}/templates'))
310
+ web_path = os.path.join(project_root, f'{blueprint_name}/templates/{blueprint_name}')
311
+ index_path = os.path.join(web_path, 'index.html')
312
+ is_home = False
313
+ if not os.path.exists(web_path) or not os.path.exists(index_path):
314
+ continue
315
+ if not home_modules and i == 0:
316
+ is_home = True
317
+ elif home_modules == blueprint_name:
318
+ is_home = True
319
+ if is_home:
320
+ self.register_static_route(blueprint_name, is_home)
321
+ self.register_static_route(blueprint_name, False)
322
+ i += 1
323
+ self.app.jinja_loader = ChoiceLoader(jinja_loader_arr)
324
+
325
+ def register_static_route(self, blueprint_name, is_home):
326
+ assets_path_pre = "/" if is_home else f"/{blueprint_name}"
327
+ modules_dir = get_modules_dir() # 获取模块目录
328
+
329
+ # 获取模块的 templates 目录
330
+ if modules_dir:
331
+ module_templates_dir = os.path.join(modules_dir, blueprint_name, 'templates')
332
+ else:
333
+ module_templates_dir = os.path.join(self._get_project_root(), f'{blueprint_name}/templates/{blueprint_name}')
334
+
335
+ # 动态生成唯一 endpoint 名称
336
+ if is_home:
337
+ index_endpoint = f"{blueprint_name}_home_index"
338
+ else:
339
+ index_endpoint = f"{blueprint_name}_index"
340
+
341
+ # 保存当前模块的 templates 目录(闭包捕获)
342
+ _templates_dir = module_templates_dir
343
+
344
+ @self.app.route(f"{assets_path_pre}", endpoint=f"{index_endpoint}_root")
345
+ def module_index_root():
346
+ # 直接发送模块自己的 index.html
347
+ return send_from_directory(_templates_dir, 'index.html')
348
+
349
+ # 统一处理所有路径请求(包括静态资源文件和 SPA 页面路由)
350
+ @self.app.route(f"{assets_path_pre}/<path:path>", endpoint=index_endpoint)
351
+ def module_index_path(path):
352
+ project_root = self._get_project_root()
353
+
354
+ # 1. 优先处理 ROUTE_CONFIG 映射(支持如 /admin/upload/xxx 映射到实际 upload 目录)
355
+ route_config = self.app.config.get('ROUTE_CONFIG', {})
356
+ for route_prefix, folder in route_config.items():
357
+ if path.startswith(f"{route_prefix}/"):
358
+ relative_path = path[len(route_prefix)+1:]
359
+ folder_dir = os.path.normpath(os.path.join(project_root, folder))
360
+ if os.path.isfile(os.path.join(folder_dir, relative_path)):
361
+ return send_from_directory(folder_dir, relative_path)
362
+
363
+ # 2. 自动探测资源文件逻辑
364
+ # 搜索优先级:1. modules/*/templates (前端打包目录) 2. 项目根目录
365
+ search_dirs = []
366
+ if modules_dir:
367
+ # 支持 modules/*/templates 目录结构
368
+ module_templates = os.path.join(modules_dir, blueprint_name, 'templates')
369
+ if os.path.isdir(module_templates):
370
+ search_dirs.append(module_templates)
371
+ search_dirs.append(os.path.join(project_root, f'{blueprint_name}/templates/{blueprint_name}'))
372
+ search_dirs.append(project_root)
373
+
374
+ for base_dir in search_dirs:
375
+ file_path = os.path.normpath(os.path.join(base_dir, path))
376
+ if os.path.isfile(file_path):
377
+ return send_from_directory(os.path.dirname(file_path), os.path.basename(file_path))
378
+
379
+ delegated = self._delegate_swagger_ui_if_needed(path)
380
+ if delegated is not None:
381
+ return delegated
382
+
383
+ # 3. SPA 路由支持:如果请求没有文件后缀,或者明确请求 index.html
384
+ file_ext = os.path.splitext(path)[1]
385
+ if not file_ext or path == 'index.html' or path.endswith('/'):
386
+ # 直接发送模块自己的 index.html
387
+ return send_from_directory(_templates_dir, 'index.html')
388
+
389
+ # 4. 如果有后缀但文件确实不存在,返回 404
390
+ abort(404)
@@ -0,0 +1,111 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 运行时钩子:在 create_app 前自动发现项目根并应用 path + iter_modules patch,
4
+ 使 Blueprint 能从 modules 目录正确加载,项目 run.py 无需手写 patch。
5
+ 支持 src/modules 和 modules 两种目录结构,优先使用配置的 MODULES_DIR。
6
+ """
7
+ import os
8
+ import pkgutil
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ _HOOK_APPLIED = False
13
+ _MODULES_DIR = None # 存储发现的模块目录
14
+
15
+
16
+ def get_modules_dir():
17
+ """获取模块目录路径"""
18
+ return str(_MODULES_DIR) if _MODULES_DIR else None
19
+
20
+ def _find_modules_dir(root: Path):
21
+ """查找模块目录,优先级:src/modules > modules"""
22
+ src_modules = root / "src" / "modules"
23
+ if src_modules.is_dir():
24
+ return src_modules
25
+ modules = root / "modules"
26
+ if modules.is_dir():
27
+ return modules
28
+ return None
29
+
30
+
31
+ def _find_project_root():
32
+ """从 cwd 向上查找包含 run.py 或 config/ 且含模块目录的项目根。"""
33
+ current = Path.cwd().resolve()
34
+ for _ in range(10):
35
+ if (current / "run.py").exists() or (current / "setup.py").exists():
36
+ if _find_modules_dir(current):
37
+ return current
38
+ # 支持 config/ 或 common/config/ 目录结构
39
+ has_config = (current / "config").is_dir() or (current / "common" / "config").is_dir()
40
+ if has_config and _find_modules_dir(current):
41
+ return current
42
+ parent = current.parent
43
+ if parent == current:
44
+ break
45
+ current = parent
46
+ return None
47
+
48
+
49
+ def apply_project_hook():
50
+ """
51
+ 若当前工作目录在弗雷德项目下(存在 modules 目录),则:
52
+ - 将项目根与 modules 目录加入 sys.path
53
+ - 将每个模块的 backend 目录加入 sys.path(支持 modules/*/backend 结构)
54
+ - patch pkgutil.iter_modules,使 Blueprints 从 modules 目录发现模块
55
+ 幂等,仅执行一次。
56
+ """
57
+ global _HOOK_APPLIED, _MODULES_DIR
58
+ if _HOOK_APPLIED:
59
+ return
60
+ root = _find_project_root()
61
+ if root is None:
62
+ return
63
+ modules_dir = _find_modules_dir(root)
64
+ if modules_dir is None:
65
+ return
66
+ _MODULES_DIR = modules_dir
67
+ root_str = str(root)
68
+ modules_dir_str = str(modules_dir)
69
+
70
+ # 收集所有需要添加的路径,然后按正确的优先级插入
71
+ # 优先级:项目根目录 > modules目录 > backend目录
72
+ paths_to_add = []
73
+
74
+ # 添加每个模块的 backend 目录(最低优先级)
75
+ for item in modules_dir.iterdir():
76
+ if item.is_dir() and not item.name.startswith('_'):
77
+ backend_dir = item / "backend"
78
+ if backend_dir.is_dir():
79
+ backend_dir_str = str(backend_dir)
80
+ paths_to_add.append(backend_dir_str)
81
+
82
+ # modules目录(中等优先级)
83
+ paths_to_add.append(modules_dir_str)
84
+
85
+ # 项目根目录(最高优先级)
86
+ paths_to_add.append(root_str)
87
+
88
+ # 先从 sys.path 中移除这些路径(如果存在),然后按正确顺序重新插入
89
+ for p in paths_to_add:
90
+ if p in sys.path:
91
+ sys.path.remove(p)
92
+
93
+ # 按相反顺序插入,使最高优先级的排在最前面
94
+ for p in paths_to_add:
95
+ sys.path.insert(0, p)
96
+
97
+ _orig_iter_modules = pkgutil.iter_modules
98
+
99
+ def _patched_iter_modules(path=None, prefix=""):
100
+ if path is not None and len(path) == 1:
101
+ p = path[0]
102
+ if p == "" or p == ".":
103
+ path = [modules_dir_str]
104
+ elif not os.path.isabs(p) and not os.path.exists(p):
105
+ alt = os.path.join(modules_dir_str, p)
106
+ if os.path.isdir(alt):
107
+ path = [alt]
108
+ return _orig_iter_modules(path, prefix)
109
+
110
+ pkgutil.iter_modules = _patched_iter_modules
111
+ _HOOK_APPLIED = True