diff --git a/package.json b/package.json index 39b4f26..5a6596c 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "moment": "^2.30.1", "prom-client": "^15.1.0", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-fast-marquee": "^1.6.5", "react-helmet": "^6.1.0", diff --git a/src/api/duty.jsx b/src/api/duty.jsx index 6d1eaaa..25daa62 100644 --- a/src/api/duty.jsx +++ b/src/api/duty.jsx @@ -112,6 +112,19 @@ async function searchCalendar(params) { } } +async function GetCalendarUsers(params) { + try { + const res = await http('get', '/api/w8t/calendar/getCalendarUsers', params); + return res; + } catch (error) { + message.open({ + type: 'error', + content: '获取值班表用户列表失败', + }); + return error + } +} + export { getDutyManagerList, createDutyManager, @@ -119,5 +132,6 @@ export { deleteDutyManager, createCalendar, updateCalendar, - searchCalendar + searchCalendar, + GetCalendarUsers } \ No newline at end of file diff --git a/src/pages/alert/rule/create.jsx b/src/pages/alert/rule/create.jsx index 17321d6..8638626 100644 --- a/src/pages/alert/rule/create.jsx +++ b/src/pages/alert/rule/create.jsx @@ -73,7 +73,7 @@ export const AlertRule = ({ type }) => { const [enabled, setEnabled] = useState(true) // 设置初始状态为 true const [recoverNotify,setRecoverNotify] = useState(true) const [alarmAggregation,setAlarmAggregation] = useState(true) - const [selectedType, setSelectedType] = useState(null) // 数据源类型 + const [selectedType, setSelectedType] = useState(0) // 数据源类型 const [datasourceOptions, setDatasourceOptions] = useState([]) // 数据源列表 const [selectedItems, setSelectedItems] = useState([]) //选择数据源 const [noticeLabels, setNoticeLabels] = useState([]) // noAice Lable @@ -85,7 +85,7 @@ export const AlertRule = ({ type }) => { const [severityValue, setSeverityValue] = useState(1) const [jaegerServiceList, setJaegerServiceList] = useState([]) - const [selectedCard, setSelectedCard] = useState(null); + const [selectedCard, setSelectedCard] = useState(0); const [exprRule, setExprRule] = useState([{}]) // 初始化时间数据的状态 const [week,setWeek] = useState(null) @@ -144,32 +144,45 @@ export const AlertRule = ({ type }) => { useEffect(() => { if (ruleTemplate) { // 使用模板数据初始化表单 - type = "tmpl"; form.setFieldsValue(ruleTemplate); - setPromQL(ruleTemplate.prometheusConfig.promQL) - setExprRule(ruleTemplate.prometheusConfig.rules) - } - }, [ruleTemplate]); - - useEffect(() => { - const handleSearchRuleInfo = async ()=>{ - try { - const params = { - ruleGroupId: id, - ruleId: ruleId - }; - const res = await searchRuleInfo(params); - setSelectedRow(res.data); // 更新状态 - initBasicInfo(res.data) - } catch (error) { - console.error('Error fetching rule info:', error); - } finally { - setLoading(false); // 请求完成后设置 loading 状态 + setPromQL(ruleTemplate.prometheusConfig.promQL); + setExprRule(ruleTemplate.prometheusConfig.rules); + + const datasourceTypeMap = { + "Prometheus": 0, + "Loki": 1, + "AliCloudSLS": 2, + "Jaeger": 3, + "CloudWatch": 4, + "VictoriaMetrics": 5, + "KubernetesEvent": 6, + "ElasticSearch": 7 + }; + + const t = datasourceTypeMap[ruleTemplate.datasourceType] || 0; + setSelectedType(t); + setSelectedCard(t); + type = 'tmpl' + } else { + const handleSearchRuleInfo = async ()=>{ + try { + const params = { + ruleGroupId: id, + ruleId: ruleId + }; + const res = await searchRuleInfo(params); + setSelectedRow(res.data); // 更新状态 + initBasicInfo(res.data) + } catch (error) { + console.error('Error fetching rule info:', error); + } finally { + setLoading(false); // 请求完成后设置 loading 状态 + } } - } - if (type === "edit"){ - handleSearchRuleInfo() + if (type === "edit"){ + handleSearchRuleInfo() + } } }, []) @@ -1034,7 +1047,7 @@ export const AlertRule = ({ type }) => {
-
diff --git a/src/pages/alert/tmpl/index.jsx b/src/pages/alert/tmpl/index.jsx index cecc4b9..05e2207 100644 --- a/src/pages/alert/tmpl/index.jsx +++ b/src/pages/alert/tmpl/index.jsx @@ -181,6 +181,8 @@ export const RuleTemplate = () => { ruleGroupName: selectedRuleGroup.label }; + console.log(templateData) + // 将数据存储到 Context 中 setRuleTemplate(templateData); diff --git a/src/pages/duty/calendar/CreateCalendar.jsx b/src/pages/duty/calendar/CreateCalendar.jsx index 5675077..76b02ed 100644 --- a/src/pages/duty/calendar/CreateCalendar.jsx +++ b/src/pages/duty/calendar/CreateCalendar.jsx @@ -1,19 +1,35 @@ -import React, { useState } from 'react' -import { Form, Modal, Divider, InputNumber, DatePicker, Select, Button, message } from 'antd' +import React, {useEffect, useState} from 'react' +import {Form, Modal, InputNumber, DatePicker, Select, Button, List, Avatar, Space, Drawer, Input} from 'antd' +import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd' +import { PlusOutlined, DeleteOutlined, MenuOutlined } from '@ant-design/icons' import { getAllUsers } from '../../../api/other.jsx' -import { createCalendar } from '../../../api/duty' +import {createCalendar, GetCalendarUsers} from '../../../api/duty' +import Search from "antd/es/input/Search"; export const CreateCalendarModal = ({ visible, onClose, dutyId }) => { const { Option } = Select const [form] = Form.useForm() - const [selectedItems, setSelectedItems] = useState([]) const [selectedMonth, setSelectedMonth] = useState(null) const [dutyPeriod, setDutyPeriod] = useState(1) const [filteredOptions, setFilteredOptions] = useState([]) const [dateType, setDateType] = useState('day') + const [selectedUsers, setSelectedUsers] = useState([]) + const [searchVisible, setSearchVisible] = useState(false) - const handleSelectChange = (_, value) => { - setSelectedItems(value) + useEffect(() => { + handleGetCalendarUsers() + }, [visible]) + + const handleGetCalendarUsers = async () =>{ + try { + const params = { + dutyId: dutyId + } + const res = await GetCalendarUsers(params) + setSelectedUsers(res.data) + } catch (error) { + console.error(error) + } } const onChangeDate = (date, dateString) => { @@ -49,19 +65,153 @@ export const CreateCalendarModal = ({ visible, onClose, dutyId }) => { } } + const onSearchDutyUser = (query) =>{ + // 确保 query 是一个有效的字符串 + if (!query || typeof query !== "string") { + handleSearchDutyUser() + return; + } + + // 过滤 filteredOptions + const filtered = filteredOptions.filter((item) => + item.username.toLowerCase().includes(query.toLowerCase()) + ); + + // 更新过滤后的结果 + setFilteredOptions(filtered); + } + + const handleDragEnd = (result) => { + if (!result.destination) return + + const items = Array.from(selectedUsers) + const [reorderedItem] = items.splice(result.source.index, 1) + items.splice(result.destination.index, 0, reorderedItem) + + setSelectedUsers(items) + } + + const handleDeleteUser = (index) => { + const newUsers = selectedUsers.filter((_, idx) => idx !== index) + setSelectedUsers(newUsers) + } + + const SelectUserModal = () => ( + setSearchVisible(false)} + footer={null} + styles={{ body: { maxHeight: 'calc(100vh - 300px)', overflowY: 'auto' } }} + > + + !selectedUsers.find(user => user.userid === option.userid) + )} + renderItem={item => ( + { + setSelectedUsers([...selectedUsers, item]) + setSearchVisible(false) + }} + style={{ cursor: 'pointer' }} + > + {item.username[0]}} + title={item.username} + /> + + )} + /> + + ) + + const DutyUserList = () => ( + +
+ + + + + {(provided) => ( +
+ {selectedUsers.map((user, index) => ( + + {(provided) => ( +
+ + + + + {user.username[0]} + {user.username} +
+ )} +
+ ))} + {provided.placeholder} +
+ )} +
+
+
+
+ ) const generateCalendar = () => { - if (selectedMonth && dutyPeriod && selectedItems.length > 0) { + if (selectedMonth && dutyPeriod && selectedUsers.length > 0) { const startDate = new Date(selectedMonth) const endDate = new Date(startDate) - endDate.setDate(endDate.getDate() + (dutyPeriod * selectedItems.length) - 1) + endDate.setDate(endDate.getDate() + (dutyPeriod * selectedUsers.length) - 1) const calendarData = { dutyId: dutyId, month: selectedMonth, dutyPeriod: dutyPeriod, dateType: dateType, - users: selectedItems.map((item) => ({ username: item.value, userid: item.userid })), + users: selectedUsers.map((user) => ({ + username: user.username, + userid: user.userid + })), } handleFormSubmit(calendarData) @@ -71,15 +221,7 @@ export const CreateCalendarModal = ({ visible, onClose, dutyId }) => { } return ( - - - +
{ /> - - - + - -
+
+ +
+ + ) } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7734924..f705f4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1377,6 +1377,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.15.4": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6": version "7.23.8" resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650" @@ -2559,6 +2566,14 @@ dependencies: "@types/node" "*" +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.6" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010" + integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.npmmirror.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -2655,6 +2670,16 @@ dependencies: "@types/react" "*" +"@types/react-redux@^7.1.20": + version "7.1.34" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e" + integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react@*": version "17.0.39" resolved "https://registry.npmmirror.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce" @@ -4321,6 +4346,13 @@ css-blank-pseudo@^3.0.3: dependencies: postcss-selector-parser "^6.0.9" +css-box-model@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" + integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== + dependencies: + tiny-invariant "^1.0.6" + css-declaration-sorter@^6.0.3: version "6.1.4" resolved "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" @@ -6240,6 +6272,13 @@ he@^1.2.0: resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hoopy@^0.1.4: version "0.1.4" resolved "https://registry.npmmirror.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -7836,6 +7875,11 @@ memfs@^3.1.2, memfs@^3.4.1: dependencies: fs-monkey "1.0.3" +memoize-one@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -9266,6 +9310,11 @@ quick-lru@^5.1.1: resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +raf-schd@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" + integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== + raf@^3.4.1: version "3.4.1" resolved "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" @@ -9772,6 +9821,19 @@ react-base16-styling@^0.6.0: lodash.flow "^3.3.0" pure-color "^1.2.0" +react-beautiful-dnd@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2" + integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ== + dependencies: + "@babel/runtime" "^7.9.2" + css-box-model "^1.2.0" + memoize-one "^5.1.1" + raf-schd "^4.0.2" + react-redux "^7.2.0" + redux "^4.0.4" + use-memo-one "^1.1.1" + react-content-loader@^5.1.3: version "5.1.4" resolved "https://registry.npmmirror.com/react-content-loader/-/react-content-loader-5.1.4.tgz#854bafe4415dd9de07174621375bc308edd0ebb5" @@ -9845,12 +9907,12 @@ react-is@18.2.0, react-is@^18.2.0: resolved "https://registry.npmmirror.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-is@^16.12.0, react-is@^16.13.1: +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.1: +react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.npmmirror.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== @@ -9890,6 +9952,18 @@ react-popper@^1.3.6: typed-styles "^0.0.7" warning "^4.0.2" +react-redux@^7.2.0: + version "7.2.9" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d" + integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" + react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" @@ -10058,6 +10132,13 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redux@^4.0.0, redux@^4.0.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" @@ -11202,6 +11283,11 @@ timsort@^0.3.0: resolved "https://registry.npmmirror.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A== +tiny-invariant@^1.0.6: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + tinycolor2@^1.4.1: version "1.6.0" resolved "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" @@ -11558,6 +11644,11 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" +use-memo-one@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" + integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"