From a5f610ce4d1843c1eae8464a6a2b34aeca3bb6a2 Mon Sep 17 00:00:00 2001 From: "daikun1@bosssoft.com.cn" Date: Fri, 10 Nov 2023 16:06:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 19 + .env | 17 + .env.development | 37 + .env.production | 34 + .env.test | 37 + .eslintignore | 8 + .eslintrc-auto-import.json | 259 + .eslintrc.js | 72 + .gitignore | 11 + .prettierignore | 11 + .stylelintignore | 6 + LICENSE | 21 + README.md | 235 + build/vite/index.ts | 107 + build/vite/optimize.ts | 112 + index.html | 152 + package.json | 133 + postcss.config.js | 5 + prettier.config.js | 22 + public/favicon.ico | Bin 0 -> 4286 bytes public/home.png | Bin 0 -> 74352 bytes public/logo.gif | Bin 0 -> 6334 bytes src/App.vue | 75 + src/api/bpm/activity/index.ts | 8 + src/api/bpm/definition/index.ts | 21 + src/api/bpm/form/index.ts | 56 + src/api/bpm/leave/index.ts | 27 + src/api/bpm/model/index.ts | 59 + src/api/bpm/processInstance/index.ts | 41 + src/api/bpm/task/index.ts | 53 + src/api/bpm/taskAssignRule/index.ts | 29 + src/api/bpm/userGroup/index.ts | 47 + src/api/infra/apiAccessLog/index.ts | 30 + src/api/infra/apiErrorLog/index.ts | 48 + src/api/infra/codegen/index.ts | 123 + src/api/infra/config/index.ts | 48 + src/api/infra/dataSourceConfig/index.ts | 35 + src/api/infra/dbDoc/index.ts | 16 + src/api/infra/file/index.ts | 17 + src/api/infra/fileConfig/index.ts | 61 + src/api/infra/job/index.ts | 63 + src/api/infra/jobLog/index.ts | 33 + src/api/infra/redis/index.ts | 8 + src/api/infra/redis/types.ts | 176 + src/api/login/index.ts | 72 + src/api/login/oauth2/index.ts | 41 + src/api/login/types.ts | 28 + src/api/redis/index.ts | 21 + src/api/system/area/index.ts | 19 + src/api/system/dept/index.ts | 43 + src/api/system/dict/dict.data.ts | 49 + src/api/system/dict/dict.type.ts | 44 + src/api/system/errorCode/index.ts | 40 + src/api/system/loginLog/index.ts | 24 + src/api/system/mail/account/index.ts | 41 + src/api/system/mail/log/index.ts | 30 + src/api/system/mail/template/index.ts | 50 + src/api/system/menu/index.ts | 49 + src/api/system/notice/index.ts | 37 + src/api/system/notify/message/index.ts | 48 + src/api/system/notify/template/index.ts | 49 + src/api/system/oauth2/client.ts | 47 + src/api/system/oauth2/token.ts | 22 + src/api/system/operatelog/index.ts | 33 + src/api/system/permission/index.ts | 42 + src/api/system/post/index.ts | 46 + src/api/system/role/index.ts | 61 + src/api/system/sensitiveWord/index.ts | 58 + src/api/system/serialNumber/index.ts | 42 + src/api/system/sms/smsChannel/index.ts | 43 + src/api/system/sms/smsLog/index.ts | 39 + src/api/system/sms/smsTemplate/index.ts | 60 + src/api/system/tenant/index.ts | 62 + src/api/system/tenantPackage/index.ts | 42 + src/api/system/user/index.ts | 76 + src/api/system/user/profile.ts | 77 + src/api/system/user/socialUser.ts | 31 + src/assets/imgs/avatar.gif | Bin 0 -> 6334 bytes src/assets/imgs/avatar.jpg | Bin 0 -> 6264 bytes src/assets/imgs/code.png | Bin 0 -> 4871 bytes src/assets/imgs/logo.png | Bin 0 -> 16773 bytes src/assets/imgs/logo1.png | Bin 0 -> 4927 bytes src/assets/imgs/logo_w.png | Bin 0 -> 17324 bytes src/assets/imgs/profile.jpg | Bin 0 -> 7885 bytes src/assets/imgs/wechat.png | Bin 0 -> 1881 bytes src/assets/svgs/403.svg | 1 + src/assets/svgs/404.svg | 1 + src/assets/svgs/500.svg | 1 + src/assets/svgs/icon.svg | 1 + src/assets/svgs/login-bg.svg | 1 + src/assets/svgs/login-box-bg.svg | 1 + src/assets/svgs/member_balance.svg | 1 + .../svgs/member_expenditure_balance.svg | 1 + src/assets/svgs/member_level.svg | 1 + src/assets/svgs/member_point.svg | 1 + src/assets/svgs/member_recharge_balance.svg | 1 + src/assets/svgs/message.svg | 1 + src/assets/svgs/money.svg | 1 + src/assets/svgs/pay/icon/alipay_app.svg | 1 + src/assets/svgs/pay/icon/alipay_bar.svg | 2 + src/assets/svgs/pay/icon/alipay_pc.svg | 1 + src/assets/svgs/pay/icon/alipay_qr.svg | 2 + src/assets/svgs/pay/icon/alipay_wap.svg | 1 + src/assets/svgs/pay/icon/mock.svg | 1 + src/assets/svgs/pay/icon/wx_app.svg | 2 + src/assets/svgs/pay/icon/wx_bar.svg | 1 + src/assets/svgs/pay/icon/wx_lite.svg | 1 + src/assets/svgs/pay/icon/wx_native.svg | 1 + src/assets/svgs/pay/icon/wx_pub.svg | 2 + src/assets/svgs/peoples.svg | 1 + src/assets/svgs/shopping.svg | 1 + src/components/Annex/index.ts | 3 + src/components/Annex/src/Annex.vue | 127 + src/components/Backtop/index.ts | 3 + src/components/Backtop/src/Backtop.vue | 17 + src/components/BasicForm/index.ts | 3 + src/components/BasicForm/src/BasicForm.vue | 407 + src/components/Card/index.ts | 3 + src/components/Card/src/CardTitle.vue | 37 + src/components/ChangeRecord/index.ts | 3 + .../ChangeRecord/src/ChangeRecord.vue | 128 + src/components/ConfigGlobal/index.ts | 3 + .../ConfigGlobal/src/ConfigGlobal.vue | 63 + src/components/ContentDetailWrap/index.ts | 3 + .../src/ContentDetailWrap.vue | 58 + src/components/ContentWrap/index.ts | 3 + .../ContentWrap/src/ContentWrap.vue | 34 + src/components/CountTo/index.ts | 3 + src/components/CountTo/src/CountTo.vue | 182 + src/components/Crontab/index.ts | 2 + src/components/Crontab/src/Crontab.vue | 1011 + src/components/Cropper/index.ts | 4 + src/components/Cropper/src/CopperModal.vue | 261 + src/components/Cropper/src/Cropper.vue | 183 + src/components/Cropper/src/CropperAvatar.vue | 142 + src/components/Cropper/src/types.ts | 8 + src/components/Descriptions/index.ts | 4 + .../Descriptions/src/Descriptions.vue | 168 + .../src/DescriptionsItemLabel.vue | 29 + src/components/Detail/index.ts | 3 + src/components/Detail/src/Detail.vue | 376 + src/components/Dialog/index.ts | 3 + src/components/Dialog/src/Dialog.vue | 140 + src/components/DictTag/index.ts | 3 + src/components/DictTag/src/DictTag.vue | 60 + src/components/DocAlert/index.vue | 34 + src/components/Echart/index.ts | 3 + src/components/Echart/src/Echart.vue | 115 + src/components/Editor/index.ts | 8 + src/components/Editor/src/Editor.vue | 202 + src/components/Error/index.ts | 3 + src/components/Error/src/Error.vue | 58 + src/components/Form/index.ts | 15 + src/components/Form/src/Form.vue | 309 + src/components/Form/src/componentMap.ts | 55 + .../Form/src/components/useRenderCheckbox.tsx | 26 + .../Form/src/components/useRenderRadio.tsx | 26 + .../Form/src/components/useRenderSelect.tsx | 57 + src/components/Form/src/helper.ts | 148 + src/components/Form/src/types.ts | 17 + src/components/Highlight/index.ts | 3 + src/components/Highlight/src/Highlight.vue | 65 + src/components/Icon/index.ts | 4 + src/components/Icon/src/Icon.vue | 85 + src/components/Icon/src/IconSelect.vue | 229 + src/components/Icon/src/data.ts | 1961 + src/components/ImageViewer/index.ts | 33 + .../ImageViewer/src/ImageViewer.vue | 35 + src/components/ImageViewer/src/types.ts | 9 + src/components/ImportForm/index.ts | 3 + src/components/ImportForm/src/ImportForm.vue | 259 + src/components/Infotip/index.ts | 3 + src/components/Infotip/src/Infotip.vue | 54 + src/components/InputPassword/index.ts | 3 + .../InputPassword/src/InputPassword.vue | 152 + src/components/Pagination/index.vue | 87 + src/components/Qrcode/index.ts | 3 + src/components/Qrcode/src/Qrcode.vue | 253 + src/components/Remarks/index.ts | 3 + src/components/Remarks/src/Remarks.vue | 119 + src/components/RouterSearch/index.vue | 76 + src/components/Search/index.ts | 3 + src/components/Search/src/Search.vue | 158 + src/components/SearchHigh/index.ts | 3 + src/components/SearchHigh/src/SearchHigh.vue | 316 + src/components/SearchTable/index.ts | 3 + .../SearchTable/src/SearchTable.vue | 91 + src/components/Sticky/index.ts | 3 + src/components/Sticky/src/Sticky.vue | 143 + src/components/Table/index.ts | 12 + src/components/Table/src/Table.vue | 331 + src/components/Table/src/helper.ts | 8 + src/components/Table/src/types.ts | 26 + src/components/TableForm/index.ts | 3 + src/components/TableForm/src/TableForm.vue | 443 + src/components/TableHead/index.ts | 3 + src/components/TableHead/src/TableHead.vue | 170 + src/components/Tabs/index.ts | 3 + src/components/Tabs/src/Tabs.vue | 60 + src/components/Tooltip/index.ts | 3 + src/components/Tooltip/src/Tooltip.vue | 17 + src/components/UploadFile/index.ts | 5 + src/components/UploadFile/src/UploadFile.vue | 177 + src/components/UploadFile/src/UploadImg.vue | 272 + src/components/UploadFile/src/UploadImgs.vue | 310 + src/components/Verifition/index.ts | 3 + src/components/Verifition/src/Verify.vue | 441 + .../Verifition/src/Verify/VerifyPoints.vue | 250 + .../Verifition/src/Verify/VerifySlide.vue | 376 + src/components/Verifition/src/Verify/index.ts | 4 + src/components/Verifition/src/utils/ase.ts | 14 + src/components/Verifition/src/utils/util.ts | 97 + src/components/XButton/index.ts | 5 + src/components/XButton/src/ButtonBase.vue | 38 + src/components/XButton/src/XButton.vue | 50 + src/components/XButton/src/XTextButton.vue | 49 + .../package/designer/ProcessDesigner.vue | 704 + .../package/designer/ProcessViewer.vue | 635 + .../package/designer/index.ts | 8 + .../package/designer/index2.ts | 8 + .../plugins/content-pad/contentPadProvider.js | 423 + .../designer/plugins/content-pad/index.js | 6 + .../package/designer/plugins/defaultEmpty.js | 24 + .../descriptor/activitiDescriptor.json | 994 + .../plugins/descriptor/camundaDescriptor.json | 1010 + .../descriptor/flowableDescriptor.json | 1207 + .../activiti/activitiExtension.js | 83 + .../extension-moddle/activiti/index.js | 11 + .../extension-moddle/camunda/extension.js | 151 + .../plugins/extension-moddle/camunda/index.js | 8 + .../flowable/flowableExtension.js | 83 + .../extension-moddle/flowable/index.js | 10 + .../designer/plugins/palette/CustomPalette.js | 221 + .../package/designer/plugins/palette/index.js | 22 + .../plugins/palette/paletteProvider.js | 213 + .../plugins/translate/customTranslate.js | 44 + .../package/designer/plugins/translate/zh.js | 240 + .../bpmnProcessDesigner/package/index.ts | 11 + .../package/palette/ProcessPalette.vue | 45 + .../package/penal/PropertiesPanel.vue | 211 + .../package/penal/base/ElementBaseInfo.vue | 184 + .../penal/flow-condition/FlowCondition.vue | 191 + .../package/penal/form/ElementForm.vue | 465 + .../package/penal/index.js | 7 + .../penal/listeners/ElementListeners.vue | 403 + .../penal/listeners/UserTaskListeners.vue | 451 + .../package/penal/listeners/template.js | 178 + .../package/penal/listeners/utilSelf.ts | 62 + .../multi-instance/ElementMultiInstance.vue | 254 + .../penal/other/ElementOtherConfig.vue | 55 + .../penal/properties/ElementProperties.vue | 169 + .../penal/signal-message/SignalAndMessage.vue | 113 + .../package/penal/task/ElementTask.vue | 86 + .../task/task-components/ReceiveTask.vue | 125 + .../penal/task/task-components/ScriptTask.vue | 99 + .../penal/task/task-components/UserTask.vue | 98 + .../package/theme/element-variables.scss | 70 + .../package/theme/index.scss | 2 + .../package/theme/process-designer.scss | 161 + .../package/theme/process-panel.scss | 107 + .../bpmnProcessDesigner/package/utils.ts | 77 + .../src/highlight/index.js | 5 + .../modules/custom-renderer/CustomRenderer.js | 14 + .../src/modules/custom-renderer/index.js | 6 + .../src/modules/rules/CustomRules.js | 16 + .../src/modules/rules/index.js | 6 + .../bpmnProcessDesigner/src/translations.ts | 25 + .../src/utils/directive/clickOutSide.js | 39 + .../bpmnProcessDesigner/src/utils/index.js | 10 + .../bpmnProcessDesigner/src/utils/xml2json.js | 50 + src/components/iFrame/index.ts | 3 + src/components/iFrame/src/IFrame.vue | 68 + src/components/index.ts | 6 + src/components/rowDrop/index.vue | 205 + src/config/axios/config.ts | 28 + src/config/axios/errorCode.ts | 6 + src/config/axios/index.ts | 55 + src/config/axios/service.ts | 239 + src/directives/index.ts | 13 + src/directives/permission/hasPermi.ts | 27 + src/directives/permission/hasRole.ts | 27 + src/hooks/event/useScrollTo.ts | 60 + src/hooks/web/useCache.ts | 27 + src/hooks/web/useConfigGlobal.ts | 9 + src/hooks/web/useCrudSchemas.ts | 374 + src/hooks/web/useDesign.ts | 18 + src/hooks/web/useEmitt.ts | 22 + src/hooks/web/useForm.ts | 94 + src/hooks/web/useI18n.ts | 53 + src/hooks/web/useIcon.ts | 8 + src/hooks/web/useIntro.ts | 47 + src/hooks/web/useLocale.ts | 35 + src/hooks/web/useMessage.ts | 95 + src/hooks/web/useNProgress.ts | 33 + src/hooks/web/usePageLoading.ts | 18 + src/hooks/web/useTable.ts | 238 + src/hooks/web/useTimeAgo.ts | 49 + src/hooks/web/useTitle.ts | 24 + src/hooks/web/useValidator.ts | 62 + src/hooks/web/useWatermark.ts | 55 + src/layout/Layout.vue | 78 + src/layout/components/AppView.vue | 61 + src/layout/components/Breadcrumb/index.ts | 3 + .../components/Breadcrumb/src/Breadcrumb.vue | 128 + .../components/Breadcrumb/src/helper.ts | 31 + src/layout/components/Collapse/index.ts | 3 + .../components/Collapse/src/Collapse.vue | 36 + src/layout/components/ContextMenu/index.ts | 10 + .../ContextMenu/src/ContextMenu.vue | 76 + src/layout/components/Footer/index.ts | 3 + src/layout/components/Footer/src/Footer.vue | 24 + src/layout/components/LocaleDropdown/index.ts | 3 + .../LocaleDropdown/src/LocaleDropdown.vue | 52 + src/layout/components/Logo/index.ts | 3 + src/layout/components/Logo/src/Logo.vue | 88 + src/layout/components/Menu/index.ts | 3 + src/layout/components/Menu/src/Menu.vue | 290 + .../Menu/src/components/useRenderMenuItem.tsx | 59 + .../src/components/useRenderMenuTitle.tsx | 22 + src/layout/components/Menu/src/helper.ts | 54 + src/layout/components/Message/index.ts | 3 + src/layout/components/Message/src/Message.vue | 125 + src/layout/components/Screenfull/index.ts | 3 + .../components/Screenfull/src/Screenfull.vue | 32 + src/layout/components/Setting/index.ts | 3 + src/layout/components/Setting/src/Setting.vue | 299 + .../src/components/ColorRadioPicker.vue | 67 + .../src/components/InterfaceDisplay.vue | 224 + .../src/components/LayoutRadioPicker.vue | 172 + src/layout/components/SizeDropdown/index.ts | 3 + .../SizeDropdown/src/SizeDropdown.vue | 40 + src/layout/components/TabMenu/index.ts | 3 + src/layout/components/TabMenu/src/TabMenu.vue | 240 + src/layout/components/TabMenu/src/helper.ts | 51 + src/layout/components/TagsView/index.ts | 3 + .../components/TagsView/src/TagsView.vue | 585 + src/layout/components/TagsView/src/helper.ts | 21 + src/layout/components/ThemeSwitch/index.ts | 3 + .../ThemeSwitch/src/ThemeSwitch.vue | 46 + src/layout/components/ToolHeader.vue | 90 + src/layout/components/UserInfo/index.ts | 3 + .../components/UserInfo/src/UserInfo.vue | 78 + src/layout/components/useRenderLayout.tsx | 306 + src/locales/en-US.ts | 447 + src/locales/zh-CN.ts | 440 + src/main.ts | 73 + src/permission.ts | 70 + src/plugins/animate.css/index.ts | 1 + src/plugins/echarts/index.ts | 45 + src/plugins/elementPlus/index.ts | 17 + src/plugins/formCreate/index.ts | 43 + src/plugins/svgIcon/index.ts | 3 + src/plugins/tongji/index.ts | 23 + src/plugins/unocss/index.ts | 1 + src/plugins/vueI18n/helper.ts | 3 + src/plugins/vueI18n/index.ts | 42 + src/router/index.ts | 28 + src/router/modules/remaining.ts | 369 + src/store/index.ts | 10 + src/store/modules/app.ts | 274 + src/store/modules/dict.ts | 104 + src/store/modules/locale.ts | 59 + src/store/modules/permission.ts | 67 + src/store/modules/tagsView.ts | 140 + src/store/modules/user.ts | 91 + src/styles/global.module.scss | 6 + src/styles/index.scss | 35 + src/styles/theme.scss | 6 + src/styles/var.css | 66 + src/styles/variables.scss | 4 + src/types/components.d.ts | 56 + src/types/configGlobal.d.ts | 4 + src/types/contextMenu.d.ts | 7 + src/types/descriptions.d.ts | 13 + src/types/elementPlus.d.ts | 3 + src/types/form.d.ts | 44 + src/types/icon.d.ts | 5 + src/types/infoTip.d.ts | 4 + src/types/layout.d.ts | 1 + src/types/localeDropdown.d.ts | 10 + src/types/qrcode.d.ts | 9 + src/types/table.d.ts | 44 + src/types/tableForm.d.ts | 44 + src/types/theme.d.ts | 16 + src/utils/Logger.ts | 100 + src/utils/auth.ts | 92 + src/utils/color.ts | 153 + src/utils/constants.ts | 360 + src/utils/dict.ts | 269 + src/utils/disposition/defaultButtons.ts | 339 + src/utils/disposition/formFields.ts | 1954 + src/utils/disposition/tableColumns.ts | 73186 ++++++++++++++++ src/utils/disposition/tableDetailsColumns.ts | 1431 + src/utils/disposition/tableSummaryColumns.ts | 100 + src/utils/disposition/tabsList.ts | 31 + src/utils/domUtils.ts | 289 + src/utils/download.ts | 38 + src/utils/filt.ts | 157 + src/utils/formCreate.ts | 54 + src/utils/formRules.ts | 7 + src/utils/formatTime.ts | 232 + src/utils/formatter.ts | 12 + src/utils/index.ts | 245 + src/utils/is.ts | 105 + src/utils/jsencrypt.ts | 31 + src/utils/permission.ts | 45 + src/utils/propTypes.ts | 28 + src/utils/routerHelper.ts | 238 + src/utils/tree.ts | 399 + src/utils/tsxHelper.ts | 16 + src/utils/validator.ts | 760 + src/views/Home/Index.vue | 381 + src/views/Home/Index2.vue | 319 + src/views/Home/echarts-data.ts | 308 + src/views/Home/types.ts | 55 + src/views/Login/Login.vue | 104 + src/views/Login/components/LoginForm.vue | 278 + src/views/Login/components/LoginFormTitle.vue | 26 + src/views/Login/components/MobileForm.vue | 225 + src/views/Login/components/QrCodeForm.vue | 30 + src/views/Login/components/RegisterForm.vue | 142 + src/views/Login/components/SSOLogin.vue | 199 + src/views/Login/components/index.ts | 8 + src/views/Login/components/useLogin.ts | 42 + src/views/Profile/Index.vue | 64 + src/views/Profile/components/BasicInfo.vue | 92 + src/views/Profile/components/ProfileUser.vue | 99 + src/views/Profile/components/ResetPwd.vue | 73 + src/views/Profile/components/UserAvatar.vue | 39 + src/views/Profile/components/UserSocial.vue | 94 + src/views/Profile/components/index.ts | 7 + src/views/Redirect/Redirect.vue | 28 + src/views/bpm/definition/index.vue | 174 + src/views/bpm/form/editor/index.vue | 119 + src/views/bpm/form/index.vue | 165 + src/views/bpm/group/UserGroupForm.vue | 132 + src/views/bpm/group/index.vue | 149 + src/views/bpm/model/ModelForm.vue | 230 + src/views/bpm/model/ModelImportForm.vue | 140 + src/views/bpm/model/editor/index.vue | 105 + src/views/bpm/model/index.vue | 314 + src/views/bpm/oa/leave/create.vue | 89 + src/views/bpm/oa/leave/detail.vue | 51 + src/views/bpm/oa/leave/index.vue | 175 + .../bpm/processInstance/create/index.vue | 133 + .../detail/ProcessInstanceBpmnViewer.vue | 57 + .../detail/ProcessInstanceTaskList.vue | 97 + .../detail/TaskReturnDialogForm.vue | 90 + .../detail/TaskUpdateAssigneeForm.vue | 83 + .../bpm/processInstance/detail/index.vue | 285 + src/views/bpm/processInstance/index.vue | 186 + src/views/bpm/task/done/TaskDetail.vue | 51 + src/views/bpm/task/done/index.vue | 125 + src/views/bpm/task/todo/index.vue | 112 + .../bpm/taskAssignRule/TaskAssignRuleForm.vue | 250 + src/views/bpm/taskAssignRule/index.vue | 136 + src/views/error/403.vue | 8 + src/views/error/404.vue | 7 + src/views/error/500.vue | 7 + .../infra/apiAccessLog/ApiAccessLogDetail.vue | 67 + src/views/infra/apiAccessLog/index.vue | 167 + .../infra/apiErrorLog/ApiErrorLogDetail.vue | 81 + src/views/infra/apiErrorLog/index.vue | 249 + src/views/infra/build/index.vue | 143 + src/views/infra/codegen/PreviewCode.vue | 222 + .../codegen/components/BasicInfoForm.vue | 87 + .../codegen/components/ColumInfoForm.vue | 153 + .../codegen/components/GenerateInfoForm.vue | 391 + src/views/infra/codegen/components/index.ts | 4 + src/views/infra/codegen/editTable.vue | 83 + src/views/infra/codegen/importTable.vue | 151 + src/views/infra/codegen/index.vue | 258 + src/views/infra/config/ConfigForm.vue | 131 + src/views/infra/config/index.vue | 169 + src/views/infra/customInterface/index.vue | 21 + .../dataSourceConfig/DataSourceConfigForm.vue | 111 + src/views/infra/dataSourceConfig/index.vue | 87 + src/views/infra/dbDoc/index.vue | 57 + src/views/infra/druid/index.vue | 25 + src/views/infra/file/FileForm.vue | 104 + src/views/infra/file/index.vue | 164 + src/views/infra/fileConfig/FileConfigForm.vue | 195 + src/views/infra/fileConfig/index.vue | 168 + src/views/infra/job/JobDetail.vue | 73 + src/views/infra/job/JobForm.vue | 131 + src/views/infra/job/index.vue | 255 + src/views/infra/job/logger/JobLogDetail.vue | 59 + src/views/infra/job/logger/index.vue | 196 + src/views/infra/redis/index.vue | 266 + src/views/infra/server/index.vue | 28 + src/views/infra/skywalking/index.vue | 25 + src/views/infra/swagger/index.vue | 26 + src/views/infra/testDemo/index.vue | 4 + src/views/infra/webSocket/index.vue | 118 + src/views/report/goview/index.vue | 10 + src/views/report/jmreport/index.vue | 13 + src/views/system/area/AreaForm.vue | 72 + src/views/system/area/index.vue | 73 + src/views/system/dept/DeptForm.vue | 173 + src/views/system/dept/index.vue | 149 + src/views/system/dict/DictTypeForm.vue | 124 + src/views/system/dict/data/DictDataForm.vue | 183 + src/views/system/dict/data/index.vue | 210 + src/views/system/dict/index.vue | 175 + src/views/system/errorCode/ErrorCodeForm.vue | 112 + src/views/system/errorCode/index.vue | 171 + src/views/system/loginlog/LoginLogDetail.vue | 51 + src/views/system/loginlog/index.vue | 140 + .../system/mail/account/MailAccountDetail.vue | 28 + .../system/mail/account/MailAccountForm.vue | 68 + src/views/system/mail/account/account.data.ts | 76 + src/views/system/mail/account/index.vue | 80 + src/views/system/mail/log/MailLogDetail.vue | 33 + src/views/system/mail/log/index.vue | 62 + src/views/system/mail/log/log.data.ts | 133 + .../system/mail/template/MailTemplateForm.vue | 74 + .../mail/template/MailTemplateSendForm.vue | 115 + src/views/system/mail/template/index.vue | 84 + .../system/mail/template/template.data.ts | 113 + src/views/system/menu/MenuForm.vue | 256 + src/views/system/menu/index.vue | 276 + src/views/system/notice/NoticeForm.vue | 132 + src/views/system/notice/index.vue | 136 + .../notify/message/NotifyMessageDetail.vue | 66 + src/views/system/notify/message/index.vue | 142 + .../notify/my/MyNotifyMessageDetail.vue | 48 + src/views/system/notify/my/index.vue | 216 + .../notify/template/NotifyTemplateForm.vue | 141 + .../template/NotifyTemplateSendForm.vue | 129 + src/views/system/notify/template/index.vue | 164 + src/views/system/oauth2/client/ClientForm.vue | 266 + src/views/system/oauth2/client/index.vue | 150 + src/views/system/oauth2/token/index.vue | 122 + .../system/operatelog/OperateLogDetail.vue | 82 + src/views/system/operatelog/index.vue | 159 + src/views/system/post/PostForm.vue | 125 + src/views/system/post/index.vue | 157 + src/views/system/role/RoleAssignMenuForm.vue | 160 + .../system/role/RoleDataPermissionForm.vue | 167 + src/views/system/role/RoleForm.vue | 126 + src/views/system/role/index.vue | 264 + .../sensitiveWord/SensitiveWordForm.vue | 131 + .../sensitiveWord/SensitiveWordTestForm.vue | 91 + src/views/system/sensitiveWord/index.vue | 191 + .../system/serialNumber/SerialNumberForm.vue | 126 + src/views/system/serialNumber/index.vue | 182 + .../system/sms/channel/SmsChannelForm.vue | 144 + src/views/system/sms/channel/index.vue | 144 + src/views/system/sms/log/SmsLogDetail.vue | 89 + src/views/system/sms/log/index.vue | 193 + .../system/sms/template/SmsTemplateForm.vue | 163 + .../sms/template/SmsTemplateSendForm.vue | 120 + src/views/system/sms/template/index.vue | 213 + src/views/system/tenant/TenantForm.vue | 178 + src/views/system/tenant/index.vue | 192 + .../tenantPackage/TenantPackageForm.vue | 194 + src/views/system/tenantPackage/index.vue | 138 + src/views/system/user/DeptTree.vue | 63 + src/views/system/user/UserAssignRoleForm.vue | 96 + src/views/system/user/UserForm.vue | 218 + src/views/system/user/UserImportForm.vue | 135 + src/views/system/user/index.vue | 260 + stylelint.config.js | 233 + tsconfig.json | 45 + types/components.d.ts | 8 + types/custom-types.d.ts | 27 + types/env.d.ts | 32 + types/global.d.ts | 50 + types/router.d.ts | 81 + uno.config.ts | 105 + vite.config.ts | 81 + 571 files changed, 134954 insertions(+) create mode 100644 .editorconfig create mode 100644 .env create mode 100644 .env.development create mode 100644 .env.production create mode 100644 .env.test create mode 100644 .eslintignore create mode 100644 .eslintrc-auto-import.json create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 .stylelintignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 build/vite/index.ts create mode 100644 build/vite/optimize.ts create mode 100644 index.html create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 prettier.config.js create mode 100644 public/favicon.ico create mode 100644 public/home.png create mode 100644 public/logo.gif create mode 100644 src/App.vue create mode 100644 src/api/bpm/activity/index.ts create mode 100644 src/api/bpm/definition/index.ts create mode 100644 src/api/bpm/form/index.ts create mode 100644 src/api/bpm/leave/index.ts create mode 100644 src/api/bpm/model/index.ts create mode 100644 src/api/bpm/processInstance/index.ts create mode 100644 src/api/bpm/task/index.ts create mode 100644 src/api/bpm/taskAssignRule/index.ts create mode 100644 src/api/bpm/userGroup/index.ts create mode 100644 src/api/infra/apiAccessLog/index.ts create mode 100644 src/api/infra/apiErrorLog/index.ts create mode 100644 src/api/infra/codegen/index.ts create mode 100644 src/api/infra/config/index.ts create mode 100644 src/api/infra/dataSourceConfig/index.ts create mode 100644 src/api/infra/dbDoc/index.ts create mode 100644 src/api/infra/file/index.ts create mode 100644 src/api/infra/fileConfig/index.ts create mode 100644 src/api/infra/job/index.ts create mode 100644 src/api/infra/jobLog/index.ts create mode 100644 src/api/infra/redis/index.ts create mode 100644 src/api/infra/redis/types.ts create mode 100644 src/api/login/index.ts create mode 100644 src/api/login/oauth2/index.ts create mode 100644 src/api/login/types.ts create mode 100644 src/api/redis/index.ts create mode 100644 src/api/system/area/index.ts create mode 100644 src/api/system/dept/index.ts create mode 100644 src/api/system/dict/dict.data.ts create mode 100644 src/api/system/dict/dict.type.ts create mode 100644 src/api/system/errorCode/index.ts create mode 100644 src/api/system/loginLog/index.ts create mode 100644 src/api/system/mail/account/index.ts create mode 100644 src/api/system/mail/log/index.ts create mode 100644 src/api/system/mail/template/index.ts create mode 100644 src/api/system/menu/index.ts create mode 100644 src/api/system/notice/index.ts create mode 100644 src/api/system/notify/message/index.ts create mode 100644 src/api/system/notify/template/index.ts create mode 100644 src/api/system/oauth2/client.ts create mode 100644 src/api/system/oauth2/token.ts create mode 100644 src/api/system/operatelog/index.ts create mode 100644 src/api/system/permission/index.ts create mode 100644 src/api/system/post/index.ts create mode 100644 src/api/system/role/index.ts create mode 100644 src/api/system/sensitiveWord/index.ts create mode 100644 src/api/system/serialNumber/index.ts create mode 100644 src/api/system/sms/smsChannel/index.ts create mode 100644 src/api/system/sms/smsLog/index.ts create mode 100644 src/api/system/sms/smsTemplate/index.ts create mode 100644 src/api/system/tenant/index.ts create mode 100644 src/api/system/tenantPackage/index.ts create mode 100644 src/api/system/user/index.ts create mode 100644 src/api/system/user/profile.ts create mode 100644 src/api/system/user/socialUser.ts create mode 100644 src/assets/imgs/avatar.gif create mode 100644 src/assets/imgs/avatar.jpg create mode 100644 src/assets/imgs/code.png create mode 100644 src/assets/imgs/logo.png create mode 100644 src/assets/imgs/logo1.png create mode 100644 src/assets/imgs/logo_w.png create mode 100644 src/assets/imgs/profile.jpg create mode 100644 src/assets/imgs/wechat.png create mode 100644 src/assets/svgs/403.svg create mode 100644 src/assets/svgs/404.svg create mode 100644 src/assets/svgs/500.svg create mode 100644 src/assets/svgs/icon.svg create mode 100644 src/assets/svgs/login-bg.svg create mode 100644 src/assets/svgs/login-box-bg.svg create mode 100644 src/assets/svgs/member_balance.svg create mode 100644 src/assets/svgs/member_expenditure_balance.svg create mode 100644 src/assets/svgs/member_level.svg create mode 100644 src/assets/svgs/member_point.svg create mode 100644 src/assets/svgs/member_recharge_balance.svg create mode 100644 src/assets/svgs/message.svg create mode 100644 src/assets/svgs/money.svg create mode 100644 src/assets/svgs/pay/icon/alipay_app.svg create mode 100644 src/assets/svgs/pay/icon/alipay_bar.svg create mode 100644 src/assets/svgs/pay/icon/alipay_pc.svg create mode 100644 src/assets/svgs/pay/icon/alipay_qr.svg create mode 100644 src/assets/svgs/pay/icon/alipay_wap.svg create mode 100644 src/assets/svgs/pay/icon/mock.svg create mode 100644 src/assets/svgs/pay/icon/wx_app.svg create mode 100644 src/assets/svgs/pay/icon/wx_bar.svg create mode 100644 src/assets/svgs/pay/icon/wx_lite.svg create mode 100644 src/assets/svgs/pay/icon/wx_native.svg create mode 100644 src/assets/svgs/pay/icon/wx_pub.svg create mode 100644 src/assets/svgs/peoples.svg create mode 100644 src/assets/svgs/shopping.svg create mode 100644 src/components/Annex/index.ts create mode 100644 src/components/Annex/src/Annex.vue create mode 100644 src/components/Backtop/index.ts create mode 100644 src/components/Backtop/src/Backtop.vue create mode 100644 src/components/BasicForm/index.ts create mode 100644 src/components/BasicForm/src/BasicForm.vue create mode 100644 src/components/Card/index.ts create mode 100644 src/components/Card/src/CardTitle.vue create mode 100644 src/components/ChangeRecord/index.ts create mode 100644 src/components/ChangeRecord/src/ChangeRecord.vue create mode 100644 src/components/ConfigGlobal/index.ts create mode 100644 src/components/ConfigGlobal/src/ConfigGlobal.vue create mode 100644 src/components/ContentDetailWrap/index.ts create mode 100644 src/components/ContentDetailWrap/src/ContentDetailWrap.vue create mode 100644 src/components/ContentWrap/index.ts create mode 100644 src/components/ContentWrap/src/ContentWrap.vue create mode 100644 src/components/CountTo/index.ts create mode 100644 src/components/CountTo/src/CountTo.vue create mode 100644 src/components/Crontab/index.ts create mode 100644 src/components/Crontab/src/Crontab.vue create mode 100644 src/components/Cropper/index.ts create mode 100644 src/components/Cropper/src/CopperModal.vue create mode 100644 src/components/Cropper/src/Cropper.vue create mode 100644 src/components/Cropper/src/CropperAvatar.vue create mode 100644 src/components/Cropper/src/types.ts create mode 100644 src/components/Descriptions/index.ts create mode 100644 src/components/Descriptions/src/Descriptions.vue create mode 100644 src/components/Descriptions/src/DescriptionsItemLabel.vue create mode 100644 src/components/Detail/index.ts create mode 100644 src/components/Detail/src/Detail.vue create mode 100644 src/components/Dialog/index.ts create mode 100644 src/components/Dialog/src/Dialog.vue create mode 100644 src/components/DictTag/index.ts create mode 100644 src/components/DictTag/src/DictTag.vue create mode 100644 src/components/DocAlert/index.vue create mode 100644 src/components/Echart/index.ts create mode 100644 src/components/Echart/src/Echart.vue create mode 100644 src/components/Editor/index.ts create mode 100644 src/components/Editor/src/Editor.vue create mode 100644 src/components/Error/index.ts create mode 100644 src/components/Error/src/Error.vue create mode 100644 src/components/Form/index.ts create mode 100644 src/components/Form/src/Form.vue create mode 100644 src/components/Form/src/componentMap.ts create mode 100644 src/components/Form/src/components/useRenderCheckbox.tsx create mode 100644 src/components/Form/src/components/useRenderRadio.tsx create mode 100644 src/components/Form/src/components/useRenderSelect.tsx create mode 100644 src/components/Form/src/helper.ts create mode 100644 src/components/Form/src/types.ts create mode 100644 src/components/Highlight/index.ts create mode 100644 src/components/Highlight/src/Highlight.vue create mode 100644 src/components/Icon/index.ts create mode 100644 src/components/Icon/src/Icon.vue create mode 100644 src/components/Icon/src/IconSelect.vue create mode 100644 src/components/Icon/src/data.ts create mode 100644 src/components/ImageViewer/index.ts create mode 100644 src/components/ImageViewer/src/ImageViewer.vue create mode 100644 src/components/ImageViewer/src/types.ts create mode 100644 src/components/ImportForm/index.ts create mode 100644 src/components/ImportForm/src/ImportForm.vue create mode 100644 src/components/Infotip/index.ts create mode 100644 src/components/Infotip/src/Infotip.vue create mode 100644 src/components/InputPassword/index.ts create mode 100644 src/components/InputPassword/src/InputPassword.vue create mode 100644 src/components/Pagination/index.vue create mode 100644 src/components/Qrcode/index.ts create mode 100644 src/components/Qrcode/src/Qrcode.vue create mode 100644 src/components/Remarks/index.ts create mode 100644 src/components/Remarks/src/Remarks.vue create mode 100644 src/components/RouterSearch/index.vue create mode 100644 src/components/Search/index.ts create mode 100644 src/components/Search/src/Search.vue create mode 100644 src/components/SearchHigh/index.ts create mode 100644 src/components/SearchHigh/src/SearchHigh.vue create mode 100644 src/components/SearchTable/index.ts create mode 100644 src/components/SearchTable/src/SearchTable.vue create mode 100644 src/components/Sticky/index.ts create mode 100644 src/components/Sticky/src/Sticky.vue create mode 100644 src/components/Table/index.ts create mode 100644 src/components/Table/src/Table.vue create mode 100644 src/components/Table/src/helper.ts create mode 100644 src/components/Table/src/types.ts create mode 100644 src/components/TableForm/index.ts create mode 100644 src/components/TableForm/src/TableForm.vue create mode 100644 src/components/TableHead/index.ts create mode 100644 src/components/TableHead/src/TableHead.vue create mode 100644 src/components/Tabs/index.ts create mode 100644 src/components/Tabs/src/Tabs.vue create mode 100644 src/components/Tooltip/index.ts create mode 100644 src/components/Tooltip/src/Tooltip.vue create mode 100644 src/components/UploadFile/index.ts create mode 100644 src/components/UploadFile/src/UploadFile.vue create mode 100644 src/components/UploadFile/src/UploadImg.vue create mode 100644 src/components/UploadFile/src/UploadImgs.vue create mode 100644 src/components/Verifition/index.ts create mode 100644 src/components/Verifition/src/Verify.vue create mode 100644 src/components/Verifition/src/Verify/VerifyPoints.vue create mode 100644 src/components/Verifition/src/Verify/VerifySlide.vue create mode 100644 src/components/Verifition/src/Verify/index.ts create mode 100644 src/components/Verifition/src/utils/ase.ts create mode 100644 src/components/Verifition/src/utils/util.ts create mode 100644 src/components/XButton/index.ts create mode 100644 src/components/XButton/src/ButtonBase.vue create mode 100644 src/components/XButton/src/XButton.vue create mode 100644 src/components/XButton/src/XTextButton.vue create mode 100644 src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue create mode 100644 src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue create mode 100644 src/components/bpmnProcessDesigner/package/designer/index.ts create mode 100644 src/components/bpmnProcessDesigner/package/designer/index2.ts create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/contentPadProvider.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/content-pad/index.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/defaultEmpty.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/activitiDescriptor.json create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/camundaDescriptor.json create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/activitiExtension.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/activiti/index.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/extension.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/camunda/index.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/flowableExtension.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/extension-moddle/flowable/index.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/palette/CustomPalette.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/palette/index.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/palette/paletteProvider.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/translate/customTranslate.js create mode 100644 src/components/bpmnProcessDesigner/package/designer/plugins/translate/zh.js create mode 100644 src/components/bpmnProcessDesigner/package/index.ts create mode 100644 src/components/bpmnProcessDesigner/package/palette/ProcessPalette.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/index.js create mode 100644 src/components/bpmnProcessDesigner/package/penal/listeners/ElementListeners.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/listeners/template.js create mode 100644 src/components/bpmnProcessDesigner/package/penal/listeners/utilSelf.ts create mode 100644 src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/other/ElementOtherConfig.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/properties/ElementProperties.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/task/ElementTask.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/task/task-components/ScriptTask.vue create mode 100644 src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue create mode 100644 src/components/bpmnProcessDesigner/package/theme/element-variables.scss create mode 100644 src/components/bpmnProcessDesigner/package/theme/index.scss create mode 100644 src/components/bpmnProcessDesigner/package/theme/process-designer.scss create mode 100644 src/components/bpmnProcessDesigner/package/theme/process-panel.scss create mode 100644 src/components/bpmnProcessDesigner/package/utils.ts create mode 100644 src/components/bpmnProcessDesigner/src/highlight/index.js create mode 100644 src/components/bpmnProcessDesigner/src/modules/custom-renderer/CustomRenderer.js create mode 100644 src/components/bpmnProcessDesigner/src/modules/custom-renderer/index.js create mode 100644 src/components/bpmnProcessDesigner/src/modules/rules/CustomRules.js create mode 100644 src/components/bpmnProcessDesigner/src/modules/rules/index.js create mode 100644 src/components/bpmnProcessDesigner/src/translations.ts create mode 100644 src/components/bpmnProcessDesigner/src/utils/directive/clickOutSide.js create mode 100644 src/components/bpmnProcessDesigner/src/utils/index.js create mode 100644 src/components/bpmnProcessDesigner/src/utils/xml2json.js create mode 100644 src/components/iFrame/index.ts create mode 100644 src/components/iFrame/src/IFrame.vue create mode 100644 src/components/index.ts create mode 100644 src/components/rowDrop/index.vue create mode 100644 src/config/axios/config.ts create mode 100644 src/config/axios/errorCode.ts create mode 100644 src/config/axios/index.ts create mode 100644 src/config/axios/service.ts create mode 100644 src/directives/index.ts create mode 100644 src/directives/permission/hasPermi.ts create mode 100644 src/directives/permission/hasRole.ts create mode 100644 src/hooks/event/useScrollTo.ts create mode 100644 src/hooks/web/useCache.ts create mode 100644 src/hooks/web/useConfigGlobal.ts create mode 100644 src/hooks/web/useCrudSchemas.ts create mode 100644 src/hooks/web/useDesign.ts create mode 100644 src/hooks/web/useEmitt.ts create mode 100644 src/hooks/web/useForm.ts create mode 100644 src/hooks/web/useI18n.ts create mode 100644 src/hooks/web/useIcon.ts create mode 100644 src/hooks/web/useIntro.ts create mode 100644 src/hooks/web/useLocale.ts create mode 100644 src/hooks/web/useMessage.ts create mode 100644 src/hooks/web/useNProgress.ts create mode 100644 src/hooks/web/usePageLoading.ts create mode 100644 src/hooks/web/useTable.ts create mode 100644 src/hooks/web/useTimeAgo.ts create mode 100644 src/hooks/web/useTitle.ts create mode 100644 src/hooks/web/useValidator.ts create mode 100644 src/hooks/web/useWatermark.ts create mode 100644 src/layout/Layout.vue create mode 100644 src/layout/components/AppView.vue create mode 100644 src/layout/components/Breadcrumb/index.ts create mode 100644 src/layout/components/Breadcrumb/src/Breadcrumb.vue create mode 100644 src/layout/components/Breadcrumb/src/helper.ts create mode 100644 src/layout/components/Collapse/index.ts create mode 100644 src/layout/components/Collapse/src/Collapse.vue create mode 100644 src/layout/components/ContextMenu/index.ts create mode 100644 src/layout/components/ContextMenu/src/ContextMenu.vue create mode 100644 src/layout/components/Footer/index.ts create mode 100644 src/layout/components/Footer/src/Footer.vue create mode 100644 src/layout/components/LocaleDropdown/index.ts create mode 100644 src/layout/components/LocaleDropdown/src/LocaleDropdown.vue create mode 100644 src/layout/components/Logo/index.ts create mode 100644 src/layout/components/Logo/src/Logo.vue create mode 100644 src/layout/components/Menu/index.ts create mode 100644 src/layout/components/Menu/src/Menu.vue create mode 100644 src/layout/components/Menu/src/components/useRenderMenuItem.tsx create mode 100644 src/layout/components/Menu/src/components/useRenderMenuTitle.tsx create mode 100644 src/layout/components/Menu/src/helper.ts create mode 100644 src/layout/components/Message/index.ts create mode 100644 src/layout/components/Message/src/Message.vue create mode 100644 src/layout/components/Screenfull/index.ts create mode 100644 src/layout/components/Screenfull/src/Screenfull.vue create mode 100644 src/layout/components/Setting/index.ts create mode 100644 src/layout/components/Setting/src/Setting.vue create mode 100644 src/layout/components/Setting/src/components/ColorRadioPicker.vue create mode 100644 src/layout/components/Setting/src/components/InterfaceDisplay.vue create mode 100644 src/layout/components/Setting/src/components/LayoutRadioPicker.vue create mode 100644 src/layout/components/SizeDropdown/index.ts create mode 100644 src/layout/components/SizeDropdown/src/SizeDropdown.vue create mode 100644 src/layout/components/TabMenu/index.ts create mode 100644 src/layout/components/TabMenu/src/TabMenu.vue create mode 100644 src/layout/components/TabMenu/src/helper.ts create mode 100644 src/layout/components/TagsView/index.ts create mode 100644 src/layout/components/TagsView/src/TagsView.vue create mode 100644 src/layout/components/TagsView/src/helper.ts create mode 100644 src/layout/components/ThemeSwitch/index.ts create mode 100644 src/layout/components/ThemeSwitch/src/ThemeSwitch.vue create mode 100644 src/layout/components/ToolHeader.vue create mode 100644 src/layout/components/UserInfo/index.ts create mode 100644 src/layout/components/UserInfo/src/UserInfo.vue create mode 100644 src/layout/components/useRenderLayout.tsx create mode 100644 src/locales/en-US.ts create mode 100644 src/locales/zh-CN.ts create mode 100644 src/main.ts create mode 100644 src/permission.ts create mode 100644 src/plugins/animate.css/index.ts create mode 100644 src/plugins/echarts/index.ts create mode 100644 src/plugins/elementPlus/index.ts create mode 100644 src/plugins/formCreate/index.ts create mode 100644 src/plugins/svgIcon/index.ts create mode 100644 src/plugins/tongji/index.ts create mode 100644 src/plugins/unocss/index.ts create mode 100644 src/plugins/vueI18n/helper.ts create mode 100644 src/plugins/vueI18n/index.ts create mode 100644 src/router/index.ts create mode 100644 src/router/modules/remaining.ts create mode 100644 src/store/index.ts create mode 100644 src/store/modules/app.ts create mode 100644 src/store/modules/dict.ts create mode 100644 src/store/modules/locale.ts create mode 100644 src/store/modules/permission.ts create mode 100644 src/store/modules/tagsView.ts create mode 100644 src/store/modules/user.ts create mode 100644 src/styles/global.module.scss create mode 100644 src/styles/index.scss create mode 100644 src/styles/theme.scss create mode 100644 src/styles/var.css create mode 100644 src/styles/variables.scss create mode 100644 src/types/components.d.ts create mode 100644 src/types/configGlobal.d.ts create mode 100644 src/types/contextMenu.d.ts create mode 100644 src/types/descriptions.d.ts create mode 100644 src/types/elementPlus.d.ts create mode 100644 src/types/form.d.ts create mode 100644 src/types/icon.d.ts create mode 100644 src/types/infoTip.d.ts create mode 100644 src/types/layout.d.ts create mode 100644 src/types/localeDropdown.d.ts create mode 100644 src/types/qrcode.d.ts create mode 100644 src/types/table.d.ts create mode 100644 src/types/tableForm.d.ts create mode 100644 src/types/theme.d.ts create mode 100644 src/utils/Logger.ts create mode 100644 src/utils/auth.ts create mode 100644 src/utils/color.ts create mode 100644 src/utils/constants.ts create mode 100644 src/utils/dict.ts create mode 100644 src/utils/disposition/defaultButtons.ts create mode 100644 src/utils/disposition/formFields.ts create mode 100644 src/utils/disposition/tableColumns.ts create mode 100644 src/utils/disposition/tableDetailsColumns.ts create mode 100644 src/utils/disposition/tableSummaryColumns.ts create mode 100644 src/utils/disposition/tabsList.ts create mode 100644 src/utils/domUtils.ts create mode 100644 src/utils/download.ts create mode 100644 src/utils/filt.ts create mode 100644 src/utils/formCreate.ts create mode 100644 src/utils/formRules.ts create mode 100644 src/utils/formatTime.ts create mode 100644 src/utils/formatter.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/is.ts create mode 100644 src/utils/jsencrypt.ts create mode 100644 src/utils/permission.ts create mode 100644 src/utils/propTypes.ts create mode 100644 src/utils/routerHelper.ts create mode 100644 src/utils/tree.ts create mode 100644 src/utils/tsxHelper.ts create mode 100644 src/utils/validator.ts create mode 100644 src/views/Home/Index.vue create mode 100644 src/views/Home/Index2.vue create mode 100644 src/views/Home/echarts-data.ts create mode 100644 src/views/Home/types.ts create mode 100644 src/views/Login/Login.vue create mode 100644 src/views/Login/components/LoginForm.vue create mode 100644 src/views/Login/components/LoginFormTitle.vue create mode 100644 src/views/Login/components/MobileForm.vue create mode 100644 src/views/Login/components/QrCodeForm.vue create mode 100644 src/views/Login/components/RegisterForm.vue create mode 100644 src/views/Login/components/SSOLogin.vue create mode 100644 src/views/Login/components/index.ts create mode 100644 src/views/Login/components/useLogin.ts create mode 100644 src/views/Profile/Index.vue create mode 100644 src/views/Profile/components/BasicInfo.vue create mode 100644 src/views/Profile/components/ProfileUser.vue create mode 100644 src/views/Profile/components/ResetPwd.vue create mode 100644 src/views/Profile/components/UserAvatar.vue create mode 100644 src/views/Profile/components/UserSocial.vue create mode 100644 src/views/Profile/components/index.ts create mode 100644 src/views/Redirect/Redirect.vue create mode 100644 src/views/bpm/definition/index.vue create mode 100644 src/views/bpm/form/editor/index.vue create mode 100644 src/views/bpm/form/index.vue create mode 100644 src/views/bpm/group/UserGroupForm.vue create mode 100644 src/views/bpm/group/index.vue create mode 100644 src/views/bpm/model/ModelForm.vue create mode 100644 src/views/bpm/model/ModelImportForm.vue create mode 100644 src/views/bpm/model/editor/index.vue create mode 100644 src/views/bpm/model/index.vue create mode 100644 src/views/bpm/oa/leave/create.vue create mode 100644 src/views/bpm/oa/leave/detail.vue create mode 100644 src/views/bpm/oa/leave/index.vue create mode 100644 src/views/bpm/processInstance/create/index.vue create mode 100644 src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue create mode 100644 src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue create mode 100644 src/views/bpm/processInstance/detail/TaskReturnDialogForm.vue create mode 100644 src/views/bpm/processInstance/detail/TaskUpdateAssigneeForm.vue create mode 100644 src/views/bpm/processInstance/detail/index.vue create mode 100644 src/views/bpm/processInstance/index.vue create mode 100644 src/views/bpm/task/done/TaskDetail.vue create mode 100644 src/views/bpm/task/done/index.vue create mode 100644 src/views/bpm/task/todo/index.vue create mode 100644 src/views/bpm/taskAssignRule/TaskAssignRuleForm.vue create mode 100644 src/views/bpm/taskAssignRule/index.vue create mode 100644 src/views/error/403.vue create mode 100644 src/views/error/404.vue create mode 100644 src/views/error/500.vue create mode 100644 src/views/infra/apiAccessLog/ApiAccessLogDetail.vue create mode 100644 src/views/infra/apiAccessLog/index.vue create mode 100644 src/views/infra/apiErrorLog/ApiErrorLogDetail.vue create mode 100644 src/views/infra/apiErrorLog/index.vue create mode 100644 src/views/infra/build/index.vue create mode 100644 src/views/infra/codegen/PreviewCode.vue create mode 100644 src/views/infra/codegen/components/BasicInfoForm.vue create mode 100644 src/views/infra/codegen/components/ColumInfoForm.vue create mode 100644 src/views/infra/codegen/components/GenerateInfoForm.vue create mode 100644 src/views/infra/codegen/components/index.ts create mode 100644 src/views/infra/codegen/editTable.vue create mode 100644 src/views/infra/codegen/importTable.vue create mode 100644 src/views/infra/codegen/index.vue create mode 100644 src/views/infra/config/ConfigForm.vue create mode 100644 src/views/infra/config/index.vue create mode 100644 src/views/infra/customInterface/index.vue create mode 100644 src/views/infra/dataSourceConfig/DataSourceConfigForm.vue create mode 100644 src/views/infra/dataSourceConfig/index.vue create mode 100644 src/views/infra/dbDoc/index.vue create mode 100644 src/views/infra/druid/index.vue create mode 100644 src/views/infra/file/FileForm.vue create mode 100644 src/views/infra/file/index.vue create mode 100644 src/views/infra/fileConfig/FileConfigForm.vue create mode 100644 src/views/infra/fileConfig/index.vue create mode 100644 src/views/infra/job/JobDetail.vue create mode 100644 src/views/infra/job/JobForm.vue create mode 100644 src/views/infra/job/index.vue create mode 100644 src/views/infra/job/logger/JobLogDetail.vue create mode 100644 src/views/infra/job/logger/index.vue create mode 100644 src/views/infra/redis/index.vue create mode 100644 src/views/infra/server/index.vue create mode 100644 src/views/infra/skywalking/index.vue create mode 100644 src/views/infra/swagger/index.vue create mode 100644 src/views/infra/testDemo/index.vue create mode 100644 src/views/infra/webSocket/index.vue create mode 100644 src/views/report/goview/index.vue create mode 100644 src/views/report/jmreport/index.vue create mode 100644 src/views/system/area/AreaForm.vue create mode 100644 src/views/system/area/index.vue create mode 100644 src/views/system/dept/DeptForm.vue create mode 100644 src/views/system/dept/index.vue create mode 100644 src/views/system/dict/DictTypeForm.vue create mode 100644 src/views/system/dict/data/DictDataForm.vue create mode 100644 src/views/system/dict/data/index.vue create mode 100644 src/views/system/dict/index.vue create mode 100644 src/views/system/errorCode/ErrorCodeForm.vue create mode 100644 src/views/system/errorCode/index.vue create mode 100644 src/views/system/loginlog/LoginLogDetail.vue create mode 100644 src/views/system/loginlog/index.vue create mode 100644 src/views/system/mail/account/MailAccountDetail.vue create mode 100644 src/views/system/mail/account/MailAccountForm.vue create mode 100644 src/views/system/mail/account/account.data.ts create mode 100644 src/views/system/mail/account/index.vue create mode 100644 src/views/system/mail/log/MailLogDetail.vue create mode 100644 src/views/system/mail/log/index.vue create mode 100644 src/views/system/mail/log/log.data.ts create mode 100644 src/views/system/mail/template/MailTemplateForm.vue create mode 100644 src/views/system/mail/template/MailTemplateSendForm.vue create mode 100644 src/views/system/mail/template/index.vue create mode 100644 src/views/system/mail/template/template.data.ts create mode 100644 src/views/system/menu/MenuForm.vue create mode 100644 src/views/system/menu/index.vue create mode 100644 src/views/system/notice/NoticeForm.vue create mode 100644 src/views/system/notice/index.vue create mode 100644 src/views/system/notify/message/NotifyMessageDetail.vue create mode 100644 src/views/system/notify/message/index.vue create mode 100644 src/views/system/notify/my/MyNotifyMessageDetail.vue create mode 100644 src/views/system/notify/my/index.vue create mode 100644 src/views/system/notify/template/NotifyTemplateForm.vue create mode 100644 src/views/system/notify/template/NotifyTemplateSendForm.vue create mode 100644 src/views/system/notify/template/index.vue create mode 100644 src/views/system/oauth2/client/ClientForm.vue create mode 100644 src/views/system/oauth2/client/index.vue create mode 100644 src/views/system/oauth2/token/index.vue create mode 100644 src/views/system/operatelog/OperateLogDetail.vue create mode 100644 src/views/system/operatelog/index.vue create mode 100644 src/views/system/post/PostForm.vue create mode 100644 src/views/system/post/index.vue create mode 100644 src/views/system/role/RoleAssignMenuForm.vue create mode 100644 src/views/system/role/RoleDataPermissionForm.vue create mode 100644 src/views/system/role/RoleForm.vue create mode 100644 src/views/system/role/index.vue create mode 100644 src/views/system/sensitiveWord/SensitiveWordForm.vue create mode 100644 src/views/system/sensitiveWord/SensitiveWordTestForm.vue create mode 100644 src/views/system/sensitiveWord/index.vue create mode 100644 src/views/system/serialNumber/SerialNumberForm.vue create mode 100644 src/views/system/serialNumber/index.vue create mode 100644 src/views/system/sms/channel/SmsChannelForm.vue create mode 100644 src/views/system/sms/channel/index.vue create mode 100644 src/views/system/sms/log/SmsLogDetail.vue create mode 100644 src/views/system/sms/log/index.vue create mode 100644 src/views/system/sms/template/SmsTemplateForm.vue create mode 100644 src/views/system/sms/template/SmsTemplateSendForm.vue create mode 100644 src/views/system/sms/template/index.vue create mode 100644 src/views/system/tenant/TenantForm.vue create mode 100644 src/views/system/tenant/index.vue create mode 100644 src/views/system/tenantPackage/TenantPackageForm.vue create mode 100644 src/views/system/tenantPackage/index.vue create mode 100644 src/views/system/user/DeptTree.vue create mode 100644 src/views/system/user/UserAssignRoleForm.vue create mode 100644 src/views/system/user/UserForm.vue create mode 100644 src/views/system/user/UserImportForm.vue create mode 100644 src/views/system/user/index.vue create mode 100644 stylelint.config.js create mode 100644 tsconfig.json create mode 100644 types/components.d.ts create mode 100644 types/custom-types.d.ts create mode 100644 types/env.d.ts create mode 100644 types/global.d.ts create mode 100644 types/router.d.ts create mode 100644 uno.config.ts create mode 100644 vite.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..dccf841 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=2 +max_line_length = 100 + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/.env b/.env new file mode 100644 index 0000000..2308eb6 --- /dev/null +++ b/.env @@ -0,0 +1,17 @@ +# 标题 +VITE_APP_TITLE=闻荫管理系统 + +# 项目本地运行端口号 +VITE_PORT=80 + +# open 运行 npm run dev 时自动打开浏览器 +VITE_OPEN=true + +# 租户开关 +VITE_APP_TENANT_ENABLE=true + +# 验证码的开关 +VITE_APP_CAPTCHA_ENABLE=true + +# 百度统计 +VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..78976cd --- /dev/null +++ b/.env.development @@ -0,0 +1,37 @@ +# 开发环境 +NODE_ENV=development + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://localhost:12080' + +# 上传路径 +VITE_UPLOAD_URL='http://localhost:12080/admin-api/infra/file/upload' + +# 接口前缀 +VITE_API_BASEPATH=/dev-api + +# 接口地址 +VITE_API_URL=/admin-api + +# 打包路径 +VITE_BASE_PATH=/ + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=false + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 输出路径 +VITE_OUT_DIR=dist + +# 自定义接口路径 +VITE_INTERFACE_URL='http://localhost:12080/magic/web/index.html' + +# 积木报表请求路径 +VITE_JMREPORT_BASE_URL='http://localhost:12080' \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..8e25d23 --- /dev/null +++ b/.env.production @@ -0,0 +1,34 @@ +# 生产环境 +NODE_ENV=production + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://localhost:12080' + +# 上传路径 +VITE_UPLOAD_URL='http://localhost:12080/admin-api/infra/file/upload' + +# 接口前缀 +VITE_API_BASEPATH= + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH=/ + +# 输出路径 +VITE_OUT_DIR=dist-pro + +# 积木报表请求路径 +VITE_JMREPORT_BASE_URL='http://dev.ccwin-in.com:25110' diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..84edcdf --- /dev/null +++ b/.env.test @@ -0,0 +1,37 @@ +# 生产环境 +NODE_ENV=test + +VITE_DEV=false + +# 请求路径 +VITE_BASE_URL='http://dev.ccwin-in.com:25100/api' + +# 上传路径 +VITE_UPLOAD_URL='http://dev.ccwin-in.com:25100/api/admin-api/infra/file/upload' + +# 接口前缀 +VITE_API_BASEPATH= + +# 接口地址 +VITE_API_URL=/admin-api + +# 是否删除debugger +VITE_DROP_DEBUGGER=true + +# 是否删除console.log +VITE_DROP_CONSOLE=true + +# 是否sourcemap +VITE_SOURCEMAP=false + +# 打包路径 +VITE_BASE_PATH=/ + +# 输出路径 +VITE_OUT_DIR=dist-test + +# 自定义接口路径 +VITE_INTERFACE_URL='http://dev.ccwin-in.com:25110/magic/web/index.html' + +# 积木报表请求路径 +VITE_JMREPORT_BASE_URL='http://dev.ccwin-in.com:25110' diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1e85c0f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,8 @@ +/build/ +/config/ +/dist/ +/*.js +/test/unit/coverage/ +/node_modules/* +/dist* +/src/main.ts diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json new file mode 100644 index 0000000..024c96a --- /dev/null +++ b/.eslintrc-auto-import.json @@ -0,0 +1,259 @@ +{ + "globals": { + "EffectScope": true, + "ElMessage": true, + "ElMessageBox": true, + "ElTag": true, + "asyncComputed": true, + "autoResetRef": true, + "computed": true, + "computedAsync": true, + "computedEager": true, + "computedInject": true, + "computedWithControl": true, + "controlledComputed": true, + "controlledRef": true, + "createApp": true, + "createEventHook": true, + "createGlobalState": true, + "createInjectionState": true, + "createReactiveFn": true, + "createSharedComposable": true, + "createUnrefFn": true, + "customRef": true, + "debouncedRef": true, + "debouncedWatch": true, + "defineAsyncComponent": true, + "defineComponent": true, + "eagerComputed": true, + "effectScope": true, + "extendRef": true, + "getCurrentInstance": true, + "getCurrentScope": true, + "h": true, + "ignorableWatch": true, + "inject": true, + "isDefined": true, + "isProxy": true, + "isReactive": true, + "isReadonly": true, + "isRef": true, + "makeDestructurable": true, + "markRaw": true, + "nextTick": true, + "onActivated": true, + "onBeforeMount": true, + "onBeforeUnmount": true, + "onBeforeUpdate": true, + "onClickOutside": true, + "onDeactivated": true, + "onErrorCaptured": true, + "onKeyStroke": true, + "onLongPress": true, + "onMounted": true, + "onRenderTracked": true, + "onRenderTriggered": true, + "onScopeDispose": true, + "onServerPrefetch": true, + "onStartTyping": true, + "onUnmounted": true, + "onUpdated": true, + "pausableWatch": true, + "provide": true, + "reactify": true, + "reactifyObject": true, + "reactive": true, + "reactiveComputed": true, + "reactiveOmit": true, + "reactivePick": true, + "readonly": true, + "ref": true, + "refAutoReset": true, + "refDebounced": true, + "refDefault": true, + "refThrottled": true, + "refWithControl": true, + "resolveComponent": true, + "resolveRef": true, + "resolveUnref": true, + "shallowReactive": true, + "shallowReadonly": true, + "shallowRef": true, + "syncRef": true, + "syncRefs": true, + "templateRef": true, + "throttledRef": true, + "throttledWatch": true, + "toRaw": true, + "toReactive": true, + "toRef": true, + "toRefs": true, + "triggerRef": true, + "tryOnBeforeMount": true, + "tryOnBeforeUnmount": true, + "tryOnMounted": true, + "tryOnScopeDispose": true, + "tryOnUnmounted": true, + "unref": true, + "unrefElement": true, + "until": true, + "useActiveElement": true, + "useArrayEvery": true, + "useArrayFilter": true, + "useArrayFind": true, + "useArrayFindIndex": true, + "useArrayJoin": true, + "useArrayMap": true, + "useArrayReduce": true, + "useArraySome": true, + "useAsyncQueue": true, + "useAsyncState": true, + "useAttrs": true, + "useBase64": true, + "useBattery": true, + "useBluetooth": true, + "useBreakpoints": true, + "useBroadcastChannel": true, + "useBrowserLocation": true, + "useCached": true, + "useClipboard": true, + "useColorMode": true, + "useConfirmDialog": true, + "useCounter": true, + "useCssModule": true, + "useCssVar": true, + "useCssVars": true, + "useCurrentElement": true, + "useCycleList": true, + "useDark": true, + "useDateFormat": true, + "useDebounce": true, + "useDebounceFn": true, + "useDebouncedRefHistory": true, + "useDeviceMotion": true, + "useDeviceOrientation": true, + "useDevicePixelRatio": true, + "useDevicesList": true, + "useDisplayMedia": true, + "useDocumentVisibility": true, + "useDraggable": true, + "useDropZone": true, + "useElementBounding": true, + "useElementByPoint": true, + "useElementHover": true, + "useElementSize": true, + "useElementVisibility": true, + "useEventBus": true, + "useEventListener": true, + "useEventSource": true, + "useEyeDropper": true, + "useFavicon": true, + "useFetch": true, + "useFileDialog": true, + "useFileSystemAccess": true, + "useFocus": true, + "useFocusWithin": true, + "useFps": true, + "useFullscreen": true, + "useGamepad": true, + "useGeolocation": true, + "useIdle": true, + "useImage": true, + "useInfiniteScroll": true, + "useIntersectionObserver": true, + "useInterval": true, + "useIntervalFn": true, + "useKeyModifier": true, + "useLastChanged": true, + "useLocalStorage": true, + "useMagicKeys": true, + "useManualRefHistory": true, + "useMediaControls": true, + "useMediaQuery": true, + "useMemoize": true, + "useMemory": true, + "useMounted": true, + "useMouse": true, + "useMouseInElement": true, + "useMousePressed": true, + "useMutationObserver": true, + "useNavigatorLanguage": true, + "useNetwork": true, + "useNow": true, + "useObjectUrl": true, + "useOffsetPagination": true, + "useOnline": true, + "usePageLeave": true, + "useParallax": true, + "usePermission": true, + "usePointer": true, + "usePointerSwipe": true, + "usePreferredColorScheme": true, + "usePreferredDark": true, + "usePreferredLanguages": true, + "useRafFn": true, + "useRefHistory": true, + "useResizeObserver": true, + "useRoute": true, + "useRouter": true, + "useScreenOrientation": true, + "useScreenSafeArea": true, + "useScriptTag": true, + "useScroll": true, + "useScrollLock": true, + "useSessionStorage": true, + "useShare": true, + "useSlots": true, + "useSpeechRecognition": true, + "useSpeechSynthesis": true, + "useStepper": true, + "useStorage": true, + "useStorageAsync": true, + "useStyleTag": true, + "useSupported": true, + "useSwipe": true, + "useTemplateRefsList": true, + "useTextDirection": true, + "useTextSelection": true, + "useTextareaAutosize": true, + "useThrottle": true, + "useThrottleFn": true, + "useThrottledRefHistory": true, + "useTimeAgo": true, + "useTimeout": true, + "useTimeoutFn": true, + "useTimeoutPoll": true, + "useTimestamp": true, + "useTitle": true, + "useToggle": true, + "useTransition": true, + "useUrlSearchParams": true, + "useUserMedia": true, + "useVModel": true, + "useVModels": true, + "useVibrate": true, + "useVirtualList": true, + "useWakeLock": true, + "useWebNotification": true, + "useWebSocket": true, + "useWebWorker": true, + "useWebWorkerFn": true, + "useWindowFocus": true, + "useWindowScroll": true, + "useWindowSize": true, + "watch": true, + "watchArray": true, + "watchAtMost": true, + "watchDebounced": true, + "watchEffect": true, + "watchIgnorable": true, + "watchOnce": true, + "watchPausable": true, + "watchPostEffect": true, + "watchSyncEffect": true, + "watchThrottled": true, + "watchTriggerable": true, + "watchWithFilter": true, + "whenever": true + } +} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..3e4af63 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,72 @@ +// @ts-check +const { defineConfig } = require('eslint-define-config') +module.exports = defineConfig({ + root: true, + env: { + browser: true, + node: true, + es6: true + }, + parser: 'vue-eslint-parser', + plugins: ['vue'], + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true + } + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + // 'prettier', + // 'plugin:prettier/recommended', + '@unocss' + ], + rules: { + 'vue/script-setup-uses-vars': 'error', + 'vue/no-reserved-component-names': 'off', + 'vue/no-setup-props-destructure': 'off', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + 'vue/custom-event-name-casing': 'off', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': 'off', + 'no-unused-vars': 'off', + 'space-before-function-paren': 'off', + + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/require-explicit-emits': 'off', + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always' + }, + svg: 'always', + math: 'always' + } + ], + 'vue/multi-word-component-names': 'off', + 'vue/no-v-html': 'off' + } +}) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0f033cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local +/dist* +*-lock.* +pnpm-debug +auto-*.d.ts +.idea +.history diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..f68ea86 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +/node_modules/** +/dist/ +/dist* +/public/* +/docs/* +/vite.config.ts +/src/types/env.d.ts +/src/types/auto-components.d.ts +/src/types/auto-imports.d.ts +/docs/**/* +CHANGELOG diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..aa605b4 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,6 @@ +/dist/* +/public/* +public/* +/dist* +/src/types/env.d.ts +/docs/**/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9861118 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-present Archer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..36ce53a --- /dev/null +++ b/README.md @@ -0,0 +1,235 @@ +**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!** + +**「我喜欢写代码,乐此不疲」** +**「我喜欢做开源,以此为乐」** + +我 ?? 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。 + +如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。 + +## ?? 新手必读 + +* nodejs > 16.18.0 && pnpm > 8.6.0 (强制使用pnpm) +* 演示地址【Vue3 + element-plus】: +* 演示地址【Vue3 + vben(ant-design-vue)】: +* 演示地址【Vue2 + element-ui】: +* 启动文档: +* 视频教程: + +## ?? 平台简介 + +**闻荫**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。 + +* 采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) 实现 +* 改换 saas,自动引入等功能 +* 使用 Element Plus 免费开源的中后台模版,具备如下特性: + +![首页](public/home.png) + +* **最新技术栈**:使用 Vue3、Vite4 等前端前沿技术开发 +* **TypeScript**: 应用程序级 JavaScript 的语言 +* **主题**: 可配置的主题 +* **国际化**:内置完善的国际化方案 +* **权限**:内置完善的动态路由权限生成方案 +* **组件**:二次封装了多个常用的组件 +* **示例**:内置丰富的示例 + +## 技术栈 + +| 框架 | 说明 | 版本 | +|----------------------------------------------------------------------|------------------|--------| +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.3.4 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.4.9 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.3.14 | +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 5.2.2 | +| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.1.6 | +| [vueuse](https://vueuse.org/) | 常用工具集 | 10.4.1 | +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.4.1 | +| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.2.5 | +| [unocss](https://uno.antfu.me/) | 原子 css | 0.56.1 | +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.1.1 | +| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 | + +## 开发工具 + +推荐 VS Code 开发,配合插件如下: + +| 插件名 | 功能 | +|-------------------------------|--------------------------| +| TypeScript Vue Plugin (Volar) | 用于 TypeScript 的 Vue 插件 | +| Vue Language Features (Volar) | Vue3.0 语法支持 | +| unocss | unocss for vscode | +| Iconify IntelliSense | Iconify 预览和搜索 | +| i18n Ally | 国际化智能提示 | +| Stylelint | Css 格式化 | +| Prettier | 代码格式化 | +| ESLint | 脚本代码检查 | +| DotENV | env 文件高亮 | + +## 内置功能 + +系统内置多种多种业务功能,可以用于快速你的业务系统: + +* 系统功能 +* 基础设施 +* 工作流程 +* 支付系统 +* 会员中心 +* 数据报表 +* 商城系统 +* 微信公众号 + +### 系统功能 + +| | 功能 | 描述 | +|-----|-------|---------------------------------| +| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 | +| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 | +| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | +| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 | +| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | +| | 岗位管理 | 配置系统用户所属担任职务 | +| ?? | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 | +| ?? | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | +| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | +| ?? | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | +| ?? | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 | +| ?? | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 | +| ?? | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | +| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | +| ?? | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | +| | 通知公告 | 系统通知公告信息发布维护 | +| ?? | 敏感词 | 配置系统敏感词,支持标签分组 | +| ?? | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 | +| ?? | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 | + +### 工作流程 + +| | 功能 | 描述 | +|-----|-------|----------------------------------------| +| ?? | 流程模型 | 配置工作流的流程模型,支持文件导入与在线设计流程图,提供 7 种任务分配规则 | +| ?? | 流程表单 | 拖动表单元素生成相应的工作流表单,覆盖 Element UI 所有的表单组件 | +| ?? | 用户分组 | 自定义用户分组,可用于工作流的审批分组 | +| ?? | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 | +| ?? | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 | +| ?? | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 | +| ?? | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 | + +### 支付系统 + +| | 功能 | 描述 | +|-----|------|---------------------------| +| ?? | 商户信息 | 管理商户信息,支持 Saas 场景下的多商户功能 | +| ?? | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 | +| ?? | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 | +| ?? | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 | + +ps:核心功能已经实现,正在对接微信小程序中... + +### 基础设施 + +| | 功能 | 描述 | +|-----|----------|----------------------------------------------| +| ?? | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | +| ?? | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | +| ?? | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | +| ?? | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | +| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | +| ?? | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | +| ?? | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | +| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | +| ?? | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | +| ?? | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | +| ?? | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | +| ?? | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | +| ?? | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 | +| ?? | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 | +| ?? | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 | +| ?? | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | +| ?? | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | + +### 数据报表 + +| | 功能 | 描述 | +|-----|-------|--------------------| +| ?? | 报表设计器 | 支持数据报表、图形报表、打印设计等 | +| ?? | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 | + +### 微信公众号 + +| | 功能 | 描述 | +|-----|--------|-------------------------------| +| ?? | 账号管理 | 配置接入的微信公众号,可支持多个公众号 | +| ?? | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 | +| ?? | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 | +| ?? | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 | +| ?? | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 | +| ?? | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 | +| ?? | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 | +| ?? | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 | +| ?? | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 | +| ?? | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 | + +### 商城系统 + +建设中... + +![功能图](http://static.iocoder.cn/mall%20%E5%8A%9F%E8%83%BD%E5%9B%BE-min.png) + +![GIF 图-耐心等待](https://raw.githubusercontent.com/YunaiV/Blog/master/Mall/onemall-admin-min.gif) + +![GIF 图-耐心等待](https://raw.githubusercontent.com/YunaiV/Blog/master/Mall/onemall-h5-min.gif) + +## ?? 演示图 + +### 系统功能 + +| 模块 | biu | biu | biu | +|------------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------| +| 登录 & 首页 | ![登录](https://static.iocoder.cn/images/ruoyi-vue-pro/登录.jpg?imageView2/2/format/webp/w/1280) | ![首页](https://static.iocoder.cn/images/ruoyi-vue-pro/首页.jpg?imageView2/2/format/webp/w/1280) | ![个人中心](https://static.iocoder.cn/images/ruoyi-vue-pro/个人中心.jpg?imageView2/2/format/webp/w/1280) | +| 用户 & 应用 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg?imageView2/2/format/webp/w/1280) | ![令牌管理](https://static.iocoder.cn/images/ruoyi-vue-pro/令牌管理.jpg?imageView2/2/format/webp/w/1280) | ![应用管理](https://static.iocoder.cn/images/ruoyi-vue-pro/应用管理.jpg?imageView2/2/format/webp/w/1280) | +| 租户 & 套餐 | ![租户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/租户管理.jpg?imageView2/2/format/webp/w/1280) | ![租户套餐](https://static.iocoder.cn/images/ruoyi-vue-pro/租户套餐.png) | - | +| 部门 & 岗位 | ![部门管理](https://static.iocoder.cn/images/ruoyi-vue-pro/部门管理.jpg?imageView2/2/format/webp/w/1280) | ![岗位管理](https://static.iocoder.cn/images/ruoyi-vue-pro/岗位管理.jpg?imageView2/2/format/webp/w/1280) | - | +| 菜单 & 角色 | ![菜单管理](https://static.iocoder.cn/images/ruoyi-vue-pro/菜单管理.jpg?imageView2/2/format/webp/w/1280) | ![角色管理](https://static.iocoder.cn/images/ruoyi-vue-pro/角色管理.jpg?imageView2/2/format/webp/w/1280) | - | +| 审计日志 | ![操作日志](https://static.iocoder.cn/images/ruoyi-vue-pro/操作日志.jpg?imageView2/2/format/webp/w/1280) | ![登录日志](https://static.iocoder.cn/images/ruoyi-vue-pro/登录日志.jpg?imageView2/2/format/webp/w/1280) | - | +| 短信 | ![短信渠道](https://static.iocoder.cn/images/ruoyi-vue-pro/短信渠道.jpg?imageView2/2/format/webp/w/1280) | ![短信模板](https://static.iocoder.cn/images/ruoyi-vue-pro/短信模板.jpg?imageView2/2/format/webp/w/1280) | ![短信日志](https://static.iocoder.cn/images/ruoyi-vue-pro/短信日志.jpg?imageView2/2/format/webp/w/1280) | +| 字典 & 敏感词 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg?imageView2/2/format/webp/w/1280) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg?imageView2/2/format/webp/w/1280) | ![敏感词](https://static.iocoder.cn/images/ruoyi-vue-pro/敏感词.jpg?imageView2/2/format/webp/w/1280) | +| 错误码 & 通知 | ![错误码管理](https://static.iocoder.cn/images/ruoyi-vue-pro/错误码管理.jpg?imageView2/2/format/webp/w/1280) | ![通知公告](https://static.iocoder.cn/images/ruoyi-vue-pro/通知公告.jpg?imageView2/2/format/webp/w/1280) | - | + +### 工作流程 + +| 模块 | biu | biu | biu | +|---------|------------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------| +| 流程模型 | ![流程模型-列表](https://static.iocoder.cn/images/ruoyi-vue-pro/流程模型-列表.jpg?imageView2/2/format/webp/w/1280) | ![流程模型-设计](https://static.iocoder.cn/images/ruoyi-vue-pro/流程模型-设计.jpg?imageView2/2/format/webp/w/1280) | ![流程模型-定义](https://static.iocoder.cn/images/ruoyi-vue-pro/流程模型-定义.jpg?imageView2/2/format/webp/w/1280) | +| 表单 & 分组 | ![流程表单](https://static.iocoder.cn/images/ruoyi-vue-pro/流程表单.jpg?imageView2/2/format/webp/w/1280) | ![用户分组](https://static.iocoder.cn/images/ruoyi-vue-pro/用户分组.jpg?imageView2/2/format/webp/w/1280) | - | +| 我的流程 | ![我的流程-列表](https://static.iocoder.cn/images/ruoyi-vue-pro/我的流程-列表.jpg?imageView2/2/format/webp/w/1280) | ![我的流程-发起](https://static.iocoder.cn/images/ruoyi-vue-pro/我的流程-发起.jpg?imageView2/2/format/webp/w/1280) | ![我的流程-详情](https://static.iocoder.cn/images/ruoyi-vue-pro/我的流程-详情.jpg?imageView2/2/format/webp/w/1280) | +| 待办 & 已办 | ![任务列表-审批](https://static.iocoder.cn/images/ruoyi-vue-pro/任务列表-审批.jpg?imageView2/2/format/webp/w/1280) | ![任务列表-待办](https://static.iocoder.cn/images/ruoyi-vue-pro/任务列表-待办.jpg?imageView2/2/format/webp/w/1280) | ![任务列表-已办](https://static.iocoder.cn/images/ruoyi-vue-pro/任务列表-已办.jpg?imageView2/2/format/webp/w/1280) | +| OA 请假 | ![OA请假-列表](https://static.iocoder.cn/images/ruoyi-vue-pro/OA请假-列表.jpg?imageView2/2/format/webp/w/1280) | ![OA请假-发起](https://static.iocoder.cn/images/ruoyi-vue-pro/OA请假-发起.jpg?imageView2/2/format/webp/w/1280) | ![OA请假-详情](https://static.iocoder.cn/images/ruoyi-vue-pro/OA请假-详情.jpg?imageView2/2/format/webp/w/1280) | + +### 基础设施 + +| 模块 | biu | biu | biu | +|---------------|----------------------------------------------------------------------|--------------------------------------------------------------------|------------------------------------------------------------------| +| 代码生成 | ![代码生成](https://static.iocoder.cn/images/ruoyi-vue-pro/代码生成.jpg?imageView2/2/format/webp/w/1280) | ![生成效果](https://static.iocoder.cn/images/ruoyi-vue-pro/生成效果.jpg?imageView2/2/format/webp/w/1280) | - | +| 文档 | ![系统接口](https://static.iocoder.cn/images/ruoyi-vue-pro/系统接口.jpg?imageView2/2/format/webp/w/1280) | ![数据库文档](https://static.iocoder.cn/images/ruoyi-vue-pro/数据库文档.jpg?imageView2/2/format/webp/w/1280) | - | +| 文件 & 配置 | ![文件配置](https://static.iocoder.cn/images/ruoyi-vue-pro/文件配置.jpg?imageView2/2/format/webp/w/1280) | ![文件管理](https://static.iocoder.cn/images/ruoyi-vue-pro/文件管理2.jpg?imageView2/2/format/webp/w/1280) | ![配置管理](https://static.iocoder.cn/images/ruoyi-vue-pro/配置管理.jpg?imageView2/2/format/webp/w/1280) | +| 定时任务 | ![定时任务](https://static.iocoder.cn/images/ruoyi-vue-pro/定时任务.jpg?imageView2/2/format/webp/w/1280) | ![任务日志](https://static.iocoder.cn/images/ruoyi-vue-pro/任务日志.jpg?imageView2/2/format/webp/w/1280) | - | +| API 日志 | ![访问日志](https://static.iocoder.cn/images/ruoyi-vue-pro/访问日志.jpg?imageView2/2/format/webp/w/1280) | ![错误日志](https://static.iocoder.cn/images/ruoyi-vue-pro/错误日志.jpg?imageView2/2/format/webp/w/1280) | - | +| MySQL & Redis | ![MySQL](https://static.iocoder.cn/images/ruoyi-vue-pro/MySQL.jpg?imageView2/2/format/webp/w/1280) | ![Redis](https://static.iocoder.cn/images/ruoyi-vue-pro/Redis.jpg?imageView2/2/format/webp/w/1280) | - | +| 监控平台 | ![Java监控](https://static.iocoder.cn/images/ruoyi-vue-pro/Java监控.jpg?imageView2/2/format/webp/w/1280) | ![链路追踪](https://static.iocoder.cn/images/ruoyi-vue-pro/链路追踪.jpg?imageView2/2/format/webp/w/1280) | ![日志中心](https://static.iocoder.cn/images/ruoyi-vue-pro/日志中心.jpg?imageView2/2/format/webp/w/1280) | + +### 支付系统 + +| 模块 | biu | biu | biu | +|---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------| +| 商家 & 应用 | ![商户信息](https://static.iocoder.cn/images/ruoyi-vue-pro/商户信息.jpg?imageView2/2/format/webp/w/1280) | ![应用信息-列表](https://static.iocoder.cn/images/ruoyi-vue-pro/应用信息-列表.jpg?imageView2/2/format/webp/w/1280) | ![应用信息-编辑](https://static.iocoder.cn/images/ruoyi-vue-pro/应用信息-编辑.jpg?imageView2/2/format/webp/w/1280) | +| 支付 & 退款 | ![支付订单](https://static.iocoder.cn/images/ruoyi-vue-pro/支付订单.jpg?imageView2/2/format/webp/w/1280) | ![退款订单](https://static.iocoder.cn/images/ruoyi-vue-pro/退款订单.jpg?imageView2/2/format/webp/w/1280) | --- | + +### 数据报表 + +| 模块 | biu | biu | biu | +|-------|--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------| +| 报表设计器 | ![数据报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-数据报表.jpg?imageView2/2/format/webp/w/1280) | ![图形报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-图形报表.jpg?imageView2/2/format/webp/w/1280) | ![报表设计器-打印设计](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-打印设计.jpg?imageView2/2/format/webp/w/1280) | +| 大屏设计器 | ![大屏列表](https://static.iocoder.cn/images/ruoyi-vue-pro/大屏设计器-列表.jpg?imageView2/2/format/webp/w/1280) | ![大屏预览](https://static.iocoder.cn/images/ruoyi-vue-pro/大屏设计器-预览.jpg?imageView2/2/format/webp/w/1280) | ![大屏编辑](https://static.iocoder.cn/images/ruoyi-vue-pro/大屏设计器-编辑.jpg?imageView2/2/format/webp/w/1280) | diff --git a/build/vite/index.ts b/build/vite/index.ts new file mode 100644 index 0000000..0206710 --- /dev/null +++ b/build/vite/index.ts @@ -0,0 +1,107 @@ +import { resolve } from 'path' +import Vue from '@vitejs/plugin-vue' +import VueJsx from '@vitejs/plugin-vue-jsx' +import progress from 'vite-plugin-progress' +import EslintPlugin from 'vite-plugin-eslint' +import PurgeIcons from 'vite-plugin-purge-icons' +import { ViteEjsPlugin } from 'vite-plugin-ejs' +// @ts-ignore +import ElementPlus from 'unplugin-element-plus/vite' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import viteCompression from 'vite-plugin-compression' +import topLevelAwait from 'vite-plugin-top-level-await' +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import UnoCSS from 'unocss/vite' + +export function createVitePlugins() { + const root = process.cwd() + + // 路径查找 + function pathResolve(dir: string) { + return resolve(root, '.', dir) + } + + return [ + Vue(), + VueJsx(), + UnoCSS(), + progress(), + PurgeIcons(), + ElementPlus({}), + AutoImport({ + include: [ + /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx + /\.vue$/, + /\.vue\?vue/, // .vue + /\.md$/ // .md + ], + imports: [ + 'vue', + 'vue-router', + // 可额外添加需要 autoImport 的组件 + { + '@/hooks/web/useI18n': ['useI18n'], + '@/hooks/web/useMessage': ['useMessage'], + '@/hooks/web/useTable': ['useTable'], + '@/hooks/web/useCrudSchemas': ['useCrudSchemas'], + '@/utils/formRules': ['required'], + '@/utils/dict': ['DICT_TYPE'] + } + ], + dts: 'src/types/auto-imports.d.ts', + resolvers: [ElementPlusResolver()], + eslintrc: { + enabled: false, // Default `false` + filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json` + globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') + } + }), + Components({ + // 要搜索组件的目录的相对路径 + dirs: ['src/components'], + // 组件的有效文件扩展名 + extensions: ['vue', 'md'], + // 搜索子目录 + deep: true, + include: [/\.vue$/, /\.vue\?vue/], + // 生成自定义 `auto-components.d.ts` 全局声明 + dts: 'src/types/auto-components.d.ts', + // 自定义组件的解析器 + resolvers: [ElementPlusResolver()], + exclude: [/[\\/]node_modules[\\/]/] + }), + EslintPlugin({ + cache: false, + include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件 + }), + VueI18nPlugin({ + runtimeOnly: true, + compositionOnly: true, + include: [resolve(__dirname, 'src/locales/**')] + }), + createSvgIconsPlugin({ + iconDirs: [pathResolve('src/assets/svgs')], + symbolId: 'icon-[dir]-[name]', + svgoOptions: true + }), + viteCompression({ + verbose: true, // 是否在控制台输出压缩结果 + disable: false, // 是否禁用 + threshold: 10240, // 体积大于 threshold 才会被压缩,单位 b + algorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw'] + ext: '.gz', // 生成的压缩包后缀 + deleteOriginFile: false //压缩后是否删除源文件 + }), + ViteEjsPlugin(), + topLevelAwait({ + // https://juejin.cn/post/7152191742513512485 + // The export name of top-level await promise for each chunk module + promiseExportName: '__tla', + // The function to generate import names of top-level await promise in each chunk module + promiseImportName: (i) => `__tla_${i}` + }) + ] +} diff --git a/build/vite/optimize.ts b/build/vite/optimize.ts new file mode 100644 index 0000000..3dda50b --- /dev/null +++ b/build/vite/optimize.ts @@ -0,0 +1,112 @@ +const include = [ + 'qs', + 'url', + 'vue', + 'sass', + 'mitt', + 'axios', + 'pinia', + 'dayjs', + 'qrcode', + 'unocss', + 'vue-router', + 'vue-types', + 'vue-i18n', + 'crypto-js', + 'cropperjs', + 'lodash-es', + 'nprogress', + 'web-storage-cache', + '@iconify/iconify', + '@vueuse/core', + '@zxcvbn-ts/core', + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'echarts-wordcloud', + '@wangeditor/editor', + '@wangeditor/editor-for-vue', + 'element-plus', + 'element-plus/es', + 'element-plus/es/locale/lang/zh-cn', + 'element-plus/es/locale/lang/en', + 'element-plus/es/components/avatar/style/css', + 'element-plus/es/components/space/style/css', + 'element-plus/es/components/backtop/style/css', + 'element-plus/es/components/form/style/css', + 'element-plus/es/components/radio-group/style/css', + 'element-plus/es/components/radio/style/css', + 'element-plus/es/components/checkbox/style/css', + 'element-plus/es/components/checkbox-group/style/css', + 'element-plus/es/components/switch/style/css', + 'element-plus/es/components/time-picker/style/css', + 'element-plus/es/components/date-picker/style/css', + 'element-plus/es/components/descriptions/style/css', + 'element-plus/es/components/descriptions-item/style/css', + 'element-plus/es/components/link/style/css', + 'element-plus/es/components/tooltip/style/css', + 'element-plus/es/components/drawer/style/css', + 'element-plus/es/components/dialog/style/css', + 'element-plus/es/components/checkbox-button/style/css', + 'element-plus/es/components/option-group/style/css', + 'element-plus/es/components/radio-button/style/css', + 'element-plus/es/components/cascader/style/css', + 'element-plus/es/components/color-picker/style/css', + 'element-plus/es/components/input-number/style/css', + 'element-plus/es/components/rate/style/css', + 'element-plus/es/components/select-v2/style/css', + 'element-plus/es/components/tree-select/style/css', + 'element-plus/es/components/slider/style/css', + 'element-plus/es/components/time-select/style/css', + 'element-plus/es/components/autocomplete/style/css', + 'element-plus/es/components/image-viewer/style/css', + 'element-plus/es/components/upload/style/css', + 'element-plus/es/components/col/style/css', + 'element-plus/es/components/form-item/style/css', + 'element-plus/es/components/alert/style/css', + 'element-plus/es/components/breadcrumb/style/css', + 'element-plus/es/components/select/style/css', + 'element-plus/es/components/input/style/css', + 'element-plus/es/components/breadcrumb-item/style/css', + 'element-plus/es/components/tag/style/css', + 'element-plus/es/components/pagination/style/css', + 'element-plus/es/components/table/style/css', + 'element-plus/es/components/table-v2/style/css', + 'element-plus/es/components/table-column/style/css', + 'element-plus/es/components/card/style/css', + 'element-plus/es/components/row/style/css', + 'element-plus/es/components/button/style/css', + 'element-plus/es/components/menu/style/css', + 'element-plus/es/components/sub-menu/style/css', + 'element-plus/es/components/menu-item/style/css', + 'element-plus/es/components/option/style/css', + 'element-plus/es/components/dropdown/style/css', + 'element-plus/es/components/dropdown-menu/style/css', + 'element-plus/es/components/dropdown-item/style/css', + 'element-plus/es/components/skeleton/style/css', + 'element-plus/es/components/skeleton/style/css', + 'element-plus/es/components/backtop/style/css', + 'element-plus/es/components/menu/style/css', + 'element-plus/es/components/sub-menu/style/css', + 'element-plus/es/components/menu-item/style/css', + 'element-plus/es/components/dropdown/style/css', + 'element-plus/es/components/tree/style/css', + 'element-plus/es/components/dropdown-menu/style/css', + 'element-plus/es/components/dropdown-item/style/css', + 'element-plus/es/components/badge/style/css', + 'element-plus/es/components/breadcrumb/style/css', + 'element-plus/es/components/breadcrumb-item/style/css', + 'element-plus/es/components/image/style/css', + 'element-plus/es/components/collapse-transition/style/css', + 'element-plus/es/components/timeline/style/css', + 'element-plus/es/components/timeline-item/style/css', + 'element-plus/es/components/collapse/style/css', + 'element-plus/es/components/collapse-item/style/css', + 'element-plus/es/components/button-group/style/css', + 'element-plus/es/components/text/style/css' +] + +const exclude = ['@iconify/json'] + +export { include, exclude } diff --git a/index.html b/index.html new file mode 100644 index 0000000..2fe32f5 --- /dev/null +++ b/index.html @@ -0,0 +1,152 @@ + + + + + + + + + + + %VITE_APP_TITLE% + + +
+ +
+
+
+ +
%VITE_APP_TITLE%
+
+
+
+
+
+
+
+
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..62dc388 --- /dev/null +++ b/package.json @@ -0,0 +1,133 @@ +{ + "name": "yudao-ui-admin-vue3", + "version": "1.8.2-snapshot", + "description": "基于vue3、vite4、element-plus、typesScript", + "author": "xingyu", + "private": false, + "scripts": { + "dev": "vite", + "test": "vite build --mode test", + "prod": "vite build --mode production", + "preview": "vite preview", + "lint": "eslint --fix --ext .js,.vue src" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.1.0", + "@form-create/designer": "^3.1.3", + "@form-create/element-ui": "^3.1.24", + "@iconify/iconify": "^3.1.1", + "@videojs-player/vue": "^1.0.0", + "@vueuse/core": "^10.4.1", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.10", + "@zxcvbn-ts/core": "^3.0.4", + "animate.css": "^4.1.1", + "axios": "^1.5.0", + "benz-amr-recorder": "^1.1.5", + "bpmn-js-token-simulation": "^0.10.0", + "camunda-bpmn-moddle": "^7.0.1", + "cropperjs": "^1.6.1", + "crypto-js": "^4.1.1", + "dayjs": "^1.11.10", + "diagram-js": "^12.3.0", + "echarts": "^5.4.3", + "echarts-wordcloud": "^2.1.0", + "element-plus": "2.3.14", + "fast-xml-parser": "^4.3.0", + "highlight.js": "^11.8.0", + "intro.js": "^7.2.0", + "jsencrypt": "^3.3.2", + "lodash-es": "^4.17.21", + "min-dash": "^4.1.1", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "pinia": "^2.1.6", + "qrcode": "^1.5.3", + "qs": "^6.11.2", + "sortablejs": "^1.15.0", + "steady-xml": "^0.1.0", + "url": "^0.11.3", + "video.js": "^7.21.5", + "vue": "^3.3.4", + "vue-dompurify-html": "^4.1.4", + "vue-i18n": "^9.4.1", + "vue-router": "^4.2.5", + "vue-types": "^5.1.1", + "vuedraggable": "^4.1.0", + "web-storage-cache": "^1.1.1", + "xml-js": "^1.6.11" + }, + "devDependencies": { + "@commitlint/cli": "^17.7.1", + "@commitlint/config-conventional": "^17.7.0", + "@iconify/json": "^2.2.119", + "@intlify/unplugin-vue-i18n": "^1.2.0", + "@purge-icons/generated": "^0.9.0", + "@types/intro.js": "^5.1.1", + "@types/lodash-es": "^4.17.9", + "@types/node": "^20.6.0", + "@types/nprogress": "^0.2.0", + "@types/qrcode": "^1.5.2", + "@types/qs": "^6.9.8", + "@typescript-eslint/eslint-plugin": "^6.7.2", + "@typescript-eslint/parser": "^6.7.2", + "@unocss/eslint-config": "^0.56.1", + "@unocss/transformer-variant-group": "^0.56.1", + "@vitejs/plugin-legacy": "^4.1.1", + "@vitejs/plugin-vue": "^4.3.4", + "@vitejs/plugin-vue-jsx": "^3.0.2", + "@vue-macros/volar": "^0.14.3", + "autoprefixer": "^10.4.16", + "bpmn-js": "8.9.0", + "bpmn-js-properties-panel": "0.46.0", + "consola": "^3.2.3", + "eslint": "^8.49.0", + "eslint-config-prettier": "^9.0.0", + "eslint-define-config": "^1.23.0", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-vue": "^9.17.0", + "lint-staged": "^14.0.1", + "postcss": "^8.4.30", + "postcss-html": "^1.5.0", + "postcss-scss": "^4.0.8", + "prettier": "^3.0.3", + "rimraf": "^5.0.1", + "rollup": "^3.29.2", + "sass": "^1.68.0", + "stylelint": "^15.10.3", + "stylelint-config-html": "^1.1.0", + "stylelint-config-recommended": "^13.0.0", + "stylelint-config-standard": "^34.0.0", + "stylelint-order": "^6.0.3", + "terser": "^5.20.0", + "typescript": "5.2.2", + "unocss": "^0.56.1", + "unplugin-auto-import": "^0.16.6", + "unplugin-element-plus": "^0.8.0", + "unplugin-vue-components": "^0.25.2", + "vite": "4.4.9", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-ejs": "^1.6.4", + "vite-plugin-eslint": "^1.8.1", + "vite-plugin-progress": "^0.0.7", + "vite-plugin-purge-icons": "^0.9.2", + "vite-plugin-svg-icons": "^2.0.1", + "vite-plugin-top-level-await": "^1.3.1", + "vue-eslint-parser": "^9.3.1", + "vue-tsc": "^1.8.13" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://gitee.com/yudaocode/yudao-ui-admin-vue3" + }, + "bugs": { + "url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues" + }, + "homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3", + "packageManager": "pnpm@8.6.0", + "engines": { + "node": ">= 16.0.0", + "pnpm": ">=8.6.0" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..961986e --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {} + } +} diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..b014bbf --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,22 @@ +module.exports = { + printWidth: 100, // 每行代码长度(默认80) + tabWidth: 2, // 每个tab相当于多少个空格(默认2)ab进行缩进(默认false) + useTabs: false, // 是否使用tab + semi: false, // 声明结尾使用分号(默认true) + vueIndentScriptAndStyle: false, + singleQuote: true, // 使用单引号(默认false) + quoteProps: 'as-needed', + bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true) + trailingComma: 'none', // 多行使用拖尾逗号(默认none) + jsxSingleQuote: false, + // 箭头函数参数括号 默认avoid 可选 avoid| always + // avoid 能省略括号的时候就省略 例如x => x + // always 总是有括号 + arrowParens: 'always', + insertPragma: false, + requirePragma: false, + proseWrap: 'never', + htmlWhitespaceSensitivity: 'strict', + endOfLine: 'auto', + rangeStart: 0 +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5a7de08267811feb034bb0c54ab38ca417731aab GIT binary patch literal 4286 zcmcJTdr*|u8OGm?f3Tad7j|KHxq~xpVq;A@HfgF7QY~O)Go9%q6O&2POq*#slbPnf zwzf$$rcG^ZYDE+@N@~3q7I49+L1DRyKt#F7{U!nn%U;+^j39aYobU7VmKqZ!%ltTJ zSayHU`<%1G3`F1^k7e(&;Z`VJu(?k;=T7X%N)jqMq!dMyZeDC3iF!z6rw+67kxV&jDKh*=XMMH7BzC%0ZZgW^F*GR;m`LJ8Nxh;MnV_2 zo#Aeu7~L8}V>!_RD+rBki)NV^cA^7!L1e&FY)JDI!(TGDXW-mnR@`bh?a0EnGI=P9 zy>>$Z2m|CjGIt$Z+!8}0*)asCbu>FBggr}a!3yv^PwX`@<_>sE4e5ZqN9V>rmTRUF zbU(T+S`C+7@m92s-#UA`Fo4_`PSqdlNi_8Le1D!YO<=@vm4O z$%$c4iIKfW(ZR8ZbU?mO?%glC2lvBQG7OL4g2E>3CE|D(x!lD@#>|2OxWk0scT#t^ zS6+JEa8?X~2srB%*M&`SJoL{S_(0yf@}t;S27g&Z0Hpg)z+Z89e{|ZcvsAWtlnyU! zrooK~1ov;@oE;J_FsSek>;)U+*tyTdzLW6F6!^;ZVSuI_-@Jq7m6vJu4@{*G56tUW zpGZTSVx!<}kX-N$2;dyp7%$QPemsxlS=d(&zn~%_Fjb*XpK`!o{mnXPeP))mj8zZ^lWb$NF4{~3AH+q%ce-ErK%W3!iN7WAAnu?S-NPqStq)-K z^r;$jQ1|uDpfTeToz0w~uIE_Ym=?0w^$yVAEIfqUV+#(N3e zk2~QhGcbJDsny&3bvhLwfBl_1IF%8kGpjCBvvt~9zrr8d9#JR!m$M(Jd}05>Eb4nd zJ`&DTz3>To1b>z3MIY{C28N5L>h#j;Kcx$R41YcR4PV_s^-rhhbVi8kGeYX7r!U!S zQoWp`s}X+Qa=*iY4)hJLtt9w=1?Lsv?f#1(Q9@*K9WgR|GWA#mr*$@egH|Q{flqJW zfn&Lc>e2!ND{_P?Q{22wTP^vKVHzF$V&C_+Q16C#BfNFp?VUHBP>oj2B zhz=UjK_mQU{=dKMNf%Wv_mX3|SB)O*b?E`FSmwIXFFL5s)z(Cu`t>S;|CO%wi8Gz> zcD{3+@uDaWG)hk4Wq*?l=C;AD68_*>&6hq4$5NbB{u8&riVPuS;Bxqt{>2%98FcW< z-UZpz{a%6r-kQ#JN!+2ZHi^e>j@Xfb z(FH3R_9nI5>KFImbdI(Z5j@?YYO33 z34gFFoDTl5j|!g{5?GNTRI+4*l?*4In&hHK`i1Yt`Ne(~9lZ9R?`G5acM|n*SGN8s znFXUbf8oK55?7tV%W!hALlXom0foB5=@9%tUGVsTz3@jvj0}t(u4OpB%*i{yd6`D*|GZP1pkYzYvxb4teMYa#Zj_Lo>g|rUJiD`FX%!C-Qg-g2Nw4TGLa#a|M&na z8A`8a_#|~g>R_v;>eddvKnJhy{!TWvy`7|kyQ1Zf^VxYMQp~8#D(_{d@N%#l^n?dP zJ>eOEc0bbbz}_Ep9p1mVhmnEN1LG{D9z=$tSMNjqf-V*rZoG@=pcx%l%Ab3d&aIih z8eE{+mp&i+1G+xk}WiODJh<6N)JDmfKzAKZd|2|w0ncYeRMI&V=sBLj;JI14`X znA}4Vday6K$fZk1`Dluh#aSF*>g2+Oy}Ud24Cm@=8E1fdP!-j*CXKqY;$HSP>1S?o zig|DLDt@t+^XG}oKAp^97_-1JPiEbH%mN~Xwb-w{LX;}_oG4M?Bhm>5iNXX9qIrUK L_}7DgzT)vecywrn literal 0 HcmV?d00001 diff --git a/public/home.png b/public/home.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd41455a9ef128c5798691a1d74b472c6d6344a GIT binary patch literal 74352 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�BJed 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 z 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 literal 0 HcmV?d00001 diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..c0d50c3 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/api/bpm/activity/index.ts b/src/api/bpm/activity/index.ts new file mode 100644 index 0000000..870d0d6 --- /dev/null +++ b/src/api/bpm/activity/index.ts @@ -0,0 +1,8 @@ +import request from '@/config/axios' + +export const getActivityList = async (params) => { + return await request.get({ + url: '/bpm/activity/list', + params + }) +} diff --git a/src/api/bpm/definition/index.ts b/src/api/bpm/definition/index.ts new file mode 100644 index 0000000..c0e51fa --- /dev/null +++ b/src/api/bpm/definition/index.ts @@ -0,0 +1,21 @@ +import request from '@/config/axios' + +export const getProcessDefinitionBpmnXML = async (id: number) => { + return await request.get({ + url: '/bpm/process-definition/get-bpmn-xml?id=' + id + }) +} + +export const getProcessDefinitionPage = async (params) => { + return await request.get({ + url: '/bpm/process-definition/page', + params + }) +} + +export const getProcessDefinitionList = async (params) => { + return await request.get({ + url: '/bpm/process-definition/list', + params + }) +} diff --git a/src/api/bpm/form/index.ts b/src/api/bpm/form/index.ts new file mode 100644 index 0000000..142ed24 --- /dev/null +++ b/src/api/bpm/form/index.ts @@ -0,0 +1,56 @@ +import request from '@/config/axios' + +export type FormVO = { + id: number + name: string + conf: string + fields: string[] + status: number + remark: string + createTime: string +} + +// 创建工作流的表单定义 +export const createForm = async (data: FormVO) => { + return await request.post({ + url: '/bpm/form/create', + data: data + }) +} + +// 更新工作流的表单定义 +export const updateForm = async (data: FormVO) => { + return await request.put({ + url: '/bpm/form/update', + data: data + }) +} + +// 删除工作流的表单定义 +export const deleteForm = async (id: number) => { + return await request.delete({ + url: '/bpm/form/delete?id=' + id + }) +} + +// 获得工作流的表单定义 +export const getForm = async (id: number) => { + return await request.get({ + url: '/bpm/form/get?id=' + id + }) +} + +// 获得工作流的表单定义分页 +export const getFormPage = async (params) => { + return await request.get({ + url: '/bpm/form/page', + params + }) +} + +// 获得动态表单的精简列表 +export const getSimpleFormList = async () => { + return await request.get({ + url: '/bpm/form/list-all-simple' + }) +} diff --git a/src/api/bpm/leave/index.ts b/src/api/bpm/leave/index.ts new file mode 100644 index 0000000..d4fe8d5 --- /dev/null +++ b/src/api/bpm/leave/index.ts @@ -0,0 +1,27 @@ +import request from '@/config/axios' + +export type LeaveVO = { + id: number + result: number + type: number + reason: string + processInstanceId: string + startTime: string + endTime: string + createTime: string +} + +// 创建请假申请 +export const createLeave = async (data: LeaveVO) => { + return await request.post({ url: '/bpm/oa/leave/create', data: data }) +} + +// 获得请假申请 +export const getLeave = async (id: number) => { + return await request.get({ url: '/bpm/oa/leave/get?id=' + id }) +} + +// 获得请假申请分页 +export const getLeavePage = async (params: PageParam) => { + return await request.get({ url: '/bpm/oa/leave/page', params }) +} diff --git a/src/api/bpm/model/index.ts b/src/api/bpm/model/index.ts new file mode 100644 index 0000000..2e1d4e6 --- /dev/null +++ b/src/api/bpm/model/index.ts @@ -0,0 +1,59 @@ +import request from '@/config/axios' + +export type ProcessDefinitionVO = { + id: string + version: number + deploymentTIme: string + suspensionState: number +} + +export type ModelVO = { + id: number + formName: string + key: string + name: string + description: string + category: string + formType: number + formId: number + formCustomCreatePath: string + formCustomViewPath: string + processDefinition: ProcessDefinitionVO + status: number + remark: string + createTime: string + bpmnXml: string +} + +export const getModelPage = async (params) => { + return await request.get({ url: '/bpm/model/page', params }) +} + +export const getModel = async (id: number) => { + return await request.get({ url: '/bpm/model/get?id=' + id }) +} + +export const updateModel = async (data: ModelVO) => { + return await request.put({ url: '/bpm/model/update', data: data }) +} + +// 任务状态修改 +export const updateModelState = async (id: number, state: number) => { + const data = { + id: id, + state: state + } + return await request.put({ url: '/bpm/model/update-state', data: data }) +} + +export const createModel = async (data: ModelVO) => { + return await request.post({ url: '/bpm/model/create', data: data }) +} + +export const deleteModel = async (id: number) => { + return await request.delete({ url: '/bpm/model/delete?id=' + id }) +} + +export const deployModel = async (id: number) => { + return await request.post({ url: '/bpm/model/deploy?id=' + id }) +} diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts new file mode 100644 index 0000000..10cd3bc --- /dev/null +++ b/src/api/bpm/processInstance/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +export type Task = { + id: string + name: string +} + +export type ProcessInstanceVO = { + id: number + name: string + processDefinitionId: string + category: string + result: number + tasks: Task[] + fields: string[] + status: number + remark: string + businessKey: string + createTime: string + endTime: string +} + +export const getMyProcessInstancePage = async (params) => { + return await request.get({ url: '/bpm/process-instance/my-page', params }) +} + +export const createProcessInstance = async (data) => { + return await request.post({ url: '/bpm/process-instance/create', data: data }) +} + +export const cancelProcessInstance = async (id: number, reason: string) => { + const data = { + id: id, + reason: reason + } + return await request.delete({ url: '/bpm/process-instance/cancel', data: data }) +} + +export const getProcessInstance = async (id: number) => { + return await request.get({ url: '/bpm/process-instance/get?id=' + id }) +} diff --git a/src/api/bpm/task/index.ts b/src/api/bpm/task/index.ts new file mode 100644 index 0000000..e6478d3 --- /dev/null +++ b/src/api/bpm/task/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +export type TaskVO = { + id: number +} + +export const getTodoTaskPage = async (params) => { + return await request.get({ url: '/bpm/task/todo-page', params }) +} + +export const getDoneTaskPage = async (params) => { + return await request.get({ url: '/bpm/task/done-page', params }) +} + +export const completeTask = async (data) => { + return await request.put({ url: '/bpm/task/complete', data }) +} + +export const approveTask = async (data) => { + return await request.put({ url: '/bpm/task/approve', data }) +} + +export const rejectTask = async (data) => { + return await request.put({ url: '/bpm/task/reject', data }) +} +export const backTask = async (data) => { + return await request.put({ url: '/bpm/task/back', data }) +} + +export const updateTaskAssignee = async (data) => { + return await request.put({ url: '/bpm/task/update-assignee', data }) +} + +export const getTaskListByProcessInstanceId = async (processInstanceId) => { + return await request.get({ + url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId + }) +} + +// 导出任务 +export const exportTask = async (params) => { + return await request.download({ url: '/bpm/task/export', params }) +} + +// 获取所有可回退的节点 +export const getReturnList = async (params) => { + return await request.get({ url: '/bpm/task/get-return-list', params }) +} + +// 回退 +export const returnTask = async (data) => { + return await request.put({ url: '/bpm/task/return', data }) +} diff --git a/src/api/bpm/taskAssignRule/index.ts b/src/api/bpm/taskAssignRule/index.ts new file mode 100644 index 0000000..5fbe342 --- /dev/null +++ b/src/api/bpm/taskAssignRule/index.ts @@ -0,0 +1,29 @@ +import request from '@/config/axios' + +export type TaskAssignVO = { + id: number + modelId: string + processDefinitionId: string + taskDefinitionKey: string + taskDefinitionName: string + options: string[] + type: number +} + +export const getTaskAssignRuleList = async (params) => { + return await request.get({ url: '/bpm/task-assign-rule/list', params }) +} + +export const createTaskAssignRule = async (data: TaskAssignVO) => { + return await request.post({ + url: '/bpm/task-assign-rule/create', + data: data + }) +} + +export const updateTaskAssignRule = async (data: TaskAssignVO) => { + return await request.put({ + url: '/bpm/task-assign-rule/update', + data: data + }) +} diff --git a/src/api/bpm/userGroup/index.ts b/src/api/bpm/userGroup/index.ts new file mode 100644 index 0000000..035762b --- /dev/null +++ b/src/api/bpm/userGroup/index.ts @@ -0,0 +1,47 @@ +import request from '@/config/axios' + +export type UserGroupVO = { + id: number + name: string + description: string + memberUserIds: number[] + status: number + remark: string + createTime: string +} + +// 创建用户组 +export const createUserGroup = async (data: UserGroupVO) => { + return await request.post({ + url: '/bpm/user-group/create', + data: data + }) +} + +// 更新用户组 +export const updateUserGroup = async (data: UserGroupVO) => { + return await request.put({ + url: '/bpm/user-group/update', + data: data + }) +} + +// 删除用户组 +export const deleteUserGroup = async (id: number) => { + return await request.delete({ url: '/bpm/user-group/delete?id=' + id }) +} + +// 获得用户组 +export const getUserGroup = async (id: number) => { + return await request.get({ url: '/bpm/user-group/get?id=' + id }) +} + +// 获得用户组分页 +export const getUserGroupPage = async (params) => { + return await request.get({ url: '/bpm/user-group/page', params }) +} + +// 获取用户组精简信息列表 +export const getSimpleUserGroupList = async (): Promise => { + return await request.get({ url: '/bpm/user-group/list-all-simple' }) +} diff --git a/src/api/infra/apiAccessLog/index.ts b/src/api/infra/apiAccessLog/index.ts new file mode 100644 index 0000000..c6b4b45 --- /dev/null +++ b/src/api/infra/apiAccessLog/index.ts @@ -0,0 +1,30 @@ +import request from '@/config/axios' + +export interface ApiAccessLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + requestUrl: string + userIp: string + userAgent: string + beginTime: Date + endTIme: Date + duration: number + resultCode: number + resultMsg: string + createTime: Date +} + +// 查询列表API 访问日志 +export const getApiAccessLogPage = (params: PageParam) => { + return request.get({ url: '/infra/api-access-log/page', params }) +} + +// 导出API 访问日志 +export const exportApiAccessLog = (params) => { + return request.download({ url: '/infra/api-access-log/export-excel', params }) +} diff --git a/src/api/infra/apiErrorLog/index.ts b/src/api/infra/apiErrorLog/index.ts new file mode 100644 index 0000000..59ee214 --- /dev/null +++ b/src/api/infra/apiErrorLog/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +export interface ApiErrorLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + requestUrl: string + userIp: string + userAgent: string + exceptionTime: Date + exceptionName: string + exceptionMessage: string + exceptionRootCauseMessage: string + exceptionStackTrace: string + exceptionClassName: string + exceptionFileName: string + exceptionMethodName: string + exceptionLineNumber: number + processUserId: number + processStatus: number + processTime: Date + resultCode: number + createTime: Date +} + +// 查询列表API 访问日志 +export const getApiErrorLogPage = (params: PageParam) => { + return request.get({ url: '/infra/api-error-log/page', params }) +} + +// 更新 API 错误日志的处理状态 +export const updateApiErrorLogPage = (id: number, processStatus: number) => { + return request.put({ + url: '/infra/api-error-log/update-status?id=' + id + '&processStatus=' + processStatus + }) +} + +// 导出API 访问日志 +export const exportApiErrorLog = (params) => { + return request.download({ + url: '/infra/api-error-log/export-excel', + params + }) +} diff --git a/src/api/infra/codegen/index.ts b/src/api/infra/codegen/index.ts new file mode 100644 index 0000000..64701ef --- /dev/null +++ b/src/api/infra/codegen/index.ts @@ -0,0 +1,123 @@ +import request from '@/config/axios' + +export type CodegenTableVO = { + id: number + tableId: number + isParentMenuIdValid: boolean + dataSourceConfigId: number + scene: number + tableName: string + tableComment: string + remark: string + moduleName: string + businessName: string + className: string + classComment: string + author: string + createTime: Date + updateTime: Date + templateType: number + parentMenuId: number +} + +export type CodegenColumnVO = { + id: number + tableId: number + columnName: string + dataType: string + columnComment: string + nullable: number + primaryKey: number + autoIncrement: string + ordinalPosition: number + javaType: string + javaField: string + dictType: string + example: string + createOperation: number + updateOperation: number + listOperation: number + listOperationCondition: string + listOperationResult: number + htmlType: string +} + +export type DatabaseTableVO = { + name: string + comment: string +} + +export type CodegenDetailVO = { + table: CodegenTableVO + columns: CodegenColumnVO[] +} + +export type CodegenPreviewVO = { + filePath: string + code: string +} + +export type CodegenUpdateReqVO = { + table: CodegenTableVO | any + columns: CodegenColumnVO[] +} + +export type CodegenCreateListReqVO = { + dataSourceConfigId: number + tableNames: string[] +} + +// 查询列表代码生成表定义 +export const getCodegenTablePage = (params: PageParam) => { + return request.get({ url: '/infra/codegen/table/page', params }) +} + +// 查询详情代码生成表定义 +export const getCodegenTable = (id: number) => { + return request.get({ url: '/infra/codegen/detail?tableId=' + id }) +} + +// 新增代码生成表定义 +export const createCodegenTable = (data: CodegenCreateListReqVO) => { + return request.post({ url: '/infra/codegen/create', data }) +} + +// 修改代码生成表定义 +export const updateCodegenTable = (data: CodegenUpdateReqVO) => { + return request.put({ url: '/infra/codegen/update', data }) +} + +// 基于数据库的表结构,同步数据库的表和字段定义 +export const syncCodegenFromDB = (id: number) => { + return request.put({ url: '/infra/codegen/sync-from-db?tableId=' + id }) +} + +// 基于 SQL 建表语句,同步数据库的表和字段定义 +export const syncCodegenFromSQL = (id: number, sql: string) => { + return request.put({ url: '/infra/codegen/sync-from-sql?tableId=' + id + '&sql=' + sql }) +} + +// 预览生成代码 +export const previewCodegen = (id: number) => { + return request.get({ url: '/infra/codegen/preview?tableId=' + id }) +} + +// 下载生成代码 +export const downloadCodegen = (id: number) => { + return request.download({ url: '/infra/codegen/download?tableId=' + id }) +} + +// 获得表定义 +export const getSchemaTableList = (params) => { + return request.get({ url: '/infra/codegen/db/table/list', params }) +} + +// 基于数据库的表结构,创建代码生成器的表定义 +export const createCodegenList = (data) => { + return request.post({ url: '/infra/codegen/create-list', data }) +} + +// 删除代码生成表定义 +export const deleteCodegenTable = (id: number) => { + return request.delete({ url: '/infra/codegen/delete?tableId=' + id }) +} diff --git a/src/api/infra/config/index.ts b/src/api/infra/config/index.ts new file mode 100644 index 0000000..5ef59f3 --- /dev/null +++ b/src/api/infra/config/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' + +export interface ConfigVO { + id: number | undefined + category: string + name: string + key: string + value: string + type: number + visible: boolean + remark: string + createTime: Date +} + +// 查询参数列表 +export const getConfigPage = (params: PageParam) => { + return request.get({ url: '/infra/config/page', params }) +} + +// 查询参数详情 +export const getConfig = (id: number) => { + return request.get({ url: '/infra/config/get?id=' + id }) +} + +// 根据参数键名查询参数值 +export const getConfigKey = (configKey: string) => { + return request.get({ url: '/infra/config/get-value-by-key?key=' + configKey }) +} + +// 新增参数 +export const createConfig = (data: ConfigVO) => { + return request.post({ url: '/infra/config/create', data }) +} + +// 修改参数 +export const updateConfig = (data: ConfigVO) => { + return request.put({ url: '/infra/config/update', data }) +} + +// 删除参数 +export const deleteConfig = (id: number) => { + return request.delete({ url: '/infra/config/delete?id=' + id }) +} + +// 导出参数 +export const exportConfig = (params) => { + return request.download({ url: '/infra/config/export', params }) +} diff --git a/src/api/infra/dataSourceConfig/index.ts b/src/api/infra/dataSourceConfig/index.ts new file mode 100644 index 0000000..b413f34 --- /dev/null +++ b/src/api/infra/dataSourceConfig/index.ts @@ -0,0 +1,35 @@ +import request from '@/config/axios' + +export interface DataSourceConfigVO { + id: number | undefined + name: string + url: string + username: string + password: string + createTime?: Date +} + +// 新增数据源配置 +export const createDataSourceConfig = (data: DataSourceConfigVO) => { + return request.post({ url: '/infra/data-source-config/create', data }) +} + +// 修改数据源配置 +export const updateDataSourceConfig = (data: DataSourceConfigVO) => { + return request.put({ url: '/infra/data-source-config/update', data }) +} + +// 删除数据源配置 +export const deleteDataSourceConfig = (id: number) => { + return request.delete({ url: '/infra/data-source-config/delete?id=' + id }) +} + +// 查询数据源配置详情 +export const getDataSourceConfig = (id: number) => { + return request.get({ url: '/infra/data-source-config/get?id=' + id }) +} + +// 查询数据源配置列表 +export const getDataSourceConfigList = () => { + return request.get({ url: '/infra/data-source-config/list' }) +} diff --git a/src/api/infra/dbDoc/index.ts b/src/api/infra/dbDoc/index.ts new file mode 100644 index 0000000..1a1a36b --- /dev/null +++ b/src/api/infra/dbDoc/index.ts @@ -0,0 +1,16 @@ +import request from '@/config/axios' + +// 导出Html +export const exportHtml = () => { + return request.download({ url: '/infra/db-doc/export-html' }) +} + +// 导出Word +export const exportWord = () => { + return request.download({ url: '/infra/db-doc/export-word' }) +} + +// 导出Markdown +export const exportMarkdown = () => { + return request.download({ url: '/infra/db-doc/export-markdown' }) +} diff --git a/src/api/infra/file/index.ts b/src/api/infra/file/index.ts new file mode 100644 index 0000000..f64bc0d --- /dev/null +++ b/src/api/infra/file/index.ts @@ -0,0 +1,17 @@ +import request from '@/config/axios' + +export interface FilePageReqVO extends PageParam { + path?: string + type?: string + createTime?: Date[] +} + +// 查询文件列表 +export const getFilePage = (params: FilePageReqVO) => { + return request.get({ url: '/infra/file/page', params }) +} + +// 删除文件 +export const deleteFile = (id: number) => { + return request.delete({ url: '/infra/file/delete?id=' + id }) +} diff --git a/src/api/infra/fileConfig/index.ts b/src/api/infra/fileConfig/index.ts new file mode 100644 index 0000000..b72f18b --- /dev/null +++ b/src/api/infra/fileConfig/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +export interface FileClientConfig { + basePath: string + host?: string + port?: number + username?: string + password?: string + mode?: string + endpoint?: string + bucket?: string + accessKey?: string + accessSecret?: string + domain: string +} + +export interface FileConfigVO { + id: number + name: string + storage: any + master: boolean + visible: boolean + config: FileClientConfig + remark: string + createTime: Date +} + +// 查询文件配置列表 +export const getFileConfigPage = (params: PageParam) => { + return request.get({ url: '/infra/file-config/page', params }) +} + +// 查询文件配置详情 +export const getFileConfig = (id: number) => { + return request.get({ url: '/infra/file-config/get?id=' + id }) +} + +// 更新文件配置为主配置 +export const updateFileConfigMaster = (id: number) => { + return request.put({ url: '/infra/file-config/update-master?id=' + id }) +} + +// 新增文件配置 +export const createFileConfig = (data: FileConfigVO) => { + return request.post({ url: '/infra/file-config/create', data }) +} + +// 修改文件配置 +export const updateFileConfig = (data: FileConfigVO) => { + return request.put({ url: '/infra/file-config/update', data }) +} + +// 删除文件配置 +export const deleteFileConfig = (id: number) => { + return request.delete({ url: '/infra/file-config/delete?id=' + id }) +} + +// 测试文件配置 +export const testFileConfig = (id: number) => { + return request.get({ url: '/infra/file-config/test?id=' + id }) +} diff --git a/src/api/infra/job/index.ts b/src/api/infra/job/index.ts new file mode 100644 index 0000000..033b2cb --- /dev/null +++ b/src/api/infra/job/index.ts @@ -0,0 +1,63 @@ +import request from '@/config/axios' + +export interface JobVO { + id: number + name: string + status: number + handlerName: string + handlerParam: string + cronExpression: string + retryCount: number + retryInterval: number + monitorTimeout: number + createTime: Date +} + +// 任务列表 +export const getJobPage = (params: PageParam) => { + return request.get({ url: '/infra/job/page', params }) +} + +// 任务详情 +export const getJob = (id: number) => { + return request.get({ url: '/infra/job/get?id=' + id }) +} + +// 新增任务 +export const createJob = (data: JobVO) => { + return request.post({ url: '/infra/job/create', data }) +} + +// 修改定时任务调度 +export const updateJob = (data: JobVO) => { + return request.put({ url: '/infra/job/update', data }) +} + +// 删除定时任务调度 +export const deleteJob = (id: number) => { + return request.delete({ url: '/infra/job/delete?id=' + id }) +} + +// 导出定时任务调度 +export const exportJob = (params) => { + return request.download({ url: '/infra/job/export-excel', params }) +} + +// 任务状态修改 +export const updateJobStatus = (id: number, status: number) => { + const params = { + id, + status + } + return request.put({ url: '/infra/job/update-status', params }) +} + +// 定时任务立即执行一次 +export const runJob = (id: number) => { + return request.put({ url: '/infra/job/trigger?id=' + id }) +} + +// 获得定时任务的下 n 次执行时间 +export const getJobNextTimes = (id: number) => { + return request.get({ url: '/infra/job/get_next_times?id=' + id }) +} diff --git a/src/api/infra/jobLog/index.ts b/src/api/infra/jobLog/index.ts new file mode 100644 index 0000000..f429cd9 --- /dev/null +++ b/src/api/infra/jobLog/index.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +export interface JobLogVO { + id: number + jobId: number + handlerName: string + handlerParam: string + cronExpression: string + executeIndex: string + beginTime: string + endTime: string + duration: string + status: number + createTime: string +} + +// 任务日志列表 +export const getJobLogPage = (params: PageParam) => { + return request.get({ url: '/infra/job-log/page', params }) +} + +// 任务日志详情 +export const getJobLog = (id: number) => { + return request.get({ url: '/infra/job-log/get?id=' + id }) +} + +// 导出定时任务日志 +export const exportJobLog = (params) => { + return request.download({ + url: '/infra/job-log/export-excel', + params + }) +} diff --git a/src/api/infra/redis/index.ts b/src/api/infra/redis/index.ts new file mode 100644 index 0000000..f27be77 --- /dev/null +++ b/src/api/infra/redis/index.ts @@ -0,0 +1,8 @@ +import request from '@/config/axios' + +/** + * 获取redis 监控信息 + */ +export const getCache = () => { + return request.get({ url: '/infra/redis/get-monitor-info' }) +} diff --git a/src/api/infra/redis/types.ts b/src/api/infra/redis/types.ts new file mode 100644 index 0000000..548bfe9 --- /dev/null +++ b/src/api/infra/redis/types.ts @@ -0,0 +1,176 @@ +export interface RedisMonitorInfoVO { + info: RedisInfoVO + dbSize: number + commandStats: RedisCommandStatsVO[] +} + +export interface RedisInfoVO { + io_threaded_reads_processed: string + tracking_clients: string + uptime_in_seconds: string + cluster_connections: string + current_cow_size: string + maxmemory_human: string + aof_last_cow_size: string + master_replid2: string + mem_replication_backlog: string + aof_rewrite_scheduled: string + total_net_input_bytes: string + rss_overhead_ratio: string + hz: string + current_cow_size_age: string + redis_build_id: string + errorstat_BUSYGROUP: string + aof_last_bgrewrite_status: string + multiplexing_api: string + client_recent_max_output_buffer: string + allocator_resident: string + mem_fragmentation_bytes: string + aof_current_size: string + repl_backlog_first_byte_offset: string + tracking_total_prefixes: string + redis_mode: string + redis_git_dirty: string + aof_delayed_fsync: string + allocator_rss_bytes: string + repl_backlog_histlen: string + io_threads_active: string + rss_overhead_bytes: string + total_system_memory: string + loading: string + evicted_keys: string + maxclients: string + cluster_enabled: string + redis_version: string + repl_backlog_active: string + mem_aof_buffer: string + allocator_frag_bytes: string + io_threaded_writes_processed: string + instantaneous_ops_per_sec: string + used_memory_human: string + total_error_replies: string + role: string + maxmemory: string + used_memory_lua: string + rdb_current_bgsave_time_sec: string + used_memory_startup: string + used_cpu_sys_main_thread: string + lazyfree_pending_objects: string + aof_pending_bio_fsync: string + used_memory_dataset_perc: string + allocator_frag_ratio: string + arch_bits: string + used_cpu_user_main_thread: string + mem_clients_normal: string + expired_time_cap_reached_count: string + unexpected_error_replies: string + mem_fragmentation_ratio: string + aof_last_rewrite_time_sec: string + master_replid: string + aof_rewrite_in_progress: string + lru_clock: string + maxmemory_policy: string + run_id: string + latest_fork_usec: string + tracking_total_items: string + total_commands_processed: string + expired_keys: string + errorstat_ERR: string + used_memory: string + module_fork_in_progress: string + errorstat_WRONGPASS: string + aof_buffer_length: string + dump_payload_sanitizations: string + mem_clients_slaves: string + keyspace_misses: string + server_time_usec: string + executable: string + lazyfreed_objects: string + db0: string + used_memory_peak_human: string + keyspace_hits: string + rdb_last_cow_size: string + aof_pending_rewrite: string + used_memory_overhead: string + active_defrag_hits: string + tcp_port: string + uptime_in_days: string + used_memory_peak_perc: string + current_save_keys_processed: string + blocked_clients: string + total_reads_processed: string + expire_cycle_cpu_milliseconds: string + sync_partial_err: string + used_memory_scripts_human: string + aof_current_rewrite_time_sec: string + aof_enabled: string + process_supervised: string + master_repl_offset: string + used_memory_dataset: string + used_cpu_user: string + rdb_last_bgsave_status: string + tracking_total_keys: string + atomicvar_api: string + allocator_rss_ratio: string + client_recent_max_input_buffer: string + clients_in_timeout_table: string + aof_last_write_status: string + mem_allocator: string + used_memory_scripts: string + used_memory_peak: string + process_id: string + master_failover_state: string + errorstat_NOAUTH: string + used_cpu_sys: string + repl_backlog_size: string + connected_slaves: string + current_save_keys_total: string + gcc_version: string + total_system_memory_human: string + sync_full: string + connected_clients: string + module_fork_last_cow_size: string + total_writes_processed: string + allocator_active: string + total_net_output_bytes: string + pubsub_channels: string + current_fork_perc: string + active_defrag_key_hits: string + rdb_changes_since_last_save: string + instantaneous_input_kbps: string + used_memory_rss_human: string + configured_hz: string + expired_stale_perc: string + active_defrag_misses: string + used_cpu_sys_children: string + number_of_cached_scripts: string + sync_partial_ok: string + used_memory_lua_human: string + rdb_last_save_time: string + pubsub_patterns: string + slave_expires_tracked_keys: string + redis_git_sha1: string + used_memory_rss: string + rdb_last_bgsave_time_sec: string + os: string + mem_not_counted_for_evict: string + active_defrag_running: string + rejected_connections: string + aof_rewrite_buffer_length: string + total_forks: string + active_defrag_key_misses: string + allocator_allocated: string + aof_base_size: string + instantaneous_output_kbps: string + second_repl_offset: string + rdb_bgsave_in_progress: string + used_cpu_user_children: string + total_connections_received: string + migrate_cached_sockets: string +} + +export interface RedisCommandStatsVO { + command: string + calls: number + usec: number +} diff --git a/src/api/login/index.ts b/src/api/login/index.ts new file mode 100644 index 0000000..444f0f2 --- /dev/null +++ b/src/api/login/index.ts @@ -0,0 +1,72 @@ +import request from '@/config/axios' +import { getRefreshToken } from '@/utils/auth' +import type { UserLoginVO } from './types' + +export interface SmsCodeVO { + mobile: string + scene: number +} + +export interface SmsLoginVO { + mobile: string + code: string +} + +// 登录 +export const login = (data: UserLoginVO) => { + return request.post({ url: '/system/auth/login', data }) +} + +// 刷新访问令牌 +export const refreshToken = () => { + return request.post({ url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken() }) +} + +// 使用租户名,获得租户编号 +export const getTenantIdByName = (name: string) => { + return request.get({ url: '/system/tenant/get-id-by-name?name=' + name }) +} + +// 登出 +export const loginOut = () => { + return request.post({ url: '/system/auth/logout' }) +} + +// 获取用户权限信息 +export const getInfo = () => { + return request.get({ url: '/system/auth/get-permission-info' }) +} + +//获取登录验证码 +export const sendSmsCode = (data: SmsCodeVO) => { + return request.post({ url: '/system/auth/send-sms-code', data }) +} + +// 短信验证码登录 +export const smsLogin = (data: SmsLoginVO) => { + return request.post({ url: '/system/auth/sms-login', data }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type: number, redirectUri: string) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} +// 获取验证图片以及 token +export const getCode = (data) => { + return request.postOriginal({ url: 'system/captcha/get', data }) +} + +// 滑动或者点选验证 +export const reqCheck = (data) => { + return request.postOriginal({ url: 'system/captcha/check', data }) +} + +// 获取验证码 +export const getCodeImg = () => { + return request.get({ + url: 'system/captcha/captchaImage', headers: { + isToken: false + }}) +} \ No newline at end of file diff --git a/src/api/login/oauth2/index.ts b/src/api/login/oauth2/index.ts new file mode 100644 index 0000000..aef1820 --- /dev/null +++ b/src/api/login/oauth2/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +// 获得授权信息 +export const getAuthorize = (clientId: string) => { + return request.get({ url: '/system/oauth2/authorize?clientId=' + clientId }) +} + +// 发起授权 +export const authorize = ( + responseType: string, + clientId: string, + redirectUri: string, + state: string, + autoApprove: boolean, + checkedScopes: string[], + uncheckedScopes: string[] +) => { + // 构建 scopes + const scopes = {} + for (const scope of checkedScopes) { + scopes[scope] = true + } + for (const scope of uncheckedScopes) { + scopes[scope] = false + } + // 发起请求 + return request.post({ + url: '/system/oauth2/authorize', + headers: { + 'Content-type': 'application/x-www-form-urlencoded' + }, + params: { + response_type: responseType, + client_id: clientId, + redirect_uri: redirectUri, + state: state, + auto_approve: autoApprove, + scope: JSON.stringify(scopes) + } + }) +} diff --git a/src/api/login/types.ts b/src/api/login/types.ts new file mode 100644 index 0000000..b2173f7 --- /dev/null +++ b/src/api/login/types.ts @@ -0,0 +1,28 @@ +export type UserLoginVO = { + username: string + password: string + captchaVerification: string +} + +export type TokenType = { + id: number // 编号 + accessToken: string // 访问令牌 + refreshToken: string // 刷新令牌 + userId: number // 用户编号 + userType: number //用户类型 + clientId: string //客户端编号 + expiresTime: number //过期时间 +} + +export type UserVO = { + id: number + username: string + nickname: string + deptId: number + email: string + mobile: string + sex: number + avatar: string + loginIp: string + loginDate: string +} diff --git a/src/api/redis/index.ts b/src/api/redis/index.ts new file mode 100644 index 0000000..b716359 --- /dev/null +++ b/src/api/redis/index.ts @@ -0,0 +1,21 @@ +import request from '@/config/axios' + +export interface RedisVO { + key: string + value: string +} + +// 加入缓存 +export const addRedis = async (data:RedisVO) => { + return await request.post({ url: `/infra/redis/set`, data }) +} + +// 获取缓存 +export const getRedis = async (key) => { + return await request.get({ url: `/infra/redis/get?key=` + key}) +} + +// 删除物料清单 +export const deleteRedis = async (key) => { + return await request.delete({ url: `/infra/redis/delete?key=` + key}) +} \ No newline at end of file diff --git a/src/api/system/area/index.ts b/src/api/system/area/index.ts new file mode 100644 index 0000000..b7da941 --- /dev/null +++ b/src/api/system/area/index.ts @@ -0,0 +1,19 @@ +import request from '@/config/axios' + +// 获得地区树 +export const getAreaTree = async () => { + return await request.get({ url: '/system/area/tree' }) +} + +export const getChildrenArea = async (id: number) => { + return await request.get({ url: '/system/area/get-children?id=' + id }) +} + +export const getAreaListByIds = async (ids) => { + return await request.get({ url: '/system/area/get-by-ids?ids=' + ids }) +} + +// 获得 IP 对应的地区名 +export const getAreaByIp = async (ip: string) => { + return await request.get({ url: '/system/area/get-by-ip?ip=' + ip }) +} diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts new file mode 100644 index 0000000..d995f13 --- /dev/null +++ b/src/api/system/dept/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface DeptVO { + id?: number + name: string + parentId: number + status: number + sort: number + leaderUserId: number + phone: string + email: string + createTime: Date +} + +// 查询部门(精简)列表 +export const getSimpleDeptList = async (): Promise => { + return await request.get({ url: '/system/dept/list-all-simple' }) +} + +// 查询部门列表 +export const getDeptPage = async (params: PageParam) => { + return await request.get({ url: '/system/dept/list', params }) +} + +// 查询部门详情 +export const getDept = async (id: number) => { + return await request.get({ url: '/system/dept/get?id=' + id }) +} + +// 新增部门 +export const createDept = async (data: DeptVO) => { + return await request.post({ url: '/system/dept/create', data: data }) +} + +// 修改部门 +export const updateDept = async (params: DeptVO) => { + return await request.put({ url: '/system/dept/update', data: params }) +} + +// 删除部门 +export const deleteDept = async (id: number) => { + return await request.delete({ url: '/system/dept/delete?id=' + id }) +} diff --git a/src/api/system/dict/dict.data.ts b/src/api/system/dict/dict.data.ts new file mode 100644 index 0000000..87e7dce --- /dev/null +++ b/src/api/system/dict/dict.data.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export type DictDataVO = { + id: number | undefined + sort: number | undefined + label: string + value: string + dictType: string + status: number + colorType: string + cssClass: string + remark: string + createTime: Date +} + +// 查询字典数据(精简)列表 +export const listSimpleDictData = () => { + return request.get({ url: '/system/dict-data/list-all-simple' }) +} + +// 查询字典数据列表 +export const getDictDataPage = (params: PageParam) => { + return request.get({ url: '/system/dict-data/page', params }) +} + +// 查询字典数据详情 +export const getDictData = (id: number) => { + return request.get({ url: '/system/dict-data/get?id=' + id }) +} + +// 新增字典数据 +export const createDictData = (data: DictDataVO) => { + return request.post({ url: '/system/dict-data/create', data }) +} + +// 修改字典数据 +export const updateDictData = (data: DictDataVO) => { + return request.put({ url: '/system/dict-data/update', data }) +} + +// 删除字典数据 +export const deleteDictData = (id: number) => { + return request.delete({ url: '/system/dict-data/delete?id=' + id }) +} + +// 导出字典类型数据 +export const exportDictData = (params) => { + return request.get({ url: '/system/dict-data/export', params }) +} diff --git a/src/api/system/dict/dict.type.ts b/src/api/system/dict/dict.type.ts new file mode 100644 index 0000000..ed2969f --- /dev/null +++ b/src/api/system/dict/dict.type.ts @@ -0,0 +1,44 @@ +import request from '@/config/axios' + +export type DictTypeVO = { + id: number | undefined + name: string + type: string + status: number + remark: string + createTime: Date +} + +// 查询字典(精简)列表 +export const getSimpleDictTypeList = () => { + return request.get({ url: '/system/dict-type/list-all-simple' }) +} + +// 查询字典列表 +export const getDictTypePage = (params: PageParam) => { + return request.get({ url: '/system/dict-type/page', params }) +} + +// 查询字典详情 +export const getDictType = (id: number) => { + return request.get({ url: '/system/dict-type/get?id=' + id }) +} + +// 新增字典 +export const createDictType = (data: DictTypeVO) => { + return request.post({ url: '/system/dict-type/create', data }) +} + +// 修改字典 +export const updateDictType = (data: DictTypeVO) => { + return request.put({ url: '/system/dict-type/update', data }) +} + +// 删除字典 +export const deleteDictType = (id: number) => { + return request.delete({ url: '/system/dict-type/delete?id=' + id }) +} +// 导出字典类型 +export const exportDictType = (params) => { + return request.get({ url: '/system/dict-type/export', params }) +} diff --git a/src/api/system/errorCode/index.ts b/src/api/system/errorCode/index.ts new file mode 100644 index 0000000..8a86a63 --- /dev/null +++ b/src/api/system/errorCode/index.ts @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +export interface ErrorCodeVO { + id: number | undefined + type: number + applicationName: string + code: number | undefined + message: string + memo: string + createTime: Date +} + +// 查询错误码列表 +export const getErrorCodePage = (params: PageParam) => { + return request.get({ url: '/system/error-code/page', params }) +} + +// 查询错误码详情 +export const getErrorCode = (id: number) => { + return request.get({ url: '/system/error-code/get?id=' + id }) +} + +// 新增错误码 +export const createErrorCode = (data: ErrorCodeVO) => { + return request.post({ url: '/system/error-code/create', data }) +} + +// 修改错误码 +export const updateErrorCode = (data: ErrorCodeVO) => { + return request.put({ url: '/system/error-code/update', data }) +} + +// 删除错误码 +export const deleteErrorCode = (id: number) => { + return request.delete({ url: '/system/error-code/delete?id=' + id }) +} +// 导出错误码 +export const excelErrorCode = (params) => { + return request.download({ url: '/system/error-code/export-excel', params }) +} diff --git a/src/api/system/loginLog/index.ts b/src/api/system/loginLog/index.ts new file mode 100644 index 0000000..f275c3e --- /dev/null +++ b/src/api/system/loginLog/index.ts @@ -0,0 +1,24 @@ +import request from '@/config/axios' + +export interface LoginLogVO { + id: number + logType: number + traceId: number + userId: number + userType: number + username: string + status: number + userIp: string + userAgent: string + createTime: Date +} + +// 查询登录日志列表 +export const getLoginLogPage = (params: PageParam) => { + return request.get({ url: '/system/login-log/page', params }) +} + +// 导出登录日志 +export const exportLoginLog = (params) => { + return request.download({ url: '/system/login-log/export', params }) +} diff --git a/src/api/system/mail/account/index.ts b/src/api/system/mail/account/index.ts new file mode 100644 index 0000000..9e10c92 --- /dev/null +++ b/src/api/system/mail/account/index.ts @@ -0,0 +1,41 @@ +import request from '@/config/axios' + +export interface MailAccountVO { + id: number + mail: string + username: string + password: string + host: string + port: number + sslEnable: boolean +} + +// 查询邮箱账号列表 +export const getMailAccountPage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-account/page', params }) +} + +// 查询邮箱账号详情 +export const getMailAccount = async (id: number) => { + return await request.get({ url: '/system/mail-account/get?id=' + id }) +} + +// 新增邮箱账号 +export const createMailAccount = async (data: MailAccountVO) => { + return await request.post({ url: '/system/mail-account/create', data }) +} + +// 修改邮箱账号 +export const updateMailAccount = async (data: MailAccountVO) => { + return await request.put({ url: '/system/mail-account/update', data }) +} + +// 删除邮箱账号 +export const deleteMailAccount = async (id: number) => { + return await request.delete({ url: '/system/mail-account/delete?id=' + id }) +} + +// 获得邮箱账号精简列表 +export const getSimpleMailAccountList = async () => { + return request.get({ url: '/system/mail-account/list-all-simple' }) +} diff --git a/src/api/system/mail/log/index.ts b/src/api/system/mail/log/index.ts new file mode 100644 index 0000000..13172a7 --- /dev/null +++ b/src/api/system/mail/log/index.ts @@ -0,0 +1,30 @@ +import request from '@/config/axios' + +export interface MailLogVO { + id: number + userId: number + userType: number + toMail: string + accountId: number + fromMail: string + templateId: number + templateCode: string + templateNickname: string + templateTitle: string + templateContent: string + templateParams: string + sendStatus: number + sendTime: Date + sendMessageId: string + sendException: string +} + +// 查询邮件日志列表 +export const getMailLogPage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-log/page', params }) +} + +// 查询邮件日志详情 +export const getMailLog = async (id: number) => { + return await request.get({ url: '/system/mail-log/get?id=' + id }) +} diff --git a/src/api/system/mail/template/index.ts b/src/api/system/mail/template/index.ts new file mode 100644 index 0000000..fb7ce5e --- /dev/null +++ b/src/api/system/mail/template/index.ts @@ -0,0 +1,50 @@ +import request from '@/config/axios' + +export interface MailTemplateVO { + id: number + name: string + code: string + accountId: number + nickname: string + title: string + content: string + params: string + status: number + remark: string +} + +export interface MailSendReqVO { + mail: string + templateCode: string + templateParams: Map +} + +// 查询邮件模版列表 +export const getMailTemplatePage = async (params: PageParam) => { + return await request.get({ url: '/system/mail-template/page', params }) +} + +// 查询邮件模版详情 +export const getMailTemplate = async (id: number) => { + return await request.get({ url: '/system/mail-template/get?id=' + id }) +} + +// 新增邮件模版 +export const createMailTemplate = async (data: MailTemplateVO) => { + return await request.post({ url: '/system/mail-template/create', data }) +} + +// 修改邮件模版 +export const updateMailTemplate = async (data: MailTemplateVO) => { + return await request.put({ url: '/system/mail-template/update', data }) +} + +// 删除邮件模版 +export const deleteMailTemplate = async (id: number) => { + return await request.delete({ url: '/system/mail-template/delete?id=' + id }) +} + +// 发送邮件 +export const sendMail = (data: MailSendReqVO) => { + return request.post({ url: '/system/mail-template/send-mail', data }) +} diff --git a/src/api/system/menu/index.ts b/src/api/system/menu/index.ts new file mode 100644 index 0000000..4bb9a87 --- /dev/null +++ b/src/api/system/menu/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface MenuVO { + id: number + name: string + permission: string + type: number + sort: number + parentId: number + path: string + icon: string + component: string + componentName?: string + status: number + visible: boolean + keepAlive: boolean + alwaysShow?: boolean + createTime: Date +} + +// 查询菜单(精简)列表 +export const getSimpleMenusList = () => { + return request.get({ url: '/system/menu/list-all-simple' }) +} + +// 查询菜单列表 +export const getMenuList = (params) => { + return request.get({ url: '/system/menu/list', params }) +} + +// 获取菜单详情 +export const getMenu = (id: number) => { + return request.get({ url: '/system/menu/get?id=' + id }) +} + +// 新增菜单 +export const createMenu = (data: MenuVO) => { + return request.post({ url: '/system/menu/create', data }) +} + +// 修改菜单 +export const updateMenu = (data: MenuVO) => { + return request.put({ url: '/system/menu/update', data }) +} + +// 删除菜单 +export const deleteMenu = (id: number) => { + return request.delete({ url: '/system/menu/delete?id=' + id }) +} diff --git a/src/api/system/notice/index.ts b/src/api/system/notice/index.ts new file mode 100644 index 0000000..62bf525 --- /dev/null +++ b/src/api/system/notice/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface NoticeVO { + id: number | undefined + title: string + type: number + content: string + status: number + remark: string + creator: string + createTime: Date +} + +// 查询公告列表 +export const getNoticePage = (params: PageParam) => { + return request.get({ url: '/system/notice/page', params }) +} + +// 查询公告详情 +export const getNotice = (id: number) => { + return request.get({ url: '/system/notice/get?id=' + id }) +} + +// 新增公告 +export const createNotice = (data: NoticeVO) => { + return request.post({ url: '/system/notice/create', data }) +} + +// 修改公告 +export const updateNotice = (data: NoticeVO) => { + return request.put({ url: '/system/notice/update', data }) +} + +// 删除公告 +export const deleteNotice = (id: number) => { + return request.delete({ url: '/system/notice/delete?id=' + id }) +} diff --git a/src/api/system/notify/message/index.ts b/src/api/system/notify/message/index.ts new file mode 100644 index 0000000..29036b9 --- /dev/null +++ b/src/api/system/notify/message/index.ts @@ -0,0 +1,48 @@ +import request from '@/config/axios' +import qs from 'qs' + +export interface NotifyMessageVO { + id: number + userId: number + userType: number + templateId: number + templateCode: string + templateNickname: string + templateContent: string + templateType: number + templateParams: string + readStatus: boolean + readTime: Date +} + +// 查询站内信消息列表 +export const getNotifyMessagePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-message/page', params }) +} + +// 获得我的站内信分页 +export const getMyNotifyMessagePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-message/my-page', params }) +} + +// 批量标记已读 +export const updateNotifyMessageRead = async (ids) => { + return await request.put({ + url: '/system/notify-message/update-read?' + qs.stringify({ ids: ids }, { indices: false }) + }) +} + +// 标记所有站内信为已读 +export const updateAllNotifyMessageRead = async () => { + return await request.put({ url: '/system/notify-message/update-all-read' }) +} + +// 获取当前用户的最新站内信列表 +export const getUnreadNotifyMessageList = async () => { + return await request.get({ url: '/system/notify-message/get-unread-list' }) +} + +// 获得当前用户的未读站内信数量 +export const getUnreadNotifyMessageCount = async () => { + return await request.get({ url: '/system/notify-message/get-unread-count' }) +} diff --git a/src/api/system/notify/template/index.ts b/src/api/system/notify/template/index.ts new file mode 100644 index 0000000..cd0e122 --- /dev/null +++ b/src/api/system/notify/template/index.ts @@ -0,0 +1,49 @@ +import request from '@/config/axios' + +export interface NotifyTemplateVO { + id?: number + name: string + nickname: string + code: string + content: string + type: number + params: string + status: number + remark: string +} + +export interface NotifySendReqVO { + userId: number | null + templateCode: string + templateParams: Map +} + +// 查询站内信模板列表 +export const getNotifyTemplatePage = async (params: PageParam) => { + return await request.get({ url: '/system/notify-template/page', params }) +} + +// 查询站内信模板详情 +export const getNotifyTemplate = async (id: number) => { + return await request.get({ url: '/system/notify-template/get?id=' + id }) +} + +// 新增站内信模板 +export const createNotifyTemplate = async (data: NotifyTemplateVO) => { + return await request.post({ url: '/system/notify-template/create', data }) +} + +// 修改站内信模板 +export const updateNotifyTemplate = async (data: NotifyTemplateVO) => { + return await request.put({ url: '/system/notify-template/update', data }) +} + +// 删除站内信模板 +export const deleteNotifyTemplate = async (id: number) => { + return await request.delete({ url: '/system/notify-template/delete?id=' + id }) +} + +// 发送站内信 +export const sendNotify = (data: NotifySendReqVO) => { + return request.post({ url: '/system/notify-template/send-notify', data }) +} diff --git a/src/api/system/oauth2/client.ts b/src/api/system/oauth2/client.ts new file mode 100644 index 0000000..6f71aca --- /dev/null +++ b/src/api/system/oauth2/client.ts @@ -0,0 +1,47 @@ +import request from '@/config/axios' + +export interface OAuth2ClientVO { + id: number + clientId: string + secret: string + name: string + logo: string + description: string + status: number + accessTokenValiditySeconds: number + refreshTokenValiditySeconds: number + redirectUris: string[] + autoApprove: boolean + authorizedGrantTypes: string[] + scopes: string[] + authorities: string[] + resourceIds: string[] + additionalInformation: string + isAdditionalInformationJson: boolean + createTime: Date +} + +// 查询 OAuth2 客户端的列表 +export const getOAuth2ClientPage = (params: PageParam) => { + return request.get({ url: '/system/oauth2-client/page', params }) +} + +// 查询 OAuth2 客户端的详情 +export const getOAuth2Client = (id: number) => { + return request.get({ url: '/system/oauth2-client/get?id=' + id }) +} + +// 新增 OAuth2 客户端 +export const createOAuth2Client = (data: OAuth2ClientVO) => { + return request.post({ url: '/system/oauth2-client/create', data }) +} + +// 修改 OAuth2 客户端 +export const updateOAuth2Client = (data: OAuth2ClientVO) => { + return request.put({ url: '/system/oauth2-client/update', data }) +} + +// 删除 OAuth2 +export const deleteOAuth2Client = (id: number) => { + return request.delete({ url: '/system/oauth2-client/delete?id=' + id }) +} diff --git a/src/api/system/oauth2/token.ts b/src/api/system/oauth2/token.ts new file mode 100644 index 0000000..ac89ae8 --- /dev/null +++ b/src/api/system/oauth2/token.ts @@ -0,0 +1,22 @@ +import request from '@/config/axios' + +export interface OAuth2TokenVO { + id: number + accessToken: string + refreshToken: string + userId: number + userType: number + clientId: string + createTime: Date + expiresTime: Date +} + +// 查询 token列表 +export const getAccessTokenPage = (params: PageParam) => { + return request.get({ url: '/system/oauth2-token/page', params }) +} + +// 删除 token +export const deleteAccessToken = (accessToken: string) => { + return request.delete({ url: '/system/oauth2-token/delete?accessToken=' + accessToken }) +} diff --git a/src/api/system/operatelog/index.ts b/src/api/system/operatelog/index.ts new file mode 100644 index 0000000..848a533 --- /dev/null +++ b/src/api/system/operatelog/index.ts @@ -0,0 +1,33 @@ +import request from '@/config/axios' + +export type OperateLogVO = { + id: number + userNickname: string + traceId: string + userId: number + module: string + name: string + type: number + content: string + exts: Map + requestMethod: string + requestUrl: string + userIp: string + userAgent: string + javaMethod: string + javaMethodArgs: string + startTime: Date + duration: number + resultCode: number + resultMsg: string + resultData: string +} + +// 查询操作日志列表 +export const getOperateLogPage = (params: PageParam) => { + return request.get({ url: '/system/operate-log/page', params }) +} +// 导出操作日志 +export const exportOperateLog = (params) => { + return request.download({ url: '/system/operate-log/export', params }) +} diff --git a/src/api/system/permission/index.ts b/src/api/system/permission/index.ts new file mode 100644 index 0000000..b3c7696 --- /dev/null +++ b/src/api/system/permission/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface PermissionAssignUserRoleReqVO { + userId: number + roleIds: number[] +} + +export interface PermissionAssignRoleMenuReqVO { + roleId: number + menuIds: number[] +} + +export interface PermissionAssignRoleDataScopeReqVO { + roleId: number + dataScope: number + dataScopeDeptIds: number[] +} + +// 查询角色拥有的菜单权限 +export const getRoleMenuList = async (roleId: number) => { + return await request.get({ url: '/system/permission/list-role-menus?roleId=' + roleId }) +} + +// 赋予角色菜单权限 +export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => { + return await request.post({ url: '/system/permission/assign-role-menu', data }) +} + +// 赋予角色数据权限 +export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => { + return await request.post({ url: '/system/permission/assign-role-data-scope', data }) +} + +// 查询用户拥有的角色数组 +export const getUserRoleList = async (userId: number) => { + return await request.get({ url: '/system/permission/list-user-roles?userId=' + userId }) +} + +// 赋予用户角色 +export const assignUserRole = async (data: PermissionAssignUserRoleReqVO) => { + return await request.post({ url: '/system/permission/assign-user-role', data }) +} diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts new file mode 100644 index 0000000..405db38 --- /dev/null +++ b/src/api/system/post/index.ts @@ -0,0 +1,46 @@ +import request from '@/config/axios' + +export interface PostVO { + id?: number + name: string + code: string + sort: number + status: number + remark: string + createTime?: Date +} + +// 查询岗位列表 +export const getPostPage = async (params: PageParam) => { + return await request.get({ url: '/system/post/page', params }) +} + +// 获取岗位精简信息列表 +export const getSimplePostList = async (): Promise => { + return await request.get({ url: '/system/post/list-all-simple' }) +} + +// 查询岗位详情 +export const getPost = async (id: number) => { + return await request.get({ url: '/system/post/get?id=' + id }) +} + +// 新增岗位 +export const createPost = async (data: PostVO) => { + return await request.post({ url: '/system/post/create', data }) +} + +// 修改岗位 +export const updatePost = async (data: PostVO) => { + return await request.put({ url: '/system/post/update', data }) +} + +// 删除岗位 +export const deletePost = async (id: number) => { + return await request.delete({ url: '/system/post/delete?id=' + id }) +} + +// 导出岗位 +export const exportPost = async (params) => { + return await request.download({ url: '/system/post/export', params }) +} diff --git a/src/api/system/role/index.ts b/src/api/system/role/index.ts new file mode 100644 index 0000000..93636ff --- /dev/null +++ b/src/api/system/role/index.ts @@ -0,0 +1,61 @@ +import request from '@/config/axios' + +export interface RoleVO { + id: number + name: string + code: string + sort: number + status: number + type: number + dataScope: number + dataScopeDeptIds: number[] + createTime: Date +} + +export interface UpdateStatusReqVO { + id: number + status: number +} + +// 查询角色列表 +export const getRolePage = async (params: PageParam) => { + return await request.get({ url: '/system/role/page', params }) +} + +// 查询角色(精简)列表 +export const getSimpleRoleList = async (): Promise => { + return await request.get({ url: '/system/role/list-all-simple' }) +} + +// 查询角色详情 +export const getRole = async (id: number) => { + return await request.get({ url: '/system/role/get?id=' + id }) +} + +// 新增角色 +export const createRole = async (data: RoleVO) => { + return await request.post({ url: '/system/role/create', data }) +} + +// 修改角色 +export const updateRole = async (data: RoleVO) => { + return await request.put({ url: '/system/role/update', data }) +} + +// 修改角色状态 +export const updateRoleStatus = async (data: UpdateStatusReqVO) => { + return await request.put({ url: '/system/role/update-status', data }) +} + +// 删除角色 +export const deleteRole = async (id: number) => { + return await request.delete({ url: '/system/role/delete?id=' + id }) +} + +// 导出角色 +export const exportRole = (params) => { + return request.download({ + url: '/system/role/export-excel', + params + }) +} diff --git a/src/api/system/sensitiveWord/index.ts b/src/api/system/sensitiveWord/index.ts new file mode 100644 index 0000000..1116226 --- /dev/null +++ b/src/api/system/sensitiveWord/index.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' +import qs from 'qs' + +export interface SensitiveWordVO { + id: number + name: string + status: number + description: string + tags: string[] + createTime: Date +} + +export interface SensitiveWordTestReqVO { + text: string + tag: string[] +} + +// 查询敏感词列表 +export const getSensitiveWordPage = (params: PageParam) => { + return request.get({ url: '/system/sensitive-word/page', params }) +} + +// 查询敏感词详情 +export const getSensitiveWord = (id: number) => { + return request.get({ url: '/system/sensitive-word/get?id=' + id }) +} + +// 新增敏感词 +export const createSensitiveWord = (data: SensitiveWordVO) => { + return request.post({ url: '/system/sensitive-word/create', data }) +} + +// 修改敏感词 +export const updateSensitiveWord = (data: SensitiveWordVO) => { + return request.put({ url: '/system/sensitive-word/update', data }) +} + +// 删除敏感词 +export const deleteSensitiveWord = (id: number) => { + return request.delete({ url: '/system/sensitive-word/delete?id=' + id }) +} + +// 导出敏感词 +export const exportSensitiveWord = (params) => { + return request.download({ url: '/system/sensitive-word/export-excel', params }) +} + +// 获取所有敏感词的标签数组 +export const getSensitiveWordTagList = () => { + return request.get({ url: '/system/sensitive-word/get-tags' }) +} + +// 获得文本所包含的不合法的敏感词数组 +export const validateText = (query: SensitiveWordTestReqVO) => { + return request.get({ + url: '/system/sensitive-word/validate-text?' + qs.stringify(query, { arrayFormat: 'repeat' }) + }) +} diff --git a/src/api/system/serialNumber/index.ts b/src/api/system/serialNumber/index.ts new file mode 100644 index 0000000..33fa754 --- /dev/null +++ b/src/api/system/serialNumber/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface SerialNumberVO { + id: number + ruleCode: string + ruleName: string + prefix: string + pattern: string + length: byte + separator: string + remark: string +} + +// 查询流水号规则列表 +export const getSerialNumberPage = async (params) => { + return await request.get({ url: `/system/serial-number/page`, params }) +} + +// 查询流水号规则详情 +export const getSerialNumber = async (id: number) => { + return await request.get({ url: `/system/serial-number/get?id=` + id }) +} + +// 新增流水号规则 +export const createSerialNumber = async (data: SerialNumberVO) => { + return await request.post({ url: `/system/serial-number/create`, data }) +} + +// 修改流水号规则 +export const updateSerialNumber = async (data: SerialNumberVO) => { + return await request.put({ url: `/system/serial-number/update`, data }) +} + +// 删除流水号规则 +export const deleteSerialNumber = async (id: number) => { + return await request.delete({ url: `/system/serial-number/delete?id=` + id }) +} + +// 导出流水号规则 Excel +export const exportSerialNumber = async (params) => { + return await request.download({ url: `/system/serial-number/export-excel`, params }) +} diff --git a/src/api/system/sms/smsChannel/index.ts b/src/api/system/sms/smsChannel/index.ts new file mode 100644 index 0000000..f335628 --- /dev/null +++ b/src/api/system/sms/smsChannel/index.ts @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface SmsChannelVO { + id: number + code: string + status: number + signature: string + remark: string + apiKey: string + apiSecret: string + callbackUrl: string + createTime: Date +} + +// 查询短信渠道列表 +export const getSmsChannelPage = (params: PageParam) => { + return request.get({ url: '/system/sms-channel/page', params }) +} + +// 获得短信渠道精简列表 +export function getSimpleSmsChannelList() { + return request.get({ url: '/system/sms-channel/list-all-simple' }) +} + +// 查询短信渠道详情 +export const getSmsChannel = (id: number) => { + return request.get({ url: '/system/sms-channel/get?id=' + id }) +} + +// 新增短信渠道 +export const createSmsChannel = (data: SmsChannelVO) => { + return request.post({ url: '/system/sms-channel/create', data }) +} + +// 修改短信渠道 +export const updateSmsChannel = (data: SmsChannelVO) => { + return request.put({ url: '/system/sms-channel/update', data }) +} + +// 删除短信渠道 +export const deleteSmsChannel = (id: number) => { + return request.delete({ url: '/system/sms-channel/delete?id=' + id }) +} diff --git a/src/api/system/sms/smsLog/index.ts b/src/api/system/sms/smsLog/index.ts new file mode 100644 index 0000000..3d54fac --- /dev/null +++ b/src/api/system/sms/smsLog/index.ts @@ -0,0 +1,39 @@ +import request from '@/config/axios' + +export interface SmsLogVO { + id: number | null + channelId: number | null + channelCode: string + templateId: number | null + templateCode: string + templateType: number | null + templateContent: string + templateParams: Map | null + apiTemplateId: string + mobile: string + userId: number | null + userType: number | null + sendStatus: number | null + sendTime: Date | null + sendCode: number | null + sendMsg: string + apiSendCode: string + apiSendMsg: string + apiRequestId: string + apiSerialNo: string + receiveStatus: number | null + receiveTime: Date | null + apiReceiveCode: string + apiReceiveMsg: string + createTime: Date | null +} + +// 查询短信日志列表 +export const getSmsLogPage = (params: PageParam) => { + return request.get({ url: '/system/sms-log/page', params }) +} + +// 导出短信日志 +export const exportSmsLog = (params) => { + return request.download({ url: '/system/sms-log/export-excel', params }) +} diff --git a/src/api/system/sms/smsTemplate/index.ts b/src/api/system/sms/smsTemplate/index.ts new file mode 100644 index 0000000..35cb489 --- /dev/null +++ b/src/api/system/sms/smsTemplate/index.ts @@ -0,0 +1,60 @@ +import request from '@/config/axios' + +export interface SmsTemplateVO { + id: number | null + type: number | null + status: number + code: string + name: string + content: string + remark: string + apiTemplateId: string + channelId: number | null + channelCode?: string + params?: string[] + createTime?: Date +} + +export interface SendSmsReqVO { + mobile: string + templateCode: string + templateParams: Map +} + +// 查询短信模板列表 +export const getSmsTemplatePage = (params: PageParam) => { + return request.get({ url: '/system/sms-template/page', params }) +} + +// 查询短信模板详情 +export const getSmsTemplate = (id: number) => { + return request.get({ url: '/system/sms-template/get?id=' + id }) +} + +// 新增短信模板 +export const createSmsTemplate = (data: SmsTemplateVO) => { + return request.post({ url: '/system/sms-template/create', data }) +} + +// 修改短信模板 +export const updateSmsTemplate = (data: SmsTemplateVO) => { + return request.put({ url: '/system/sms-template/update', data }) +} + +// 删除短信模板 +export const deleteSmsTemplate = (id: number) => { + return request.delete({ url: '/system/sms-template/delete?id=' + id }) +} + +// 导出短信模板 +export const exportSmsTemplate = (params) => { + return request.download({ + url: '/system/sms-template/export-excel', + params + }) +} + +// 发送短信 +export const sendSms = (data: SendSmsReqVO) => { + return request.post({ url: '/system/sms-template/send-sms', data }) +} diff --git a/src/api/system/tenant/index.ts b/src/api/system/tenant/index.ts new file mode 100644 index 0000000..176c375 --- /dev/null +++ b/src/api/system/tenant/index.ts @@ -0,0 +1,62 @@ +import request from '@/config/axios' + +export interface TenantVO { + id: number + name: string + contactName: string + contactMobile: string + status: number + domain: string + packageId: number + username: string + password: string + expireTime: Date + accountCount: number + createTime: Date +} + +export interface TenantPageReqVO extends PageParam { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} + +export interface TenantExportReqVO { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} + +// 查询租户列表 +export const getTenantPage = (params: TenantPageReqVO) => { + return request.get({ url: '/system/tenant/page', params }) +} + +// 查询租户详情 +export const getTenant = (id: number) => { + return request.get({ url: '/system/tenant/get?id=' + id }) +} + +// 新增租户 +export const createTenant = (data: TenantVO) => { + return request.post({ url: '/system/tenant/create', data }) +} + +// 修改租户 +export const updateTenant = (data: TenantVO) => { + return request.put({ url: '/system/tenant/update', data }) +} + +// 删除租户 +export const deleteTenant = (id: number) => { + return request.delete({ url: '/system/tenant/delete?id=' + id }) +} + +// 导出租户 +export const exportTenant = (params: TenantExportReqVO) => { + return request.download({ url: '/system/tenant/export-excel', params }) +} diff --git a/src/api/system/tenantPackage/index.ts b/src/api/system/tenantPackage/index.ts new file mode 100644 index 0000000..01d139e --- /dev/null +++ b/src/api/system/tenantPackage/index.ts @@ -0,0 +1,42 @@ +import request from '@/config/axios' + +export interface TenantPackageVO { + id: number + name: string + status: number + remark: string + creator: string + updater: string + updateTime: string + menuIds: number[] + createTime: Date +} + +// 查询租户套餐列表 +export const getTenantPackagePage = (params: PageParam) => { + return request.get({ url: '/system/tenant-package/page', params }) +} + +// 获得租户 +export const getTenantPackage = (id: number) => { + return request.get({ url: '/system/tenant-package/get?id=' + id }) +} + +// 新增租户套餐 +export const createTenantPackage = (data: TenantPackageVO) => { + return request.post({ url: '/system/tenant-package/create', data }) +} + +// 修改租户套餐 +export const updateTenantPackage = (data: TenantPackageVO) => { + return request.put({ url: '/system/tenant-package/update', data }) +} + +// 删除租户套餐 +export const deleteTenantPackage = (id: number) => { + return request.delete({ url: '/system/tenant-package/delete?id=' + id }) +} +// 获取租户套餐精简信息列表 +export const getTenantPackageList = () => { + return request.get({ url: '/system/tenant-package/get-simple-list' }) +} diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts new file mode 100644 index 0000000..6224f0e --- /dev/null +++ b/src/api/system/user/index.ts @@ -0,0 +1,76 @@ +import request from '@/config/axios' + +export interface UserVO { + id: number + username: string + nickname: string + deptId: number + postIds: string[] + email: string + mobile: string + sex: number + avatar: string + loginIp: string + status: number + remark: string + loginDate: Date + createTime: Date +} + +// 查询用户管理列表 +export const getUserPage = (params: PageParam) => { + return request.get({ url: '/system/user/page', params }) +} + +// 查询用户详情 +export const getUser = (id: number) => { + return request.get({ url: '/system/user/get?id=' + id }) +} + +// 新增用户 +export const createUser = (data: UserVO) => { + return request.post({ url: '/system/user/create', data }) +} + +// 修改用户 +export const updateUser = (data: UserVO) => { + return request.put({ url: '/system/user/update', data }) +} + +// 删除用户 +export const deleteUser = (id: number) => { + return request.delete({ url: '/system/user/delete?id=' + id }) +} + +// 导出用户 +export const exportUser = (params) => { + return request.download({ url: '/system/user/export', params }) +} + +// 下载用户导入模板 +export const importUserTemplate = () => { + return request.download({ url: '/system/user/get-import-template' }) +} + +// 用户密码重置 +export const resetUserPwd = (id: number, password: string) => { + const data = { + id, + password + } + return request.put({ url: '/system/user/update-password', data: data }) +} + +// 用户状态修改 +export const updateUserStatus = (id: number, status: number) => { + const data = { + id, + status + } + return request.put({ url: '/system/user/update-status', data: data }) +} + +// 获取用户精简信息列表 +export const getSimpleUserList = (): Promise => { + return request.get({ url: '/system/user/list-all-simple' }) +} diff --git a/src/api/system/user/profile.ts b/src/api/system/user/profile.ts new file mode 100644 index 0000000..b2623c8 --- /dev/null +++ b/src/api/system/user/profile.ts @@ -0,0 +1,77 @@ +import request from '@/config/axios' + +export interface ProfileDept { + id: number + name: string +} +export interface ProfileRole { + id: number + name: string +} +export interface ProfilePost { + id: number + name: string +} +export interface SocialUser { + id: number + type: number + openid: string + token: string + rawTokenInfo: string + nickname: string + avatar: string + rawUserInfo: string + code: string + state: string +} +export interface ProfileVO { + id: number + username: string + nickname: string + dept: ProfileDept + roles: ProfileRole[] + posts: ProfilePost[] + socialUsers: SocialUser[] + email: string + mobile: string + sex: number + avatar: string + status: number + remark: string + loginIp: string + loginDate: Date + createTime: Date +} + +export interface UserProfileUpdateReqVO { + nickname: string + email: string + mobile: string + sex: number +} + +// 查询用户个人信息 +export const getUserProfile = () => { + return request.get({ url: '/system/user/profile/get' }) +} + +// 修改用户个人信息 +export const updateUserProfile = (data: UserProfileUpdateReqVO) => { + return request.put({ url: '/system/user/profile/update', data }) +} + +// 用户密码重置 +export const updateUserPassword = (oldPassword: string, newPassword: string) => { + return request.put({ + url: '/system/user/profile/update-password', + data: { + oldPassword: oldPassword, + newPassword: newPassword + } + }) +} + +// 用户头像上传 +export const uploadAvatar = (data) => { + return request.upload({ url: '/system/user/profile/update-avatar', data: data }) +} diff --git a/src/api/system/user/socialUser.ts b/src/api/system/user/socialUser.ts new file mode 100644 index 0000000..79f4d40 --- /dev/null +++ b/src/api/system/user/socialUser.ts @@ -0,0 +1,31 @@ +import request from '@/config/axios' + +// 社交绑定,使用 code 授权码 +export const socialBind = (type, code, state) => { + return request.post({ + url: '/system/social-user/bind', + data: { + type, + code, + state + } + }) +} + +// 取消社交绑定 +export const socialUnbind = (type, openid) => { + return request.delete({ + url: '/system/social-user/unbind', + data: { + type, + openid + } + }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type, redirectUri) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} diff --git a/src/assets/imgs/avatar.gif b/src/assets/imgs/avatar.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdbd32c675f85af4ed57021ac0638a21a3c6cad3 GIT binary patch literal 6334 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 literal 0 HcmV?d00001 diff --git a/src/assets/imgs/avatar.jpg b/src/assets/imgs/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d46a70a46430e31744420865138cc7eedb8b77e1 GIT binary patch literal 6264 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 BLq7lj literal 0 HcmV?d00001 diff --git a/src/assets/imgs/code.png b/src/assets/imgs/code.png new file mode 100644 index 0000000000000000000000000000000000000000..ac4c16f913928a6490c26c7b0b96c05c55f8a9c1 GIT binary patch literal 4871 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 literal 0 HcmV?d00001 diff --git a/src/assets/imgs/logo.png b/src/assets/imgs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..87c1d32cb902c4171ce38ae5bbbfc5fe9faace4b GIT binary patch literal 16773 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