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
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import List, Dict, Any, Optional
|
|
3
|
+
from flask import current_app
|
|
4
|
+
from iotdb.Session import Session
|
|
5
|
+
from iotdb.utils.IoTDBConstants import TSDataType
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IoTDBClient:
|
|
9
|
+
"""
|
|
10
|
+
IoTDB 数据库操作工具类
|
|
11
|
+
封装 IoTDB 的增删改查操作
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
"""
|
|
16
|
+
初始化 IoTDB 连接
|
|
17
|
+
"""
|
|
18
|
+
self.iotdb_client = None
|
|
19
|
+
self._connection_error = None
|
|
20
|
+
self._init_iotdb_connection()
|
|
21
|
+
|
|
22
|
+
def _init_iotdb_connection(self):
|
|
23
|
+
"""
|
|
24
|
+
初始化 IoTDB 数据库连接
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
# 获取 IoTDB 配置
|
|
28
|
+
iotdb_config = current_app.config.get('IOTDB_CONFIG', {})
|
|
29
|
+
host = iotdb_config.get('host', '127.0.0.1')
|
|
30
|
+
port = iotdb_config.get('port', 6667)
|
|
31
|
+
username = iotdb_config.get('username', 'root')
|
|
32
|
+
password = iotdb_config.get('password', 'root')
|
|
33
|
+
|
|
34
|
+
# 建立连接
|
|
35
|
+
self.iotdb_client = Session(host, port, username, password)
|
|
36
|
+
self.iotdb_client.open()
|
|
37
|
+
except Exception as e:
|
|
38
|
+
# 连接失败时,将 iotdb_client 设置为 None,并记录错误信息
|
|
39
|
+
self.iotdb_client = None
|
|
40
|
+
self._connection_error = str(e)
|
|
41
|
+
|
|
42
|
+
def _check_connection(self):
|
|
43
|
+
"""
|
|
44
|
+
检查 IoTDB 连接状态
|
|
45
|
+
如果连接失败,抛出异常
|
|
46
|
+
"""
|
|
47
|
+
if self.iotdb_client is None:
|
|
48
|
+
error_msg = self._connection_error or "IoTDB 连接失败"
|
|
49
|
+
from flask import abort
|
|
50
|
+
from flask_babelplus import gettext
|
|
51
|
+
abort(500, gettext(f"IoTDB 连接失败: {error_msg}"))
|
|
52
|
+
|
|
53
|
+
def _get_data_type(self, data_type_str: str):
|
|
54
|
+
"""
|
|
55
|
+
获取数据类型常量
|
|
56
|
+
:param data_type_str: 数据类型字符串,如 'INT32', 'INT64', 'FLOAT', 'DOUBLE', 'TEXT', 'BOOLEAN', 'INT'
|
|
57
|
+
:return: TSDataType 常量
|
|
58
|
+
"""
|
|
59
|
+
type_map = {
|
|
60
|
+
'INT32': TSDataType.INT32,
|
|
61
|
+
'INT64': TSDataType.INT64,
|
|
62
|
+
'FLOAT': TSDataType.FLOAT,
|
|
63
|
+
'DOUBLE': TSDataType.DOUBLE,
|
|
64
|
+
'TEXT': TSDataType.TEXT,
|
|
65
|
+
'BOOLEAN': TSDataType.BOOLEAN,
|
|
66
|
+
'INT': TSDataType.INT64, # INT 映射到 INT64
|
|
67
|
+
}
|
|
68
|
+
return type_map.get(data_type_str.upper(), TSDataType.TEXT)
|
|
69
|
+
|
|
70
|
+
def create_device(self, device_path: str, measurements: list, data_types: list) -> bool:
|
|
71
|
+
"""
|
|
72
|
+
创建设备时序数据(如果时序已存在则跳过)
|
|
73
|
+
:param device_path: 设备路径,如 'root.inference.camera_1_inference'
|
|
74
|
+
:param measurements: 测量项列表
|
|
75
|
+
:param data_types: 数据类型列表
|
|
76
|
+
:return: 操作成功与否
|
|
77
|
+
"""
|
|
78
|
+
self._check_connection()
|
|
79
|
+
try:
|
|
80
|
+
# 确保设备路径以 root 开头
|
|
81
|
+
if not device_path.startswith('root.'):
|
|
82
|
+
device_path = f'root.{device_path}'
|
|
83
|
+
|
|
84
|
+
created_count = 0
|
|
85
|
+
skipped_count = 0
|
|
86
|
+
|
|
87
|
+
# 为每个测量项创建时序
|
|
88
|
+
for measurement, data_type in zip(measurements, data_types):
|
|
89
|
+
# IoTDB 需要完整的路径格式:root.xxx.xxx.measurement
|
|
90
|
+
full_path = f"{device_path}.{measurement}"
|
|
91
|
+
# 将字符串类型转换为 IoTDB 数据类型
|
|
92
|
+
iotdb_data_type = self._get_data_type(data_type).name
|
|
93
|
+
create_sql = f"CREATE TIMESERIES {full_path} WITH DATATYPE={iotdb_data_type} ENCODING=PLAIN"
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
# 使用 execute_non_query_statement 执行非查询语句
|
|
97
|
+
self.iotdb_client.execute_non_query_statement(create_sql)
|
|
98
|
+
created_count += 1
|
|
99
|
+
except Exception as e:
|
|
100
|
+
error_msg = str(e)
|
|
101
|
+
# 如果时序已存在(错误码 503),则跳过
|
|
102
|
+
if "already exist" in error_msg or "503" in error_msg:
|
|
103
|
+
skipped_count += 1
|
|
104
|
+
continue
|
|
105
|
+
else:
|
|
106
|
+
# 其他错误则抛出
|
|
107
|
+
raise
|
|
108
|
+
|
|
109
|
+
return True
|
|
110
|
+
except Exception as e:
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
def insert_data(self, device_path: str, timestamp: int, measurements: list, types_lst: list, values: list) -> bool:
|
|
114
|
+
"""
|
|
115
|
+
插入数据
|
|
116
|
+
:param device_path: 设备路径,如 'root.inference.camera_1_inference'
|
|
117
|
+
:param timestamp: 时间戳(时序值,单位由 Config.TIMESTAMP_TO_MS_MULTIPLIER 决定)
|
|
118
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000,则为毫秒
|
|
119
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000000,则为微秒
|
|
120
|
+
:param measurements: 测量项列表
|
|
121
|
+
:param types_lst: 数据类型列表
|
|
122
|
+
:param values: 数据值列表(单条记录)
|
|
123
|
+
:return: 插入是否成功
|
|
124
|
+
"""
|
|
125
|
+
self._check_connection()
|
|
126
|
+
try:
|
|
127
|
+
# 确保设备路径以 root 开头
|
|
128
|
+
if not device_path.startswith('root.'):
|
|
129
|
+
device_path = f'root.{device_path}'
|
|
130
|
+
|
|
131
|
+
# 将数据类型字符串转换为 TSDataType 常量
|
|
132
|
+
data_types = [self._get_data_type(dt) for dt in types_lst]
|
|
133
|
+
|
|
134
|
+
# 使用 insert_record 插入单条数据
|
|
135
|
+
# 参数顺序:device_path, timestamp, measurements, data_types, values
|
|
136
|
+
self.iotdb_client.insert_record(
|
|
137
|
+
device_path,
|
|
138
|
+
timestamp,
|
|
139
|
+
measurements,
|
|
140
|
+
data_types,
|
|
141
|
+
values
|
|
142
|
+
)
|
|
143
|
+
return True
|
|
144
|
+
except Exception as e:
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
def _build_query_sql(self, device_path: str, start_time: Optional[int] = None,
|
|
148
|
+
end_time: Optional[int] = None, limit: Optional[int] = None,
|
|
149
|
+
order_by: Optional[str] = None, offset: Optional[int] = None,
|
|
150
|
+
enable_tracing: bool = False) -> str:
|
|
151
|
+
"""
|
|
152
|
+
构建查询 SQL 语句
|
|
153
|
+
:param device_path: 设备路径,支持通配符如 'root.inference.**'
|
|
154
|
+
:param start_time: 开始时间戳(时序值,单位由 Config.TIMESTAMP_TO_MS_MULTIPLIER 决定)
|
|
155
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000,则为毫秒
|
|
156
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000000,则为微秒
|
|
157
|
+
通过时序值(timestamp)进行时间区间查询
|
|
158
|
+
:param end_time: 结束时间戳(时序值,单位由 Config.TIMESTAMP_TO_MS_MULTIPLIER 决定)
|
|
159
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000,则为毫秒
|
|
160
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000000,则为微秒
|
|
161
|
+
通过时序值(timestamp)进行时间区间查询
|
|
162
|
+
:param limit: 返回结果数量限制
|
|
163
|
+
:param order_by: 排序方式,如 'time DESC' 或 'time ASC',默认为 None(不排序)
|
|
164
|
+
:param offset: 跳过前 N 行,用于分页查询
|
|
165
|
+
:param enable_tracing: 是否启用性能追踪(TRACING),用于分析查询性能
|
|
166
|
+
:return: SQL 语句
|
|
167
|
+
"""
|
|
168
|
+
# 确保设备路径以 root 开头
|
|
169
|
+
if not device_path.startswith('root.'):
|
|
170
|
+
device_path = f'root.{device_path}'
|
|
171
|
+
|
|
172
|
+
# 构建 WHERE 子句
|
|
173
|
+
where_parts = []
|
|
174
|
+
|
|
175
|
+
# 时间区间查询:使用时序值(timestamp)进行过滤
|
|
176
|
+
# IoTDB 的 time 字段是时序值,这是最有效的查询方式
|
|
177
|
+
if start_time is not None:
|
|
178
|
+
where_parts.append(f"time >= {start_time}")
|
|
179
|
+
if end_time is not None:
|
|
180
|
+
where_parts.append(f"time <= {end_time}")
|
|
181
|
+
|
|
182
|
+
# 注意:IoTDB 的 WHERE 子句主要用于时间范围查询(通过时序值 timestamp)
|
|
183
|
+
# 对于测量值的过滤,IoTDB 支持有限,通常需要在应用层(内存中)进行过滤
|
|
184
|
+
# 如果需要过滤测量值,建议在查询结果返回后在应用层进行过滤
|
|
185
|
+
|
|
186
|
+
where_clause = f" WHERE {' AND '.join(where_parts)}" if where_parts else ""
|
|
187
|
+
|
|
188
|
+
# 构建 ORDER BY 子句
|
|
189
|
+
order_by_clause = f" ORDER BY {order_by}" if order_by else ""
|
|
190
|
+
|
|
191
|
+
# 构建 LIMIT 和 OFFSET 子句
|
|
192
|
+
# IoTDB 支持 LIMIT N OFFSET M 语法进行分页查询
|
|
193
|
+
if limit is not None:
|
|
194
|
+
if offset is not None and offset > 0:
|
|
195
|
+
limit_clause = f" LIMIT {limit} OFFSET {offset}"
|
|
196
|
+
else:
|
|
197
|
+
limit_clause = f" LIMIT {limit}"
|
|
198
|
+
else:
|
|
199
|
+
limit_clause = ""
|
|
200
|
+
|
|
201
|
+
# 使用 SELECT * 语法,支持通配符路径
|
|
202
|
+
# IoTDB 支持使用 ** 进行递归查询
|
|
203
|
+
# 注意:在 IoTDB 中,SELECT * FROM device_path 会自动查询该设备下的所有测量值
|
|
204
|
+
# 不需要添加 .* 后缀,添加 .* 反而可能导致查询失败
|
|
205
|
+
# 如果路径已经以 .* 结尾,去掉它
|
|
206
|
+
if device_path.endswith('.*'):
|
|
207
|
+
device_path = device_path[:-2]
|
|
208
|
+
|
|
209
|
+
# 如果启用追踪,在 SQL 前添加 TRACING 关键词
|
|
210
|
+
tracing_prefix = "TRACING " if enable_tracing else ""
|
|
211
|
+
sql = f"{tracing_prefix}SELECT * FROM {device_path}{where_clause}{order_by_clause}{limit_clause}"
|
|
212
|
+
return sql.strip()
|
|
213
|
+
|
|
214
|
+
@staticmethod
|
|
215
|
+
def _extract_measurement_name(col_name: str) -> str:
|
|
216
|
+
"""
|
|
217
|
+
从列名提取测量值名称(移除设备路径前缀)
|
|
218
|
+
:param col_name: 列名,如 'root.inference.camera_1_inference.frame_stamp'
|
|
219
|
+
:return: 测量值名称,如 'frame_stamp'
|
|
220
|
+
"""
|
|
221
|
+
return col_name.split('.')[-1] if '.' in col_name else col_name
|
|
222
|
+
|
|
223
|
+
def _convert_field_value(self, field_obj, data_type) -> Any:
|
|
224
|
+
"""
|
|
225
|
+
根据数据类型转换字段值为 Python 原生类型
|
|
226
|
+
:param field_obj: IoTDB 字段对象
|
|
227
|
+
:param data_type: 数据类型
|
|
228
|
+
:return: 转换后的值
|
|
229
|
+
"""
|
|
230
|
+
try:
|
|
231
|
+
if field_obj.is_null():
|
|
232
|
+
return None
|
|
233
|
+
|
|
234
|
+
if data_type == TSDataType.BOOLEAN:
|
|
235
|
+
return bool(field_obj.get_bool_value())
|
|
236
|
+
elif data_type == TSDataType.INT32:
|
|
237
|
+
return int(field_obj.get_int_value())
|
|
238
|
+
elif data_type == TSDataType.INT64:
|
|
239
|
+
return int(field_obj.get_long_value())
|
|
240
|
+
elif data_type == TSDataType.FLOAT:
|
|
241
|
+
return float(field_obj.get_float_value())
|
|
242
|
+
elif data_type == TSDataType.DOUBLE:
|
|
243
|
+
return float(field_obj.get_double_value())
|
|
244
|
+
elif data_type == TSDataType.TEXT:
|
|
245
|
+
return str(field_obj.get_string_value())
|
|
246
|
+
else:
|
|
247
|
+
value = field_obj.get_object_value(data_type)
|
|
248
|
+
if value is not None:
|
|
249
|
+
type_name = value.__class__.__name__.lower()
|
|
250
|
+
if 'int' in type_name:
|
|
251
|
+
return int(value)
|
|
252
|
+
elif 'float' in type_name or 'double' in type_name:
|
|
253
|
+
return float(value)
|
|
254
|
+
elif 'bool' in type_name:
|
|
255
|
+
return bool(value)
|
|
256
|
+
elif not isinstance(value, (str, int, float, bool, type(None))):
|
|
257
|
+
return str(value)
|
|
258
|
+
return value
|
|
259
|
+
except Exception:
|
|
260
|
+
return None
|
|
261
|
+
|
|
262
|
+
def _parse_query_result(self, session_data_set, measurements: Optional[List[str]] = None) -> List[Dict[str, Any]]:
|
|
263
|
+
"""
|
|
264
|
+
解析查询结果集
|
|
265
|
+
:param session_data_set: IoTDB 查询结果集
|
|
266
|
+
:param measurements: 要查询的测量值列表,如果为 None 则查询所有测量值
|
|
267
|
+
:return: 查询结果列表
|
|
268
|
+
"""
|
|
269
|
+
results = []
|
|
270
|
+
column_names = session_data_set.get_column_names()
|
|
271
|
+
|
|
272
|
+
# 如果指定了 measurements,转换为集合以提高查找效率
|
|
273
|
+
measurements_set = set(measurements) if measurements else None
|
|
274
|
+
|
|
275
|
+
while session_data_set.has_next():
|
|
276
|
+
row = session_data_set.next()
|
|
277
|
+
# 确保 timestamp 是整数类型
|
|
278
|
+
timestamp = row.get_timestamp()
|
|
279
|
+
record = {'timestamp': int(timestamp) if timestamp is not None else None}
|
|
280
|
+
fields = row.get_fields()
|
|
281
|
+
|
|
282
|
+
# 构建列名到字段值的映射(不包括 Time 列)
|
|
283
|
+
col_name_to_field = {}
|
|
284
|
+
field_index = 0
|
|
285
|
+
for col_name in column_names:
|
|
286
|
+
if col_name == 'Time':
|
|
287
|
+
continue
|
|
288
|
+
|
|
289
|
+
if field_index < len(fields):
|
|
290
|
+
col_name_to_field[col_name] = fields[field_index]
|
|
291
|
+
field_index += 1
|
|
292
|
+
|
|
293
|
+
# 遍历所有列名(除了 Time),提取 measurement 名称并处理值
|
|
294
|
+
for col_name in column_names:
|
|
295
|
+
if col_name == 'Time':
|
|
296
|
+
continue
|
|
297
|
+
|
|
298
|
+
if col_name not in col_name_to_field:
|
|
299
|
+
continue
|
|
300
|
+
|
|
301
|
+
field_obj = col_name_to_field[col_name]
|
|
302
|
+
data_type = field_obj.get_data_type()
|
|
303
|
+
|
|
304
|
+
# 转换字段值
|
|
305
|
+
value = self._convert_field_value(field_obj, data_type)
|
|
306
|
+
|
|
307
|
+
# 提取测量值名称
|
|
308
|
+
measurement_name = self._extract_measurement_name(col_name)
|
|
309
|
+
|
|
310
|
+
# 如果指定了 measurements,只处理指定的测量值
|
|
311
|
+
if measurements_set is None or measurement_name in measurements_set:
|
|
312
|
+
# 对于同一个 measurement_name,优先保留非 None 值
|
|
313
|
+
if measurement_name in record:
|
|
314
|
+
if record[measurement_name] is not None:
|
|
315
|
+
if value is not None:
|
|
316
|
+
pass # 保留旧值
|
|
317
|
+
else:
|
|
318
|
+
record[measurement_name] = value
|
|
319
|
+
else:
|
|
320
|
+
record[measurement_name] = value
|
|
321
|
+
|
|
322
|
+
results.append(record)
|
|
323
|
+
|
|
324
|
+
return results
|
|
325
|
+
|
|
326
|
+
def list_timeseries(self, path_pattern: str = "root.**") -> List[str]:
|
|
327
|
+
"""
|
|
328
|
+
列出所有时序路径
|
|
329
|
+
:param path_pattern: 路径模式,如 'root.inference.**'
|
|
330
|
+
:return: 时序路径列表
|
|
331
|
+
"""
|
|
332
|
+
self._check_connection()
|
|
333
|
+
try:
|
|
334
|
+
# 确保路径以 root 开头
|
|
335
|
+
if not path_pattern.startswith('root.'):
|
|
336
|
+
path_pattern = f'root.{path_pattern}'
|
|
337
|
+
|
|
338
|
+
# 使用 SHOW TIMESERIES 查询
|
|
339
|
+
# IoTDB 的 SHOW TIMESERIES 语法:SHOW TIMESERIES [pathPattern]
|
|
340
|
+
sql = f"SHOW TIMESERIES {path_pattern}"
|
|
341
|
+
|
|
342
|
+
session_data_set = self.iotdb_client.execute_query_statement(sql)
|
|
343
|
+
session_data_set.set_fetch_size(10000)
|
|
344
|
+
|
|
345
|
+
timeseries_list = []
|
|
346
|
+
while session_data_set.has_next():
|
|
347
|
+
row = session_data_set.next()
|
|
348
|
+
# SHOW TIMESERIES 返回的列:timeseries, alias, storage group, dataType, encoding, compression, tags, attributes
|
|
349
|
+
fields = row.get_fields()
|
|
350
|
+
if fields and len(fields) > 0:
|
|
351
|
+
timeseries_path = fields[0].get_string_value()
|
|
352
|
+
timeseries_list.append(timeseries_path)
|
|
353
|
+
|
|
354
|
+
session_data_set.close_operation_handle()
|
|
355
|
+
return timeseries_list
|
|
356
|
+
except Exception as e:
|
|
357
|
+
return []
|
|
358
|
+
|
|
359
|
+
def query_count(self, device_path: str, start_time: Optional[int] = None,
|
|
360
|
+
end_time: Optional[int] = None) -> int:
|
|
361
|
+
"""
|
|
362
|
+
使用 COUNT 聚合查询获取记录总数(优化性能)
|
|
363
|
+
:param device_path: 设备路径,如 'root.inference.camera_1_inference' 或 'root.inference.**'
|
|
364
|
+
:param start_time: 开始时间戳(时序值)
|
|
365
|
+
:param end_time: 结束时间戳(时序值)
|
|
366
|
+
:return: 记录总数,如果查询失败返回 0
|
|
367
|
+
"""
|
|
368
|
+
self._check_connection()
|
|
369
|
+
try:
|
|
370
|
+
# 确保设备路径以 root 开头
|
|
371
|
+
if not device_path.startswith('root.'):
|
|
372
|
+
device_path = f'root.{device_path}'
|
|
373
|
+
|
|
374
|
+
# 构建 WHERE 子句
|
|
375
|
+
where_parts = []
|
|
376
|
+
if start_time is not None:
|
|
377
|
+
where_parts.append(f"time >= {start_time}")
|
|
378
|
+
if end_time is not None:
|
|
379
|
+
where_parts.append(f"time <= {end_time}")
|
|
380
|
+
where_clause = f" WHERE {' AND '.join(where_parts)}" if where_parts else ""
|
|
381
|
+
|
|
382
|
+
# 构建 COUNT 查询 SQL
|
|
383
|
+
# 注意:IoTDB 的 COUNT 查询需要指定具体的测量值,不能使用 COUNT(*)
|
|
384
|
+
# 对于通配符路径,需要指定一个具体的测量值,比如第一个测量值
|
|
385
|
+
# 这里尝试使用一个常见的测量值(如 frame_stamp)来统计记录数
|
|
386
|
+
# 如果 device_path 包含通配符,需要先获取一个具体的测量值
|
|
387
|
+
if '**' in device_path or '*' in device_path:
|
|
388
|
+
# 对于通配符路径,尝试使用 COUNT(第一个测量值)
|
|
389
|
+
# 先尝试使用 frame_stamp(推理日志中常见的字段)
|
|
390
|
+
sql = f"SELECT COUNT(frame_stamp) FROM {device_path}{where_clause}"
|
|
391
|
+
else:
|
|
392
|
+
# 对于具体路径,可以使用任意测量值
|
|
393
|
+
sql = f"SELECT COUNT(frame_stamp) FROM {device_path}{where_clause}"
|
|
394
|
+
|
|
395
|
+
# 执行查询
|
|
396
|
+
session_data_set = self.iotdb_client.execute_query_statement(sql)
|
|
397
|
+
session_data_set.set_fetch_size(10000)
|
|
398
|
+
|
|
399
|
+
# 解析结果
|
|
400
|
+
count = 0
|
|
401
|
+
if session_data_set.has_next():
|
|
402
|
+
row = session_data_set.next()
|
|
403
|
+
fields = row.get_fields()
|
|
404
|
+
if fields and len(fields) > 0:
|
|
405
|
+
# COUNT 查询返回的是聚合结果
|
|
406
|
+
count_value = fields[0].get_long_value() if hasattr(fields[0], 'get_long_value') else fields[0].get_int_value()
|
|
407
|
+
count = int(count_value) if count_value is not None else 0
|
|
408
|
+
|
|
409
|
+
session_data_set.close_operation_handle()
|
|
410
|
+
return count
|
|
411
|
+
except Exception as e:
|
|
412
|
+
return -1 # 返回 -1 表示 COUNT 查询失败,需要使用其他方法
|
|
413
|
+
|
|
414
|
+
def query_data(self, device_path: str, measurements: Optional[List[str]] = None,
|
|
415
|
+
start_time: Optional[int] = None, end_time: Optional[int] = None,
|
|
416
|
+
limit: Optional[int] = None, order_by: Optional[str] = None,
|
|
417
|
+
offset: Optional[int] = None, enable_tracing: bool = False) -> List[Dict[str, Any]]:
|
|
418
|
+
"""
|
|
419
|
+
查询数据
|
|
420
|
+
:param device_path: 设备路径,如 'root.inference.camera_1_inference' 或 'root.inference.**'
|
|
421
|
+
:param measurements: 要查询的测量值列表,如果为 None 则查询所有测量值
|
|
422
|
+
:param start_time: 开始时间戳(时序值,单位由 Config.TIMESTAMP_TO_MS_MULTIPLIER 决定)
|
|
423
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000,则为毫秒
|
|
424
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000000,则为微秒
|
|
425
|
+
通过时序值(timestamp)进行时间区间查询,如果为 None 则不限制开始时间
|
|
426
|
+
:param end_time: 结束时间戳(时序值,单位由 Config.TIMESTAMP_TO_MS_MULTIPLIER 决定)
|
|
427
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000,则为毫秒
|
|
428
|
+
如果 TIMESTAMP_TO_MS_MULTIPLIER = 1000000,则为微秒
|
|
429
|
+
通过时序值(timestamp)进行时间区间查询,如果为 None 则不限制结束时间
|
|
430
|
+
:param limit: 返回结果数量限制
|
|
431
|
+
:param order_by: 排序方式,如 'time DESC' 或 'time ASC',默认为 None(不排序)
|
|
432
|
+
:param offset: 跳过前 N 行,用于分页查询
|
|
433
|
+
:param enable_tracing: 是否启用性能追踪(TRACING),用于分析查询性能
|
|
434
|
+
:return: 查询结果列表,每个元素是一个字典,包含 timestamp 和各个测量值
|
|
435
|
+
"""
|
|
436
|
+
self._check_connection()
|
|
437
|
+
try:
|
|
438
|
+
# 构建 SQL 语句
|
|
439
|
+
sql = self._build_query_sql(device_path, start_time, end_time, limit, order_by, offset, enable_tracing)
|
|
440
|
+
|
|
441
|
+
# 执行查询
|
|
442
|
+
session_data_set = self.iotdb_client.execute_query_statement(sql)
|
|
443
|
+
session_data_set.set_fetch_size(10000)
|
|
444
|
+
|
|
445
|
+
# 解析结果
|
|
446
|
+
results = self._parse_query_result(session_data_set, measurements)
|
|
447
|
+
|
|
448
|
+
session_data_set.close_operation_handle()
|
|
449
|
+
|
|
450
|
+
return results
|
|
451
|
+
except Exception as e:
|
|
452
|
+
return []
|
|
453
|
+
|
|
454
|
+
def delete_data(self, device_path: str, start_time: Optional[int] = None,
|
|
455
|
+
end_time: Optional[int] = None, measurements: Optional[List[str]] = None) -> bool:
|
|
456
|
+
"""
|
|
457
|
+
删除数据
|
|
458
|
+
:param device_path: 设备路径,如 'root.inference.camera_1_inference' 或 'root.inference.**'
|
|
459
|
+
:param start_time: 开始时间戳(毫秒),如果为 None 则删除所有数据
|
|
460
|
+
:param end_time: 结束时间戳(毫秒),如果为 None 则删除到最新
|
|
461
|
+
:param measurements: 要删除的测量值列表,如果为 None 则删除所有测量值
|
|
462
|
+
:return: 删除是否成功
|
|
463
|
+
"""
|
|
464
|
+
self._check_connection()
|
|
465
|
+
try:
|
|
466
|
+
# 确保设备路径以 root 开头
|
|
467
|
+
if not device_path.startswith('root.'):
|
|
468
|
+
device_path = f'root.{device_path}'
|
|
469
|
+
|
|
470
|
+
# 如果使用通配符路径,需要先列出所有时序路径,然后逐个删除
|
|
471
|
+
if '**' in device_path or '*' in device_path:
|
|
472
|
+
# 列出所有时序路径
|
|
473
|
+
timeseries_list = self.list_timeseries(device_path)
|
|
474
|
+
|
|
475
|
+
if not timeseries_list:
|
|
476
|
+
return True # 没有数据可删,返回成功
|
|
477
|
+
|
|
478
|
+
# 提取所有唯一的设备路径(用于统计)
|
|
479
|
+
device_paths = set()
|
|
480
|
+
for ts_path in timeseries_list:
|
|
481
|
+
# 时序路径格式:root.inference.camera_1_inference.frame_stamp
|
|
482
|
+
# 提取设备路径:root.inference.camera_1_inference
|
|
483
|
+
parts = ts_path.split('.')
|
|
484
|
+
if len(parts) >= 3:
|
|
485
|
+
device_path_extracted = '.'.join(parts[:3])
|
|
486
|
+
device_paths.add(device_path_extracted)
|
|
487
|
+
|
|
488
|
+
# 如果指定了 measurements,只删除指定的测量值
|
|
489
|
+
# 否则删除所有时序路径
|
|
490
|
+
if measurements:
|
|
491
|
+
# 只删除指定测量值的时序路径
|
|
492
|
+
paths_to_delete = []
|
|
493
|
+
for ts_path in timeseries_list:
|
|
494
|
+
measurement_name = ts_path.split('.')[-1] # 获取测量值名称
|
|
495
|
+
if measurement_name in measurements:
|
|
496
|
+
paths_to_delete.append(ts_path)
|
|
497
|
+
else:
|
|
498
|
+
# 删除所有时序路径
|
|
499
|
+
paths_to_delete = timeseries_list
|
|
500
|
+
|
|
501
|
+
# 按设备路径分组删除(更高效)
|
|
502
|
+
device_path_to_timeseries = {}
|
|
503
|
+
for ts_path in paths_to_delete:
|
|
504
|
+
parts = ts_path.split('.')
|
|
505
|
+
if len(parts) >= 3:
|
|
506
|
+
dev_path = '.'.join(parts[:3])
|
|
507
|
+
if dev_path not in device_path_to_timeseries:
|
|
508
|
+
device_path_to_timeseries[dev_path] = []
|
|
509
|
+
device_path_to_timeseries[dev_path].append(ts_path)
|
|
510
|
+
|
|
511
|
+
# 直接删除所有时序路径(IoTDB 的 DELETE FROM 需要精确的时序路径)
|
|
512
|
+
# 因为时序路径格式复杂(如 root.inference.camera_1.model_5.tag_1.xxx),
|
|
513
|
+
# 删除设备路径可能无法删除子路径数据,所以直接删除所有时序路径
|
|
514
|
+
# 注意:IoTDB 的 DELETE FROM 只删除数据点,不删除时序路径定义
|
|
515
|
+
for ts_path in paths_to_delete:
|
|
516
|
+
try:
|
|
517
|
+
if start_time is not None and end_time is not None:
|
|
518
|
+
delete_sql = f"DELETE FROM {ts_path} WHERE time >= {start_time} AND time <= {end_time}"
|
|
519
|
+
elif start_time is not None:
|
|
520
|
+
delete_sql = f"DELETE FROM {ts_path} WHERE time >= {start_time}"
|
|
521
|
+
elif end_time is not None:
|
|
522
|
+
delete_sql = f"DELETE FROM {ts_path} WHERE time <= {end_time}"
|
|
523
|
+
else:
|
|
524
|
+
# 删除所有数据,使用 DELETE FROM 或 DELETE DATABASE
|
|
525
|
+
# 对于单个时序路径,使用 DELETE FROM
|
|
526
|
+
delete_sql = f"DELETE FROM {ts_path}"
|
|
527
|
+
|
|
528
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
529
|
+
except Exception as e:
|
|
530
|
+
pass
|
|
531
|
+
else:
|
|
532
|
+
# 构建删除路径列表
|
|
533
|
+
if measurements:
|
|
534
|
+
# 删除指定测量值
|
|
535
|
+
paths = [f"{device_path}.{measurement}" for measurement in measurements]
|
|
536
|
+
else:
|
|
537
|
+
# 删除整个设备的所有数据
|
|
538
|
+
paths = [device_path]
|
|
539
|
+
|
|
540
|
+
# 构建删除 SQL
|
|
541
|
+
if start_time is not None and end_time is not None:
|
|
542
|
+
# 删除指定时间范围的数据
|
|
543
|
+
for path in paths:
|
|
544
|
+
delete_sql = f"DELETE FROM {path} WHERE time >= {start_time} AND time <= {end_time}"
|
|
545
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
546
|
+
elif start_time is not None:
|
|
547
|
+
# 删除从开始时间到现在的数据
|
|
548
|
+
for path in paths:
|
|
549
|
+
delete_sql = f"DELETE FROM {path} WHERE time >= {start_time}"
|
|
550
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
551
|
+
elif end_time is not None:
|
|
552
|
+
# 删除到结束时间的数据
|
|
553
|
+
for path in paths:
|
|
554
|
+
delete_sql = f"DELETE FROM {path} WHERE time <= {end_time}"
|
|
555
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
556
|
+
else:
|
|
557
|
+
# 删除所有数据
|
|
558
|
+
for path in paths:
|
|
559
|
+
delete_sql = f"DELETE FROM {path}"
|
|
560
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
561
|
+
|
|
562
|
+
return True
|
|
563
|
+
except Exception as e:
|
|
564
|
+
return False
|
|
565
|
+
|
|
566
|
+
def clear_all_data(self, path_pattern: str = "root.inference.**") -> bool:
|
|
567
|
+
"""
|
|
568
|
+
清空所有数据
|
|
569
|
+
:param path_pattern: 路径模式,如 'root.inference.**'
|
|
570
|
+
:return: 清空是否成功
|
|
571
|
+
"""
|
|
572
|
+
self._check_connection()
|
|
573
|
+
try:
|
|
574
|
+
# 列出所有时序路径
|
|
575
|
+
timeseries_list = self.list_timeseries(path_pattern)
|
|
576
|
+
|
|
577
|
+
if not timeseries_list:
|
|
578
|
+
return True
|
|
579
|
+
|
|
580
|
+
# 提取所有唯一的设备路径
|
|
581
|
+
device_paths = set()
|
|
582
|
+
for ts_path in timeseries_list:
|
|
583
|
+
parts = ts_path.split('.')
|
|
584
|
+
if len(parts) >= 3:
|
|
585
|
+
device_path = '.'.join(parts[:3])
|
|
586
|
+
device_paths.add(device_path)
|
|
587
|
+
|
|
588
|
+
# 逐个清空每个设备的所有数据
|
|
589
|
+
for device_path in device_paths:
|
|
590
|
+
try:
|
|
591
|
+
delete_sql = f"DELETE FROM {device_path}"
|
|
592
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
593
|
+
except Exception as e:
|
|
594
|
+
pass
|
|
595
|
+
|
|
596
|
+
return True
|
|
597
|
+
except Exception as e:
|
|
598
|
+
return False
|
|
599
|
+
|
|
600
|
+
def delete_timeseries(self, path_pattern: str) -> bool:
|
|
601
|
+
"""
|
|
602
|
+
删除时序路径定义(删除路径结构,不仅仅是数据)
|
|
603
|
+
:param path_pattern: 路径模式,支持通配符,如 'root.inference.**' 或 'root.inference.camera_1.label_2.**'
|
|
604
|
+
:return: 删除是否成功
|
|
605
|
+
"""
|
|
606
|
+
self._check_connection()
|
|
607
|
+
try:
|
|
608
|
+
# 确保路径以 root 开头
|
|
609
|
+
if not path_pattern.startswith('root.'):
|
|
610
|
+
path_pattern = f'root.{path_pattern}'
|
|
611
|
+
|
|
612
|
+
# 如果使用通配符路径,需要先列出所有时序路径,然后逐个删除
|
|
613
|
+
if '**' in path_pattern or '*' in path_pattern:
|
|
614
|
+
# 列出所有匹配的时序路径
|
|
615
|
+
timeseries_list = self.list_timeseries(path_pattern)
|
|
616
|
+
|
|
617
|
+
if not timeseries_list:
|
|
618
|
+
return True # 没有路径可删,返回成功
|
|
619
|
+
|
|
620
|
+
# 逐个删除每个时序路径
|
|
621
|
+
for ts_path in timeseries_list:
|
|
622
|
+
try:
|
|
623
|
+
delete_sql = f"DELETE TIMESERIES {ts_path}"
|
|
624
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
625
|
+
except Exception as e:
|
|
626
|
+
error_msg = str(e)
|
|
627
|
+
# 如果路径不存在(508错误)或由设备模板表示,视为成功(幂等性)
|
|
628
|
+
if "508" in error_msg or "does not exist" in error_msg or "device template" in error_msg.lower():
|
|
629
|
+
continue
|
|
630
|
+
# 其他错误记录警告但继续删除其他路径
|
|
631
|
+
continue
|
|
632
|
+
else:
|
|
633
|
+
# 对于具体路径,判断是设备路径还是时序路径
|
|
634
|
+
# 先尝试列出该路径下的所有时序路径(使用通配符)
|
|
635
|
+
# 如果路径以 .** 结尾,直接使用;否则添加 .** 来匹配该路径下的所有时序路径
|
|
636
|
+
if path_pattern.endswith('.**'):
|
|
637
|
+
search_pattern = path_pattern
|
|
638
|
+
else:
|
|
639
|
+
# 对于设备路径(如 root.inference.camera_1.tag_1),添加 .** 来匹配所有时序路径
|
|
640
|
+
search_pattern = f"{path_pattern}.**"
|
|
641
|
+
|
|
642
|
+
# 列出该路径下的所有时序路径
|
|
643
|
+
timeseries_list = self.list_timeseries(search_pattern)
|
|
644
|
+
|
|
645
|
+
if not timeseries_list:
|
|
646
|
+
# 如果没有找到时序路径,可能是:
|
|
647
|
+
# 1. 路径不存在(已删除)
|
|
648
|
+
# 2. 传入的是完整的时序路径,尝试直接删除
|
|
649
|
+
if not path_pattern.endswith('.**'):
|
|
650
|
+
# 尝试作为完整的时序路径直接删除
|
|
651
|
+
try:
|
|
652
|
+
delete_sql = f"DELETE TIMESERIES {path_pattern}"
|
|
653
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
654
|
+
return True
|
|
655
|
+
except Exception as e:
|
|
656
|
+
error_msg = str(e)
|
|
657
|
+
# 如果路径不存在(508错误)或由设备模板表示,视为成功(幂等性)
|
|
658
|
+
if "508" in error_msg or "does not exist" in error_msg or "device template" in error_msg.lower():
|
|
659
|
+
return True
|
|
660
|
+
# 其他错误才视为失败
|
|
661
|
+
return False
|
|
662
|
+
else:
|
|
663
|
+
# 路径下没有时序路径,视为删除成功
|
|
664
|
+
return True
|
|
665
|
+
|
|
666
|
+
# 逐个删除每个时序路径
|
|
667
|
+
success_count = 0
|
|
668
|
+
fail_count = 0
|
|
669
|
+
for ts_path in timeseries_list:
|
|
670
|
+
try:
|
|
671
|
+
delete_sql = f"DELETE TIMESERIES {ts_path}"
|
|
672
|
+
self.iotdb_client.execute_non_query_statement(delete_sql)
|
|
673
|
+
success_count += 1
|
|
674
|
+
except Exception as e:
|
|
675
|
+
error_msg = str(e)
|
|
676
|
+
# 如果路径不存在(508错误)或由设备模板表示,视为成功(幂等性)
|
|
677
|
+
if "508" in error_msg or "does not exist" in error_msg or "device template" in error_msg.lower():
|
|
678
|
+
success_count += 1
|
|
679
|
+
else:
|
|
680
|
+
# 其他错误记录警告
|
|
681
|
+
fail_count += 1
|
|
682
|
+
|
|
683
|
+
# 如果至少有一个成功,或者所有都因为不存在而跳过,视为成功
|
|
684
|
+
if success_count > 0 or fail_count == 0:
|
|
685
|
+
return True
|
|
686
|
+
else:
|
|
687
|
+
return False
|
|
688
|
+
|
|
689
|
+
return True
|
|
690
|
+
except Exception as e:
|
|
691
|
+
return False
|
|
692
|
+
|
|
693
|
+
def close_connection(self):
|
|
694
|
+
"""关闭 IoTDB 连接"""
|
|
695
|
+
try:
|
|
696
|
+
self.iotdb_client.close()
|
|
697
|
+
except Exception as e:
|
|
698
|
+
pass
|