This commit is contained in:
JayJiaJun 2025-03-13 09:58:38 +08:00
parent b752d013bb
commit f43f1d57ed
5 changed files with 250 additions and 84 deletions

View File

@ -6,7 +6,7 @@
* @LastEditors: Andy * @LastEditors: Andy
* @LastEditTime: 2024-03-11 11:07:00 * @LastEditTime: 2024-03-11 11:07:00
*/ */
var MQTT_MODE = 1; var MQTT_MODE = 0;
function pageName() { function pageName() {
var a = location.href; var a = location.href;

View File

@ -112,9 +112,9 @@ class GamepadController {
const axis9 = axes[9]; const axis9 = axes[9];
const roundedAxis9 = Math.round(axis9 * 100) / 100; const roundedAxis9 = Math.round(axis9 * 100) / 100;
if (roundedAxis9 <= -0.9) { if (roundedAxis9 <= -0.9) {
this.directionAxis9 = 0;
} else if (roundedAxis9 >= 0.0 && roundedAxis9 <= 0.2) {
this.directionAxis9 = 1; this.directionAxis9 = 1;
} else if (roundedAxis9 >= 0.0 && roundedAxis9 <= 0.2) {
this.directionAxis9 = 2;
// } else if (roundedAxis9 >= 0.6 && roundedAxis9 <= 0.8) { // } else if (roundedAxis9 >= 0.6 && roundedAxis9 <= 0.8) {
// this.directionAxis9 = "左"; // this.directionAxis9 = "左";
// } else if (roundedAxis9 >= -0.5 && roundedAxis9 <= -0.4) { // } else if (roundedAxis9 >= -0.5 && roundedAxis9 <= -0.4) {

View File

@ -223,7 +223,8 @@ export default {
initWebSocket() { initWebSocket() {
try { try {
console.log('正在连接 WebSocket...'); console.log('正在连接 WebSocket...');
this.ws = new WebSocket('ws://192.168.4.120/ws'); // this.ws = new WebSocket('ws://192.168.4.120/ws');
this.ws = new WebSocket('ws://192.168.1.120/ws');
// this.ws = new WebSocket('ws://192.168.1.60:81'); // this.ws = new WebSocket('ws://192.168.1.60:81');

View File

@ -1,13 +1,7 @@
<template> <template>
<div class="gateway-setting"> <div class="gateway-setting">
<!-- 固定标题栏 --> <!-- 固定标题栏 -->
<van-nav-bar <van-nav-bar title="事件列表" left-arrow @click-left="onClickLeft" fixed placeholder />
title="事件列表"
left-arrow
@click-left="onClickLeft"
fixed
placeholder
/>
<!-- 添加下拉刷新组件 --> <!-- 添加下拉刷新组件 -->
<van-pull-refresh v-model="refreshing" @refresh="onRefresh"> <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
@ -33,14 +27,8 @@
<div class="info-title">网络参数</div> <div class="info-title">网络参数</div>
<div class="info-row"> <div class="info-row">
<span class="info-label">网络ID</span> <span class="info-label">网络ID</span>
<van-field <van-field v-model="networkId" type="text" input-align="right" placeholder="请输入网络ID" maxlength="6"
v-model="networkId" :formatter="value => value.replace(/[^0-9]/g, '')" />
type="text"
input-align="right"
placeholder="请输入网络ID"
maxlength="6"
:formatter="value => value.replace(/[^0-9]/g, '')"
/>
</div> </div>
<div class="info-row"> <div class="info-row">
<span class="info-label">无线频段</span> <span class="info-label">无线频段</span>
@ -72,7 +60,12 @@
<!-- 设备地址输入 --> <!-- 设备地址输入 -->
<van-cell-group inset> <van-cell-group inset>
<van-field v-model="deviceAddress" label="设备地址" placeholder="请输入设备地址" input-align="right" /> <van-field
v-model="deviceAddress"
label="设备地址"
placeholder="请输入设备地址"
input-align="right"
/>
<van-cell center title="事件开关"> <van-cell center title="事件开关">
<template #right-icon> <template #right-icon>
<van-switch v-model="eventEnabled" size="24" /> <van-switch v-model="eventEnabled" size="24" />
@ -109,8 +102,28 @@
<van-cell-group inset title="基础设置"> <van-cell-group inset title="基础设置">
<van-field v-model="currentEvent.type" is-link readonly label="事件类型" placeholder="请选择事件类型" <van-field v-model="currentEvent.type" is-link readonly label="事件类型" placeholder="请选择事件类型"
input-align="right" @click="showTypePopup" /> input-align="right" @click="showTypePopup" />
<!-- 当选择"其他"时显示的输入框 -->
<van-field
v-if="currentEvent.type === '其他'"
v-model="customEventType"
label="自定义类型"
placeholder="请输入自定义事件类型"
input-align="right"
type="number"
/>
<van-field v-model="currentEvent.source" is-link readonly label="事件来源" placeholder="请选择事件来源" <van-field v-model="currentEvent.source" is-link readonly label="事件来源" placeholder="请选择事件来源"
input-align="right" @click="showSourcePopup" /> input-align="right" @click="showSourcePopup" />
<!-- 当选择"其他"时显示的输入框 -->
<van-field
v-if="currentEvent.source === '其他'"
v-model="customEventSource"
label="自定义来源"
placeholder="请输入自定义事件来源"
input-align="right"
type="number"
/>
<van-field v-model="currentEvent.priority" is-link readonly label="优先级" placeholder="请选择优先级" <van-field v-model="currentEvent.priority" is-link readonly label="优先级" placeholder="请选择优先级"
input-align="right" @click="showPriorityPopup" /> input-align="right" @click="showPriorityPopup" />
</van-cell-group> </van-cell-group>
@ -160,6 +173,42 @@
</template> </template>
</van-cell> </van-cell>
</div> </div>
<!-- 在输出设置部分添加自定义输入框 -->
<template v-if="output.type === '其他'">
<div class="output-settings">
<van-field
v-model="output.customTarget"
label="目标板卡号"
type="number"
input-align="right"
placeholder="请输入目标板卡号"
/>
<div class="custom-data-inputs">
<van-field
v-model="output.customData1"
label="数据1"
type="number"
input-align="right"
placeholder="请输入数据1"
/>
<van-field
v-model="output.customData2"
label="数据2"
type="number"
input-align="right"
placeholder="请输入数据2"
/>
<van-field
v-model="output.customData3"
label="数据3"
type="number"
input-align="right"
placeholder="请输入数据3"
/>
</div>
</div>
</template>
</template> </template>
<template #right-icon> <template #right-icon>
<van-button size="small" type="danger" @click="removeOutput(index)">删除</van-button> <van-button size="small" type="danger" @click="removeOutput(index)">删除</van-button>
@ -223,7 +272,7 @@
</template> </template>
<script> <script>
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'; import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
// import { showConfirmDialog, showToast } from 'vant'; // import { showConfirmDialog, showToast } from 'vant';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
@ -313,20 +362,30 @@ export default {
const timeSourceTypes = [ const timeSourceTypes = [
{ text: '本台设备', value: 0x00 }, { text: '本台设备', value: 0x00 },
{ text: '任意设备(除本身外任意设备)', value: 0xfe }, { text: '任意设备(除本身外任意设备)', value: 0xfe },
{ text: '任意设备', value: 0xff } { text: '任意设备', value: 0xff },
{ text: '其他', value: 'other' }
]; ];
const priorityLevels = [ const priorityLevels = [
{ text: '0', value: 0 }, { text: '0', value: 0 },
{ text: '1', value: 1 }, { text: '1', value: 1 },
{ text: '2', value: 2 } { text: '2', value: 2 },
{ text: '3', value: 3 },
{ text: '4', value: 4 },
{ text: '5', value: 5 },
{ text: '6', value: 6 },
{ text: '7', value: 7 },
{ text: '8', value: 8 },
{ text: '9', value: 9 },
{ text: '10', value: 10 },
]; ];
const outputTypes = [ const outputTypes = [
{ text: '显卡输出', value: 'display' }, { text: '显卡输出', value: 'display' },
{ text: '声卡输出', value: 'audio' }, { text: '声卡输出', value: 'audio' },
{ text: '路锥输出', value: 'serial' }, { text: '路锥输出', value: 'serial' },
{ text: '引脚模式', value: 'io' } { text: '引脚模式', value: 'io' },
{ text: '其他', value: 'other' }
]; ];
const currentEvent = reactive({ const currentEvent = reactive({
@ -352,6 +411,10 @@ export default {
// WebSocket // WebSocket
const ws = ref(null); const ws = ref(null);
// setup
const customEventType = ref('');
const customEventSource = ref('');
const onClickLeft = () => { const onClickLeft = () => {
router.back(); router.back();
}; };
@ -389,23 +452,29 @@ export default {
const onOutputConfirm = (value) => { const onOutputConfirm = (value) => {
const outputType = value.selectedOptions[0].text; const outputType = value.selectedOptions[0].text;
const newOutput = { const output = {
type: outputType, type: outputType,
...(outputType === '显卡输出' ? { ...(outputType === '显卡输出' ? {
programNumber: '1', programNumber: '1',
duration: '60' duration: '10'
} : {}), } : {}),
...(outputType === '声卡输出' ? { ...(outputType === '声卡输出' ? {
audioNumber: '1' audioNumber: '1'
} : {}), } : {}),
...(outputType === '路锥输出' ? { ...(outputType === '路锥输出' ? {
lightMode: '' lightMode: '常亮'
} : {}), } : {}),
...(outputType === '引脚模式' ? { ...(outputType === '引脚模式' ? {
pins: [] pins: []
} : {}),
...(outputType === '其他' ? {
customTarget: '',
customData1: '0',
customData2: '0',
customData3: '0'
} : {}) } : {})
}; };
currentEvent.outputs.push(newOutput); currentEvent.outputs.push(output);
outputPickerVisible.value = false; outputPickerVisible.value = false;
}; };
@ -425,29 +494,37 @@ export default {
}; };
const saveEvent = () => { const saveEvent = () => {
// //
if (!currentEvent.type || !currentEvent.source || !currentEvent.priority || currentEvent.outputs.length === 0) { if (!currentEvent.type || !currentEvent.source || !currentEvent.priority || currentEvent.outputs.length === 0) {
showToast('请填写所有必填字段并至少添加一个输出'); showToast('请填写所有必填字段并至少添加一个输出');
return; return;
} }
// //
if (currentEvent.type === '其他' && !customEventType.value) {
showToast('请填写自定义事件类型');
return;
}
if (currentEvent.source === '其他' && !customEventSource.value) {
showToast('请填写自定义事件来源');
return;
}
const outputs = currentEvent.outputs.map(output => { const outputs = currentEvent.outputs.map(output => {
let target; let target = 0;
let data = [0, 0, 0]; let data = [0, 0, 0];
//
switch (output.type) { switch (output.type) {
case '显卡输出': case '显卡输出':
target = 101; target = 102;
data = [ data = [
parseInt(output.programNumber) || 0, parseInt(output.programNumber) || 0,
parseInt(output.duration) || 0, parseInt(output.duration) || 10,
0 0
]; ];
break; break;
case '声卡输出': case '声卡输出':
target = 102; target = 103;
data = [ data = [
parseInt(output.audioNumber) || 0, parseInt(output.audioNumber) || 0,
0, 0,
@ -455,7 +532,7 @@ export default {
]; ];
break; break;
case '路锥输出': case '路锥输出':
target = 103; target = 106;
data = [ data = [
lightModes.find(mode => mode.text === output.lightMode)?.value || 0, lightModes.find(mode => mode.text === output.lightMode)?.value || 0,
0, 0,
@ -463,48 +540,40 @@ export default {
]; ];
break; break;
case '引脚模式': case '引脚模式':
target = 104; target = 1;
const pinValue = output.pins.reduce((acc, pin) => acc | (1 << parseInt(pin)), 0); const pinValue = output.pins.reduce((acc, pin) => acc | (1 << parseInt(pin)), 0);
data = [pinValue, 0, 0]; data = [pinValue, 0, 0];
break; break;
case '其他':
target = parseInt(output.customTarget) || 0;
data = [
parseInt(output.customData1) || 0,
parseInt(output.customData2) || 0,
parseInt(output.customData3) || 0
];
break;
} }
return { return { target, data };
target,
data
};
}); });
// 使 index
const getNextAvailableIndex = () => {
const usedIndices = events.value.map(e => e.index).sort((a, b) => a - b);
let index = 0;
while (usedIndices.includes(index)) {
index++;
}
return index;
};
//
const eventConfig = { const eventConfig = {
"JSON_id": jsonId.value, board_id: 1,
"board_id": 1, JSON_id: jsonId.value,
"gateway": { gateway: {
"trig_cfg": { trig_cfg: {
"event_en": eventEnabled.value ? 1 : 0, event_group: [{
"addr": parseInt(deviceAddress.value) || 0, index: events.value.length,
"operate": isEdit.value ? 2 : 1, // ""使
"event_group": [ event_id: currentEvent.type === '其他'
{ ? parseInt(customEventType.value)
"index": isEdit.value : parseInt(eventTypes.find(type => type.text === currentEvent.type)?.value || '0'),
? currentEvent.index source: currentEvent.source === '其他'
: getNextAvailableIndex(), ? parseInt(customEventSource.value)
"event_id": parseInt(eventTypes.find(type => type.text === currentEvent.type)?.value) || 0, : timeSourceTypes.find(source => source.text === currentEvent.source)?.value || 0,
"source": timeSourceTypes.find(source => source.text === currentEvent.source)?.value || 0, priority: parseInt(currentEvent.priority),
"priority": parseInt(currentEvent.priority) || 0, output: outputs
"output": outputs }]
}
]
} }
} }
}; };
@ -804,26 +873,26 @@ export default {
// //
switch (output.target) { switch (output.target) {
case 101: // case 102: //
type = '显卡输出'; type = '显卡输出';
config = { config = {
programNumber: output.data[0].toString(), programNumber: output.data[0].toString(),
duration: output.data[1].toString() duration: output.data[1].toString()
}; };
break; break;
case 102: // case 103: //
type = '声卡输出'; type = '声卡输出';
config = { config = {
audioNumber: output.data[0].toString() audioNumber: output.data[0].toString()
}; };
break; break;
case 103: // case 106: //
type = '路锥输出'; type = '路锥输出';
config = { config = {
lightMode: lightModes.find(mode => mode.value === output.data[0].toString())?.text || '常亮' lightMode: lightModes.find(mode => mode.value === output.data[0].toString())?.text || '常亮'
}; };
break; break;
case 104: // case 1: //
type = '引脚模式'; type = '引脚模式';
const pinValue = output.data[0]; const pinValue = output.data[0];
config = { config = {
@ -877,11 +946,94 @@ export default {
}, 1000); }, 1000);
}; };
// setup
const sendDeviceAddressConfig = () => {
const configData = {
"board_id": 1,
"JSON_id": jsonId.value,
"gateway": {
"device_addr": deviceAddress.value
}
};
console.log('Sending device address config:', configData);
if (isLocal.value) {
axios.post('/communication', configData, {
headers: {
"content-type": "application/json"
}
})
.then(response => {
console.log('Device address config response:', response.data);
showToast('设备设置成功');
jsonId.value++;
})
.catch(error => {
console.error('Device address config error:', error);
showToast('设备设置失败');
jsonId.value++;
});
} else {
MQTT_send(configData);
}
};
const sendEventSwitchConfig = () => {
const configData = {
"board_id": 1,
"JSON_id": jsonId.value,
"gateway": {
"event_enable": eventEnabled.value ? 1 : 0
}
};
console.log('Sending event switch config:', configData);
if (isLocal.value) {
axios.post('/communication', configData, {
headers: {
"content-type": "application/json"
}
})
.then(response => {
console.log('Event switch config response:', response.data);
showToast('事件开关打开成功');
jsonId.value++;
})
.catch(error => {
console.error('Event switch config error:', error);
showToast('事件开关打开失败');
jsonId.value++;
});
} else {
MQTT_send(configData);
}
};
//
let deviceAddressTimeout;
watch(deviceAddress, (newValue, oldValue) => {
if (newValue && newValue !== oldValue) {
// 使 setTimeout
if (deviceAddressTimeout) {
clearTimeout(deviceAddressTimeout);
}
deviceAddressTimeout = setTimeout(() => {
sendDeviceAddressConfig();
}, 1000); // 1
}
});
//
watch(eventEnabled, () => {
sendEventSwitchConfig();
});
// //
onMounted(() => { onMounted(() => {
checkEnvironment(); checkEnvironment();
getLoRaConfig();
}); });
// //
@ -1008,6 +1160,10 @@ export default {
firmwareVersionEl, firmwareVersionEl,
macAddressEl, macAddressEl,
ws, ws,
sendDeviceAddressConfig,
sendEventSwitchConfig,
customEventType,
customEventSource,
}; };
} }
}; };
@ -1141,4 +1297,12 @@ export default {
min-height: 100vh; min-height: 100vh;
background-color: #f7f8fa; background-color: #f7f8fa;
} }
.custom-data-inputs {
margin-top: 8px;
}
.custom-data-inputs :deep(.van-field) {
margin-bottom: 8px;
}
</style> </style>

View File

@ -4,6 +4,7 @@ const AutoImport = require('unplugin-auto-import/webpack');
const Components = require('unplugin-vue-components/webpack'); const Components = require('unplugin-vue-components/webpack');
const { codeInspectorPlugin } = require('code-inspector-plugin'); const { codeInspectorPlugin } = require('code-inspector-plugin');
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers') const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
const CompressionWebpackPlugin = require('compression-webpack-plugin');
module.exports = defineConfig({ module.exports = defineConfig({
lintOnSave: false, lintOnSave: false,
@ -44,7 +45,7 @@ module.exports = defineConfig({
}), }),
Components.default({ resolvers: [VantResolver(),ElementPlusResolver()] }), Components.default({ resolvers: [VantResolver(),ElementPlusResolver()] }),
// new CompressionPlugin({ // new CompressionWebpackPlugin({
// algorithm: 'gzip', // 使用gzip压缩 // algorithm: 'gzip', // 使用gzip压缩
// test: /\.js$|\.html$|\.css$/, // 匹配文件名 // test: /\.js$|\.html$|\.css$/, // 匹配文件名
// filename: '[path][base].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz) // filename: '[path][base].gz[query]', // 压缩后的文件名(保持原文件名,后缀加.gz)