|
@@ -2,9 +2,7 @@ package com.fujica.abk.slice;
|
|
|
|
|
|
|
|
import com.fujica.abk.ResourceTable;
|
|
import com.fujica.abk.ResourceTable;
|
|
|
import com.fujica.abk.api.cache;
|
|
import com.fujica.abk.api.cache;
|
|
|
-import com.fujica.abk.utils.Log;
|
|
|
|
|
-import com.fujica.abk.utils.Toast;
|
|
|
|
|
-import com.fujica.abk.utils.api;
|
|
|
|
|
|
|
+import com.fujica.abk.utils.*;
|
|
|
import com.huawei.hms.accountsdk.constant.CommonConstant;
|
|
import com.huawei.hms.accountsdk.constant.CommonConstant;
|
|
|
import com.huawei.hms.accountsdk.exception.ApiException;
|
|
import com.huawei.hms.accountsdk.exception.ApiException;
|
|
|
import com.huawei.hms.accountsdk.support.account.AccountAuthManager;
|
|
import com.huawei.hms.accountsdk.support.account.AccountAuthManager;
|
|
@@ -35,7 +33,7 @@ import ohos.sysappcomponents.settings.SystemSettings;
|
|
|
import ohos.utils.zson.ZSONObject;
|
|
import ohos.utils.zson.ZSONObject;
|
|
|
import com.fujica.abk.model.response.ParkNearRes;
|
|
import com.fujica.abk.model.response.ParkNearRes;
|
|
|
import com.fujica.abk.model.response.Page;
|
|
import com.fujica.abk.model.response.Page;
|
|
|
-import com.fujica.abk.utils.R;
|
|
|
|
|
|
|
+
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.CompletableFuture;
|
|
@@ -80,20 +78,25 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
private ScrollView parkingListScroll; // 停车场列表滚动视图
|
|
private ScrollView parkingListScroll; // 停车场列表滚动视图
|
|
|
private DirectionalLayout parkingListContainer; // 停车场列表容器
|
|
private DirectionalLayout parkingListContainer; // 停车场列表容器
|
|
|
private int currentPage = 1; // 当前页码
|
|
private int currentPage = 1; // 当前页码
|
|
|
- private int pageSize = 10; // 每页数量
|
|
|
|
|
|
|
+ private int pageSize = 20; // 每页数量
|
|
|
private boolean isLoading = false; // 是否正在加载
|
|
private boolean isLoading = false; // 是否正在加载
|
|
|
private boolean hasMore = true; // 是否还有更多数据
|
|
private boolean hasMore = true; // 是否还有更多数据
|
|
|
private int filterType = 2; // 筛选类型:2=全部,1=推荐
|
|
private int filterType = 2; // 筛选类型:2=全部,1=推荐
|
|
|
private List<ParkNearRes> parkingList = new ArrayList<>(); // 停车场列表数据
|
|
private List<ParkNearRes> parkingList = new ArrayList<>(); // 停车场列表数据
|
|
|
private long lastLoadTime = 0; // 上次加载时间,用于防抖
|
|
private long lastLoadTime = 0; // 上次加载时间,用于防抖
|
|
|
private static final long LOAD_THROTTLE_MS = 500; // 防抖时间间隔(毫秒)
|
|
private static final long LOAD_THROTTLE_MS = 500; // 防抖时间间隔(毫秒)
|
|
|
|
|
+ private ParkingItemComponent selectedParkingItem = null; // 当前选中的停车场列表项
|
|
|
|
|
|
|
|
DataAbilityHelper dataAbilityHelper;
|
|
DataAbilityHelper dataAbilityHelper;
|
|
|
IDataAbilityObserver dataAbilityObserver;
|
|
IDataAbilityObserver dataAbilityObserver;
|
|
|
|
|
|
|
|
|
|
+ // Loading组件
|
|
|
|
|
+ private LoadingComponent loadingComponent;
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public void onStart(Intent intent) {
|
|
public void onStart(Intent intent) {
|
|
|
super.onStart(intent);
|
|
super.onStart(intent);
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
//com.fujica.abk_BD8VI9k5bO0HeGAPnhTGeYX++mgKw87G8y+3RZ6nrb9evCePddojupXJN03auUKxTKn1qbFrYQAjFyGumpjsHzw=
|
|
//com.fujica.abk_BD8VI9k5bO0HeGAPnhTGeYX++mgKw87G8y+3RZ6nrb9evCePddojupXJN03auUKxTKn1qbFrYQAjFyGumpjsHzw=
|
|
|
String appId = getApplicationContext().getBundleManager().getBundleInfo(getBundleName(), 0).getAppId();
|
|
String appId = getApplicationContext().getBundleManager().getBundleInfo(getBundleName(), 0).getAppId();
|
|
@@ -111,6 +114,9 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
// 设置布局
|
|
// 设置布局
|
|
|
super.setUIContent(ResourceTable.Layout_ability_main);
|
|
super.setUIContent(ResourceTable.Layout_ability_main);
|
|
|
|
|
|
|
|
|
|
+ // 初始化Loading组件并添加到根布局
|
|
|
|
|
+ loadingComponent = findComponentById(ResourceTable.Id_loading_component);
|
|
|
|
|
+
|
|
|
// 初始化组件
|
|
// 初始化组件
|
|
|
initComponents();
|
|
initComponents();
|
|
|
|
|
|
|
@@ -161,13 +167,13 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
} catch (ApiException e) {
|
|
} catch (ApiException e) {
|
|
|
// 处理初始化登录授权服务失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因
|
|
// 处理初始化登录授权服务失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因
|
|
|
e.getStatusCode();
|
|
e.getStatusCode();
|
|
|
- Toast.error(getContext(),"Init Huawei accountAuthService FAILED.");
|
|
|
|
|
|
|
+ Toast.error(getContext(), "Init Huawei accountAuthService FAILED.");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- Toast.info(getContext(),"Init Huawei accountAuthService SUCCESS");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "Init Huawei accountAuthService SUCCESS");
|
|
|
|
|
|
|
|
if (accountAuthService == null) {
|
|
if (accountAuthService == null) {
|
|
|
- Toast.error(getContext(),"获取不到账号信息");
|
|
|
|
|
|
|
+ Toast.error(getContext(), "获取不到账号信息");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
// 调用静默登录接口。
|
|
// 调用静默登录接口。
|
|
@@ -175,43 +181,43 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
// 否则静默登录失败,需要在失败监听中,显式地调用前台登录授权接口,完成登录授权。
|
|
// 否则静默登录失败,需要在失败监听中,显式地调用前台登录授权接口,完成登录授权。
|
|
|
Task<AuthAccount> taskSilentSignIn = accountAuthService.silentSignIn();
|
|
Task<AuthAccount> taskSilentSignIn = accountAuthService.silentSignIn();
|
|
|
// Task<AuthAccount> taskSilentSignIn = accountAuthService.silentSignIn();
|
|
// Task<AuthAccount> taskSilentSignIn = accountAuthService.silentSignIn();
|
|
|
- Toast.info(getContext(),"SilentSign START.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SilentSign START.");
|
|
|
// 添加静默登录成功处理监听
|
|
// 添加静默登录成功处理监听
|
|
|
taskSilentSignIn.addOnSuccessListener(authAccount -> updateUI(authAccount));
|
|
taskSilentSignIn.addOnSuccessListener(authAccount -> updateUI(authAccount));
|
|
|
// 添加静默登录失败监听
|
|
// 添加静默登录失败监听
|
|
|
taskSilentSignIn.addOnFailureListener(e -> {
|
|
taskSilentSignIn.addOnFailureListener(e -> {
|
|
|
if (e instanceof ApiException) {
|
|
if (e instanceof ApiException) {
|
|
|
ApiException apiException = (ApiException) e;
|
|
ApiException apiException = (ApiException) e;
|
|
|
- Toast.error(getContext(),"SilentSignIn FAILED, status code: " + apiException.getStatusCode() + ". Need to foreground sign in" + "\r\n" + apiException.getStatusMessage()
|
|
|
|
|
|
|
+ Toast.error(getContext(), "SilentSignIn FAILED, status code: " + apiException.getStatusCode() + ". Need to foreground sign in" + "\r\n" + apiException.getStatusMessage()
|
|
|
+ "\r\n" + apiException.getMessage() + "\r\n" + apiException.getCause());
|
|
+ "\r\n" + apiException.getMessage() + "\r\n" + apiException.getCause());
|
|
|
|
|
|
|
|
// 静默登录失败,显式地调用前台登录授权接口,完成登录授权。
|
|
// 静默登录失败,显式地调用前台登录授权接口,完成登录授权。
|
|
|
Task<AuthAccount> taskSignIn = accountAuthService.signIn();
|
|
Task<AuthAccount> taskSignIn = accountAuthService.signIn();
|
|
|
- Toast.info(getContext(),"SignIn foreground START.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SignIn foreground START.");
|
|
|
if (taskSignIn == null) {
|
|
if (taskSignIn == null) {
|
|
|
- Toast.info(getContext(),"SignIn foreground task is null.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SignIn foreground task is null.");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
taskSignIn.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
|
|
taskSignIn.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
|
|
|
@Override
|
|
@Override
|
|
|
public void onSuccess(AuthAccount result) {
|
|
public void onSuccess(AuthAccount result) {
|
|
|
- Toast.info(getContext(),"SignIn foreground SUCCESS.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SignIn foreground SUCCESS.");
|
|
|
updateUI(result);
|
|
updateUI(result);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
taskSignIn.addOnFailureListener(new OnFailureListener() {
|
|
taskSignIn.addOnFailureListener(new OnFailureListener() {
|
|
|
@Override
|
|
@Override
|
|
|
public void onFailure(Exception e) {
|
|
public void onFailure(Exception e) {
|
|
|
- Toast.info(getContext(),"SignIn foreground FAILED.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SignIn foreground FAILED.");
|
|
|
if (e instanceof ApiException) {
|
|
if (e instanceof ApiException) {
|
|
|
ApiException apiException = (ApiException) e;
|
|
ApiException apiException = (ApiException) e;
|
|
|
// 登录失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因
|
|
// 登录失败,status code标识了失败的原因,请参考API中的错误码参考了解详细错误原因
|
|
|
apiException.getStatusCode();
|
|
apiException.getStatusCode();
|
|
|
- Toast.info(getContext(),"SignIn foreground FAILED. status code: "
|
|
|
|
|
|
|
+ Toast.info(getContext(), "SignIn foreground FAILED. status code: "
|
|
|
+ apiException.getStatusCode()
|
|
+ apiException.getStatusCode()
|
|
|
+ ".");
|
|
+ ".");
|
|
|
if (CommonConstant.RETCODE.SIGN_IN_CANCELLED == apiException.getStatusCode()) {
|
|
if (CommonConstant.RETCODE.SIGN_IN_CANCELLED == apiException.getStatusCode()) {
|
|
|
- Toast.info(getContext(),"Error message: User click CANCEL or Return, user cancel login in.");
|
|
|
|
|
|
|
+ Toast.info(getContext(), "Error message: User click CANCEL or Return, user cancel login in.");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -221,7 +227,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void updateUI(AuthAccount authAccount) {
|
|
private void updateUI(AuthAccount authAccount) {
|
|
|
- Toast.info(getContext(),authAccount.getOpenId() + " : " + authAccount.getUnionId());
|
|
|
|
|
|
|
+ Toast.info(getContext(), authAccount.getOpenId() + " : " + authAccount.getUnionId());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -576,38 +582,38 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
if (currentTime - lastLoadTime < LOAD_THROTTLE_MS) {
|
|
if (currentTime - lastLoadTime < LOAD_THROTTLE_MS) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果正在加载或没有更多数据,直接返回
|
|
// 如果正在加载或没有更多数据,直接返回
|
|
|
if (isLoading || !hasMore) {
|
|
if (isLoading || !hasMore) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 计算是否滚动到底部
|
|
// 计算是否滚动到底部
|
|
|
int scrollY = parkingListScroll.getScrollValue(1);
|
|
int scrollY = parkingListScroll.getScrollValue(1);
|
|
|
int viewHeight = parkingListScroll.getHeight();
|
|
int viewHeight = parkingListScroll.getHeight();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 获取内容高度(使用容器的高度)
|
|
// 获取内容高度(使用容器的高度)
|
|
|
int contentHeight = 0;
|
|
int contentHeight = 0;
|
|
|
if (parkingListContainer != null) {
|
|
if (parkingListContainer != null) {
|
|
|
contentHeight = parkingListContainer.getHeight();
|
|
contentHeight = parkingListContainer.getHeight();
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果容器高度为0,尝试使用EstimatedHeight
|
|
// 如果容器高度为0,尝试使用EstimatedHeight
|
|
|
if (contentHeight == 0) {
|
|
if (contentHeight == 0) {
|
|
|
contentHeight = parkingListScroll.getEstimatedHeight();
|
|
contentHeight = parkingListScroll.getEstimatedHeight();
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 如果内容高度或视图高度为0,无法计算,直接返回
|
|
// 如果内容高度或视图高度为0,无法计算,直接返回
|
|
|
if (contentHeight == 0 || viewHeight == 0) {
|
|
if (contentHeight == 0 || viewHeight == 0) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 计算剩余滚动距离
|
|
// 计算剩余滚动距离
|
|
|
int remainingDistance = contentHeight - scrollY - viewHeight;
|
|
int remainingDistance = contentHeight - scrollY - viewHeight;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 计算阈值(50像素,约等于50vp),当剩余距离小于等于阈值时触发加载
|
|
// 计算阈值(50像素,约等于50vp),当剩余距离小于等于阈值时触发加载
|
|
|
int threshold = 50;
|
|
int threshold = 50;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 当滚动到底部(剩余距离小于等于阈值)时,触发加载
|
|
// 当滚动到底部(剩余距离小于等于阈值)时,触发加载
|
|
|
if (remainingDistance <= threshold && remainingDistance >= 0) {
|
|
if (remainingDistance <= threshold && remainingDistance >= 0) {
|
|
|
lastLoadTime = currentTime;
|
|
lastLoadTime = currentTime;
|
|
@@ -634,18 +640,20 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
if (parkingListContainer != null) {
|
|
if (parkingListContainer != null) {
|
|
|
parkingListContainer.removeAllComponents();
|
|
parkingListContainer.removeAllComponents();
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ // 清除选中状态
|
|
|
|
|
+ selectedParkingItem = null;
|
|
|
|
|
+
|
|
|
// 更新标签样式
|
|
// 更新标签样式
|
|
|
Color selectedColor = new Color(Color.getIntColor("#FA6332"));
|
|
Color selectedColor = new Color(Color.getIntColor("#FA6332"));
|
|
|
Color normalColor = new Color(Color.getIntColor("#FF666666"));
|
|
Color normalColor = new Color(Color.getIntColor("#FF666666"));
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (tabAll != null) {
|
|
if (tabAll != null) {
|
|
|
tabAll.setTextColor(filter == 2 ? selectedColor : normalColor);
|
|
tabAll.setTextColor(filter == 2 ? selectedColor : normalColor);
|
|
|
}
|
|
}
|
|
|
if (tabRecommended != null) {
|
|
if (tabRecommended != null) {
|
|
|
tabRecommended.setTextColor(filter == 1 ? selectedColor : normalColor);
|
|
tabRecommended.setTextColor(filter == 1 ? selectedColor : normalColor);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新下划线显示
|
|
// 更新下划线显示
|
|
|
if (tabAllUnderline != null) {
|
|
if (tabAllUnderline != null) {
|
|
|
tabAllUnderline.setVisibility(filter == 2 ? Component.VISIBLE : Component.HIDE);
|
|
tabAllUnderline.setVisibility(filter == 2 ? Component.VISIBLE : Component.HIDE);
|
|
@@ -653,7 +661,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
if (tabRecommendedUnderline != null) {
|
|
if (tabRecommendedUnderline != null) {
|
|
|
tabRecommendedUnderline.setVisibility(filter == 1 ? Component.VISIBLE : Component.HIDE);
|
|
tabRecommendedUnderline.setVisibility(filter == 1 ? Component.VISIBLE : Component.HIDE);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 加载数据
|
|
// 加载数据
|
|
|
loadParkingData(true);
|
|
loadParkingData(true);
|
|
|
}
|
|
}
|
|
@@ -698,16 +706,13 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
|
|
|
|
|
// 发送请求(网络请求已在后台线程)
|
|
// 发送请求(网络请求已在后台线程)
|
|
|
CompletableFuture<R<Object>> future = api.http(getContext(), url, "GET", null, null, null);
|
|
CompletableFuture<R<Object>> future = api.http(getContext(), url, "GET", null, null, null);
|
|
|
|
|
+ loadingComponent.show();
|
|
|
future.thenAccept(response -> {
|
|
future.thenAccept(response -> {
|
|
|
// 在后台线程解析数据,避免阻塞UI
|
|
// 在后台线程解析数据,避免阻塞UI
|
|
|
try {
|
|
try {
|
|
|
if (response == null || !response.isSuccess()) {
|
|
if (response == null || !response.isSuccess()) {
|
|
|
String errorMsg = response != null ? response.getMsg() : "请求失败";
|
|
String errorMsg = response != null ? response.getMsg() : "请求失败";
|
|
|
Log.error("加载停车场数据失败: " + errorMsg);
|
|
Log.error("加载停车场数据失败: " + errorMsg);
|
|
|
- getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
- // 请求失败,保持currentPage不变,允许重试
|
|
|
|
|
- });
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -715,9 +720,6 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
Object dataObj = response.getData();
|
|
Object dataObj = response.getData();
|
|
|
if (dataObj == null) {
|
|
if (dataObj == null) {
|
|
|
Log.error("响应数据为空");
|
|
Log.error("响应数据为空");
|
|
|
- getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
- });
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -733,18 +735,12 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
Page<ParkNearRes> page = parsePageData(pageObj);
|
|
Page<ParkNearRes> page = parsePageData(pageObj);
|
|
|
if (page == null || page.getRecords() == null) {
|
|
if (page == null || page.getRecords() == null) {
|
|
|
Log.error("解析分页数据失败");
|
|
Log.error("解析分页数据失败");
|
|
|
- getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
- });
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
List<ParkNearRes> records = page.getRecords();
|
|
List<ParkNearRes> records = page.getRecords();
|
|
|
if (records.isEmpty()) {
|
|
if (records.isEmpty()) {
|
|
|
- getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ hasMore = false;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -773,18 +769,17 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
|
|
|
|
|
// 只在UI线程更新界面
|
|
// 只在UI线程更新界面
|
|
|
getUITaskDispatcher().asyncDispatch(() -> {
|
|
getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
- isLoading = false;
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 检查currentPage是否已经被其他请求更新(防止旧请求覆盖新数据)
|
|
// 检查currentPage是否已经被其他请求更新(防止旧请求覆盖新数据)
|
|
|
// 如果currentPage > requestPage,说明有更新的请求已经完成,忽略这个旧请求的结果
|
|
// 如果currentPage > requestPage,说明有更新的请求已经完成,忽略这个旧请求的结果
|
|
|
if (currentPage > requestPage) {
|
|
if (currentPage > requestPage) {
|
|
|
Log.info("忽略过期请求,当前页码: " + currentPage + ", 请求页码: " + requestPage);
|
|
Log.info("忽略过期请求,当前页码: " + currentPage + ", 请求页码: " + requestPage);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 添加到列表
|
|
// 添加到列表
|
|
|
parkingList.addAll(finalRecords);
|
|
parkingList.addAll(finalRecords);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 批量渲染列表项(减少UI更新次数,延迟批量添加)
|
|
// 批量渲染列表项(减少UI更新次数,延迟批量添加)
|
|
|
if (parkingListContainer != null && !finalRecords.isEmpty()) {
|
|
if (parkingListContainer != null && !finalRecords.isEmpty()) {
|
|
|
// 先批量创建所有组件
|
|
// 先批量创建所有组件
|
|
@@ -795,7 +790,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
items.add(item);
|
|
items.add(item);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 批量添加到容器(减少UI重绘次数)
|
|
// 批量添加到容器(减少UI重绘次数)
|
|
|
for (Component item : items) {
|
|
for (Component item : items) {
|
|
|
parkingListContainer.addComponent(item);
|
|
parkingListContainer.addComponent(item);
|
|
@@ -812,9 +807,9 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
Log.error("解析停车场数据失败: " + e.getMessage());
|
|
Log.error("解析停车场数据失败: " + e.getMessage());
|
|
|
e.printStackTrace();
|
|
e.printStackTrace();
|
|
|
- getUITaskDispatcher().asyncDispatch(() -> {
|
|
|
|
|
- isLoading = false;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ isLoading = false;
|
|
|
|
|
+ loadingComponent.hide();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
@@ -825,7 +820,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
private Page<ParkNearRes> parsePageData(ZSONObject pageObj) {
|
|
private Page<ParkNearRes> parsePageData(ZSONObject pageObj) {
|
|
|
try {
|
|
try {
|
|
|
Page<ParkNearRes> page = new Page<>();
|
|
Page<ParkNearRes> page = new Page<>();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (pageObj.containsKey("total")) {
|
|
if (pageObj.containsKey("total")) {
|
|
|
page.setTotal(pageObj.getIntValue("total"));
|
|
page.setTotal(pageObj.getIntValue("total"));
|
|
|
}
|
|
}
|
|
@@ -852,7 +847,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
page.setRecords(parkList);
|
|
page.setRecords(parkList);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return page;
|
|
return page;
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
Log.error("解析Page数据失败: " + e.getMessage());
|
|
Log.error("解析Page数据失败: " + e.getMessage());
|
|
@@ -928,6 +923,7 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 创建停车场列表项组件(不添加到容器)
|
|
* 创建停车场列表项组件(不添加到容器)
|
|
|
|
|
+ * 使用 ParkingItemComponent 组件
|
|
|
*/
|
|
*/
|
|
|
private Component createParkingItem(ParkNearRes park) {
|
|
private Component createParkingItem(ParkNearRes park) {
|
|
|
if (parkingListContainer == null) {
|
|
if (parkingListContainer == null) {
|
|
@@ -935,75 +931,18 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 加载列表项布局
|
|
|
|
|
- Component item = LayoutScatter.getInstance(this)
|
|
|
|
|
- .parse(ResourceTable.Layout_item_parking, null, false);
|
|
|
|
|
-
|
|
|
|
|
- // 设置停车场名称
|
|
|
|
|
- Text nameText = (Text) item.findComponentById(ResourceTable.Id_parking_name);
|
|
|
|
|
- if (nameText != null && park.getParkName() != null) {
|
|
|
|
|
- nameText.setText(park.getParkName());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置距离和地址
|
|
|
|
|
- Text addressText = (Text) item.findComponentById(ResourceTable.Id_parking_address);
|
|
|
|
|
- if (addressText != null) {
|
|
|
|
|
- String distanceStr = park.getDistance() != null ?
|
|
|
|
|
- String.format("%.1fkm", park.getDistance() / 1000.0) : "0km";
|
|
|
|
|
- String address = park.getAddress() != null ? park.getAddress() : "";
|
|
|
|
|
- addressText.setText(distanceStr + " | " + address);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置总车位
|
|
|
|
|
- Text totalPlaceText = (Text) item.findComponentById(ResourceTable.Id_text_total_place);
|
|
|
|
|
- if (totalPlaceText != null && park.getTotalPlace() != null) {
|
|
|
|
|
- totalPlaceText.setText(String.valueOf(park.getTotalPlace()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置剩余车位
|
|
|
|
|
- Text residuePlaceText = (Text) item.findComponentById(ResourceTable.Id_text_residue_place);
|
|
|
|
|
- if (residuePlaceText != null && park.getResiduePlace() != null) {
|
|
|
|
|
- residuePlaceText.setText(String.valueOf(park.getResiduePlace()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置免费时长(从chargeInfo中解析,这里简化处理)
|
|
|
|
|
- Text freeDurationText = (Text) item.findComponentById(ResourceTable.Id_text_free_duration);
|
|
|
|
|
- if (freeDurationText != null) {
|
|
|
|
|
- // 这里可以根据chargeInfo解析免费时长,暂时显示"15分"
|
|
|
|
|
- freeDurationText.setText("15分");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置标签
|
|
|
|
|
- DirectionalLayout tagsContainer = (DirectionalLayout) item.findComponentById(ResourceTable.Id_tags_container);
|
|
|
|
|
- if (tagsContainer != null) {
|
|
|
|
|
- tagsContainer.removeAllComponents();
|
|
|
|
|
-
|
|
|
|
|
- // 根据数据添加标签
|
|
|
|
|
- // 商场、学校等标签需要根据业务逻辑判断,这里简化处理
|
|
|
|
|
- // 可预约 - 浅蓝色(#4CAF50 或 #2196F3)
|
|
|
|
|
- if (park.getIsreserver() != null && park.getIsreserver() == 1) {
|
|
|
|
|
- addTag(tagsContainer, "可预约", "#4CAF50");
|
|
|
|
|
- }
|
|
|
|
|
- // 可充电 - 浅蓝色
|
|
|
|
|
- if (park.getPowerEnable() != null && park.getPowerEnable() == 1) {
|
|
|
|
|
- addTag(tagsContainer, "可充电", "#4CAF50");
|
|
|
|
|
- }
|
|
|
|
|
- // 优惠 - 红色
|
|
|
|
|
- if (park.getReductionEnable() != null && park.getReductionEnable() == 1) {
|
|
|
|
|
- addTag(tagsContainer, "惠", "#FF0000");
|
|
|
|
|
|
|
+ // 使用 ParkingItemComponent 组件
|
|
|
|
|
+ ParkingItemComponent item = new ParkingItemComponent(this, park);
|
|
|
|
|
+
|
|
|
|
|
+ // 设置选中监听器,实现全局选中状态管理
|
|
|
|
|
+ item.setOnItemSelectedListener((component, parkData) -> {
|
|
|
|
|
+ // 如果之前有选中的项,取消其选中状态
|
|
|
|
|
+ if (selectedParkingItem != null && selectedParkingItem != component) {
|
|
|
|
|
+ selectedParkingItem.setSelected(false);
|
|
|
}
|
|
}
|
|
|
- // 商场、学校等标签 - 橙色(#FA6332,需要根据业务逻辑判断,这里暂时不添加)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 设置导航按钮点击事件
|
|
|
|
|
- Image navButton = item.findComponentById(ResourceTable.Id_btn_navigate);
|
|
|
|
|
- if (navButton != null) {
|
|
|
|
|
- navButton.setClickedListener(component -> {
|
|
|
|
|
- // 导航功能
|
|
|
|
|
- Log.info("导航到: " + park.getParkName());
|
|
|
|
|
- // TODO: 实现导航功能
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 更新当前选中的项
|
|
|
|
|
+ selectedParkingItem = component;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
return item;
|
|
return item;
|
|
|
|
|
|
|
@@ -1023,26 +962,4 @@ public class MainAbilitySlice extends AbilitySlice {
|
|
|
parkingListContainer.addComponent(item);
|
|
parkingListContainer.addComponent(item);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 添加标签
|
|
|
|
|
- */
|
|
|
|
|
- private void addTag(DirectionalLayout container, String text, String bgColor) {
|
|
|
|
|
- Text tag = new Text(getContext());
|
|
|
|
|
- tag.setText(text);
|
|
|
|
|
- tag.setTextSize(11);
|
|
|
|
|
- tag.setTextColor(Color.WHITE);
|
|
|
|
|
- tag.setPadding(8, 4, 8, 4);
|
|
|
|
|
-
|
|
|
|
|
- // 创建圆角背景(椭圆形)
|
|
|
|
|
- ShapeElement background = new ShapeElement();
|
|
|
|
|
- background.setShape(ShapeElement.RECTANGLE);
|
|
|
|
|
- RgbColor rgbColor = new RgbColor(Color.getIntColor(bgColor));
|
|
|
|
|
- background.setRgbColor(rgbColor);
|
|
|
|
|
- background.setCornerRadius(12);
|
|
|
|
|
- tag.setBackground(background);
|
|
|
|
|
-
|
|
|
|
|
- tag.setMarginLeft(4);
|
|
|
|
|
- container.addComponent(tag);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|