【类 型】:feat

【原  因】:地图组件 地图源地址选择 改为从数据库获取
【过  程】:
【影  响】:

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
This commit is contained in:
air 2025-06-21 11:39:44 +08:00
parent 8598cb98dc
commit 024e79c80c
5 changed files with 63 additions and 292 deletions

View File

@ -24,117 +24,7 @@ export default {
isflow: false, // isflow: false, //
currentStyleIndex: 0, // currentStyleIndex: 0, //
guidedMarker: null, // guidedMarker: null, //
// mapStyles: this.$store.state.mapStyleList//
mapStyles: [
// mapbox
{
name: '谷歌卫星',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
google: {
type: 'raster',
tileSize: 256,
tiles: ['https://sb.im/google-maps/vt?lyrs=s&x={x}&y={y}&z={z}']
}
},
layers: [{ id: 'GoogleRasterLayer', type: 'raster', source: 'google' }]
},
{
name: '必应卫星',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
bing: {
type: 'raster',
tileSize: 256,
tiles: [
'https://ecn.t3.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=1'
],
attribution: '© Microsoft, Bing Maps'
}
},
layers: [{ id: 'BingRasterLayer', type: 'raster', source: 'bing' }]
},
{
name: 'Mapbox Streets',
sprite: 'mapbox://sprites/mapbox/streets-v11',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
mapbox: {
type: 'raster',
tileSize: 256,
tiles: ['https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=YOUR_MAPBOX_ACCESS_TOKEN']
}
},
layers: [{ id: 'MapboxStreetsLayer', type: 'raster', source: 'mapbox' }]
},
{
name: 'Google Maps',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
google: {
type: 'raster',
tileSize: 256,
tiles: ['https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}']
}
},
layers: [{ id: 'GoogleMapsLayer', type: 'raster', source: 'google' }]
},
{
name: 'OpenStreetMap',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
osm: {
type: 'raster',
tileSize: 256,
tiles: ['https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png']
}
},
layers: [{ id: 'OSMRasterLayer', type: 'raster', source: 'osm' }]
},
//
{
name: '高德矢量',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
gaode: {
type: 'raster',
tileSize: 256, // 256 512
tiles: [
'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
]
}
},
layers: [{ id: 'GaodeVectorLayer', type: 'raster', source: 'gaode' }]
},
//
{
name: '高德卫星',
sprite: this.$store.state.settings.host + '/Public/map/sprite',
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
gaode: {
type: 'raster',
tileSize: 256, // 256 512
tiles: [
'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
]
}
},
layers: [{ id: 'GaodeRasterLayer', type: 'raster', source: 'gaode' }]
}
]
} }
}, },
props: { props: {
@ -204,7 +94,7 @@ export default {
color: 'white', color: 'white',
'horizon-blend': 0.01 'horizon-blend': 0.01
}) })
// 线 // // 线
// this.map.addSource('contours', { // this.map.addSource('contours', {
// type: 'vector', // type: 'vector',
// url: 'mapbox://mapbox.mapbox-terrain-v2' // url: 'mapbox://mapbox.mapbox-terrain-v2'
@ -223,7 +113,7 @@ export default {
// 'line-width': 1 // 线 // 'line-width': 1 // 线
// } // }
// }) // })
// 3D // // 3D
// this.map.addSource('mapbox-dem', { // this.map.addSource('mapbox-dem', {
// type: 'raster-dem', // type: 'raster-dem',
// url: 'mapbox://mapbox.mapbox-terrain-dem-v1', // url: 'mapbox://mapbox.mapbox-terrain-dem-v1',

View File

@ -1,72 +1,12 @@
<template> <template>
<div class="mainBox flex column no-select"> <div class="mainBox flex column no-select">
<!-- 心跳 --> <!-- 心跳 -->
<div class="flex"> <!-- <div class="flex">
<div class="tag flex mac mc iconfont" <div class="tag flex mac mc iconfont"
:class="online ? heartAnimation ? 'icon-heart online' : 'icon-heart1 online' : 'icon-xinsui offline'"> :class="online ? heartAnimation ? 'icon-heart online' : 'icon-heart1 online' : 'icon-xinsui offline'">
</div> </div>
</div> </div> -->
<!-- 锁定状态 -->
<div class="flex">
<div class="tag flex mac mc iconfont" :class="isLockState ? 'icon-suoding' : 'icon-jiesuo'">
</div>
</div>
<!-- 飞机模式 -->
<div class="flex">
<div v-if="getPlaneMode" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ getPlaneMode }}</font>
</div>
<div class="tag flex mac mc iconfont icon-moshixuanze">
</div>
</div>
<!-- 卫星 -->
<div class="flex">
<div v-if="satCount" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ fixType }} {{ satCount }}</font>
</div>
<div class="tag flex mac mc iconfont icon-weixing">
</div>
</div>
<!-- 电池电压 -->
<div class="flex">
<div v-if="voltagBattery" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ voltagBattery }}V</font>
</div>
<div class="tag flex mac mc iconfont icon-dianya1">
</div>
</div>
<!-- 电池电流 -->
<div class="flex">
<div v-if="currentBattery" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ currentBattery }}A</font>
</div>
<div class="tag flex mac mc iconfont icon-dianliu">
</div>
</div>
<!-- 飞机高度 -->
<div class="flex">
<div v-if="positionAlt" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ positionAlt }}</font>
</div>
<div class="tag flex mac mc iconfont icon-gaodu">
</div>
</div>
<!-- 飞机对地速度 -->
<div class="flex">
<div v-if="groundSpeed" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{ groundSpeed }}/</font>
</div>
<div class="tag flex mac mc iconfont icon-sudu">
</div>
</div>
<!-- 飞机载重 钩子状态 -->
<div class="flex">
<div v-if="loadweight" class="plane-mode p-l-5 p-r-5 mc mac">
<font class="plane-mode-text">{{hookstatus}} {{ loadweight }}</font>
</div>
<div class="tag flex mac mc iconfont icon-mianxingdiaogou">
</div>
</div>
</div> </div>
</template> </template>
@ -74,13 +14,9 @@
<script> <script>
export default { export default {
name: 'PlaneStatus', name: 'Statistics',
data () { data () {
return { return {
/* 心跳 */
heartAnimation: false, //
online: false,
isOnlineSetTimeout: null
} }
}, },
props: { props: {
@ -92,110 +28,9 @@ export default {
components: { components: {
}, },
computed: { computed: {
//
heartRandom () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.heartRandom
}
return null
},
//
isLockState () {
if (this.plane && this.plane.planeState) {
if (Number(this.plane.planeState.heartBeat) & 128) {
return false
}
}
return true
},
//
getPlaneMode () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.getPlaneMode
}
return null
},
//
satCount () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.satCount
}
return null
},
//
fixType () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.fixType
}
return null
},
//
voltagBattery () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.voltagBattery
}
return null
},
//
currentBattery () {
if (this.plane && this.plane.planeState) {
if (Number(this.plane.planeState.currentBattery) > 0) {
return this.plane.planeState.currentBattery
} else {
return 0
}
}
return null
},
//
positionAlt () {
if (this.plane && this.plane.planeState && this.plane.planeState.position.length > 0) {
const posLen = this.plane.planeState.position.length
return this.plane.planeState.position[posLen - 1][2]
}
return null
},
//
groundSpeed () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.groundSpeed
}
return null
},
//
hookstatus () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.hookstatus
}
return null
},
//
loadweight () {
if (this.plane && this.plane.planeState) {
return this.plane.planeState.loadweight
}
return null
}
}, },
watch: { watch: {
heartRandom: {
handler () {
console.log('心跳:', this.plane.heartBeat)
//
this.heartAnimation = true
setTimeout(() => {
this.heartAnimation = false
}, 500)
// 线
if (this.isOnlineSetTimeout) { // 线
clearInterval(this.isOnlineSetTimeout)
}
this.online = true
this.isOnlineSetTimeout = setTimeout(() => { // 10 线
this.online = false
}, 10000)
}
}
}, },
methods: { methods: {
@ -203,9 +38,6 @@ export default {
created () { created () {
}, },
destroyed () { destroyed () {
if (this.isOnlineSetTimeout) {
clearInterval(this.isOnlineSetTimeout)
}
} }
} }

View File

@ -25,6 +25,7 @@ const store = new Vuex.Store({
paidOrderList: [], // 已付款 和已退款但是发货状态为 已发货 订单列表 paidOrderList: [], // 已付款 和已退款但是发货状态为 已发货 订单列表
logList: [], // 操作日志列表 logList: [], // 操作日志列表
messageList: [], // 管理员公告列表 messageList: [], // 管理员公告列表
mapStyleList: [], // 地图样式列表
crosFrequency: null, // 对频macadd crosFrequency: null, // 对频macadd
ADSBList: [] // 存放当前活跃的 ADSB 飞机数据 ADSBList: [] // 存放当前活跃的 ADSB 飞机数据
}, },
@ -146,6 +147,13 @@ const store = new Vuex.Store({
state.ADSBList.push({ ...ADSB, timestamp: Date.now() }) state.ADSBList.push({ ...ADSB, timestamp: Date.now() })
} }
}, },
/**
* @description: 设置地图样式列表
* @param {*} list 地图样式列表
*/
setMapStyleList (state, list) {
state.mapStyleList = list
},
/** /**
* @description: 清除过期的 ADSB 数据 * @description: 清除过期的 ADSB 数据
*/ */
@ -1159,6 +1167,44 @@ const store = new Vuex.Store({
logData.timestamp = typeof logData.timestamp !== 'undefined' ? logData.color : new Date().getTime() logData.timestamp = typeof logData.timestamp !== 'undefined' ? logData.color : new Date().getTime()
commit('insertNewLog', logData) commit('insertNewLog', logData)
/* 积攒 向服务器提交 日志 待续写... */ /* 积攒 向服务器提交 日志 待续写... */
},
/**
* @description: 获取地图样式列表
* @param {*} param0.rootState 传this.$store.state.settings.host 即云端存放sprite 的地址
*/
async fetchMapStyleList ({ commit, rootState }) {
const res = await api.get('getMapStyleList', 'Plane')
if (res.data.status === 1) {
const host = rootState.settings.host
const list = res.data.mapStyleList.map(style => {
const tiles = Array.isArray(style.tiles) ? style.tiles : JSON.parse(style.tiles)
const sourceKey = style.source_key || 'default'
return {
name: style.name,
sprite: `${host}/Public/map/sprite`,
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
version: 8,
sources: {
[sourceKey]: {
type: 'raster',
tileSize: Number(style.tileSize || 256),
tiles,
attribution: style.attribution || ''
}
},
layers: [{
id: `${sourceKey}Layer`,
type: 'raster',
source: sourceKey
}]
}
})
commit('setMapStyleList', list)
} else {
commit('setMapStyleList', [])
Message.error(res.data.msg || '地图样式获取失败')
}
} }
}, },
modules: { modules: {

View File

@ -1,15 +1,16 @@
<template> <template>
<div class="h-100"> <div class="h-100">
<map-box ref="mapbox"> <map-box ref="mapbox">
<template #content> <!-- <template #content>
<PlaneStatus :plane="plane" /> <Statistics :plane="plane" />
</template> </template> -->
</map-box> </map-box>
</div> </div>
</template> </template>
<script> <script>
import MapBox from '@/components/MapBox' import MapBox from '@/components/MapBox'
// import Statistics from '@/components/Statistics'
export default { export default {
name: 'Home', name: 'Home',
@ -19,6 +20,7 @@ export default {
}, },
components: { components: {
MapBox MapBox
// Statistics
}, },
computed: { computed: {
airList () { airList () {

View File

@ -122,7 +122,8 @@ export default {
this.$store.dispatch('fetchSpuList'), this.$store.dispatch('fetchSpuList'),
this.$store.dispatch('fetchSkuList'), this.$store.dispatch('fetchSkuList'),
this.$store.dispatch('fetchPaidOrderList'), this.$store.dispatch('fetchPaidOrderList'),
this.$store.dispatch('fetchMessageList') this.$store.dispatch('fetchMessageList'),
this.$store.dispatch('fetchMapStyleList', this.$store.state.settings.host)
]).then(() => { ]).then(() => {
return this.$store.dispatch('fetchNoflyData', this.shop_id) return this.$store.dispatch('fetchNoflyData', this.shop_id)
}) })