干燥机配套车间生产管理系统/云平台服务端
bsw215583320
2024-04-09 1f1fd51a80c6d790e0e797fca3b233399e92ce5e
src/views/dashboard/control/index.vue
@@ -1,21 +1,164 @@
<template>
  <a-modal v-model:visible="visible" centered :mask="false" :closable="false" :cancelText="null" title="警告"
           @ok="hideModal">
  <a-modal v-model:visible="visible" centered :mask="true" :maskClosable="false" :keyboard="false" :closable="false" :cancelText="null" title="警告"
           @ok="hideModal" @cancel="cnacelModal" >
    <a-card>
       <div class="indented-text">在使用远程控制设备前,请确保机器周围没有其他人员。建立一个安全区域,确保没有人能够进入该区域,防止不必要的伤害。</div>
      <div style="display: flex; justify-content: space-between; padding-top: 20px; ">
        <p style="font-weight: bold;" >请输入密码:</p>
        <p style="color: red">{{ error }}</p>
      </div>
       <div >
        <a-input-password v-model:value="password" placeholder="请输入密码!"></a-input-password>
       </div>
    </a-card>
  </a-modal>
  <div class="app">
    <a-card title="指令">
      <div class="com-box">
        <a-button v-for="item in comList" :key="item.id" type="primary" class="com-btn"
                  @click="comClick(item)">
          {{ item.title }}
        </a-button>
    <a-row>
      <div style="width: 60%">
      <a-card title="照明" >
      <div class="light-box">
        <div v-for="item in lightList" :key="item.identifier"  class="center">
          <!-- <a-button v-if="item.type == 0"  type="primary" class="com-btn"
                  @click="deviceClick(item)">
          {{ item.name }}
        </a-button> -->
          <div v-if="item.type==0" @click="deviceClick(item)">
            <div   :class="[ item.value?'lightOn':'lightOff' ,'device']">
            </div>
            <div class="text-center">{{ item.name }}</div>
            </div>
        </div>
      </div>
    </a-card>
    <a-card title="控制台" style="margin-top: 10px">
  </div>
  <div style="width: 40%">
    <a-card title="监控" style=" margin-left: 10px;">
      <div class="monitor-box">
        <div v-for="item in lightList" :key="item.identifier" class="center" >
          <div v-if="item.type==1" @click="deviceClick(item)">
            <div   :class="[ item.value?'camOn':'camOff' ,'device']">
            </div>
            <div class="text-center">{{ item.name }}</div>
            </div>
      </div>
      </div>
    </a-card>
</div>
    </a-row>
 <a-row>
      <div style="width: 50%">
