<template>
|
<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-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>
|
</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>
|
|
</a-card>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { ref, onMounted } from "vue";
|
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[]>([
|
{
|
id: 1010,
|
title: "干燥启动",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1007,
|
title: "停止运行",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1013,
|
title: "热风启动",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1012,
|
title: "后门开关",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1003,
|
title: "滚筒升",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1004,
|
title: "滚筒降",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1005,
|
title: "滚筒正转",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1006,
|
title: "滚筒反转",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1014,
|
title: "开门观察",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1015,
|
title: "出料",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1016,
|
title: "清除",
|
icon: "caret-right-outlined"
|
}, {
|
id: 1017,
|
title: "手动/自动",
|
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);
|
//发送指令
|
sendCmd(item);
|
}
|
|
/**
|
* 发送指令
|
* @param item
|
*/
|
function sendCmd(item) {
|
var params = { msg: item.title, code: item.id, tenantId: 1003, machineId: "GM001" };
|
sendCommand(params).then(res => {
|
if (res.success) {
|
addLog("响应", res.message);
|
console.info(res);
|
} else {
|
console.info(res);
|
addLog("响应", res.message);
|
}
|
|
});
|
}
|
|
/**
|
* 添加log
|
* @param type
|
* @param msg
|
*/
|
function addLog(type, msg) {
|
//发送log
|
const date = new Date();
|
const format = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")} ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}`;
|
const log = format + " " + type + ":" + msg;
|
logList.value.unshift(log);
|
}
|
|
const showModal = () => {
|
visible.value = true;
|
};
|
|
const cnacelModal = () => {
|
router.back()
|
}
|
|
const hideModal = () => {
|
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>
|
|
<style lang="less" scoped>
|
.app {
|
margin: 10px;
|
}
|
|
.com-box {
|
// 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: 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>
|