index.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <template>
  2. <view class="page-container">
  3. <view class="page-container-tip">
  4. <view class="tip">
  5. <u-icon name="volume" color="#4573FC" size="16"></u-icon>{{`尊敬的驾驶员,当前任务完成率${renderItem(trackInfo,'percentage','--')}%`}}
  6. </view>
  7. </view>
  8. <map-container
  9. ref="mapContainerRef"
  10. :pointsData="pointsData"
  11. @handleMarkerClick="handleMarkerClick"
  12. @onload="handleOnload"
  13. :markerClusterOptions="{
  14. maxZoom: 1,
  15. }"
  16. >
  17. </map-container>
  18. <u-modal :show="alarmShow" width="600rpx" confirmText="我知道了" confirmColor="#1D6FE9"
  19. @confirm="() => {
  20. alarmShow = false
  21. alarmName = ''
  22. }"
  23. >
  24. <view class="slot-content">
  25. <view class="err-tip">
  26. {{alarmName?`${alarmName},请核查!`:''}}
  27. </view>
  28. </view>
  29. </u-modal>
  30. <vehInfo ref="vehInfoRef" :trackInfo='trackInfo' :workTrackInfo="workTrackInfo"></vehInfo>
  31. </view>
  32. </template>
  33. <script>
  34. import {trackInfo,workTrackInfoRecord} from '@/api/system/workPlan.js'
  35. import MapContainer from '@/components/MapContainer'
  36. import vehInfo from './module/vehInfo.vue'
  37. import {isEmpty} from 'lodash'
  38. import {getImages} from '@/plugins/images'
  39. let car_online = getImages('/assetsMobile/images/map/icon/vehicle/car_online.png') //行驶在线--地图
  40. let pointWarning = getImages('/assetsMobile/images/map/icon/pointWarning.png') //报警图标
  41. export default {
  42. components: {
  43. MapContainer,
  44. vehInfo,
  45. },
  46. computed: {
  47. pointsData() {
  48. let list = []
  49. return list;
  50. },
  51. },
  52. data() {
  53. return {
  54. map: null,
  55. schId: null,
  56. trackList: [], //轨迹路线坐标系列表
  57. trackPoyline: null,
  58. polyline: null,
  59. //路线坐标系列表
  60. pointList: [],
  61. //绑定站点列表
  62. bindList: [],
  63. //车辆图标
  64. iconUrl: null,
  65. trackInfo: {},
  66. workTrackInfo: {},
  67. alarmShow: false,
  68. alarmName: '',
  69. alarmList:[], //报警列表
  70. fetched: false,
  71. timener: null,
  72. }
  73. },
  74. onLoad({schId}) {
  75. if(schId) {
  76. this.schId = schId
  77. }
  78. if (this.timener) {
  79. clearInterval(this.timener)
  80. }
  81. },
  82. beforeDestroy() {
  83. clearInterval(this.timener)
  84. },
  85. watch: {
  86. alarmList: {
  87. immediate: false,
  88. deep: true,
  89. handler(newVal,oldVal) {
  90. // console.log(newVal,oldVal,'newVal')
  91. if(!isEmpty(newVal) && this.fetched) {
  92. if(newVal.length > oldVal.length) {
  93. let len = newVal.length
  94. this.alarmName = newVal[len-1].alarmName
  95. this.alarmShow = true
  96. }
  97. }
  98. if(!this.fetched) {
  99. this.fetched = true
  100. }
  101. }
  102. }
  103. },
  104. onShow() {
  105. },
  106. onHide() {
  107. },
  108. onReady() {
  109. },
  110. methods: {
  111. initTime() {
  112. if (this.timener) {
  113. return
  114. } else {
  115. this.timener = setInterval(() => {
  116. this.getTrackInfo({schId: this.schId})
  117. }, 10000)
  118. }
  119. },
  120. async getTrackInfo({schId}) {
  121. let {code,data} = await trackInfo({schId})
  122. if(code == 0) {
  123. /* 绑定点 */
  124. this.bindList = data.bindList.map((item) => {
  125. return {
  126. facType: item.facType,
  127. iconUrl: item.iconUrl,
  128. id: item.id,
  129. name: item.name,
  130. lng:item.lng,
  131. lat:item.lat,
  132. radius:item.radius,
  133. }
  134. })
  135. this.iconUrl = data.iconUrl
  136. this.pointList = data.pointList
  137. this.trackInfo = data
  138. this.getWorkTrackInfoRecord({schId: this.schId})
  139. }
  140. },
  141. async getWorkTrackInfoRecord({schId}) {
  142. let {code,data} = await workTrackInfoRecord({schId})
  143. if(code == 0) {
  144. this.trackList = data.trackList
  145. this.workTrackInfo = data
  146. this.alarmList = data.alarmList?data.alarmList:[]
  147. this.drawBindList()
  148. this.drawPolyline()
  149. this.drawtrackPoyline(this.iconUrl)
  150. if(data.workStatus==0 || data.workStatus == 1) {
  151. this.initTime()
  152. }
  153. }
  154. },
  155. /* 画覆盖物 */
  156. drawBindList() {
  157. this.$refs.mapContainerRef.createProjects('removeAllMarkers')
  158. /* 画绑定点 */
  159. let getPoints = []
  160. this.bindList.forEach((item) => {
  161. getPoints.push({
  162. ...item,
  163. lng02: item.lng,
  164. lat02: item.lat,
  165. option: {
  166. position:[item.lng,item.lat],
  167. content: item.iconUrl?`<img style="width: 28px;" src="${getImages(item.iconUrl)}" />`:'',
  168. offset: item.iconUrl?[-14,-28]:[0,0],
  169. title: item.name
  170. },
  171. hiddenInfoWindow: true,
  172. })
  173. })
  174. this.alarmList.forEach((item) => {
  175. getPoints.push({
  176. ...item,
  177. option: {
  178. position:[item.lng02,item.lat02],
  179. content: `<img style="width: 20px;" src="${pointWarning}" />`,
  180. offset: [-14,-28],
  181. title: item.alarmName
  182. },
  183. hiddenInfoWindow: true,
  184. })
  185. })
  186. // console.log(getPoints,'getPointsgetPoints')
  187. this.$refs.mapContainerRef.createProjects('createMarker', { list: getPoints, type: 'workPlan' })
  188. },
  189. /* 画本计划路线 */
  190. drawPolyline() {
  191. if(isEmpty(this.pointList)) return
  192. let getPath = []
  193. this.pointList.forEach((item) => {
  194. getPath.push([item.lng,item.lat])
  195. })
  196. if (!this.isNull(this.polyline)) {
  197. this.$refs.mapContainerRef.removeOverlays(this.polyline)
  198. }
  199. this.polyline = this.$refs.mapContainerRef.createPolyline(getPath,{
  200. isOutline: true,
  201. outlineColor: '#FD5D09',
  202. borderWeight: 2,
  203. strokeColor: "#FEAE84",
  204. strokeOpacity: 1,
  205. strokeWeight: 4,
  206. // 折线样式还支持 'dashed'
  207. strokeStyle: "solid",
  208. // strokeStyle是dashed时有效
  209. // strokeDasharray: [10, 5],
  210. lineJoin: 'round',
  211. lineCap: 'round',
  212. zIndex: 50,
  213. showDir: false,
  214. })
  215. this.$refs.mapContainerRef.setFitView(this.polyline, false, [40, 200, 20, 20])
  216. },
  217. /*画轨迹 车辆图标*/
  218. drawtrackPoyline(iconUrl) {
  219. if(isEmpty(this.trackList)) return
  220. let getPath = []
  221. this.trackList.forEach((item) => {
  222. getPath.push([item.lng02,item.lat02])
  223. })
  224. if (!this.isNull(this.trackPoyline)) {
  225. this.$refs.mapContainerRef.removeOverlays(this.trackPoyline)
  226. }
  227. this.trackPoyline = this.$refs.mapContainerRef.createPolyline(getPath,{
  228. isOutline: true,
  229. outlineColor: '#00FFFF',
  230. borderWeight: 2,
  231. strokeColor: "#7FFFFF",
  232. strokeOpacity: 1,
  233. strokeWeight: 4,
  234. // 折线样式还支持 'dashed'
  235. strokeStyle: "solid",
  236. // strokeStyle是dashed时有效
  237. strokeDasharray: [10, 5],
  238. lineJoin: 'round',
  239. lineCap: 'round',
  240. zIndex: 52,
  241. showDir: false,
  242. })
  243. /* 添加车辆图标 */
  244. let getPoints= []
  245. if(!isEmpty(this.trackList)) {
  246. let end = this.trackList[this.trackList.length-1]
  247. getPoints.push({
  248. ...end,
  249. tabStyle: 'vehicle',
  250. option: {
  251. position:[end.lng02,end.lat02],
  252. content: `<img style="width: 28px;transform:rotate(${end.direction}deg);" src="${iconUrl?getImages(iconUrl) : car_online}" />`,
  253. offset: [-14,-14],
  254. },
  255. hiddenInfoWindow: true,
  256. })
  257. }
  258. // console.log(iconUrl,'iconUrliconUrl')
  259. this.$refs.mapContainerRef.createProjects('createMarker', { list: getPoints, type: 'workPlan' })
  260. },
  261. //点击标注点
  262. handleMarkerClick(e) {
  263. // console.log(e,'handleMarkerClick')
  264. const {cluster} = e
  265. let item = cluster.p.item
  266. // const {address} = item
  267. // if(address) this.$refs.vehInfoRef.show(item)
  268. },
  269. handleOnload(map) {
  270. this.map = map
  271. this.getTrackInfo({schId: this.schId})
  272. },
  273. }
  274. }
  275. </script>
  276. <style lang="scss" scoped>
  277. .err-tip {
  278. font-family: PingFangSC, PingFang SC;
  279. font-weight: 400;
  280. font-size: 32rpx;
  281. color: #FF2D2D;
  282. text-align: right;
  283. font-style: normal;
  284. }
  285. .page-container {
  286. background: #fff;
  287. font-size: 28rpx;
  288. height: 100vh;
  289. position: relative;
  290. .page-container-tip {
  291. height: 72rpx;
  292. width: 100%;
  293. position: absolute;
  294. top: 0;
  295. left: 0;
  296. z-index: 1000;
  297. background: rgba(69, 115, 252, 0.1);
  298. display: flex;
  299. align-items: center;
  300. .tip {
  301. margin-left: 40rpx;
  302. font-family: PingFangSC, PingFang SC;
  303. font-weight: 400;
  304. font-size: 24rpx;
  305. color: #4573FC;
  306. line-height: 40rpx;
  307. text-align: left;
  308. font-style: normal;
  309. display: flex;
  310. align-items: center;
  311. }
  312. }
  313. .footer {
  314. padding: 10rpx 0;
  315. position: fixed;
  316. width: 100%;
  317. left: 0;
  318. bottom: 0;
  319. }
  320. }
  321. ::v-deep {
  322. .u-form-item__body {
  323. padding: 0;
  324. }
  325. .hidde-cell-title {
  326. .u-cell__body__content {
  327. width: auto;
  328. flex: none;
  329. }
  330. .u-cell__body {
  331. .value {
  332. flex: 1;
  333. }
  334. }
  335. }
  336. }
  337. </style>