CMVR-IOT-UI/src/views/test/configs/index.vue
2025-09-11 15:42:24 +08:00

697 lines
19 KiB
Vue

<template>
<div class="app-container">
<div ref="topContainerRef">
<TableSearch
:queryParams="queryParams"
:showSearch="showSearch"
queryRef="queryRef"
@refresh="resetQuery"
@search="handleQuery"
>
<template #one>
<el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24" :xxl="6">
<el-form-item label="任务名称" prop="taskName">
<el-input
v-model="queryParams.taskName"
clearable
placeholder="请输入任务名称"
style="width: 100%"
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
<el-col :lg="6" :md="12" :sm="24" :xl="6" :xs="24" :xxl="6">
<el-form-item label="任务描述" prop="taskDesc">
<el-input
v-model="queryParams.taskDesc"
clearable
placeholder="请输入任务描述"
style="width: 100%"
@keyup.enter="handleQuery"
/>
</el-form-item>
</el-col>
</template>
</TableSearch>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
v-hasPermi="['test:config:add']"
icon="Plus"
plain
type="primary"
@click="handleAdd"
>新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['test:config:edit']"
:disabled="single"
icon="Edit"
plain
type="success"
@click="handleUpdate"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
v-hasPermi="['test:config:remove']"
:disabled="multiple"
icon="Delete"
plain
type="danger"
@click="handleDelete"
>删除
</el-button>
</el-col>
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
</div>
<div :style="containerHeight">
<el-table
v-loading="loading"
height="100%"
:data="configList"
@selection-change="handleSelectionChange"
>
<el-table-column align="center" type="selection" width="55" />
<el-table-column
align="center"
label="id"
prop="id"
show-overflow-tooltip
/>
<el-table-column
align="center"
label="任务名称"
prop="taskName"
show-overflow-tooltip
/>
<el-table-column
align="center"
label="分组名称"
prop="groupName"
show-overflow-tooltip
/>
<el-table-column
align="center"
label="任务描述"
prop="taskDesc"
show-overflow-tooltip
/>
<el-table-column
align="center"
label="备注"
prop="remark"
show-overflow-tooltip
/>
<el-table-column align="center" label="状态" prop="status">
<template #default="scope">
<el-switch
v-model="scope.row.status"
active-text="启用"
active-value="0"
inactive-text="停用"
inactive-value="1"
inline-prompt
@change="handleChange(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
align="center"
class-name="small-padding fixed-width"
label="操作"
width="280"
>
<template #default="scope">
<el-button
v-hasPermi="['test:config:edit']"
icon="Edit"
link
type="primary"
@click="handleUpdate(scope.row)"
>
修改
</el-button>
<el-button
v-hasPermi="['test:config:config']"
icon="Finished"
link
type="primary"
@click="handleTaskConfig(scope.row)"
>编排
</el-button>
<el-button
v-hasPermi="['test:config:execute']"
icon="Cpu"
link
type="primary"
@click="handleTaskExecuteOpen(scope.row)"
>执行
</el-button>
<el-button
v-hasPermi="['test:config:remove']"
icon="Delete"
link
type="primary"
@click="handleDelete(scope.row)"
>删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNum"
:total="total"
@pagination="getList"
/>
</div>
<!-- 添加或修改任务流程编排对话框 -->
<el-dialog v-model="open" :title="title" append-to-body width="500px">
<el-form ref="configRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="任务名称" prop="taskName">
<el-input v-model="form.taskName" placeholder="请输入任务名称" />
</el-form-item>
<el-form-item label="任务描述" prop="taskDesc">
<el-input v-model="form.taskDesc" placeholder="请输入任务描述" />
</el-form-item>
<el-form-item label="所属分组">
<el-select v-model="form.groupId" placeholder="请选择所属分组">
<el-option
v-for="group in groupList"
:key="group.value"
:label="group.label"
:value="group.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="form.remark"
:rows="2"
placeholder="请输入备注"
type="textarea"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 自定义任务流程编排对话框 -->
<el-dialog
v-model="taskConfigOpen"
:title="title"
append-to-body
width="700px"
@closed="resetTaskList"
@open="handleTaskConfigOpen"
>
<el-row :gutter="24">
<el-col :span="12">
<div style="height: 55vh">
<div class="task-title">待检测项</div>
<draggable
:animation="340"
:forceFallback="true"
:list="taskLeftList"
class="draggable-group"
ghostClass="dragClass"
group="people"
itemKey="name"
>
<template #item="{ element, index }">
<div class="list-group-item">
<el-icon>
<Tools />
</el-icon>
{{ element.name }}
</div>
</template>
</draggable>
</div>
</el-col>
<el-col :span="12">
<div style="height: 55vh">
<div class="task-title">流程编排</div>
<draggable
:animation="340"
:forceFallback="true"
:list="taskRightList"
class="draggable-group"
ghostClass="dragClass"
group="people"
itemKey="name"
>
<template #item="{ element, index }">
<div class="list-group-item">
{{ index + 1 }} 、{{ element.name }}
</div>
</template>
</draggable>
</div>
</el-col>
</el-row>
<div class="custom-block">
<div class="mb5">1、将待检测项拖拽至流程编排中</div>
<div>2、流程编排中可拖拽自定义其顺序</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitTaskForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
<!-- 任务参数填写对话框 -->
<el-drawer
v-model="taskExecuteOpen"
:title="title"
append-to-body
destroy-on-close
modal-class="test-config"
size="600"
@closed="resetTaskList"
@open="paramsOpen"
>
<el-form ref="dynamicFormRef" :model="fModel">
<el-card
v-for="(item, idx) in fModel.list"
:header="`${item.itemName}的参数`"
style="margin-bottom: 20px"
>
<template v-for="(paramItem, paramItemIdx) in item.params">
<el-form-item
:label="paramItem['paramCnName']"
:prop="'list.' + idx + '.params.' + paramItemIdx + '.sourceValue'"
:rules="{
required: paramItem['required'],
message: '此项为必填',
trigger: 'blur',
}"
>
<el-input v-model="paramItem['sourceValue']"></el-input>
</el-form-item>
</template>
</el-card>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="() => (executeOpen = true)"
>执 行</el-button
>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-drawer>
<Run
:drawer="executeOpen"
@close="executeOpen = false"
:currentRow="currentRow"
/>
</div>
</template>
<script name="Config" setup>
import {
addConfig,
delConfig,
getConfig,
getTaskConfig,
getTaskParamsById,
listConfig,
taskConfig,
taskExecute,
updateConfig,
} from "@/api/test/config";
import { flowExecute } from "@/api/device/flow";
import TableSearch from "@/components/TableSearch/index.vue";
import draggable from "vuedraggable";
import { listDetect } from "@/api/test/detect.js";
import { Tools } from "@element-plus/icons-vue";
import { listGroup } from "@/api/system/group.js";
import { listTerminal } from "@/api/device/terminal.js";
import Run from "./Run.vue";
import { ref, reactive, toRefs, onMounted } from "vue";
import { useContainerHeight } from "@/hooks/tableHeight";
const topContainerRef = ref();
const containerHeight = useContainerHeight(topContainerRef);
const { proxy } = getCurrentInstance();
const configList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const taskConfigOpen = ref(false);
const taskExecuteOpen = ref(false);
const executeOpen = ref(false);
const currentRow = ref(undefined);
const dynamicFormRef = ref();
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
taskCode: null,
taskName: null,
taskDesc: null,
status: null,
versionNo: null,
groupCode: null,
},
paramsFormList: [],
rules: {},
});
const { queryParams, form, rules, paramsFormList } = toRefs(data);
const taskLeftList = ref([]);
const taskRightList = ref([]);
/** 查询任务流程编排列表 */
function getList() {
loading.value = true;
listConfig(queryParams.value).then((response) => {
configList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 取消按钮
function cancel() {
open.value = false;
taskExecuteOpen.value = false;
taskConfigOpen.value = false;
executeOpen.value = false;
selectedTerminal.value = "";
reset();
}
// 表单重置
function reset() {
form.value = {
// id: null,
// createBy: null,
// createTime: null,
// updateBy: null,
// updateTime: null,
// remark: null,
// taskCode: null,
// taskName: null,
// taskDesc: null,
// status: null,
// versionNo: null,
// groupCode: null
};
proxy.resetForm("configRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
function handleAdd() {
reset();
open.value = true;
title.value = "添加任务流程编排";
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const _id = row.id || ids.value;
getConfig(_id).then((response) => {
form.value = response.data;
open.value = true;
title.value = "修改任务流程编排";
});
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["configRef"].validate((valid) => {
if (valid) {
if (form.value.id != null) {
updateConfig(form.value).then((response) => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addConfig(form.value).then((response) => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal
.confirm('是否确认删除任务流程编排编号为"' + _ids + '"的数据项?')
.then(function () {
return delConfig(_ids);
})
.then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
})
.catch(() => {});
}
/** 导出按钮操作 */
function handleExport() {
proxy.download(
"test/config/export",
{
...queryParams.value,
},
`config_${new Date().getTime()}.xlsx`
);
}
function handleChange(row) {
updateConfig({ status: row.status, id: row.id }).then((response) => {
proxy.$modal.msgSuccess("修改成功");
getList();
});
}
function handleTaskConfig(row) {
taskConfigOpen.value = true;
currentRow.value = row;
}
//获取左侧待检测项数据
const getLiftTaskList = () => {
listDetect({ isDeploy: "0" }).then((response) => {
let tempLeftData =
response.rows?.map((item) => {
return {
name: item.detectName,
id: item.id,
};
}) || [];
if (taskRightList.value.length === 0) {
taskLeftList.value = tempLeftData;
return;
}
taskLeftList.value = tempLeftData.filter((item) => {
return !taskRightList.value.some((item2) => {
return item.id === item2.id;
});
});
});
};
//获取右侧编排数据
const getRightTaskList = () => {
getTaskConfig({ taskId: currentRow.value.id }).then((response) => {
taskRightList.value =
response.rows?.map((item) => {
return {
name: item.itemName,
id: item.itemId,
};
}) || [];
getLiftTaskList();
});
};
const handleTaskConfigOpen = (v) => {
getRightTaskList();
};
const resetTaskList = () => {
taskLeftList.value = [];
taskRightList.value = [];
currentRow.value = undefined;
};
const submitTaskForm = () => {
const taskId = currentRow.value.id;
const taskIds = taskRightList.value.map((item) => item.id);
const data = Object.assign({}, { taskId, itemIds: taskIds });
taskConfig(data).then((res) => {
proxy.$modal.msgSuccess("操作成功");
taskConfigOpen.value = false;
resetTaskList();
getList();
});
};
const formatCode = (arr) => {
return arr.map((item) => ({
itemId: item.detectId,
params: item.params.reduce((acc, param) => {
acc[param.paramEnName] = param.sourceValue;
return acc;
}, {}),
}));
};
const handleTaskExecute = (formEl) => {
if (!selectedTerminal.value) {
proxy.$modal.msgError("请选择执行终端");
return;
}
const data = Object.assign(
{},
{ runParams: { terminalId: selectedTerminal.value } },
{ taskId: currentRow.value.id }
);
// taskExecute(data).then((res) => {
// proxy.$modal.msgSuccess("下发成功")
// resetTaskList()
// executeOpen.value = false
// taskExecuteOpen.value = false
// currentRow.value = undefined
// selectedTerminal.value = ""
// })
flowExecute(data).then((res) => {
console.log("res", res);
proxy.$modal.msgSuccess("下发成功");
resetTaskList();
executeOpen.value = false;
taskExecuteOpen.value = false;
currentRow.value = undefined;
selectedTerminal.value = "";
});
};
const handleTaskExecuteOpen = (row) => {
currentRow.value = row;
executeOpen.value = true;
title.value = "任务执行";
};
const fModel = reactive({
list: [],
});
const paramsOpen = () => {
getTaskParamsById(currentRow.value.id).then((response) => {
paramsFormList.value = response.data;
fModel.list = response.data;
});
};
const groupList = ref([]);
/** 获取系统分组列表(默认传1查询检测项列表) */
function handleGetSystemGroup(row) {
listGroup({ type: 2 }).then((response) => {
groupList.value = response.rows?.map((item) => {
return {
label: item.groupName,
value: String(item.groupId),
};
});
});
}
const terminalGroup = ref([]);
const selectedTerminal = ref("");
/** 获取设备终端列表 */
function handleGetTerminalGroup(row) {
listTerminal({
pageNum: 1,
pageSize: 1000,
}).then((response) => {
terminalGroup.value = response.rows?.map((item) => {
return {
label: `${item.name}(${item.host}:${item.port})`,
value: item.id,
};
});
});
}
onMounted(() => {
getList();
handleGetSystemGroup();
});
</script>
<style lang="scss" scoped>
.flow_container {
width: 100%;
height: 100%;
.containerRef {
width: 100%;
height: 100%;
}
}
</style>