├── .github ├── release-drafter.yml └── workflows │ ├── release-ci.yml │ └── test-ci.yml ├── .gitignore ├── Dockerfile ├── Dockerfile-nginx ├── README.md ├── logo.jpeg ├── package.json ├── postcss.config.js ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.jsx ├── api │ ├── ai.jsx │ ├── auditLog.jsx │ ├── cloudwatch.jsx │ ├── dashboard.jsx │ ├── datasource.jsx │ ├── duty.jsx │ ├── event.jsx │ ├── faultCenter.jsx │ ├── kubernetes.jsx │ ├── notice.jsx │ ├── noticeTmpl.jsx │ ├── other.jsx │ ├── permissions.jsx │ ├── probing.jsx │ ├── role.jsx │ ├── rule.jsx │ ├── ruleTmpl.jsx │ ├── settings.jsx │ ├── silence.jsx │ ├── subscribe.jsx │ ├── tenant.jsx │ └── user.jsx ├── components │ ├── context │ │ └── index.jsx │ ├── index.css │ ├── index.jsx │ └── sider │ │ └── index.jsx ├── context │ └── RuleContext.js ├── img │ ├── 701986.svg │ ├── WatchAlert.png │ ├── github_logo.png │ └── logo.jpeg ├── index.css ├── index.js ├── pages │ ├── alert │ │ ├── assets │ │ │ ├── event.svg │ │ │ ├── log.svg │ │ │ ├── metric.svg │ │ │ └── trace.svg │ │ ├── preview │ │ │ └── searchViewLogs.jsx │ │ ├── rule │ │ │ ├── create.jsx │ │ │ ├── img │ │ │ │ ├── AWSlogo.svg │ │ │ │ ├── ElasticSearch.svg │ │ │ │ ├── Kubernetes.svg │ │ │ │ ├── L.svg │ │ │ │ ├── Prometheus.svg │ │ │ │ ├── alicloud.svg │ │ │ │ ├── jaeger.svg │ │ │ │ ├── victorialogs.svg │ │ │ │ └── victoriametrics.svg │ │ │ ├── index.css │ │ │ └── index.jsx │ │ ├── ruleGroup │ │ │ ├── AlertRuleGroupCreateModal.jsx │ │ │ └── index.jsx │ │ ├── tmpl │ │ │ ├── RuleTemplateCreateModal.jsx │ │ │ └── index.jsx │ │ └── tmplGroup │ │ │ ├── RuleTemplateGroupCreateModal.jsx │ │ │ └── index.jsx │ ├── audit │ │ └── index.jsx │ ├── chart │ │ └── noticeMetricChart.jsx │ ├── dashboards │ │ ├── dashboard │ │ │ ├── iframe.jsx │ │ │ └── index.jsx │ │ └── folder │ │ │ ├── create.jsx │ │ │ └── index.jsx │ ├── datasources │ │ ├── DatasourceCreateModal.jsx │ │ ├── index.css │ │ └── index.jsx │ ├── duty │ │ ├── DutyManageCreateModal.jsx │ │ ├── calendar │ │ │ ├── CreateCalendar.jsx │ │ │ ├── UpdateCalendar.jsx │ │ │ ├── index.css │ │ │ └── index.jsx │ │ └── index.jsx │ ├── event │ │ ├── currentEvent.jsx │ │ ├── historyEvent.jsx │ │ ├── index.css │ │ └── tmpl │ │ │ └── index.jsx │ ├── faultCenter │ │ ├── create.jsx │ │ ├── detail.jsx │ │ ├── index.css │ │ ├── index.jsx │ │ ├── notify.jsx │ │ └── upgrade.jsx │ ├── global.css │ ├── home.jsx │ ├── login.jsx │ ├── members │ │ ├── role │ │ │ ├── UserRoleCreateModal.jsx │ │ │ └── index.jsx │ │ └── user │ │ │ ├── UserChangePass.jsx │ │ │ ├── UserCreateModal.jsx │ │ │ └── index.jsx │ ├── notice │ │ ├── NoticeObjectCreateModal.jsx │ │ ├── history.jsx │ │ ├── img │ │ │ ├── Email.svg │ │ │ ├── customhook.svg │ │ │ ├── dingding.svg │ │ │ ├── feishu.svg │ │ │ └── qywechat.svg │ │ ├── index.jsx │ │ ├── notification-type-icon.jsx │ │ └── tmpl │ │ │ ├── NoticeTemplateCreateModal.jsx │ │ │ └── index.jsx │ ├── probing │ │ ├── create.jsx │ │ ├── detail.jsx │ │ ├── index.css │ │ ├── index.jsx │ │ └── once.jsx │ ├── profile │ │ └── index.jsx │ ├── promethues │ │ ├── index.css │ │ └── index.jsx │ ├── settings │ │ ├── index.css │ │ └── index.jsx │ ├── silence │ │ ├── SilenceRuleCreateModal.jsx │ │ └── index.jsx │ ├── subscribe │ │ ├── create.jsx │ │ └── index.jsx │ └── tenant │ │ ├── CreateTenant.jsx │ │ ├── detail.jsx │ │ ├── index.css │ │ ├── index.jsx │ │ ├── quota.jsx │ │ ├── security.jsx │ │ └── users.jsx ├── routes │ └── index.jsx └── utils │ ├── Auth.jsx │ ├── Error.jsx │ ├── JsonTable.jsx │ ├── MarkdownRenderer.css │ ├── MarkdownRenderer.jsx │ ├── See.jsx │ ├── VSCodeEditor.jsx │ ├── copyToClipboard.jsx │ ├── exportAlarmRecordToHTML.jsx │ └── http.jsx ├── tailwind.config.js ├── w8t.conf └── yarn.lock /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - ignore-for-release 5 | categories: 6 | - title: '🚀 Features' 7 | labels: 8 | - 'feature' 9 | - title: '🐛 Bug Fixes' 10 | labels: 11 | - 'bug' 12 | - title: 📝 Documentation updates 13 | labels: 14 | - documentation 15 | - title: 👻 Maintenance 16 | labels: 17 | - dependencies 18 | - title: 🚦 Tests 19 | labels: 20 | - tests 21 | - title: Other Changes 22 | labels: 23 | - "*" -------------------------------------------------------------------------------- /.github/workflows/release-ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v3 15 | 16 | - name: Set up QEMU 17 | uses: docker/setup-qemu-action@v3 18 | 19 | - name: Inject slug/short variables 20 | uses: rlespinasse/github-slug-action@v4 21 | 22 | - name: Set up Docker Buildx 23 | id: buildx 24 | uses: docker/setup-buildx-action@v3 25 | with: 26 | driver: docker-container 27 | 28 | - name: Available platforms 29 | run: echo ${{ steps.buildx.outputs.platforms }} 30 | 31 | - name: Login to Docker Hub 32 | uses: docker/login-action@v3 33 | with: 34 | username: ${{ secrets.DOCKERHUB_USER }} 35 | password: ${{ secrets.DOCKERHUB_TOKEN }} 36 | 37 | - name: Set env variables 38 | id: set_env 39 | run: | 40 | echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV 41 | 42 | - name: Build and push 43 | uses: docker/build-push-action@v6 44 | with: 45 | context: . 46 | file: ./Dockerfile-nginx 47 | platforms: linux/amd64,linux/arm64 48 | push: true 49 | build-args: | 50 | VERSION=${{ env.TAG_NAME }} 51 | tags: | 52 | cairry/watchalert-web:latest 53 | cairry/watchalert-web:${{ env.TAG_NAME }} -------------------------------------------------------------------------------- /.github/workflows/test-ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*/*' 7 | - 'master' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout code 15 | uses: actions/checkout@v3 16 | 17 | - name: Set up QEMU 18 | uses: docker/setup-qemu-action@v3 19 | 20 | - name: Inject slug/short variables 21 | uses: rlespinasse/github-slug-action@v4 22 | 23 | - name: Set up Docker Buildx 24 | id: buildx 25 | uses: docker/setup-buildx-action@v3 26 | with: 27 | driver: docker-container 28 | 29 | - name: Available platforms 30 | run: echo ${{ steps.buildx.outputs.platforms }} 31 | 32 | - name: Login to Docker Hub 33 | uses: docker/login-action@v3 34 | with: 35 | username: ${{ secrets.DOCKERHUB_USER }} 36 | password: ${{ secrets.DOCKERHUB_TOKEN }} 37 | 38 | - name: Set env variables 39 | id: set_env 40 | run: | 41 | echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV 42 | 43 | - name: Build and push 44 | uses: docker/build-push-action@v6.15.0 45 | with: 46 | context: . 47 | file: ./Dockerfile-nginx 48 | platforms: linux/amd64,linux/arm64 49 | push: true 50 | build-args: | 51 | VERSION=${{ env.DATE }} 52 | tags: | 53 | cairry/watchalert-web:${{ env.BRANCH_NAME }} 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18.15.0-alpine3.17 as build 2 | 3 | RUN mkdir /app 4 | 5 | COPY . /app 6 | 7 | WORKDIR /app 8 | 9 | RUN yarn config set registry https://registry.npmmirror.com && \ 10 | yarn install 11 | 12 | EXPOSE 3000 13 | 14 | # 如果需要指定后端服务端口号,例如:REACT_APP_BACKEND_PORT=9002 yarn start。 15 | CMD [ "yarn", "start" ] 16 | 17 | #FROM node:18.15.0-alpine3.17 as build 18 | # 19 | #RUN mkdir /app 20 | # 21 | #COPY . /app 22 | # 23 | #WORKDIR /app 24 | # 25 | #RUN yarn config set registry https://registry.npmmirror.com && \ 26 | # yarn build 27 | # 28 | #FROM firesh/nginx-lua:alpine-3.18 as release 29 | # 30 | #COPY --from=build /app/build/ /app/ 31 | # 32 | #COPY ./w8t.conf /etc/nginx/conf.d 33 | # 34 | #WORKDIR /etc/nginx/ 35 | # 36 | #EXPOSE 80 37 | # 38 | #CMD ["nginx","-g","daemon off;"] 39 | -------------------------------------------------------------------------------- /Dockerfile-nginx: -------------------------------------------------------------------------------- 1 | FROM node:18.20.3-alpine3.20 as build 2 | 3 | RUN mkdir /app 4 | 5 | COPY . /app 6 | 7 | WORKDIR /app 8 | 9 | RUN yarn config set registry https://registry.npmmirror.com && \ 10 | yarn install && \ 11 | yarn build && \ 12 | tar zcf build.tar.gz ./build 13 | 14 | FROM nginx:1.18.0 as release 15 | 16 | RUN mkdir /app 17 | 18 | COPY --from=build /app/build.tar.gz /app 19 | 20 | RUN tar zxf /app/build.tar.gz -C /app && \ 21 | mv /app/build/* /app && \ 22 | rm -rf /app/build* && \ 23 | rm -rf /etc/nginx/conf.d/default.conf 24 | 25 | COPY ./w8t.conf /etc/nginx/conf.d 26 | 27 | WORKDIR /etc/nginx/ 28 | 29 | EXPOSE 80 30 | 31 | CMD ["nginx","-g","daemon off;"] 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/logo.jpeg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "watchalert-web", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@ant-design/icons": "^6.0.0", 7 | "@ant-design/x": "^1.0.5", 8 | "@codemirror/autocomplete": "^0.18.3", 9 | "@codemirror/closebrackets": "^0.18.0", 10 | "@codemirror/commands": "^0.18.0", 11 | "@codemirror/comment": "^0.18.0", 12 | "@codemirror/highlight": "^0.18.3", 13 | "@codemirror/history": "^0.18.0", 14 | "@codemirror/language": "^0.18.0", 15 | "@codemirror/lint": "^0.18.1", 16 | "@codemirror/matchbrackets": "^0.18.0", 17 | "@codemirror/search": "^0.18.2", 18 | "@codemirror/state": "^0.18.2", 19 | "@codemirror/view": "^0.18.3", 20 | "@heroui/react": "^2.7.8", 21 | "@heroui/toast": "^2.0.9", 22 | "@monaco-editor/react": "^4.7.0", 23 | "@tailwindcss/postcss": "^4.1.6", 24 | "antd": "5.13.2", 25 | "axios": "^0.26.0", 26 | "codemirror": "^6.0.1", 27 | "codemirror-promql": "0.17.0", 28 | "components": "^0.1.0", 29 | "dayjs": "^1.11.13", 30 | "echarts": "^5.6.0", 31 | "echarts-for-react": "^3.0.2", 32 | "framer-motion": "^12.11.0", 33 | "github-markdown-css": "^5.8.1", 34 | "lodash-es": "^4.17.21", 35 | "lucide-react": "^0.510.0", 36 | "moment": "^2.30.1", 37 | "monaco-editor": "^0.52.2", 38 | "next": "^15.1.0", 39 | "react": "^18.2.0", 40 | "react-beautiful-dnd": "^13.1.1", 41 | "react-dom": "^18.2.0", 42 | "react-fast-marquee": "^1.6.5", 43 | "react-helmet": "^6.1.0", 44 | "react-is": "^18.2.0", 45 | "react-json-editor-ajrm": "^2.5.14", 46 | "react-json-view": "^1.21.3", 47 | "react-markdown": "^10.0.1", 48 | "react-router-dom": "^6.22.1", 49 | "react-scripts": "5.0.0", 50 | "react-syntax-highlighter": "^15.6.1", 51 | "react-toastify": "^10.0.4", 52 | "reactstrap": "^8.0.1", 53 | "recharts": "^2.15.3", 54 | "tailwind": "^4.0.0", 55 | "tailwindcss": "3.4.16" 56 | }, 57 | "scripts": { 58 | "start": "react-scripts start", 59 | "build": "react-scripts build", 60 | "test": "react-scripts test", 61 | "eject": "react-scripts eject" 62 | }, 63 | "eslintConfig": { 64 | "extends": [ 65 | "react-app", 66 | "react-app/jest" 67 | ] 68 | }, 69 | "browserslist": { 70 | "production": [ 71 | ">0.2%", 72 | "not dead", 73 | "not op_mini all" 74 | ], 75 | "development": [ 76 | "last 1 chrome version", 77 | "last 1 firefox version", 78 | "last 1 safari version" 79 | ] 80 | }, 81 | "devDependencies": { 82 | "autoprefixer": "^10.4.21", 83 | "json-server": "^0.17.0", 84 | "postcss": "^8.5.3", 85 | "tailwindcss": "^4.1.6" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ConfigProvider, theme } from 'antd'; 3 | import { Helmet } from 'react-helmet'; 4 | import routes from './routes'; 5 | import { useRoutes } from 'react-router-dom'; 6 | import './index.css' 7 | import { ContextProvider } from './context/RuleContext'; 8 | 9 | export default function App() { 10 | const element = useRoutes(routes); 11 | const title = "WatchAlert"; 12 | 13 | return ( 14 | 15 | 16 | 17 | {title} 18 | 19 | {element} 20 | 21 | 22 | ); 23 | } -------------------------------------------------------------------------------- /src/api/ai.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | export async function ReqAiAnalyze(params) { 5 | try { 6 | const response = await http('post', `/api/w8t/ai/chat`,params); 7 | return response; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: `Ai 分析失败: ${error.message}`, 12 | }); 13 | return error 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/api/auditLog.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function listAuditLog(params) { 5 | try { 6 | const queryString = Object.keys(params) 7 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 8 | .filter(Boolean) 9 | .join('&'); 10 | const res = await http('get', `/api/w8t/auditLog/listAuditLog?${queryString}`); 11 | return res; 12 | } catch (error) { 13 | message.open({ 14 | type: 'error', 15 | content: '审计日志列表获取失败', 16 | }); 17 | return error 18 | } 19 | } 20 | 21 | async function searchAuditLog(params) { 22 | try { 23 | const queryString = Object.keys(params) 24 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 25 | .filter(Boolean) 26 | .join('&'); 27 | 28 | const res = await http('get', `/api/w8t/auditLog/searchAuditLog?${queryString}`); 29 | return res; 30 | } catch (error) { 31 | message.open({ 32 | type: 'error', 33 | content: '日志审计列表查询失败', 34 | }); 35 | return error 36 | } 37 | } 38 | 39 | export { 40 | listAuditLog, 41 | searchAuditLog 42 | } -------------------------------------------------------------------------------- /src/api/cloudwatch.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getMetricTypes() { 5 | try { 6 | const res = await http('get', '/api/w8t/community/cloudwatch/metricTypes'); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '指标类型获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function getMetricNames(params) { 18 | try { 19 | const res = await http('get', '/api/w8t/community/cloudwatch/metricNames?metricType='+params.metricType); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '指标获取失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function getStatistics() { 31 | try { 32 | const res = await http('get', '/api/w8t/community/cloudwatch/statistics'); 33 | return res; 34 | } catch (error) { 35 | message.open({ 36 | type: 'error', 37 | content: '统计类型获取失败', 38 | }); 39 | return error 40 | } 41 | } 42 | 43 | async function getDimensions(params) { 44 | try { 45 | const res = await http('get', '/api/w8t/community/cloudwatch/dimensions?metricType='+params.metricType); 46 | return res; 47 | } catch (error) { 48 | message.open({ 49 | type: 'error', 50 | content: '端点类型获取失败', 51 | }); 52 | return error 53 | } 54 | } 55 | 56 | async function getRdsInstances(params) { 57 | try { 58 | const res = await http('get', '/api/w8t/community/rds/instances?datasourceId='+params.datasourceId); 59 | return res; 60 | } catch (error) { 61 | message.open({ 62 | type: 'error', 63 | content: '端点实例获取失败', 64 | }); 65 | return error 66 | } 67 | } 68 | 69 | async function getRdsClusters(params) { 70 | try { 71 | const res = await http('get', '/api/w8t/community/rds/clusters?datasourceId='+params.datasourceId); 72 | return res; 73 | } catch (error) { 74 | message.open({ 75 | type: 'error', 76 | content: '端点集群获取失败', 77 | }); 78 | return error 79 | } 80 | } 81 | 82 | export { 83 | getMetricTypes, 84 | getMetricNames, 85 | getStatistics, 86 | getDimensions, 87 | getRdsInstances, 88 | getRdsClusters 89 | } -------------------------------------------------------------------------------- /src/api/dashboard.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getFolderList(params?: any) { 5 | try { 6 | const res = await http('get', '/api/w8t/dashboard/listFolder', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '文件夹列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function getFolderInfo(params?: any) { 18 | try { 19 | const res = await http('get', '/api/w8t/dashboard/getFolder', params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '文件夹信息获取失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function getDashboardList(params) { 31 | try { 32 | const res = await http('get', '/api/w8t/dashboard/listDashboard', params); 33 | return res; 34 | } catch (error) { 35 | message.open({ 36 | type: 'error', 37 | content: '仪表盘列表获取失败', 38 | }); 39 | return error 40 | } 41 | } 42 | 43 | async function getDashboardData(params) { 44 | const queryString = Object.keys(params) 45 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 46 | .filter(Boolean) 47 | .join('&'); 48 | 49 | try { 50 | const res = await http('get', `/api/w8t/dashboard/getDashboard?${queryString}`); 51 | return res; 52 | } catch (error) { 53 | message.open({ 54 | type: 'error', 55 | content: '仪表盘数据获取失败', 56 | }); 57 | return error 58 | } 59 | } 60 | 61 | async function createDashboard(params) { 62 | try { 63 | const res = await http('post', '/api/w8t/dashboard/createDashboard', params); 64 | message.open({ 65 | type: 'success', 66 | content: '仪表盘创建成功', 67 | }); 68 | return res; 69 | } catch (error) { 70 | message.open({ 71 | type: 'error', 72 | content: '仪表盘创建失败', 73 | }); 74 | return error 75 | } 76 | } 77 | 78 | async function updateDashboard(params) { 79 | try { 80 | const res = await http('post', '/api/w8t/dashboard/updateDashboard', params); 81 | message.open({ 82 | type: 'success', 83 | content: '仪表盘更新成功', 84 | }); 85 | return res; 86 | } catch (error) { 87 | message.open({ 88 | type: 'error', 89 | content: '仪表盘更新失败', 90 | }); 91 | return error 92 | } 93 | } 94 | 95 | async function deleteDashboard(params) { 96 | try { 97 | const res = await http('post', '/api/w8t/dashboard/deleteDashboard', params); 98 | message.open({ 99 | type: 'success', 100 | content: '仪表盘删除成功', 101 | }); 102 | return res; 103 | } catch (error) { 104 | message.open({ 105 | type: 'error', 106 | content: '仪表盘删除失败', 107 | }); 108 | return error 109 | } 110 | } 111 | 112 | async function searchDashboard(params) { 113 | const queryString = Object.keys(params) 114 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 115 | .filter(Boolean) 116 | .join('&'); 117 | 118 | try { 119 | const res = await http('get', `/api/w8t/dashboard/searchDashboard?${queryString}`); 120 | return res; 121 | } catch (error) { 122 | message.open({ 123 | type: 'error', 124 | content: '仪表盘数据获取失败', 125 | }); 126 | return error 127 | } 128 | } 129 | 130 | async function createDashboardFolder(params) { 131 | try { 132 | const res = await http('post', '/api/w8t/dashboard/createFolder', params); 133 | return res; 134 | } catch (error) { 135 | message.open({ 136 | type: 'error', 137 | content: '文件夹创建失败', 138 | }); 139 | return error 140 | } 141 | } 142 | 143 | async function deleteDashboardFolder(params) { 144 | try { 145 | const res = await http('post', '/api/w8t/dashboard/deleteFolder', params); 146 | message.open({ 147 | type: 'success', 148 | content: '文件夹删除成功', 149 | }); 150 | return res; 151 | } catch (error) { 152 | message.open({ 153 | type: 'error', 154 | content: '文件夹删除失败', 155 | }); 156 | return error 157 | } 158 | } 159 | 160 | async function updateDashboardFolder(params) { 161 | try { 162 | const res = await http('post', '/api/w8t/dashboard/updateFolder', params); 163 | message.open({ 164 | type: 'success', 165 | content: '文件夹更新成功', 166 | }); 167 | return res; 168 | } catch (error) { 169 | message.open({ 170 | type: 'error', 171 | content: '文件夹更新失败', 172 | }); 173 | return error 174 | } 175 | } 176 | 177 | async function getGrafanaDashboardList(params?: any) { 178 | try { 179 | const res = await http('get', '/api/w8t/dashboard/listGrafanaDashboards', params); 180 | return res; 181 | } catch (error) { 182 | message.open({ 183 | type: 'error', 184 | content: 'Grafana仪表盘列表获取失败', 185 | }); 186 | return error 187 | } 188 | } 189 | 190 | async function getDashboardFullUrl(params?: any) { 191 | try { 192 | const res = await http('get', '/api/w8t/dashboard/getDashboardFullUrl', params); 193 | return res; 194 | } catch (error) { 195 | message.open({ 196 | type: 'error', 197 | content: 'Grafana仪表盘完整URL获取失败', 198 | }); 199 | return error 200 | } 201 | } 202 | 203 | export { 204 | getFolderList, 205 | getFolderInfo, 206 | getDashboardList, 207 | getDashboardData, 208 | createDashboard, 209 | updateDashboard, 210 | deleteDashboard, 211 | searchDashboard, 212 | createDashboardFolder, 213 | updateDashboardFolder, 214 | deleteDashboardFolder, 215 | getGrafanaDashboardList, 216 | getDashboardFullUrl, 217 | } -------------------------------------------------------------------------------- /src/api/datasource.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getDatasourceList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/datasource/dataSourceList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '数据源列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function searchDatasource(params) { 18 | try { 19 | const queryString = Object.keys(params) 20 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 21 | .filter(Boolean) 22 | .join('&'); 23 | const res = await http('get', `/api/w8t/datasource/dataSourceSearch?${queryString}`); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '数据源搜索失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function getDatasource(params) { 35 | try { 36 | const queryString = Object.keys(params) 37 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 38 | .filter(Boolean) 39 | .join('&'); 40 | const res = await http('get', `/api/w8t/datasource/dataSourceGet?${queryString}`); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '数据源搜索失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function createDatasource(params) { 52 | try { 53 | const res = await http('post', '/api/w8t/datasource/dataSourceCreate', params); 54 | message.open({ 55 | type: 'success', 56 | content: '数据源创建成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '数据源创建失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | async function updateDatasource(params) { 69 | try { 70 | const res = await http('post', '/api/w8t/datasource/dataSourceUpdate', params); 71 | message.open({ 72 | type: 'success', 73 | content: '数据源更新成功', 74 | }); 75 | return res; 76 | } catch (error) { 77 | message.open({ 78 | type: 'error', 79 | content: '数据源更新失败', 80 | }); 81 | return error 82 | } 83 | } 84 | 85 | async function deleteDatasource(params) { 86 | try { 87 | const res = await http('post', `/api/w8t/datasource/dataSourceDelete`, params); 88 | message.open({ 89 | type: 'success', 90 | content: '数据源删除成功', 91 | }); 92 | return res; 93 | } catch (error) { 94 | message.open({ 95 | type: 'error', 96 | content: '数据源删除失败', 97 | }); 98 | return error 99 | } 100 | } 101 | 102 | async function DatasourcePing(params) { 103 | try { 104 | const res = await http('post', `/api/w8t/datasource/dataSourcePing`, params); 105 | message.open({ 106 | type: 'success', 107 | content: '数据源测试通过', 108 | }); 109 | return res; 110 | } catch (error) { 111 | message.open({ 112 | type: 'error', 113 | content: '数据源测试失败', 114 | }); 115 | return error 116 | } 117 | } 118 | 119 | async function ElasticSearchData(params) { 120 | try { 121 | const res = await http('post', `/api/w8t/datasource/esSearch`, params); 122 | message.open({ 123 | type: 'success', 124 | content: '查询ES内容成功', 125 | }); 126 | return res; 127 | } catch (error) { 128 | message.open({ 129 | type: 'error', 130 | content: '查询ES内容失败', 131 | }); 132 | return error 133 | } 134 | } 135 | 136 | async function SearchViewLogsContent(params) { 137 | try { 138 | const res = await http('post', `/api/w8t/datasource/searchViewLogsContent`, params); 139 | return res; 140 | } catch (error) { 141 | message.open({ 142 | type: 'error', 143 | content: '数据预览内容查询失败', 144 | }); 145 | return error 146 | } 147 | } 148 | 149 | export { 150 | getDatasourceList, 151 | searchDatasource, 152 | createDatasource, 153 | updateDatasource, 154 | deleteDatasource, 155 | getDatasource, 156 | DatasourcePing, 157 | ElasticSearchData, 158 | SearchViewLogsContent 159 | } -------------------------------------------------------------------------------- /src/api/duty.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getDutyManagerList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/dutyManage/dutyManageList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '值班列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createDutyManager(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/dutyManage/dutyManageCreate', params); 20 | message.open({ 21 | type: 'success', 22 | content: '值班表创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '值班表创建失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateDutyManager(params) { 35 | try { 36 | const res = await http('post', '/api/w8t/dutyManage/dutyManageUpdate', params); 37 | message.open({ 38 | type: 'success', 39 | content: '值班表更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '值班表更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteDutyManager(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/dutyManage/dutyManageDelete`, params); 54 | message.open({ 55 | type: 'success', 56 | content: '值班表删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '值班表删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | async function createCalendar(params) { 69 | try { 70 | const res = await http('post', '/api/w8t/calendar/calendarCreate', params); 71 | message.open({ 72 | type: 'success', 73 | content: '日程表发布成功', 74 | }); 75 | return res; 76 | } catch (error) { 77 | message.open({ 78 | type: 'error', 79 | content: '日程表发布失败', 80 | }); 81 | return error 82 | } 83 | } 84 | 85 | async function updateCalendar(params) { 86 | try { 87 | const res = await http('post', '/api/w8t/calendar/calendarUpdate', params); 88 | message.open({ 89 | type: 'success', 90 | content: '日程表更新成功', 91 | }); 92 | return res; 93 | } catch (error) { 94 | message.open({ 95 | type: 'error', 96 | content: '日程表更新失败', 97 | }); 98 | return error 99 | } 100 | } 101 | 102 | async function searchCalendar(params) { 103 | try { 104 | const res = await http('get', '/api/w8t/calendar/calendarSearch', params); 105 | return res; 106 | } catch (error) { 107 | message.open({ 108 | type: 'error', 109 | content: '日程表查询失败', 110 | }); 111 | return error 112 | } 113 | } 114 | 115 | async function GetCalendarUsers(params) { 116 | try { 117 | const res = await http('get', '/api/w8t/calendar/getCalendarUsers', params); 118 | return res; 119 | } catch (error) { 120 | message.open({ 121 | type: 'error', 122 | content: '获取值班表用户列表失败', 123 | }); 124 | return error 125 | } 126 | } 127 | 128 | export { 129 | getDutyManagerList, 130 | createDutyManager, 131 | updateDutyManager, 132 | deleteDutyManager, 133 | createCalendar, 134 | updateCalendar, 135 | searchCalendar, 136 | GetCalendarUsers 137 | } -------------------------------------------------------------------------------- /src/api/event.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getCurEventList(params) { 5 | try { 6 | const queryString = Object.keys(params) 7 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 8 | .filter(Boolean) 9 | .join('&'); 10 | const res = await http('get', `/api/w8t/event/curEvent?${queryString}`); 11 | return res; 12 | } catch (error) { 13 | message.open({ 14 | type: 'error', 15 | content: '当前告警列表获取失败', 16 | }); 17 | return error 18 | } 19 | } 20 | 21 | async function getHisEventList(params) { 22 | try { 23 | const queryString = Object.keys(params) 24 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 25 | .filter(Boolean) 26 | .join('&'); 27 | 28 | const url = `/api/w8t/event/hisEvent?${queryString}`; 29 | const res = await http('get', url); 30 | return res; 31 | } catch (error) { 32 | message.open({ 33 | type: 'error', 34 | content: '历史告警列表获取失败', 35 | }); 36 | return error 37 | } 38 | } 39 | 40 | async function ProcessAlertEvent(params) { 41 | return await http('post', `/api/w8t/event/processAlertEvent`,params); 42 | } 43 | 44 | export { 45 | getCurEventList, 46 | getHisEventList, 47 | ProcessAlertEvent 48 | } -------------------------------------------------------------------------------- /src/api/faultCenter.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function FaultCenterList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/faultCenter/faultCenterList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '故障中心列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function FaultCenterSearch(params) { 18 | try { 19 | const res = await http('get', '/api/w8t/faultCenter/faultCenterSearch', params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '故障中心详情获取失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function FaultCenterCreate(params) { 31 | try { 32 | const res = await http('post', '/api/w8t/faultCenter/faultCenterCreate', params); 33 | message.open({ 34 | type: 'success', 35 | content: '故障中心创建成功', 36 | }); 37 | return res; 38 | } catch (error) { 39 | message.open({ 40 | type: 'error', 41 | content: `故障中心创建失败`, 42 | }); 43 | return error 44 | } 45 | } 46 | 47 | async function FaultCenterUpdate(params) { 48 | try { 49 | const res = await http('post', '/api/w8t/faultCenter/faultCenterUpdate', params); 50 | message.open({ 51 | type: 'success', 52 | content: '故障中心更新成功', 53 | }); 54 | return res; 55 | } catch (error) { 56 | message.open({ 57 | type: 'error', 58 | content: `故障中心更新失败`, 59 | }); 60 | return error 61 | } 62 | } 63 | 64 | async function FaultCenterDelete(params) { 65 | try { 66 | const res = await http('post', '/api/w8t/faultCenter/faultCenterDelete', params); 67 | message.open({ 68 | type: 'success', 69 | content: '故障中心删除成功', 70 | }); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: `故障中心删除失败`, 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | async function FaultCenterReset(params) { 82 | try { 83 | const res = await http('post', '/api/w8t/faultCenter/faultCenterReset', params); 84 | message.open({ 85 | type: 'success', 86 | content: '故障中心信息编辑成功', 87 | }); 88 | return res; 89 | } catch (error) { 90 | message.open({ 91 | type: 'error', 92 | content: `故障中心信息编辑失败`, 93 | }); 94 | return error 95 | } 96 | } 97 | 98 | export { 99 | FaultCenterList, 100 | FaultCenterSearch, 101 | FaultCenterCreate, 102 | FaultCenterUpdate, 103 | FaultCenterDelete, 104 | FaultCenterReset 105 | } -------------------------------------------------------------------------------- /src/api/kubernetes.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getKubernetesResourceList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/kubernetes/getResourceList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '获取Kubernetes资源列表失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function getKubernetesReasonList(params) { 18 | try { 19 | const res = await http('get', '/api/w8t/kubernetes/getReasonList', params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '获取Kubernetes事件类型列表失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | export { 31 | getKubernetesResourceList, 32 | getKubernetesReasonList 33 | } -------------------------------------------------------------------------------- /src/api/notice.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getNoticeList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/notice/noticeList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '通知对象列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createNotice(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/notice/noticeCreate', params); 20 | message.open({ 21 | type: 'success', 22 | content: '通知对象创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '通知对象创建失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateNotice(params) { 35 | try { 36 | const res = await http('post', '/api/w8t/notice/noticeUpdate', params); 37 | message.open({ 38 | type: 'success', 39 | content: '通知对象更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '通知对象更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteNotice(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/notice/noticeDelete`, params); 54 | message.open({ 55 | type: 'success', 56 | content: '通知对象删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '通知对象删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | async function searchNotice(params) { 69 | try { 70 | const res = await http('get', '/api/w8t/notice/noticeSearch', params); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: '搜索通知对象失败', 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | async function noticeRecordList(params) { 82 | try { 83 | const res = await http('get', '/api/w8t/notice/noticeRecordList',params); 84 | return res; 85 | } catch (error) { 86 | message.open({ 87 | type: 'error', 88 | content: '获取通知记录列表失败', 89 | }); 90 | return error 91 | } 92 | } 93 | 94 | async function noticeRecordMetric() { 95 | try { 96 | const res = await http('get', '/api/w8t/notice/noticeRecordMetric'); 97 | return res; 98 | } catch (error) { 99 | message.open({ 100 | type: 'error', 101 | content: '获取通知记录指标失败', 102 | }); 103 | return error 104 | } 105 | } 106 | 107 | export { 108 | getNoticeList, 109 | createNotice, 110 | updateNotice, 111 | deleteNotice, 112 | searchNotice, 113 | noticeRecordList, 114 | noticeRecordMetric 115 | } -------------------------------------------------------------------------------- /src/api/noticeTmpl.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getNoticeTmplList() { 5 | try { 6 | const res = await http('get', '/api/w8t/noticeTemplate/noticeTemplateList'); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '通知模版列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createNoticeTmpl(params) { 18 | try { 19 | const res = await http('post', `/api/w8t/noticeTemplate/noticeTemplateCreate`, params); 20 | message.open({ 21 | type: 'success', 22 | content: '通知模版创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '通知模版创建失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateNoticeTmpl(params) { 35 | try { 36 | const res = await http('post', `/api/w8t/noticeTemplate/noticeTemplateUpdate`, params); 37 | message.open({ 38 | type: 'success', 39 | content: '通知模版更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '通知模版更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteNoticeTmpl(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/noticeTemplate/noticeTemplateDelete`,params); 54 | message.open({ 55 | type: 'success', 56 | content: '通知模版删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '通知模版删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | async function searchNoticeTmpl(params) { 69 | try { 70 | const res = await http('get', '/api/w8t/noticeTemplate/searchNoticeTmpl', params); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: '搜索通知模版失败', 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | export { 82 | getNoticeTmplList, 83 | createNoticeTmpl, 84 | updateNoticeTmpl, 85 | deleteNoticeTmpl, 86 | searchNoticeTmpl 87 | } -------------------------------------------------------------------------------- /src/api/other.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getAllUsers(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/user/searchDutyUser', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '获取用户信息失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function getDashboardInfo(params) { 18 | try { 19 | const res = await http('get', '/api/system/getDashboardInfo', params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '获取仪表盘数据失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function getJaegerService(params) { 31 | try { 32 | const queryString = Object.keys(params) 33 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 34 | .filter(Boolean) 35 | .join('&'); 36 | const res = await http('get', `/api/w8t/c/getJaegerService?${queryString}`); 37 | return res; 38 | } catch (error) { 39 | message.open({ 40 | type: 'error', 41 | content: '获取Jaeger服务列表失败', 42 | }); 43 | return error 44 | } 45 | } 46 | 47 | async function queryPromMetrics(params) { 48 | try { 49 | const res = await http('get', `/api/w8t/datasource/promQuery`, params); 50 | return res; 51 | } catch (error) { 52 | message.open({ 53 | type: 'error', 54 | content: '查询Metrics失败', 55 | }); 56 | return error 57 | } 58 | } 59 | 60 | export { 61 | getAllUsers, 62 | getDashboardInfo, 63 | getJaegerService, 64 | queryPromMetrics 65 | } -------------------------------------------------------------------------------- /src/api/permissions.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getPermissionsList() { 5 | try { 6 | const res = await http('get', `/api/w8t/permissions/permsList`); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '权限列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | export { 18 | getPermissionsList 19 | } -------------------------------------------------------------------------------- /src/api/probing.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function ProbingList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/probing/listProbing', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '拨测列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function ProbingSearch(params) { 18 | try { 19 | const res = await http('get', '/api/w8t/probing/searchProbing', params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '拨测规则信息获取失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function ProbingCreate(params) { 31 | try { 32 | const res = await http('post', '/api/w8t/probing/createProbing', params); 33 | message.open({ 34 | type: 'success', 35 | content: '拨测规则创建成功', 36 | }); 37 | return res; 38 | } catch (error) { 39 | message.open({ 40 | type: 'error', 41 | content: '拨测规则创建失败', 42 | }); 43 | return error 44 | } 45 | } 46 | 47 | async function ProbingUpdate(params) { 48 | try { 49 | const res = await http('post', '/api/w8t/probing/updateProbing', params); 50 | message.open({ 51 | type: 'success', 52 | content: '拨测规则更新成功', 53 | }); 54 | return res; 55 | } catch (error) { 56 | message.open({ 57 | type: 'error', 58 | content: '拨测规则更新失败', 59 | }); 60 | return error 61 | } 62 | } 63 | 64 | async function ProbingDelete(params) { 65 | try { 66 | const res = await http('post', '/api/w8t/probing/deleteProbing', params); 67 | message.open({ 68 | type: 'success', 69 | content: '拨测规则删除成功', 70 | }); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: '拨测规则删除失败', 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | async function ProbingOnce(params) { 82 | try { 83 | const res = await http('post', '/api/w8t/probing/onceProbing', params); 84 | message.open({ 85 | type: 'success', 86 | content: '拨测请求提交成功!', 87 | }); 88 | return res; 89 | } catch (error) { 90 | message.open({ 91 | type: 'error', 92 | content: '拨测请求提交失败!', 93 | }); 94 | return error 95 | } 96 | } 97 | 98 | async function ProbingGetHistory(params) { 99 | return await http('get', '/api/w8t/probing/getProbingHistory', params); 100 | } 101 | 102 | export { 103 | ProbingList, 104 | ProbingSearch, 105 | ProbingCreate, 106 | ProbingUpdate, 107 | ProbingDelete, 108 | ProbingOnce, 109 | ProbingGetHistory 110 | } -------------------------------------------------------------------------------- /src/api/role.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getRoleList() { 5 | try { 6 | const res = await http('get', `/api/w8t/role/roleList`); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '角色列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createRole(params) { 18 | try { 19 | const res = await http('post', `/api/w8t/role/roleCreate`, params); 20 | message.open({ 21 | type: 'success', 22 | content: '角色创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '角色创建失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateRole(params) { 35 | try { 36 | const res = await http('post', `/api/w8t/role/roleUpdate`, params); 37 | message.open({ 38 | type: 'success', 39 | content: '角色更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '角色更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteRole(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/role/roleDelete`,params); 54 | message.open({ 55 | type: 'success', 56 | content: '角色删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '角色删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | export { 69 | getRoleList, 70 | createRole, 71 | updateRole, 72 | deleteRole 73 | } -------------------------------------------------------------------------------- /src/api/rule.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getRuleList(params) { 5 | try { 6 | const res = await http('get', `/api/w8t/rule/ruleList`, params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '规则获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createRule(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/rule/ruleCreate', params); 20 | message.open({ 21 | type: 'success', 22 | content: '创建规则成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '创建规则失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateRule(params) { 35 | try { 36 | const res = await http('post', '/api/w8t/rule/ruleUpdate', params); 37 | message.open({ 38 | type: 'success', 39 | content: '规则更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '规则更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteRule(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/rule/ruleDelete`, params); 54 | message.open({ 55 | type: 'success', 56 | content: '规则删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '规则删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | async function searchRuleInfo(params) { 69 | try { 70 | const res = await http('get', `/api/w8t/rule/ruleSearch`, params); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: '规则信息查询失败', 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | async function getRuleGroupList(params) { 82 | try { 83 | const headers = { 84 | 'TenantID': 'xxxxxxxxx' 85 | } 86 | const res = await http('get', '/api/w8t/ruleGroup/ruleGroupList', params, headers); 87 | return res; 88 | } catch (error) { 89 | message.open({ 90 | type: 'error', 91 | content: '规则组列表获取失败', 92 | }); 93 | return error 94 | } 95 | } 96 | 97 | async function createRuleGroup(params) { 98 | try { 99 | const res = await http('post', '/api/w8t/ruleGroup/ruleGroupCreate', params); 100 | message.open({ 101 | type: 'success', 102 | content: '规则组创建成功', 103 | }); 104 | return res; 105 | } catch (error) { 106 | message.open({ 107 | type: 'error', 108 | content: '创建规则组失败', 109 | }); 110 | return error 111 | } 112 | } 113 | 114 | async function updateRuleGroup(params) { 115 | try { 116 | const res = await http('post', '/api/w8t/ruleGroup/ruleGroupUpdate', params); 117 | message.open({ 118 | type: 'success', 119 | content: '规则组更新成功', 120 | }); 121 | return res; 122 | } catch (error) { 123 | message.open({ 124 | type: 'error', 125 | content: '规则组更新失败', 126 | }); 127 | return error 128 | } 129 | } 130 | 131 | async function deleteRuleGroup(params) { 132 | try { 133 | const res = await http('post', `/api/w8t/ruleGroup/ruleGroupDelete`,params); 134 | message.open({ 135 | type: 'success', 136 | content: '规则组删除成功', 137 | }); 138 | return res; 139 | } catch (error) { 140 | message.open({ 141 | type: 'error', 142 | content: '规则组删除失败', 143 | }); 144 | return error 145 | } 146 | } 147 | 148 | export { 149 | getRuleList, 150 | createRule, 151 | updateRule, 152 | deleteRule, 153 | searchRuleInfo, 154 | getRuleGroupList, 155 | createRuleGroup, 156 | updateRuleGroup, 157 | deleteRuleGroup, 158 | } -------------------------------------------------------------------------------- /src/api/ruleTmpl.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getRuleTmplList(params) { 5 | try { 6 | const queryString = Object.keys(params) 7 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 8 | .filter(Boolean) 9 | .join('&'); 10 | const res = await http('get', `/api/w8t/ruleTmpl/ruleTmplList?${queryString}`); 11 | return res; 12 | } catch (error) { 13 | message.open({ 14 | type: 'error', 15 | content: '规则模版列表获取失败', 16 | }); 17 | return error 18 | } 19 | } 20 | 21 | async function createRuleTmpl(params) { 22 | try { 23 | const res = await http('post', `/api/w8t/ruleTmpl/ruleTmplCreate`, params); 24 | message.open({ 25 | type: 'success', 26 | content: '规则模版创建成功', 27 | }); 28 | return res; 29 | } catch (error) { 30 | message.open({ 31 | type: 'error', 32 | content: '规则模版创建失败', 33 | }); 34 | return error 35 | } 36 | } 37 | 38 | async function updateRuleTmpl(params) { 39 | try { 40 | const res = await http('post', `/api/w8t/ruleTmpl/ruleTmplUpdate`, params); 41 | message.open({ 42 | type: 'success', 43 | content: '规则模版更新成功', 44 | }); 45 | return res; 46 | } catch (error) { 47 | message.open({ 48 | type: 'error', 49 | content: '规则模版更新失败', 50 | }); 51 | return error 52 | } 53 | } 54 | 55 | async function deleteRuleTmpl(params) { 56 | try { 57 | 58 | const res = await http('post', `/api/w8t/ruleTmpl/ruleTmplDelete`, params); 59 | message.open({ 60 | type: 'success', 61 | content: '规则模版删除成功', 62 | }); 63 | return res; 64 | } catch (error) { 65 | message.open({ 66 | type: 'error', 67 | content: '规则模版删除失败', 68 | }); 69 | return error 70 | } 71 | } 72 | 73 | async function getRuleTmplGroupList(params) { 74 | try { 75 | const res = await http('get', `/api/w8t/ruleTmplGroup/ruleTmplGroupList`, params); 76 | return res; 77 | } catch (error) { 78 | message.open({ 79 | type: 'error', 80 | content: '规则模版组获取失败', 81 | }); 82 | return error 83 | } 84 | } 85 | 86 | async function createRuleTmplGroup(params) { 87 | try { 88 | const res = await http('post', `/api/w8t/ruleTmplGroup/ruleTmplGroupCreate`, params); 89 | message.open({ 90 | type: 'success', 91 | content: '规则模版组创建成功', 92 | }); 93 | return res; 94 | } catch (error) { 95 | message.open({ 96 | type: 'error', 97 | content: '规则模版组创建失败', 98 | }); 99 | return error 100 | } 101 | } 102 | 103 | async function updateRuleTmplGroup(params) { 104 | try { 105 | const res = await http('post', `/api/w8t/ruleTmplGroup/ruleTmplGroupUpdate`, params); 106 | message.open({ 107 | type: 'success', 108 | content: '规则模版组更新成功', 109 | }); 110 | return res; 111 | } catch (error) { 112 | message.open({ 113 | type: 'error', 114 | content: '规则模版组更新失败', 115 | }); 116 | return error 117 | } 118 | } 119 | 120 | async function deleteRuleTmplGroup(params) { 121 | try { 122 | const res = await http('post', `/api/w8t/ruleTmplGroup/ruleTmplGroupDelete`,params); 123 | message.open({ 124 | type: 'success', 125 | content: '规则模版组删除成功', 126 | }); 127 | return res; 128 | } catch (error) { 129 | message.open({ 130 | type: 'error', 131 | content: '规则模版组删除失败', 132 | }); 133 | return error 134 | } 135 | } 136 | 137 | export { 138 | getRuleTmplList, 139 | createRuleTmpl, 140 | updateRuleTmpl, 141 | deleteRuleTmpl, 142 | getRuleTmplGroupList, 143 | createRuleTmplGroup, 144 | updateRuleTmplGroup, 145 | deleteRuleTmplGroup 146 | } -------------------------------------------------------------------------------- /src/api/settings.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getSystemSetting() { 5 | try { 6 | const res = await http('get', '/api/w8t/setting/getSystemSetting'); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '系统配置获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function saveSystemSetting(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/setting/saveSystemSetting', params); 20 | message.open({ 21 | type: 'success', 22 | content: '系统配置保存成功, 且立即生效!', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '系统配置保存失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | export { 35 | getSystemSetting, 36 | saveSystemSetting 37 | } -------------------------------------------------------------------------------- /src/api/silence.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getSilenceList(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/silence/silenceList', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '静默规则列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createSilence(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/silence/silenceCreate', params); 20 | message.open({ 21 | type: 'success', 22 | content: '静默规则创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: '静默规则创建失败', 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function updateSilence(params) { 35 | try { 36 | const res = await http('post', '/api/w8t/silence/silenceUpdate', params); 37 | message.open({ 38 | type: 'success', 39 | content: '静默规则更新成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '静默规则更新失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | async function deleteSilence(params) { 52 | try { 53 | const res = await http('post', `/api/w8t/silence/silenceDelete`, params); 54 | message.open({ 55 | type: 'success', 56 | content: '静默规则删除成功', 57 | }); 58 | return res; 59 | } catch (error) { 60 | message.open({ 61 | type: 'error', 62 | content: '静默规则删除失败', 63 | }); 64 | return error 65 | } 66 | } 67 | 68 | export { 69 | getSilenceList, 70 | createSilence, 71 | updateSilence, 72 | deleteSilence 73 | } -------------------------------------------------------------------------------- /src/api/subscribe.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function listSubscribe(params) { 5 | try { 6 | const res = await http('get', '/api/w8t/subscribe/listSubscribe', params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '订阅列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function createSubscribe(params) { 18 | try { 19 | const res = await http('post', '/api/w8t/subscribe/createSubscribe', params); 20 | message.open({ 21 | type: 'success', 22 | content: '订阅规则创建成功', 23 | }); 24 | return res; 25 | } catch (error) { 26 | message.open({ 27 | type: 'error', 28 | content: `订阅规则创建失败`, 29 | }); 30 | return error 31 | } 32 | } 33 | 34 | async function deleteSubscribe(params) { 35 | try { 36 | const res = await http('post', `/api/w8t/subscribe/deleteSubscribe`, params); 37 | message.open({ 38 | type: 'success', 39 | content: '订阅规则删除成功', 40 | }); 41 | return res; 42 | } catch (error) { 43 | message.open({ 44 | type: 'error', 45 | content: '订阅规则删除失败', 46 | }); 47 | return error 48 | } 49 | } 50 | 51 | export { 52 | listSubscribe, 53 | createSubscribe, 54 | deleteSubscribe 55 | } -------------------------------------------------------------------------------- /src/api/tenant.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getTenantList(params) { 5 | try { 6 | const res = await http('get', `/api/w8t/tenant/getTenantList`,params); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '租户列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | async function getTenant(params) { 18 | try { 19 | const res = await http('get', `/api/w8t/tenant/getTenant`, params); 20 | return res; 21 | } catch (error) { 22 | message.open({ 23 | type: 'error', 24 | content: '租户信息获取失败', 25 | }); 26 | return error 27 | } 28 | } 29 | 30 | async function createTenant(params) { 31 | try { 32 | const res = await http('post', `/api/w8t/tenant/createTenant`, params); 33 | message.open({ 34 | type: 'success', 35 | content: '租户创建成功', 36 | }); 37 | return res; 38 | } catch (error) { 39 | message.open({ 40 | type: 'error', 41 | content: '租户创建失败', 42 | }); 43 | return error 44 | } 45 | } 46 | 47 | async function updateTenant(params) { 48 | try { 49 | const res = await http('post', `/api/w8t/tenant/updateTenant`, params); 50 | message.open({ 51 | type: 'success', 52 | content: '租户更新成功', 53 | }); 54 | return res; 55 | } catch (error) { 56 | message.open({ 57 | type: 'error', 58 | content: '租户更新失败', 59 | }); 60 | return error 61 | } 62 | } 63 | 64 | async function deleteTenant(params) { 65 | try { 66 | const res = await http('post', `/api/w8t/tenant/deleteTenant`, params); 67 | message.open({ 68 | type: 'success', 69 | content: '租户删除成功', 70 | }); 71 | return res; 72 | } catch (error) { 73 | message.open({ 74 | type: 'error', 75 | content: '租户删除失败', 76 | }); 77 | return error 78 | } 79 | } 80 | 81 | async function getUsersForTenant(params) { 82 | try { 83 | const res = await http('get', `/api/w8t/tenant/getUsersForTenant`, params); 84 | return res; 85 | } catch (error) { 86 | message.open({ 87 | type: 'error', 88 | content: '租户成员列表获取失败', 89 | }); 90 | return error 91 | } 92 | } 93 | 94 | async function addUsersToTenant(params) { 95 | try { 96 | const res = await http('post', `/api/w8t/tenant/addUsersToTenant`, params); 97 | return res; 98 | } catch (error) { 99 | message.open({ 100 | type: 'error', 101 | content: '向租户添加成员失败', 102 | }); 103 | return error 104 | } 105 | } 106 | 107 | async function delUsersOfTenant(params) { 108 | try { 109 | const res = await http('post', `/api/w8t/tenant/delUsersOfTenant`, params); 110 | return res; 111 | } catch (error) { 112 | message.open({ 113 | type: 'error', 114 | content: '删除租户成员失败', 115 | }); 116 | return error 117 | } 118 | } 119 | 120 | async function changeTenantUserRole(params) { 121 | try { 122 | const res = await http('post', `/api/w8t/tenant/changeTenantUserRole`, params); 123 | return res; 124 | } catch (error) { 125 | message.open({ 126 | type: 'error', 127 | content: '修改租户成员角色失败', 128 | }); 129 | return error 130 | } 131 | } 132 | 133 | export { 134 | getTenantList, 135 | createTenant, 136 | updateTenant, 137 | deleteTenant, 138 | getTenant, 139 | getUsersForTenant, 140 | addUsersToTenant, 141 | delUsersOfTenant, 142 | changeTenantUserRole 143 | } -------------------------------------------------------------------------------- /src/api/user.jsx: -------------------------------------------------------------------------------- 1 | import http from '../utils/http'; 2 | import { message } from 'antd'; 3 | 4 | async function getUserList() { 5 | try { 6 | const res = await http('get', `/api/w8t/user/userList`); 7 | return res; 8 | } catch (error) { 9 | message.open({ 10 | type: 'error', 11 | content: '用户列表获取失败', 12 | }); 13 | return error 14 | } 15 | } 16 | 17 | 18 | async function loginUser(params) { 19 | try { 20 | const res = await http('post', `/api/system/login`, params); 21 | return res; 22 | } catch (error) { 23 | message.open({ 24 | type: 'error', 25 | content: '用户不存在或密码错误', 26 | }); 27 | return error 28 | } 29 | } 30 | 31 | async function registerUser(params) { 32 | try { 33 | const res = await http('post', `/api/system/register`, params); 34 | message.open({ 35 | type: 'success', 36 | content: '用户注册成功', 37 | }); 38 | return res; 39 | } catch (error) { 40 | message.open({ 41 | type: 'error', 42 | content: '用户注册失败', 43 | }); 44 | return error 45 | } 46 | } 47 | 48 | async function updateUser(params) { 49 | try { 50 | const res = await http('post', `/api/w8t/user/userUpdate`, params); 51 | message.open({ 52 | type: 'success', 53 | content: '用户更新成功', 54 | }); 55 | return res; 56 | } catch (error) { 57 | message.open({ 58 | type: 'error', 59 | content: '用户更新失败', 60 | }); 61 | return error 62 | } 63 | } 64 | 65 | async function deleteUser(params) { 66 | try { 67 | const res = await http('post', `/api/w8t/user/userDelete`,params); 68 | message.open({ 69 | type: 'success', 70 | content: '用户删除成功', 71 | }); 72 | return res; 73 | } catch (error) { 74 | message.open({ 75 | type: 'error', 76 | content: '用户删除失败', 77 | }); 78 | return error 79 | } 80 | } 81 | 82 | async function getUserInfo() { 83 | try { 84 | const res = await http('get', `/api/system/userInfo`); 85 | return res; 86 | } catch (error) { 87 | message.open({ 88 | type: 'error', 89 | content: '用户信息获取失败', 90 | }); 91 | return error 92 | } 93 | } 94 | 95 | async function checkUser(params) { 96 | try { 97 | const queryString = Object.keys(params) 98 | .map(key => params[key] !== undefined ? `${key}=${params[key]}` : '') 99 | .filter(Boolean) 100 | .join('&'); 101 | const res = await http('get', `/api/system/checkUser?${queryString}`); 102 | return res; 103 | } catch (error) { 104 | return error 105 | } 106 | } 107 | 108 | async function changeUserPass(params) { 109 | try { 110 | const res = await http('post', `/api/w8t/user/userChangePass`, params); 111 | message.open({ 112 | type: 'success', 113 | content: '修改密码成功', 114 | }); 115 | return res; 116 | } catch (error) { 117 | message.open({ 118 | type: 'error', 119 | content: '修改密码失败', 120 | }); 121 | return error 122 | } 123 | } 124 | 125 | async function searchUser(params) { 126 | try { 127 | const res = await http('get', '/api/w8t/user/searchUser', params); 128 | return res; 129 | } catch (error) { 130 | message.open({ 131 | type: 'error', 132 | content: '获取用户信息失败', 133 | }); 134 | return error 135 | } 136 | } 137 | 138 | export { 139 | getUserList, 140 | loginUser, 141 | registerUser, 142 | updateUser, 143 | deleteUser, 144 | checkUser, 145 | getUserInfo, 146 | changeUserPass, 147 | searchUser 148 | } -------------------------------------------------------------------------------- /src/components/context/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState, useContext } from 'react'; 2 | 3 | // 创建一个 Context 4 | const DataContext = createContext(); 5 | 6 | // 创建一个提供者组件 7 | export const DataProvider = ({ children }) => { 8 | const [data, setData] = useState(''); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | }; 16 | 17 | // 自定义 hook,方便使用 Context 18 | export const useData = () => { 19 | return useContext(DataContext); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/index.css: -------------------------------------------------------------------------------- 1 | .ant-select-selector { 2 | border: none; 3 | } 4 | 5 | .ant-card:active { 6 | transform: scale(0.98); /* 轻微缩小卡片 */ 7 | } 8 | 9 | .ant-menu-light.ant-menu-root.ant-menu-inline { 10 | border-inline-end: none; 11 | } -------------------------------------------------------------------------------- /src/context/RuleContext.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext, useState } from 'react'; 2 | 3 | const RuleContext = createContext(); 4 | 5 | export const ContextProvider = ({ children }) => { 6 | const [ruleTemplate, setRuleTemplate] = useState(null); 7 | 8 | return ( 9 | 10 | {children} 11 | 12 | ); 13 | }; 14 | 15 | export const useRule = () => useContext(RuleContext); -------------------------------------------------------------------------------- /src/img/WatchAlert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/src/img/WatchAlert.png -------------------------------------------------------------------------------- /src/img/github_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/src/img/github_logo.png -------------------------------------------------------------------------------- /src/img/logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opsre/WatchAlert-web/85e8f39a1d4c2c8884eaee4bd2257b357a0f5716/src/img/logo.jpeg -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | :root{ 2 | height: 100vh; 3 | width: 100%; 4 | } 5 | #root { 6 | height: 100vh; 7 | width: 100%; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | padding: 0; 13 | height: 100vh; 14 | width: 100%; 15 | background-color: rgb(238, 240, 243); 16 | } 17 | 18 | *::-webkit-scrollbar { 19 | display: none; 20 | } 21 | 22 | * { 23 | scrollbar-width: none; 24 | } 25 | 26 | * { 27 | -ms-overflow-style: none; 28 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import { BrowserRouter } from 'react-router-dom'; 4 | import App from './App.jsx'; 5 | import { ConfigProvider } from 'antd'; 6 | import zhCN from 'antd/es/locale/zh_CN.js'; 7 | 8 | ReactDOM.createRoot(document.getElementById('root')).render( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/pages/alert/assets/event.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/assets/log.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/assets/metric.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/assets/trace.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/preview/searchViewLogs.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { Spin, Tag, Divider, Empty } from "antd"; 3 | import {SearchViewLogsContent} from "../../../api/datasource"; 4 | 5 | export const SearchViewLogs = ({ type, datasourceId, index, query }) => { 6 | const [logs, setLogs] = useState([]); 7 | const [loading, setLoading] = useState(false); 8 | const [error, setError] = useState(null); 9 | 10 | useEffect(() => { 11 | const fetchLogs = async () => { 12 | try { 13 | setLoading(true); 14 | setError(null); 15 | const { code, data, msg } = await SearchViewLogsContent({ 16 | type, 17 | datasourceId, 18 | index, 19 | query 20 | }); 21 | 22 | if (code === 200) { 23 | setLogs(data || []); 24 | } else { 25 | setError(msg || 'Failed to load logs'); 26 | } 27 | } catch (err) { 28 | setError('Network error occurred'); 29 | console.error('Fetch error:', err); 30 | } finally { 31 | setLoading(false); 32 | } 33 | }; 34 | 35 | fetchLogs(); 36 | }, []); 37 | 38 | const renderLogMessage = (message) => { 39 | try { 40 | // 如果 message 是对象,就格式化显示 JSON 41 | const prettyJson = JSON.stringify(message, null, 2); 42 | 43 | return ( 44 |
 54 |                 {prettyJson}
 55 |             
