Commit c1620424 authored by 张耀's avatar 张耀

feat:

预警规则设置接口对接
parent 0629c24b
// 通知方式 // 通知方式
export const METHODS = { export const METHODS = {
1: '钉钉', dingtalk: '钉钉',
2: '短信' sms: '短信'
} }
// 可以新增的数量 // 可以新增的数量
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
:model="state.form" :model="state.form"
ref="form_ref" ref="form_ref"
:rules="state.rules" :rules="state.rules"
label-width="110px" :label-width="labelWidth"
:disabled="disabled" :disabled="disabled"
style="width: 100%"> style="width: 100%">
<el-form-item :label="methodLabel || '通知方式'" prop="method"> <el-form-item :label="methodLabel || '通知方式'" prop="method">
...@@ -97,6 +97,10 @@ const props = defineProps({ ...@@ -97,6 +97,10 @@ const props = defineProps({
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },
labelWidth: {
type: String,
default: "110px",
},
}); });
const form_ref = ref(null); const form_ref = ref(null);
// 表单数据 // 表单数据
......
...@@ -129,13 +129,42 @@ const rule_label = [ ...@@ -129,13 +129,42 @@ const rule_label = [
], ],
]; ];
const rule_data = ref({}); const rule_data = ref({});
const ruleTypeOptions = { const ruleTypeOptions = ref({});
empty: "", const getRuleTypeOptions = () => {
1: "百分比范围", let arr = [
2: "毫秒范围", {
3: "秒范围", id: "empty",
4: "个范围", label: "",
5: "温度范围", },
{
id: "1",
label: "百分比范围",
unit: "%",
},
{
id: "2",
label: "毫秒范围",
unit: "ms",
},
{
id: "3",
label: "秒范围",
unit: "s",
},
{
id: "4",
label: "个范围",
unit: "",
},
{
id: "5",
label: "温度范围",
unit: "",
},
];
arr.forEach((e) => {
ruleTypeOptions.value[e.id] = e.label;
});
}; };
const advanced_label = [ const advanced_label = [
[ [
...@@ -225,6 +254,7 @@ const getInfoData = () => { ...@@ -225,6 +254,7 @@ const getInfoData = () => {
}); });
}; };
onBeforeMount(() => { onBeforeMount(() => {
getRuleTypeOptions();
getInfoData(); getInfoData();
}); });
</script> </script>
......
...@@ -211,8 +211,7 @@ const selectable = (row, index) => { ...@@ -211,8 +211,7 @@ const selectable = (row, index) => {
}; };
const getTableRows = () => { const getTableRows = () => {
let params = { ...state.filter, class_id: node.value.data.class_id }; let params = { ...state.filter, class_id: node.value.data.class_id };
// axios.get("/v1/api/metric_config/list", { params }).then((res) => { axios.get("/v1/api/metric_config/list", { params }).then((res) => {
axios.get("/v1/api/metric_config/list").then((res) => {
if (res.data.code == 200) { if (res.data.code == 200) {
state.tableRows = state.tableRows =
res.data.data?.list?.map((e) => { res.data.data?.list?.map((e) => {
......
...@@ -70,14 +70,40 @@ const props = defineProps({ ...@@ -70,14 +70,40 @@ const props = defineProps({
// 预警规则类型下拉 // 预警规则类型下拉
const ruleTypeOptions = ref({}); const ruleTypeOptions = ref({});
const getRuleTypeOptions = () => { const getRuleTypeOptions = () => {
ruleTypeOptions.value = { let arr = [
empty: "", {
1: "百分比范围", id: "empty",
2: "毫秒范围", label: "",
3: "秒范围", },
4: "个范围", {
5: "温度范围", id: "1",
}; label: "百分比范围",
unit: "%",
},
{
id: "2",
label: "毫秒范围",
unit: "ms",
},
{
id: "3",
label: "秒范围",
unit: "s",
},
{
id: "4",
label: "个范围",
unit: "",
},
{
id: "5",
label: "温度范围",
unit: "",
},
];
arr.forEach((e) => {
ruleTypeOptions.value[e.id] = e.label;
});
}; };
// 当前是否是编辑 // 当前是否是编辑
const isEdit = computed(() => !!props.row); const isEdit = computed(() => !!props.row);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
</div> </div>
<div class="add-btns"> <div class="add-btns">
<el-button size="default" @click="Cancle">取消</el-button> <el-button size="default" @click="Cancle">取消</el-button>
<el-button type="primary" size="default" @click="Save">保存</el-button> <el-button type="primary" size="default" @click="SaveSubmit">保存</el-button>
</div> </div>
</div> </div>
</div> </div>
...@@ -18,15 +18,20 @@ import { ref } from "vue"; ...@@ -18,15 +18,20 @@ import { ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import addForm from "../modules/add-form.vue"; import addForm from "../modules/add-form.vue";
import { ElMessage } from "element-plus";
import { Save } from "../modules/interface.js";
const router = useRouter(); const router = useRouter();
const Cancle = () => { const Cancle = () => {
router.go(-1); router.go(-1);
}; };
const add_form = ref(null); const add_form = ref(null);
const Save = async () => { const SaveSubmit = async () => {
let res = await add_form.value.Submit(); let res = await add_form.value.Submit();
if (!res) return; if (!res) return;
console.log("res: ", res); console.log("res: ", res);
Save(res, {}, () => {
Cancle();
});
}; };
</script> </script>
......
...@@ -13,9 +13,17 @@ ...@@ -13,9 +13,17 @@
</template> </template>
</Info> </Info>
</div> </div>
<gap-title :hasLine="true" title="预警范围"></gap-title> <div class="warn-scope" v-if="detection_type == 1">
<div class="info"> <gap-title :hasLine="true" title="预警范围"></gap-title>
<Info :labelData="warning_scope_label" :valueData="watning_scope_data"> </Info> <div class="info">
<Info :labelData="warning_scope_label" :valueData="watning_scope_data"> </Info>
</div>
</div>
<div class="warn-scope" v-else>
<gap-title :hasLine="true" title="指标表达式"></gap-title>
<div class="indicator-expression">
<bg-code-editor v-model="indicator_expression" :disabled="true"></bg-code-editor>
</div>
</div> </div>
<gap-title :hasLine="true" title="预警规则"></gap-title> <gap-title :hasLine="true" title="预警规则"></gap-title>
<div class="info"> <div class="info">
...@@ -29,7 +37,7 @@ ...@@ -29,7 +37,7 @@
<div class="info"> <div class="info">
<Info :labelData="ticket_push_label" :valueData="ticket_push_data"> <Info :labelData="ticket_push_label" :valueData="ticket_push_data">
<template #notification_method="{ valueData }"> <template #notification_method="{ valueData }">
<span>{{ valueData.notification_method.map((e) => METHODS[e]).join("") }}</span> <span>{{ valueData.notification_method?.map((e) => METHODS[e]).join("") || "" }}</span>
</template> </template>
</Info> </Info>
<div class="push-lists"> <div class="push-lists">
...@@ -42,13 +50,34 @@ ...@@ -42,13 +50,34 @@
</template> </template>
<script setup> <script setup>
import { ref, onBeforeMount, computed } from "vue";
import { ElMessage } from "element-plus";
import axios from "@/request/http.js";
import { useRoute } from "vue-router";
import gapTitle from "@/components/gap-title.vue"; import gapTitle from "@/components/gap-title.vue";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import Info from "@/components/warn-detail/info.vue"; import Info from "@/components/warn-detail/info.vue";
import { METHODS } from "@/components/manual-distribution/env.js"; import { METHODS } from "@/components/manual-distribution/env.js";
const STATUS_OBJ = { const route = useRoute();
enabled: "启用", const { id } = route.query;
disabled: "禁用", const STATUS_OBJ = ["禁用", "启用"];
const ruleTypeOptions = ref({});
const selectRule = {
"=": "等于",
"!=": "不等于",
"=~": "正则匹配",
"!~": "正则不匹配",
};
const riskLevelOptions = {
4: "重大风险",
3: "较大风险",
2: "一般风险",
1: "低风险",
};
const unitOptions = {
s: "",
m: "分钟",
h: "小时",
}; };
const labelData = [ const labelData = [
[ [
...@@ -92,34 +121,9 @@ const labelData = [ ...@@ -92,34 +121,9 @@ const labelData = [
}, },
], ],
]; ];
const info = { const info = ref({});
warning_rule_name: "服务中断推送规则1", const warning_scope_label = ref([]);
status: "enabled", const watning_scope_data = ref({});
warning_target: "容器云",
warning_type: "容器集群",
warning_index: "CPU使用率",
create_by: "admin",
create_time: "2020-01-01 00:00:00",
update_time: "2020-01-01 00:00:00",
};
const warning_scope_label = [
[
{
prop: "colony",
label: "集群",
},
],
[
{
prop: "core_com",
label: "核心组件",
},
],
];
const watning_scope_data = {
colony: "等于 default",
core_com: "等于 kube-apiserver/kube-apiserver2/kube-apiserver3",
};
const advanced_label = [ const advanced_label = [
[ [
{ {
...@@ -134,10 +138,7 @@ const advanced_label = [ ...@@ -134,10 +138,7 @@ const advanced_label = [
}, },
], ],
]; ];
const advanced_data = { const advanced_data = ref({});
duration: "直接产生预警",
inspection_cycle: "1分钟",
};
const ticket_push_label = [ const ticket_push_label = [
[ [
{ {
...@@ -158,51 +159,135 @@ const ticket_push_label = [ ...@@ -158,51 +159,135 @@ const ticket_push_label = [
}, },
], ],
]; ];
const ticket_push_data = { const ticket_push_data = ref({});
notification_method: ["1", "2"], const ruleHeaders = ref([
push_num: "10次",
push_frequency: "60分钟",
};
const ruleHeaders = [
{
prop: "warning_threshold",
label: "预警阈值",
},
{ {
prop: "risk_level", prop: "risk_level",
label: "风险程度", label: "风险程度",
}, },
]; ]);
const ruleRows = [ const ruleRows = ref([]);
{
warning_threshold: "12% - 50% ",
risk_level: "较大风险",
},
{
warning_threshold: "50% - 100% ",
risk_level: "重大风险",
},
];
const pushHeaders = [ const pushHeaders = [
{ {
prop: "warning_threshold", prop: "system_account",
label: "预警阈值", label: "账号",
},
{
prop: "risk_level",
label: "风险程度",
}, },
];
const pushRows = [
{ {
warning_threshold: "12% - 50% ", prop: "user_name",
risk_level: "较大风险", label: "姓名",
}, },
{ {
warning_threshold: "50% - 100% ", prop: "phone",
risk_level: "重大风险", label: "联系方式",
}, },
]; ];
const pushRows = ref([]);
const detection_type = ref(1);
const indicator_expression = ref("");
const getInfoData = () => {
axios
.get("/v1/api/alert_rules", {
params: {
id: id,
},
})
.then((res) => {
if (res.data.code == 200) {
const { data } = res.data;
detection_type.value = data.detection_type;
indicator_expression.value = data.expr;
info.value = {
warning_rule_name: data.metric_name,
status: data.is_enabled,
warning_target: data.class_parent_name,
warning_type: data.class_name,
warning_index: data.metric_config_name,
create_by: data.created_by,
create_time: data.created_at,
update_time: data.updated_at,
};
data.alert_range.forEach((e) => {
warning_scope_label.value.push([
{
prop: e.name,
label: e.chinese_name || e.name,
},
]);
watning_scope_data.value[e.name] = e.value == ".*" ? "全部" : `${selectRule[e.compare]} ${e.value}`;
});
let isEmpty = !data.alert_rule_type || data.alert_rule_type == "empty";
if (!isEmpty) {
ruleHeaders.value = [
{
prop: "warning_threshold",
label: "预警阈值",
},
...ruleHeaders.value,
];
}
ruleRows.value = data.alert_condition.map((e) => {
return {
warning_threshold: `${e.thresholds_min}${ruleTypeOptions.value[data.alert_rule_type].unit} - ${
e.thresholds_max
}${ruleTypeOptions.value[data.alert_rule_type].unit}`,
risk_level: riskLevelOptions[e.risk_level],
};
});
advanced_data.value = {
duration: data.duration == 0 ? "直接产生预警" : data.duration + unitOptions[data.duration_unit],
inspection_cycle: data.check_period + "分钟",
};
ticket_push_data.value = {
notification_method: data.notify_method,
push_num: data.notify_push_count + "",
push_frequency: data.notify_push_frequency + "分钟",
};
pushRows.value = data.notify_recipients;
} else {
ElMessage.error(res.data.data);
}
});
};
const getRuleTypeOptions = () => {
let arr = [
{
id: "empty",
label: "",
},
{
id: "1",
label: "百分比范围",
unit: "%",
},
{
id: "2",
label: "毫秒范围",
unit: "ms",
},
{
id: "3",
label: "秒范围",
unit: "s",
},
{
id: "4",
label: "个范围",
unit: "",
},
{
id: "5",
label: "温度范围",
unit: "",
},
];
arr.forEach((e) => {
ruleTypeOptions.value[e.id] = e;
});
getInfoData();
};
onBeforeMount(() => {
getRuleTypeOptions();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -221,6 +306,16 @@ const pushRows = [ ...@@ -221,6 +306,16 @@ const pushRows = [
:deep(.gap-title) { :deep(.gap-title) {
margin-bottom: 16px; margin-bottom: 16px;
} }
.warn-scope {
margin-bottom: 24px;
.indicator-expression {
height: 300px;
width: 100%;
:deep(.vue-ace-editor) {
margin-top: 0;
}
}
}
.info { .info {
max-width: 1072px; max-width: 1072px;
width: 100%; width: 100%;
...@@ -241,8 +336,8 @@ const pushRows = [ ...@@ -241,8 +336,8 @@ const pushRows = [
border-radius: 50%; border-radius: 50%;
margin-right: 8px; margin-right: 8px;
$statusObj: ( $statusObj: (
enabled: #48ad97, 1: #48ad97,
disabled: #9e9e9e, 0: #9e9e9e,
); );
@each $status, $color in $statusObj { @each $status, $color in $statusObj {
&-#{$status} { &-#{$status} {
......
...@@ -7,181 +7,155 @@ ...@@ -7,181 +7,155 @@
</div> </div>
<div class="add-btns"> <div class="add-btns">
<el-button size="default" @click="Cancle">取消</el-button> <el-button size="default" @click="Cancle">取消</el-button>
<el-button type="primary" size="default" @click="Save">保存</el-button> <el-button type="primary" size="default" @click="SaveSubmit">保存</el-button>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref, onBeforeMount } from "vue";
import { useRouter } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import addForm from "../modules/add-form.vue"; import addForm from "../modules/add-form.vue";
// const infoData = ref({ import axios from "@/request/http.js";
// id: 1, import { ElMessage } from "element-plus";
// name: "11", import { Save } from "../modules/interface.js";
// type_key: "static", const infoData = ref({});
// duration: 1,
// time: 10,
// inspection_cycle: 1,
// push_num: 1,
// push_frequency: 60,
// enabled: true,
// type_com_ref: {
// warn_type: "colony",
// warn_indicator: "1",
// warn_target: "1",
// warn_type_com: {
// value1: "22",
// value1_select: "3",
// value2: "33",
// value2_select: "2",
// risk_level: 1,
// },
// },
// manual_distribution_form: {
// method: ["1", "2"],
// lists: [
// {
// user_id: 2,
// user_name: 22,
// phone: 13000000002,
// },
// {
// user_id: 3,
// user_name: 33,
// phone: 13000000003,
// },
// ],
// },
// });
const infoData = ref({
name: "11",
type_key: "static",
duration: 1,
time: 10,
inspection_cycle: 1,
push_num: 1,
push_frequency: 60,
enabled: true,
type_com_ref: {
warn_type: "gateway",
warn_indicator: "1",
warn_target: "1",
warn_type_com: {
ruleRows: [
{
from: "22",
to: "33",
risk_level: 1,
},
{
from: "44",
to: "55",
risk_level: 2,
},
],
},
},
manual_distribution_form: {
method: ["1"],
lists: [
{
user_id: 1,
user_name: 11,
phone: 13000000001,
},
],
},
});
// const infoData = ref({
// id: 1,
// name: "11",
// type_key: "static",
// duration: 1,
// time: 10,
// inspection_cycle: 1,
// push_num: 1,
// push_frequency: 60,
// enabled: true,
// type_com_ref: {
// warn_type: "colony",
// warn_indicator: "1",
// warn_target: "1",
// warn_type_com: {
// value1: "22",
// value1_select: "3",
// value2: "33",
// value2_select: "2",
// risk_level: 1,
// },
// },
// manual_distribution_form: {
// method: ["1", "2"],
// lists: [
// {
// user_id: 2,
// user_name: 22,
// phone: 13000000002,
// },
// {
// user_id: 3,
// user_name: 33,
// phone: 13000000003,
// },
// ],
// },
// });
// const infoData = ref({
// name: "11",
// type_key: "custom",
// duration: 1,
// time: 10,
// inspection_cycle: 1,
// push_num: 1,
// push_frequency: 60,
// enabled: true,
// type_com_ref: {
// warn_target: "22",
// warn_type: "33",
// warn_indicator: "44",
// indicator_expression: "55\n66\n77",
// rule_type: "1",
// ruleRows: [
// {
// from: "88",
// to: "99",
// risk_level: 1,
// },
// ],
// },
// manual_distribution_form: {
// method: ["1", "2"],
// lists: [
// {
// user_id: 1,
// user_name: 11,
// phone: 13000000001,
// },
// {
// user_id: 2,
// user_name: 22,
// phone: 13000000002,
// },
// ],
// },
// });
const router = useRouter(); const router = useRouter();
const route = useRoute();
const { id } = route.query;
const Cancle = () => { const Cancle = () => {
router.go(-1); router.go(-1);
}; };
const add_form = ref(null); const add_form = ref(null);
const Save = async () => { const SaveSubmit = async () => {
let res = await add_form.value.Submit(); let res = await add_form.value.Submit();
if (!res) return; if (!res) return;
console.log("res: ", res); console.log("res: ", res);
Save(res, { id }, () => {
Cancle();
});
}; };
const staticTypeOptions = ref([]);
const findTypeBySecond = (id) => {
return staticTypeOptions.value.find((e) => {
return e.children.find((e_c) => e_c.class_id == id);
});
};
const getInfoData = () => {
axios
.get("/v1/api/alert_rules", {
params: {
id: id,
},
})
.then((res) => {
if (res.data.code == 200) {
const { data } = res.data;
console.log("data: ", data);
const isEmpty = !data.alert_rule_type || data.alert_rule_type == "empty";
let type_json = {
1: () => {
let obj = {
key: "static",
type_com_ref: {
warn_type: data.class_id,
warn_indicator: data.metric_config_id,
warn_target: findTypeBySecond(data.class_id)?.class_id || "",
rule_type: data.alert_rule_type,
},
};
// if (isEmpty) {
// obj.type_com_ref.risk_level = data.alert_condition[0].risk_level;
// } else {
obj.type_com_ref.warning_scpoe_form =
data.alert_range?.map((e) => {
return {
...e,
select: e.compare,
options: [],
};
}) || [];
obj.type_com_ref.ruleRows =
data.alert_condition?.map((e) => {
return {
from: e.thresholds_min,
to: e.thresholds_max,
risk_level: e.risk_level,
};
}) || [];
// }
return obj;
},
2: () => {
let obj = {
key: "custom",
type_com_ref: {
warn_target: data.class_parent_name,
warn_type: data.class_name,
warn_indicator: data.metric_config_name,
indicator_expression: data.expr,
rule_type: data.alert_rule_type,
},
};
if (isEmpty) {
obj.type_com_ref.risk_level = data.alert_condition[0].risk_level;
} else {
obj.type_com_ref.ruleRows =
data.alert_condition?.map((e) => {
return {
from: e.thresholds_min,
to: e.thresholds_max,
risk_level: e.risk_level,
};
}) || [];
}
return obj;
},
};
let d = type_json[`${data.detection_type}`]();
infoData.value = {
name: data.metric_name,
type_key: d.key,
unit: data.duration_unit,
time: data.duration,
inspection_cycle: data.check_period,
push_num: data.notify_push_count,
push_frequency: data.notify_push_frequency,
enabled: data.is_enabled ? 1 : 2,
type_com_ref: d.type_com_ref,
manual_distribution_form: {
method: data.notify_method,
lists:
data.notify_recipients?.map((e) => {
return {
user_id: e.system_account,
user_name: e.user_name,
phone: e.phone,
};
}) || [],
},
};
} else {
ElMessage.error(res.data.data);
}
});
};
const getStaticTypeOptions = () => {
axios.get("/v1/api/alert_class/tree").then(async (res) => {
if (res.data.code == 200) {
staticTypeOptions.value = res.data.data;
getInfoData();
} else {
ElMessage.error(res.data.msg);
}
});
};
onBeforeMount(() => {
getStaticTypeOptions();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div class="main_container"> <div class="main_container">
<bg-filter-group <bg-filter-group
@search="changeSearch" @search="changeSearch"
v-model="filter.search" v-model="filter.keyword"
inputWidth="380px" inputWidth="380px"
placeholder="请输入预警规则名称/预警对象/预警分类/预警指标"> placeholder="请输入预警规则名称/预警对象/预警分类/预警指标">
<template v-slot:left_action> <template v-slot:left_action>
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<div class="left-filter filter_list"> <div class="left-filter filter_list">
<div class="filter_item"> <div class="filter_item">
<span class="filter_title">通知方式</span> <span class="filter_title">通知方式</span>
<el-select v-model="filter.notice_method" placeholder="请选择" style="width: 300px"> <el-select v-model="filter.notify_method" placeholder="请选择" style="width: 300px">
<el-option <el-option
v-for="(item, index) in noticeTypes" v-for="(item, index) in noticeTypes"
:key="'noticeTypes' + index" :key="'noticeTypes' + index"
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
</div> </div>
<div class="filter_item"> <div class="filter_item">
<span class="filter_title">启用状态</span> <span class="filter_title">启用状态</span>
<el-select v-model="filter.state" placeholder="请选择" style="width: 300px"> <el-select v-model="filter.is_enabled" placeholder="请选择" style="width: 300px">
<el-option <el-option
v-for="(item, index) in stateOptions" v-for="(item, index) in stateOptions"
:key="'stateOptions' + index" :key="'stateOptions' + index"
...@@ -49,8 +49,8 @@ ...@@ -49,8 +49,8 @@
<el-date-picker <el-date-picker
style="width: 300px" style="width: 300px"
v-model="filter.time" v-model="filter.time"
type="daterange" type="datetimerange"
value-format="yyyy-MM-DD" value-format="YYYY-MM-DD HH:mm:ss"
range-separator="至" range-separator="至"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" /> end-placeholder="结束日期" />
...@@ -73,28 +73,31 @@ ...@@ -73,28 +73,31 @@
:isIndex="true" :isIndex="true"
:select="true" :select="true"
:stripe="true"> :stripe="true">
<template v-slot:rule_name="{ row }"> <template v-slot:metric_name="{ row }">
<span class="can_click_text" @click="goDetail(row)"> <span class="can_click_text" @click="goDetail(row)">
{{ row.rule_name }} {{ row.metric_name }}
</span> </span>
</template> </template>
<template v-slot:notice_method="{ row }"> <template v-slot:notify_method="{ row }">
{{ ["", "钉钉", "短信"][row.notice_method] }} {{ row.notify_method.map((e) => METHODS[e]).join("") }}
</template> </template>
<template #state="{ row }"> <template v-slot:notify_recipients="{ row }">
{{ row.notify_recipients.length }}
</template>
<template #is_enabled="{ row }">
<bg-switch <bg-switch
@click="stateChange(row)" @click="stateChange(row)"
:labels="['否', '是']" :labels="['否', '是']"
:values="[0, 1]" :values="[2, 1]"
v-model="row.state"></bg-switch> v-model="row.is_enabled"></bg-switch>
</template> </template>
<template v-slot:created_time="{ row }"> <template v-slot:created_at="{ row }">
{{ row.created_time ? row.created_time.split("+")[0].replace("T", " ").replace("Z", " ") : "-" }} {{ row.created_at ? row.created_at.split("+")[0].replace("T", " ").replace("Z", " ") : "-" }}
</template> </template>
<template v-slot:action="{ row }"> <template v-slot:action="{ row }">
<bg-table-btns2 :limit="3" :tableData="tableRows"> <bg-table-btns2 :limit="3" :tableData="tableRows">
<bg-table-btn :disabled="row.state != 0" @click="editRow(row)">编辑</bg-table-btn> <bg-table-btn :disabled="row.is_enabled != 2" @click="editRow(row)">编辑</bg-table-btn>
<bg-table-btn :disabled="row.state != 0" @click="deleteRow(row)">删除</bg-table-btn> <bg-table-btn :disabled="row.is_enabled != 2" @click="deleteRow(row)">删除</bg-table-btn>
</bg-table-btns2> </bg-table-btns2>
</template> </template>
</bg-table> </bg-table>
...@@ -128,7 +131,10 @@ import axios from "@/request/http.js"; ...@@ -128,7 +131,10 @@ import axios from "@/request/http.js";
import { Search } from "@element-plus/icons-vue"; import { Search } from "@element-plus/icons-vue";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue"; import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const METHODS = {
dingtalk: "钉钉",
sms: "短信",
};
const router = useRouter(); const router = useRouter();
const dataTable = ref(null); const dataTable = ref(null);
...@@ -141,13 +147,13 @@ const state = reactive({ ...@@ -141,13 +147,13 @@ const state = reactive({
}, },
{ {
name: "钉钉", name: "钉钉",
value: 1, value: "dingtalk",
}, },
{ {
name: "短信", name: "短信",
value: 2, value: "sms",
}, },
], // 风险等级 ],
stateOptions: [ stateOptions: [
{ {
name: "全部", name: "全部",
...@@ -165,40 +171,40 @@ const state = reactive({ ...@@ -165,40 +171,40 @@ const state = reactive({
headers: [ headers: [
{ {
label: "预警规则名称", label: "预警规则名称",
prop: "rule_name", prop: "metric_name",
width: 200, width: 200,
}, },
{ {
label: "预警分类", label: "预警分类",
prop: "warning_object", prop: "class_parent_name",
}, },
{ {
label: "预警对象", label: "预警对象",
prop: "warning_type_name", prop: "class_name",
}, },
{ {
label: "预警指标", label: "预警指标",
prop: "warning_target_name", prop: "metric_config_name",
}, },
{ {
label: "通知方式", label: "通知方式",
prop: "notice_method", prop: "notify_method",
}, },
{ {
label: "通知人数", label: "通知人数",
prop: "notice_people_num", prop: "notify_recipients",
}, },
{ {
label: "是否启用", label: "是否启用",
prop: "state", prop: "is_enabled",
}, },
{ {
label: "创建人", label: "创建人",
prop: "created_user", prop: "created_by",
}, },
{ {
label: "创建时间", label: "创建时间",
prop: "created_time", prop: "created_at",
width: 160, width: 160,
}, },
{ {
...@@ -212,10 +218,10 @@ const state = reactive({ ...@@ -212,10 +218,10 @@ const state = reactive({
selected: [], //选择数据 selected: [], //选择数据
tableTotal: 0, // 表格数据条数 tableTotal: 0, // 表格数据条数
filter: { filter: {
notice_method: "", // 通知方式 notify_method: "", // 通知方式
state: "", // 状态 is_enabled: "", // 状态
time: [], time: [],
search: "", keyword: "",
page: 1, page: 1,
limit: 10, limit: 10,
}, // 表格筛选项 }, // 表格筛选项
...@@ -253,7 +259,7 @@ const goDetail = (row) => { ...@@ -253,7 +259,7 @@ const goDetail = (row) => {
}; // 查看详情 }; // 查看详情
const changeSearch = (val) => { const changeSearch = (val) => {
state.filter.search = val; state.filter.keyword = val;
changePage(1); changePage(1);
}; // 表格关键字筛选 }; // 表格关键字筛选
...@@ -263,10 +269,10 @@ const filterAction = () => { ...@@ -263,10 +269,10 @@ const filterAction = () => {
const filterClear = () => { const filterClear = () => {
state.filter = { state.filter = {
notice_method: "", // 通知方式 notify_method: "", // 通知方式
state: "", // 状态 is_enabled: "", // 状态
time: "", time: "",
search: "", keyword: "",
page: 1, page: 1,
limit: 10, limit: 10,
}; };
...@@ -274,61 +280,28 @@ const filterClear = () => { ...@@ -274,61 +280,28 @@ const filterClear = () => {
}; // 重置筛选项 }; // 重置筛选项
const selectable = (row, index) => { const selectable = (row, index) => {
return row.state === 0; return row.is_enabled === 2;
}; };
const getTableRows = () => { const getTableRows = () => {
let params = { ...state.filter }; let [start_time = "", end_time = ""] = state.filter.time || [];
// axios let params = {
// .get(`/apaas/system/v5/dictionary/list`, { ...state.filter,
// params, start_time,
// }) end_time,
// .then((res) => { };
// if (res.data.code == 200) { Reflect.deleteProperty(params, "time");
// state.tableRows = res.data.data || []; axios
// state.tableTotal = res.data.total; .get(`/v1/api/alert_rules/list`, {
// } else { params,
// ElMessage.error(res.data.data); })
// } .then((res) => {
// }); if (res.data.code == 200) {
state.tableTotal = 23; state.tableRows = res.data.data?.list || [];
state.tableRows = [ state.tableTotal = res.data.data.total_count;
{ } else {
id: 1, ElMessage.error(res.data.data);
rule_name: "容器云/tyyh", }
warning_object: "容器云", });
warning_type_name: "容器组",
warning_target_name: "服务中断",
notice_people_num: 1,
created_user: "王五",
created_time: "2020-01-01 00:00:00",
state: 1,
notice_method: 1,
},
{
id: 2,
rule_name: "容器云/kube-apiserver",
warning_object: "容器云",
warning_type_name: "容器集群",
warning_target_name: "内存使用率",
notice_people_num: 23,
created_user: "李四",
created_time: "2020-01-01 00:00:00",
state: 0,
notice_method: 2,
},
{
id: 3,
rule_name: "容器云/kube-apiserver",
warning_object: "容器云",
warning_type_name: "容器集群",
warning_target_name: "内存使用率",
notice_people_num: 456,
created_user: "张三",
created_time: "2020-01-01 00:00:00",
state: 0,
notice_method: 1,
},
];
}; // 获取表格数据 }; // 获取表格数据
const changePage = (page) => { const changePage = (page) => {
...@@ -341,30 +314,29 @@ const changeSize = (size) => { ...@@ -341,30 +314,29 @@ const changeSize = (size) => {
changePage(1); changePage(1);
}; // 改变每页条数 }; // 改变每页条数
const stateChange = (row) => { const stateChange = ({ id, is_enabled }) => {
console.log("更改状态"); const params = {
// axios id,
// .put(`/xxx/xxx?id=${row.id}&state=${row.state}`) is_enabled,
// .then((res) => { };
// if (res.data.code == 200) { axios.put(`/v1/api/alert_rules/is_enabled`, params).then((res) => {
// ElMessage.success(res.data.msg); if (res.data.code == 200) {
// changePage(1); ElMessage.success("状态修改成功");
// } else { changePage(1);
// ElMessage.error(res.data.data); } else {
// row.state = row.state == 0 ? 1 : 0; ElMessage.error(res.data.msg);
// } row.state = row.state == 1 ? 2 : 1;
// }); }
});
}; };
const addRule = () => { const addRule = () => {
console.log("新增");
router.push({ router.push({
path: `/forewarning/rule-set/add`, path: `/forewarning/rule-set/add`,
}); });
}; // 新增规则 }; // 新增规则
const editRow = (row) => { const editRow = (row) => {
console.log("编辑");
router.push({ router.push({
path: `/forewarning/rule-set/edit`, path: `/forewarning/rule-set/edit`,
query: { query: {
...@@ -377,7 +349,6 @@ const deleteRow = (row) => { ...@@ -377,7 +349,6 @@ const deleteRow = (row) => {
state.actionRow = row; state.actionRow = row;
state.delType = 1; state.delType = 1;
state.delDialog = true; state.delDialog = true;
console.log("删除");
}; // 删除 }; // 删除
const delConfirm = () => { const delConfirm = () => {
...@@ -389,12 +360,22 @@ const delConfirm = () => { ...@@ -389,12 +360,22 @@ const delConfirm = () => {
return e.id; return e.id;
}); });
} }
console.log(ids); axios
state.delDialog = false; .delete("/v1/api/alert_rules", {
setTimeout(() => { data: {
clearSelected(); ids,
changePage(1); },
}, 200); })
.then((res) => {
if (res.data.code == "200") {
ElMessage.success("删除成功");
state.delDialog = false;
clearSelected();
changePage(1);
} else {
ElMessage.error(res.data.msg);
}
});
}; // 确定删除 }; // 确定删除
onBeforeMount(() => { onBeforeMount(() => {
......
<template> <template>
<div class="add-form"> <div class="add-form">
<el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="110px"> <el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="120px">
<div class="add-form-item"> <div class="add-form-item">
<el-form-item label="预警规则名称" prop="name"> <el-form-item label="预警规则名称" prop="name">
<el-input v-model="state.form.name" :disabled="isEdit" placeholder="请输入预警规则名称"></el-input> <el-input v-model="state.form.name" :disabled="isEdit" placeholder="请输入预警规则名称"></el-input>
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
<ManualDistributionForm <ManualDistributionForm
ref="manual_distribution_form" ref="manual_distribution_form"
class="manual-distribution-form" class="manual-distribution-form"
labelWidth="120px"
:noElLabel="false" :noElLabel="false"
methodLabel="预警通知方式" methodLabel="预警通知方式"
:history="history" /> :history="history" />
......
<template>
<div class="container-cluster-form">
<el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="110px">
<gap-title :hasLine="true" title="预警范围"></gap-title>
<div class="container-cluster-form-item warning-scope-form-item">
<el-form-item :label="typeToTextJson[props.type][0]" prop="value1">
<el-input v-model="state.form.value1" placeholder="请输入">
<template #prepend>
<el-select class="rule-select" v-model="state.form.value1_select" style="width: 114px">
<el-option v-for="(value, key) in selectRule" :key="key" :label="value" :value="key" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item :label="typeToTextJson[props.type][1]" prop="value2">
<el-input v-model="state.form.value2" placeholder="请输入">
<template #prepend>
<el-select class="rule-select" v-model="state.form.value2_select" style="width: 114px">
<el-option v-for="(value, key) in selectRule" :key="key" :label="value" :value="key" />
</el-select>
</template>
</el-input>
</el-form-item>
</div>
<gap-title :hasLine="true" title="预警规则"></gap-title>
<div class="container-cluster-form-item">
<el-form-item label="风险程度" prop="risk_level">
<el-select style="flex: 1" v-model="state.form.risk_level" placeholder="请选择" filterable>
<el-option v-for="item in riskLevelOptions" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script setup>
import { reactive, ref, watch } from "vue";
import gapTitle from "@/components/gap-title.vue";
const props = defineProps({
type: {
type: String,
default: "",
},
form: {
type: Object,
default: null,
},
});
const typeToTextJson = {
colony: ["集群", "核心组件"],
node: ["集群", "节点"],
group: ["命名空间", "容器"],
};
const selectRule = ref({
1: "遍历",
2: "等于",
3: "不等于",
4: "正则匹配",
5: "正则不匹配",
});
const state = reactive({
form: {
value1: "",
value1_select: "1",
value2: "",
value2_select: "1",
risk_level: "",
},
rules: {
value1: [{ required: true, message: "请输入", trigger: "blur" }],
value2: [{ required: true, message: "请输入", trigger: "blur" }],
risk_level: [{ required: true, message: "请选择", trigger: "change" }],
},
});
const form_ref = ref(null);
watch(
() => props.type,
(n) => {
state.form.value1 = "";
state.form.value1_select = "1";
state.form.value2 = "";
state.form.value2_select = "1";
form_ref.value.clearValidate(["value1", "value2", "risk_level"]);
}
);
watch(
() => props.form,
(n) => {
if (!n) return;
state.form.value1 = n.value1;
state.form.value1_select = n.value1_select || "1";
state.form.value2 = n.value2;
state.form.value2_select = n.value2_select || "1";
state.form.risk_level = n.risk_level;
},
{
deep: true,
immediate: true,
}
);
const riskLevelOptions = ref([
{
id: 1,
name: "重大风险",
},
{
id: 2,
name: "较大风险",
},
{
id: 3,
name: "一般风险",
},
{
id: 4,
name: "低风险",
},
]);
const Submit = async () => {
let form_valid = await new Promise((resolve, reject) => {
form_ref.value.validate((res) => resolve(res));
});
return form_valid;
};
defineExpose({
Submit,
form: state.form,
form_ref,
});
</script>
<style lang="scss" scoped>
.container-cluster-form {
:deep(.gap-title) {
margin-bottom: 16px;
}
&-item {
max-width: 1080px;
width: 100%;
padding-left: 8px;
}
.warning-scope-form-item {
display: flex;
align-items: center;
:deep(.el-form-item) {
flex: 1;
.el-input-group__prepend {
border-radius: 4px !important;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
overflow: hidden;
}
}
:deep(.el-input-group__prepend) {
background-color: #2b4695;
.el-input__wrapper {
box-shadow: 1px 0 0 0 #2b4695 !important;
&,
.el-input__inner {
color: #fff;
}
.el-input__wrapper {
color: #fff;
}
}
}
}
}
</style>
<template> <template>
<div class="custom-form"> <div class="custom-form">
<el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="110px"> <el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="120px">
<div class="custom-form-item"> <div class="custom-form-item">
<el-form-item label="预警对象" prop="warn_target"> <el-form-item label="预警分类" prop="warn_target">
<el-input <el-input
v-model="state.form.warn_target" v-model="state.form.warn_target"
placeholder="请输入预警对象" placeholder="请输入预警分类"
:disabled="isEdit" :disabled="isEdit"
:maxlength="20" :maxlength="20"
show-word-limit show-word-limit
clearable clearable
@change="changeWarnCustomTarget"></el-input> @change="changeWarnCustomTarget"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="预警分类" prop="warn_type"> <el-form-item label="预警对象" prop="warn_type">
<el-input <el-input
v-model="state.form.warn_type" v-model="state.form.warn_type"
placeholder="请输入预警分类" placeholder="请输入预警对象"
:disabled="isEdit" :disabled="isEdit"
clearable clearable
:maxlength="20" :maxlength="20"
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
</el-form-item> </el-form-item>
</div> </div>
<gap-title :hasLine="true" title="预警规则"></gap-title> <gap-title :hasLine="true" title="预警规则"></gap-title>
<div class="add-form-item"> <div class="custom-form-item">
<el-form-item label="预警规则类型" prop="rule_type"> <el-form-item label="预警规则类型" prop="rule_type">
<el-select <el-select
style="flex: 1" style="flex: 1"
...@@ -54,7 +54,12 @@ ...@@ -54,7 +54,12 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="" v-if="state.form.ruleRows.length > 0 && state.form.rule_type != 'empty'"> <el-form-item label="风险程度" prop="risk_level" v-if="isEmpty">
<el-select style="flex: 1" v-model="state.form.risk_level" placeholder="请选择风险程度" filterable>
<el-option v-for="item in riskLevels" :key="item.id" :label="item.name" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="" v-else-if="state.form.ruleRows.length > 0">
<div class="rule-table" style="width: 100%"> <div class="rule-table" style="width: 100%">
<el-form <el-form
:model="state.form.ruleRows" :model="state.form.ruleRows"
...@@ -76,7 +81,8 @@ ...@@ -76,7 +81,8 @@
style="flex: 1" style="flex: 1"
v-model="state.form.ruleRows[$index].from" v-model="state.form.ruleRows[$index].from"
placeholder="请输入" placeholder="请输入"
@input="changeWarningThresholdFrom($index)"> @input="inputNum($index, 'from')"
@blur="changeWarningThresholdFrom($index)">
<template #append>{{ unitMap }}</template> <template #append>{{ unitMap }}</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
...@@ -87,7 +93,8 @@ ...@@ -87,7 +93,8 @@
v-model="state.form.ruleRows[$index].to" v-model="state.form.ruleRows[$index].to"
placeholder="请输入" placeholder="请输入"
clearable clearable
@input="changeWarningThresholdTo($index)"> @input="inputNum($index, 'to')"
@blur="changeWarningThresholdTo($index)">
<template #append>{{ unitMap }}</template> <template #append>{{ unitMap }}</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
...@@ -140,7 +147,7 @@ ...@@ -140,7 +147,7 @@
</template> </template>
<script setup> <script setup>
import { computed, reactive, ref, watch } from "vue"; import { computed, onBeforeMount, reactive, ref, watch } from "vue";
import gapTitle from "@/components/gap-title.vue"; import gapTitle from "@/components/gap-title.vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
const props = defineProps({ const props = defineProps({
...@@ -164,7 +171,6 @@ var validateWarnIndex = (rule, value, callback) => { ...@@ -164,7 +171,6 @@ var validateWarnIndex = (rule, value, callback) => {
callback(); callback();
} }
}; };
const state = reactive({ const state = reactive({
form: { form: {
warn_target: "", warn_target: "",
...@@ -173,12 +179,14 @@ const state = reactive({ ...@@ -173,12 +179,14 @@ const state = reactive({
indicator_expression: "", indicator_expression: "",
rule_type: "empty", rule_type: "empty",
ruleRows: [], ruleRows: [],
risk_level: "",
}, },
rules: { rules: {
warn_target: [{ required: true, message: "请输入预警对象", trigger: "blur" }], warn_target: [{ required: true, message: "请输入预警分类", trigger: "blur" }],
warn_type: [{ required: true, message: "请输入预警分类", trigger: "blur" }], warn_type: [{ required: true, message: "请输入预警对象", trigger: "blur" }],
warn_indicator: [{ validator: validateWarnIndex, trigger: "blur" }], warn_indicator: [{ validator: validateWarnIndex, trigger: "blur" }],
indicator_expression: [{ required: true, message: "请输入预警指标", trigger: "blur" }], indicator_expression: [{ required: true, message: "请输入预警指标", trigger: "blur" }],
risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }],
}, },
tableRules: { tableRules: {
from: [{ required: true, message: "请输入", trigger: "blur" }], from: [{ required: true, message: "请输入", trigger: "blur" }],
...@@ -186,6 +194,7 @@ const state = reactive({ ...@@ -186,6 +194,7 @@ const state = reactive({
risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }], risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }],
}, },
}); });
const isEmpty = computed(() => state.form.rule_type == "empty");
const changeWarnCustomTarget = () => {}; const changeWarnCustomTarget = () => {};
const changeWarnCustomType = () => {}; const changeWarnCustomType = () => {};
const setLimits = (index) => { const setLimits = (index) => {
...@@ -200,11 +209,21 @@ const setLimits = (index) => { ...@@ -200,11 +209,21 @@ const setLimits = (index) => {
}) || [] }) || []
); );
}; };
const inputNum = (index, key) => {
state.form.ruleRows[index][key] = +`${state.form.ruleRows[index][key]}`.replace(/[^\d]/g, "");
};
const changeWarningThresholdFrom = (index) => { const changeWarningThresholdFrom = (index) => {
let { down, up } = limit.value; let { down, up } = limit.value;
if (down === "") return; if (down === "") return;
let { from, to } = state.form.ruleRows[index]; let { from, to } = state.form.ruleRows[index];
if (+from > +up || (index == 0 && +from < +down) || +from > +to) { if (+from > +up || (index == 0 && +from < +down) || (to != "" && from > +to)) {
if (+from < +down) {
ElMessage.error(`下限不能小于${down}`);
} else if (+from > +up) {
ElMessage.error(`上限不能超过${up}`);
} else {
ElMessage.error(`下限不能大于上限`);
}
state.form.ruleRows[index].from = ""; state.form.ruleRows[index].from = "";
return; return;
} }
...@@ -212,11 +231,12 @@ const changeWarningThresholdFrom = (index) => { ...@@ -212,11 +231,12 @@ const changeWarningThresholdFrom = (index) => {
if (rows.length == 0) return; if (rows.length == 0) return;
try { try {
rows.forEach((e) => { rows.forEach((e) => {
if (+e.up >= +from > +e.down) { if (e.up !== "" && e.down !== "" && +e.up >= +from > +e.down) {
throw ""; throw "";
} }
}); });
} catch (e) { } catch (e) {
ElMessage.error(`该范围已被设置`);
state.form.ruleRows[index].from = ""; state.form.ruleRows[index].from = "";
} }
}; };
...@@ -224,7 +244,14 @@ const changeWarningThresholdTo = (index) => { ...@@ -224,7 +244,14 @@ const changeWarningThresholdTo = (index) => {
let { down, up } = limit.value; let { down, up } = limit.value;
if (up === "") return; if (up === "") return;
let { from, to } = state.form.ruleRows[index]; let { from, to } = state.form.ruleRows[index];
if ((index == 0 && +to > +up) || +to < +down || +from > +to) { if ((index == 0 && +to > +up) || +to < +down || (from != "" && +from > +to)) {
if (+to > +up) {
ElMessage.error(`上限不能超过${up}`);
} else if (+to < +down) {
ElMessage.error(`下限不能小于${down}`);
} else {
ElMessage.error(`上限不能小于下限`);
}
state.form.ruleRows[index].to = ""; state.form.ruleRows[index].to = "";
return; return;
} }
...@@ -232,7 +259,7 @@ const changeWarningThresholdTo = (index) => { ...@@ -232,7 +259,7 @@ const changeWarningThresholdTo = (index) => {
if (rows.length == 0) return; if (rows.length == 0) return;
try { try {
rows.forEach((e) => { rows.forEach((e) => {
if (+e.up > +to > +e.down) { if (e.up !== "" && e.down !== "" && +e.up > +to > +e.down) {
throw ""; throw "";
} }
}); });
...@@ -247,6 +274,9 @@ const Submit = async () => { ...@@ -247,6 +274,9 @@ const Submit = async () => {
let form_valid = await new Promise((resolve, reject) => { let form_valid = await new Promise((resolve, reject) => {
form_ref.value.validate((res) => resolve(res)); form_ref.value.validate((res) => resolve(res));
}); });
if (isEmpty.value) {
return form_valid;
}
let table_form_valid = await new Promise((resolve, reject) => { let table_form_valid = await new Promise((resolve, reject) => {
table_form.value.validate((res) => resolve(res)); table_form.value.validate((res) => resolve(res));
}); });
...@@ -254,19 +284,19 @@ const Submit = async () => { ...@@ -254,19 +284,19 @@ const Submit = async () => {
}; };
const riskLevels = ref([ const riskLevels = ref([
{ {
id: 1, id: 4,
name: "重大风险", name: "重大风险",
}, },
{ {
id: 2, id: 3,
name: "较大风险", name: "较大风险",
}, },
{ {
id: 3, id: 2,
name: "一般风险", name: "一般风险",
}, },
{ {
id: 4, id: 1,
name: "低风险", name: "低风险",
}, },
]); ]);
...@@ -281,61 +311,73 @@ const riskLevelOptions = computed(() => { ...@@ -281,61 +311,73 @@ const riskLevelOptions = computed(() => {
return riskLevels.value.filter((e) => !rows.includes(e.id)); return riskLevels.value.filter((e) => !rows.includes(e.id));
}; };
}); });
const ruleTypeOptions = ref({});
const unitMap = computed(() => { const unitMap = computed(() => {
return ruleTypeOptions[state.form.rule_type].unit || ""; return ruleTypeOptions.value[state.form.rule_type]?.unit || "";
}); });
const limit = computed(() => { const limit = computed(() => {
return ( return (
ruleTypeOptions[state.form.rule_type].limit || { ruleTypeOptions.value[state.form.rule_type].limit || {
down: "", down: "",
up: "", up: "",
} }
); );
}); });
const ruleTypeOptions = { const getRuleTypeOptions = () => {
empty: { let arr = [
label: "", {
}, id: "empty",
1: { label: "",
label: "百分比范围",
unit: "%",
limit: {
down: 0,
up: 100,
}, },
}, {
2: { id: "1",
label: "毫秒范围", label: "百分比范围",
unit: "ms", unit: "%",
limit: { limit: {
down: 0, down: 0,
up: "", up: 100,
},
}, },
}, {
3: { id: "2",
label: "秒范围", label: "毫秒范围",
unit: "s", unit: "ms",
limit: { limit: {
down: 0, down: 0,
up: "", up: "",
},
}, },
}, {
4: { id: "3",
label: "个范围", label: "秒范围",
unit: "", unit: "s",
limit: { limit: {
down: 0, down: 0,
up: "", up: "",
},
}, },
}, {
5: { id: "4",
label: "温度范围", label: "个范围",
unit: "", unit: "",
limit: { limit: {
down: "", down: 0,
up: "", up: "",
},
}, },
}, {
id: "5",
label: "温度范围",
unit: "",
limit: {
down: "",
up: "",
},
},
];
arr.forEach((e) => {
ruleTypeOptions.value[e.id] = e;
});
}; };
const ruleHeaders = [ const ruleHeaders = [
{ {
...@@ -370,8 +412,9 @@ watch( ...@@ -370,8 +412,9 @@ watch(
state.form.warn_indicator = f.warn_indicator; state.form.warn_indicator = f.warn_indicator;
state.form.indicator_expression = f.indicator_expression; state.form.indicator_expression = f.indicator_expression;
state.form.rule_type = f.rule_type; state.form.rule_type = f.rule_type;
state.form.risk_level = f.risk_level;
state.form.ruleRows = state.form.ruleRows =
f.ruleRows.map((e) => { f?.ruleRows?.map((e) => {
return { return {
from: e.from, from: e.from,
to: e.to, to: e.to,
...@@ -387,9 +430,25 @@ watch( ...@@ -387,9 +430,25 @@ watch(
immediate: true, immediate: true,
} }
); );
// watch(
// () => state.form,
// (n) => {
// console.log(state.form);
// },
// { deep: true }
// );
const formatForm = computed(() => {
return {
...state.form,
isEmpty: isEmpty.value,
};
});
onBeforeMount(() => {
getRuleTypeOptions();
});
defineExpose({ defineExpose({
Submit, Submit,
form: state.form, form: formatForm,
form_ref, form_ref,
}); });
</script> </script>
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
@input="inputNum($index, 'from')" @input="inputNum($index, 'from')"
@blur="changeWarningThresholdFrom($index)"> @blur="changeWarningThresholdFrom($index)">
<template v-if="state.form.rule_type != 'empty'" #append>{{ <template v-if="state.form.rule_type != 'empty'" #append>{{
ruleTypeOptions[props.rule_type].unit ruleTypeOptions[rule_type]?.unit || ""
}}</template> }}</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
@input="inputNum($index, 'to')" @input="inputNum($index, 'to')"
@blur="changeWarningThresholdTo($index)"> @blur="changeWarningThresholdTo($index)">
<template v-if="state.form.rule_type != 'empty'" #append>{{ <template v-if="state.form.rule_type != 'empty'" #append>{{
ruleTypeOptions[props.rule_type].unit ruleTypeOptions[rule_type]?.unit || ""
}}</template> }}</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
</template> </template>
<script setup> <script setup>
import { computed, reactive, ref, watch } from "vue"; import { computed, nextTick, reactive, ref, watch } from "vue";
import gapTitle from "@/components/gap-title.vue"; import gapTitle from "@/components/gap-title.vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
const props = defineProps({ const props = defineProps({
...@@ -94,50 +94,64 @@ const props = defineProps({ ...@@ -94,50 +94,64 @@ const props = defineProps({
default: "1", default: "1",
}, },
}); });
const ruleTypeOptions = { const ruleTypeOptions = ref({});
empty: { const getRuleTypeOptions = async (cb) => {
label: "", let arr = [
}, {
1: { id: "empty",
label: "百分比范围", label: "",
unit: "%",
limit: {
down: 0,
up: 100,
}, },
}, {
2: { id: "1",
label: "毫秒范围", label: "百分比范围",
unit: "ms", unit: "%",
limit: { limit: {
down: 0, down: 0,
up: "", up: 100,
},
}, },
}, {
3: { id: "2",
label: "秒范围", label: "毫秒范围",
unit: "s", unit: "ms",
limit: { limit: {
down: 0, down: 0,
up: "", up: "",
},
}, },
}, {
4: { id: "3",
label: "个范围", label: "秒范围",
unit: "", unit: "s",
limit: { limit: {
down: 0, down: 0,
up: "", up: "",
},
}, },
}, {
5: { id: "4",
label: "温度范围", label: "个范围",
unit: "", unit: "",
limit: { limit: {
down: "", down: 0,
up: "", up: "",
},
}, },
}, {
id: "5",
label: "温度范围",
unit: "",
limit: {
down: "",
up: "",
},
},
];
arr.forEach((e) => {
ruleTypeOptions.value[e.id] = e;
});
await nextTick();
cb && cb();
}; };
const state = reactive({ const state = reactive({
form: { form: {
...@@ -158,19 +172,19 @@ const Submit = async () => { ...@@ -158,19 +172,19 @@ const Submit = async () => {
}; };
const riskLevels = ref([ const riskLevels = ref([
{ {
id: 1, id: 4,
name: "重大风险", name: "重大风险",
}, },
{ {
id: 2, id: 3,
name: "较大风险", name: "较大风险",
}, },
{ {
id: 3, id: 2,
name: "一般风险", name: "一般风险",
}, },
{ {
id: 4, id: 1,
name: "低风险", name: "低风险",
}, },
]); ]);
...@@ -215,9 +229,13 @@ const setLimits = (index) => { ...@@ -215,9 +229,13 @@ const setLimits = (index) => {
}) || [] }) || []
); );
}; };
const rule_type = computed(() => {
// return props.rule_type
return "1";
});
const limit = computed(() => { const limit = computed(() => {
return ( return (
ruleTypeOptions[props.rule_type].limit || { ruleTypeOptions.value[rule_type.value].limit || {
down: "", down: "",
up: "", up: "",
} }
...@@ -227,7 +245,7 @@ const changeWarningThresholdFrom = (index) => { ...@@ -227,7 +245,7 @@ const changeWarningThresholdFrom = (index) => {
let { down, up } = limit.value; let { down, up } = limit.value;
if (down === "") return; if (down === "") return;
let { from, to } = state.form.ruleRows[index]; let { from, to } = state.form.ruleRows[index];
if (+from > +up || (index == 0 && +from < +down) || (to != "" && from > +to)) { if ((up != "" && +from > +up) || (index == 0 && +from < +down) || (to != "" && from > +to)) {
if (+from < +down) { if (+from < +down) {
ElMessage.error(`下限不能小于${down}`); ElMessage.error(`下限不能小于${down}`);
} else if (+from > +up) { } else if (+from > +up) {
...@@ -242,7 +260,7 @@ const changeWarningThresholdFrom = (index) => { ...@@ -242,7 +260,7 @@ const changeWarningThresholdFrom = (index) => {
if (rows.length == 0) return; if (rows.length == 0) return;
try { try {
rows.forEach((e) => { rows.forEach((e) => {
if (+e.up >= +from > +e.down) { if (e.up !== "" && e.down !== "" && +e.up >= +from > +e.down) {
throw ""; throw "";
} }
}); });
...@@ -252,13 +270,13 @@ const changeWarningThresholdFrom = (index) => { ...@@ -252,13 +270,13 @@ const changeWarningThresholdFrom = (index) => {
} }
}; };
const inputNum = (index, key) => { const inputNum = (index, key) => {
state.form.ruleRows[index][key] = state.form.ruleRows[index][key].replace(/[^\d]/g, ""); state.form.ruleRows[index][key] = +`${state.form.ruleRows[index][key]}`.replace(/[^\d]/g, "");
}; };
const changeWarningThresholdTo = (index) => { const changeWarningThresholdTo = (index) => {
let { down, up } = limit.value; let { down, up } = limit.value;
if (up === "") return; if (up === "") return;
let { from, to } = state.form.ruleRows[index]; let { from, to } = state.form.ruleRows[index];
if ((index == 0 && +to > +up) || +to < +down || (from != "" && +from > +to)) { if ((index == 0 && +to > +up) || (down != "" && +to < +down) || (from != "" && +from > +to)) {
if (+to > +up) { if (+to > +up) {
ElMessage.error(`上限不能超过${up}`); ElMessage.error(`上限不能超过${up}`);
} else if (+to < +down) { } else if (+to < +down) {
...@@ -273,7 +291,7 @@ const changeWarningThresholdTo = (index) => { ...@@ -273,7 +291,7 @@ const changeWarningThresholdTo = (index) => {
if (rows.length == 0) return; if (rows.length == 0) return;
try { try {
rows.forEach((e) => { rows.forEach((e) => {
if (+e.up > +to > +e.down) { if (e.up !== "" && e.down !== "" && +e.up > +to > +e.down) {
throw ""; throw "";
} }
}); });
...@@ -287,22 +305,25 @@ const removeRule = (index) => { ...@@ -287,22 +305,25 @@ const removeRule = (index) => {
}; };
watch( watch(
() => props.form, () => props.form,
(f) => { (n) => {
if (!f?.ruleRows) { if (!n || n?.length == 0) {
getRuleTypeOptions();
createRule(); createRule();
return; return;
} }
state.form.ruleRows = getRuleTypeOptions(() => {
f.ruleRows.map((e) => { state.form.ruleRows =
return { n?.map((e) => {
from: e.from, return {
to: e.to, from: e.from,
risk_level: e.risk_level, to: e.to,
}; risk_level: e.risk_level,
}) || []; };
if (state.form.ruleRows.length == 0) { }) || [];
createRule(); if (state.form.ruleRows.length == 0) {
} createRule();
}
});
}, },
{ {
deep: true, deep: true,
...@@ -325,7 +346,7 @@ defineExpose({ ...@@ -325,7 +346,7 @@ defineExpose({
&-item { &-item {
max-width: 1080px; max-width: 1080px;
width: 100%; width: 100%;
padding-left: 110px; padding-left: 120px;
:deep(.el-table thead th) { :deep(.el-table thead th) {
background-color: #f5f6f9; background-color: #f5f6f9;
} }
......
import { ElMessage } from "element-plus";
import axios from "@/request/http.js";
// max(container_fs_usage_bytes{pod!=\"\", namespace!=\"arms-prom\",namespace!=\"monitoring\"}) by (pod_name, namespace, device)/max(container_fs_limit_bytes{pod!=\"\"}) by (pod_name,namespace, device) * 100
const setParams = (res, { id }) => {
console.log('res: ', res);
let isEmpty = res.type_com_ref.isEmpty
let params = {
// 预警规则名称
metric_name: res.name,
// 持续时间
duration: +res.time,
// 持续时间单位
duration_unit: res.unit,
// 检查周期
check_period: +res.inspection_cycle,
// 预警通知方式
notify_method: res.manual_distribution_form.method,
// 预警通知人员列表
notify_recipients: res.manual_distribution_form.lists.map(e => {
return {
system_account: `${e.user_id}`,
user_name: `${e.user_name}`,
phone: `${e.phone}`
}
}),
// 消息推送次数
notify_push_count: +res.push_num,
// 消息推送频率
notify_push_frequency: +res.push_frequency,
// 是否立即启用
is_enabled: res.enabled ? 1 : 2
}
let params_push = {
// 自定义传参
custom: () => {
return {
detection_type: 2,
// 预警分类
class_parent_name: res.type_com_ref.warn_target,
// 预警对象
class_name: res.type_com_ref.warn_type,
// 预警指标
metric_config_name: res.type_com_ref.warn_indicator,
// 指标表达式
expr: res.type_com_ref.indicator_expression || "",
// 预警规则(下拉)
alert_rule_type: res.type_com_ref.rule_type,
// 预警规则对象数组
alert_condition,
alert_range: []
}
},
// 静态阈值传参
static: () => {
return {
detection_type: 1,
// 预警对象
class_id: +res.type_com_ref.warn_type,
metric_config_id: res.type_com_ref.warn_indicator,
// 报警范围(指标)
alert_range: res.type_com_ref.warning_scpoe_form.map(e => {
return {
variable_name: e.variable_name,
metric_name: e.metric_name,
chinese_name: e.chinese_name,
metric_label: e.metric_label,
is_required: e.is_required,
is_linked: e.is_linked,
value: e.select == 'all' ? '.*' : e.value,
compare: e.select == 'all' ? '=~' : e.select
}
}),
// // 预警规则(下拉)
// alert_rule_type: res.module_data.alert_rule_type,
}
}
}
let alert_condition = []
// debugger;
if (isEmpty) {
alert_condition = [{
thresholds_max: 0,
thresholds_min: 0,
risk_level: +res.type_com_ref.risk_level
}]
} else {
alert_condition = res.type_com_ref.ruleRows.map(e => {
return {
thresholds_max: +e.to,
thresholds_min: +e.from,
risk_level: +e.risk_level
}
})
}
params = {
...params,
...params_push[res.type_key](),
// 预警规则对象数组
alert_condition,
}
if (id) {
params.id = id
}
return params;
}
export const Save = (res, p, cb) => {
let params = setParams(res, p);
console.log('params: ', params);
return;
axios[p.id ? 'put' : 'post']('/v1/api/alert_rules', params).then(res => {
if (res.data.code == 200) {
ElMessage.success(`${p.id ? '编辑' : '新增'}成功`)
cb && cb()
} else {
ElMessage.error(res.data.data)
}
})
}
\ No newline at end of file
<template> <template>
<div class="static-form"> <div class="static-form">
<el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="110px"> <el-form :model="state.form" ref="form_ref" :rules="state.rules" label-width="120px">
<div class="static-form-item"> <div class="static-form-item">
<el-form-item label="预警对象/分类" prop="warn_type"> <el-form-item label="预警对象/分类" prop="warn_type">
<el-cascader <el-cascader
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
style="flex: 1" style="flex: 1"
:disabled="!formFormat.warn_type || props.isEdit" :disabled="!formFormat.warn_type || props.isEdit"
v-model="state.form.warn_indicator" v-model="state.form.warn_indicator"
placeholder="请选择预警指标"> placeholder="请选择预警指标"
<el-option v-for="(value, key) in warningIndexOptions" :key="key" :label="value" :value="key"> </el-option> @change="chooseWarnIndicator">
<el-option v-for="item in warningIndexOptions" :key="item.id" :label="item.metric_name" :value="item.id">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
...@@ -53,8 +55,8 @@ ...@@ -53,8 +55,8 @@
class="warn-scpoe-input-value" class="warn-scpoe-input-value"
v-model="state.form.warning_scpoe_form[index].value" v-model="state.form.warning_scpoe_form[index].value"
:placeholder="`请输入${item.chinese_name}`" :placeholder="`请输入${item.chinese_name}`"
v-if="!showSelect.includes(item.select)" v-if="!item.is_linked"
:disabled="item.select == 1"> :disabled="item.select == 'all'">
</el-input> </el-input>
<el-select <el-select
class="warn-scpoe-input-value" class="warn-scpoe-input-value"
...@@ -64,10 +66,10 @@ ...@@ -64,10 +66,10 @@
filterable filterable
:loading="item.loading" :loading="item.loading"
remote remote
:remote-method="(query) => remoteMethod(query, index)" :disabled="item.select == 'all'"
:remote-method="(query) => remoteMethod(query, index, item)"
multiple> multiple>
<el-option v-for="item in item.options" :key="item.id" :label="item.name" :value="item.id"> <el-option v-for="item in item.options" :key="item" :label="item" :value="item"> </el-option>
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
...@@ -83,7 +85,7 @@ ...@@ -83,7 +85,7 @@
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<Gateway v-else ref="warn_type_com" :rule_type="alert_rule_type" /> <Gateway v-else ref="warn_type_com" :form="rule_rows" :rule_type="alert_rule_type" />
</div> </div>
</div> </div>
</div> </div>
...@@ -98,33 +100,35 @@ ...@@ -98,33 +100,35 @@
</template> </template>
<script setup> <script setup>
import { computed, nextTick, reactive, ref, shallowReactive, watch } from "vue"; import { computed, nextTick, onMounted, reactive, ref, shallowReactive, watch } from "vue";
import gapTitle from "@/components/gap-title.vue"; import gapTitle from "@/components/gap-title.vue";
// import CommonCom from "./common-com.vue"; // import CommonCom from "./common-com.vue";
import Gateway from "./gateway.vue"; import Gateway from "./gateway.vue";
const showSelect = ["4", "5"]; import { ElMessage } from "element-plus";
import axios from "@/request/http.js";
const showSelect = ["=~", "!~"];
const selectRule = ref({ const selectRule = ref({
1: "全部", all: "全部",
2: "等于", "=": "等于",
3: "不等于", "!=": "不等于",
4: "正则匹配", "=~": "正则匹配",
5: "正则不匹配", "!~": "正则不匹配",
}); });
const riskLevelOptions = ref([ const riskLevelOptions = ref([
{ {
id: 1, id: 4,
name: "重大风险", name: "重大风险",
}, },
{ {
id: 2, id: 3,
name: "较大风险", name: "较大风险",
}, },
{ {
id: 3, id: 2,
name: "一般风险", name: "一般风险",
}, },
{ {
id: 4, id: 1,
name: "低风险", name: "低风险",
}, },
]); ]);
...@@ -145,15 +149,14 @@ const props = defineProps({ ...@@ -145,15 +149,14 @@ const props = defineProps({
}, },
}); });
const changeSelect = (index, item) => { const changeSelect = (index, item) => {
console.log("item.select: ", item.select); if (showSelect.includes(item.is_linked)) {
if (showSelect.includes(item.select)) {
state.form.warning_scpoe_form[index].value = []; state.form.warning_scpoe_form[index].value = [];
} else { } else {
state.form.warning_scpoe_form[index].value = ""; state.form.warning_scpoe_form[index].value = "";
} }
}; };
const validateValue = (rule, value, callback, item, index) => { const validateValue = (rule, value, callback, item, index) => {
if (!item.is_required || item.select == 1) return callback(); if (!item.is_required || item.select == "all") return callback();
if (item.value == "") { if (item.value == "") {
let msg = showSelect.includes(item.select) ? `请选择${item.chinese_name}` : `请输入${item.chinese_name}`; let msg = showSelect.includes(item.select) ? `请选择${item.chinese_name}` : `请输入${item.chinese_name}`;
return callback(new Error(msg)); return callback(new Error(msg));
...@@ -173,140 +176,72 @@ const state = reactive({ ...@@ -173,140 +176,72 @@ const state = reactive({
risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }], risk_level: [{ required: true, message: "请选择风险程度", trigger: "change" }],
}, },
}); });
const module_data = { const module_data = ref({});
id: "20da8f87-628a-4f0c-bd9c-0ad176d18d59", const alert_rule_type = ref("");
class_id: 101,
metric_name: "xx请求次数告警",
expr: 'shttp_requests_total{method="GET",$pod$}',
duration: 5,
duration_unit: "m",
check_period: 3,
is_enabled: 1,
alert_rule_type: "9f1e6170-65e8-4e14-9c17-6a7b87a900a7",
created_by: "",
created_at: "2023-06-28 17:28:29",
updated_by: "",
updated_at: "2023-06-28 17:54:33",
alert_range: [
{
variable_name: "$pod$",
metric_name: "shttp_requests_total",
metric_label: "pod",
chinese_name: "demoString",
is_required: true,
is_linked: true,
},
{
variable_name: "$image$",
metric_name: "shttp_requests_total",
metric_label: "image",
chinese_name: "镜像",
is_required: true,
is_linked: true,
},
],
};
const isEmpty = computed(() => { const isEmpty = computed(() => {
return false; return !alert_rule_type.value || alert_rule_type.value == "empty";
// return module_data.alert_rule_type == "9f1e6170-65e8-4e14-9c17-6a7b87a900a7";
});
state.form.warning_scpoe_form = module_data.alert_range.map((e) => {
return {
...e,
value: "",
select: "1",
options: [],
loading: false,
};
}); });
watch( const chooseWarnIndicator = () => {
() => state.form, axios
(n) => { .get("/v1/api/metric_config", {
console.log(n); params: {
}, id: state.form.warn_indicator,
{
deep: true,
}
);
const remoteMethod = (query, index) => {
console.log("query, index: ", query, index);
if (!query) {
state.form.warning_scpoe_form[index].options = [];
return;
}
state.form.warning_scpoe_form[index].loading = true;
setTimeout(() => {
state.form.warning_scpoe_form[index].loading = false;
state.form.warning_scpoe_form[index].options = [
{
id: 1,
name: 111,
}, },
{ })
id: 2, .then((res) => {
name: 222, if (res.data.code == 200) {
}, module_data.value = res.data.data;
]; alert_rule_type.value = module_data.value.alert_rule_type;
}, 1000); state.form.warning_scpoe_form = module_data.value.alert_range.map((e) => {
return {
...e,
value: "",
select: "all",
options: [],
loading: false,
};
});
} else {
ElMessage.error(res.data.data);
}
});
};
const remoteMethod = (query, index, item) => {
console.log("query, index, item: ", query, index, item);
// if (!query) {
// state.form.warning_scpoe_form[index].options = [];
// return;
// }
state.form.warning_scpoe_form[index].loading = true;
const params = {
// metric_name: item.metric_name,
metric_name: "grpc_client_handled_total",
// metric_label: item.metric_label,
metric_label: "grpc_method",
value: query,
};
axios.get(`/v1/api/prometheus/value`, { params }).then((res) => {
if (res.data.code == 200) {
state.form.warning_scpoe_form[index].options = res.data.data.list || [];
state.form.warning_scpoe_form[index].loading = false;
}
});
}; };
const warn_type_com_form = computed(() => props.form?.warn_type_com || null); const warn_type_com_form = computed(() => props.form?.warn_type_com || null);
watch(
() => props.form,
(n) => {
if (!n) return;
state.form.warn_type = n.warn_target && n.warn_type ? [n.warn_target, n.warn_type] : [];
state.form.warn_indicator = n.warn_indicator;
},
{ deep: true, immediate: true }
);
const cascaderProps = { const cascaderProps = {
value: "id", value: "class_id",
label: "label", label: "class_name",
};
const staticTypeOptions = ref([]);
const getStaticTypeOptions = () => {
axios.get("/v1/api/alert_class/tree").then(async (res) => {
if (res.data.code == 200) {
staticTypeOptions.value = res.data.data;
} else {
ElMessage.error(res.data.msg);
}
});
}; };
const staticTypeOptions = [
{
id: "1",
label: "容器云平台",
children: [
{
id: "colony",
label: "容器集群",
options: {
1: "服务中断",
2: "CPU使用率",
3: "内存使用率",
4: "磁盘使用率",
},
},
{
id: "node",
label: "容器节点",
options: {
1: "服务中断",
2: "CPU使用率",
3: "内存使用率",
4: "磁盘使用率",
},
},
{
id: "group",
label: "容器组",
options: {
1: "服务中断",
2: "CPU使用率",
3: "内存使用率",
},
},
{
id: "gateway",
label: "网关",
options: {
1: "平均响应时长(入口网关)",
},
},
],
},
];
const formFormat = computed(() => { const formFormat = computed(() => {
let [warn_target = "", warn_type = ""] = state.form.warn_type || []; let [warn_target = "", warn_type = ""] = state.form.warn_type || [];
let obj = { let obj = {
...@@ -314,21 +249,40 @@ const formFormat = computed(() => { ...@@ -314,21 +249,40 @@ const formFormat = computed(() => {
warn_target, warn_target,
warn_type, warn_type,
isEmpty: isEmpty.value, isEmpty: isEmpty.value,
// module_data: module_data.value
}; };
if (isEmpty.value) { if (!isEmpty.value) {
obj.warn_type_com = warn_type_com.value?.form || {}; obj = {
...obj,
...(warn_type_com.value?.form || {}),
};
} }
return obj; return obj;
}); });
const warningIndexOptions = ref({}); const warningIndexOptions = ref({});
const cascader_ref = ref(null); const cascader_ref = ref(null);
const changeWarnStaticType = async () => { const changeWarnStaticType = async () => {
const { data } = cascader_ref.value.getCheckedNodes()[0]; // const { data } = cascader_ref.value.getCheckedNodes()[0];
warningIndexOptions.value = data.options; let class_id = state.form.warn_type[1];
let keys = Object.keys(warningIndexOptions.value); let params = { page: 1, page_size: 10000000000000, class_id };
state.form.warn_indicator = keys[0]; getWarningIndicator(params);
setTimeout(() => { };
form_ref.value.clearValidate(["warn_indicator"]); const getWarningIndicator = (params, cb) => {
axios.get("/v1/api/metric_config/list", { params }).then((res) => {
if (res.data.code == 200) {
warningIndexOptions.value = res.data.data?.list || [];
if (!cb) {
state.form.warn_indicator = warningIndexOptions.value[0]?.id || "";
if (state.form.warn_indicator) {
chooseWarnIndicator();
}
} else {
cb();
}
setTimeout(() => {
form_ref.value.clearValidate(["warn_indicator"]);
});
}
}); });
}; };
const changeRuleType = () => {}; const changeRuleType = () => {};
...@@ -339,7 +293,7 @@ const Submit = async () => { ...@@ -339,7 +293,7 @@ const Submit = async () => {
form_ref.value.validate((res) => resolve(res)); form_ref.value.validate((res) => resolve(res));
}); });
if (isEmpty.value) return form_valid; if (isEmpty.value) return form_valid;
let warn_type_com_valid = (await warn_type_com.value?.Submit()) || true; let warn_type_com_valid = await warn_type_com.value?.Submit();
return form_valid && warn_type_com_valid; return form_valid && warn_type_com_valid;
}; };
const ruleHeaders = [ const ruleHeaders = [
...@@ -353,6 +307,24 @@ const ruleHeaders = [ ...@@ -353,6 +307,24 @@ const ruleHeaders = [
label: "风险程度", label: "风险程度",
}, },
]; ];
const rule_rows = computed(() => props.form?.ruleRows || []);
watch(
() => props.form,
(n) => {
if (!n) return;
state.form.warn_type = n.warn_target && n.warn_type ? [n.warn_target, n.warn_type] : [];
state.form.warn_indicator = n.warn_indicator;
alert_rule_type.value = n.rule_type || "1";
let params = { page: 1, page_size: 10000000000000, class_id: n.warn_type };
getWarningIndicator(params, () => {
state.form.warning_scpoe_form = n?.warning_scpoe_form || [];
});
},
{ deep: true, immediate: true }
);
onMounted(() => {
getStaticTypeOptions();
});
defineExpose({ defineExpose({
Submit, Submit,
form: formFormat, form: formFormat,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment