Commit 85b0c4af authored by 张俊's avatar 张俊

[feat](任务管理): 接口对接70%

parent e8660ffb
......@@ -143,9 +143,9 @@ const { content } = toRefs(states);
right: 0 !important;
}
/* 光标颜色 */
.vue-ace-editor :deep() .ace_cursor {
/* .vue-ace-editor :deep() .ace_cursor {
color: #fff;
}
} */
.vue-ace-editor-disable :deep() .ace_scrollbar-v {
width: 6px !important;
right: 2px;
......
......@@ -2,7 +2,12 @@
<div>
<el-form ref="ruleFormRef" :model="state.ruleForm" :rules="state.rules" label-position="top" label-width="120px">
<el-form-item label="任务名称" prop="name">
<el-input v-model="state.ruleForm.name" maxlength="20" placeholder="请输入任务名称" show-word-limit />
<el-input
v-model="state.ruleForm.name"
maxlength="20"
:disabled="props.isEdit"
placeholder="请输入任务名称"
show-word-limit />
</el-form-item>
<el-form-item label="任务描述" prop="desc">
<el-input
......@@ -31,6 +36,10 @@ const props = defineProps({
type: Object,
default: () => {},
},
isEdit: {
type: Boolean,
default: false,
},
});
const ruleFormRef = ref(null);
......
......@@ -2,11 +2,11 @@
<div class="step-container">
<div class="step-base">
<img src="@/assets/imgs/img_data-complete.png" />
<p class="tips" v-if="props.state">新增成功</p>
<p class="tips" v-else>新增失败</p>
<p class="tips" v-if="props.state">{{ ["新增", "编辑", "复制"][props.finishType] }}成功</p>
<p class="tips" v-else>{{ ["新增", "编辑", "复制"][props.finishType] }}失败</p>
<div class="apaas_button btns" v-if="props.state">
<el-button type="default" @click="goToList"> 返回列表 </el-button>
<el-button type="primary" @click="goStepOne"> 继续新增 </el-button>
<el-button type="primary" @click="goStepOne"> {{ props.finishType == 1 ? "重新提交" : "继续新增" }} </el-button>
</div>
</div>
</div>
......@@ -24,6 +24,10 @@ const props = defineProps({
type: Boolean,
default: true,
},
finishType: {
type: Number,
default: 0,
},
});
const emit = defineEmits(["clear"]);
......
......@@ -42,10 +42,28 @@
<div
class="content_main log_content_nor"
:style="step == 3 && state.isSave ? { height: 'calc(100vh - 234px)' } : {}">
<base-info v-show="step == 1" :data="state.data" ref="baseInfoRef"></base-info>
<use-content v-show="step == 2" :data="state.data" ref="useContentRef"></use-content>
<finish v-show="step == 3 && state.isSave" :state="true" @clear="clearData"></finish>
<finish-use v-show="step == 3 && !state.isSave" :state="true" time="00:00:11"></finish-use>
<base-info
v-show="step == 1"
v-if="state.loadComponents"
:isEdit="state.pageType == 1"
:data="state.data"
ref="baseInfoRef"></base-info>
<use-content
v-show="step == 2"
v-if="state.loadComponents"
:data="state.data"
ref="useContentRef"></use-content>
<finish
v-show="step == 3 && state.isSave"
:state="state.status"
:finishType="state.pageType"
v-if="state.loadComponents"
@clear="clearData"></finish>
<finish-use
v-show="step == 3 && !state.isSave"
v-if="state.loadComponents"
:state="state.status"
time="00:00:11"></finish-use>
</div>
<div class="content_foot apaas_button" v-if="step == 1 || step == 2 || (step == 3 && !state.isSave)">
<el-button type="default" v-if="step == 1 || step == 2" @click="cancel"> 取消 </el-button>
......@@ -104,6 +122,9 @@ const state = reactive({
useData: ["yaml", "json"],
useText: "",
isSave: true,
status: true,
pageType: 0, //0新增,1编辑,2复制
loadComponents: false, //控制子组件的加载
});
const cancel = () => {
......@@ -131,11 +152,55 @@ const saveTask = async () => {
.save()
.then(() => {
step.value = 3;
//todo:掉接口保存,并获取状态
if (state.pageType == 0 || state.pageType == 2) {
postTask();
} else if (state.pageType == 1) {
editTask();
}
})
.catch(() => {});
};
const editTask = () => {
axios
.put(`/v1/api/automated_mainten/task_manage/edit`, {
task_name: state.data.name,
task_desc: state.data.desc,
yaml_desc: state.data.useText,
yaml_url: JSON.stringify(state.data.doc_file),
host_group_id: state.data.pcName,
})
.then((res) => {
if (res.data.code == 200) {
state.status = true;
ElMessage.success("保存成功");
} else {
state.status = false;
ElMessage.error(res.data.msg);
}
});
};
const postTask = () => {
axios
.post(`/v1/api/automated_mainten/task_manage/add`, {
task_name: state.data.name,
task_desc: state.data.desc,
yaml_desc: state.data.useText,
yaml_url: JSON.stringify(state.data.doc_file),
host_group_id: state.data.pcName,
})
.then((res) => {
if (res.data.code == 200) {
state.status = true;
ElMessage.success("保存成功");
} else {
state.status = false;
ElMessage.error(res.data.msg);
}
});
};
const useScript = async () => {
//填写完成才可以进行执行
await useContentRef.value
......@@ -167,9 +232,53 @@ const clearData = () => {
useContentRef.value.clear();
state.data = {};
step.value = 1;
state.loadComponents = false;
init();
};
onBeforeMount(() => {});
const getDetails = () => {
axios
.get(`/v1/api/automated_mainten/task_manage/details`, {
params: {
id: route.query.id,
},
})
.then((res) => {
if (res.data.code == 200) {
let data = res.data.data;
state.data = {
name: data.task_name,
desc: data.task_desc,
useText: data.yaml_desc,
doc_file: data.yaml_url ? JSON.parse(data.yaml_url) : [],
pcName: data.host_group_id,
};
//复制,名字置空
if (state.pageType == 2) {
state.data.name = "";
}
state.loadComponents = true;
}
});
};
const init = () => {
if (route.path.indexOf("edit") > -1) {
state.pageType = 1;
} else if (route.path.indexOf("copy") > -1) {
state.pageType = 2;
}
if (state.pageType !== 0) {
getDetails();
} else {
state.loadComponents = true;
}
};
onBeforeMount(() => {
state.loadComponents = false;
init();
});
</script>
<style scoped>
......
......@@ -17,9 +17,9 @@
<el-form ref="pcFormRef" :model="state.ruleForm" :rules="state.rules" label-position="top" label-width="120px">
<el-form-item label="主机分组名称" prop="pcName" style="width: 1100px">
<el-select v-model="state.ruleForm.pcName" style="width: 1020px" clearable placeholder="请选择">
<el-option v-for="item in state.options" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in state.options" :key="item.id" :label="item.host_name" :value="item.id" />
</el-select>
<span class="add-pc can_click_text">去创建</span>
<span class="add-pc can_click_text" @click="gotoPage(`/auto-maintenance/host-manage/add`)">去创建</span>
</el-form-item>
</el-form>
</div>
......@@ -28,6 +28,7 @@
<script setup>
import { reactive, ref, onBeforeMount, toRefs, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
import axios from "@/request/http.js";
import { ElMessage } from "element-plus";
const router = useRouter();
const route = useRoute();
......@@ -52,14 +53,13 @@ const state = reactive({
rules: {
pcName: [{ required: true, message: "请选择主机分组", trigger: "change" }],
},
options: [
{
label: "12",
value: "qwqw",
},
],
options: [],
});
const gotoPage = (url) => {
router.push(url);
};
const save = () => {
return new Promise((resolve, reject) => {
pcFormRef.value.validate((valid, fields) => {
......@@ -67,7 +67,9 @@ const save = () => {
props.data.pcName = state.ruleForm.pcName;
if (state.useType == 0) {
props.data.useText = state.useText;
props.data.doc_file = [];
} else {
props.data.useText = "";
props.data.doc_file = state.doc_file;
}
resolve();
......@@ -86,17 +88,26 @@ const clear = () => {
state.useType = 0;
};
const getPC = () => {
axios.get(`/v1/api/automated_mainten/host_manage/list`).then((res) => {
if (res.data.code == 200) {
state.options = res.data.data || [];
}
});
};
onMounted(() => {
if (
(props.data && props.data.useText == "" && props.data.doc_file.length == 0) ||
(!props.data.useText && !props.data.doc_file)
) {
state.useType = 0;
} else if (props.data && props.data.useText !== "") {
} else if (props.data && props.data.useText == "") {
state.useType = 1;
} else if (props.data && props.data.doc_file.length == 0) {
state.useType = 0;
}
getPC();
});
defineExpose({
......
......@@ -3,19 +3,15 @@
<bg-breadcrumb></bg-breadcrumb>
<div class="main_container">
<bg-form-gap title="基本信息"></bg-form-gap>
<bg-detail-table2 style="width: 1076px" :list="state.baseInfo">
<template #status>
<span> <i class="use"></i> 启用 </span>
</template>
</bg-detail-table2>
<bg-detail-table2 style="width: 1076px; margin-bottom: 20px" :list="state.baseInfo"> </bg-detail-table2>
<bg-form-gap title="执行脚本"></bg-form-gap>
<div style="height: 260px; margin-bottom: 20px; width: 1076px">
<bg-code-editor v-model="state.useText"></bg-code-editor>
<div v-if="state.docFile.length == 0" style="height: 260px; margin-bottom: 20px; width: 1076px">
<bg-code-editor :disabled="true" v-model="state.useText"></bg-code-editor>
</div>
<div class="file-box">
<bg-icon icon="#bg-ic-c-file-data"></bg-icon>&nbsp;&nbsp; 文件.yml
<el-button type="primary" @click="downloadFile(url)"
<div class="file-box" v-for="(item, index) in state.docFile">
<bg-icon icon="#bg-ic-c-file-data"></bg-icon>&nbsp;&nbsp; {{ item.name }}
<el-button type="primary" @click="download(item.url, item.name)"
><bg-icon icon="#bg-ic-to-bottom"></bg-icon>&nbsp;&nbsp;下载</el-button
>
</div>
......@@ -38,9 +34,20 @@
<bg-table style="width: 1076px" :headers="state.historyHeaders" :rows="state.historyTableRows" :stripe="true">
<template v-slot:state="{ row }">
<span>
{{ row.state }}
<bg-icon
:style="{
color: ['#2b4695', '#429e8a', '#d75138'][row.state],
}"
:icon="
['#bg-ic-s-circle-restart', '#bg-ic-s-circle-check', '#bg-ic-s-circle-close'][row.state]
"></bg-icon>
{{ ["执行中", "成功", "失败"][row.state] }}
</span>
</template>
<template v-slot:exec_start_time="{ row }">
<span>{{ dateStringTransform(row.exec_start_time) }}</span>
</template>
</bg-table>
<div style="width: 1076px" v-if="state.tableTotal > 10">
<bg-pagination
......@@ -60,45 +67,43 @@ import { reactive, ref, onBeforeMount, toRefs } from "vue";
import { useRouter, useRoute } from "vue-router";
import { ElMessage } from "element-plus";
import bgBreadcrumb from "@/components/bg-breadcrumb.vue";
import axios from "@/request/http.js";
import { dateStringTransform, downloadFile } from "@/services/helper.js";
const router = useRouter();
const route = useRoute();
const state = reactive({
baseInfo: [
{
label: "预警规则名称",
value: "服务中断推送规则1",
label: "任务名称",
value: "",
},
{
label: "启用状态",
value: "启用",
childSlot: "status",
label: "执行次数",
value: "",
},
{
label: "预警对象",
value: "容器云",
label: "执行成功次数",
value: "",
},
{
label: "预警分类",
value: "容器集群",
label: "执行失败次数",
value: "",
},
{
label: "创建人",
value: "admin",
value: "",
},
{
label: "创建时间",
value: "2023-08-19 23:22:22",
value: "",
},
{
label: "更新时间",
value: "2023-08-19 23:22:22",
},
{
label: "预警指标",
value: "CPU使用率",
label: "任务描述",
value: "",
},
],
useText: "",
docFile: [],
historyHeaders: [
{
label: "状态",
......@@ -106,19 +111,19 @@ const state = reactive({
},
{
label: "执行说明",
prop: "desc",
prop: "exec_desc",
},
{
label: "执行开始时间",
prop: "begin",
prop: "exec_start_time",
},
{
label: "执行耗时",
prop: "time",
label: "执行耗时(s)",
prop: "exec_time",
},
{
label: "操作人",
prop: "person",
prop: "create_user",
},
],
historyTableRows: [],
......@@ -129,38 +134,77 @@ const state = reactive({
tableTotal: 0,
pcHeaders: [
{
label: "账号",
prop: "account",
label: "IP",
prop: "ip",
},
{
label: "端口",
prop: "port",
},
],
pcTableRows: [
{
account: "asasdd",
port: "8080",
},
{
account: "asasdd",
port: "8080",
},
],
pcTableRows: [],
});
const downloadFile = () => {};
const download = (url, name) => {
downloadFile(url, name);
};
const changePage = (page) => {
state.filter.page = page;
getTableRows();
};
const changeSize = (size) => {
state.filter.limit = size;
state.filter.size = size;
changePage(1);
};
const getTableRows = () => {};
const getTableRows = () => {
axios
.get(`/v1/api/automated_mainten/task_history/task_info_list`, {
params: {
task_id: route.query.id,
page: state.filter.page,
page_size: state.filter.size,
},
})
.then((res) => {
if (res.data.code == 200) {
state.historyTableRows = res.data.data;
state.tableTotal = res.data.total;
}
});
};
const getDetails = () => {
axios
.get(`/v1/api/automated_mainten/task_manage/details`, {
params: {
id: route.query.id,
},
})
.then((res) => {
if (res.data.code == 200) {
let data = res.data.data;
state.baseInfo[0].value = data.task_name;
state.baseInfo[1].value = data.exec_cnt;
state.baseInfo[2].value = data.success_cnt;
state.baseInfo[3].value = data.fail_cnt;
state.baseInfo[4].value = data.create_user;
state.baseInfo[5].value = data.create_time.split("+")[0].replace("T", " ").replace("Z", " ");
state.baseInfo[6].value = data.task_desc;
state.useText = data.yaml_desc;
state.docFile = data.yaml_url ? JSON.parse(data.yaml_url) : [];
state.pcTableRows = data.host_list || [];
}
});
};
onBeforeMount(() => {
getDetails();
getTableRows();
});
</script>
<style lang="scss" scoped>
......
......@@ -11,7 +11,7 @@
</el-button>
<el-button type="default" @click="deleteAllTips"> 批量删除 </el-button>
<span class="header_info"
>已选择 <span style="color: #202531; font-weight: bold"> {{ state.selected.length }} </span>
>已选择 <span style="color: #202531; font-weight: bold"> {{ state.selectedNum }} </span>
</span>
<span class="header_info can_click_text" @click="clearSelected">清空</span>
</div>
......@@ -23,7 +23,7 @@
<el-date-picker
v-model="filter.time"
type="daterange"
value-format="yyyy-MM-DD"
value-format="YYYY-MM-DD"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期" />
......@@ -45,13 +45,13 @@
:isIndex="true"
:select="true"
:stripe="true">
<template v-slot:name="{ row }">
<template v-slot:task_name="{ row }">
<span class="can_click_text" @click="gotoPage(`/auto-maintenance/task-manage/detail?id=${row.id}`)">
{{ row.name }}
{{ row.task_name }}
</span>
</template>
<template v-slot:updated_time="{ row }">
{{ row.updated_time.split("+")[0].replace("T", " ").replace("Z", " ") }}
<template v-slot:create_time="{ row }">
{{ row.create_time.split("+")[0].replace("T", " ").replace("Z", " ") }}
</template>
<template v-slot:action="{ row }">
<bg-table-btns2 :limit="3" :tableData="tableRows">
......@@ -128,25 +128,26 @@ const dataTable = ref(null);
const headers = [
{
label: "任务名称",
prop: "name",
prop: "task_name",
width: 200,
},
{
label: "执行次数",
prop: "times",
prop: "exec_cnt",
},
{
label: "描述",
prop: "describe",
minWidth: 360,
prop: "task_desc",
minWidth: 300,
},
{
label: "创建人",
prop: "person",
prop: "create_user",
},
{
label: "创建时间",
prop: "updated_time",
width: 220,
prop: "create_time",
width: 180,
},
{
label: "操作",
......@@ -157,28 +158,22 @@ const headers = [
];
const state = reactive({
tableRows: [
{
name: 23123,
times: 1,
describe: 12313,
person: 21323,
updated_time: "2021-01-01+TZ",
},
], // 表格数据
tableRows: [], // 表格数据
selected: [], //选择数据
selectedNum: 0, //选择数据数量
tableTotal: 0, // 表格数据条数
filter: {
time: "",
search: "",
page: 1,
limit: 10,
page_size: 10,
}, // 表格筛选项
actionRow: null, // 当前操作的数据
dialogDelete: false, // 删除弹窗
useScriptShow: false,
useType: 0,
useData: ["yaml", "json"],
deleteType: 0, //0单个删除,1批量删除
});
const useRow = (row) => {
......@@ -197,13 +192,38 @@ const confirmUse = () => {
const deleteRow = (row) => {
state.actionRow = row;
state.dialogDelete = true;
state.deleteType = 0;
};
const deleteData = () => {
state.dialogDelete = false;
let ids = [];
if (state.deleteType == 0) {
ids = [state.actionRow.id];
} else {
let dealData = dataTable.value.dealSelectData();
for (const key in dealData) {
ids.push(dealData[key].id);
}
}
axios
.delete(`/v1/api/automated_mainten/task_manage/del`, {
data: {
id: ids,
},
})
.then((res) => {
if (res.data.code == 200) {
ElMessage.success("删除成功");
changePage(1);
} else {
ElMessage.error(res.data.msg);
}
});
};
const selectRows = (data) => {
state.selectedNum = data.allLength;
state.selected = data.selection;
};
......@@ -214,6 +234,7 @@ const clearSelected = () => {
const deleteAllTips = () => {
if (state.selected.length > 0) {
state.dialogDelete = true;
state.deleteType = 1;
} else {
ElMessage.error("请先选择要删除任务");
}
......@@ -236,21 +257,30 @@ const filterClear = () => {
state.filter = {
time: "",
search: "",
limit: 10,
page: 1,
page_size: 10,
};
changePage(1);
}; // 重置筛选项
const getTableRows = () => {
let params = { ...state.filter };
if (params.time) {
params.create_date_from = params.time[0];
params.create_date_to = params.time[1];
} else {
params.create_date_from = "";
params.create_date_to = "";
}
axios
.get(`/apaas/system/v5/dictionary/list`, {
.get(`/v1/api/automated_mainten/task_manage/list`, {
params,
})
.then((res) => {
if (res.data.code == 200) {
let data = res.data.data || [];
state.tableRows = data;
state.tableTotal = res.data.total;
} else {
ElMessage.error(res.data.data);
}
......@@ -263,11 +293,13 @@ const changePage = (page) => {
}; // 改变页码
const changeSize = (size) => {
state.filter.limit = size;
state.filter.page_size = size;
changePage(1);
}; // 改变每页条数
onBeforeMount(() => {});
onBeforeMount(() => {
getTableRows();
});
const { tableRows, tableTotal, filter } = toRefs(state);
</script>
......
......@@ -299,6 +299,18 @@ const downloadBlob = (blobData, type, fileName) => {
window.URL.revokeObjectURL(url);
};
const downloadFile = (url, fileName) => {
const aLink = document.createElement("a");
aLink.style.display = "none";
aLink.href = url;
//指定文件名,不指定就默认
if (fileName) aLink.setAttribute("download", fileName);
document.body.appendChild(aLink);
aLink.click();
/** 下载完成移除元素 */
document.body.removeChild(aLink);
};
export {
GetProperty,
dateFormat,
......@@ -317,4 +329,5 @@ export {
getFirstChild,
getImageUrl,
downloadBlob,
downloadFile,
};
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