显示周边加氢站
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 去除高德默认的 label 边框和背景 */
|
||||
/* 去除高德默认的 label 边框 and 背景 */
|
||||
.amap-marker-label {
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
@@ -221,6 +221,7 @@
|
||||
var currentLat, currentLng;
|
||||
var isTruckMode = false;
|
||||
var isInitialLocationSet = false;
|
||||
var stationMarkers = []; // 存储所有站点的标记
|
||||
|
||||
|
||||
function initMap() {
|
||||
@@ -336,6 +337,8 @@
|
||||
fetchStationInfo(addressComponent.province, addressComponent.city,
|
||||
addressComponent.district, lat, lng);
|
||||
|
||||
fetchStationInfoList(lat, lng);
|
||||
|
||||
// 策略1: 优先使用最近的、类型合适的POI的名称
|
||||
if (pois && pois.length > 0) {
|
||||
// 查找第一个类型不是“商务住宅”或“地名地址信息”的POI,这类POI通常是具体的建筑或地点名
|
||||
@@ -397,7 +400,6 @@
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
// "asoco-token": "e28eada8-4611-4dc2-a942-0122e52f52da"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
province: province,
|
||||
@@ -437,6 +439,73 @@
|
||||
.catch(err => console.error('JS->:获取站点信息失败:', err));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点列表
|
||||
*/
|
||||
function fetchStationInfoList(lat, lng) {
|
||||
fetch('https://beta-esg.api.lnh2e.com/appointment/station/getNearbyHydrogenStationsByLocation', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
longitude: lng,
|
||||
latitude: lat,
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('网络响应错误: ' + response.status);
|
||||
}
|
||||
return response.json(); // 解析 JSON
|
||||
})
|
||||
.then(res => {
|
||||
console.log("JS->:2 接口完整返回:", JSON.stringify(res));
|
||||
if (res.code === 0 && res.data && Array.isArray(res.data)) {
|
||||
// 1. 清除旧的站点标记
|
||||
stationMarkers.forEach(m => m.setMap(null));
|
||||
stationMarkers = [];
|
||||
|
||||
// 2. 循环标记所有加氢站
|
||||
res.data.forEach(station => {
|
||||
var stationIcon = new AMap.Icon({
|
||||
size: new AMap.Size(32, 32),
|
||||
image: 'ic_tag.png',
|
||||
imageSize: new AMap.Size(32, 32)
|
||||
});
|
||||
|
||||
var sMarker = new AMap.Marker({
|
||||
map: map,
|
||||
position: [station.longitude, station.latitude],
|
||||
icon: stationIcon,
|
||||
offset: new AMap.Pixel(-16, -32),
|
||||
title: station.name,
|
||||
label: {
|
||||
content: '<div class="custom-bubble">' + station.name + '</div>',
|
||||
direction: 'top'
|
||||
}
|
||||
});
|
||||
|
||||
// 3. 绑定点击事件:选中即为目的地,并开始规划
|
||||
sMarker.on('click', function() {
|
||||
document.getElementById('endInput').value = station.address || station.name;
|
||||
// 更新当前的 destMarker (如果需要)
|
||||
if (destMarker) destMarker.setMap(null);
|
||||
destMarker = sMarker;
|
||||
|
||||
startRouteSearch();
|
||||
});
|
||||
|
||||
stationMarkers.push(sMarker);
|
||||
});
|
||||
|
||||
} else {
|
||||
console.log("JS->: 业务报错或无数据:", res.message);
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('JS->:获取站点信息失败:', err));
|
||||
}
|
||||
|
||||
/**
|
||||
* 地理编码并在地图标记终点
|
||||
*/
|
||||
@@ -447,7 +516,6 @@
|
||||
if (destMarker) destMarker.setMap(null);
|
||||
|
||||
// 2. 创建自定义图标
|
||||
// 假设图标大小为 32x32,你可以根据实际图片尺寸调整 Size
|
||||
var destIcon = new AMap.Icon({
|
||||
size: new AMap.Size(32, 32), // 图标尺寸
|
||||
image: 'ic_tag.png', // 本地图片路径
|
||||
@@ -459,8 +527,6 @@
|
||||
map: map,
|
||||
position: [longitude, latitude],
|
||||
icon: destIcon, // 使用自定义图标
|
||||
// 偏移量:如果图标底部中心是尖角,offset 设为宽的一半的负数,高度的负数
|
||||
// 这样能确保图片的底部尖端指向地图上的精确位置
|
||||
offset: new AMap.Pixel(-16, -32),
|
||||
title: name,
|
||||
label: {
|
||||
@@ -469,17 +535,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 4. 打印调试信息
|
||||
console.log("JS->: 终点标记已添加", address, loc.toString());
|
||||
|
||||
// 5. 自动调整视野包含起点和终点
|
||||
// if (marker) {
|
||||
// // 如果起点标志已存在,缩放地图以展示两者
|
||||
// map.setFitView([marker, destMarker], false, [60, 60, 60, 60]);
|
||||
// } else {
|
||||
// // 如果没有起点,直接跳到终点
|
||||
// map.setCenter(loc);
|
||||
// }
|
||||
console.log("JS->: 终点标记已添加", address);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,40 +579,34 @@
|
||||
document.getElementById('startInput').blur();
|
||||
document.getElementById('endInput').blur();
|
||||
|
||||
// --- 构造路径规划的点 (使用数组方式,更灵活) ---
|
||||
// --- 构造路径规划的点 ---
|
||||
var points = [];
|
||||
|
||||
// 1. 处理起点逻辑
|
||||
// 如果输入框是空的,或者写着 "我的位置",则使用 GPS 坐标
|
||||
if (!startKw || startKw === '我的位置') {
|
||||
if (!startKw || startKw === '我的位置' || startKw.includes('当前位置')) {
|
||||
if (!currentLng || !currentLat) {
|
||||
// 如果还没获取到定位
|
||||
if (window.flutter_inappwebview) {
|
||||
window.flutter_inappwebview.callHandler('requestLocation');
|
||||
}
|
||||
alert("正在获取定位,请稍后...");
|
||||
return;
|
||||
}
|
||||
// 使用精准坐标对象 (避免高德去猜 '我的位置' 关键词)
|
||||
points.push({
|
||||
keyword: '我的位置', // 用于显示的名字
|
||||
location: new AMap.LngLat(currentLng, currentLat) // 实际导航用的坐标
|
||||
keyword: '我的位置',
|
||||
location: new AMap.LngLat(currentLng, currentLat)
|
||||
});
|
||||
} else {
|
||||
// 如果用户手动输入了地点 (例如 "北京南站")
|
||||
// 直接存入关键词,让高德自己去搜
|
||||
points.push({
|
||||
keyword: startKw
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 处理终点逻辑 (通常是关键词)
|
||||
// 2. 处理终点逻辑
|
||||
points.push({
|
||||
keyword: endKw
|
||||
});
|
||||
|
||||
// 3. 发起搜索
|
||||
// points 数组里现在是一个起点对象和一个终点对象
|
||||
driving.search(points, function (status, result) {
|
||||
if (status === 'complete') {
|
||||
console.log('JS: 规划成功');
|
||||
|
||||
150
ln_jq_app/lib/pages/b_page/history/controller.dart
Normal file
150
ln_jq_app/lib/pages/b_page/history/controller.dart
Normal file
@@ -0,0 +1,150 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||
import 'package:ln_jq_app/pages/b_page/site/controller.dart'; // Reuse ReservationModel
|
||||
|
||||
class HistoryController extends GetxController with BaseControllerMixin {
|
||||
@override
|
||||
String get builderId => 'history';
|
||||
|
||||
// --- 定义 API 需要的日期格式化器 ---
|
||||
final DateFormat _apiDateFormat = DateFormat('yyyy-MM-dd');
|
||||
|
||||
// 默认查询最近7天
|
||||
final Rx<DateTime> startDate = DateTime.now().subtract(const Duration(days: 7)).obs;
|
||||
final Rx<DateTime> endDate = DateTime.now().obs;
|
||||
final TextEditingController plateNumberController = TextEditingController();
|
||||
|
||||
final RxString totalHydrogen = '0'.obs;
|
||||
final RxString totalCompletions = '0'.obs;
|
||||
|
||||
final RxList<ReservationModel> historyList = <ReservationModel>[].obs;
|
||||
final RxBool isLoading = true.obs;
|
||||
final RxBool hasData = false.obs;
|
||||
|
||||
String get formattedStartDate => DateFormat('yyyy/MM/dd').format(startDate.value);
|
||||
String get formattedEndDate => DateFormat('yyyy/MM/dd').format(endDate.value);
|
||||
|
||||
String stationName = "";
|
||||
|
||||
final Map<String, String> statusOptions = {
|
||||
'': '全部',
|
||||
'0': '待加氢',
|
||||
'1': '已加氢',
|
||||
'2': '未加氢',
|
||||
'5': '拒绝加氢',
|
||||
};
|
||||
|
||||
final RxString selectedStatus = ''.obs;
|
||||
final RxString selectedDateType = ''.obs; // week, month, three_month
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
final args = Get.arguments as Map<String, dynamic>;
|
||||
stationName = args['stationName'] as String? ?? "";
|
||||
refreshData();
|
||||
}
|
||||
|
||||
void refreshData() {
|
||||
getAllOrderCounts();
|
||||
fetchHistoryData();
|
||||
}
|
||||
|
||||
Future<void> getAllOrderCounts() async {
|
||||
var response = await HttpService.to.post(
|
||||
"appointment/orderAddHyd/getAllOrderCounts",
|
||||
data: {
|
||||
/*'startTime': _apiDateFormat.format(startDate.value),
|
||||
'endTime': _apiDateFormat.format(endDate.value),*/
|
||||
'plateNumber': plateNumberController.text,
|
||||
'stationName': stationName,
|
||||
"status": selectedStatus.value,
|
||||
"dateType": selectedDateType.value,
|
||||
},
|
||||
);
|
||||
if (response == null || response.data == null) {
|
||||
totalHydrogen.value = '0';
|
||||
totalCompletions.value = '0';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final baseModel = BaseModel<dynamic>.fromJson(response.data);
|
||||
final dataMap = baseModel.data as Map<String, dynamic>;
|
||||
totalHydrogen.value = '${dataMap['totalAddAmount'] ?? 0}';
|
||||
totalCompletions.value = '${dataMap['orderCompleteCount'] ?? 0}';
|
||||
} catch (e) {
|
||||
totalHydrogen.value = '0';
|
||||
totalCompletions.value = '0';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchHistoryData() async {
|
||||
isLoading.value = true;
|
||||
updateUi();
|
||||
|
||||
try {
|
||||
var response = await HttpService.to.post(
|
||||
"appointment/orderAddHyd/sitOrderPage",
|
||||
data: {
|
||||
/*'startTime': _apiDateFormat.format(startDate.value),
|
||||
'endTime': _apiDateFormat.format(endDate.value),*/
|
||||
'plateNumber': plateNumberController.text,
|
||||
'pageNum': 1,
|
||||
'pageSize': 50,
|
||||
'stationName': stationName,
|
||||
"status": selectedStatus.value,
|
||||
"dateType": selectedDateType.value,
|
||||
},
|
||||
);
|
||||
|
||||
if (response == null || response.data == null) {
|
||||
_resetData();
|
||||
return;
|
||||
}
|
||||
|
||||
final baseModel = BaseModel<dynamic>.fromJson(response.data);
|
||||
if (baseModel.code == 0 && baseModel.data != null) {
|
||||
final dataMap = baseModel.data as Map<String, dynamic>;
|
||||
final List<dynamic> listFromServer = dataMap['records'] ?? [];
|
||||
historyList.assignAll(
|
||||
listFromServer
|
||||
.map((item) => ReservationModel.fromJson(item as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
hasData.value = historyList.isNotEmpty;
|
||||
} else {
|
||||
_resetData();
|
||||
}
|
||||
} catch (e) {
|
||||
_resetData();
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
updateUi();
|
||||
}
|
||||
}
|
||||
|
||||
void _resetData() {
|
||||
historyList.clear();
|
||||
hasData.value = false;
|
||||
}
|
||||
|
||||
void onStatusSelected(String status) {
|
||||
if (selectedStatus.value == status) return;
|
||||
selectedStatus.value = status;
|
||||
refreshData();
|
||||
}
|
||||
|
||||
void onDateTypeSelected(String type) {
|
||||
selectedDateType.value = type;
|
||||
refreshData();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
plateNumberController.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,6 @@ class MallPage extends GetView<MallController> {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:getx_scaffold/common/index.dart';
|
||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||
import 'package:ln_jq_app/common/styles/theme.dart';
|
||||
import 'package:ln_jq_app/pages/c_page/reservation/controller.dart';
|
||||
import 'package:ln_jq_app/pages/c_page/reservation_edit/controller.dart';
|
||||
import 'package:ln_jq_app/pages/c_page/reservation_edit/view.dart';
|
||||
@@ -203,14 +204,14 @@ class _ReservationListBottomSheetState extends State<ReservationListBottomSheet>
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
side: BorderSide(color: Colors.grey.shade400), // 灰色边框
|
||||
shape: const StadiumBorder(), // 胶囊形状
|
||||
side: BorderSide(color: Colors.grey.shade400),
|
||||
shape: const StadiumBorder(),
|
||||
),
|
||||
child: Text(
|
||||
'取消预约',
|
||||
style: TextStyle(
|
||||
color: Colors.grey.shade600,
|
||||
fontSize: 12,
|
||||
fontSize: 11.sp,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -241,13 +242,13 @@ class _ReservationListBottomSheetState extends State<ReservationListBottomSheet>
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
side: const BorderSide(color: Colors.blue), // 蓝色边框
|
||||
side: BorderSide(color: AppTheme.themeColor),
|
||||
shape: const StadiumBorder(),
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'修改',
|
||||
style: TextStyle(color: Colors.blue, fontSize: 12),
|
||||
style: TextStyle(color: AppTheme.themeColor, fontSize: 11.sp),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user