56 | ); 57 | } catch (e) { 58 | // 如果不是对象或无法转换为 JSON,则显示原始文本 59 | return ( 60 |
67 | Invalid Format 68 |
 69 |                     {String(message)}
 70 |                 
71 |
72 | ); 73 | } 74 | }; 75 | 76 | const renderLogItem = (item, index) => ( 77 | <> 78 | {item.ProviderName} 79 | {item.Message?.length || 0} messages 80 | 81 | 82 |
83 |

Metadata

84 |
85 | {Object.entries(item.Metric || {}).map(([key, value]) => ( 86 | 87 | {key}: {value} 88 | 89 | ))} 90 |
91 |
92 | 93 | 94 | 95 |
96 |

Log Messages

97 | {item.Message?.length > 0 ? ( 98 |
99 | {item.Message.map((msg, i) => ( 100 |
{renderLogMessage(msg)}
101 | ))} 102 |
103 | ) : ( 104 | 105 | )} 106 |
107 | 108 | ); 109 | 110 | return ( 111 |
112 | {loading ? ( 113 |
119 | 120 |
121 | ) : error ? ( 122 |
128 | 129 |
130 | ) : logs.length === 0 ? ( 131 |
137 | 138 |
139 | ) : ( 140 |
144 | {logs.map(renderLogItem)} 145 |
146 | )} 147 |
148 | ); 149 | }; -------------------------------------------------------------------------------- /src/pages/alert/rule/img/AWSlogo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/rule/img/ElasticSearch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/rule/img/Kubernetes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/rule/img/Prometheus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/rule/img/alicloud.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/alert/rule/index.css: -------------------------------------------------------------------------------- 1 | .rule-config-container { 2 | border: 1px solid #ccc; 3 | padding: 16px; 4 | border-radius: 4px; 5 | margin-top: 10px; 6 | } 7 | 8 | .log-rule-config-container { 9 | border: 1px solid #ccc; 10 | padding: 16px; 11 | border-radius: 4px; 12 | margin-top: 10px; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .rule-item { 17 | display: flex; 18 | margin-bottom: 10px; 19 | } 20 | 21 | .rule-content { 22 | display: flex; 23 | } 24 | 25 | .duration-input { 26 | display: flex; 27 | margin-top: -20px; 28 | align-items: center; 29 | } 30 | 31 | .action-buttons { 32 | display: flex; 33 | align-items: center; 34 | justify-content: flex-end; 35 | margin-right: -15px; 36 | margin-top: -10px; 37 | } 38 | 39 | 40 | .scroll-container { 41 | max-height: 460px; /* 根据需要调整 */ 42 | overflow-y: auto; 43 | overflow-x: auto; /* 添加横向滚动 */ 44 | border: 1px solid #ddd; 45 | /*padding: 8px; !* 增加内部边距 *!*/ 46 | /*white-space: nowrap; !* 防止内容自动换行 *!*/ 47 | } 48 | 49 | .list-item-content { 50 | display: flex; 51 | justify-content: space-between; 52 | width: 100%; 53 | } 54 | 55 | .value { 56 | margin-left: auto; 57 | padding-left: 20px; /* 增加间距以使内容更易读 */ 58 | } 59 | 60 | /* 状态容器 */ 61 | .status-container { 62 | display: flex; 63 | align-items: center; 64 | gap: 8px; 65 | } 66 | 67 | /* 小圆点 */ 68 | .status-dot { 69 | width: 8px; 70 | height: 8px; 71 | border-radius: 50%; 72 | position: relative; 73 | } 74 | 75 | /* 启用状态的小圆点 */ 76 | .status-enabled { 77 | background-color: #52c41a; /* 绿色 */ 78 | animation: pulse-enabled 1.5s infinite; 79 | } 80 | 81 | /* 禁用状态的小圆点 */ 82 | .status-disabled { 83 | background-color: #ff4d4f; /* 红色 */ 84 | animation: pulse-disabled 1.5s infinite; 85 | } 86 | 87 | /* 启用状态动态效果 */ 88 | @keyframes pulse-enabled { 89 | 0% { 90 | box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.4); 91 | } 92 | 70% { 93 | box-shadow: 0 0 0 10px rgba(82, 196, 26, 0); 94 | } 95 | 100% { 96 | box-shadow: 0 0 0 0 rgba(82, 196, 26, 0); 97 | } 98 | } 99 | 100 | /* 禁用状态动态效果 */ 101 | @keyframes pulse-disabled { 102 | 0% { 103 | box-shadow: 0 0 0 0 rgba(196, 26, 26, 0.4); 104 | } 105 | 70% { 106 | box-shadow: 0 0 0 10px rgba(82, 196, 26, 0); 107 | } 108 | 100% { 109 | box-shadow: 0 0 0 0 rgba(82, 196, 26, 0); 110 | } 111 | } -------------------------------------------------------------------------------- /src/pages/alert/ruleGroup/AlertRuleGroupCreateModal.jsx: -------------------------------------------------------------------------------- 1 | import { createRuleGroup, updateRuleGroup } from '../../../api/rule' 2 | import { Modal, Form, Input, Button, message } from 'antd' 3 | import React, { useState, useEffect } from 'react' 4 | 5 | const MyFormItemContext = React.createContext([]) 6 | 7 | function toArr(str) { 8 | return Array.isArray(str) ? str : [str] 9 | } 10 | 11 | const MyFormItem = ({ name, ...props }) => { 12 | const prefixPath = React.useContext(MyFormItemContext) 13 | const concatName = name !== undefined ? [...prefixPath, ...toArr(name)] : undefined 14 | return 15 | } 16 | 17 | export const AlertRuleGroupCreateModal = ({ visible, onClose, selectedRow, type, handleList, pagination}) => { 18 | const [form] = Form.useForm() 19 | 20 | // 禁止输入空格 21 | const [spaceValue, setSpaceValue] = useState('') 22 | 23 | const handleInputChange = (e) => { 24 | // 移除输入值中的空格 25 | const newValue = e.target.value.replace(/\s/g, '') 26 | setSpaceValue(newValue) 27 | } 28 | 29 | const handleKeyPress = (e) => { 30 | // 阻止空格键的默认行为 31 | if (e.key === ' ') { 32 | e.preventDefault() 33 | } 34 | } 35 | 36 | useEffect(() => { 37 | if (selectedRow) { 38 | form.setFieldsValue({ 39 | id: selectedRow.id, 40 | name: selectedRow.name, 41 | description: selectedRow.description, 42 | }) 43 | } 44 | 45 | }, [selectedRow, form]) 46 | 47 | const handleCreate = async (data) => { 48 | try { 49 | await createRuleGroup(data) 50 | handleList(pagination.index,pagination.size) 51 | } catch (error) { 52 | console.error(error) 53 | } 54 | } 55 | 56 | const handleUpdate = async (data) => { 57 | try { 58 | await updateRuleGroup(data) 59 | handleList(pagination.index,pagination.size) 60 | } catch (error) { 61 | console.error(error) 62 | } 63 | } 64 | 65 | const handleFormSubmit = async (values) => { 66 | 67 | if (type === 'create') { 68 | await handleCreate(values) 69 | } 70 | 71 | if (type === 'update') { 72 | const newValues = { 73 | ...values, 74 | tenantId: selectedRow.tenantId, 75 | id: selectedRow.id 76 | } 77 | await handleUpdate(newValues) 78 | } 79 | 80 | onClose() 81 | } 82 | 83 | return ( 84 | 85 |
86 | 93 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
104 | 113 |
114 |
115 |
116 | ) 117 | } -------------------------------------------------------------------------------- /src/pages/alert/tmplGroup/RuleTemplateGroupCreateModal.jsx: -------------------------------------------------------------------------------- 1 | import { Modal, Form, Input, Button } from 'antd' 2 | import React, { useState, useEffect } from 'react' 3 | import {createRuleTmplGroup, updateRuleTmplGroup} from '../../../api/ruleTmpl' 4 | 5 | const MyFormItemContext = React.createContext([]) 6 | 7 | function toArr(str) { 8 | return Array.isArray(str) ? str : [str] 9 | } 10 | 11 | const MyFormItem = ({ name, ...props }) => { 12 | const prefixPath = React.useContext(MyFormItemContext) 13 | const concatName = name !== undefined ? [...prefixPath, ...toArr(name)] : undefined 14 | return 15 | } 16 | 17 | const RuleTemplateGroupCreateModal = ({ visible, onClose, selectedRow, openType, tmplType, handleList }) => { 18 | const [form] = Form.useForm() 19 | 20 | // 禁止输入空格 21 | const [spaceValue, setSpaceValue] = useState('') 22 | 23 | const handleInputChange = (e) => { 24 | // 移除输入值中的空格 25 | const newValue = e.target.value.replace(/\s/g, '') 26 | setSpaceValue(newValue) 27 | } 28 | 29 | const handleKeyPress = (e) => { 30 | // 阻止空格键的默认行为 31 | if (e.key === ' ') { 32 | e.preventDefault() 33 | } 34 | } 35 | 36 | useEffect(() => { 37 | if (selectedRow) { 38 | form.setFieldsValue({ 39 | id: selectedRow.id, 40 | name: selectedRow.name, 41 | type: selectedRow.type, 42 | description: selectedRow.description, 43 | }) 44 | } 45 | 46 | }, [selectedRow, form]) 47 | 48 | const handleCreate = async (data) => { 49 | try { 50 | const params = { 51 | ...data, 52 | type: tmplType, 53 | } 54 | await createRuleTmplGroup(params) 55 | handleList() 56 | } catch (error) { 57 | console.error(error) 58 | } 59 | } 60 | 61 | const handleUpdate = async (data) => { 62 | try { 63 | const params = { 64 | ...data, 65 | id: selectedRow.id, 66 | type: selectedRow.type, 67 | } 68 | await updateRuleTmplGroup(params) 69 | handleList() 70 | } catch (error) { 71 | console.error(error) 72 | } 73 | } 74 | 75 | const handleFormSubmit = async (values) => { 76 | if (openType === 'create') { 77 | await handleCreate(values) 78 | } 79 | 80 | if (openType === 'update') { 81 | await handleUpdate(values) 82 | } 83 | 84 | // 关闭弹窗 85 | onClose() 86 | } 87 | 88 | return ( 89 | 90 |
91 | 94 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
105 | 114 |
115 |
116 |
117 | ) 118 | } 119 | 120 | export default RuleTemplateGroupCreateModal -------------------------------------------------------------------------------- /src/pages/chart/noticeMetricChart.jsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { 5 | Area, 6 | AreaChart, 7 | CartesianGrid, 8 | XAxis, 9 | YAxis, 10 | Tooltip, 11 | Legend, 12 | ResponsiveContainer, 13 | } from "recharts" 14 | 15 | import { 16 | Typography, 17 | } from "antd" 18 | 19 | const { Text } = Typography 20 | 21 | // 告警等级颜色配置 22 | const SEVERITY_COLORS = { 23 | P0: '#ff4d4f', 24 | P1: '#faad14', 25 | P2: '#b0e1fb' 26 | } 27 | 28 | export const NoticeMetricChart = ({ data }) => { 29 | if (!data || !data.date || !data.series) { 30 | return ( 31 |
32 | 暂无图表数据 33 |
34 | ) 35 | } 36 | 37 | // 将接口返回的数据转换成 recharts 支持的格式 38 | const chartData = data.date.map((date, index) => ({ 39 | name: date, 40 | P0: data.series.p0?.[index] ?? 0, 41 | P1: data.series.p1?.[index] ?? 0, 42 | P2: data.series.p2?.[index] ?? 0, 43 | })) 44 | 45 | return ( 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 67 | { 70 | const date = new Date(value) 71 | return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}` 72 | }} 73 | axisLine={true} 74 | tickLine={false} 75 | tickMargin={8} 76 | /> 77 | 82 | 83 | { 94 | const date = new Date(label) 95 | return 日期: {date.getFullYear()}-{date.getMonth() + 1}-{date.getDate()} 96 | }} 97 | formatter={(value, name) => [value, name]} 98 | /> 99 | 100 | 101 | 102 | 110 | 118 | 126 | 127 | 128 | ) 129 | } -------------------------------------------------------------------------------- /src/pages/dashboards/dashboard/iframe.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { getDashboardFullUrl, getFolderInfo} from '../../../api/dashboard'; 3 | import { useParams } from 'react-router-dom' 4 | 5 | export const GrafanaDashboardComponent = () => { 6 | const { fid,did } = useParams() 7 | const [iframeSrc, setIframeSrc] = useState('') 8 | 9 | useEffect(() => { 10 | run(); 11 | }, []); 12 | 13 | const run = async () => { 14 | try { 15 | const fParams = { 16 | id: fid 17 | } 18 | const resInfo = await getFolderInfo(fParams) 19 | const params = { 20 | theme: resInfo.data.theme, 21 | grafanaHost: resInfo.data.grafanaHost, 22 | grafanaDashboardUid: did 23 | } 24 | const res = await getDashboardFullUrl(params) 25 | setIframeSrc(res.data) 26 | } catch (error) { 27 | console.error(error) 28 | } 29 | } 30 | 31 | return ( 32 | <> 33 |
Loading...
34 |
35 |