ChargeComponent.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. package com.fujica.abk.component.nav;
  2. import com.fujica.abk.ResourceTable;
  3. import com.fujica.abk.api.cache;
  4. import com.fujica.abk.api.common;
  5. import com.fujica.abk.component.LoadingComponent;
  6. import com.fujica.abk.model.in.ChargeQuery;
  7. import com.fujica.abk.model.out.MemberPlateH5Dto;
  8. import com.fujica.abk.model.out.ParkingFeeInfo;
  9. import com.fujica.abk.utils.*;
  10. import com.google.gson.reflect.TypeToken;
  11. import ohos.aafwk.ability.DataAbilityHelper;
  12. import ohos.aafwk.ability.IDataAbilityObserver;
  13. import ohos.agp.components.*;
  14. import ohos.app.Context;
  15. import ohos.sysappcomponents.settings.SystemSettings;
  16. import java.util.concurrent.CompletableFuture;
  17. /**
  18. * 计费页面组件
  19. */
  20. public class ChargeComponent extends DirectionalLayout {
  21. private Component rootLayout;
  22. private Context context;
  23. private DirectionalLayout filterPlateNo;
  24. private Text textPlateNo;
  25. // 不同状态的卡片
  26. private DirectionalLayout cardNormalFee; // feeType 0或16: 正常缴费
  27. private DirectionalLayout cardNoEntry; // feeType 10或12: 未入场
  28. private DirectionalLayout cardBlacklist; // feeType 14: 黑名单
  29. private DirectionalLayout cardMonthly; // feeType 3: 月卡车辆
  30. private DirectionalLayout cardNoFee; // feeType 1/2/4/5/13: 无需缴费
  31. private DirectionalLayout cardFullDiscount; // feeType 6: 全额优惠
  32. private DirectionalLayout addVehicleCard; // 无车牌缓存
  33. // 正常缴费卡片的组件
  34. private Text textParkName;
  35. private Text textStayTime;
  36. private Text textActualAmount;
  37. private Text textDiscountAmount;
  38. private Button btnPayNow;
  39. // 未入场卡片的组件
  40. private Button btnRefresh;
  41. // 黑名单卡片的组件
  42. private Text textParkNameBlacklist;
  43. private Text textStayTimeBlacklist;
  44. // 月卡卡片的组件
  45. private Text textParkNameMonthly;
  46. private Text textStayTimeMonthly;
  47. private Button btnRenew;
  48. // 无需缴费卡片的组件
  49. private Text textParkNameNoFee;
  50. private Text textStayTimeNoFee;
  51. // 全额优惠卡片的组件
  52. private Text textParkNameFullDiscount;
  53. private Text textStayTimeFullDiscount;
  54. // 无车牌缓存卡片的组件
  55. private Button btnInputLicensePlate;
  56. // 当前停车费信息
  57. private ParkingFeeInfo currentFeeInfo;
  58. private LoadingComponent loadingComponent; // Loading组件
  59. private OnPayDetailShowListener onPayDetailShowListener; // 支付详情展示监听器
  60. /**
  61. * 支付详情展示监听器
  62. */
  63. public interface OnPayDetailShowListener {
  64. void onShowPayDetail(ParkingFeeInfo feeInfo);
  65. }
  66. /**
  67. * 设置Loading组件
  68. */
  69. public void setLoadingComponent(LoadingComponent loadingComponent) {
  70. this.loadingComponent = loadingComponent;
  71. }
  72. /**
  73. * 设置支付详情展示监听器
  74. */
  75. public void setOnPayDetailShowListener(OnPayDetailShowListener listener) {
  76. this.onPayDetailShowListener = listener;
  77. }
  78. /**
  79. * 构造函数
  80. */
  81. public ChargeComponent(Context context) {
  82. super(context);
  83. this.context = context;
  84. initComponent(context);
  85. }
  86. /**
  87. * 初始化组件
  88. */
  89. private void initComponent(Context context) {
  90. // 设置布局属性
  91. setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
  92. setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
  93. setOrientation(VERTICAL);
  94. // 加载布局文件
  95. rootLayout = LayoutScatter.getInstance(context)
  96. .parse(ResourceTable.Layout_layout_charge, null, false);
  97. addComponent(rootLayout);
  98. // 初始化UI组件
  99. initViews();
  100. // 设置事件监听
  101. setupListeners();
  102. // 根据缓存状态显示不同UI
  103. checkCacheAndUpdateUI();
  104. }
  105. /**
  106. * 初始化视图组件
  107. */
  108. private void initViews() {
  109. filterPlateNo = rootLayout.findComponentById(ResourceTable.Id_filter_plateNo);
  110. textPlateNo = rootLayout.findComponentById(ResourceTable.Id_text_plateNo);
  111. // 获取所有卡片容器
  112. cardNormalFee = rootLayout.findComponentById(ResourceTable.Id_card_normal_fee);
  113. cardNoEntry = rootLayout.findComponentById(ResourceTable.Id_card_no_entry);
  114. cardBlacklist = rootLayout.findComponentById(ResourceTable.Id_card_blacklist);
  115. cardMonthly = rootLayout.findComponentById(ResourceTable.Id_card_monthly);
  116. cardNoFee = rootLayout.findComponentById(ResourceTable.Id_card_no_fee);
  117. cardFullDiscount = rootLayout.findComponentById(ResourceTable.Id_card_full_discount);
  118. addVehicleCard = rootLayout.findComponentById(ResourceTable.Id_add_vehicle_card);
  119. // 正常缴费卡片的组件
  120. textParkName = rootLayout.findComponentById(ResourceTable.Id_text_park_name);
  121. textStayTime = rootLayout.findComponentById(ResourceTable.Id_text_stay_time);
  122. textActualAmount = rootLayout.findComponentById(ResourceTable.Id_text_actual_amount);
  123. textDiscountAmount = rootLayout.findComponentById(ResourceTable.Id_text_discount_amount);
  124. btnPayNow = rootLayout.findComponentById(ResourceTable.Id_btn_pay_now);
  125. // 未入场卡片的组件
  126. btnRefresh = rootLayout.findComponentById(ResourceTable.Id_btn_refresh);
  127. // 黑名单卡片的组件
  128. textParkNameBlacklist = rootLayout.findComponentById(ResourceTable.Id_text_park_name_blacklist);
  129. textStayTimeBlacklist = rootLayout.findComponentById(ResourceTable.Id_text_stay_time_blacklist);
  130. // 月卡卡片的组件
  131. textParkNameMonthly = rootLayout.findComponentById(ResourceTable.Id_text_park_name_monthly);
  132. textStayTimeMonthly = rootLayout.findComponentById(ResourceTable.Id_text_stay_time_monthly);
  133. btnRenew = rootLayout.findComponentById(ResourceTable.Id_btn_renew);
  134. // 无需缴费卡片的组件
  135. textParkNameNoFee = rootLayout.findComponentById(ResourceTable.Id_text_park_name_no_fee);
  136. textStayTimeNoFee = rootLayout.findComponentById(ResourceTable.Id_text_stay_time_no_fee);
  137. // 全额优惠卡片的组件
  138. textParkNameFullDiscount = rootLayout.findComponentById(ResourceTable.Id_text_park_name_full_discount);
  139. textStayTimeFullDiscount = rootLayout.findComponentById(ResourceTable.Id_text_stay_time_full_discount);
  140. // 无车牌缓存卡片的组件
  141. btnInputLicensePlate = rootLayout.findComponentById(ResourceTable.Id_btn_input_license_plate);
  142. }
  143. /**
  144. * 设置事件监听
  145. */
  146. private void setupListeners() {
  147. filterPlateNo.setClickedListener(v -> showLicensePlateInputDialog());
  148. // 输入车牌缴费按钮点击事件
  149. btnInputLicensePlate.setClickedListener(component -> showLicensePlateInputDialog());
  150. // 立即缴费按钮点击事件
  151. if (btnPayNow != null) {
  152. btnPayNow.setClickedListener(component -> {
  153. // if(true){
  154. // Runnable payRunnable = new Runnable() {
  155. // @Override
  156. // public void run() {
  157. // com.huawei.hms.a
  158. // AggrPayClient client = Pay.getPayClient(this);
  159. // PayResult payResult = client.carPay(orderStr);
  160. // mHandler.post(() -> dealPayResult(payResult));
  161. // }
  162. // };
  163. // Thread payThread = new Thread(payRunnable);
  164. // payThread.start();
  165. // return;
  166. // }
  167. if (currentFeeInfo != null) {
  168. // 展示支付详情
  169. if (onPayDetailShowListener != null) {
  170. onPayDetailShowListener.onShowPayDetail(currentFeeInfo);
  171. } else {
  172. Toast.info(context, "请稍后重试");
  173. }
  174. }
  175. });
  176. }
  177. // 刷新按钮点击事件
  178. if (btnRefresh != null) {
  179. btnRefresh.setClickedListener(component -> {
  180. checkCacheAndUpdateUI();
  181. });
  182. }
  183. // 立即续费按钮点击事件
  184. if (btnRenew != null) {
  185. btnRenew.setClickedListener(component -> {
  186. if (currentFeeInfo != null) {
  187. // TODO: 跳转到续费页面
  188. Toast.info(context, "跳转到续费页面");
  189. }
  190. });
  191. }
  192. }
  193. /**
  194. * 显示车牌输入对话框
  195. */
  196. private void showLicensePlateInputDialog() {
  197. LicensePlateInputDialog licensePlateInputDialog = new LicensePlateInputDialog(context);
  198. licensePlateInputDialog.setOnConfirmListener(licensePlate -> {
  199. // 确认后保存车牌并查询计费
  200. simulateLicensePlateInput(licensePlate);
  201. });
  202. licensePlateInputDialog.show();
  203. }
  204. private String plateNo = "";
  205. DataAbilityHelper dataAbilityHelper;
  206. IDataAbilityObserver dataAbilityObserver;
  207. // if (dataAbilityHelper != null) {
  208. // dataAbilityHelper.unregisterObserver(SystemSettings.getUri(SystemSettings.Date.TIME_FORMAT), dataAbilityObserver);
  209. // }
  210. /**
  211. * 检查缓存并更新UI
  212. */
  213. private void checkCacheAndUpdateUI() {
  214. if (plateNo == null || plateNo.isEmpty()) {
  215. if (dataAbilityHelper == null) {
  216. dataAbilityHelper = DataAbilityHelper.creator(getContext());
  217. }
  218. // 发起异步请求获取默认车牌
  219. CompletableFuture<R<MemberPlateH5Dto>> future = api.http(context, new ApiOption("/member/plate/default"), new TypeToken<R<MemberPlateH5Dto>>() {});
  220. future.thenAccept(result -> {
  221. // 处理响应结果
  222. if (result != null && result.isSuccess() && result.getData() != null) {
  223. MemberPlateH5Dto plateData = result.getData();
  224. if (plateData.getPlateNo() != null && !plateData.getPlateNo().isEmpty()) {
  225. plateNo = plateData.getPlateNo();
  226. cache.setDefaultPlateNo(getContext(), plateNo);
  227. }
  228. }
  229. if(plateNo == null || plateNo.isEmpty()){
  230. plateNo = SystemSettings.getValue(dataAbilityHelper, "car_license_plate_number");
  231. common.updateDefaultPlateNo(context, plateNo);
  232. }
  233. // 异步请求完成后,更新UI(确保在主线程执行)
  234. DialogUtil.postTask(() -> {
  235. updateUIAfterPlateNoLoaded();
  236. });
  237. }).exceptionally(throwable -> {
  238. // 异常情况下也要更新UI(确保在主线程执行)
  239. DialogUtil.postTask(() -> {
  240. updateUIAfterPlateNoLoaded();
  241. });
  242. return null;
  243. });
  244. } else {
  245. // 已经有plateNo,直接更新UI
  246. updateUIAfterPlateNoLoaded();
  247. }
  248. }
  249. /**
  250. * 加载plateNo后更新UI
  251. */
  252. private void updateUIAfterPlateNoLoaded() {
  253. if (plateNo != null && !plateNo.isEmpty()) {
  254. // 有缓存,直接查询计费
  255. queryParkingFee(plateNo);
  256. filterPlateNo.setVisibility(VISIBLE);
  257. textPlateNo.setText(plateNo);
  258. } else {
  259. // 无缓存,显示添加车辆卡片
  260. showAddVehicleCard();
  261. filterPlateNo.setVisibility(HIDE);
  262. textPlateNo.setText("");
  263. }
  264. }
  265. /**
  266. * 显示添加车辆卡片
  267. */
  268. private void showAddVehicleCard() {
  269. hideAllCards();
  270. if (addVehicleCard != null) {
  271. addVehicleCard.setVisibility(VISIBLE);
  272. }
  273. }
  274. /**
  275. * 隐藏所有卡片
  276. */
  277. private void hideAllCards() {
  278. if (cardNormalFee != null) cardNormalFee.setVisibility(HIDE);
  279. if (cardNoEntry != null) cardNoEntry.setVisibility(HIDE);
  280. if (cardBlacklist != null) cardBlacklist.setVisibility(HIDE);
  281. if (cardMonthly != null) cardMonthly.setVisibility(HIDE);
  282. if (cardNoFee != null) cardNoFee.setVisibility(HIDE);
  283. if (cardFullDiscount != null) cardFullDiscount.setVisibility(HIDE);
  284. if (addVehicleCard != null) addVehicleCard.setVisibility(HIDE);
  285. }
  286. /**
  287. * 模拟车牌输入(后续会被实际输入逻辑替换)
  288. */
  289. private void simulateLicensePlateInput(String licensePlate) {
  290. // 更新顶部车牌显示
  291. filterPlateNo.setVisibility(VISIBLE);
  292. textPlateNo.setText(licensePlate);
  293. this.plateNo = licensePlate;
  294. // 查询计费
  295. queryParkingFee(this.plateNo);
  296. }
  297. /**
  298. * 查询停车费用
  299. * 参考 index.vue 中的 getCharge 方法实现
  300. */
  301. private void queryParkingFee(String licensePlate) {
  302. // 构建请求参数
  303. ChargeQuery query = new ChargeQuery();
  304. query.setChargeScene(2); // 计费场景: 2
  305. query.setPlateNo(licensePlate);
  306. CompletableFuture<R<ParkingFeeInfo>> future = common.queryParkingFee(getContext(), query);
  307. if (loadingComponent != null) {
  308. loadingComponent.show();
  309. }
  310. future.thenAccept(result1 -> {
  311. // 在主线程更新UI
  312. DialogUtil.postTask(() -> {
  313. // String json = "{\"code\":0,\"data\":{\"actualAmount\":1400,\"discountAmount\":110,\"feeType\":12,\"followList\":[],\"parkId\":\"559581682204741\",\"parkName\":\"车场0818\",\"parkingDays\":0,\"parkingHours\":0,\"parkingMinutes\":0,\"plateColor\":\"6\",\"plateNo\":\"粤B11111\",\"rzStatus\":false,\"stayTime\":\"0天6小时39分\",\"totalFee\":0},\"success\":true}";
  314. // R<ParkingFeeInfo> result = new Gson().fromJson(json, new TypeToken<R<ParkingFeeInfo>>() {
  315. // });
  316. R<ParkingFeeInfo> result = result1;
  317. if (result == null || "timeout".equals(result.getMsg())) {
  318. // 查询结果为空或超时:按照未入场处理(feeType=10)
  319. // 参考 Charge.ets 第467行的实现
  320. ParkingFeeInfo emptyFeeInfo = new ParkingFeeInfo();
  321. emptyFeeInfo.setFeeType(10);
  322. emptyFeeInfo.setPlateNo(licensePlate);
  323. updateParkingInfo(emptyFeeInfo);
  324. } else if (result.isSuccess() && result.getData() != null) {
  325. ParkingFeeInfo feeInfo = result.getData();
  326. currentFeeInfo = feeInfo;
  327. // 更新停车信息显示
  328. updateParkingInfo(feeInfo);
  329. // 处理 feeType 16:有历史欠费订单(临停加欠费补缴)
  330. // if (feeInfo.getFeeType() == 16 && feeInfo.getFollowList() != null && !feeInfo.getFollowList().isEmpty()) {
  331. // int arrearageCount = feeInfo.getFollowList().size();
  332. // String message = "您有" + arrearageCount + "笔历史欠费订单(不含本次停车订单)尚未支付,请尽快处理";
  333. // showArrearageDialog(message, feeInfo, "立即补缴");
  334. // }
  335. // // 处理 feeType 13:本次停车未产生费用,但有历史欠费订单
  336. // else if (feeInfo.getFeeType() == 13 && feeInfo.getFollowList() != null && !feeInfo.getFollowList().isEmpty()) {
  337. // int arrearageCount = feeInfo.getFollowList().size();
  338. // String message = "本次停车未产生费用,但您仍有" + arrearageCount + "笔历史欠费订单尚未支付,请尽快处理";
  339. // showArrearageDialog(message, feeInfo, "立即补缴");
  340. // }
  341. // TODO: 检查车辆认证状态
  342. // 这里需要获取用户的车辆列表,检查当前车牌是否已认证(status == 2)
  343. // 如果未认证,设置 rzStatus = false
  344. // if (user.cars.findIndex(item => item.plateNo == feeInfo.getPlateNo() && item.status == 2) == -1) {
  345. // feeInfo.setRzStatus(false);
  346. // } else {
  347. // feeInfo.setRzStatus(true);
  348. // }
  349. } else {
  350. // 查询失败
  351. Toast.error(context, "查询失败,请稍后重试");
  352. showAddVehicleCard();
  353. }
  354. });
  355. }).exceptionally(throwable -> {
  356. // 异常处理(包括超时)
  357. // 参考 Vue 中的实现:计费超时按照未入场处理(feeType=10)
  358. DialogUtil.postTask(() -> {
  359. // 异常按照未入场处理
  360. ParkingFeeInfo errorFeeInfo = new ParkingFeeInfo();
  361. errorFeeInfo.setFeeType(10);
  362. errorFeeInfo.setPlateNo(licensePlate);
  363. updateParkingInfo(errorFeeInfo);
  364. });
  365. return null;
  366. }).whenComplete((result, throwable) -> {
  367. // finally 块:无论成功还是失败都隐藏 loading
  368. DialogUtil.postTask(() -> {
  369. if (loadingComponent != null) {
  370. loadingComponent.hide();
  371. }
  372. });
  373. });
  374. }
  375. /**
  376. * 显示欠费订单提示对话框
  377. * 参考 Vue 中的 uni.showModal 实现
  378. */
  379. private void showArrearageDialog(String message, ParkingFeeInfo feeInfo, String confirmText) {
  380. com.fujica.abk.utils.ConfirmDialog dialog = new com.fujica.abk.utils.ConfirmDialog(context);
  381. dialog.setTitle("温馨提示")
  382. .setMessage(message)
  383. .setConfirmText(confirmText)
  384. .setConfirmListener(dialogInstance -> {
  385. // 点击确定按钮:跳转到欠费补缴页面
  386. handleArrearagePayment(feeInfo);
  387. dialogInstance.dismiss();
  388. })
  389. .setCancelListener(dialogInstance -> {
  390. // 点击取消按钮:关闭对话框
  391. dialogInstance.dismiss();
  392. })
  393. .show();
  394. }
  395. /**
  396. * 处理欠费补缴
  397. * 根据欠费订单数量跳转到不同页面
  398. */
  399. private void handleArrearagePayment(ParkingFeeInfo feeInfo) {
  400. if (feeInfo.getFollowList() == null || feeInfo.getFollowList().isEmpty()) {
  401. return;
  402. }
  403. // TODO: 实现跳转逻辑
  404. // 如果只有一笔欠费订单,跳转到订单详情页
  405. if (feeInfo.getFollowList().size() == 1) {
  406. // storage.set('arrearageDetail', feeInfo.getFollowList().get(0));
  407. // pageTo('/pages/pay/arrearage/detail', { type: "pay" });
  408. Toast.info(context, "跳转到欠费订单详情页");
  409. } else {
  410. // 如果有多笔欠费订单,跳转到订单列表页
  411. // storage.set('arrearageList', feeInfo);
  412. // pageTo('/pages/pay/arrearage/list', { type: "singlePay" });
  413. Toast.info(context, "跳转到欠费订单列表页");
  414. }
  415. }
  416. /**
  417. * 更新停车信息显示
  418. * 根据 feeType 显示不同的界面,参考 index.vue 的实现
  419. */
  420. private void updateParkingInfo(ParkingFeeInfo feeInfo) {
  421. hideAllCards();
  422. int feeType = feeInfo.getFeeType();
  423. switch (feeType) {
  424. case 0: // 正常缴费
  425. case 16: // 临停加欠费补缴
  426. showNormalFeeCard(feeInfo);
  427. break;
  428. case 10: // 未入场
  429. case 12: // 场外月卡
  430. showNoEntryCard();
  431. break;
  432. case 14: // 黑名单车辆
  433. showBlacklistCard(feeInfo);
  434. break;
  435. case 3: // 月卡车辆
  436. showMonthlyCard(feeInfo);
  437. break;
  438. case 1: // 无需缴费
  439. case 2: // 已缴费免费离场时间内
  440. case 4: // 免费时间内
  441. case 5: // 无需缴费
  442. case 13: // 欠费补缴(本次无需缴费)
  443. showNoFeeCard(feeInfo);
  444. break;
  445. case 6: // 全额优惠,无需缴费
  446. showFullDiscountCard(feeInfo);
  447. break;
  448. default:
  449. showAddVehicleCard();
  450. break;
  451. }
  452. }
  453. /**
  454. * 显示正常缴费卡片 (feeType 0或16)
  455. */
  456. private void showNormalFeeCard(ParkingFeeInfo feeInfo) {
  457. if (cardNormalFee == null) return;
  458. cardNormalFee.setVisibility(VISIBLE);
  459. // 设置车场名称(如果未认证,显示提示)
  460. if (textParkName != null) {
  461. String parkName = feeInfo.getParkName() != null ? feeInfo.getParkName() : "未知车场";
  462. textParkName.setText(parkName);
  463. }
  464. // 设置停车时长
  465. if (textStayTime != null) {
  466. String stayTime = feeInfo.getStayTime() != null ? "已停" + feeInfo.getStayTime() : "已停0小时0分";
  467. textStayTime.setText(stayTime);
  468. }
  469. // 设置实际金额(分转元)
  470. if (textActualAmount != null) {
  471. double amount = feeInfo.getActualAmount() / 100.0;
  472. textActualAmount.setText(String.format("%.2f", amount));
  473. }
  474. // 设置减免金额
  475. if (textDiscountAmount != null && feeInfo.getDiscountAmount() > 0) {
  476. double discountAmount = feeInfo.getDiscountAmount() / 100.0;
  477. textDiscountAmount.setText(String.format("已减免%.2f元", discountAmount));
  478. textDiscountAmount.setVisibility(VISIBLE);
  479. } else {
  480. textDiscountAmount.setVisibility(HIDE);
  481. }
  482. }
  483. /**
  484. * 显示未入场卡片 (feeType 10或12)
  485. */
  486. private void showNoEntryCard() {
  487. if (cardNoEntry != null) {
  488. cardNoEntry.setVisibility(VISIBLE);
  489. }
  490. }
  491. /**
  492. * 显示黑名单卡片 (feeType 14)
  493. */
  494. private void showBlacklistCard(ParkingFeeInfo feeInfo) {
  495. if (cardBlacklist == null) return;
  496. cardBlacklist.setVisibility(VISIBLE);
  497. if (textParkNameBlacklist != null) {
  498. String parkName = feeInfo.getParkName() != null ? feeInfo.getParkName() : "";
  499. textParkNameBlacklist.setText(parkName);
  500. }
  501. if (textStayTimeBlacklist != null) {
  502. String stayTime = feeInfo.getStayTime() != null ? "已停" + feeInfo.getStayTime() : "";
  503. textStayTimeBlacklist.setText(stayTime);
  504. }
  505. }
  506. /**
  507. * 显示月卡卡片 (feeType 3)
  508. */
  509. private void showMonthlyCard(ParkingFeeInfo feeInfo) {
  510. if (cardMonthly == null) return;
  511. cardMonthly.setVisibility(VISIBLE);
  512. if (textParkNameMonthly != null) {
  513. String parkName = feeInfo.getParkName() != null ? feeInfo.getParkName() : "";
  514. textParkNameMonthly.setText(parkName);
  515. }
  516. if (textStayTimeMonthly != null) {
  517. String stayTime = feeInfo.getStayTime() != null ? "已停" + feeInfo.getStayTime() : "";
  518. textStayTimeMonthly.setText(stayTime);
  519. }
  520. }
  521. /**
  522. * 显示无需缴费卡片 (feeType 1/2/4/5/13)
  523. */
  524. private void showNoFeeCard(ParkingFeeInfo feeInfo) {
  525. if (cardNoFee == null) return;
  526. cardNoFee.setVisibility(VISIBLE);
  527. if (textParkNameNoFee != null) {
  528. String parkName = feeInfo.getParkName() != null ? feeInfo.getParkName() : "";
  529. textParkNameNoFee.setText(parkName);
  530. }
  531. if (textStayTimeNoFee != null) {
  532. String stayTime = feeInfo.getStayTime() != null ? "已停" + feeInfo.getStayTime() : "";
  533. textStayTimeNoFee.setText(stayTime);
  534. }
  535. }
  536. /**
  537. * 显示全额优惠卡片 (feeType 6)
  538. */
  539. private void showFullDiscountCard(ParkingFeeInfo feeInfo) {
  540. if (cardFullDiscount == null) return;
  541. cardFullDiscount.setVisibility(VISIBLE);
  542. if (textParkNameFullDiscount != null) {
  543. String parkName = feeInfo.getParkName() != null ? feeInfo.getParkName() : "";
  544. textParkNameFullDiscount.setText(parkName);
  545. }
  546. if (textStayTimeFullDiscount != null) {
  547. String stayTime = feeInfo.getStayTime() != null ? "已停" + feeInfo.getStayTime() : "";
  548. textStayTimeFullDiscount.setText(stayTime);
  549. }
  550. }
  551. /**
  552. * 刷新页面数据
  553. * 当页面切换过来时调用,重新检查缓存并更新UI
  554. */
  555. public void refresh() {
  556. checkCacheAndUpdateUI();
  557. }
  558. }