<template> <div id="pagetwo" class="page-data"> <!--搜素框--> <div class="page-filter"> <page-filter :query.sync="siteFilterInfo.query" :filter-list="siteFilterInfo.list" @handleClick="handleClick" /> </div> <div class="page-content"> <!--表格--> <div class="h-100"> <page-table tabIndex pagination :api-url="siteTableInfo.url" :refresh="siteTableInfo.refresh" :data.sync="siteTableInfo.data" :query="siteFilterInfo.query" :page-query="siteTableInfo.pageQuery" :list-type-info="listTypeInfo" :init-curpage="siteTableInfo.initCurpage" :field-list="siteTableInfo.fieldList" :handle="siteTableInfo.handle" @handleClick="handleClick" > <!-- 自定义插槽显示状态 --> <template v-slot:col-equips="scope"> <el-button type="text" size="small" @click="handleClick('look',scope.row)">查看设备</el-button> </template> </page-table> </div> </div> <!-- 新增/修改的弹出框 --> <el-dialog :visible.sync="yzaddflag" width="1000px" true :title="title" @close="closedialog('ruleForm')" > <div> <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="110px" > <el-form-item label="站点名称" prop="stName" style="width: 100%"> <el-input size="small" v-model="ruleForm.stName" class="selectInput" ></el-input> <span >站点名称命名规则 "[项目名称]" +安装位置关键标识,例如[武昌]湖北大学东门监测站点</span > </el-form-item> <el-form-item label="站点类型" prop="stationType"> <el-select class="selectInput" size="small" v-model="ruleForm.stationType" placeholder="请选择站点类型" > <el-option class="selectOption" v-for="item in siteTypeList" :key="item.code" :label="item.name" :value="item.code" ></el-option> </el-select> <span>按实际设备类型选择站点类型</span> </el-form-item> <el-form-item label="所属项目" prop="platformCode"> <el-select class="selectInput" size="small" filterable v-model="ruleForm.platformCode" placeholder="请选择所属项目" > <el-option class="selectOption" v-for="item in projectList" :key="item.id" :label="item.key" :value="item.value" ></el-option> </el-select> </el-form-item> <el-form-item label="所属区域" prop="area"> <el-cascader ref="cascader" popper-class="form-cascader" class="selectInput" v-model="ruleForm.area" :options="syscityList" filterable placeholder="请选择所属区域" :props="syscityListProps" @change="handleChange" @visible-change="visiblechange" ></el-cascader> </el-form-item> <el-form-item label="站点安装定位" required> <el-col :span="7"> <el-form-item prop="coordinateSystem" ><el-input size="small" v-model="ruleForm.coordinateSystem" ></el-input ></el-form-item> </el-col> <el-col :span="1"> 经度</el-col> <el-col :span="5"> <el-form-item prop="lon" ><el-input size="small" v-model="ruleForm.lon"></el-input ></el-form-item> </el-col> <el-col :span="1"> 纬度</el-col> <el-col :span="5"> <el-form-item prop="lat" ><el-input size="small" v-model="ruleForm.lat"></el-input ></el-form-item> </el-col> </el-form-item> <el-form-item label="站点安装位置" prop="address"> <el-input size="small" v-model="ruleForm.address" class="selectInput" ></el-input> <span >按实际安装位置填写,可填入地图定位软件显示的中文名或自行输入</span > </el-form-item> <el-form-item label="安装负责人" prop="person" style="width: 100%"> <el-input size="small" v-model="ruleForm.person" class="selectInput" ></el-input> <span>填写安装负责人</span> </el-form-item> <el-form-item label="现场安装图片" prop="height"> <!-- 点击上传按钮 --> <el-upload v-loading="loading" element-loading-text="正在上传图片..." element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.3)" :auto-upload="false" multiple action="#" :on-change="fileChange" > <i class="el-icon-plus">添加图片</i> </el-upload> <!-- 渲染服务器返回给我们的图片列表 --> <div class="imglist"> <div class="imgbox" v-for="(item, index) in ruleForm.fileList" :key="index" > <img class="imgtype" :src="item.fileAbbreviatedCloudStorageKey" @click="handlePictureCardPreview(item)" /> <span class="deleteSpan" @click="deleteImg(item.fileNo)" ><span class="deletex">x</span></span > </div> </div> <!-- 点击图片预览大图的效果 --> <el-dialog :visible.sync="dialogVisible" append-to-body> <img width="100%" :src="dialogImageUrl" alt="" /> </el-dialog> </el-form-item> </el-form> </div> <span slot="footer" class="dialog-footer"> <el-button @click="resetField('ruleForm')">取消</el-button> <el-button type="primary" @click="saveOru('ruleForm')">保存</el-button> </span> </el-dialog> <!--关联设备弹窗--> <page-dialog class="page-data-dialog" :title="dialogInfo.title[dialogInfo.type]" :visible.sync="dialogInfo.visible" width="80%" :bt-loading="dialogInfo.btLoading" :bt-list="dialogInfo.btList" @handleClick="handleClick" > <template v-if="dialogInfo.type === 'look'"> <div class="page-filter"> <el-form :inline="true" :model="deviceRelatedQuery" ref="deviceRelatedQuery" size="medium"> <el-form-item label=""> <el-input v-model="deviceRelatedQuery.searchStr" placeholder="请输入设备编号/厂家" clearable></el-input> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" size="medium" @click="handleClick('deviceSearch')">查询</el-button> </el-form-item> </el-form> </div> <div class="page-content"> <el-row :gutter="20" class="h-100"> <el-col :span="10" class="h-100 flex flex-d"> <div class="table-title">未关联设备列表</div> <page-table class="flex-1" checkBox pagination type="unRelated" :api-url="deviceTableInfo.url" :refresh="deviceTableInfo.refresh" :data.sync="unRelatedDeviceTableInfo.data" :query="unRelatedDeviceTableInfo.query" :init-curpage="deviceTableInfo.initCurpage" :field-list="deviceTableInfo.fieldList" @handleClick="handleClick" @handleEvent="handleEvent" /> </el-col> <el-col :span="4" class="h-100"> <div class="btn-group"> <el-button type="primary" size="small" icon="el-icon-d-arrow-right" :disabled="isCanInsertDevice" @click="handleClick('insert')" >添加</el-button > <el-button type="primary" size="small" icon="el-icon-d-arrow-left" :disabled="isCanRemoveDevice" @click="handleClick('remove')" >移除</el-button > </div> </el-col> <el-col :span="10" class="h-100 flex flex-d"> <div class="table-title">已关联设备列表</div> <page-table class="flex-1" checkBox pagination type="isRelated" :api-url="deviceTableInfo.url" :refresh="deviceTableInfo.refresh" :data.sync="isRelatedDeviceTableInfo.data" :query="isRelatedDeviceTableInfo.query" :init-curpage="deviceTableInfo.initCurpage" :field-list="deviceTableInfo.fieldList" @handleClick="handleClick" @handleEvent="handleEvent" /> </el-col> </el-row> </div> </template> </page-dialog> </div> </template> <script> import axios from "axios"; import { mapGetters } from "vuex"; export default { data() { return { //站点搜索相关 siteFilterInfo: { query: { searchStr: "", startDate: "", endDate: "" }, list: [ {type: "input", label: "站点名称/编号", value: "searchStr", hideLabel: true }, {type: "date", label: "开始时间", value: "startDate", dateType: "date", datePickerOptions: "pickerOptionsStart", hideLabel: true}, {type: "date", label: "结束时间", value: "endDate", dateType: "date", datePickerOptions: "pickerOptionsEnd", hideLabel: true}, {type: "button", label: "查询", btType: "primary", icon: "el-icon-search", event: "search", show: true}, {type: "button", label: "添加站点", btType: "primary", icon: "el-icon-circle-plus-outline", event: "create", show: true, has: "m11-2-1"} ] }, //站点表格相关 siteTableInfo: { url: this.nozzle.listExtend, //接口地址 refresh: 1, initCurpage: 1, data: [], fieldList: [ { label: "站点编号", value: "stCode", minWidth: 120, tooltip: true }, { label: "站点名称", value: "stName", minWidth: 120, tooltip: true }, { label: "站点类型", value: "stationTypeName", width: 120 }, { label: "站点安装时间", value: "createTime", minWidth: 120, tooltip: true }, { label: "安装人", value: "person", width: 100 }, { label: "关联设备", value: "equips", width: 100, type: "slot" }, { label: "首次数据接入时间", value: "tt", minWidth: 150, tooltip: true }, ], handle: { fixed: "right", label: "操作", width: "80", btList: [ { label: "修改", size: "small", type: "text", event: "update", show: true, has: 'm11-2-2' } ] } }, //列表相关 listTypeInfo: {}, loadingdelet: undefined, loading: false, timer: null, dialogImageUrl: "", dialogVisible: false, title: "站点管理", siteTypeList: [], //弹框里面站点类型列表 yzaddflag: false, ruleForm: { id: "", //站点ID stName: "", //站点名称 stCode: "", //站点编号 tt: "", area: "", //所属区域 constructionStatus: "", faultStatus: "", taskStatus: "", platformCode: "", lat: "", //维度 lon: "", //经度 isPush: "", createTime: "", coordinateSystem: "", status: "", offlineTime: "", stationType: "", //站点类型 // stationTypeName: "", //站点名称 coordinateSystem: "", //坐标系(经纬度所对应的的坐标系) address: "", //站点安装位置 person: "", //安装负责人 fileList: [] //现场安装图片 }, rules: { area: [ { required: true, message: "请选择所属区域", trigger: "change" } ], stationType: [ { required: true, message: "请选择站点类型", trigger: "change" } ], platformCode: [ { required: true, message: "请选择所属项目", trigger: "change" } ], stName: [ { required: true, message: "请填写站点名称", trigger: "blur" } ], lon: [ { required: true, message: "请填写经度", trigger: "blur" } ], lat: [ { required: true, message: "请填写纬度", trigger: "blur" } ], coordinateSystem: [ { required: true, message: "请填写站点坐标系", trigger: "blur" } ], address: [ { required: true, message: "请填写站点安装位置", trigger: "blur" } ], person: [ { required: true, message: "请填写安装负责人", trigger: "blur" } ] }, value: [], // 站点管理/所属区域数组 syscityList: [], syscityListProps: { checkStrictly: true, value: "id", label: "name" }, //当前用户权限内的项目数据 projectList: [], //弹窗相关 dialogInfo: { title: { look: '' }, width: "60%", visible: false, btLoading: false, type: "", btList: [ { label: "关闭", type: "", icon: "", event: "close", show: true } ] }, //设备表格通用相关 deviceTableInfo: { url: this.nozzle.sysEquipRelatedList, //接口地址 refresh: 1, initCurpage: 1, fieldList: [ { label: "设备编号", value: "equipNo", minWidth: 100, tooltip: true }, { label: "设备厂家", value: "equipFactory", minWidth: 150, tooltip: true }, ] }, //已关联设备表格相关 isRelatedDeviceTableInfo: { data: [], query: { sign: "" }, selectList: [] }, //未关联设备表格相关 unRelatedDeviceTableInfo: { data: [], query: { sign: "unbound" }, selectList: [] }, //设备关联过滤相关 deviceRelatedQuery: { searchStr: "", siteCode: "" } }; }, mounted() { this.siteTableInfo.refresh = Math.random(); this.getsityType(); this.getCurrentUserProject(); //获取当前用户所绑定的项目 }, computed: { //移除按钮是否可点击 isCanRemoveDevice() { return this.isRelatedDeviceTableInfo.selectList.length ? false : true; }, //添加按钮是否可点击 isCanInsertDevice() { return this.unRelatedDeviceTableInfo.selectList.length ? false : true; }, ...mapGetters(["allDept", "allRole", "allCity"]) }, watch: { "ruleForm.area": { handler(newVal, oldVal) { if (this.$refs.cascader) { let children = this.$refs.cascader.getCheckedNodes(); if ( children.length && children[0].children && children[0].children.length < 1 ) { this.$refs.cascader.dropDownVisible = false; } } }, deep: true // 深度监听 }, dialogVisible: { handler(newVal, oldval) { if (oldval) { this.dialogImageUrl = ""; } } }, "dialogInfo.visible"(val) { if (!val) { this.deviceTableInfo.data = []; this.deviceRelatedQuery.searchStr = ""; this.dialogInfo.btLoading = false; } }, "deviceRelatedQuery.searchStr"(val) { Object.assign(this.isRelatedDeviceTableInfo.query, this.deviceRelatedQuery); Object.assign(this.unRelatedDeviceTableInfo.query, this.deviceRelatedQuery); } }, methods: { //上传头像 fileChange(file) { this.loading = true; const isLt1M = file.size / 1024 / 1024 < 1; if (file.raw.type != "image/jpeg" && file.raw.type != "image/png") { this.loading = false; this.$message.error("上传图片只能是JPG或PNG格式!"); return; } if (!isLt1M) { this.loading = false; this.$message.error("上传图片大小不能超过 1MB!"); return; } var formdata = new FormData(); formdata.append("files", file.raw); formdata.append("siteNo", this.ruleForm.stCode); formdata.append("username", "admin"); let config = { headers: { "Content-Type": "multipart/form-data" } }; axios.post(this.nozzle.upload, formdata, config).then(res => { if (res.data.code == 1) { this.loading = false; this.$message({ message: "上传图片成功!", type: "success" }); this.ruleForm.fileList.push(res.data.data[0]); this.siteTableInfo.refresh = Math.random(); } }) .catch(res => { this.loading = false; this.$message({ message: "服务器问题!请重试!", type: "warning" }); }); }, // 删除图片按钮 deleteImg(fileNo) { this.$confirm("此操作将永久删除该图片文件,无法撤回!是否继续?", "提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }) .then(() => { let fileNos = []; fileNos.push(fileNo); const loadingdelet = this.$loading({ lock: true, text: "正在删除....", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)" }); this.$http .post(this.nozzle.delete, { data: { siteNo: this.ruleForm.stCode, fileNos: fileNos } }) .then(res => { loadingdelet.close(); if(res.data.code === 1) { this.siteTableInfo.refresh = Math.random(); } this.$message({ type: res.data.code === 1 ? "success" : "error", message: res.data.msg }); this.ruleForm.fileList = this.ruleForm.fileList.filter(item => { return item.fileNo != fileNo; }); }) .catch(res => { loadingdelet.close(); this.$message({ type: "info", message: "删除失败,请重试!" }); }); }) .catch(() => { loadingdelet.close(); this.$message({ type: "info", message: "已取消删除" }); }); }, // 点击图片显示图片预览大图 handlePictureCardPreview(file) { this.dialogImageUrl = file.fileCloudStorageKey; this.dialogVisible = true; }, // 弹框提交表单按钮 saveOru(formName) { this.$refs[formName].validate(valid => { if (valid) { this.$http.post(this.nozzle.saveOrupdate, { data: this.ruleForm }) .then(res => { if(res.data.code === 1) { this.siteTableInfo.refresh = Math.random(); this.yzaddflag = false; } this.$message({ message: res.data.msg, type: res.data.code === 1 ? 'success' : 'error', showClose: true, }) }); } }); }, // 弹框取消表单按钮 resetField(formName) { this.yzaddflag = false; this.$refs[formName].resetFields(); }, visiblechange(visible) { let that = this; if (visible) { this.timer = setInterval(() => { NodeList.prototype.forEach = Array.prototype.forEach; document.querySelectorAll(".el-cascader-node__label").forEach(el => { el.onclick = function() { if (this.previousElementSibling) this.previousElementSibling.click(); }; el.ondblclick = function() { if(Array.isArray(that.$refs.cascader)) { that.$refs.cascader[0].dropDownVisible = false; }else{ that.$refs.cascader.dropDownVisible = false; } }; }); }, 1000); } else { clearInterval(this.timer); } }, //获取站点类型列表 async getsityType() { const { data } = await this.$http.post(this.nozzle.sityType, { data: { siteType: "site_type" } }); this.siteTypeList = data.data; }, //获取当前用户所绑定的项目 getCurrentUserProject() { this.$http .post(this.nozzle.sysPlatformList, { current: 0, size: 0, data: { searchStr: "", startDate: "", endDate: "" } }) .then(res => { if (res.data.code === 1) { this.projectList = res.data.data.list.map(item => { return { id: item.id, key: item.name, value: item.platformCode }; }); } }); }, //表格checkbox选择事件 handleEvent(event, data) { switch (event) { case "isRelated": this.isRelatedDeviceTableInfo.selectList = data; break; case "unRelated": this.unRelatedDeviceTableInfo.selectList = data; break; } }, //点击事件 handleClick(event, data, index){ switch(event) { //站点搜索 case "search": this.siteTableInfo.initCurpage = Math.random(); this.siteTableInfo.refresh = Math.random(); break; //添加站点 case "create": this.yzaddflag = true; this.title = "新增站点"; this.syscityList = this.removeEmptyChild(this.allCity); break; //编辑站点 case "update": this.title = "修改站点"; for (let key in data) { if (key === "stationType") { data[key] = data[key].toString(); } this.ruleForm[key] = data[key]; } this.syscityList = this.removeEmptyChild(this.allCity); this.yzaddflag = true; break; //查看关联设备 case "look": this.dialogInfo.type = event; this.deviceRelatedQuery.siteCode = data.stCode; this.dialogInfo.visible = true; setTimeout(() => { Object.assign(this.isRelatedDeviceTableInfo.query, this.deviceRelatedQuery); Object.assign(this.unRelatedDeviceTableInfo.query, this.deviceRelatedQuery); this.deviceTableInfo.refresh = Math.random(); }, 0); break; //关联设备搜索 case "deviceSearch": this.deviceTableInfo.initCurpage = Math.random(); this.deviceTableInfo.refresh = Math.random(); break; //添加设备到站点 case "insert": const insertEquipNoArr = this.unRelatedDeviceTableInfo.selectList.map( item => item.equipNo); const insertData = { siteCode: this.unRelatedDeviceTableInfo.query.siteCode, equipNos: insertEquipNoArr }; this.$http.post(this.nozzle.sysEquipInsertBatch, { data: insertData }).then(res => { if (res.data.code === 1) { this.deviceRelatedQuery.searchStr = ""; this.deviceTableInfo.refresh = Math.random(); this.deviceTableInfo.initCurpage = Math.random(); } this.$message({ message: res.data.msg, type: res.data.code === 1 ? "success" : "error", showClose: true }); }); break; //解绑设备与站点 case "remove": const removeEquipNoArr = this.isRelatedDeviceTableInfo.selectList.map(item => item.equipNo); const removeData = { siteCode: this.isRelatedDeviceTableInfo.query.siteCode, equipNos: removeEquipNoArr }; this.$http.post(this.nozzle.sysEquipRemoveBatch, { data: removeData }).then(res => { if (res.data.code === 1) { this.deviceRelatedQuery.searchStr = ""; this.deviceTableInfo.refresh = Math.random(); this.deviceTableInfo.initCurpage = Math.random(); } this.$message({ message: res.data.msg, type: res.data.code === 1 ? "success" : "error", showClose: true }); }).catch(e =>{console.log(e)}); break; //关闭 case "close": setTimeout(() => { this.dialogInfo.visible = false; }, 0); break; } }, // 关闭弹框后做的操作 closedialog(formName) { this.$refs["ruleForm"].resetFields(); this.ruleForm = { id: "", //站点ID stName: "", //站点名称 stCode: "", //站点编号 tt: "", area: "", //所属区域 constructionStatus: "", faultStatus: "", taskStatus: "", platformCode: "", lat: "", //维度 lon: "", //经度 isPush: "", createTime: "", coordinateSystem: "", status: "", offlineTime: "", stationType: "", //站点类型 // stationTypeName: "", coordinateSystem: "", //坐标系(经纬度所对应的的坐标系) address: "", //站点安装位置 person: "", //安装负责人 fileList: [] //现场安装图片 }; this.$refs.cascader.$refs.panel.activePath = []; this.$refs.cascader.$refs.panel.clearCheckedNodes(); }, handleChange(value) { // 取选中数组的最后一项的id this.ruleForm.area = value.slice(-1)[0]; }, //将空的children置为undefined,避免在没有下一级数据的情况下显示暂无数据 removeEmptyChild(arr) { arr.forEach(item => { if (!item.children || item.children.length < 1) { item.children = undefined; } else { this.removeEmptyChild(item.children); } }); return arr; } }, destroyed() { clearInterval(this.timer); } }; </script> <style lang="scss" scoped> .imgtype { width: 150px; height: 100px; } /deep/ .el-upload-list { display: none; } .imgbox { display: inline-block; margin: 0 20px 20px 0; position: relative; } .deleteSpan { position: absolute; display: inline-block; right: -6px; top: -8px; cursor: pointer; background: var(--white); color: var(--white); width: 15px; height: 15px; border-radius: 13px; text-align: center; } .deletex { color: var(--black); position: absolute; top: -12px; left: 4px; } .form { display: flex; align-items: center; justify-content: flex-start; height: 50px; text-align: left; color: var(--white); font-size: 14px; box-sizing: border-box; padding-left: 10px; } .form .el-input { width: 200px; margin: 0 10px; } .title, .table-title{ @include hl(30px,30px); color: #409EFF; text-align: center; font-size: 16px; margin-bottom: 10px; } .tableSection { padding: 10px; background: rgba(270, 255, 255, 0.05); } /deep/ .el-dialog .el-dialog__body { text-align: left; padding-bottom: 0; } .el-dialog .selectInput { width: 30% !important; } .el-dialog .selectInput .el-select-dropdown__empty { width: 100% !important; } .btn-group { height: 100%; @include fdaj(center, center); /deep/ .el-button + .el-button { margin-left: 0; margin-top: 10px; } } </style>