合伙人运营小程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. const api = require('../../api/index.js');
  2. Page({
  3. data: {
  4. // 地图基础配置
  5. longitude: 0,
  6. latitude: 0,
  7. scale: 10,
  8. polyline: [],
  9. markers: [],
  10. // 选项卡默认选中车
  11. activeType: 'car',
  12. // 四类点位数据(车+电站+用户+司机)
  13. pointData: {
  14. car: [],
  15. station: [],
  16. user: [],
  17. driver: [] // 新增司机数据字段
  18. },
  19. currentList: [],
  20. // 四类点位自定义图标(新增司机图标)
  21. markerIcons: {
  22. car: 'https://esos-iot.com/myminio/project/e9c0fba9b61448e59458054d335b162b.png', // 储能车图标
  23. station: 'https://esos-iot.com/myminio/project/62a7a9c509f948558436bc56ee9bfe2e.png', // 电站图标
  24. user: 'https://esos-iot.com/myminio/project/42dd004817dd4f268d97dcd1145ca113.png', // 用户用电图标
  25. driver: 'https://esos-iot.com/myminio/project/6dc37b15321b462f9ab59c47263dd224.png' // 司机图标(替换为实际路径)
  26. },
  27. selectcardata: [],
  28. powerindex: 0,
  29. objectArray: []
  30. },
  31. onLoad(options) {
  32. wx.$on('wsMessage', this.handleWsMessage);
  33. if (wx.getStorageSync('projectId') == '') {
  34. wx.setStorage({
  35. key: 'projectId',
  36. data: ''
  37. });
  38. this.getaddredisredis()
  39. }
  40. this.getproject()
  41. // 初始化地图(延迟执行确保数据加载完成)
  42. setTimeout(() => {
  43. this.initAllMarkers();
  44. }, 2000);
  45. },
  46. onHide() {
  47. // 取消WebSocket订阅,防止内存泄漏
  48. wx.$off('wsMessage', this.handleWsMessage);
  49. },
  50. /**
  51. * 处理WebSocket消息
  52. */
  53. handleWsMessage(message) {
  54. console.log('收到WebSocket消息:', message);
  55. switch (message.api) {
  56. case '/syscar/selectcar':
  57. this.getproject();
  58. break;
  59. }
  60. },
  61. /**
  62. * 获取电站列表
  63. */
  64. getproject() {
  65. api.request(`/sysproject/selectproject`, 'post', {}, { isPublic: false })
  66. .then((res) => {
  67. console.log('电站列表:', res.data);
  68. if (res.code === 200) {
  69. // 新增"全部电站"选项
  70. const projectList = [{
  71. createTime: "",
  72. electric: "",
  73. partnership: "",
  74. projectId: "",
  75. projectType: "",
  76. projectName: "全部电站"
  77. }, ...res.data];
  78. this.setData({
  79. objectArray: projectList
  80. });
  81. // 设置默认选中项
  82. for (let i = 0; i < projectList.length; i++) {
  83. if (projectList[i].projectId === wx.getStorageSync('projectId')) {
  84. this.setData({ powerindex: i });
  85. break;
  86. }
  87. }
  88. // 重新加载所有数据
  89. this.getaddredisredis();
  90. this.oncar();
  91. this.onstation();
  92. this.onuser();
  93. this.ondriver(); // 新增加载司机数据
  94. }
  95. })
  96. .catch((err) => {
  97. console.error('获取电站列表失败:', err);
  98. });
  99. },
  100. /**
  101. * 缓存项目ID到redis
  102. */
  103. getaddredisredis() {
  104. const data = {
  105. projectId: wx.getStorageSync('projectId')
  106. };
  107. api.request(`/sysproject/insertredis`, 'POST', data)
  108. .then((res) => {
  109. console.log('Redis缓存结果:', res);
  110. })
  111. .catch((err) => {
  112. console.error('Redis缓存失败:', err);
  113. });
  114. },
  115. /**
  116. * 选择电站下拉框事件
  117. */
  118. bindPickerChange(e) {
  119. console.log('选择电站:', e.detail.value);
  120. const selectedIndex = e.detail.value;
  121. const selectedProject = this.data.objectArray[selectedIndex];
  122. // 缓存选中的项目ID
  123. wx.setStorage({
  124. key: 'projectId',
  125. data: selectedProject.projectId
  126. });
  127. // 更新redis缓存
  128. api.request(`/sysproject/insertredis`, 'POST', {
  129. projectId: selectedProject.projectId
  130. }).then((res) => {
  131. console.log('切换电站缓存结果:', res);
  132. this.getproject(); // 重新加载数据
  133. }).catch((err) => {
  134. console.error('切换电站缓存失败:', err);
  135. });
  136. },
  137. /**
  138. * 获取车辆数据
  139. */
  140. oncar() {
  141. api.request(`/syscar/selectcar`, 'post', {}, { isPublic: false })
  142. .then((res) => {
  143. console.log('车辆数据:', res.data);
  144. if (res.code === 200) {
  145. // 处理车辆数据,拆分经纬度
  146. const processedData = res.data.map(item => {
  147. // 拆分并清洗经纬度
  148. const posArr = item.carPosition?.split(',')
  149. .map(pos => pos.trim())
  150. .filter(pos => pos);
  151. const latitude = parseFloat(posArr?.[0]) || 0;
  152. const longitude = parseFloat(posArr?.[1]) || 0;
  153. return {
  154. ...item,
  155. latitude,
  156. longitude,
  157. type: 'car'
  158. };
  159. });
  160. this.setData({
  161. "pointData.car": processedData
  162. });
  163. // 如果当前选中的是车辆标签,更新列表
  164. if (this.data.activeType === 'car') {
  165. this.switchType({ currentTarget: { dataset: { type: 'car' } } });
  166. }
  167. }
  168. })
  169. .catch((err) => {
  170. console.error('获取车辆数据失败:', err);
  171. });
  172. },
  173. /**
  174. * 获取购电电站数据
  175. */
  176. onstation() {
  177. api.request(`/sysaddress/selectaddress`, 'post', { addressType: 1 }, { isPublic: false })
  178. .then((res) => {
  179. console.log('购电电站数据:', res.data);
  180. if (res.code === 200) {
  181. // 处理电站数据,补充经纬度和类型
  182. const processedData = res.data.map(item => {
  183. // 解析经纬度(根据实际字段调整)
  184. const latitude = parseFloat(item.latitude || item.addressLat) || 0;
  185. const longitude = parseFloat(item.longitude || item.addressLng) || 0;
  186. return {
  187. ...item,
  188. latitude,
  189. longitude,
  190. type: 'station'
  191. };
  192. });
  193. this.setData({
  194. "pointData.station": processedData
  195. });
  196. // 如果当前选中的是购电标签,更新列表
  197. if (this.data.activeType === 'station') {
  198. this.switchType({ currentTarget: { dataset: { type: 'station' } } });
  199. }
  200. }
  201. })
  202. .catch((err) => {
  203. console.error('获取购电电站数据失败:', err);
  204. });
  205. },
  206. /**
  207. * 获取售电用户数据
  208. */
  209. onuser() {
  210. api.request(`/sysaddress/selectaddress`, 'post', { addressType: 2 }, { isPublic: false })
  211. .then((res) => {
  212. console.log('售电用户数据:', res.data);
  213. if (res.code === 200) {
  214. // 处理用户数据,补充经纬度和类型
  215. const processedData = res.data.map(item => {
  216. // 解析经纬度(根据实际字段调整)
  217. const latitude = parseFloat(item.latitude || item.addressLat) || 0;
  218. const longitude = parseFloat(item.longitude || item.addressLng) || 0;
  219. return {
  220. ...item,
  221. latitude,
  222. longitude,
  223. type: 'user'
  224. };
  225. });
  226. this.setData({
  227. "pointData.user": processedData
  228. });
  229. // 如果当前选中的是售电标签,更新列表
  230. if (this.data.activeType === 'user') {
  231. this.switchType({ currentTarget: { dataset: { type: 'user' } } });
  232. }
  233. }
  234. })
  235. .catch((err) => {
  236. console.error('获取售电用户数据失败:', err);
  237. });
  238. },
  239. /**
  240. * 新增:获取司机数据
  241. */
  242. ondriver() {
  243. // 请替换为实际的司机接口地址和参数
  244. api.request(`/sysoperation/selectoperation`, 'post', {}, { isPublic: false })
  245. .then((res) => {
  246. console.log('司机数据:', res.data);
  247. if (res.code === 200) {
  248. // 处理司机数据,补充经纬度和类型
  249. const processedData = res.data.map(item => {
  250. // 解析经纬度(根据实际字段调整)
  251. const posArr = item.driverPosition?.split(',')
  252. .map(pos => pos.trim())
  253. .filter(pos => pos);
  254. const latitude = parseFloat(posArr?.[0] || item.latitude || 0);
  255. const longitude = parseFloat(posArr?.[1] || item.longitude || 0);
  256. return {
  257. ...item,
  258. latitude,
  259. longitude,
  260. type: 'driver',
  261. id: item.driverId || item.id, // 统一ID字段
  262. driverName: item.driverName || item.name || '未知司机' // 统一名称字段
  263. };
  264. });
  265. this.setData({
  266. "pointData.driver": processedData
  267. });
  268. // 如果当前选中的是司机标签,更新列表
  269. if (this.data.activeType === 'driver') {
  270. this.switchType({ currentTarget: { dataset: { type: 'driver' } } });
  271. }
  272. }
  273. })
  274. .catch((err) => {
  275. console.error('获取司机数据失败:', err);
  276. });
  277. },
  278. /**
  279. * 初始化所有点位标记
  280. */
  281. initAllMarkers() {
  282. // 合并所有四类点位数据
  283. const allPoints = [
  284. ...this.data.pointData.car,
  285. ...this.data.pointData.station,
  286. ...this.data.pointData.user,
  287. ...this.data.pointData.driver // 新增司机点位
  288. ];
  289. console.log('所有点位数据:', allPoints);
  290. // 适配地图视野并生成标记
  291. this.autoFitMap(allPoints);
  292. this.generateAllMarkers(allPoints);
  293. },
  294. /**
  295. * 自动适配地图视野,确保所有点位都可见
  296. */
  297. autoFitMap(pointList) {
  298. if (!pointList || pointList.length === 0) {
  299. // 无数据时默认定位上海
  300. this.setData({ longitude: 121.473701, latitude: 31.230416, scale: 14 });
  301. return;
  302. }
  303. // 提取有效经纬度
  304. const longitudes = pointList.map(item => Number(item.longitude)).filter(v => !isNaN(v) && v !== 0);
  305. const latitudes = pointList.map(item => Number(item.latitude)).filter(v => !isNaN(v) && v !== 0);
  306. if (longitudes.length === 0 || latitudes.length === 0) {
  307. this.setData({ longitude: 121.473701, latitude: 31.230416, scale: 14 });
  308. return;
  309. }
  310. // 计算极值和中心点
  311. const maxLng = Math.max(...longitudes);
  312. const minLng = Math.min(...longitudes);
  313. const maxLat = Math.max(...latitudes);
  314. const minLat = Math.min(...latitudes);
  315. const centerLng = (maxLng + minLng) / 2;
  316. const centerLat = (maxLat + minLat) / 2;
  317. // 计算跨度并添加缓冲
  318. const lngDiff = (maxLng - minLng) + 0.01;
  319. const latDiff = (maxLat - minLat) + 0.01;
  320. // 计算缩放级别
  321. const systemInfo = wx.getSystemInfoSync();
  322. const screenWidth = systemInfo.windowWidth;
  323. let scale = 1;
  324. if (lngDiff > 0) {
  325. scale = Math.log2((360 * screenWidth) / (lngDiff * 256 * Math.cos(centerLat * Math.PI / 180)));
  326. }
  327. const latScale = Math.log2((180 * screenWidth) / (latDiff * 256));
  328. scale = Math.min(scale, latScale);
  329. // 限制缩放范围(1-20)
  330. scale = Math.max(1, Math.min(20, Math.floor(scale)));
  331. // 更新地图配置
  332. this.setData({
  333. longitude: centerLng,
  334. latitude: centerLat,
  335. scale: scale
  336. });
  337. },
  338. /**
  339. * 生成所有点位的标记
  340. */
  341. generateAllMarkers(pointList) {
  342. if (!pointList || pointList.length === 0) {
  343. this.setData({ markers: [] });
  344. return;
  345. }
  346. // 生成标记数组
  347. const markers = pointList.map((item, index) => {
  348. // 构建标记弹窗内容
  349. let calloutContent = '';
  350. if (item.type === 'car') {
  351. calloutContent = `${item.carName || '储能车'}\n编号: ${item.controllerId || item.carId}\n状态: ${item.lineType === 1 ? '在线' : '离线'}`;
  352. } else if (item.type === 'station') {
  353. calloutContent = `${item.poiName || '购电站'}\n地址: ${item.addressName || '未知'}\n状态: ${item.addressDeletetype === 0 ? '在线' : '离线'}`;
  354. } else if (item.type === 'user') {
  355. calloutContent = `${item.poiName || '用电用户'}\n地址: ${item.addressName || '未知'}\n状态: ${item.addressDeletetype === 0 ? '在线' : '离线'}`;
  356. } else if (item.type === 'driver') {
  357. calloutContent = `${item.driverName || '司机'}\nID: ${item.driverId || item.id}\n状态: ${item.status === 0 ? '在线' : '离线'}`;
  358. }
  359. return {
  360. id: index + 1, // 唯一ID
  361. longitude: Number(item.longitude),
  362. latitude: Number(item.latitude),
  363. iconPath: this.data.markerIcons[item.type] || this.data.markerIcons.station, // 兜底图标
  364. width: 40,
  365. height: 40,
  366. anchor: { x: 0.5, y: 0.5 }, // 图标中心点对齐
  367. callout: {
  368. content: calloutContent,
  369. fontSize: 12,
  370. borderRadius: 8,
  371. bgColor: '#fff',
  372. padding: 8,
  373. display: 'BYCLICK',
  374. textAlign: 'left'
  375. },
  376. customData: item // 携带原始数据
  377. };
  378. });
  379. this.setData({ markers });
  380. },
  381. /**
  382. * 切换选项卡
  383. */
  384. switchType(e) {
  385. const type = e.currentTarget.dataset.type;
  386. this.setData({
  387. activeType: type,
  388. currentList: this.data.pointData[type] || []
  389. });
  390. },
  391. /**
  392. * 定位到指定点位
  393. */
  394. toPosition(e) {
  395. const item = e.currentTarget.dataset.item;
  396. if (!item || !item.longitude || !item.latitude || item.longitude === 0 || item.latitude === 0) {
  397. wx.showToast({
  398. title: '该点位无坐标信息',
  399. icon: 'none'
  400. });
  401. return;
  402. }
  403. // 定位到指定点位并放大
  404. this.setData({
  405. longitude: Number(item.longitude),
  406. latitude: Number(item.latitude),
  407. scale: 17
  408. });
  409. // 显示提示
  410. let title = '';
  411. if (item.type === 'car') title = `已定位到${item.carName || '储能车'}`;
  412. else if (item.type === 'station') title = `已定位到${item.poiName || '购电站'}`;
  413. else if (item.type === 'user') title = `已定位到${item.poiName || '用电用户'}`;
  414. else if (item.type === 'driver') title = `已定位到${item.driverName || '司机'}`;
  415. wx.showToast({
  416. title: title,
  417. icon: 'success',
  418. duration: 1200
  419. });
  420. },
  421. /**
  422. * 点击地图标记点
  423. */
  424. onMarkerTap(e) {
  425. const marker = this.data.markers.find(item => item.id === e.detail.markerId);
  426. if (marker) {
  427. this.setData({
  428. longitude: marker.longitude,
  429. latitude: marker.latitude,
  430. scale: 18
  431. });
  432. }
  433. },
  434. /**
  435. * 地图视野变化监听
  436. */
  437. onRegionChange(e) {
  438. if (e.type === 'end' && e.causedBy === 'drag') {
  439. this.setData({
  440. longitude: e.detail.centerLongitude,
  441. latitude: e.detail.centerLatitude,
  442. scale: e.detail.scale
  443. });
  444. }
  445. },
  446. /**
  447. * 查看详情
  448. */
  449. ondetails(e) {
  450. const item = e.currentTarget.dataset.item;
  451. console.log('查看详情:', item);
  452. // 根据类型跳转到不同详情页
  453. let url = '';
  454. if (item.type === 'car') {
  455. url = `/pages/car/index?id=${item.carId || item.id}&type=${item.type}`;
  456. } else if (item.type === 'station' || item.type === 'user') {
  457. url = `/pages/stationdetail/index?id=${item.addressId || item.id}&type=${item.type}`;
  458. } else if (item.type === 'driver') {
  459. url = `/pages/driverdetail/index?id=${item.operationId || item.id}&type=${item.type}`; // 新增司机详情页
  460. }
  461. if (url) {
  462. wx.navigateTo({ url });
  463. } else {
  464. wx.showToast({
  465. title: '暂无详情页面',
  466. icon: 'none'
  467. });
  468. }
  469. },
  470. onUnload() {
  471. // 页面卸载时清理WebSocket监听
  472. wx.$off('wsMessage', this.handleWsMessage);
  473. }
  474. });