主要版本
parent
98fdd6a489
commit
cedf6b613d
|
@ -1,10 +0,0 @@
|
||||||
node_modules
|
|
||||||
.DS_Store
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
.vscode
|
|
||||||
.idea
|
|
||||||
|
|
||||||
public/Cesium
|
|
|
@ -1,29 +0,0 @@
|
||||||
# Vite Electron Typescript Template
|
|
||||||
|
|
||||||
`vite 2` `vue 3` `electron 12`
|
|
||||||
|
|
||||||
## How to use
|
|
||||||
clone the repo via git and install dependencies:
|
|
||||||
```shell
|
|
||||||
git clone --depth 1 --single-branch https://github.com/hocili/vite-electron-typescript-template.git your-project-name
|
|
||||||
cd your-project-name
|
|
||||||
yarn
|
|
||||||
```
|
|
||||||
|
|
||||||
## Starting Development
|
|
||||||
Start the app in the `dev` environment:
|
|
||||||
```shell
|
|
||||||
yarn dev
|
|
||||||
```
|
|
||||||
|
|
||||||
```shell
|
|
||||||
yarn electron:dev
|
|
||||||
```
|
|
||||||
## Packaging for Production
|
|
||||||
To package apps for the local platform:
|
|
||||||
```shell
|
|
||||||
yarn electron:build
|
|
||||||
```
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
1. 使用web serial api实现串口数据接收
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"serialport": {
|
|
||||||
"path": "COM3",
|
|
||||||
"baudRate": 115200
|
|
||||||
},
|
|
||||||
"extend_tdt_window": false
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html class="w-h-full">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>北斗卫星数据监测展示软件</title>
|
|
||||||
</head>
|
|
||||||
<body class="w-h-full">
|
|
||||||
<div id="app" class="w-h-full"></div>
|
|
||||||
<script type="module" src="/src/render/main.ts"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
require('ts-node').register({
|
|
||||||
project:'./tsconfig.electron.json'
|
|
||||||
});
|
|
||||||
require('./src/main/app.ts')
|
|
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"name": "beidou-satellite-data-monitor",
|
|
||||||
"description": "beidou-satellite-data-monitor",
|
|
||||||
"author": "hwasmart",
|
|
||||||
"version": "5.5.9",
|
|
||||||
"main": "dist/main/app.js",
|
|
||||||
"scripts": {
|
|
||||||
"install": "electron-rebuild",
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build",
|
|
||||||
"serve": "vite preview",
|
|
||||||
"electron:dev": "cross-env NODE_ENV=development electron index.js",
|
|
||||||
"electron:build": "rimraf dist && vite build && tsc -p tsconfig.electron.json && electron-builder"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cesium": "^1.88.0",
|
|
||||||
"echarts": "^5.1.0",
|
|
||||||
"electron-store": "^8.0.0",
|
|
||||||
"nmea": "http://git.hwasmart.com/bd_group/node-nmea.git",
|
|
||||||
"serialport": "10.0.0",
|
|
||||||
"vue": "^3.2.26",
|
|
||||||
"vue-cesium": "3.0.2-beta.13",
|
|
||||||
"vue-echarts": "^6.0.0-rc.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vitejs/plugin-vue": "^1.1.5",
|
|
||||||
"@vue/compiler-sfc": "^3.2.26",
|
|
||||||
"autoprefixer": "^10.2.5",
|
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"electron": "^13.6.3",
|
|
||||||
"electron-builder": "^22.10.5",
|
|
||||||
"electron-rebuild": "2.3.5",
|
|
||||||
"postcss": "^8.2.10",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
|
||||||
"tailwindcss": "^2.1.1",
|
|
||||||
"ts-node": "^9.1.1",
|
|
||||||
"typescript": "^4.2.3",
|
|
||||||
"vite": "^2.0.5"
|
|
||||||
},
|
|
||||||
"build": {
|
|
||||||
"appId": "hwasmart.id",
|
|
||||||
"directories": {
|
|
||||||
"output": "dist/release"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist/main/**/*",
|
|
||||||
"dist/render/**/*"
|
|
||||||
],
|
|
||||||
"mac": {
|
|
||||||
"category": "hwasmart.app.category.type"
|
|
||||||
},
|
|
||||||
"win": {
|
|
||||||
"icon": "public/favicon.ico"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 72 KiB |
|
@ -1,3 +0,0 @@
|
||||||
// 加密关键字
|
|
||||||
const keyword = 'BD'
|
|
||||||
export { keyword }
|
|
|
@ -1,103 +0,0 @@
|
||||||
import { parse, Helpers } from 'nmea'
|
|
||||||
|
|
||||||
let events = {}
|
|
||||||
const on = (eventName, callback) => {
|
|
||||||
if (!(eventName in events)) {
|
|
||||||
events[eventName] = []
|
|
||||||
}
|
|
||||||
|
|
||||||
events[eventName].push(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
const emit = (eventName, ...args) => {
|
|
||||||
if (!(eventName in events)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const cbs = events[eventName]
|
|
||||||
|
|
||||||
cbs.forEach(cb => {
|
|
||||||
cb.call(this, ...args)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const handle = (value) => {
|
|
||||||
if (value.length <= 0) return
|
|
||||||
|
|
||||||
emit('received', value)
|
|
||||||
nmeaObj = resetNMEAObj()
|
|
||||||
|
|
||||||
const strArr = value.split('\r\n')
|
|
||||||
for (let i = 0; i < strArr.length; i++) {
|
|
||||||
const element = strArr[i];
|
|
||||||
doHandle(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('handled', nmeaObj)
|
|
||||||
}
|
|
||||||
|
|
||||||
const doHandle = (value) => {
|
|
||||||
if (!verify(value)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = parse(value)
|
|
||||||
switch (result.sentence) {
|
|
||||||
case 'GGA':
|
|
||||||
nmeaObj.GGA = result
|
|
||||||
break;
|
|
||||||
case 'GLL':
|
|
||||||
nmeaObj.GLL = result
|
|
||||||
break;
|
|
||||||
case 'RMC':
|
|
||||||
nmeaObj.RMC = result
|
|
||||||
break;
|
|
||||||
case 'VTG':
|
|
||||||
nmeaObj.VTG = result
|
|
||||||
break;
|
|
||||||
case 'ZDA':
|
|
||||||
nmeaObj.ZDA = result
|
|
||||||
break;
|
|
||||||
case 'TXT':
|
|
||||||
nmeaObj.TXT = result
|
|
||||||
break;
|
|
||||||
case 'GSA':
|
|
||||||
nmeaObj.GSA.push(result)
|
|
||||||
break;
|
|
||||||
case 'GSV':
|
|
||||||
nmeaObj.GSV.push(result)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const verify = (value) => {
|
|
||||||
if (!value) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const dollar_index = value.indexOf('$')
|
|
||||||
const star_index = value.indexOf('*')
|
|
||||||
if (value.indexOf('$') !== 0 || star_index <= dollar_index) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const [sentence, checksum, ] = value.split('*')
|
|
||||||
return Helpers.verifyChecksum(sentence, checksum)
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetNMEAObj = () => {
|
|
||||||
return {
|
|
||||||
GGA: null,
|
|
||||||
GLL: null,
|
|
||||||
RMC: null,
|
|
||||||
VTG: null,
|
|
||||||
ZDA: null,
|
|
||||||
TXT: null,
|
|
||||||
GSA: [],
|
|
||||||
GSV: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let nmeaObj = resetNMEAObj()
|
|
||||||
|
|
||||||
export default { on, handle }
|
|
|
@ -1,208 +0,0 @@
|
||||||
import { app, screen, globalShortcut, BrowserWindow, ipcMain, dialog } from 'electron'
|
|
||||||
import { join } from "path"
|
|
||||||
import config from './config'
|
|
||||||
import './load-serialport'
|
|
||||||
import { keyword } from './KeyWord'
|
|
||||||
|
|
||||||
const child_process = require('child_process')
|
|
||||||
const crypto = require('crypto')
|
|
||||||
|
|
||||||
function queryPass(passPath: string, passValue: string) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
try {
|
|
||||||
child_process.exec(`reg query ${passPath} /v ${passValue}`, (error: Error, stdout: string, stderr: string) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resolve({stdout, stderr})
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function queryKey(keyPath: string, keyValue: string) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
try {
|
|
||||||
child_process.exec(`reg query ${keyPath} /v ${keyValue}`, (error: Error, stdout: string, stderr: string) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resolve({stdout, stderr})
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function cryptMD5(GUID: string) {
|
|
||||||
let md5 = crypto.createHash('md5')
|
|
||||||
let ciphertext = md5.update(GUID).digest('hex')
|
|
||||||
return ciphertext.slice(0,8)+'-'+ciphertext.slice(8,12)+'-'+ciphertext.slice(12,16)+'-'+ciphertext.slice(16,20)+'-'+ciphertext.slice(20,32)
|
|
||||||
}
|
|
||||||
|
|
||||||
const passPath = 'HKEY_CURRENT_USER\\SOFTWARE\\HwaSmart'
|
|
||||||
const passValue = 'BDAuthorization'
|
|
||||||
const keyPath = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography'
|
|
||||||
const keyValue = 'MachineGuid'
|
|
||||||
|
|
||||||
async function checkLaunchEnv() {
|
|
||||||
try {
|
|
||||||
const passResult: any = await queryPass(passPath, passValue)
|
|
||||||
const keyResult: any = await queryKey(keyPath, keyValue)
|
|
||||||
if(cryptMD5(keyResult.stdout.slice(83,119) + keyword) == passResult.stdout.slice(72,108)){
|
|
||||||
return true
|
|
||||||
}else{
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// 成功
|
|
||||||
// 查询到 有这个app启动项
|
|
||||||
} catch (error) {
|
|
||||||
// 没有查询到该app启动项目
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
// 异步代码
|
|
||||||
const checkReault: any = await checkLaunchEnv()
|
|
||||||
console.log('env right:', checkReault)
|
|
||||||
|
|
||||||
// 异步代码执行完毕后执行的代码
|
|
||||||
if (checkReault) {
|
|
||||||
const URl_REGEX = /[a-zA-z]+:\/\/[^\s]*/
|
|
||||||
const DEFAULT_OPTION = {
|
|
||||||
fullscreen: true,
|
|
||||||
frame: false,
|
|
||||||
webPreferences: {
|
|
||||||
nodeIntegration: true,
|
|
||||||
preload: join(__dirname, 'preload.js')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const launch = () => {
|
|
||||||
const extend_tdt_window = config.get('extend_tdt_window')
|
|
||||||
const displays = screen.getAllDisplays()
|
|
||||||
|
|
||||||
const { option, url } = getMonitorWindowArguments(displays[0])
|
|
||||||
createWindow(option, url)
|
|
||||||
|
|
||||||
if (extend_tdt_window) {
|
|
||||||
const { option, url } = getTDTWindowArguments(displays[displays.length - 1])
|
|
||||||
createWindow(option, url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getMonitorWindowArguments = (display: any) => {
|
|
||||||
const option = getOption(display)
|
|
||||||
const url = process.env.NODE_ENV === 'development' ? 'http://localhost:3000/' : 'dist/render/index.html'
|
|
||||||
|
|
||||||
return { option, url }
|
|
||||||
}
|
|
||||||
const getTDTWindowArguments = (display: any) => {
|
|
||||||
const option = getOption(display)
|
|
||||||
const url = 'http://gd.map.hwasmart.com/'
|
|
||||||
|
|
||||||
return { option, url }
|
|
||||||
}
|
|
||||||
|
|
||||||
const getOption = (display: any) => {
|
|
||||||
const origin = getDisplayOrigin(display)
|
|
||||||
const option = Object.assign({}, DEFAULT_OPTION, origin)
|
|
||||||
return option
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDisplayOrigin = (display: any) => {
|
|
||||||
const origin = !display ? {x: 0, y: 0} : {x: display.bounds.x, y: display.bounds.y}
|
|
||||||
return origin
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWindow(option: any, url: any) {
|
|
||||||
const win = new BrowserWindow(option)
|
|
||||||
|
|
||||||
if (URl_REGEX.test(url)) {
|
|
||||||
win.loadURL(url)
|
|
||||||
} else {
|
|
||||||
win.loadFile(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
const isWindows = process.platform === 'win32';
|
|
||||||
let needsFocusFix = false;
|
|
||||||
let triggeringProgrammaticBlur = false;
|
|
||||||
|
|
||||||
//弹出警报窗口后 input获取不到焦点
|
|
||||||
win.on('blur', (event: any) => {
|
|
||||||
if(!triggeringProgrammaticBlur) {
|
|
||||||
needsFocusFix = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
win.on('focus', (event: any) => {
|
|
||||||
if(isWindows && needsFocusFix) {
|
|
||||||
needsFocusFix = false;
|
|
||||||
triggeringProgrammaticBlur = true;
|
|
||||||
//弹出弹窗后重新聚焦导致windows任务栏显示,重新隐藏底部windows任务栏
|
|
||||||
win.minimize(); //最小化函数
|
|
||||||
win.restore(); //取消最小化函数(从最小化窗口还原函数)
|
|
||||||
setTimeout(function () {
|
|
||||||
win.blur(); //失去焦点函数
|
|
||||||
win.focus(); //获取焦点函数
|
|
||||||
setTimeout(function () {
|
|
||||||
triggeringProgrammaticBlur = false;
|
|
||||||
}, 100);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if(process.env.NODE_ENV === 'development') win.webContents.openDevTools()
|
|
||||||
|
|
||||||
ipcMain.on('CLOSE', (event) => {
|
|
||||||
const res = dialog.showMessageBox({
|
|
||||||
type: 'warning',
|
|
||||||
title: '警告',
|
|
||||||
message: '确定要关闭软件吗?',
|
|
||||||
detail: '关闭软件',
|
|
||||||
cancelId: 1, // 按esc默认点击索引按钮
|
|
||||||
defaultId: 0, // 默认高亮的按钮下标
|
|
||||||
buttons: ['确认', '取消'], // 按钮按索引从右往左排序
|
|
||||||
})
|
|
||||||
|
|
||||||
res.then((data)=>{
|
|
||||||
if(data.response == 0){
|
|
||||||
win.close()
|
|
||||||
}else{
|
|
||||||
console.log('not close software')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
launch()
|
|
||||||
|
|
||||||
// 屏蔽 F11 进入/退出全屏功能
|
|
||||||
globalShortcut.register('F11', () => {return})
|
|
||||||
})
|
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
app.quit()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.on('activate', () => {
|
|
||||||
if (BrowserWindow.getAllWindows().length === 0) {
|
|
||||||
launch()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
dialog.showErrorBox('系统提示', '软件启动出错,请联系售后技术支持人员')
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
|
@ -1,8 +0,0 @@
|
||||||
import Store from 'electron-store'
|
|
||||||
|
|
||||||
const store = new Store()
|
|
||||||
const set = (key, val) => store.set(key, val)
|
|
||||||
|
|
||||||
const get = (key) => store.get(key)
|
|
||||||
|
|
||||||
export default {set, get}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { ipcMain } from 'electron'
|
|
||||||
|
|
||||||
const senders = []
|
|
||||||
ipcMain.on("APP_MOUNTED", (event) => {
|
|
||||||
const { sender } = event
|
|
||||||
senders.push(sender)
|
|
||||||
|
|
||||||
sender.once('destroyed', () => {
|
|
||||||
const index = senders.indexOf(sender)
|
|
||||||
if (index >= 0) senders.splice(index, 1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const sendMsg = (channel, msg) => {
|
|
||||||
if (senders.length <= 0) return
|
|
||||||
|
|
||||||
try {
|
|
||||||
senders.forEach((sender) => {
|
|
||||||
sender.send(channel, msg)
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default sendMsg
|
|
|
@ -1,51 +0,0 @@
|
||||||
import SerialPort from 'serialport'
|
|
||||||
import InterByteTimeout from '@serialport/parser-inter-byte-timeout'
|
|
||||||
import config from './config'
|
|
||||||
import sendMsg from './ipcRendererManager'
|
|
||||||
import NMEAHandler from './api/NMEAHandler'
|
|
||||||
|
|
||||||
const DEFAULT_BAUDRATE = 115200
|
|
||||||
const getSerialPortConstructorArguments = (ports) => {
|
|
||||||
// 很多电脑自带COM1接口,过滤掉COM1口
|
|
||||||
ports = ports.filter((port) => port.path != 'COM1')
|
|
||||||
if (ports.length == 0) return
|
|
||||||
|
|
||||||
// console.log(ports, '=====================')
|
|
||||||
const serialport = config.get('serialport')
|
|
||||||
const path = ( serialport && serialport.path ) ? serialport.path : ports[0].path
|
|
||||||
const baudRate = ( serialport && serialport.baudRate ) ? serialport.baudRate : DEFAULT_BAUDRATE
|
|
||||||
return { path, baudRate }
|
|
||||||
}
|
|
||||||
|
|
||||||
const openSerialport = (ports) => {
|
|
||||||
try {
|
|
||||||
const constructorArguments = getSerialPortConstructorArguments(ports)
|
|
||||||
if (!constructorArguments) {
|
|
||||||
console.error('设备未连接')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { path, baudRate } = constructorArguments
|
|
||||||
|
|
||||||
// console.log(path, baudRate, '++++++++++++++===');
|
|
||||||
const serialPort = new SerialPort(path, { baudRate })
|
|
||||||
const parser = serialPort.pipe(new InterByteTimeout({interval: 300}))
|
|
||||||
|
|
||||||
NMEAHandler.on('received' , (nmeaStr) => {
|
|
||||||
sendMsg('NMEA_RECEIVED', nmeaStr)
|
|
||||||
})
|
|
||||||
|
|
||||||
NMEAHandler.on('handled' , (nmeaObj) => {
|
|
||||||
sendMsg('NMEA_HANDLED', JSON.stringify(nmeaObj))
|
|
||||||
})
|
|
||||||
|
|
||||||
parser.on('data', (data) => NMEAHandler.handle(data.toString()))
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SerialPort.list().then(
|
|
||||||
ports => openSerialport(ports),
|
|
||||||
err => console.error(err)
|
|
||||||
)
|
|
|
@ -1,20 +0,0 @@
|
||||||
const { ipcRenderer, contextBridge } = require('electron')
|
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('ipcRenderer', {
|
|
||||||
send: (channel, data) => {
|
|
||||||
// whitelist channels
|
|
||||||
let validChannels = ['toMain']
|
|
||||||
if (validChannels.includes(channel)) {
|
|
||||||
ipcRenderer.send(channel, data)
|
|
||||||
}
|
|
||||||
ipcRenderer.send(channel, data)
|
|
||||||
},
|
|
||||||
receive: (channel, func) => {
|
|
||||||
let validChannels = ['fromMain']
|
|
||||||
if (validChannels.includes(channel)) {
|
|
||||||
// Deliberately strip event as it includes `sender`
|
|
||||||
ipcRenderer.on(channel, (event, ...args) => func(...args))
|
|
||||||
}
|
|
||||||
ipcRenderer.on(channel, (event, ...args) => func(...args))
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -1,60 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="w-h-full fixed">
|
|
||||||
<EarthView ref="earthViewInstance" />
|
|
||||||
</div>
|
|
||||||
<div class="w-h-full fixed grid grid-cols-2 p-10 front-container">
|
|
||||||
<div class="text-left">
|
|
||||||
<SNRView ref="snrViewInstance" />
|
|
||||||
</div>
|
|
||||||
<div class="text-center w-1/2 ml-auto">
|
|
||||||
<PlanisphereView ref="planisphereViewInstance" />
|
|
||||||
</div>
|
|
||||||
<div class="text-left">
|
|
||||||
<NMEAView ref="nmeaViewInstance" />
|
|
||||||
</div>
|
|
||||||
<div class="text-center w-1/2 ml-auto">
|
|
||||||
<BaseInfoView ref="baseInfoViewInstance" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, onMounted } from 'vue'
|
|
||||||
import SNRView from './components/SNRView.vue'
|
|
||||||
import NMEAView from './components/NMEAView.vue'
|
|
||||||
import EarthView from './components/EarthView.vue'
|
|
||||||
import BaseInfoView from './components/BaseInfoView.vue'
|
|
||||||
import PlanisphereView from './components/PlanisphereView.vue'
|
|
||||||
|
|
||||||
|
|
||||||
const nmeaViewInstance = ref(null)
|
|
||||||
const snrViewInstance = ref(null)
|
|
||||||
const earthViewInstance = ref(null)
|
|
||||||
const baseInfoViewInstance = ref(null)
|
|
||||||
const planisphereViewInstance = ref(null)
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if ('ipcRenderer' in window) {
|
|
||||||
ipcRenderer.receive('NMEA_RECEIVED', nmeaViewInstance.value.update)
|
|
||||||
|
|
||||||
ipcRenderer.receive('NMEA_HANDLED' , (nmeaStr: string) => {
|
|
||||||
const nmea = JSON.parse(nmeaStr)
|
|
||||||
|
|
||||||
snrViewInstance.value.update(nmea)
|
|
||||||
earthViewInstance.value.update(nmea)
|
|
||||||
baseInfoViewInstance.value.update(nmea)
|
|
||||||
planisphereViewInstance.value.update(nmea)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcRenderer.send('APP_MOUNTED')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.front-container {
|
|
||||||
grid-template-rows: 55vh;
|
|
||||||
background: linear-gradient(to right, rgba(17, 24, 39, 0.8) , transparent, rgba(17, 24, 39, 0.8));
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,113 +0,0 @@
|
||||||
import { Helpers } from 'nmea'
|
|
||||||
|
|
||||||
const getPosition = (nmea) => {
|
|
||||||
if (!nmea) return
|
|
||||||
|
|
||||||
const { RMC } = nmea
|
|
||||||
const position = { lng: Helpers.parseLongitude(RMC.lon, RMC.lonPole), lat: Helpers.parseLatitude(RMC.lat, RMC.latPole) }
|
|
||||||
|
|
||||||
return position
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBaseInfo = (nmea) => {
|
|
||||||
if (!nmea) return
|
|
||||||
|
|
||||||
const { RMC, GGA } = nmea
|
|
||||||
try {
|
|
||||||
const longitude = (!RMC.lon || !RMC.lonPole) ? '' : Helpers.parseLongitude(RMC.lon, RMC.lonPole)
|
|
||||||
const latitude = (!RMC.lat || !RMC.latPole) ? '' : Helpers.parseLatitude(RMC.lat, RMC.latPole)
|
|
||||||
const altitude = GGA.alt + GGA.altUnit
|
|
||||||
const date = (!RMC.date) ? '' : '20' + RMC.date.slice(4, 6) + '-' + RMC.date.slice(2, 4) + '-' + RMC.date.slice(0, 2)
|
|
||||||
let UTCTime = '', BJTime = ''
|
|
||||||
if (RMC.timestamp) {
|
|
||||||
const hour = parseInt(RMC.timestamp.slice(0, 2))
|
|
||||||
const bjHour = (hour + 8) % 24
|
|
||||||
UTCTime = hour.toString().padStart(2, '0') + ':' + RMC.timestamp.slice(2, 4) + ':' + RMC.timestamp.slice(4, 6)
|
|
||||||
BJTime = bjHour.toString().padStart(2, '0') + ':' + RMC.timestamp.slice(2, 4) + ':' + RMC.timestamp.slice(4, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseInfo = { longitude, latitude, altitude, date, UTCTime, BJTime }
|
|
||||||
return baseInfo
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSNROption = (nmea) => {
|
|
||||||
if (!nmea) return
|
|
||||||
|
|
||||||
const { GSV, GSA } = nmea
|
|
||||||
const GSVArr = GSV.filter((gsv) => gsv.talker_id === 'BD')
|
|
||||||
const GSAArr = GSA.filter((gsa) => gsa.talker_id === 'BD')
|
|
||||||
|
|
||||||
try {
|
|
||||||
let yAxis_data = [], series_data = []
|
|
||||||
const in_positioning_id = get_in_positioning_id(GSAArr)
|
|
||||||
|
|
||||||
GSVArr.forEach(({ satellites }) => {
|
|
||||||
satellites.forEach(({ id, SNRdB }) => {
|
|
||||||
yAxis_data.push(id)
|
|
||||||
if (in_positioning_id.indexOf(parseInt(id)) < 0) {
|
|
||||||
series_data.push([SNRdB, id, false])
|
|
||||||
} else {
|
|
||||||
series_data.push([SNRdB, id, true])
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const SNROption = {
|
|
||||||
yAxis: {
|
|
||||||
data: yAxis_data
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
data: series_data
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
return SNROption
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPlanisphereOption = (nmea) => {
|
|
||||||
if (!nmea) return
|
|
||||||
|
|
||||||
const { GSV, GSA } = nmea
|
|
||||||
const GSVArr = GSV.filter((gsv) => gsv.talker_id === 'BD')
|
|
||||||
const GSAArr = GSA.filter((gsa) => gsa.talker_id === 'BD')
|
|
||||||
|
|
||||||
try {
|
|
||||||
let data = []
|
|
||||||
const in_positioning_id = get_in_positioning_id(GSAArr)
|
|
||||||
|
|
||||||
GSVArr.forEach(({ satellites }) => {
|
|
||||||
satellites.forEach(({ id, elevationDeg, azimuthTrue }) => {
|
|
||||||
if (in_positioning_id.indexOf(parseInt(id)) < 0) {
|
|
||||||
data.push([parseInt(elevationDeg), azimuthTrue, id, false])
|
|
||||||
} else {
|
|
||||||
data.push([parseInt(elevationDeg), azimuthTrue, id, true])
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const planisphereOption = {
|
|
||||||
series: [{ data }]
|
|
||||||
}
|
|
||||||
|
|
||||||
return planisphereOption
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const get_in_positioning_id = (GSAArr) => {
|
|
||||||
let in_positioning_id = []
|
|
||||||
GSAArr.forEach(({ satellites }) => {
|
|
||||||
in_positioning_id.push(...satellites)
|
|
||||||
});
|
|
||||||
|
|
||||||
return in_positioning_id
|
|
||||||
}
|
|
||||||
|
|
||||||
export { getPosition, getBaseInfo, getSNROption, getPlanisphereOption }
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
|
@ -1,107 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<SubTitleView :title="'基础信息'" />
|
|
||||||
<div class="text-center text-2xl leading-loose text-blue-100">
|
|
||||||
<div>
|
|
||||||
<div class="label">经 度:</div>
|
|
||||||
<div class="content">{{ baseInfo.longitude ? baseInfo.longitude : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">经度度分:</div>
|
|
||||||
<div class="content">{{ baseInfo.longitude ? longitudeD + ' ' + longitudeM : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">经度分秒:</div>
|
|
||||||
<div class="content">{{ baseInfo.longitude ? longitudeD + ' ' + longitudeM + ' ' + longitudeS : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">纬 度:</div>
|
|
||||||
<div class="content">{{ baseInfo.latitude ? baseInfo.latitude : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">纬度度分:</div>
|
|
||||||
<div class="content">{{ baseInfo.latitude ? latitudeD + ' ' + latitudeM : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">纬度分秒:</div>
|
|
||||||
<div class="content">{{ baseInfo.latitude ? latitudeD + ' ' + latitudeM + ' ' + latitudeS : '' }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">海 拔:</div>
|
|
||||||
<div class="content">{{ baseInfo.altitude }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">日 期:</div>
|
|
||||||
<div class="content">{{ baseInfo.date }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">UTC时间:</div>
|
|
||||||
<div class="content">{{ baseInfo.UTCTime }}</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="label">北京时间:</div>
|
|
||||||
<div class="content">{{ baseInfo.BJTime }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { reactive, ref } from 'vue'
|
|
||||||
import SubTitleView from './SubTitleView.vue'
|
|
||||||
import { getBaseInfo } from '../api/util'
|
|
||||||
|
|
||||||
|
|
||||||
let baseInfo = reactive({
|
|
||||||
longitude : '',
|
|
||||||
latitude : '',
|
|
||||||
altitude : '',
|
|
||||||
date : '',
|
|
||||||
UTCTime : '',
|
|
||||||
BJTime : '',
|
|
||||||
})
|
|
||||||
|
|
||||||
let longitudeD = ref()
|
|
||||||
let longitudeM = ref()
|
|
||||||
let longitudeS = ref()
|
|
||||||
|
|
||||||
let latitudeD = ref()
|
|
||||||
let latitudeM = ref()
|
|
||||||
let latitudeS = ref()
|
|
||||||
|
|
||||||
const update = (nmea) => {
|
|
||||||
const newBaseInfo = getBaseInfo(nmea)
|
|
||||||
if (!newBaseInfo) return
|
|
||||||
|
|
||||||
Object.assign(baseInfo, newBaseInfo)
|
|
||||||
|
|
||||||
longitudeD.value = baseInfo.longitude.substring(0,baseInfo.longitude.indexOf("."))+'°'
|
|
||||||
longitudeM.value = String((Number('0.'+baseInfo.longitude.substring(baseInfo.longitude.indexOf(".")+1,baseInfo.longitude.length))*60).toFixed(10)).substring(0,String((Number('0.'+baseInfo.longitude.substring(baseInfo.longitude.indexOf(".")+1,baseInfo.longitude.length))*60).toFixed(10)).indexOf("."))+'′'
|
|
||||||
longitudeS.value = (Number('0.'+(Number('0.'+baseInfo.longitude.substring(baseInfo.longitude.indexOf(".")+1,baseInfo.longitude.length))*60).toFixed(10).substring(String((Number('0.'+baseInfo.longitude.substring(baseInfo.longitude.indexOf(".")+1,baseInfo.longitude.length))*60).toFixed(10)).indexOf(".")+1,((Number('0.'+baseInfo.longitude.substring(baseInfo.longitude.indexOf(".")+1,baseInfo.longitude.length))*60).toFixed(10)).length))*60).toFixed(6)+'″'
|
|
||||||
|
|
||||||
latitudeD.value = baseInfo.latitude.substring(0,baseInfo.latitude.indexOf("."))+'°'
|
|
||||||
latitudeM.value = String((Number('0.'+baseInfo.latitude.substring(baseInfo.latitude.indexOf(".")+1,baseInfo.latitude.length))*60).toFixed(10)).substring(0,String((Number('0.'+baseInfo.latitude.substring(baseInfo.latitude.indexOf(".")+1,baseInfo.latitude.length))*60).toFixed(10)).indexOf("."))+'′'
|
|
||||||
latitudeS.value = (Number('0.'+(Number('0.'+baseInfo.latitude.substring(baseInfo.latitude.indexOf(".")+1,baseInfo.latitude.length))*60).toFixed(10).substring(String((Number('0.'+baseInfo.latitude.substring(baseInfo.latitude.indexOf(".")+1,baseInfo.latitude.length))*60).toFixed(10)).indexOf(".")+1,((Number('0.'+baseInfo.latitude.substring(baseInfo.latitude.indexOf(".")+1,baseInfo.latitude.length))*60).toFixed(10)).length))*60).toFixed(6)+'″'
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ update })
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
@layer components {
|
|
||||||
.label {
|
|
||||||
@apply float-left text-right w-2/5;
|
|
||||||
min-width: 120px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer components {
|
|
||||||
.content {
|
|
||||||
@apply float-left text-left w-3/5;
|
|
||||||
min-width: 165px;
|
|
||||||
height: 36px;
|
|
||||||
/* min-height: 48px; */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,58 +0,0 @@
|
||||||
<template>
|
|
||||||
<vc-viewer :shouldAnimate="true" :showCredit="false" :infoBox="false" @ready="onViewerReady">
|
|
||||||
<vc-layer-imagery>
|
|
||||||
<vc-provider-imagery-singletile :url="earth" />
|
|
||||||
</vc-layer-imagery>
|
|
||||||
|
|
||||||
<vc-entity :show="show" :position="position">
|
|
||||||
<vc-graphics-billboard :image="pin" :verticalOrigin="1" />
|
|
||||||
</vc-entity>
|
|
||||||
</vc-viewer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { reactive, computed } from 'vue'
|
|
||||||
import { getPosition } from '../api/util'
|
|
||||||
import pin from '../assets/pin.png'
|
|
||||||
import earth from '../assets/earth.jpg'
|
|
||||||
|
|
||||||
const position = reactive({ lng: NaN, lat: NaN })
|
|
||||||
const show = computed(() => {
|
|
||||||
const { lng, lat } = position
|
|
||||||
|
|
||||||
if (isNaN(lng) || lng > 180 || lng < -180) return false
|
|
||||||
if (isNaN(lat) || lat > 90 || lat < -90 ) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
// 设置地球自转动画效果
|
|
||||||
const onViewerReady = ({ Cesium, viewer }) => {
|
|
||||||
const { JulianDate, Cartesian3 } = Cesium
|
|
||||||
const { clock, scene } = viewer
|
|
||||||
|
|
||||||
let prev = clock.currentTime
|
|
||||||
clock.onTick.addEventListener(() => {
|
|
||||||
const current = clock.currentTime
|
|
||||||
|
|
||||||
const interval = JulianDate.toDate(current) - JulianDate.toDate(prev)
|
|
||||||
prev = current
|
|
||||||
|
|
||||||
scene.camera.rotate(
|
|
||||||
Cartesian3.UNIT_Z,
|
|
||||||
(Math.PI / (24 * 60 * 60)) * interval * 1,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const update = (nmea) => {
|
|
||||||
const newPosition = getPosition(nmea)
|
|
||||||
if (!newPosition) return
|
|
||||||
|
|
||||||
Object.assign(position, newPosition)
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ update })
|
|
||||||
</script>
|
|
|
@ -1,20 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<SubTitleView :title="'NMEA'" />
|
|
||||||
|
|
||||||
<div ref="nmeaContainer" class="whitespace-pre-line text-blue-100 text-sm">
|
|
||||||
{{ nmeaStr }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import SubTitleView from './SubTitleView.vue'
|
|
||||||
|
|
||||||
const nmeaStr = ref('')
|
|
||||||
const update = (value) => nmeaStr.value = value
|
|
||||||
|
|
||||||
defineExpose({ update })
|
|
||||||
</script>
|
|
|
@ -1,86 +0,0 @@
|
||||||
<template>
|
|
||||||
<SubTitleView :title="'星位视图'" />
|
|
||||||
<div @dblclick="close" class="h-4/5">
|
|
||||||
<v-chart :option="option" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { use } from "echarts/core";
|
|
||||||
import { CanvasRenderer } from "echarts/renderers";
|
|
||||||
import { ScatterChart } from "echarts/charts";
|
|
||||||
import { PolarComponent } from "echarts/components";
|
|
||||||
import VChart from "vue-echarts";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import SubTitleView from './SubTitleView.vue'
|
|
||||||
import { getPlanisphereOption } from '../api/util'
|
|
||||||
|
|
||||||
use([
|
|
||||||
CanvasRenderer,
|
|
||||||
ScatterChart,
|
|
||||||
PolarComponent
|
|
||||||
]);
|
|
||||||
|
|
||||||
const LOCATED_COLOR = '#e5323e'
|
|
||||||
const UNLOCATED_COLOR = '#9ca3af'
|
|
||||||
|
|
||||||
|
|
||||||
const option = reactive({
|
|
||||||
polar: {},
|
|
||||||
radiusAxis: {
|
|
||||||
inverse: true,
|
|
||||||
min: 0,
|
|
||||||
max: 90,
|
|
||||||
axisLabel: {
|
|
||||||
rotate: -25,
|
|
||||||
showMinLabel: false,
|
|
||||||
showMaxLabel: false,
|
|
||||||
verticalAlign: 'bottom'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
angleAxis: {
|
|
||||||
type: 'value',
|
|
||||||
min: 0,
|
|
||||||
max: 360,
|
|
||||||
axisTick: {show: false},
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value) {
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case 0 : return 'N';
|
|
||||||
case 90 : return 'E';
|
|
||||||
case 180 : return 'S';
|
|
||||||
case 270 : return 'W';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
coordinateSystem: 'polar',
|
|
||||||
type: 'scatter',
|
|
||||||
symbolSize: 32,
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
formatter: '{@[2]}'
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
color: ({ value }) => {
|
|
||||||
return value[3] ? LOCATED_COLOR : UNLOCATED_COLOR
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
|
|
||||||
const update = (nmea) => {
|
|
||||||
const newOption = getPlanisphereOption(nmea)
|
|
||||||
if (!newOption) return
|
|
||||||
|
|
||||||
Object.assign(option, newOption)
|
|
||||||
}
|
|
||||||
|
|
||||||
const close = () => {
|
|
||||||
window.ipcRenderer.send('CLOSE')
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ update })
|
|
||||||
</script>
|
|
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<SubTitleView :title="'载噪比'" />
|
|
||||||
<div class="w-2/3 h-4/5">
|
|
||||||
<v-chart :option="option" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { use, graphic } from "echarts/core";
|
|
||||||
import { CanvasRenderer } from "echarts/renderers";
|
|
||||||
import { BarChart } from "echarts/charts";
|
|
||||||
import VChart from "vue-echarts";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import SubTitleView from './SubTitleView.vue'
|
|
||||||
import { getSNROption } from '../api/util'
|
|
||||||
|
|
||||||
use([
|
|
||||||
CanvasRenderer,
|
|
||||||
BarChart
|
|
||||||
]);
|
|
||||||
|
|
||||||
const LOCATED_COLOR = new graphic.LinearGradient(
|
|
||||||
0, 0, 1, 0,
|
|
||||||
[
|
|
||||||
{offset: 0.3, color: '#83bff6'},
|
|
||||||
{offset: 1, color: '#188df0'}
|
|
||||||
]
|
|
||||||
)
|
|
||||||
const UNLOCATED_COLOR = '#9ca3af'
|
|
||||||
|
|
||||||
const option = reactive({
|
|
||||||
grid: {
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
show: false,
|
|
||||||
type: 'value',
|
|
||||||
min: 0,
|
|
||||||
max: 60,
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'category',
|
|
||||||
inverse: true,
|
|
||||||
axisLine: {show: false},
|
|
||||||
axisTick: {show: false},
|
|
||||||
axisLabel: {color: 'white'}
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
type: 'bar',
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'insideRight',
|
|
||||||
formatter: function ({ value }) {
|
|
||||||
return value[0] <= 5 ? '' : value[0];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
color: ({ value }) => {
|
|
||||||
return value[2] ? LOCATED_COLOR : UNLOCATED_COLOR
|
|
||||||
}
|
|
||||||
},
|
|
||||||
barMaxWidth: 24
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
|
|
||||||
const update = (nmea) => {
|
|
||||||
const newOption = getSNROption(nmea)
|
|
||||||
if (!newOption) return
|
|
||||||
|
|
||||||
Object.assign(option, newOption)
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ update })
|
|
||||||
</script>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<template>
|
|
||||||
<h1 class="text-4xl text-yellow-50 mb-5"> {{ title }} </h1>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
defineProps({
|
|
||||||
title: String
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -1,9 +0,0 @@
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
@layer components {
|
|
||||||
.w-h-full {
|
|
||||||
@apply w-full h-full m-0 p-0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { createApp } from 'vue'
|
|
||||||
import App from './App.vue'
|
|
||||||
|
|
||||||
import 'vue-cesium/dist/index.css'
|
|
||||||
import { VcViewer, VcEntity, VcLayerImagery, VcProviderImagerySingletile, VcGraphicsBillboard } from 'vue-cesium'
|
|
||||||
|
|
||||||
import './main.css'
|
|
||||||
|
|
||||||
const cesiumPath = (process.env.NODE_ENV === 'development' ? './node_modules/cesium/Build/Cesium/Cesium.js': './Cesium/Cesium.js')
|
|
||||||
|
|
||||||
const app = createApp(App)
|
|
||||||
// 局部引入VueCesium
|
|
||||||
app.use(VcViewer).use(VcEntity).use(VcLayerImagery).use(VcProviderImagerySingletile).use(VcGraphicsBillboard)
|
|
||||||
app.config.globalProperties.$VueCesium = { cesiumPath }
|
|
||||||
app.mount('#app')
|
|
|
@ -1,5 +0,0 @@
|
||||||
declare module '*.vue' {
|
|
||||||
import { DefineComponent } from 'vue'
|
|
||||||
const component: DefineComponent<{}, {}, any>
|
|
||||||
export default component
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
|
||||||
darkMode: false, // or 'media' or 'class'
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "CommonJS",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"strict": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowJs": true,
|
|
||||||
"outDir": "dist/main"
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/main/app.ts",
|
|
||||||
"src/main/preload.js",
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"strict": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"sourceMap": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"lib": ["esnext", "dom"],
|
|
||||||
"types": ["vite/client"],
|
|
||||||
// ---------------------- //
|
|
||||||
"noImplicitAny": false
|
|
||||||
},
|
|
||||||
"include": ["src/render/**/*.ts", "src/render/**/*.d.ts", "src/render/**/*.tsx", "src/render/**/*.vue"],
|
|
||||||
"exclude": ["src/app.ts"]
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { join } from 'path'
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
import copy from 'rollup-plugin-copy'
|
|
||||||
|
|
||||||
const outDir = join(__dirname, 'dist/render')
|
|
||||||
const renderDir = join(__dirname, 'src/render')
|
|
||||||
const publicDir = join(__dirname, 'public')
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
publicDir,
|
|
||||||
base: './',
|
|
||||||
plugins: [vue(),copy({
|
|
||||||
targets: [
|
|
||||||
{ src: './node_modules/cesium/Build/Cesium', dest: publicDir }, //编译时,执行Cesium库的拷贝
|
|
||||||
]
|
|
||||||
})],
|
|
||||||
build: {
|
|
||||||
outDir,
|
|
||||||
emptyOutDir: true,
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': renderDir,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue