IOT平台的后端管理前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

750 lines
24 KiB

<template>
<div class="app-container" v-loading="loading">
<!-- 添加或修改设备模型信息对话框 -->
<div class="marginbottom50px">
<el-steps :active="currentStep">
<el-step title="模型信息" description="名称、编号、序号、备注等" />
<el-step title="参数类别配置" description="模型的参数类别" />
<el-step title="完成" description="操作成功" />
</el-steps>
</div>
<div class="overflowscroll">
<el-form ref="devicemodelRef" :model="form" :rules="rules" label-width="100px">
<el-carousel ref="carousel" :autoplay="false" :arrow="never" pause-on-hover="false" class="customCarousel"
:height="tableHeightNew">
<el-carousel-item :key="1" name="1" class="textaligncenter overflowscroll" :style="{ height: tableHeightNew }">
<div class="widthhalfinlineblock">
<el-form-item label="模型名称" prop="modelName">
<el-input v-model="form.modelName" placeholder="请输入模型名称" />
</el-form-item>
<el-form-item label="模型编码" prop="modelCode">
<el-input v-model="form.modelCode" placeholder="请输入模型编码" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="form.sort" :min="1" :max="100" placeholder="请输入排序" />
</el-form-item>
<el-form-item label="上级" prop="pid">
<el-tree-select v-model="form.pid" :data="devicemodelOptions"
:props="{ value: 'id', label: 'modelName', children: 'children' }" value-key="id" placeholder="请选择上级"
check-strictly :default-expand-all="true" :default-checked-keys="defaultCheckedKeys" />
</el-form-item>
<el-form-item label="模型类别" key="selectmodelType" prop="modelTypeId">
<el-select v-model="form.modelTypeId" placeholder="请选择模型类别" clearable @change="modalTypeControllButton">
<el-option v-for="dict in modeltypeList" :key="dict.modelTypeCode" :label="dict.modelTypeName"
:value="dict.modelTypeCode" />
<!-- <el-option v-for="dict in dc_model_type" :key="dict.value" :label="dict.label" :value="dict.value" /> -->
</el-select>
</el-form-item>
<el-form-item label="是否可用" prop="vailable">
<el-switch v-model="form.vailable" class="ml-2i" />
</el-form-item>
<el-form-item label="备注" prop="note">
<el-input v-model="form.note" type="textarea" placeholder="请输入内容" />
</el-form-item>
</div>
<div class="width50percent textalignright">
<el-form-item class="inlineblock marginright6percent divsonmarginleft0">
<el-button type="primary" v-if="prevStepButtonShow" @click="prevStep"
style="display: inline-block !important">上一步</el-button>
<el-button type="primary" v-if="submitButtonShow" @click="submitForm"
style="display: inline-block !important">提交</el-button>
<el-button type="primary" v-if="nextStepButtonShow" @click="nextStep"
style="display: inline-block !important">下一步</el-button>
<el-button @click="cancel" style="display: inline-block !important">取 消</el-button>
</el-form-item>
</div>
</el-carousel-item>
<el-carousel-item :key="2" name="2" class="textaligncenter overflowscroll" :style="{ height: tableHeightNew }">
<div class="width75percentinlineblock vxeTableStyle">
<div class="table" height="auto">
<Table ref="paramModelTable" :config="config" :colField="colField" :columns="columns"
:tableData="selectedModelListTable" :loading="loading" :hasAddRows="true" :hasDelSelect="true"
:hasAllSave="true" @pageChange="pageChange" @addRowsCallBack="addRowsCallBack"
@beforeAddRowsCallBack="beforeAddRowsCallBack" @insertRecords="insertRecords"
@updateRecords="updateRecords" @delSelectData="removeRecords" @delRowData="delRowData"
addRowsText="添加参数模版" :addRowsType=2 @btnClick="addParamModel">
</Table>
</div>
</div>
<div class="fixedbottomright width50percent textalignleft">
<el-form-item class="inlineblock marginright6percent divsonmarginleft0">
<el-button type="primary" v-if="prevStepButtonShow" @click="prevStep"
style="display: inline-block !important">上一步</el-button>
<el-button type="primary" v-if="submitButtonShow" @click="submitForm"
style="display: inline-block !important">提交</el-button>
<el-button type="primary" v-if="nextStepButtonShow" @click="nextStep"
style="display: inline-block !important">下一步</el-button>
<el-button @click="cancel" style="display: inline-block !important">取 消</el-button>
</el-form-item>
</div>
</el-carousel-item>
<el-carousel-item :key="3" name="3" class="textaligncenter overflowscroll" :style="{ height: tableHeightNew }">
<div class="width75percentinlineblock vxeTableStyle"
:style="{ lineHeight: tableHeightNewSec, height: tableHeightNewSec }">
<h1 style="color: rgb(9, 161, 9);font-size: 36px;">操作成功!</h1>
<h2 style="font-size: 24px;color: #5555556f;">
倒计时:<span style="color: rgb(255, 77, 0); font-size: 36px;">{{ countdown }}</span> 秒返回首页
</h2>
</div>
</el-carousel-item>
</el-carousel>
</el-form>
<el-dialog :title="title" v-model="addParamModelShow" width="800px" append-to-body
:dc_device_partion="dc_device_partion" :dc_class_type="dc_class_type" draggable>
<el-label></el-label>
<el-select v-model="value" placeholder="请选择分区" clearable @change="partionChange">
<el-option v-for="dict in dc_device_partion" :value="dict.value" :label="dict.label" :key="dict.key" />
</el-select>
<el-table ref="dialogTable" v-show="paramClassTableShow" :data="paramModelListShow" key="newTable"
style="width: 100%" :style="{ maxHeight: tableHeightNew ,overflow:'auto'}" class="table_over_flow">
<el-table-column type="selection" width="55" :selectable="ifselectable" />
<el-table-column label="参数名称" align="center" prop="paramClassName" />
<el-table-column label="参数编码" align="center" prop="paramClassCode" />
<el-table-column label="类别" align="center" prop="classType">
<template #default="scope">
<dict-tag :options="dc_class_type" :value="scope.row.classType" />
</template>
</el-table-column>
</el-table>
<div class="textalignright margintop10">
<el-button type="primary" @click="selectedSubmit">提交</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<style lang="scss">
@import "@/assets/styles/self-defined.scss";
.customCarousel {
div {
button {
display: none !important;
}
}
ul {
display: none !important;
}
.table_over_flow{
overflow: auto !important;;
}
}
.customCarousel .vxeTableStyle button {
display: inline-block !important;
}
</style>
<script setup name="editdevicemodel">
import { listDevicemodel, addDevicemodel, updateDevicemodel, getDevicemodel } from "@/api/model/devicemodel";
import { listParamclassNoPage, } from "@/api/model/paramclass";
import { listModelTypeNoPage } from "@/api/model/modelType";
import { required } from "@vee-validate/rules";
import { delModelparam, listModelparamNoPage, addBatch, editBatch, } from "@/api/model/modelparam";
import Table from "@/components/TableColumnTreeSelect/index.vue";
import { ElMessageBox } from 'element-plus';
import { onMounted, ref } from 'vue';
const { proxy } = getCurrentInstance();
const { dc_class_type, dc_device_partion } = proxy.useDict('dc_class_type', 'dc_device_partion');
const router = useRouter();
const devicemodelOptions = ref([]);
const loading = ref(false);
const modeltypeList = ref([]);
const currentStep = ref(1);
const nextStepButtonShow = ref(false);
const prevStepButtonShow = ref(false);
const submitButtonShow = ref(true);
const paramModelList = ref([]);
const paramModelListShow = ref([]);
const paramModelListTable = ref([]);
const paramModelListVxetable = ref([]);
const addParamModelShow = ref(false);
const selectedModelList = ref([]);
const tableHeight = ref("0px");
const paramClassTableShow = ref(false);
const insertRecordsCache = ref([]);
const updateRecordsCache = ref([]);
const delSelectDataCache = ref([]);
const countdown = ref(3); // 倒计时初始值
const modelId = router.currentRoute._value.query.pid;
const modelCode = router.currentRoute._value.query.modelCode;
const selectedModelListTable = ref([]);
const tableHeightNew = ref('0px');
const tableHeightNewSec = ref('0px');
const newSelectedList = ref([]);
const model_group = ref("model_group");
const model = ref("model");
const data = reactive({
form: {
sort: 1,
},
queryParams: {
currentPage: 1,
pageSize: 10,
total: 0,
},
rules: {
modelTypeId: [
{ required: true, message: "模型类别不能为空", trigger: "change" }
],
modelName: [
{ required: true, message: "模型名称不能为空", trigger: "change" }
],
modelCode: [
{ required: true, message: "模型编码不能为空", trigger: "change" }
],
pid: [
{ required: true, message: "上级不能为空", trigger: "change" }
],
plcAdr: [
{ required }
]
},
validations: {
inputValue: { required }
}
});
const { queryParams, form, rules } = toRefs(data);
const yes_or_no = [
{ label: '可控', value: true },
{ label: '不可控', value: false }
]
// 取消按钮
function cancel() {
ElMessageBox.confirm('您确定要取消吗', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 用户点击了确认按钮
router.push({
path: 'devicemodel',
query: {}
});
}).catch(() => {
// 用户点击了取消按钮
// 可以在这里执行其他操作
});
}
// 表单重置
function reset() {
form.value = {
tentantId: null,
version: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null,
deptId: null,
userId: null,
deleteBy: null,
deleteTime: null,
id: null,
modelName: null,
modelCode: null,
sort: null,
modelTypeId: null,
pid: null,
note: null
};
proxy.resetForm("devicemodelRef");
}
const columns = ref([
{ type: "checkbox", width: 50, fixed: "left" },
{
field: "paramClassId",
title: "参数名称",
width: 'auto',
minWidth: 120,
editRender: {
name: "$select",
options: paramModelListTable,
attrs: { placeholder: "请输入参数名称" },
},
slots: {
edit: "select",
options: paramModelListVxetable,
value: 'value',
label: 'label',
key: 'value',
visibleChange: beforeChangeParamClass
}
},
{
field: "paramClassId",
title: "参数编码",
width: 'auto',
minWidth: 120,
editRender: {
name: "$input",
attrs: { placeholder: "请输入参数编码" },
}
},
{
field: "plcAdr",
title: "PLC地址位",
width: 'auto',
minWidth: 120,
editRender: { name: "$input", attrs: { placeholder: "请输入PLC地址位" } },
},
{
field: "controllab",
title: "是否可控",
width: 'auto',
minWidth: 120,
editRender: { name: "$select", options: yes_or_no, attrs: { placeholder: "请选择是否可控" } },
},
{
field: "classType",
title: "类别",
width: 'auto',
minWidth: 120,
editRender: { name: "$select", options: dc_class_type, attrs: { placeholder: "请输入角色内共享" } },
},
{
field: "partion",
title: "分区",
width: 'auto',
minWidth: 120,
editRender: { name: "$select", options: dc_device_partion, attrs: { placeholder: "请输入用户共享" } },
},
{
field: "note",
title: "备注",
width: 'auto',
minWidth: 120,
editRender: { name: "$input", attrs: { placeholder: "请输入统计单元状态" } },
},
{
title: "操作",
width: 380,
slots: {
default: "operateNew",
}
},
]);
const tableData = ref([]);
const config = ref({
//表格配置项
id: "table", //唯一标识
height: 'auto', //表格的高度;支持铺满父容器或者固定高度
minHeight: '200px',
maxHeight: tableHeight,
rowHeight: 66,
align: "center", //所有的列对齐方式
border: "none", //是否带有边框:false|default 默认显示边框,true|full 显示完整边框,outer 显示外边框,inner 显示内边框,none
round: true, //是否为圆角边框
stripe: true, //是否带有斑马纹
size: "medium", //表格的尺寸:medium, small, mini
loading: false, //表格是否显示加载中
showHeader: true, //是否显示表头
columnConfig: {
//列配置信息
isCurrent: false, //当鼠标点击列头时,是否要高亮当前列
isHover: true, //当鼠标移到列头时,是否要高亮当前头
},
rowConfig: {
//行配置信息
keyField: "id", //自定义行数据唯一主键的字段名
isCurrent: false, //当鼠标点击行时,是否要高亮当前行
isHover: true, //当鼠标移到行时,是否要高亮当前行
},
editConfig: {
//可编辑配置项
trigger: "dblclick", //触发方式click(点击触发编辑),dblclick(双击触发编辑)
mode: "row", //编辑模式cell(单元格编辑模式),row(行编辑模式)
},
pagerConfig: {
//分页配置项
enabled: true, //是否启用
currentPage: 1, //当前页
pageSize: 10, //每页大小
total: 0, //总条数
autoHidden: false, //当只有一页时自动隐藏
pageSizes: [10, 15, 20, 50, 100], //每页大小选项列表
},
toolbarConfig: {
//工具栏配置
refresh: true, // 显示刷新按钮
import: false, // 显示导入按钮
export: false, // 显示导出按钮
zoom: true, // 显示全屏按钮
custom: true, // 显示自定义列按钮
},
editRules: {
partion: [
{ required: true, message: '分区不能为空' },
],
}
});
/** 提交按钮 */
function submitForm() {
loading.value = false;
proxy.$refs["devicemodelRef"].validate(valid => {
if (valid) {
//模型按钮主表维护
if (form.value.id != null) {
updateDevicemodel(form.value).then(response => {
console.log("form.value.modelTypeId");
console.log(form.value.modelTypeId);
console.log("response.code == '200'");
console.log(response.code == '200');
console.log(form.value.modelTypeId == model_group.value && response.code == '200');
if (form.value.modelTypeId == model_group.value && response.code == '200') {
endStep();
}
});
} else {
addDevicemodel(form.value).then(response => {
if (form.value.modelTypeId == model_group.value && response.code == '200') {
endStep();
}
});
}
if (form.value.modelTypeId == model.value) {
proxy.$refs.paramModelTable.allSubmit(executeRequests);
}
}
});
}
async function executeRequests() {
try {
if (insertRecordsCache.value?.length > 0) {
await addBatch(insertRecordsCache.value).then(response => {
console.log("addBatch");
console.log(insertRecordsCache.value);
console.log(response);
});
}
if (updateRecordsCache.value?.length > 0) {
await editBatch(updateRecordsCache.value).then(response => {
console.log("editBatch");
console.log(updateRecordsCache.value);
console.log(response);
});
}
if (delSelectDataCache.value?.length > 0) {
await delModelparam(delSelectDataCache.value).then(response => {
console.log("delModelparam");
console.log(delSelectDataCache.value);
console.log(response);
});
}
insertRecordsCache.value = [];
updateRecordsCache.value = [];
delSelectDataCache.value = [];
proxy.$modal.msgSuccess("操作成功");
nextStep();
} catch (error) {
// 前一个请求执行失败的处理逻辑
console.error(error);
}
}
/** 查询设备模型类型列表 */
function getModelTypeListNoPage() {
loading.value = true;
listModelTypeNoPage(queryParams.value).then(response => {
modeltypeList.value = response.data;
loading.value = false;
});
}
function getTreeselect() {
listDevicemodel().then(response => {
devicemodelOptions.value = [];
const data = { id: 0, modelName: '顶级节点', children: [] };
const parentData = response.data.filter(item => {
return (item.modelTypeId == '1');
});
data.children = proxy.handleTree(parentData, "id", "pid");
devicemodelOptions.value.push(data);
});
}
onMounted(() => {
let type = router.currentRoute._value.query.type;
if (type == 'edit') {
getDevicemodel(modelId).then(response => {
form.value = response.data;
modalTypeControllButton();
})
}
calculateTableHeight();
window.addEventListener('resize', calculateTableHeight);
window.onresize = () => {
return (() => {
calculateTableHeight();
})()
}
// 在组件首次加载完成后执行的逻辑
// 可以在这里给组件复制
// form.value.pid=tempPid;
});
function modalTypeControllButton(val) {
console.log('modalTypeControllButton');
console.log(val);
if (form.value.modelTypeId == model.value) {
submitButtonShow.value = false;
nextStepButtonShow.value = true;
} else if (form.value.modelTypeId == model_group.value) {
submitButtonShow.value = true;
nextStepButtonShow.value = false;
}
}
function nextStep() {
proxy.$refs["devicemodelRef"].validate(valid => {
if (valid) {
if (currentStep.value < 2) {
currentStep.value = currentStep.value + 1;
proxy.$refs.carousel.next();
submitButtonShow.value = true;
nextStepButtonShow.value = false;
prevStepButtonShow.value = true;
if (currentStep.value == 2) {
let param = {
modelTypeId: form.value.modelTypeId,
modelId: modelCode
}
getOldModelParams(param);
}
} else if (currentStep.value == 2) {
currentStep.value = currentStep.value + 1;
proxy.$refs.carousel.next();
submitButtonShow.value = false;
nextStepButtonShow.value = false;
prevStepButtonShow.value = false;
startCountdown();
}
}
});
}
function endStep() {
console.log("endStep");
console.log(currentStep.value);
proxy.$refs["devicemodelRef"].validate(valid => {
console.log("valid");
console.log(valid);
if (valid) {
console.log("form.value.modelTypeId == model_group");
console.log(form.value.modelTypeId == model_group.value);
if (form.value.modelTypeId == model_group.value) {
currentStep.value = 3;
proxy.$refs.carousel.next();
proxy.$refs.carousel.next();
submitButtonShow.value = false;
nextStepButtonShow.value = false;
prevStepButtonShow.value = false;
console.log("currentStep.value");
console.log(currentStep.value);
startCountdown();
}
}
});
}
function prevStep() {
currentStep.value = currentStep.value - 1;
proxy.$refs.carousel.prev();
submitButtonShow.value = false;
nextStepButtonShow.value = true;
prevStepButtonShow.value = false;
}
/** 查询参数模型信息列表 */
function addParamModel() {
loading.value = true;
addParamModelShow.value = true;
loading.value = false;
}
function partionChange(val) {
let paramClassTableShowByPartion = ref();
let selectedModelListByPartion = ref();
paramClassTableShow.value = true;
paramClassTableShowByPartion.value = paramModelList.value;
selectedModelListByPartion.value = selectedModelList.value?.filter(element => {
return element.partion == val;
});
paramModelListShow.value = paramClassTableShowByPartion.value?.filter(element => {
return !selectedModelListByPartion.value?.some(item => item.paramClassId === element.paramClassCode);
});
paramModelListShow.value?.map(item => {
item.paramClassId = item.paramClassCode;
item.modelId = form.value.modelCode;
item.controllab = false;
item.partion = val;
item.id = "ABCDEFXYZ" + form.value.modelCode + item.paramClassCode;
});
debugger
}
function selectedSubmit() {
newSelectedList.value = proxy.$refs.dialogTable.getSelectionRows().map(row => ({
...row,
editing: false, // 添加 'editing' 属性并设置初始值为 false
}));
proxy.$refs.paramModelTable.addRows(newSelectedList.value.length);
addParamModelShow.value = false;
}
function getOldModelParams(param) {
listModelparamNoPage(param).then(res => {
selectedModelList.value = res.data;
config.value.pagerConfig.total = selectedModelList.value.length;
pageChange(queryParams.value.currentPage, queryParams.value.pageSize);
});
}
const calculateTableHeight = () => {
nextTick(() => {
const windowHeight = window.innerHeight;
const remainingHeight = windowHeight - 523;
tableHeight.value = remainingHeight + 'px';
tableHeightNew.value = remainingHeight + 70 + 'px';
tableHeightNewSec.value = remainingHeight + 20 + 'px';
});
};
function getModelParamList() {
listParamclassNoPage(queryParams.value).then(response => {
paramModelList.value = response.data;
paramModelListTable.value = paramModelList.value.map(item => {
return {
value: item.paramClassCode,
label: item.paramClassName,
};
});
paramModelListVxetable.value = paramModelListTable.value
});
}
function insertRecords(rows) {
insertRecordsCache.value = [
...rows,
...insertRecordsCache.value,
];
}
function updateRecords(rows) {
updateRecordsCache.value = [
...rows,
...updateRecordsCache.value,
];
}
function removeRecords(rows) {
// 过滤掉ABCDEFXYZ开头的数据
const params = rows.map((i) => i.id);
delSelectDataCache.value = [
...params.filter(item => {
if (typeof item === 'string' && item.includes('ABCDEFXYZ')) {
return false; // 过滤掉包含 'ABCDEFXYZ' 的字符串项
}
return true; // 保留非字符串项
}),
...delSelectDataCache.value
];
}
function delRowData(row) {
const params = [row.id];
delSelectDataCache.value = [
...params.filter(item => {
if (typeof item === 'string' && item.includes('ABCDEFXYZ')) {
return false; // 过滤掉包含 'ABCDEFXYZ' 的字符串项
}
return true; // 保留非字符串项
}),
...delSelectDataCache.value
];
}
function pageChange(currentPage, pageSize) {
config.value.pagerConfig.currentPage = currentPage;
config.value.pagerConfig.pageSize = pageSize;
queryParams.value.currentPage = currentPage;
queryParams.value.pageSize = pageSize;
// 对selectedModelList.value进行分页处理
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
selectedModelListTable.value = selectedModelList.value.slice(startIndex, endIndex);
}
function beforeChangeParamClass(envent, row, column) {
if (envent !== undefined && envent) {
let thePartionModelList = selectedModelList.value.filter(item => {
return row.partion === item.partion;
})
paramModelListVxetable.value = paramModelList.value.filter(element => {
return !thePartionModelList.some(item => {
return element.paramClassCode === item.paramClassId;
});
}).map(temp => {
{
return {
value: temp.paramClassCode,
label: temp.paramClassName,
};
}
});
} else {
paramModelListVxetable.value = paramModelListTable.value
}
}
function startCountdown() {
const timer = setInterval(() => {
countdown.value--;
if (countdown.value === 0) {
clearInterval(timer);
// 在倒计时结束后导航到首页
router.push({
path: "devicemodel",
query: {
}
});
}
}, 1000); // 每秒减少1秒
}
function addRowsCallBack(records, callback) {
callback([...newSelectedList.value])
}
getTreeselect();
getModelTypeListNoPage();
getModelParamList();
getOldModelParams();
</script>