<a-card title="指令" style="margin-top: 10px; ">
      <div class="com-box">
        <!-- <a-button v-for="item in comList" :key="item.id" type="primary" class="com-btn"
                  @click="comClick(item)">
          {{ item.title }}
        </a-button> -->
        <div style="width: 500px;"  >
        <a-row class="button-row">
          <a-button type="primary" :disabled="btnDisabled"  @click="clickButton(1010, '干燥启动')" class="com-btn">
            <div> <PlayCircleOutlined style="font-size: 20px;" /> </div>
          <div>  干燥启动 </div>
        </a-button>
        <!-- <a-button type="normal" @click="clickButton(1012)" class="com-btn">
          <div> <SplitCellsOutlined style="font-size: 20px;" /> </div>
          <div>  后门开关 </div>
        </a-button> -->
        <a-button type="default" :disabled="btnDisabled"  @click="clickButton(1003,'滚筒升')" class="com-btn w300">
          <div> <UpCircleOutlined style="font-size: 20px;" /> </div>
          <div>  滚筒升 </div>
        </a-button>
        <a-button type="normal" :disabled="btnDisabled" @click="clickButton(1016,'清除')" class="com-btn">
          <div> <ClearOutlined style="font-size: 20px;" /> </div>
          <div>  清除 </div>
        </a-button>
        </a-row>
        <a-row class="button-row">
          <a-button type="normal" :disabled="btnDisabled"  @click="clickButton(1005,'滚筒正转')" class="com-btn h100">
            <div>  <RedoOutlined style="font-size: 20px;" /> </div>
            <div> 滚筒正转 </div>
        </a-button>
          <a-button type="danger" :disabled="btnDisabled"  @click="clickButton(1007,'停止')" class="com-btn h100 w300 " >
            <div> <PauseCircleOutlined style="font-size: 20px;" />  </div>
            <div>  停止 </div>
        </a-button>
        <a-button type="normal" :disabled="btnDisabled"  @click="clickButton(1006,'滚筒反转')" class="com-btn h100">
          <div> <UndoOutlined style="font-size: 20px;" /> </div>
          <div>  滚筒反转 </div>
        </a-button>
        </a-row>
        <a-row class="button-row">
          <a-button type="success" :disabled="btnDisabled"  @click="clickButton(1015,'出料')" class="com-btn">
            <div> <DownloadOutlined style="font-size: 20px;" /> </div>
            <div>  出料 </div>
        </a-button>
        <!-- <a-button type="normal" @click="clickButton(1010)" class="com-btn">
          <div> <SplitCellsOutlined style="font-size: 20px;" /> </div>
          <div>  前门开关 </div>
        </a-button> -->
        <a-button type="normal" :disabled="btnDisabled"  @click="clickButton(1004,'滚筒降')" class="com-btn w300">
          <div> <DownCircleOutlined style="font-size: 20px;" /> </div>
          <div>  滚筒降 </div>
        </a-button>
        <a-button type="normal" :disabled="btnDisabled"  @click="clickButton(1013,'热风启动')" class="com-btn">
          <div> <FireOutlined style="font-size: 20px;" /> </div>
            <div>  热风启动 </div>
        </a-button>
      </a-row>
        </div>
      </div>
    </a-card>
    </div>
    <div style="width: 50%">
    <a-card title="状态" style="margin-left: 10px;margin-top:10px">
      <div class="com-box">
        <div>
      <div>
          <a-button type="warning" :disabled="btnDisabled"  @click="clickButton(1017,'手动/自动')" class="com-btn">
            <div> <SyncOutlined style="font-size: 20px;" /> </div>
          <div>  手动/自动 </div>
        </a-button>
      </div>
      <div>
        <a-button type="info" :disabled="btnDisabled"  @click="clickButton(1014, '开门观察')" class="com-btn">
          <div> <SettingOutlined style="font-size: 20px;" /> </div>
          <div>  开门观察 </div>
        </a-button>
      </div>
      <div>
        <a-button type="normal" @click="lock()" class="com-btn">
          <div> <Icon :icon="lockIcon" :size="28" /> </div>
          <div>  {{lockText}} </div>
        </a-button>
      </div>
      </div>
    </div>
    </a-card>
  </div>
    </a-row>
    <a-card title="控制台" style="margin-top: 10px; ">
      <div class="log-box">
        <p v-for="log in logList" :key="log"> {{ log }}</p>
      </div>
@@ -26,16 +169,31 @@
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { sendCommand } from "./api";
import { sendCommand, sendWriteCommand, listAll } from "./api";
import { useGlobSetting } from '/@/hooks/setting';
import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
import { useUserStore } from '/@/store/modules/user';
import { RedoOutlined ,SettingOutlined, UndoOutlined,FireOutlined, SplitCellsOutlined, DownloadOutlined, PauseCircleOutlined,ClearOutlined, SyncOutlined,PlayCircleOutlined, SwapOutlined , UpCircleOutlined, DownCircleOutlined, LeftCircleOutlined, RightCircleOutlined} from '@ant-design/icons-vue';
import { router } from '/@/router'
const error = ref('')
const lockIcon = ref('tdesign:lock-off')
const lockText = ref('解锁')
const password = ref()
const visible = ref<boolean>(false);
  const glob = useGlobSetting();
interface Commant {
  id: number;
  title: string;
  icon: string;
}
interface Device {
  name: string;
  identifier: string;
  value: boolean;
  sort_order: number;
}
const userStore = useUserStore();
const logList = ref<string[]>([]);
const comList = ref<Commant[]>([
  {
@@ -88,6 +246,19 @@
    icon: "caret-right-outlined"
  }]);
