123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- <template>
- <div>
- <el-dialog v-model="dialogVisible" title="装置端子关系配置" width="60%" @close="handleClose"
- :close-on-click-modal="false">
- <div class="masBox" v-loading="pastLoading">
- <div class="leftBox">
- <h1 style="
- border-bottom: 1px solid #7484AB;
- width: 73%;
- margin: 25px auto;
- padding-bottom: 10px;
- ">{{ startTxt }}</h1>
- <div style="height: auto;">
- <div style="margin-bottom: 10px;" v-for="(item, index) in curList"
- @click="setIndex(item, index)">
- <span :class="index == leftIndex ? 'result' : 'anther'">{{ index + 1 }}</span>
- <span :class="index == leftIndex ? 'results' : 'anthers'" :id="item.id">{{ item.fcda_name
- }}</span>
- </div>
- </div>
- </div>
- <div class="middleBox">
- <p class="background" :style="{ 'background-image': `url(${setBackground})`, 'color': setColor }">{{
- setGooseOrSv }}</p>
- </div>
- <div class="rightBox" v-loading="loading">
- <h1 style="
- border-bottom: 1px solid #7484AB;
- width: 73%;
- margin: 25px auto;
- padding-bottom: 10px;
- ">{{ endTxt }}</h1>
- <div style="height: auto;">
- <div v-for="(item, index) in outList">
- <el-checkbox-group v-model="checkList" @change="checkChange">
- <el-checkbox :id="item.id" :label="item.id" :key="item.id">
- {{ item.fcda_name }}
- </el-checkbox>
- </el-checkbox-group>
- </div>
- <!-- <div style="margin-bottom: 10px;" v-for="(item, index) in outList" :id="item.id" class="anthers">
- <el-radio-group v-if="item.from_ied_type==''" v-model="checkList" @change="checkChange">
- <el-radio :label="item.id" :key="item.id"> {{ item.fcda_name }}</el-radio>
- </el-radio-group>
- <span v-else >{{ item.fcda_name }}</span>
- </div> -->
- </div>
- </div>
- <div id="wrapper"></div>
- </div>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="cancels">取消</el-button>
- <el-button type="primary" @click="sureClick">确定</el-button>
- </span>
- </template>
- </el-dialog>
- </div>
- </template>
- <script>
- import { ref, onMounted, watch, toRefs, computed, onBeforeUnmount } from 'vue';
- import flow from '@/api/flow/flow';
- import { ElMessage } from 'element-plus';
- import LeaderLine from "../../../../public/leader-line.min.js";
- export default {
- props: {
- ldModal: {
- type: Boolean,
- required: true,
- },
- startTarget: {
- type: Object,
- required: true
- },//开始数据
- endTarget: {
- type: Object,
- required: true,
- },//结尾数据
- modelId: {
- type: String,
- required: true,
- },//模型id
- numCase: {
- type: Number,
- required: true
- },//用于判断goose还是sv,0为sv,1为goose
- startText: {
- type: String,
- required: true
- },//开始节点文本
- endText: {
- type: String,
- required: true
- },//结束文本
- lineType: {
- type: String,
- required: true
- },//用于判断goose还是sv
- },
- setup(props, { emit }) {
- let dialogVisible = ref(false)//模态框开关
- let starts = ref({})//开始装置数据
- let ends = ref({})//结束装置数据
- let modelIds = ref("")//本组件的模型id
- let startTxt = ref("")//本组件开始文本
- let endTxt = ref("")//本组件结束文本
- let curList = ref([])//箭头开始list
- let outList = ref([])//箭头结束list
- let numStatus = ref(0)//判断goose还是sv
- let visibleItems = ref([])//选择的数组
- let fcdaIds = ref("")//需要的fcda_ids
- let leftIndex = ref(-1)//左侧选择的输出下标
- let leftFcda = ref("")//左侧的fcdaid
- let together = ref("")//绑定的id
- let checkList = ref([])//select数据
- let loading = ref(false)
- let arrNew = ref([])//新的存储fdcdids
- let gv = ref('')
- let pastLoading = ref(false)
- let leaderLineList = ref({})//组件leader-line数据,以方便离开组件时清除画线,key:start和end对象的端子id组合,value为line对象
- watch(() => props.modelId, (newVal) => {
- modelIds.value = newVal
- })
- watch(() => props.startText, (newVal) => {
- startTxt.value = newVal
- })
- watch(() => props.endText, (newVal) => {
- endTxt.value = newVal
- })
- watch(() => props.numCase, (newVal) => {
- numStatus.value = newVal
- })
- watch(() => props.lineType, (newVal) => {
- gv.value = newVal
- })
- // 初始化函数
- async function reload() {
- pastLoading.value = true
- dialogVisible.value = props.ldModal
- modelIds.value = props.modelId
- starts.value = props.startTarget
- ends.value = props.endTarget
- if(props.startText==null || props.startText==''){
- startTxt.value = starts.value.ied_type
- }else{
- startTxt.value = props.startText
- }
- if(props.endText==null || props.endText==''){
- endTxt.value = ends.value.ied_type
- }else{
- endTxt.value = props.endText
- }
- numStatus.value = props.numCase
- gv.value = props.lineType
- await flow.getModelAndIed({
- model_id: modelIds.value - 0,
- ied_type: starts.value.ied_type,
- sv_or_goose: gv.value,
- in_or_out: "输出",
- ref_ied_type: ends.value.ied_type
- }).then(res => {
- //if ( res.data) {
- //liling:避免提示空错误提示,res.data为空不代表接口有错误,所以先判断接口code值
- pastLoading.value = false
- if (res.code == 0) {
- if (res.data == null || res.data=="") {
- curList.value = [];
- return;
- }
-
- let tmpList = [];
- //对结果进行重排排序:将已关联到输出装置的端子排在前面
- res.data.forEach((item, index) => {
- if (item.to_ied_type == ends.value.ied_type) {
- tmpList.unshift(item)
- } else {
- //未关联的端子按原结果顺序排列
- tmpList.push(item)
- }
- })
-
- curList.value = tmpList
- //pastLoading.value = false
- } else {
- ElMessage({
- message: res.msg,
- type: "error"
- })
- }
- })
- await flow.getModelAndIed({
- model_id: modelIds.value - 0,
- ied_type: ends.value.ied_type,
- sv_or_goose: gv.value,
- in_or_out: "接收",
- ref_ied_type: starts.value.ied_type
- }).then(res => {
- console.log(res.data, '!!!!!');
- //if ( res.data) {
- //liling:避免提示空错误提示,res.data为空不代表接口有错误,所以先判断接口code值
- if (res.code == 0) {
- if (res.data == null || res.data=="") {
- outList.value = [];
- return;
- }
-
- //对结果进行重排排序:将已关联到输出装置的端子排在前面
- let tmpList = [];
- res.data.forEach((item, index) => {
- if (item.from_ied_type == starts.value.ied_type) {
- tmpList.unshift(item)
- } else {
- //未关联的端子按原结果顺序排列
- tmpList.push(item)
- }
- })
-
- outList.value = tmpList;
- // 将 setTimeout 移动到 then 方法中
- setTimeout(() => {
- res.data.forEach((item, index) => {
- let line = {
- start: item.from_fcda_id,
- end: item.id
- };
- let starts = document.getElementById(line.start);
- let ends = document.getElementById(line.end).parentNode;
- // console.log(starts, ends, '??????');
- // 检查 starts 和 ends 是否存在
- if (starts && ends) {
- /*
- leaderLineList.value.push();
- */
- const key=line.start+','+line.end
- leaderLineList.value[key] = new LeaderLine(starts, ends, {
- color: "#ccc",
- size: 2,
- path: "straight",
- startSocket: "right",
- endSocket: "left",
- endPlug: 'arrow3',
- endPlugSize: 2
- })
- hiddenLine();
- pastLoading.value = false
- } else {
- console.error(`Element with ID ${line.start} or ${line.end} not found.`);
- }
- });
- }, 100);
- } else {
- ElMessage({
- message: res.msg,
- type: "error"
- });
- }
- });
- curList.value.sort((obj1, obj2) => {
- if (outList.value[0] == null) return 1;
- const nameB = outList.value[0].fcda_name;
- if (obj1.fcda_name === nameB) return -1; // 将 name 与数组 b 中第一个对象的 name 属性相等的对象移到数组的第一位
- if (obj2.fcda_name === nameB) return 1;
- return 0;
- });
- }
- // 关闭模态框
- function closeModal() {
- removeLine3()
- dialogVisible.value = false
- emit("lineBack", dialogVisible.value)
- }
- // 确认关闭模态框
- function sureClose() {
- // if (leftFcda.value == '') {
- // leftFcda.value = curList.value[0].id
- // }
- // flow.saveModelOn({
- // model_id: modelIds.value - 0,
- // from_ied_type: starts.value.ied_type,
- // to_ied_type: ends.value.ied_type,
- // from_fcda_id: leftFcda.value - 0,
- // to_fcda_ids: fcdaIds.value,
- // goosesv: setGooseOrSv.value,
- // }).then(res => {
- // if (res.code == 0) {
- // ElMessage({
- // type: "success",
- // message: "关联成功!"
- // })
- dialogVisible.value = false
- removeLine3()
- // emit("lineBack", dialogVisible.value)
- // } else {
- // ElMessage({
- // type: "error",
- // message: res.msg
- // })
- // }
- // })
- }
- // 返回goose还是sv
- const setGooseOrSv = computed(() => {
- if (gv.value == "SV") {
- return "SV"
- } else if (gv.value == "GOOSE") {
- return "GOOSE"
- }
- })
- // 返回图片
- const setBackground = computed(() => {
- if (gv.value == "SV") {
- return require("../../../assets/image/sv_orange.png")
- } else if (gv.value == "GOOSE") {
- return require("../../../assets/image/goose_blue.png")
- }
- })
- // 返回文字颜色
- const setColor = computed(() => {
- if (gv.value == "SV") {
- return 'orange'
- } else if (gv.value == "GOOSE") {
- return 'blue'
- }
- })
- // 下标选择
- function setIndex(row, num) {
- console.log(row, 'row');
- if (row && num) {
- leftFcda.value = row.id
- // checkList.value = [row.to_fcda_id]
- fcdaIds.value = row.to_fcda_id
- leftIndex.value = num
- // flow.getModelOn({
- // model_id: modelIds.value - 0,
- // from_fcda_id: row.id - 0
- // }).then(res => {
- // if (res.data != null) {
- // together.value = res.data
- // checkList.value = together.value.map(item => {
- // return item.to_fcda_id
- // })
- // fcdaIds.value = res.data.map(item => {
- // return item.to_fcda_id
- // }).join(",")
- // loading.value = false
- // } else {
- // together.value = []
- // checkList.value = []
- // loading.value = false
- // }
- // })
- } else {
- if (curList.value.length > 0) {
- console.log(curList.value, 'cur');
- curList.value.map(item => {
- if (item.to_fcda_id != '0' || item.to_fcda_id != '') {
- checkList.value.push(item.to_fcda_id)
- }
- })
- leftFcda.value = curList.value[0].id
- // checkList.value = [curList.value[0].to_fcda_id]
- fcdaIds.value = curList.value[0].to_fcda_id
- leftIndex.value = 0
- // flow.getModelOn({
- // model_id: modelIds.value - 0,
- // from_fcda_id: curList.value[0].id - 0
- // }).then(res => {
- // if (res.data != null) {
- // together.value = res.data
- // checkList.value = together.value.map(item => {
- // return item.to_fcda_id
- // })
- // fcdaIds.value = res.data.map(item => {
- // return item.to_fcda_id
- // }).join(",")
- // loading.value = false
- // } else {
- // together.value = []
- // checkList.value = []
- // loading.value = false
- // }
- // })
- } else {
- ElMessage({
- type: "info",
- message: "您还没有配置装置"
- })
- loading.value = false
- }
- }
- }
- function checkChange(e) {
- if (e.length > 1) {
- fcdaIds.value = e[0]
- ElMessage({
- message: "只能选择一个端子,已保存上一次选择的端子",
- type: "error"
- })
- } else {
- fcdaIds.value = e.join(",")
- if (leftFcda.value == '') {
- leftFcda.value = curList.value[0].id
- }
- flow.saveModelOn({
- model_id: modelIds.value - 0,
- from_ied_type: starts.value.ied_type,
- to_ied_type: ends.value.ied_type,
- from_fcda_id: leftFcda.value - 0,
- to_fcda_ids: fcdaIds.value,
- goosesv: setGooseOrSv.value,
- }).then(res => {
- if (res.code == 0) {
- ElMessage({
- type: "success",
- message: "关联成功!"
- })
- reload()
- setIndex()
- removeLine3()
- emit("lineBack", dialogVisible.value)
- } else {
- ElMessage({
- type: "error",
- message: res.msg
- })
- }
- })
- }
- }
- //弹窗打开后使得线条在指定区域中
- function hiddenLine() {
- const elmWrapper = document.getElementById("wrapper");
- // 移动 line
- document.body.querySelectorAll("body .leader-line").forEach((node) => {
- elmWrapper.appendChild(node);
- });
- elmWrapper.style.transform = "none";
- var rectWrapper = elmWrapper.getBoundingClientRect();
- // Move to the origin of coordinates as the document
- elmWrapper.style.transform = `translate(${(rectWrapper.left + window.scrollY) * -1
- }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
- };
- // 稳定leader-line函数
- function removeLine3() {
- leaderLineList.value = {};
- const elmWrapper = document.getElementById("wrapper");
- if (elmWrapper) {
- document.body.querySelectorAll("#wrapper .leader-line").forEach((node) => {
- elmWrapper.removeChild(node);
- });
- }
- };
- onMounted(async () => {
- await reload()
- setIndex()
- })
- onBeforeUnmount(() => {
- for(let key in leaderLineList.value){
- leaderLineList.value[key].remove();
- }
- //leaderLineList.value.forEach(line => line.remove());//离开当前组件时清除连线
- removeLine3()
- })
- return {
- dialogVisible,//模态框开关
- reload,//初始化函数
- starts,//开始节点数据
- ends,//结束节点数据
- handleClose: closeModal,//关闭模态框
- cancels: closeModal,//关闭模态框
- sureClick: sureClose,//确认关闭模态框
- modelIds,//本组件的模型id
- startTxt,//本组件开始文本
- endTxt,//本组件结束文本
- curList,//渲染list
- setGooseOrSv,//判断显示goose还是sv
- setBackground,//判断显示背景图
- setColor,//判断文字颜色
- visibleItems,//选择的数组
- // toggleVisibility,//模拟多选框方法
- fcdaIds,//需要的fcda_ids
- leftIndex,//左侧下标选择
- setIndex,//下标选择函数
- // getClass,//设置多选span的class函数
- leftFcda,//左侧单选的fcdaid
- outList,//箭头指向端list
- together,//绑定的id
- // isVisible,
- loading,
- checkList,
- checkChange,
- arrNew,//新的存储ids
- gv,
- pastLoading,//maxbox加载动画
- leaderLineList,//组件库leader-line数据,以方便离开组件时清除画线
- hiddenLine,//使leader-line显示在模态框内
- removeLine3,// 稳定leader-line函数
- }
- }
- }
- </script>
- <style scoped>
- .masBox {
- width: 100%;
- height: calc(100vh - 400px);
- /* border: 1px solid red; */
- display: flex;
- justify-content: space-around;
- align-items: center;
- overflow-y: auto;
- position: relative;
- }
- .leftBox {
- width: 33%;
- /* height: calc(100vh - 420px); */
- text-align: center;
- background-color: #F7F8FB;
- border: 2px dashed #A3ADE0;
- position: absolute;
- top: 2%;
- left: 5%;
- }
- .middleBox {
- width: 22%;
- height: calc(100vh - 420px);
- display: flex;
- justify-content: space-around;
- align-items: center;
- position: absolute;
- top: 5%;
- left: 39%;
- }
- .rightBox {
- width: 33%;
- /* height: calc(100vh - 420px); */
- text-align: center;
- background-color: #EDF3FF;
- border: 2px dashed #A3ADE0;
- position: absolute;
- top: 2%;
- right: 5%;
- }
- .result {
- display: inline-block;
- width: 11%;
- height: 40px;
- border: 1px solid blue;
- text-align: center;
- line-height: 40px;
- background-color: #D9E6FE;
- color: blue;
- margin-right: 10px;
- }
- .anther {
- display: inline-block;
- width: 11%;
- height: 40px;
- border: 1px solid black;
- text-align: center;
- line-height: 40px;
- background-color: #F5FAFE;
- color: black;
- margin-right: 10px;
- }
- .results {
- display: inline-block;
- width: 75%;
- height: 40px;
- border: 1px solid blue;
- text-align: left;
- line-height: 40px;
- background-color: #D9E6FE;
- color: blue;
- padding-left: 5px;
- }
- .anthers {
- display: inline-block;
- width: 75%;
- height: 40px;
- border: 1px solid black;
- text-align: left;
- line-height: 40px;
- background-color: #F5FAFE;
- color: black;
- padding-left: 5px;
- }
- .background {
- width: 90%;
- height: calc(100vh - 850px);
- /* background-position: 100%; */
- background-repeat: no-repeat;
- background-size: 100%;
- text-align: center;
- background-position: 100% 50%;
- line-height: calc(100vh - 850px);
- }
- :deep(.el-checkbox__inner) {
- width: 40px !important;
- height: 40px !important;
- background-color: white !important;
- }
- :deep(.el-checkbox__inner::after) {
- height: 30px !important;
- left: 11px !important;
- width: 15px !important;
- top: -2px !important;
- border-color: #2B5AE5;
- }
- :deep(.el-checkbox__input.is-checked .el-checkbox__inner::after) {
- border-color: #2B5AE5;
- }
- :deep(.el-checkbox) {
- width: 300px !important;
- height: 42px !important;
- margin-right: 0 !important;
- margin-bottom: 10px !important;
- }
- :deep(.el-checkbox__label) {
- width: 202px !important;
- height: 42px !important;
- margin-left: 10px !important;
- line-height: 42px !important;
- text-align: center;
- }
- .leader-line {
- z-index: 3000;
- }
- #wrapper {
- width: 0;
- height: 0;
- position: relative;
- /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
- }
- :deep(.el-radio__inner) {
- width: 32px;
- height: 32px;
- }
- :deep(.el-radio__input.is-checked .el-radio__inner::after) {
- width: 15px;
- height: 15px;
- }
- :deep(.el-radio-group) {
- width: 100%;
- justify-content: space-between;
- margin: 4px;
- }
- </style>
|