Compare commits

..

No commits in common. "dcf7393393f0c9e0ca2d4e449479c5e264c6b3ff" and "5de81ff43744599d1dca767871234f6df046a9f5" have entirely different histories.

2 changed files with 166 additions and 287 deletions

View file

@ -1,6 +1,6 @@
<template> <template>
<a-layout-footer class="footer"> <a-layout-footer class="footer">
<a href="https://github.com/silenty4ng/k5web" target="_blank">K5Web - V0.1.202402022130</a> <a href="https://github.com/silenty4ng/k5web" target="_blank">K5Web - V0.1.202402021050</a>
</a-layout-footer> </a-layout-footer>
</template> </template>

View file

@ -30,56 +30,123 @@
</a-space> </a-space>
</a-col> </a-col>
</a-row> </a-row>
<t-table <a-table
:loading="loading" :loading="loading"
size="large"
:columns="columns" :columns="columns"
:data="cstate.renderData" :data="cstate.renderData"
style="margin-top: 20px"
:pagination="{ :pagination="{
defaultPageSize: cstate.pageSize, pageSize: cstate.pageSize,
total: cstate.renderData.length, current: cstate.nowPage,
defaultCurrent: 1, showPageSize: true,
pageSizeOptions: [15, 30, 50, 100, 200] pageSizeOptions: [15, 30, 50]
}" }"
@change="(e: any)=>{cstate.pageSize = e.pagination.pageSize, cstate.nowPage = e.pagination.current}" @page-change="(e)=>{cstate.nowPage = e;}"
bordered @page-size-change="(e)=>{cstate.pageSize = e;}"
lazy-load
> >
<template #index="{ row, rowIndex }"> <template #index="{ record, rowIndex }">
{{ (cstate.nowPage - 1) * cstate.pageSize + rowIndex + 1 }} {{(cstate.nowPage - 1) * cstate.pageSize + rowIndex + 1}}
</template> </template>
<template #reverse="{ row, rowIndex }"> <template #name="{ record, rowIndex }">
<t-switch v-model="row.reverse" /> <a-input v-model="record.name" />
</template> </template>
<template #busy="{ row, rowIndex }"> <template #bandwidth="{ record, rowIndex }">
<t-switch v-model="row.busy" /> <a-select v-model="record.bandwidth" allow-clear>
<a-option v-for="value of Object.keys(state.bandwidthOption)" :value="value">{{state.bandwidthOption[value]}}</a-option>
</a-select>
</template> </template>
<template #dtmf="{ row, rowIndex }"> <template #tx="{ record, rowIndex }">
<t-switch v-model="row.dtmf" /> <a-input-number v-model="record.tx" :precision="5" />
</template> </template>
<template #scanlist="{ row, rowIndex }"> <template #rx="{ record, rowIndex }">
<t-checkbox-group v-model="row.scanlist"> <a-input-number v-model="record.rx" :precision="5" />
<t-checkbox key="I" label="I" value="I" />
<t-checkbox key="II" label="II" value="II" />
</t-checkbox-group>
</template> </template>
<template #operate="{ row, rowIndex }"> <template #power="{ record, rowIndex }">
<t-button theme="default" variant="dashed" @click="clearRow((cstate.nowPage - 1) * cstate.pageSize + rowIndex)">清空</t-button> <a-select v-model="record.power" allow-clear>
<a-option v-for="value of Object.keys(state.powerOption)" :value="value">{{state.powerOption[value]}}</a-option>
</a-select>
</template> </template>
</t-table> <template #rxTone="{ record, rowIndex }">
<a-select v-model="record.rxTone" allow-clear>
<a-option v-for="value of Object.keys(state.toneOption)" :value="value">{{state.toneOption[value]}}</a-option>
</a-select>
</template>
<template #rxCTCSS="{ record, rowIndex }">
<a-select v-model="record.rxCTCSS" allow-clear>
<a-option v-for="value of state.CTCSSOption" :value="value">{{value.toFixed(1)}}</a-option>
</a-select>
</template>
<template #rxDCS="{ record, rowIndex }">
<a-select v-model="record.rxDCS" allow-clear>
<a-option v-for="value of state.DCSOption" :value="value">{{"0" + value}}</a-option>
</a-select>
</template>
<template #txTone="{ record, rowIndex }">
<a-select v-model="record.txTone" allow-clear>
<a-option v-for="value of Object.keys(state.toneOption)" :value="value">{{state.toneOption[value]}}</a-option>
</a-select>
</template>
<template #txCTCSS="{ record, rowIndex }">
<a-select v-model="record.txCTCSS" allow-clear>
<a-option v-for="value of state.CTCSSOption" :value="value">{{value.toFixed(1)}}</a-option>
</a-select>
</template>
<template #txDCS="{ record, rowIndex }">
<a-select v-model="record.txDCS" allow-clear>
<a-option v-for="value of state.DCSOption" :value="value">{{"0" + value}}</a-option>
</a-select>
</template>
<template #step="{ record, rowIndex }">
<a-select v-model="record.step" allow-clear>
<a-option v-for="value of state.stepOption" :value="value">{{value.toFixed(1)}}</a-option>
</a-select>
</template>
<template #reverse="{ record, rowIndex }">
<a-switch v-model="record.reverse" />
</template>
<template #scramb="{ record, rowIndex }">
<a-select v-model="record.scramb" allow-clear>
<a-option v-for="value of state.scrambOption">{{value}}</a-option>
</a-select>
</template>
<template #busy="{ record, rowIndex }">
<a-switch v-model="record.busy" />
</template>
<template #pttid="{ record, rowIndex }">
<a-select v-model="record.pttid" allow-clear>
<a-option v-for="value of state.pttidOption">{{value}}</a-option>
</a-select>
</template>
<template #mode="{ record, rowIndex }">
<a-select v-model="record.mode" allow-clear>
<a-option v-for="value of Object.keys(state.modeOption)" :value="value">{{state.modeOption[value]}}</a-option>
</a-select>
</template>
<template #dtmf="{ record, rowIndex }">
<a-switch v-model="record.dtmf" />
</template>
<template #scanlist="{ record, rowIndex }">
<a-checkbox-group v-model="record.scanlist">
<a-checkbox value="I">I</a-checkbox>
<a-checkbox value="II">II</a-checkbox>
</a-checkbox-group>
</template>
<template #operate="{ record, rowIndex }">
<a-button @click="clearRow((cstate.nowPage - 1) * cstate.pageSize + rowIndex)">清空</a-button>
</template>
</a-table>
</a-card> </a-card>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, reactive } from 'vue'; import { reactive } from 'vue';
import { Input, Select } from 'tdesign-vue-next';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import { eeprom_read, uint8ArrayToHexReverseString, uint8ArrayToString, hexReverseStringToUint8Array, stringToUint8Array, eeprom_write, eeprom_reboot, eeprom_init } from '@/utils/serial.js'; import { eeprom_read, uint8ArrayToHexReverseString, uint8ArrayToString, hexReverseStringToUint8Array, stringToUint8Array, eeprom_write, eeprom_reboot, eeprom_init } from '@/utils/serial.js';
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
const appStore = useAppStore(); const appStore = useAppStore();
const { loading, setLoading } = useLoading(false); const { loading, setLoading } = useLoading(true);
const state = { const state = {
bandwidthOption: {'0': '25KHz', '1': '12.5KHz'}, bandwidthOption: {'0': '25KHz', '1': '12.5KHz'},
modeOption: {'0': 'FM', '1': 'AM', '2': 'USB'}, modeOption: {'0': 'FM', '1': 'AM', '2': 'USB'},
@ -112,330 +179,144 @@
pageSize: number, pageSize: number,
nowPage: number nowPage: number
} = reactive({ } = reactive({
renderData: Array.from({length: 200}).map(e=>{return {}}), renderData: [],
pageSize: 15, pageSize: 15,
nowPage: 1, nowPage: 1,
}) })
const columns = computed(() => [ setTimeout(() => {
cstate.renderData = Array.from({length: 200}).map(e=>{return {}});
setLoading(false)
}, 1);
const columns = [
{ {
title: '#', title: '#',
colKey: 'index', dataIndex: 'index',
align: 'left', slotName: 'index',
width: 100 width: 70
}, },
{ {
title: '信道名称', title: '信道名称',
colKey: 'name', dataIndex: 'name',
width: 150, slotName: 'name',
align: 'left', width: 200
edit: {
component: Input,
props: {
clearable: true
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
},
},
}, },
{ {
title: '带宽', title: '带宽',
colKey: 'bandwidth', dataIndex: 'bandwidth',
align: 'left', slotName: 'bandwidth',
width: 150, width: 150
cell: (h, { row }) => state.bandwidthOption[row.bandwidth] ?? "",
edit: {
component: Select,
props: {
clearable: true,
options: Object.keys(state.bandwidthOption).map(e=>{return {value: e, label: state.bandwidthOption[e]}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '接收频率', title: '接收频率',
colKey: 'rx', dataIndex: 'rx',
align: 'left', slotName: 'rx',
width: 200, width: 150
cell: (h, { row }) => parseFloat(row.rx) ? parseFloat(row.rx).toFixed(5) : undefined,
edit: {
component: Input,
props: {
clearable: true
},
onEdited: (context: any) => {
context.newRowData.rx = context.newRowData.rx ? context.newRowData.rx : undefined
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
},
},
}, },
{ {
title: '发送频率', title: '发送频率',
colKey: 'tx', dataIndex: 'tx',
align: 'left', slotName: 'tx',
width: 200, width: 150
cell: (h, { row }) => parseFloat(row.tx) ? parseFloat(row.tx).toFixed(5) : undefined,
edit: {
component: Input,
props: {
clearable: true
},
onEdited: (context: any) => {
context.newRowData.tx = context.newRowData.tx ? context.newRowData.tx : undefined
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
},
},
}, },
{ {
title: '发送功率', title: '发送功率',
colKey: 'power', dataIndex: 'power',
align: 'left', slotName: 'power',
width: 150, width: 150
cell: (h, { row }) => state.powerOption[row.power] ?? "",
edit: {
component: Select,
props: {
clearable: true,
options: Object.keys(state.powerOption).map(e=>{return {value: e, label: state.powerOption[e]}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '接收亚音类型', title: '接收亚音类型',
colKey: 'rxTone', dataIndex: 'rxTone',
align: 'left', slotName: 'rxTone',
width: 180, width: 150
cell: (h, { row }) => state.toneOption[row.rxTone] ?? "",
edit: {
component: Select,
props: {
clearable: true,
options: Object.keys(state.toneOption).map(e=>{return {value: e, label: state.toneOption[e]}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '接收亚音频Hz', title: '接收亚音频Hz',
colKey: 'rxCTCSS', dataIndex: 'rxCTCSS',
align: 'left', slotName: 'rxCTCSS',
width: 150, width: 150
cell: (h, { row }) => state.CTCSSOption.indexOf(row.rxCTCSS) >= 0 ? row.rxCTCSS?.toFixed(1) : undefined,
edit: {
component: Select,
props: {
clearable: true,
options: state.CTCSSOption.map(e=>{return {value: e, label: e.toFixed(1)}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '接收亚音数码', title: '接收亚音数码',
colKey: 'rxDCS', dataIndex: 'rxDCS',
align: 'left', slotName: 'rxDCS',
width: 150, width: 150
cell: (h, { row }) => state.DCSOption.indexOf(row.rxDCS) >= 0 ? "0" + row.rxDCS : undefined,
edit: {
component: Select,
props: {
clearable: true,
options: state.DCSOption.map(e=>{return {value: e, label: "0" + e}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '发送亚音类型', title: '发送亚音类型',
colKey: 'txTone', dataIndex: 'txTone',
align: 'left', slotName: 'txTone',
width: 180, width: 150
cell: (h, { row }) => state.toneOption[row.txTone] ?? "",
edit: {
component: Select,
props: {
clearable: true,
options: Object.keys(state.toneOption).map(e=>{return {value: e, label: state.toneOption[e]}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '发送亚音频Hz', title: '发送亚音频Hz',
colKey: 'txCTCSS', dataIndex: 'txCTCSS',
align: 'left', slotName: 'txCTCSS',
width: 150, width: 150
cell: (h, { row }) => state.CTCSSOption.indexOf(row.txCTCSS) >= 0 ? row.txCTCSS?.toFixed(1) : undefined,
edit: {
component: Select,
props: {
clearable: true,
options: state.CTCSSOption.map(e=>{return {value: e, label: e.toFixed(1)}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '发送亚音数码', title: '发送亚音数码',
colKey: 'txDCS', dataIndex: 'txDCS',
align: 'left', slotName: 'txDCS',
width: 150, width: 150
cell: (h, { row }) => state.DCSOption.indexOf(row.txDCS) >= 0 ? "0" + row.txDCS : undefined,
edit: {
component: Select,
props: {
clearable: true,
options: state.DCSOption.map(e=>{return {value: e, label: "0" + e}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '频率步进', title: '频率步进',
colKey: 'step', dataIndex: 'step',
align: 'left', slotName: 'step',
width: 150, width: 150
cell: (h, { row }) => state.stepOption.indexOf(row.step) >= 0 ? row.step?.toFixed(1) : undefined,
edit: {
component: Select,
props: {
clearable: true,
options: state.stepOption.map(e=>{return {value: e, label: e.toFixed(1)}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '倒频', title: '倒频',
colKey: 'reverse', dataIndex: 'reverse',
align: 'left', slotName: 'reverse',
width: 150 width: 150
}, },
{ {
title: '加密', title: '加密',
colKey: 'scramb', dataIndex: 'scramb',
align: 'left', slotName: 'scramb',
width: 150, width: 150
edit: {
component: Select,
props: {
clearable: true,
options: state.scrambOption.map(e=>{return {value: e, label: e}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '繁忙禁发', title: '繁忙禁发',
colKey: 'busy', dataIndex: 'busy',
align: 'left', slotName: 'busy',
width: 150 width: 150
}, },
{ {
title: '信令码', title: '信令码',
colKey: 'pttid', dataIndex: 'pttid',
align: 'left', slotName: 'pttid',
width: 150, width: 150
edit: {
component: Select,
props: {
clearable: true,
options: state.pttidOption.map(e=>{return {value: e, label: e}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: '信道模式', title: '信道模式',
colKey: 'mode', dataIndex: 'mode',
align: 'left', slotName: 'mode',
width: 150, width: 150
cell: (h, { row }) => state.modeOption[row.mode] ?? "",
edit: {
component: Select,
props: {
clearable: true,
options: Object.keys(state.modeOption).map(e=>{return {value: e, label: state.modeOption[e]}}),
},
onEdited: (context: any) => {
const newData = [...cstate.renderData];
newData.splice(context.rowIndex, 1, context.newRowData);
cstate.renderData = newData;
}
},
}, },
{ {
title: 'DTMF解码', title: 'DTMF解码',
colKey: 'dtmf', dataIndex: 'dtmf',
align: 'left', slotName: 'dtmf',
width: 150 width: 150
}, },
{ {
title: '扫描列表', title: '扫描列表',
colKey: 'scanlist', dataIndex: 'scanlist',
align: 'left', slotName: 'scanlist',
width: 150 width: 150
}, },
{ {
title: '操作', title: '操作',
colKey: 'operate', dataIndex: 'operate',
align: 'left', slotName: 'operate',
width: 150 width: 150
} }
]); ];
const readChannel = async() => { const readChannel = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;}; if(appStore.connectState != true){alert('请先连接手台!'); return;};
@ -582,14 +463,14 @@
if(_channel.scanlist?.indexOf('I') >= 0) scanlist += 8; if(_channel.scanlist?.indexOf('I') >= 0) scanlist += 8;
if(_channel.scanlist?.indexOf('II') >= 0) scanlist += 4; if(_channel.scanlist?.indexOf('II') >= 0) scanlist += 4;
console.log((scanlist << 4) + 0) console.log((scanlist << 4) + 0)
rawEEPROM2.set([(scanlist << 4) + 0], i / 0x10) rawEEPROM2.set([(scanlist << 4) + 0], i >> 4)
const mergedArray = new Uint8Array(0x10); const mergedArray = new Uint8Array(0x10);
mergedArray.set(stringToUint8Array(_channel.name ?? "", appStore.configuration?.charset).subarray(0, 0x10), 0); mergedArray.set(stringToUint8Array(_channel.name ?? "", appStore.configuration?.charset).subarray(0, 0x10), 0);
rawEEPROM3.set(mergedArray, i) rawEEPROM3.set(mergedArray, i)
}else{ }else{
rawEEPROM.set(hexReverseStringToUint8Array("ffffffffffffffffffffffffffffffff"), i) rawEEPROM.set(hexReverseStringToUint8Array("ffffffffffffffffffffffffffffffff"), i)
rawEEPROM2.set([0xFF], i / 0x10) rawEEPROM2.set([0xFF], i >> 4)
rawEEPROM3.set(hexReverseStringToUint8Array("ffffffffffffffffffffffffffffffff"), i) rawEEPROM3.set(hexReverseStringToUint8Array("ffffffffffffffffffffffffffffffff"), i)
} }
i += 0x10 i += 0x10
@ -605,9 +486,7 @@
setLoading(false) setLoading(false)
} }
const clearRow = async (row: any) =>{ const clearRow = async (row: any) =>{
const newData = [...cstate.renderData]; cstate.renderData[row] = {}
newData.splice(row, 1, {});
cstate.renderData = newData;
} }
const saveChannel = () => { const saveChannel = () => {
const _data = JSON.stringify(cstate.renderData); const _data = JSON.stringify(cstate.renderData);