const btnDisabled = ref(true)
const lightList = ref<Device[]>([]);
const monitorList = ref<Device[]>([]);
function lock() {
  btnDisabled.value = !btnDisabled.value
  lockIcon.value = btnDisabled.value?'tdesign:lock-off':'tdesign:lock-on'
  lockText.value = btnDisabled.value?'解锁': '锁定'
  if (btnDisabled.value) {
    showModal()
  }
}
function comClick(item) {
  addLog("发送", item.title);
  //发送指令
@@ -129,13 +300,109 @@
  visible.value = true;
};
const cnacelModal = () => {
  router.back()
}
const hideModal = () => {
  visible.value = false;
  if(!password.value || password.value.length<=0) {
    error.value="请输入密码!"
  }else
  if(password.value === 'LBit@123') {
    visible.value = false;
    password.value = ''
    error.value = ''
  } else {
    error.value = '密码错误!'
  }
};
/**
 * 查询灯和摄像头列表
 */
function queryDevice() {
  listAll({}).then(res => {
    console.log("ress000:",res);
    lightList.value = res
  })
}
function clickButton(cmd, msg) {
  console.log("target::::",cmd);
  let tenantId = userStore.getTenant;
  var params = { msg: msg, code: cmd, tenantId: tenantId, machineId: "GM001" };
  sendCommand(params).then(res => {
    if (res.success) {
      addLog("响应", res.message);
      console.info(res);
    } else {
      console.info(res);
      addLog("响应", res.message);
    }
  });
}
function deviceClick(item) {
  //console.log("item===",item.value);
  let params = {code: item.identifier, msg: !item.value}
  sendWriteCommand(params).then(res => {
    console.log("写指令结果::", res)
    if(res.success) {
      lightList.value.forEach(device => {
          if(device.identifier == item.identifier) {
            device.value = !item.value
          }
        })
    }
  })
}
    // 初始化 WebSocket
    function initWebSocket() {
        let user = userStore.getUserInfo;
        let tenantId = user.loginTenantId;
        console.log(user);
        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
         let url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/drySocket/' + tenantId;
         connectWebSocket(url);
         onWebSocket(onWebSocketMessage);
      }
      function onWebSocketMessage(data) {
        console.log("drysocket:data::",data)
        lightList.value.forEach(item => {
          if(item.identifier == data.identifier) {
            item.value = data.value
          }
        })
      }
      function keydown(e) {
        error.value = ''
        if(e.keyCode == 13) {
          hideModal()
        }
      }
onMounted(() => {
  showModal();
  initWebSocket();
  window.addEventListener('keydown', keydown)
});
queryDevice()
</script>
@@ -146,23 +413,101 @@
}
.com-box {
  display: flex;
  flex-wrap: wrap;
  // margin-left: 200px;
  display: flex;
  justify-content: center;
  .com-btn {
    border-radius: 5px;
    width: 100px;
    margin: 10px;
    height: 70px;
  }
}
.button-row {
  display: flex; justify-content: space-between;
}
.log-box {
  min-height: 200px;
  max-height: 300px;
  overflow-y: scroll;
  min-height: 150px;
  max-height: 150px;
  overflow-y: auto;
}
.indented-text {
  text-indent: 20px;
  font-size: 16px;
}
.light-box {
  display: flex;
  justify-items: center;
justify-content: center;
  flex-wrap: wrap;
}
.center {
  display: flex;
justify-items: center;
justify-content: center;
}
.text-center {
  text-align: center;
}
.lightOn {
    background-image: url(/src/assets/images/dry/control/light.png);
    background-repeat: no-repeat;
      background-size: 50px;
      /* border-radius: 10px; */
      background-position: 48px 0px;
  }
  .lightOff {
    background-image: url(/src/assets/images/dry/control/light-close.png);
    background-repeat: no-repeat;
      background-size: 50px;
      /* border-radius: 10px; */
      background-position: 48px 0px;
  }
  .camOn {
    background-image: url(/src/assets/images/dry/control/cam1.png);
    background-repeat: no-repeat;
      background-size: 50px;
      /* border-radius: 10px; */
      background-position: 48px 0px;
  }
  .camOff {
    background-image: url(/src/assets/images/dry/control/cam0.png);
    background-repeat: no-repeat;
      background-size: 50px;
      /* border-radius: 10px; */
      background-position: 48px 0px;
  }
.device {
  width: 150px; height: 60px;
}
.h100 {
  height: 70px !important;
}
.w300 {
  width: 100px !important;
}
.monitor-box {
  display: flex;
  justify-items: center;
justify-content: center;
flex-wrap: wrap;
}
</style>