| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- <template>
- <view class="page" :style="{ height: windowHeight + 'px', flexDirection: flexDirection }">
- <view id="map" :style="{ height: mapHeight + 'px', width: mapWidth + 'px' }" class='map' />
- <view v-show="popupShow" class="popup" :style="{ height: popupHeight + 'px', width: popupWidth + 'px' }">
- <!-- <uni-section title="活动路线列表" type="line"> -->
- <uni-data-picker class="actionsTree" :style="{ width: popupWidth + 'px' }" placeholder="请选择活动" popup-title="请选择活动路线" :localdata="actionsTree"
- v-model="sltActRoute" @change="onActionChange" @popupopened="onActionsTreePopupOpened" @popupclosed="onActionsTreePopupClosed"></uni-data-picker>
- <!-- </uni-section> -->
- <!-- <uni-section title="玩家列表" type="line"> -->
- <scroll-view :scroll-top="0" scroll-y="true" class="scroll-Y" :style="{ height: popupHeight - 35 + 'px'}">
- <uni-list v-for="(item, index) in players" :key="index" :border="true" class="list">
- <uni-list-item :clickable="true" @click="onPlayerListItemClick(item)" class="list-item" :class="{
- 'list-item-focus': focusPlayerId == item.id
- }">
- <template v-slot:header>
- <!-- <image class="slot-image" src="/static/logo.png" mode="widthFix"></image> -->
- <div class="slot-image" :style="'background-color:' + getPlayerColor(item.id)"></div>
- </template>
- <template v-slot:body>
- <view class="slot-box">
- <view class="slot-title">
- [{{index+1}}] <span class="slot-phone" @click="onPhoneClick(item.phone)">
- {{item.name}} </span>
- 打点 {{item.effectivenum}}/{{item.totalcontrolnum}} 距离
- {{item.distance}}米 配速 {{formatTime(item.pace, false)}}
- </view>
- <view class="slot-note">
- 心率 {{item.lasthr}} 平均 {{item.avghr}} 最大 {{item.maxhr}} | Cal
- {{Math.round(item.calorie/1000)}} Ck {{item.ck}} Ei
- {{Math.round(item.ei*100)/100}}
- </view>
- </view>
- </template>
- <!-- <template v-slot:footer>
- <image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
- </template> -->
- </uni-list-item>
- </uni-list>
- </scroll-view>
- <!-- </uni-section> -->
- </view>
- </view>
- </template>
- <script>
- import {
- mapState,
- mapGetters
- } from 'vuex'
- import {
- DefaultRequest,
- IdRequest,
- } from "@/grpc/base_pb.js"
- import {
- ToActionIdAndCourseIdRequest
- } from "@/grpc/track_offical_pb.js"
-
- import {
- formatTime
- } from "@/utils/util.js"
- export default {
- components: {},
- data() {
- return {
- interval_loadActionsTree: null,
- interval_loadData: null,
- actionsTreePopup: false,
- systemInfo: null,
- flexDirection: 'column',
- windowHeight: 0,
- windowWidth: 0,
- mapHeight: 0,
- mapWidth: 0,
- popupHeight: 0,
- popupWidth: 0,
- popupHeightPortrait: 360, // 竖屏状态下的底部弹框高度
- popupWidthlandscape: 336, // 横屏状态下的右侧弹框宽度
- popupType: 'bottom',
- popupShow: false,
- extraIcon: {
- // color: '#4cd964',
- // size: '22',
- // type: 'gear-filled'
- },
- mapId: 0,
- mapDetail: {},
- mapUrl: null,
- mapInfo: {},
- actionId: 0,
- actionDetail: {},
- routeId: 0,
- routeDetail: {},
- // checkPoints: [],
- nextCP: [], // 用户即将到达控制点列表
- players: [],
- players_position: [],
- focusPlayerId: 0,
- trailTime: 0,
- sltActRoute: '',
- actionsTree: []
- }
- },
- computed: {
- ...mapState([
- 'username', // 映射 this.username 为 store.state.username
- ]),
- ...mapGetters([
- 'metadata'
- ]),
- },
- mounted() {
- this.$global.getWindowInfo()
- uni.$on('windowResize', this.reLoad)
- this.popupShow = this.$store.state.mapPopupShow
- this.layoutInit()
- },
- onLoad(option) {
- console.log('[onLoad] mapId:' + option.mapId)
- if (option.mapId > 0) {
- this.mapId = option.mapId
- this.loadMap(this.mapId)
- if (this.mapId == this.$store.state.mapSltMapId) { // 页面重载
- this.sltActRoute = this.$store.state.mapSltActRoute
- this.loadData(this.sltActRoute)
- }
-
- if (this.interval_loadActionsTree != null) {
- clearInterval(this.interval_loadActionsTree)
- }
-
- let that = this
- this.interval_loadActionsTree = setInterval(async function() {
- if (!that.actionsTreePopup) {
- await that.loadActionsTree()
- }
- }, 3000);
- }
- },
- beforeDestroy() {
- console.log("[beforeDestroy]")
- clearInterval(this.interval_loadActionsTree)
- clearInterval(this.interval_loadData)
- // leafletHelper.free()
- uni.$off('windowResize', this.reLoad)
- },
- methods: {
- formatTime,
- reLoad() {
- this.$store.commit('setMapSltMapId', this.mapId)
- this.savePlayersData()
- var fullPath = this.$route.fullPath
- console.log("[windowResize] reLaunch: " + fullPath)
- uni.redirectTo({
- url: fullPath
- });
- },
- // 布局初始化 设置地图高度
- layoutInit() {
- this.windowHeight = this.$global.windowHeight
- this.windowWidth = this.$global.windowWidth
- if (this.$global.deviceOrientation == 'portrait') { // 竖屏
- this.flexDirection = 'column'
- this.mapWidth = this.$global.windowWidth
- this.mapHeight = this.$global.windowHeight
- // if (this.popupShow) {
- // this.mapHeight = this.$global.windowHeight - this.popupHeightPortrait
- // } else {
- // this.mapHeight = this.$global.windowHeight
- // }
- // console.log("竖屏", this.mapHeight)
- this.popupHeight = this.popupHeightPortrait
- this.popupWidth = this.$global.windowWidth
- } else { // 横屏
- this.flexDirection = 'row'
- this.mapHeight = this.$global.windowHeight
- this.mapWidth = this.$global.windowWidth
- // if (this.popupShow) {
- // this.mapWidth = this.$global.windowWidth - this.popupWidthlandscape
- // } else {
- // this.mapWidth = this.$global.windowWidth
- // }
- // console.log("横屏", this.mapWidth)
- this.popupHeight = this.$global.windowHeight
- this.popupWidth = this.popupWidthlandscape
- // console.log("横屏 popupHeight", this.popupHeight)
- }
- },
- popupToggle() {
- this.popupShow = !this.popupShow
- this.$store.commit('setMapPopupShow', this.popupShow)
- // this.layoutInit()
- },
- fullScreenToggle() {
- this.$global.fullscreen()
- this.$global.getWindowInfo()
- this.layoutInit()
- },
- makeActionsTree(actselectrsList) {
- this.actionsTree.length = 0 // 先清空数组
- for (let i = 0; i < actselectrsList.length; i++) {
- var act = actselectrsList[i]
- var pushData = {
- text: act.actname,
- value: act.actid,
- children: []
- }
- var actUserNum = 0
- for (let j = 0; j < act.courseselectrsList.length; j++) {
- var course = act.courseselectrsList[j]
- actUserNum += course.courseusernum
- pushData.children.push({
- text: course.coursename + ' (' + course.courseusernum + '人)',
- value: act.actid + '-' + course.courseid
- })
- }
- if (actUserNum >= 0) {
- pushData.children.unshift({
- text: '全部 (' + actUserNum + '人)',
- value: act.actid + '-' + 0
- })
- }
- pushData.text += ' (' + actUserNum + '人)'
- this.actionsTree.push(pushData)
- }
- // console.log("[makeActionsTree]" + JSON.stringify(this.actionsTree))
- },
- async loadMap() {
- await this.loadActionsTree()
- uni.setNavigationBarTitle({
- title: this.mapDetail.mapinfo.mapname
- });
- // console.log(this.actionDetail)
- this.initMap()
- this.handleMapToggle()
- },
- async loadActionsTree() {
- this.mapDetail = await this.getToMapDetail(this.mapId)
- this.makeActionsTree(this.mapDetail.actselectrsList)
- },
- async loadData(sltActRoute) {
- console.log("[loadData] sltActRoute: ", sltActRoute)
- if (sltActRoute == null || sltActRoute.length == 0) {
- return
- }
- var actRouteArr = sltActRoute[1].value.split('-')
- this.actionId = actRouteArr[0]
- this.routeId = actRouteArr[1]
- this.actionDetail = await this.getToActionDetail(this.actionId, this.routeId)
- uni.setNavigationBarTitle({
- title: this.mapDetail.mapinfo.mapname + ' - ' + this.actionDetail.name
- });
- // console.log(this.actionDetail)
- if (this.interval_loadData != null) {
- clearInterval(this.interval_loadData)
- }
- this.players = await this.getToUsersInGameDetail(this.actionId, this.routeId)
- // console.log('players', that.players)
- // leafletHelper.global.setPlayers(this.players)
- this.players_position = await this.getToUsersInGameGpsQuery(this.actionId, this.routeId)
- // leafletHelper.global.setPlayersPosition(this.players_position)
-
- this.nextCP = await this.getToNextControlPointInGame(this.actionId, this.routeId)
-
- this.handleMapDrawRoute()
- this.handleMapDrawPlayer()
- this.handleMapDrawTrail()
- let that = this
- this.interval_loadData = setInterval(async function() {
- that.players = await that.getToUsersInGameDetail(that.actionId, that.routeId)
- that.players_position = await that.getToUsersInGameGpsQuery(that.actionId, that
- .routeId)
- that.nextCP = await that.getToNextControlPointInGame(that.actionId, that.routeId)
- //// leaflet.leafletHelper.global.setPlayers(that.players)
- // leafletHelper.global.setPlayersPosition(that.players_position)
- that.handleMapDrawPlayer()
- that.handleMapDrawTrail()
- }, 1000);
- },
- //场控端_地图详情
- async getToMapDetail(mapId) {
- try {
- return new Promise((resolve, reject) => {
- // 创建请求参数并赋值
- var request = new IdRequest()
- request.setId(mapId)
- // 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
- this.$client.toMapDetail(request, this.metadata, (err, response) => {
- if (err) {
- console.warn(`[toMapDetail] err: code = ${err.code}` +
- `, message = "${err.message}"`)
- reject(err)
- } else {
- let res = response.toObject()
- // console.log('[toMapDetail]', res)
- resolve(res)
- }
- })
- });
- } catch (e) {
- console.log('[getToMapDetail] err', e)
- reject(e)
- }
- },
- //场控端_活动详情
- async getToActionDetail(actId, routeId = 0) {
- try {
- return new Promise((resolve, reject) => {
- // 创建请求参数并赋值
- var request = new ToActionIdAndCourseIdRequest()
- request.setActid(actId)
- request.setCourseid(routeId)
- // 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
- this.$client.toActionDetail(request, this.metadata, (err, response) => {
- if (err) {
- console.warn(`[toActionDetail] err: code = ${err.code}` +
- `, message = "${err.message}"`)
- reject(err)
- } else {
- let res = response.toObject()
- console.log('[toActionDetail]', res)
- resolve(res)
- }
- })
- });
- } catch (e) {
- console.log('[getToActionDetail] err', e)
- reject(e)
- }
- },
- //场控端_正在进行中所有用户实时信息
- async getToUsersInGameDetail(actId, routeId = 0) {
- try {
- return new Promise((resolve, reject) => {
- // 创建请求参数并赋值
- var request = new ToActionIdAndCourseIdRequest()
- request.setActid(actId)
- request.setCourseid(routeId)
- // 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
- this.$client.toUsersInGameDetail(request, this.metadata, (err,
- response) => {
- if (err) {
- console.warn(`[toUsersInGameDetail] err: code = ${err.code}` +
- `, message = "${err.message}"`)
- reject(err)
- } else {
- let res = response.toObject()
- // console.log('[toUsersInGameDetail]', res)
- resolve(res.usersList)
- }
- })
- });
- } catch (e) {
- console.log('[getToUsersInGameDetail] err', e)
- reject(e)
- }
- },
- //场控端_正在进行中所有用户实时gps查询
- async getToUsersInGameGpsQuery(actId, routeId = 0) {
- try {
- return new Promise((resolve, reject) => {
- // 创建请求参数并赋值
- var request = new ToActionIdAndCourseIdRequest()
- request.setActid(actId)
- request.setCourseid(routeId)
- // 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
- this.$client.toUsersInGameGpsQuery(request, this.metadata, (err,
- response) => {
- if (err) {
- console.warn(`[toUsersInGameGpsQuery] err: code = ${err.code}` +
- `, message = "${err.message}"`)
- reject(err)
- } else {
- let res = response.toObject()
- // console.log('[toUsersInGameGpsQuery]', res)
- resolve(res.gpsinfoList)
- }
- })
- });
- } catch (e) {
- console.log('[getToUsersInGameGpsQuery] err', e)
- reject(e)
- }
- },
- //场控端_正在进行中所有用户即将到达控制点列表,结果去重
- async getToNextControlPointInGame(actId, routeId = 0) {
- try {
- return new Promise((resolve, reject) => {
- // 创建请求参数并赋值
- var request = new ToActionIdAndCourseIdRequest()
- request.setActid(actId)
- request.setCourseid(routeId)
- // 调用客户端相应的grpc方法,发送grpc请求,并接受后台发送回来的返回值
- this.$client.toNextControlPointInGame(request, this.metadata, (err,
- response) => {
- if (err) {
- console.warn(`[toNextControlPointInGame] err: code = ${err.code}` +
- `, message = "${err.message}"`)
- reject(err)
- } else {
- let res = response.toObject()
- // console.log('[toNextControlPointInGame]', res)
- resolve(res.nextcontrolpointrsList)
- }
- })
- });
- } catch (e) {
- console.log('[getToUsersInGameGpsQuery] err', e)
- reject(e)
- }
- },
- onActionChange(e) {
- const sltActRoute = e.detail.value
- console.log("onActionChange", sltActRoute)
- this.$store.commit('setMapSltActRoute', sltActRoute)
- if (sltActRoute == null || sltActRoute.length == 0) {
- this.reLoad()
- return
- }
- this.loadData(sltActRoute)
- },
- onActionsTreePopupOpened() {
- // console.log("onActionsTreePopupOpened")
- this.actionsTreePopup = true
- },
- onActionsTreePopupClosed() {
- // console.log("onActionsTreePopupClosed")
- this.actionsTreePopup = false
- },
- onPlayerListItemClick(item) {
- // console.log("onListItemClick", item)
- this.handlePlayerListItemClick(item)
- },
- onPhoneClick(phoneNumber) {
- if (phoneNumber.length == 11) {
- uni.makePhoneCall({
- phoneNumber: phoneNumber
- })
- } else {
- uni.showToast({
- title: '手机号码不正确',
- icon: 'none'
- })
- }
- },
- }
- }
- </script>
- <script module="leaflet" lang="renderjs">
- import 'leaflet/dist/leaflet.css'
- import '@/utils/map/leafletHelper.css'
- // import mapHelper from '@/utils/mapHelper'
- import leafletHelper from '@/utils/map/leafletHelper'
- export default {
- components: {},
- // data() {
- // return {},
- // },
- // mounted() {
- // uni.$on('myEvent', this.myEventHandler);
- // },
- // destroyed() {
- // uni.$off('myEvent', this.myEventHandler);
- // },
- beforeDestroy() {
- // console.log("beforeDestroy")
- // clearInterval(this.interval_loadData)
- leafletHelper.free()
- },
- methods: {
- // myEventHandler(data) {
- // console.log('视图层接收到数据:', data);
- // },
- initMap() {
- if (this.mapDetail != null && this.mapDetail.mapinfo != null) {
- // const mapid = this.mapDetail.mapinfo.lid
- const mapUrl = this.mapDetail.mapinfo.mapurl
- const centPoint = [this.mapDetail.mapinfo.centerlatitude, this.mapDetail.mapinfo.centerlongitude]
- const zoomNum = this.mapDetail.mapinfo.defscale
- const mapOptions = {
- center: centPoint,
- zoom: zoomNum,
- maxBounds: [
- [36.659365, 117.105246],
- [36.653753, 117.122841]
- ],
- }
- leafletHelper.init(this, 'map', mapUrl, mapOptions)
- }
- },
- handleWindowResize() {
- leafletHelper.onWindowResize()
- },
- handleMapDrawRoute() {
- // leafletHelper.global.setCheckPoints(this.checkPoints)
- // leafletHelper.global.setRoutes(this.mapDetail.routesList)
- leafletHelper.global.setRoutes(this.actionDetail.routesList)
- // leafletHelper.checkPoint.drawAllCheckPoints()
- // leafletHelper.checkPoint.drawPath()
- leafletHelper.route.drawAllRoutes()
- // leafletHelper.route.drawAllPath()
- },
- handleMapDrawPlayer() {
- leafletHelper.global.setPlayers(this.players)
- leafletHelper.global.setPlayersPosition(this.players_position)
- leafletHelper.player.drawAllPlayers()
- // leafletHelper.player.drawOnePlayer(2)
- // leafletHelper.player.drawOnePlayer(3)
- leafletHelper.global.dealStaleData()
- },
- handleMapDrawTrail() {
- this.trailTime = leafletHelper.config.trailTime
- // leafletHelper.player.drawOneTrail(2, 10000)
- // leafletHelper.player.drawOneTrail(3, 10000)
- // leafletHelper.player.drawOneTrail(2, 0, false)
- leafletHelper.player.drawAllTrails(this.trailTime)
- },
- handleMapToggle() {
- // leafletHelper.checkPoint.toggle(true)
- // leafletHelper.route.toggle(true)
- // leafletHelper.player.togglePlayer(true)
- // leafletHelper.player.toggleTooltip(true)
- // leafletHelper.player.toggleTrail(true)
- leafletHelper.route.toggle(this.$store.state.mapControlRoute)
- leafletHelper.player.togglePlayer(this.$store.state.mapControlPlayer)
- leafletHelper.player.toggleTooltip(this.$store.state.mapControlTooltip)
- leafletHelper.player.toggleTrail(this.$store.state.mapControlTrail)
- },
- handlePlayerListItemClick(item) {
- this.focusPlayerId = item.id
- leafletHelper.player.handleFocusPlayer(this.focusPlayerId)
- },
- getPlayerColor(playerId) {
- if (playerId != this.focusPlayerId)
- return leafletHelper.player.getPlayerColor(playerId)
- else
- return leafletHelper.config.gStyle.marker.focus.fillColor
- },
- // 页面reLoad前调用本方法,将用户数据先保存,页面重载后再进行数据恢复
- savePlayersData() {
- leafletHelper.global.savePlayersData()
- },
- },
- }
- </script>
- <style lang="scss" scoped>
- .page {
- display: flex;
- // margin: 0px;
- // padding: 0px;
- }
- // 勿删,解决map控件获得焦点后出现边框颜色的问题
- :focus-visible {
- outline: none;
- }
- .map {
- flex: 1 1 auto;
- background-color: white;
- z-index: 0;
- // display: flex;
- // justify-content: center;
- // align-items: center;
- }
- .popup {
- display: flex;
- flex-direction: column;
- align-items: center;
- background-color: #f5f5f5;
- border-left: #dedede solid 1px;
- // border-top: #dedede solid 1px;
- // overflow: scroll;
- }
-
- .actionsTree {
- // width: 100%;
- // background-color: #ffffff;
-
- /deep/ .input-value-border {
- border-top: 1px solid #e5e5e5;
- border-bottom: 1px solid #e5e5e5;
- border-radius: 0px;
- }
-
- /deep/ .uni-scroll-view {
- overflow: unset !important;
- }
- }
- .scroll-Y {
- // height: 100vh;
- }
- .list {
- margin-left: -6px;
- }
- .list-item {
- /* #ifndef APP-NVUE */
- display: flex;
- /* #endif */
- flex-direction: row;
- align-items: center;
- height: 46px;
- }
- .list-item-focus {
- background-color: #fffaef !important;
- }
- .slot-box {
- /* #ifndef APP-NVUE */
- display: flex;
- /* #endif */
- flex-direction: column;
- align-items: flex-start;
- width: 330px;
- max-width: 350px;
- }
- .slot-image {
- /* #ifndef APP-NVUE */
- display: block;
- /* #endif */
- margin-right: 6px;
- width: 6px;
- height: 33px;
- align-self: center;
- }
- .slot-title {
- flex: 1;
- font-size: 13px;
- color: #424242;
- line-height: 18px;
- // margin-right: 10px;
- // overflow:hidden; //超出的文本隐藏
- // text-overflow:ellipsis; //溢出用省略号显示
- white-space: nowrap; //溢出不换行
- }
- .slot-note {
- flex: 1;
- font-size: 12px;
- color: #7d8da7;
- line-height: 18px;
- // margin-right: 10px;
- // overflow:hidden; //超出的文本隐藏
- // text-overflow:ellipsis; //溢出用省略号显示
- white-space: nowrap; //溢出不换行
- }
- .slot-phone {
- padding: 0 5px;
- color: #000;
- font-weight: bold;
- }
- /deep/ .uni-data-tree-dialog {
- top: 39px;
- }
- </style>
|