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>
<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>
</template>

View file

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