Files
gjt_mini/pages/map/index.vue
2026-01-20 16:35:30 +08:00

2061 lines
66 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="content">
<u-sticky>
<view style="background-color: #fff">
<u-subsection
mode="subsection"
:list="list"
:current="current"
@change="sectionChange"
activeColor="#7ba746"
:fontSize="30"
>
</u-subsection>
<view class="searchBox">
<view class="item" v-if="current === 0">
<u-picker
:show="showPlateNumberPicker"
:columns="[truckList]"
keyName="name"
:immediateChange="true"
@confirm="confirmPlateNumber"
@cancel="showPlateNumberPicker = false"
>
</u-picker>
<u-input
border="surround"
:value="datas.plateNumber"
disabled
fontSize="26"
:disabledColor="'#ffffff'"
placeholder="车牌号"
@tap="searchPlatNumber"
>
</u-input>
</view>
<view class="item" v-else>
<u-picker
:show="showHydrogenPicker"
:columns="[hydrogenList]"
keyName="name"
:immediateChange="true"
@confirm="confirmHydrogen"
@cancel="showHydrogenPicker = false"
>
</u-picker>
<u-input
border="surround"
:value="datas.hydrogenStationName"
disabled
fontSize="26"
:disabledColor="'#ffffff'"
placeholder="加氢站"
@tap="searchHydrogen()"
>
</u-input>
</view>
<image
src="/static/detail.png"
style="width: 32px; height: 32px"
@tap="showPicker"
></image>
</view>
</view>
<ba-tree-picker
ref="treePicker"
:isShowOrgPicker="false"
@select-change="selectChange"
@emitOrgId="emitOrgId"
:title="` `"
:localdata="listData"
multiple
valueKey="id"
textKey="name"
childrenKey="children"
/>
<page-container
:show="checkListShow"
:duration="200"
:overlay="false"
@beforeleave="onBeforeLeave"
>
<!-- @afterShow="onAfterShow"
@afterHide="onAfterHide" -->
<view class="right-panel" @tap.native.stop="banIosChuanTou">
<view class="panel-header">
<view class="panel-title"
>该区域有以下{{ current === 0 ? "车辆" : "加氢站" }}
</view>
<view v-if="current === 0"
>当前数量:{{ _clusterSelList.length || 0 }}()</view
>
<view v-else>当前数量:{{ _clusterSelList.length || 0 }}()</view>
<view class="close-btn" @tap="checkListShow = false">
<u-icon name="close" color="#333" size="22"></u-icon>
</view>
</view>
<view v-if="current === 0" class="tableOption">
<view class="optionItem">
<!-- <view
class="item right-u-popup u-border"
style="border-radius: 4px"
>
<u-picker
:show="showOrgPicker"
:columns="[_orgList]"
keyName="nameAndCount"
@confirm="confirmOrg"
:immediateChange="true"
@cancel="showOrgPicker = false"
>
</u-picker>
<u-input
v-model="orgName"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
disabled
placeholder="请选择车辆主体"
@tap="showOrgPicker = true"
>
<template slot="suffix">
<view
class="close-btn"
v-if="orgName"
@tap.stop="clearClick"
>
<u-icon name="close" color="#333" size="20"></u-icon>
</view>
</template>
</u-input>
</view> -->
<view
class="item right-u-popup u-border"
style="border-radius: 4px"
>
<u-input
v-model="plateNumberInput"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
placeholder="请输入车牌号"
>
<template slot="suffix">
<view
class="close-btn"
v-if="plateNumberInput"
@tap.stop="clearNumberInput"
>
<u-icon name="close" color="#333" size="20"></u-icon>
</view>
</template>
</u-input>
</view>
<view
class="item right-u-popup u-border"
style="border-radius: 4px; flex: 1"
>
<u-picker
:show="showTruckTypePicker"
:columns="[_truckTypeList]"
keyName="nameAndCount"
@confirm="confirmTruckType"
:immediateChange="true"
@cancel="showTruckTypePicker = false"
>
</u-picker>
<u-input
v-model="truckTypeName"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
disabled
placeholder="请选择车辆型号"
@tap="showTruckTypePicker = true"
>
<template slot="suffix">
<view
class="close-btn"
v-if="truckTypeName"
@tap.stop="clearClickTruckType"
>
<u-icon name="close" color="#333" size="20"></u-icon>
</view>
</template>
</u-input>
</view>
</view>
<!-- <view class="optionItem">
<view
class="item right-u-popup u-border"
style="border-radius: 4px"
>
<u-picker
:show="showAreaPicker"
:columns="[_areaList]"
keyName="nameAndCount"
@confirm="confirmArea"
:immediateChange="true"
@cancel="showAreaPicker = false"
>
</u-picker>
<u-input
v-model="areaName"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
disabled
placeholder="请选择车辆地区代码"
@tap="showAreaPicker = true"
>
<template slot="suffix">
<view
class="close-btn"
v-if="areaName"
@tap.stop="clearClickArea"
>
<u-icon name="close" color="#333" size="20"></u-icon>
</view>
</template>
</u-input>
</view>
<view
class="item right-u-popup u-border"
style="border-radius: 4px"
>
<u-picker
:show="showDepartPicker"
:columns="[_departList]"
keyName="nameAndCount"
@confirm="confirmDepart"
:immediateChange="true"
@cancel="showDepartPicker = false"
>
</u-picker>
<u-input
v-model="departName"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
disabled
placeholder="请选择业务部门"
@tap="showDepartPicker = true"
>
<template slot="suffix">
<view
class="close-btn"
v-if="departName"
@tap.stop="clearClickDepart"
>
<u-icon name="close" color="#333" size="20"></u-icon>
</view>
</template>
</u-input>
</view>
</view> -->
<view class="optionItem">
<!-- 占位的空div保持布局一致性 -->
<view
v-if="
current === 0 &&
isMapResetForTruck &&
hasClickedBackRightForTruck
"
class="item"
style="flex: 1"
></view>
<view
v-if="
current === 0 &&
!isMapResetForTruck &&
!hasClickedBackRightForTruck
"
class="item"
style="display: flex; align-items: center"
>
全部车辆:
<u-switch
size="58"
activeColor="#2F6D47"
v-model="allTruckSwitch"
@change="changeSwitch"
></u-switch>
</view>
</view>
</view>
<view v-else class="tableOption" style="padding-top: 10px">
<view class="optionItem">
<view
class="item right-u-popup u-border"
style="border-radius: 4px"
>
<u-picker
:show="showCoopPicker"
:columns="[CoopList]"
keyName="dicName"
@confirm="confirmCoop"
:immediateChange="true"
@cancel="showCoopPicker = false"
>
</u-picker>
<u-input
v-model="CoopName"
border="surround"
:disabledColor="'#ffffff'"
style="font-size: 13px"
disabled
placeholder="请选择加氢站合作状态"
@tap="showCoopPicker = true"
>
<template slot="suffix">
<u-icon
v-if="CoopName"
name="close"
color="#bfc7d6"
size="50"
@tap.stop="clearClickCoop"
></u-icon>
</template>
</u-input>
</view>
<view
v-if="
current === 1 &&
!isMapResetForHydrogen &&
!hasClickedBackRightForHydrogen
"
class="item"
style="display: flex; align-items: center"
>
全部加氢站:
<u-switch
size="58"
activeColor="#2F6D47"
v-model="allHydrogenSwitch"
@change="changeSwitchHydrogen"
></u-switch>
</view>
</view>
</view>
<scroll-view
ref="scrollView"
scroll-y="true"
:scroll-top="scrollTop"
style="height: calc(100vh - 200px)"
@scrolltolower="loadMoreData"
@scroll="onScroll"
>
<view class="rightPop">
<view
v-if="current === 0"
style="
margin: 10px 0;
display: flex;
justify-content: space-between;
"
>
<view>里程单位(km)</view>
<view>
<view
style="
width: 10px;
height: 10px;
background-color: #ffd00e;
border-radius: 50%;
display: inline-block;
margin-right: 5px;
"
>
</view
>表示未对接车机数据</view
>
</view>
<u-row justify="space-between" gutter="10" v-if="current === 0">
<u-col span="3">
<view class="demo-layout">车牌</view>
</u-col>
<u-col span="3">
<view
class="demo-layout"
style="display: flex; align-items: center"
@tap="toggleMileageSort"
>
行驶里程
<text style="margin-left: 4px; font-size: 12px">{{
mileageSortOrder === "desc" ? "↓" : "↑"
}}</text>
</view>
</u-col>
<u-col span="3">
<view class="demo-layout">仪表盘</view>
</u-col>
<u-col span="3">
<view class="demo-layout">车型</view>
</u-col>
</u-row>
<view
v-for="(item, index) in virtualClusterList"
class="clusterItem"
:key="index"
>
<u-badge
v-if="current === 0"
class="dot"
:isDot="true"
:type="item.isOnline === '否' ? 'error' : 'success'"
></u-badge>
<u-badge
v-if="current === 1"
class="dot"
:isDot="true"
:type="item.cooperate ? 'success' : 'error'"
></u-badge>
<view style="display: flex" @tap="gotoDetail(item)">
<view class="item" style="padding-left: 5px">{{
current === 0 ? item.plateNumber : item.stationName
}}</view>
<view class="item" v-if="current === 0">{{
item.dayMileage || 0
}}</view>
<view class="item" v-if="current === 0">
<view v-if="item.totalMileage">{{
item.totalMileage
}}</view>
<view
v-else
style="
width: 10px;
height: 10px;
background-color: #ffd00e;
border-radius: 50%;
"
>
</view>
</view>
<view class="item" v-if="current === 0">{{
item.noticeModel || "--"
}}</view>
</view>
</view>
<!-- 虚拟滚动加载控制 -->
<view
v-if="
virtualClusterList.length > 0 &&
_clusterSelList.length > virtualScrollPageSize
"
class="load-more-controls"
>
<view class="load-more-info">
已加载 {{ virtualClusterList.length }} /
{{ _clusterSelList.length }} 条
</view>
<view v-if="virtualScrollHasMore" class="load-more-button">
<view
class="load-more-btn"
:class="{ loading: virtualScrollLoading }"
@tap="loadMoreData"
>
<text v-if="!virtualScrollLoading">加载更多</text>
<view v-else class="loading-content">
<text class="loading-text">加载中</text>
<text class="loading-dot">.</text>
<text class="loading-dot">.</text>
<text class="loading-dot">.</text>
</view>
</view>
</view>
<view v-else class="no-more-data"> 已加载全部数据 </view>
</view>
<!-- <view>查看详细分布</view> -->
</view>
</scroll-view>
</view>
</page-container>
<image
src="/static/reset.png"
style="
width: 26px;
height: 26px;
position: absolute;
left: 4px;
margin-top: 6px;
"
@tap="resetMap"
></image>
<image
src="/static/expand-left-line.png"
style="
position: absolute;
top: 45vh;
right: 4px;
width: 26px;
height: 26px;
"
@tap="backRight"
></image>
</u-sticky>
<!-- :style="{ display: checkListShow ? 'none' : 'block' }" 用来解决穿透问题的方法 但是会导致IOS定位到南极 -->
<view
class="page-section page-section-gap"
:style="{ visibility: checkListShow ? 'hidden' : 'visible' }"
>
<map
id="map"
style="width: 100%; height: calc(100vh - 116px)"
:markers="markers"
:latitude="latitude"
:longitude="longitude"
@tap="mapTap"
@markertap="markertap"
:scale="scale"
@regionchange="onRegionChange"
>
</map>
</view>
<!-- <cover-view class="popup_left"> </cover-view> -->
<cover-view class="popup" v-if="showPopup">
<cover-view class="popup-header">
<!-- <cover-view style="display: flex" :show-location="true"
><cover-image
:src="
current === 0 ? '/static/kachetou.png' : '/static/jiaqingzhan.png'
"
style="width: 40rpx; height: 40rpx; margin: 5px"
></cover-image
>1111</cover-view
> -->
<cover-view style="display: flex; padding: 5px; flex: 1">
<cover-image
:src="
current === 0 ? '/static/kachetou.png' : '/static/jiaqingzhan.png'
"
style="width: 40rpx; height: 40rpx; margin-right: 5px"
></cover-image>
<cover-view style="flex: 1">{{
currMarker.plateNumber || currMarker.shortName || currMarker.name
}}</cover-view>
<cover-image
v-if="current === 0"
:src="
currMarker.isOnline === '否'
? '/static/offline.png'
: '/static/online.png'
"
style="width: 40rpx; height: 40rpx; margin: 0 5px"
>
</cover-image>
<cover-view v-if="current === 0">{{
currMarker.isOnline === "否" ? "离线" : "在线"
}}</cover-view>
</cover-view>
<cover-view v-if="current === 0" style="display: flex; padding: 5px">
<cover-image
src="/static/hydrogen.png"
style="width: 36rpx; height: 36rpx; margin-right: 5px"
></cover-image>
<cover-view>{{ currMarker.remainHydrogen || 0 }}kg</cover-view>
<cover-image
src="/static/electricity.png"
style="width: 40rpx; height: 40rpx; margin: 0 5px 0 10px"
></cover-image>
<cover-view>{{ currMarker.soc || 0 }}%</cover-view>
</cover-view>
</cover-view>
<cover-view class="popup-content">
<cover-view style="display: flex; white-space: normal">
<u-icon
name="map"
size="45"
slot="active-icon"
color="#2F6D47"
></u-icon>
{{ currMarker.address || "" }}</cover-view
>
<cover-view class="content-items" v-if="current === 0">
<cover-view class="item">
<cover-view>总里程Km</cover-view>
<cover-view>{{ currMarker.totalMileage || 0 }}</cover-view>
</cover-view>
<cover-view class="item">
<cover-view>今日用氢Kg</cover-view>
<cover-view>{{ currMarker.todayHydrogen || 0 }}</cover-view>
</cover-view>
<cover-view class="item">
<cover-view>今日里程Km</cover-view>
<cover-view>{{ currMarker.todayMileage || 0 }}</cover-view>
</cover-view>
</cover-view>
<cover-view v-else>
<cover-view
class="content-items"
style="text-align: left"
v-if="currMarker.shortName"
>
<cover-view style="flex: 1; white-space: normal">
加氢站全称:{{ currMarker.name || "--" }}
</cover-view>
</cover-view>
<cover-view class="content-items" style="text-align: left">
<cover-view style="flex: 1">
氢源:{{ currMarker.hydrogenSource || "--" }}
</cover-view>
<cover-view style="flex: 1">
氢气价格:{{ currMarker.price + currMarker.priceUnit || "--" }}
</cover-view>
</cover-view>
<cover-view class="content-items" style="text-align: left">
<cover-view style="flex: 1">
站点状态:{{ currMarker.isOpenLabel || "--" }}
</cover-view>
<cover-view style="flex: 1">
营业时间:{{ currMarker.tradeTimeLabel || "--" }}
</cover-view>
</cover-view>
<cover-view class="content-items" style="text-align: left">
<cover-view style="flex: 1">
联系人:{{ currMarker.contact || "--" }}
</cover-view>
<cover-view style="flex: 1">
联系方式:{{ currMarker.tel || "--" }}
</cover-view>
</cover-view>
</cover-view>
</cover-view>
</cover-view>
<!-- <h3>常见应用</h3> :markers="covers"-->
<!-- <button @click="gotoMap">进入地图</button> -->
<tab-bar></tab-bar>
</view>
</template>
<script>
// import axios from "@/utils/request";
import { checkButtonPermission } from "@/utils/permission.js";
import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue";
export default {
options: {
styleIsolation: "shared", // 解除样式隔离
},
components: {
baTreePicker,
},
data() {
return {
listData: [],
id: 0, // 使用 marker点击事件 需要填写id
title: "map",
latitude: 34.15394,
scale: 4,
longitude: 108.56325,
truckIcon: "https://lnh2etest.oss-cn-shanghai.aliyuncs.com/truck25.png", //货车图标
hydrogenRefuelingStationIcon:
"https://lnh2etest.oss-cn-shanghai.aliyuncs.com/station25.png", //氢能加电站图标
_mapContext: null,
current: 0,
list: ["车辆", "加氢站"],
showPopup: false,
showLeftPopup: false,
currMarker: null,
popTimer: false,
showPlateNumberPicker: false,
showHydrogenPicker: false,
truckList: [],
hydrogenList: [],
datas: {
plateNumber: "",
truckId: "",
hydrogenStationName: "",
hydrogenStationId: "",
},
covers: [], //用于搜索
markers: [], //用户实现不渲染地图显示callout内容
shouldCluster: true,
isSearch: false, //是否搜索过, 搜过完缩放地图后刷新marker
//includePoints: [], //用来实现缩放 scale不好用 ##25.12.8更新 直接诶用_mapContext.includePoints效果更好
//privatyShow: false,
//showMarkers: [], //用于显示marker
checkListShow: false,
clusterSelList: [],
showOrgPicker: false, //是否显示主体选择器
orgList: [], //组织列表
orgName: "",
areaList: [],
areaName: "", //地区代码
showAreaPicker: false, //是否显示主体选择器
CoopList: [],
CoopName: "", //合作状态
CoopCode: "", //合作状态
showCoopPicker: false, //是否显示合作状态
plateNumberInput: "", //车牌号输入框
departList: [], //业务部门
departName: "", //业务部门
truckTypeList: [], //车辆类型
showDepartPicker: false, //是否业务部门选择器
showTruckTypePicker: false, //是否车辆型号选择器
truckTypeName: "", //车辆型号名称
showAllVehicles: false, //是否显示全部车辆
originalClusterList: [], //保存切换前的clusterSelList
mileageSortOrder: "desc", // 行驶里程排序方向desc-从大到小asc-从小到大
backRightTimer: null, // backRight方法的防抖定时器
allTruckSwitch: false, //是否显示全部车辆
allHydrogenSwitch: false, //是否显示全部加氢站
originalHydrogenList: [], //保存切换前的加氢站列表
virtualScrollPageSize: 150, // 虚拟滚动每页显示数量
virtualScrollCurrentPage: 1, // 虚拟滚动当前页码
virtualScrollTotalPages: 1, // 虚拟滚动总页数
virtualScrollLoading: false, // 是否正在加载下一页
virtualScrollHasMore: true, // 是否还有更多数据
scrollTop: 0, // 滚动位置
isMapResetForTruck: true, // 车辆是否为重置地图状态
isMapResetForHydrogen: true, // 加氢站是否为重置地图状态
hasClickedBackRightForTruck: false, // 车辆是否已经点击过backRight
hasClickedBackRightForHydrogen: false, // 加氢站是否已经点击过backRight
};
},
computed: {
chooseCompany() {
return checkButtonPermission(
"mapOrgSelect",
"vehicle" //按钮在基础信息菜单的车辆信息下面
);
},
// 虚拟滚动显示的数据
virtualClusterList() {
const endIndex =
this.virtualScrollCurrentPage * this.virtualScrollPageSize;
return this._clusterSelList.slice(0, endIndex);
},
// 虚拟滚动总页数
virtualScrollTotalPages() {
return Math.ceil(
this._clusterSelList.length / this.virtualScrollPageSize
);
},
// 是否还有更多数据
virtualScrollHasMore() {
return this.virtualClusterList.length < this._clusterSelList.length;
},
_showOrgPicker() {
return this.chooseCompany && this.current === 0;
},
_orgList() {
const arr = this.orgList.map((item) => {
const carNumber =
this.clusterSelList.filter((t) => {
return t.orgName == item.orgName;
})?.length || 0;
item.carNumber = carNumber;
item.nameAndCount = item.orgName + " (" + carNumber + ")";
return item;
});
return arr.filter((item) => item.carNumber) || [];
},
_departList() {
const arr = this.departList.map((item) => {
const carNumber =
this.clusterSelList.filter((t) => {
return (
item.dicName?.toString().indexOf(t.shortDepName) > -1 &&
t.shortDepName
);
})?.length || 0;
item.carNumber = carNumber;
item.nameAndCount = item.dicName + " (" + carNumber + ")";
return item;
});
return arr.filter((item) => item.carNumber) || [];
},
_truckTypeList() {
const arr = this.truckTypeList.map((item) => {
const carNumber =
this.clusterSelList.filter((t) => {
return t.noticeModel === item.dicName;
})?.length || 0;
item.carNumber = carNumber;
item.nameAndCount = item.dicName + " (" + carNumber + ")";
return item;
});
return arr.filter((item) => item.carNumber) || [];
},
_areaList() {
const arr = this.areaList.map((item) => {
const carNumber =
this.clusterSelList.filter((t) => {
return t.plateNumber?.toString().indexOf(item.dicName) > -1;
})?.length || 0;
item.carNumber = carNumber;
item.nameAndCount = item.dicName + " (" + carNumber + ")";
return item;
});
return arr.filter((item) => item.carNumber) || [];
},
_clusterSelList() {
const isCooperate = this.CoopCode == 1 ? true : false;
console.log(isCooperate);
let filteredList =
this.current === 0
? this.clusterSelList.filter(
(item) =>
(this.orgName === "" || item.orgName === this.orgName) &&
(this.areaName === "" ||
item.plateNumber?.toString().indexOf(this.areaName) > -1) &&
(this.departName === "" ||
this.departName?.toString().indexOf(item.shortDepName) > 0) &&
(this.truckTypeName === "" ||
item.noticeModel === this.truckTypeName) &&
(this.plateNumberInput === "" ||
item.plateNumber?.toString().indexOf(this.plateNumberInput) >
-1)
)
: this.clusterSelList.filter(
(item) => this.CoopName === "" || item.cooperate === isCooperate
);
// 按行驶里程排序(仅对车辆视图)
if (this.current === 0 && filteredList.length > 0) {
filteredList.sort((a, b) => {
const mileageA = parseFloat(a.dayMileage) || 0;
const mileageB = parseFloat(b.dayMileage) || 0;
// 根据排序方向决定排序方式
return this.mileageSortOrder === "desc"
? mileageB - mileageA // 从大到小
: mileageA - mileageB; // 从小到大
});
}
return filteredList;
},
},
onShow() {
console.log("onShow");
},
onPullDownRefresh(event) {},
mounted() {
console.log("mounted");
this.sectionChange(this.current);
this.getOrgList();
this.getAreaList();
this.getDepartList();
this.getTruckType();
this.getCoopList();
// this.getVehicleMarkers();
//this.gotoMap();
},
beforeDestroy() {
// 清理定时器,防止内存泄露
if (this.popTimer) {
clearTimeout(this.popTimer);
this.popTimer = null;
}
// 清理backRight防抖定时器
if (this.backRightTimer) {
clearTimeout(this.backRightTimer);
this.backRightTimer = null;
}
// 清理地图事件监听器
if (this._mapContext) {
// 直接移除所有监听器,不需要传递回调函数
try {
this._mapContext.off("markerClusterCreate");
this._mapContext.off("markerClusterClick");
} catch (e) {
console.log("移除地图事件监听器失败:", e);
}
this._mapContext = null;
}
},
methods: {
changeSwitch(e) {
console.log("change", e);
if (e) {
// 开启开关,保存当前数据并显示全部
this.originalClusterList = [...this.clusterSelList];
this.clusterSelList = [...this.covers];
this.virtualScrollCurrentPage = 1; // 重置到第一页
this.$nextTick(() => {
this.resetScrollPosition();
});
} else {
// 关闭开关,恢复原始数据
this.clusterSelList = [...this.originalClusterList];
this.virtualScrollCurrentPage = 1; // 重置到第一页
this.$nextTick(() => {
this.resetScrollPosition();
});
}
},
changeSwitchHydrogen(e) {
console.log("changeSwitchHydrogen", e);
if (e) {
// 开启开关,保存当前数据并显示全部
this.originalHydrogenList = [...this.clusterSelList];
this.clusterSelList = [...this.covers];
this.virtualScrollCurrentPage = 1; // 重置到第一页
this.$nextTick(() => {
this.resetScrollPosition();
});
} else {
// 关闭开关,恢复原始数据
this.clusterSelList = [...this.originalHydrogenList];
this.virtualScrollCurrentPage = 1; // 重置到第一页
this.$nextTick(() => {
this.resetScrollPosition();
});
}
},
// 滚动事件处理
onScroll(e) {
if (this.virtualScrollLoading || !this.virtualScrollHasMore) return;
const { scrollTop, scrollHeight, clientHeight } = e.detail;
// 当滚动到三分之二位置时触发加载
const threshold = scrollHeight * (2 / 3);
if (scrollTop + clientHeight >= threshold) {
this.loadMoreData();
}
},
// 加载更多数据
loadMoreData() {
if (this.virtualScrollLoading || !this.virtualScrollHasMore) return;
this.virtualScrollLoading = true;
// 模拟网络延迟,实际项目中可以移除
setTimeout(() => {
this.virtualScrollCurrentPage++;
this.virtualScrollLoading = false;
}, 300);
},
// 重置滚动位置到顶部
resetScrollPosition() {
// 先设置为非0值再设置为0确保触发滚动
this.scrollTop = 1;
this.$nextTick(() => {
this.scrollTop = 0;
});
},
banIosChuanTou() {
// 阻止iOS事件穿透到地图
console.log("阻止事件穿透");
},
// 切换行驶里程排序方向
toggleMileageSort() {
this.mileageSortOrder = this.mileageSortOrder === "desc" ? "asc" : "desc";
},
// page-container 离开前的处理
onBeforeLeave() {
this.checkListShow = false;
},
// page-container 显示后的处理
// onAfterShow() {
// // 弹窗显示后,地图已经隐藏,无需额外操作
// },
// // page-container 隐藏后的处理
// onAfterHide() {
// // 弹窗隐藏后,地图已经显示,可以重置地图状态
// // this.$nextTick(() => {
// // // 如果需要,可以在这里刷新地图
// // this.createMapContext();
// // });
// },
clearNumberInput() {
this.plateNumberInput = ""; // 重置车牌号输入框
},
clearClickDepart() {
this.departName = ""; // 重置业务部门
},
clearClickTruckType() {
this.truckTypeName = ""; // 重置车辆型号
},
clearClick() {
this.orgName = ""; // 重置组织名称
},
showOrgPickerFunc() {
this.showOrgPicker = true;
},
showAreaPickerFunc() {
this.showAreaPicker = true;
},
showDepartPickerFunc() {
this.showDepartPicker = true;
},
getOrgList() {
this.orgName = ""; // 重置组织名称
this.$api.map.getOrgsList().then((res) => {
console.log("res:\n", res);
const errList = ["羚牛总部", "嘉兴羚牛汽车服务有限公司"];
this.orgList =
res?.filter((item) => !errList.includes(item.orgName)) || [];
});
},
confirmOrg(e) {
console.log("confirmOrg:\n", e.value[0]);
this.orgName = e.value[0].orgName;
console.log(this.clusterSelList);
this.showOrgPicker = false;
},
clearClickArea() {
this.areaName = ""; //
},
getAreaList() {
this.areaName = ""; //
this.$api.map.getPlateAreaDic().then((res) => {
console.log("res:\n", res);
this.areaList = res || [];
});
},
getTruckType() {
this.truckTypeName = "";
this.$api.standbyVehicle.getTruckType().then((res) => {
this.truckTypeList = res || [];
});
},
getDepartList() {
this.departName = ""; //
this.$api.map.getOwnDepartDic().then((res) => {
console.log("res:\n", res);
this.departList = res || [];
});
},
confirmArea(e) {
console.log("confirmArea:\n", e.value[0]);
this.showAreaPicker = false;
this.areaName = e.value[0].dicName;
console.log(this.areaName);
},
confirmDepart(e) {
console.log("confirmDepart:\n", e.value[0]);
this.showDepartPicker = false;
this.departName = e.value[0].dicName;
console.log(this.areaName);
},
confirmTruckType(e) {
console.log("confirmTruckType:\n", e.value[0]);
this.showTruckTypePicker = false;
this.truckTypeName = e.value[0].dicName;
},
clearClickCoop() {
this.CoopName = "";
this.CoopCode = "";
},
getCoopList() {
this.CoopName = "";
this.CoopCode = "";
this.$api.map.getHydrogenCoopDic().then((res) => {
console.log("res:\n", res);
this.CoopList = res || [];
});
},
confirmCoop(e) {
this.CoopName = e.value[0].dicName;
this.CoopCode = e.value[0].dicCode;
this.showCoopPicker = false;
},
resetMap() {
this.isMapResetForTruck = true;
this.isMapResetForHydrogen = true;
this.hasClickedBackRightForTruck = false;
this.hasClickedBackRightForHydrogen = false;
this.sectionChange(this.current, {});
},
backRight() {
// 防抖处理
if (this.backRightTimer) {
clearTimeout(this.backRightTimer);
}
this.backRightTimer = setTimeout(() => {
this.executeBackRight();
}, 300);
},
executeBackRight() {
if (!this.clusterSelList || this.clusterSelList.length === 0) {
this.clusterSelList = this.covers;
}
// 如果是重置地图后第一次点击backRight隐藏对应的switch
if (
this.current === 0 &&
this.isMapResetForTruck &&
!this.hasClickedBackRightForTruck
) {
this.hasClickedBackRightForTruck = true;
} else if (
this.current === 1 &&
this.isMapResetForHydrogen &&
!this.hasClickedBackRightForHydrogen
) {
this.hasClickedBackRightForHydrogen = true;
}
this.checkListShow = true;
this._mapContext.includePoints({
points: this.clusterSelList,
padding: [50, 50, 50, 50],
});
this.showPopup = false; //关闭底部弹窗
this.resetScrollPosition(); // 重置滚动位置
// if (this.clusterSelList && this.clusterSelList.length > 0) {
// //this.includePoints = this.clusterSelList; //返回聚合点视图
// this.checkListShow = true;
// this._mapContext.includePoints({
// points: this.clusterSelList,
// padding: [50, 50, 50, 50],
// });
// this.showPopup = false; //关闭底部弹窗
// }
},
// 显示选择器
async showPicker() {
this.showPopup = false;
await this.getInfoTree();
this.$refs.treePicker._initTree();
this.$refs.treePicker._show();
if (this._showOrgPicker) this.$refs.treePicker.getOrgList();
},
//监听选择ids为数组
selectChange(obj) {
//cityFilter
this.sectionChange(this.current, obj);
},
zoomIn(single = null) {
//single为车牌/加氢站搜索功能 不传就是城市搜索
// 通过扩大或缩小 include-points 的范围来控制缩放
// const scale = this.scale * 0.01; // 缩放因子
// const latDelta = 0.01 * scale;
// const lngDelta = 0.01 * scale;
// this.includePoints = single ? [single] : this.covers;
this._mapContext.includePoints({
points: single ? [single] : this.covers,
padding: [50, 50, 50, 50],
});
},
onRegionChange(e) {
console.log(e);
if (e.type === "end") {
// 获取最新的缩放级别
const newScale = e.detail.scale;
console.log("新的缩放级别:", newScale);
// 根据缩放级别决定是否需要聚合
// 更新markers
console.log(newScale);
// if (
// //(this.shouldCluster && newScale < 18) ||
// !this.shouldCluster &&
// newScale >= 18
// ) {
// this.shouldCluster = newScale < 18 ? true : false;
// } else {
// this.shouldCluster = newScale < 18 ? true : false;
// }
if (
//(this.shouldCluster && newScale < 18) ||
this.shouldCluster &&
newScale > 18
) {
this.shouldCluster = false;
} else {
//&& newScale > 14
if (this.isSearch && newScale < 15) {
this.shouldCluster = true;
console.log("onRegionChange------------addMarkers");
//this.addMarkers();
this.markers = this.markers.map((item) => {
item.joinCluster = true;
if (item.id == this.currMarker.hashCode) {
item.callout.display = "ALWAYS";
} else {
item.callout.display = "BYCLICK";
}
return item;
});
this.isSearch = false;
}
// this.createMapContext();
// this.addMarkers();
}
}
},
emitOrgId(id = "") {
this.getInfoTree(id);
},
async getInfoTree(id = "") {
if (this.current === 0) {
await this.$api.map.getTruckInfoTree({ orgId: id }).then((res) => {
console.log("res:\n", res);
this.listData = res || [];
if (id && (!res || res.length === 0)) {
uni.showToast({
title: "该主体下无车辆",
icon: "none",
duration: 1500,
});
}
});
} else {
await this.$api.map.getStationInfoTree().then((res) => {
console.log("res:\n", res);
this.listData = res || [];
});
}
// this.listData = [
// {
// id: 1,
// name: "公司1",
// children: [
// {
// id: 11,
// name: "研发部",
// children: [
// {
// id: 111,
// name: "张三",
// },
// {
// id: 112,
// name: "李四",
// },
// ],
// },
// {
// id: 12,
// name: "综合部",
// },
// ],
// },
// ];
},
getHydrogenStationList(name) {
this.showPopup = false;
this.$api.map.getHydrogenList({ stationName: name }).then((res) => {
console.log("res:\n", res);
this.hydrogenList = res || [];
this.showHydrogenPicker = true;
});
},
confirmHydrogen(e) {
console.log("truckInfo:\n", e.value[0]);
this.datas.hydrogenStationId = e.value[0].id;
this.datas.hydrogenStationName = e.value[0].name;
this.showHydrogenPicker = false;
this.clusterSelList = []; //清除刷新按钮状态,不显示右侧数据
this.gotoMarker();
},
searchPlatNumber() {
console.log(`searchPlatNumber`);
//this.privatyShow = true;
uni.showModal({
title: "车牌号关键字",
confirmText: "搜索",
editable: true,
placeholderText: "请输入车牌号关键字用于检索",
success: (res) => {
res.confirm && this.queryAuthListByPlateNumber(res.content);
},
});
},
searchHydrogen() {
uni.showModal({
title: "加氢站名称关键字",
confirmText: "搜索",
editable: true,
placeholderText: "请输入加氢站名称关键字用于检索",
success: (res) => {
res.confirm && this.getHydrogenStationList(res.content);
},
});
},
queryAuthListByPlateNumber(plateNumber) {
this.$api.map.getAllplateNumbere({ plateNumber }).then((res) => {
console.log("res:\n", res);
this.truckList = res || [];
this.showPopup = false;
this.showPlateNumberPicker = true;
});
},
async confirmPlateNumber(e) {
console.log("truckInfo:\n", e.value[0]);
this.datas.truckId = e.value[0].id;
this.datas.plateNumber = e.value[0].name;
this.showPopup = false;
this.showPlateNumberPicker = false;
this.clusterSelList = []; //清除刷新按钮状态,不显示右侧数据
this.gotoMarker();
},
gotoDetail(item) {
console.log("item:\n", item);
if (this.current === 0) {
this.datas.truckId = item.id;
} else {
this.datas.hydrogenStationId = item.id;
}
this.gotoMarker();
this.checkListShow = false;
},
async gotoMarker() {
const obj =
this.current === 0
? this.covers.find((item) => item.id == this.datas.truckId)
: this.covers.find((item) => item.id == this.datas.hydrogenStationId);
if (!obj) {
console.log("123123");
console.log(this.datas);
console.log(this.covers);
uni.showToast({
title:
this.current === 0
? "该车辆不在当前区域内"
: "该站点不在当前区域内",
icon: "none",
duration: 1500,
});
return;
}
//this.showMarkers = [obj];
// this._mapContext.moveToLocation({
// latitude: Number(obj.latitude),
// longitude: Number(obj.longitude),
// });
this.latitude = Number(obj.latitude);
this.longitude = Number(obj.longitude);
this.zoomIn({ latitude: this.latitude, longitude: this.longitude });
this.scale = 19;
this.onRegionChange({ type: "end", detail: { scale: 19 } });
this.markertap(
{
detail: { markerId: obj.hashCode },
}
// true //用下刷新marker 2025.9.23重构 直接用markers map刷新 不用重新渲染了
);
},
mapTap(row) {
console.log(`mapTap-----------------------------`);
console.log(row);
// console.log(this.currMarker);
// if (
// this.currMarker &&
// this.currMarker.latitude > row.detail.latitude - 1 &&
// this.currMarker.latitude < row.detail.latitude + 1 &&
// this.currMarker.longitude > row.detail.longitude - 1 &&
// this.currMarker.longitude < row.detail.longitude + 1
// ) {
// return;
// }
//为了防止马上隐藏掉popup所以加了一个定时器
if (this.popTimer) {
return;
}
this.showPopup = false;
},
async markertap(row) {
// isUpdate = false
console.log(`markertap#################`);
console.log(row);
this.showPopup = true;
this.popTimer = true;
const currRow =
this.covers.find((item) => item.hashCode == row.detail.markerId) || {};
console.log(currRow);
if (this.current === 0) {
await this.$api.map
.getVehicleDetail({ id: currRow?.id })
.then((response) => {
this.currMarker = response || {};
console.log("currMarker:\n", this.currMarker);
});
} else {
await this.$api.map
.getHydrogenDetail({ id: currRow?.id })
.then((response) => {
this.currMarker = response || {};
console.log("currMarker:\n", this.currMarker);
});
}
const index = this.markers.findIndex((m) => m.id === row.detail.markerId);
this.$set(this.markers, index, {
...this.markers[index],
joinCluster: false,
callout: {
...this.markers[index].callout,
display: "ALWAYS", // 设置为 ALWAYS 显示
color: "#7ba746",
},
});
// const cMarker =
// this.covers.filter((item) => item.hashCode == row.detail.markerId) &&
// this.covers.filter((item) => item.id == row.detail.markerId).length ===
// 1
// ? this.covers.filter((item) => item.id == row.detail.markerId)[0]
// : {};
Object.assign(this.currMarker, currRow);
//获取地址翻译
await this.getAddressByLocation();
//为了实现点击地图空白关闭详情加了定时器
// if (isUpdate) { //都不用重新this.addMarkers()渲染了。 直接makrers.map就行了。。。
// console.log("markertap--------------------addMarkers");
// this.addMarkers(); //为了显示当前点击的marker需要重新渲染整个markers 放在regionchagne里
// }
// 清理之前的定时器,防止重复创建
if (this.popTimer) {
clearTimeout(this.popTimer);
}
this.popTimer = setTimeout(() => {
this.popTimer = null;
this.isSearch = true;
}, 1000);
},
// 在需要的地方导入必要的模块
async getAddressByLocation() {
const { latitude, longitude } = this.currMarker;
this.$api.map.getAddress({ longitude, latitude }).then((res) => {
console.log(res?.data);
this.currMarker.address = res?.data ?? "--";
});
// const key = "GZVBZ-NFU6T-3KKXM-VXORH-ALOT7-AKFBH"; // 替换为你的实际密钥
// const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${key}`;
// try {
// const response = await uni.request({
// url: url,
// method: "GET",
// });
// console.log(response);
// if (response.statusCode === 200) {
// // 请求成功
// console.log(response.data.result.address);
// this.currMarker.address = response.data.result.address;
// // return response[1].data.result.address;
// } else {
// console.error("获取地址失败");
// }
// } catch (error) {
// console.error("请求出错:", error);
// }
},
async sectionChange(index, params = undefined) {
this.clusterSelList = []; //清除刷新按钮右侧列表状态
this.current = index;
this.showPopup = false;
this.datas = {
plateNumber: "",
truckId: "",
hydrogenStationName: "",
hydrogenStationId: "",
};
// 重置switch状态
this.allTruckSwitch = false;
this.allHydrogenSwitch = false;
// 重置对应视图的首次点击状态
if (index === 0) {
this.isMapResetForTruck = true;
this.hasClickedBackRightForTruck = false;
} else {
this.isMapResetForHydrogen = true;
this.hasClickedBackRightForHydrogen = false;
}
let obj = params || undefined;
if (index === 0) {
await this.getVehicleMarkers(obj);
} else {
await this.getHydrogenStationMarkers(obj);
}
},
createMapContext() {
// 清理之前的地图上下文,防止重复创建
if (this._mapContext) {
try {
this._mapContext.off("markerClusterCreate");
this._mapContext.off("markerClusterClick");
} catch (e) {
console.log("移除地图事件监听器失败:", e);
}
this._mapContext = null;
}
// 创建地图对象
this._mapContext = uni.createMapContext("map", this);
// 仅调用初始化,才会触发 on.("markerClusterCreate", (e) => {})
this._mapContext.initMarkerCluster({
// 初始化点聚合的配置 文档https://developers.weixin.qq.com/miniprogram/dev/api/media/map/MapContext.initMarkerCluster.html
enableDefaultStyle: false, // 是否使用默认样式
zoomOnClick: true, //点击已经聚合的标记点时是否实现聚合分离
gridSize: 60, //聚合算法的可聚合距离,即距离小于该值的点会聚合至一起,以像素为单位
complete(res) {
console.log("initMarkerCluster", res);
},
});
// 新的聚合簇产生时触发 缩放或拖动导致新的聚合簇产生时触发,仅返回新创建的聚合簇信息
//https://developers.weixin.qq.com/miniprogram/dev/api/media/map/MapContext.on.html
this._mapContext.on("markerClusterCreate", (e) => {
let clusterMarkers = [];
const clusters = e.clusters; // 新产生的聚合簇
clusters.forEach((cluster, index) => {
const {
center, // 聚合点的经纬度数组
clusterId, // 聚合簇id
markerIds, // 已经聚合了的标记点id数组
} = cluster;
let color = "#419afcD9";
if (markerIds.length > 100) {
color = "#b700ffD9";
} else if (markerIds.length > 10) {
color = "#ffbf00D9";
}
let clusterObj = {
clusterId, //必须
...center,
width: 0,
height: 0,
iconPath: "",
label: {
// 定制聚合簇样式
content: markerIds.length + "",
fontSize: 16,
color: "#fff",
width: 50,
height: 50,
bgColor: color,
borderRadius: 25,
textAlign: "center",
anchorX: -0,
anchorY: -25,
},
};
clusterMarkers.push(clusterObj);
});
// 添加聚合簇
this._mapContext.addMarkers({
markers: clusterMarkers,
clear: false, //是否先清空地图上所有的marker
});
});
this._mapContext.on("markerClusterClick", (res) => {
this.clearNumberInput();
console.log("点击聚合簇", res);
// this._mapContext.getScale({
// success: (res) => {
// console.log("缩放级别", res.scale);
// this.scale = res.scale;
// },
// });
this.showPopup = false; //底部pop
this.checkListShow = true; //右侧pop
if (this.current === 0) {
//点击聚合簇时,清除筛选条件
this.orgName = "";
this.areaName = "";
this.truckTypeName = "";
this.allTruckSwitch = false; // 重置显示全部开关
} else {
this.CoopName = "";
this.CoopCode = "";
this.allHydrogenSwitch = false; // 重置显示全部加氢站开关
}
const numCluster = res.cluster.markerIds.map((item) => Number(item));
this.clusterSelList =
this.covers.filter((item) => numCluster.includes(item.hashCode)) ||
[];
// 重置switch状态因为现在有具体的clusterSelList了
this.allTruckSwitch = false;
this.allHydrogenSwitch = false;
// 设置为非重置地图状态,只重置当前视图的状态
if (this.current === 0) {
this.isMapResetForTruck = false;
this.hasClickedBackRightForTruck = false;
} else {
this.isMapResetForHydrogen = false;
this.hasClickedBackRightForHydrogen = false;
}
this.virtualScrollCurrentPage = 1; // 重置到第一页
this.resetScrollPosition(); // 重置滚动位置
console.log("聚合簇点击", this.clusterSelList);
});
},
// 调接口获取所有点标记经纬度
// 添加点标记
addMarkers() {
console.log(
"addMarkers----------------------------------------------=--"
);
let markers = [];
let iconPath = "";
let calloutText = "";
console.log("this.shouldCluster", this.shouldCluster);
console.log(this.shouldCluster);
console.log("this.covers", this.covers);
this.covers.forEach((item) => {
//根据点位类型不同定义不同的标记icon
switch (item.type) {
case "1":
iconPath =
item.isOnline === "否"
? `/static/mapcar2.png`
: `/static/mapcar.png`;
calloutText = item.plateNumber;
break;
case "2":
//iconPath = this.hydrogenRefuelingStationIcon;
iconPath = item.cooperate
? `/static/maph.png`
: `/static/maph2.png`;
calloutText = item.shortName || item.stationName;
break;
}
// let flag = false;
// if (this.currMarker && item.hashCode === this.currMarker.hashCode) {
// flag = true;
// console.log("currFlag=true", item); 不通过addMarkers改callout-display-ALWAYS了 直接用$set makrers
// }
let markerObj = {
width: 25,
height: 25,
id: item.hashCode,
iconPath,
latitude: Number(item.latitude),
longitude: Number(item.longitude),
joinCluster: this.shouldCluster, // 产生聚合簇,需添加该属性
callout: {
content: calloutText,
// color: flag ? "#7ba746" : "#000",
color: "#000",
fontSize: 12,
borderRadius: 5,
bgColor: "#fff",
padding: 5,
display: "BYCLICK", // 或 'BYCLICK'
// display: flag ? "ALWAYS" : "BYCLICK", // 或 'BYCLICK'
},
//title: item.plateNumber,
zIndex: 9999,
anchor: {
x: 0.5,
y: 1,
},
};
const newMarker = Object.assign({}, markerObj);
markers.push(newMarker);
});
this.markers = markers; //为了渲染callout
this._mapContext.addMarkers({
markers,
clear: true, // 是否先清空地图上所有marker
});
},
async getHydrogenStationMarkers(params = undefined) {
await this.$api.map.getHydrogenStationMarkers(params).then((response) => {
console.log("res:\n", response);
let arr = response.filter(
(item) =>
item.latitude > -90 &&
item.latitude < 90 &&
item.longitude > -180 &&
item.longitude < 180
);
// console.log(arr.filter((item) => item.id == 568809102995525));
// const tempType = this.current === 0 ? "1" : "2";
// this.covers = arr.filter((item) => item.type === tempType);
this.covers = arr.map((item) => {
item.hashCode = Number(item.hashCode);
item.type = "2";
return item;
}); //接口重写不用前端过滤了
if (params) {
console.log("如果是区域搜索重置地图视野");
if (this.covers && this.covers.length === 1) {
this.gotoDetail(this.covers[0]); //如果是一个加氢站走gotoMarker
// this.gotoDetail(params.cityFilter[0]); //如果是一个加氢站走gotoMarker
} else {
this.zoomIn();
}
} else {
this.latitude = 34.15394;
this.longitude = 108.56325;
this.scale = 4; //缩放
}
//this.showMarkers = [...this.covers];
console.log("arr", arr);
this.createMapContext();
this.addMarkers();
});
},
async getVehicleMarkers(params = undefined) {
await this.$api.map.getVehicleMarkers(params).then((response) => {
console.log("res:\n", response);
let arr =
response && response.length > 0
? response.filter(
(item) =>
item.latitude > -90 &&
item.latitude < 90 &&
item.longitude > -180 &&
item.longitude < 180
)
: [];
// console.log(arr.filter((item) => item.id == 568809102995525));
// const tempType = this.current === 0 ? "1" : "2";
// this.covers = arr.filter((item) => item.type === tempType);
this.covers = arr.map((item) => {
item.hashCode = Number(item.hashCode);
item.type = "1";
return item;
}); //接口重写不用前端过滤了
if (params) {
//如果是区域搜索重置地图视野
console.log("如果是区域搜索重置地图视野");
if (this.covers && this.covers.length === 1) {
this.gotoDetail(this.covers[0]); //如果是一辆车走gotoMarker
} else {
this.zoomIn();
}
} else {
this.latitude = 34.15394;
this.longitude = 108.56325;
this.scale = 4; //缩放
}
//this.showMarkers = [...this.covers];
console.log("getVehicleMarkers----------addMarkers", arr);
this.createMapContext();
this.addMarkers();
});
// axios
// .post(`http://47.99.166.38:20000/VehicleDataActual/getVehicleMarkers`)
// .then((response) => {
// //let arr = response.slice(0, 100);
// let arr = response.filter(
// (item) =>
// item.latitude > -90 &&
// item.latitude < 90 &&
// item.longitude > -180 &&
// item.longitude < 180
// );
// // console.log(arr.filter((item) => item.id == 568809102995525));
// const tempType = this.current === 0 ? "1" : "2";
// this.covers = arr.filter((item) => item.type === tempType);
// console.log("arr", arr);
// this.createMapContext();
// this.addMarkers();
// // this.covers = arr.map((item) => {
// // item.iconPath =
// // item.type == 2
// // ? this.hydrogenRefuelingStationIcon
// // : this.truckIcon;
// // item.width = 25;
// // item.height = 25;
// // item.joinCluster = item.type == 1 ? true : false;
// // return item;
// // });
// // console.log(this.covers);
// });
// this.hMarkers = HM;
},
// gotoMap() {
// uni.navigateTo({
// url: `/pages/webview/index?url=http://192.168.130.136:3000/baiduMap`,
// success: () => {},
// fail: (err) => {
// console.log("Failed to navigate back:", err);
// },
// });
// },
},
};
</script>
<style lang="less" scoped>
.banner {
height: 30vh;
width: 100%;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.login-btn {
margin: 30rpx 0rpx;
}
.wexin-but::after {
border: unset !important;
}
.wexin-but {
border: unset !important;
border-radius: unset;
box-sizing: unset;
background-color: transparent;
padding-left: 0px;
padding-right: 0px;
}
</style>
<style lang="less" scoped>
/deep/ .right-u-popup.u-border {
border-width: 1rpx !important;
border-color: #d4c7c7 !important;
border-style: solid !important;
}
/deep/.u-picker__view {
height: 200px !important;
}
/deep/ .u-popup .uicon-close {
font-size: 25px !important;
}
/* 解决iOS点击穿透问题 */
/deep/ .u-popup__content {
background-color: #fff;
position: relative;
z-index: 9999;
}
/* page-container 右侧面板样式 */
.right-panel {
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100vh;
background-color: #fff;
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
z-index: 999;
display: flex;
flex-direction: column;
transition: transform 0.3s ease-in-out;
transform: translateX(0);
pointer-events: auto;
}
/* 页面区域过渡效果 */
.page-section {
transition: opacity 0.2s ease-in-out;
}
.panel-header {
padding: 15px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
}
.close-btn {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: #f5f5f5;
}
.panel-title {
font-size: 16px;
font-weight: bold;
color: #333;
display: flex;
justify-content: space-between;
}
.tableOption {
display: flex;
flex-direction: column;
gap: 10px;
padding: 0 10px;
.optionItem {
display: flex;
gap: 10px;
.item {
flex: 1;
}
}
}
.rightPop {
padding: 0 15px 30px 25px;
// .demo-layout {
// margin-top: 15px;
// }
.clusterItem {
padding: 5px 0;
margin: 7px 0;
position: relative;
background-color: #f2f1f6;
/deep/ .u-badge--success {
background-color: #7ba746 !important;
}
/deep/ .u-badge--dot {
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -12px;
}
.item {
flex: 1;
display: inline-block;
// max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
}
}
}
.content {
background: #e1eae5;
height: calc(100vh - 50px);
// /deep/ .u-tabbar-item {
// padding-bottom: 19px;
// }
.searchBox {
display: flex;
.item {
flex: 1;
}
}
// .popup_left {
// position: absolute;
// background-color: white;
// height: 500px;
// width: 100%;
// left: 0;
// bottom: 0;
// border-radius: 5px;
// box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
// }
.popup {
position: absolute;
background-color: white;
height: 200px;
width: 100%;
left: 0;
bottom: 0;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
.popup-header {
color: #fff;
line-height: 30px;
display: flex;
justify-content: space-between;
background-color: #7ba746;
}
.popup-content {
display: flex;
flex-direction: column;
padding: 10rpx;
.content-items {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
text-align: center;
margin: 8rpx;
font-size: 24rpx;
.item {
flex: 1;
margin: 10rpx 10rpx 0;
padding: 20rpx 0;
border: 1px solid #7ba746;
font-size: 28rpx;
border-radius: 20rpx;
}
}
}
}
// 虚拟滚动加载样式
.load-more-controls {
display: flex;
flex-direction: column;
align-items: center;
padding: 12px 0;
background-color: #f8f9fa;
border-top: 1px solid #e9ecef;
.load-more-info {
font-size: 12px;
color: #999;
margin-bottom: 8px;
}
.load-more-button {
.load-more-btn {
padding: 6px 20px;
font-size: 12px;
background-color: #f0f0f0;
color: #666;
border-radius: 15px;
border: none;
transition: all 0.3s ease;
&.loading {
background-color: #f0f0f0;
color: #999;
.loading-content {
display: flex;
align-items: center;
.loading-text {
margin-right: 2px;
}
.loading-dot {
animation: loadingDot 1.4s infinite ease-in-out both;
&:nth-child(2) {
animation-delay: -0.32s;
}
&:nth-child(3) {
animation-delay: -0.16s;
}
}
}
}
&:active {
background-color: #e0e0e0;
transform: scale(0.98);
}
}
}
.no-more-data {
font-size: 12px;
color: #bbb;
padding: 6px 0;
}
}
@keyframes loadingDot {
0%,
80%,
100% {
opacity: 0.3;
}
40% {
opacity: 1;
}
}
}
</style>