9 changed files with 1154 additions and 19 deletions
-
6app/src/main/AndroidManifest.xml
-
51app/src/main/java/com/ouxuan/oxface/OXFaceOnlineActivity.java
-
31app/src/main/java/com/ouxuan/oxface/network/OrderVerificationResultHandler.java
-
267app/src/main/java/com/ouxuan/oxface/orderOX/OrderSelectionActivity.java
-
127app/src/main/java/com/ouxuan/oxface/orderOX/adapter/OrderSelectionAdapter.java
-
245app/src/main/java/com/ouxuan/oxface/orderOX/model/OrderVerificationData.java
-
147app/src/main/res/layout/activity_order_selection.xml
-
126app/src/main/res/layout/item_order_selection.xml
-
173订单核销选择页面实现说明.md
@ -0,0 +1,267 @@ |
|||
package com.ouxuan.oxface.orderOX; |
|||
|
|||
import android.content.Intent; |
|||
import android.os.Bundle; |
|||
import android.os.Handler; |
|||
import android.view.View; |
|||
import android.view.Window; |
|||
import android.view.WindowManager; |
|||
import android.widget.Button; |
|||
import android.widget.TextView; |
|||
import android.widget.Toast; |
|||
|
|||
import androidx.appcompat.app.AppCompatActivity; |
|||
import androidx.recyclerview.widget.LinearLayoutManager; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.ouxuan.oxface.R; |
|||
import com.ouxuan.oxface.orderOX.adapter.OrderSelectionAdapter; |
|||
import com.ouxuan.oxface.orderOX.model.OrderVerificationData; |
|||
import com.ouxuan.oxface.utils.LogManager; |
|||
|
|||
import java.text.SimpleDateFormat; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.Locale; |
|||
|
|||
/** |
|||
* 订单核销选择页面 |
|||
* 用于显示人脸验证后返回的订单列表,供用户选择要核销的订单 |
|||
*/ |
|||
public class OrderSelectionActivity extends AppCompatActivity { |
|||
|
|||
private static final String TAG = "OrderSelectionActivity"; |
|||
public static final String EXTRA_ORDER_DATA = "order_data"; |
|||
public static final String EXTRA_VERIFICATION_TYPE = "verification_type"; |
|||
public static final String EXTRA_FACE_BASE64 = "face_base64"; |
|||
|
|||
private RecyclerView rvOrderList; |
|||
private Button btnConfirm, btnCancel; |
|||
private TextView tvBackHome, tvStoreName, tvVerificationDate; |
|||
|
|||
private OrderSelectionAdapter adapter; |
|||
private List<OrderVerificationData.OrderItem> orderList; |
|||
private int verificationType; |
|||
private String faceBase64; |
|||
private Handler countdownHandler; |
|||
private int countdown = 6; |
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
|
|||
// 设置无标题栏 |
|||
requestWindowFeature(Window.FEATURE_NO_TITLE); |
|||
|
|||
// 设置背景透明,实现弹窗效果 |
|||
getWindow().setBackgroundDrawableResource(android.R.color.transparent); |
|||
|
|||
setContentView(R.layout.activity_order_selection); |
|||
|
|||
// 设置窗口属性 |
|||
Window window = getWindow(); |
|||
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); |
|||
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); |
|||
|
|||
initViews(); |
|||
initData(); |
|||
setupListeners(); |
|||
startCountdown(); |
|||
|
|||
LogManager.logInfo(TAG, "订单选择页面启动成功"); |
|||
} |
|||
|
|||
private void initViews() { |
|||
rvOrderList = findViewById(R.id.rv_order_list); |
|||
btnConfirm = findViewById(R.id.btn_confirm); |
|||
btnCancel = findViewById(R.id.btn_cancel); |
|||
tvBackHome = findViewById(R.id.tv_back_home); |
|||
tvStoreName = findViewById(R.id.tv_store_name); |
|||
tvVerificationDate = findViewById(R.id.tv_verification_date); |
|||
|
|||
// 设置当前日期 |
|||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); |
|||
String currentDate = sdf.format(new Date()); |
|||
tvVerificationDate.setText("核销日期:" + currentDate); |
|||
|
|||
// 设置RecyclerView |
|||
rvOrderList.setLayoutManager(new LinearLayoutManager(this)); |
|||
} |
|||
|
|||
private void initData() { |
|||
// 获取传入的数据 |
|||
Intent intent = getIntent(); |
|||
String orderDataJson = intent.getStringExtra(EXTRA_ORDER_DATA); |
|||
verificationType = intent.getIntExtra(EXTRA_VERIFICATION_TYPE, 2); |
|||
faceBase64 = intent.getStringExtra(EXTRA_FACE_BASE64); |
|||
|
|||
if (orderDataJson != null) { |
|||
try { |
|||
// 解析JSON数据 |
|||
Gson gson = new Gson(); |
|||
OrderVerificationData orderData = gson.fromJson(orderDataJson, OrderVerificationData.class); |
|||
|
|||
if (orderData != null && orderData.getData() != null && orderData.getData().getResult() != null) { |
|||
orderList = orderData.getData().getResult(); |
|||
|
|||
// 设置适配器 |
|||
adapter = new OrderSelectionAdapter(orderList); |
|||
rvOrderList.setAdapter(adapter); |
|||
|
|||
// 设置点击监听 |
|||
adapter.setOnOrderClickListener(new OrderSelectionAdapter.OnOrderClickListener() { |
|||
@Override |
|||
public void onOrderClick(OrderVerificationData.OrderItem order, int position) { |
|||
LogManager.logInfo(TAG, "选择订单: " + order.getOrder_no()); |
|||
// 更新确认按钮状态 |
|||
btnConfirm.setEnabled(true); |
|||
btnConfirm.setAlpha(1.0f); |
|||
} |
|||
|
|||
@Override |
|||
public void onVerifyClick(OrderVerificationData.OrderItem order, int position) { |
|||
// 直接核销选中的订单 |
|||
performOrderVerification(order); |
|||
} |
|||
}); |
|||
|
|||
LogManager.logInfo(TAG, "成功加载" + orderList.size() + "个订单"); |
|||
} else { |
|||
LogManager.logWarning(TAG, "订单数据为空"); |
|||
showToast("未找到可核销的订单"); |
|||
} |
|||
|
|||
} catch (Exception e) { |
|||
LogManager.logError(TAG, "解析订单数据失败", e); |
|||
showToast("订单数据解析失败"); |
|||
} |
|||
} else { |
|||
LogManager.logError(TAG, "未接收到订单数据"); |
|||
showToast("未接收到订单数据"); |
|||
} |
|||
|
|||
// 初始状态下确认按钮不可用 |
|||
btnConfirm.setEnabled(false); |
|||
btnConfirm.setAlpha(0.5f); |
|||
} |
|||
|
|||
private void setupListeners() { |
|||
// 确认按钮 |
|||
btnConfirm.setOnClickListener(v -> { |
|||
OrderVerificationData.OrderItem selectedOrder = adapter.getSelectedOrder(); |
|||
if (selectedOrder != null) { |
|||
performOrderVerification(selectedOrder); |
|||
} else { |
|||
showToast("请选择要核销的订单"); |
|||
} |
|||
}); |
|||
|
|||
// 取消按钮 |
|||
btnCancel.setOnClickListener(v -> { |
|||
LogManager.logInfo(TAG, "用户取消选择"); |
|||
setResult(RESULT_CANCELED); |
|||
finish(); |
|||
}); |
|||
|
|||
// 返回首页按钮 |
|||
tvBackHome.setOnClickListener(v -> { |
|||
LogManager.logInfo(TAG, "用户点击返回首页"); |
|||
setResult(RESULT_CANCELED); |
|||
finish(); |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 执行订单核销 |
|||
*/ |
|||
private void performOrderVerification(OrderVerificationData.OrderItem order) { |
|||
LogManager.logInfo(TAG, "执行订单核销: " + order.getOrder_no()); |
|||
|
|||
// 停止倒计时 |
|||
stopCountdown(); |
|||
|
|||
// 准备结果数据 |
|||
Intent resultIntent = new Intent(); |
|||
resultIntent.putExtra("selected_order", new Gson().toJson(order)); |
|||
resultIntent.putExtra("order_no", order.getOrder_no()); |
|||
resultIntent.putExtra("verification_code", order.getVerificationCode()); |
|||
resultIntent.putExtra("order_type", order.getOrder_type()); |
|||
resultIntent.putExtra("card_no", order.getInfo() != null ? order.getInfo().getCard_no() : ""); |
|||
resultIntent.putExtra("project", order.getProject()); |
|||
resultIntent.putExtra("verification_type", verificationType); |
|||
|
|||
setResult(RESULT_OK, resultIntent); |
|||
|
|||
// 显示成功提示并跳转到结果页面 |
|||
showToast("订单核销成功"); |
|||
|
|||
// 跳转到核销结果页面 |
|||
Intent intent = new Intent(this, OrderVerificationResultActivity.class); |
|||
intent.putExtra("verification_type", verificationType); |
|||
intent.putExtra("order_no", order.getOrder_no()); |
|||
intent.putExtra("verification_code", order.getVerificationCode()); |
|||
intent.putExtra("order_type", order.getOrder_type()); |
|||
intent.putExtra("card_no", order.getInfo() != null ? order.getInfo().getCard_no() : ""); |
|||
intent.putExtra("status", "核销成功"); |
|||
startActivity(intent); |
|||
|
|||
finish(); |
|||
} |
|||
|
|||
/** |
|||
* 开始倒计时 |
|||
*/ |
|||
private void startCountdown() { |
|||
countdownHandler = new Handler(); |
|||
updateCountdown(); |
|||
} |
|||
|
|||
/** |
|||
* 停止倒计时 |
|||
*/ |
|||
private void stopCountdown() { |
|||
if (countdownHandler != null) { |
|||
countdownHandler.removeCallbacksAndMessages(null); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 更新倒计时显示 |
|||
*/ |
|||
private void updateCountdown() { |
|||
if (countdown > 0) { |
|||
tvBackHome.setText("返回首页(0" + countdown + "s)"); |
|||
countdown--; |
|||
|
|||
if (countdownHandler != null) { |
|||
countdownHandler.postDelayed(this::updateCountdown, 1000); |
|||
} |
|||
} else { |
|||
// 倒计时结束,自动返回 |
|||
LogManager.logInfo(TAG, "倒计时结束,自动返回"); |
|||
setResult(RESULT_CANCELED); |
|||
finish(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 显示Toast消息 |
|||
*/ |
|||
private void showToast(String message) { |
|||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); |
|||
} |
|||
|
|||
@Override |
|||
protected void onDestroy() { |
|||
super.onDestroy(); |
|||
stopCountdown(); |
|||
LogManager.logInfo(TAG, "订单选择页面销毁"); |
|||
} |
|||
|
|||
@Override |
|||
public void onBackPressed() { |
|||
super.onBackPressed(); |
|||
setResult(RESULT_CANCELED); |
|||
} |
|||
} |
@ -0,0 +1,127 @@ |
|||
package com.ouxuan.oxface.orderOX.adapter; |
|||
|
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.widget.TextView; |
|||
import androidx.annotation.NonNull; |
|||
import androidx.recyclerview.widget.RecyclerView; |
|||
import com.ouxuan.oxface.R; |
|||
import com.ouxuan.oxface.orderOX.model.OrderVerificationData; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 订单选择列表适配器 |
|||
*/ |
|||
public class OrderSelectionAdapter extends RecyclerView.Adapter<OrderSelectionAdapter.OrderViewHolder> { |
|||
|
|||
private List<OrderVerificationData.OrderItem> orderList; |
|||
private OnOrderClickListener onOrderClickListener; |
|||
private int selectedPosition = -1; |
|||
|
|||
public interface OnOrderClickListener { |
|||
void onOrderClick(OrderVerificationData.OrderItem order, int position); |
|||
void onVerifyClick(OrderVerificationData.OrderItem order, int position); |
|||
} |
|||
|
|||
public OrderSelectionAdapter(List<OrderVerificationData.OrderItem> orderList) { |
|||
this.orderList = orderList; |
|||
} |
|||
|
|||
public void setOnOrderClickListener(OnOrderClickListener listener) { |
|||
this.onOrderClickListener = listener; |
|||
} |
|||
|
|||
public void setSelectedPosition(int position) { |
|||
int previousPosition = selectedPosition; |
|||
selectedPosition = position; |
|||
|
|||
if (previousPosition != -1) { |
|||
notifyItemChanged(previousPosition); |
|||
} |
|||
if (selectedPosition != -1) { |
|||
notifyItemChanged(selectedPosition); |
|||
} |
|||
} |
|||
|
|||
public OrderVerificationData.OrderItem getSelectedOrder() { |
|||
if (selectedPosition >= 0 && selectedPosition < orderList.size()) { |
|||
return orderList.get(selectedPosition); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public OrderViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |
|||
View view = LayoutInflater.from(parent.getContext()) |
|||
.inflate(R.layout.item_order_selection, parent, false); |
|||
return new OrderViewHolder(view); |
|||
} |
|||
|
|||
@Override |
|||
public void onBindViewHolder(@NonNull OrderViewHolder holder, int position) { |
|||
OrderVerificationData.OrderItem order = orderList.get(position); |
|||
|
|||
// 设置订单信息 |
|||
holder.tvOrderTitle.setText("订单信息 (共" + order.getNumber() + "场次)"); |
|||
holder.tvOrderNumber.setText("订单编号:" + order.getOrder_no()); |
|||
|
|||
// 设置预订信息 - 这里需要根据实际数据结构调整 |
|||
String bookingInfo = order.getProject() + " " + order.getFormattedTimeInfo() + ";"; |
|||
holder.tvBookingInfo.setText("预订信息:" + bookingInfo); |
|||
|
|||
holder.tvProjectName.setText("预订项目:" + order.getProject()); |
|||
holder.tvUsageDate.setText("使用日期:" + order.getFormattedUsageDate()); |
|||
|
|||
// 设置选中状态 |
|||
if (position == selectedPosition) { |
|||
holder.itemView.setBackgroundResource(R.drawable.gate_imageview_radius); |
|||
holder.itemView.setSelected(true); |
|||
} else { |
|||
holder.itemView.setBackgroundResource(R.drawable.gate_radius_compare); |
|||
holder.itemView.setSelected(false); |
|||
} |
|||
|
|||
// 设置点击事件 |
|||
holder.itemView.setOnClickListener(v -> { |
|||
if (onOrderClickListener != null) { |
|||
onOrderClickListener.onOrderClick(order, position); |
|||
} |
|||
setSelectedPosition(position); |
|||
}); |
|||
|
|||
// 去核销按钮点击事件 |
|||
holder.tvVerifyButton.setOnClickListener(v -> { |
|||
if (onOrderClickListener != null) { |
|||
onOrderClickListener.onVerifyClick(order, position); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
@Override |
|||
public int getItemCount() { |
|||
return orderList != null ? orderList.size() : 0; |
|||
} |
|||
|
|||
static class OrderViewHolder extends RecyclerView.ViewHolder { |
|||
TextView tvSessionLabel; |
|||
TextView tvOrderTitle; |
|||
TextView tvOrderNumber; |
|||
TextView tvBookingInfo; |
|||
TextView tvProjectName; |
|||
TextView tvUsageDate; |
|||
TextView tvVerifyButton; |
|||
|
|||
public OrderViewHolder(@NonNull View itemView) { |
|||
super(itemView); |
|||
tvSessionLabel = itemView.findViewById(R.id.tv_session_label); |
|||
tvOrderTitle = itemView.findViewById(R.id.tv_order_title); |
|||
tvOrderNumber = itemView.findViewById(R.id.tv_order_number); |
|||
tvBookingInfo = itemView.findViewById(R.id.tv_booking_info); |
|||
tvProjectName = itemView.findViewById(R.id.tv_project_name); |
|||
tvUsageDate = itemView.findViewById(R.id.tv_usage_date); |
|||
tvVerifyButton = itemView.findViewById(R.id.tv_verify_button); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,245 @@ |
|||
package com.ouxuan.oxface.orderOX.model; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 订单核销数据模型 |
|||
*/ |
|||
public class OrderVerificationData { |
|||
|
|||
private int code; |
|||
private Data data; |
|||
private String message; |
|||
private String extension; |
|||
|
|||
public static class Data { |
|||
private List<OrderItem> result; |
|||
private int skip; |
|||
|
|||
public List<OrderItem> getResult() { |
|||
return result; |
|||
} |
|||
|
|||
public void setResult(List<OrderItem> result) { |
|||
this.result = result; |
|||
} |
|||
|
|||
public int getSkip() { |
|||
return skip; |
|||
} |
|||
|
|||
public void setSkip(int skip) { |
|||
this.skip = skip; |
|||
} |
|||
} |
|||
|
|||
public static class OrderItem { |
|||
private String order_no; |
|||
private String start_time; |
|||
private String end_time; |
|||
private int order_type; |
|||
private String project; |
|||
private int number; |
|||
private List<String> v_code; |
|||
private OrderInfo info; |
|||
private int success; |
|||
private int pv_usage_duration; |
|||
private boolean many_enter; |
|||
|
|||
public static class OrderInfo { |
|||
private String card_no; |
|||
private int rest_number; |
|||
private int status; |
|||
private String user_face_id; |
|||
|
|||
public String getCard_no() { |
|||
return card_no; |
|||
} |
|||
|
|||
public void setCard_no(String card_no) { |
|||
this.card_no = card_no; |
|||
} |
|||
|
|||
public int getRest_number() { |
|||
return rest_number; |
|||
} |
|||
|
|||
public void setRest_number(int rest_number) { |
|||
this.rest_number = rest_number; |
|||
} |
|||
|
|||
public int getStatus() { |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(int status) { |
|||
this.status = status; |
|||
} |
|||
|
|||
public String getUser_face_id() { |
|||
return user_face_id; |
|||
} |
|||
|
|||
public void setUser_face_id(String user_face_id) { |
|||
this.user_face_id = user_face_id; |
|||
} |
|||
} |
|||
|
|||
// Getters and Setters |
|||
public String getOrder_no() { |
|||
return order_no; |
|||
} |
|||
|
|||
public void setOrder_no(String order_no) { |
|||
this.order_no = order_no; |
|||
} |
|||
|
|||
public String getStart_time() { |
|||
return start_time; |
|||
} |
|||
|
|||
public void setStart_time(String start_time) { |
|||
this.start_time = start_time; |
|||
} |
|||
|
|||
public String getEnd_time() { |
|||
return end_time; |
|||
} |
|||
|
|||
public void setEnd_time(String end_time) { |
|||
this.end_time = end_time; |
|||
} |
|||
|
|||
public int getOrder_type() { |
|||
return order_type; |
|||
} |
|||
|
|||
public void setOrder_type(int order_type) { |
|||
this.order_type = order_type; |
|||
} |
|||
|
|||
public String getProject() { |
|||
return project; |
|||
} |
|||
|
|||
public void setProject(String project) { |
|||
this.project = project; |
|||
} |
|||
|
|||
public int getNumber() { |
|||
return number; |
|||
} |
|||
|
|||
public void setNumber(int number) { |
|||
this.number = number; |
|||
} |
|||
|
|||
public List<String> getV_code() { |
|||
return v_code; |
|||
} |
|||
|
|||
public void setV_code(List<String> v_code) { |
|||
this.v_code = v_code; |
|||
} |
|||
|
|||
public OrderInfo getInfo() { |
|||
return info; |
|||
} |
|||
|
|||
public void setInfo(OrderInfo info) { |
|||
this.info = info; |
|||
} |
|||
|
|||
public int getSuccess() { |
|||
return success; |
|||
} |
|||
|
|||
public void setSuccess(int success) { |
|||
this.success = success; |
|||
} |
|||
|
|||
public int getPv_usage_duration() { |
|||
return pv_usage_duration; |
|||
} |
|||
|
|||
public void setPv_usage_duration(int pv_usage_duration) { |
|||
this.pv_usage_duration = pv_usage_duration; |
|||
} |
|||
|
|||
public boolean isMany_enter() { |
|||
return many_enter; |
|||
} |
|||
|
|||
public void setMany_enter(boolean many_enter) { |
|||
this.many_enter = many_enter; |
|||
} |
|||
|
|||
/** |
|||
* 获取格式化的时间信息 |
|||
*/ |
|||
public String getFormattedTimeInfo() { |
|||
if (start_time != null && end_time != null) { |
|||
// 提取时间部分 (HH:mm) |
|||
String startTimeOnly = start_time.substring(11, 16); |
|||
String endTimeOnly = end_time.substring(11, 16); |
|||
return startTimeOnly + "-" + endTimeOnly; |
|||
} |
|||
return ""; |
|||
} |
|||
|
|||
/** |
|||
* 获取格式化的使用日期 |
|||
*/ |
|||
public String getFormattedUsageDate() { |
|||
if (start_time != null) { |
|||
String date = start_time.substring(0, 10); |
|||
// 简单判断是否是今天(这里可以根据实际需求优化) |
|||
return date + " (今天)"; |
|||
} |
|||
return ""; |
|||
} |
|||
|
|||
/** |
|||
* 获取验证码字符串 |
|||
*/ |
|||
public String getVerificationCode() { |
|||
if (v_code != null && !v_code.isEmpty()) { |
|||
return v_code.get(0); |
|||
} |
|||
return ""; |
|||
} |
|||
} |
|||
|
|||
// Getters and Setters for main class |
|||
public int getCode() { |
|||
return code; |
|||
} |
|||
|
|||
public void setCode(int code) { |
|||
this.code = code; |
|||
} |
|||
|
|||
public Data getData() { |
|||
return data; |
|||
} |
|||
|
|||
public void setData(Data data) { |
|||
this.data = data; |
|||
} |
|||
|
|||
public String getMessage() { |
|||
return message; |
|||
} |
|||
|
|||
public void setMessage(String message) { |
|||
this.message = message; |
|||
} |
|||
|
|||
public String getExtension() { |
|||
return extension; |
|||
} |
|||
|
|||
public void setExtension(String extension) { |
|||
this.extension = extension; |
|||
} |
|||
} |
@ -0,0 +1,147 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:background="#80000000"> |
|||
|
|||
<!-- 主弹窗容器 --> |
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_centerInParent="true" |
|||
android:layout_marginLeft="40dp" |
|||
android:layout_marginRight="40dp" |
|||
android:background="@drawable/dialog_background" |
|||
android:orientation="vertical" |
|||
android:padding="0dp"> |
|||
|
|||
<!-- 顶部标题栏 --> |
|||
<RelativeLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="80dp" |
|||
android:background="@drawable/gradient_background" |
|||
android:paddingLeft="20dp" |
|||
android:paddingRight="20dp"> |
|||
|
|||
<!-- 店铺图标和名称 --> |
|||
<LinearLayout |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_centerVertical="true" |
|||
android:gravity="center_vertical" |
|||
android:orientation="horizontal"> |
|||
|
|||
<ImageView |
|||
android:id="@+id/iv_store_icon" |
|||
android:layout_width="40dp" |
|||
android:layout_height="40dp" |
|||
android:layout_marginRight="12dp" |
|||
android:background="@drawable/circle_background" |
|||
android:padding="8dp" |
|||
android:src="@drawable/ic_warriors_logo" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/tv_store_name" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:text="Test门店" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="18sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
<!-- 返回按钮 --> |
|||
<TextView |
|||
android:id="@+id/tv_back_home" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_alignParentRight="true" |
|||
android:layout_centerVertical="true" |
|||
android:background="@drawable/rounded_button_background" |
|||
android:drawableLeft="@drawable/ic_close" |
|||
android:drawablePadding="8dp" |
|||
android:gravity="center" |
|||
android:paddingLeft="12dp" |
|||
android:paddingTop="8dp" |
|||
android:paddingRight="12dp" |
|||
android:paddingBottom="8dp" |
|||
android:text="返回首页(06s)" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="14sp" /> |
|||
|
|||
</RelativeLayout> |
|||
|
|||
<!-- 标题 --> |
|||
<TextView |
|||
android:id="@+id/tv_title" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="30dp" |
|||
android:gravity="center" |
|||
android:text="请选择订单核销" |
|||
android:textColor="@android:color/black" |
|||
android:textSize="24sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<!-- 核销日期 --> |
|||
<TextView |
|||
android:id="@+id/tv_verification_date" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="right" |
|||
android:layout_marginTop="20dp" |
|||
android:layout_marginRight="20dp" |
|||
android:text="核销日期:2025-09-04" |
|||
android:textColor="#666666" |
|||
android:textSize="14sp" /> |
|||
|
|||
<!-- 订单列表 --> |
|||
<androidx.recyclerview.widget.RecyclerView |
|||
android:id="@+id/rv_order_list" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="20dp" |
|||
android:layout_marginBottom="20dp" |
|||
android:maxHeight="400dp" |
|||
android:paddingLeft="20dp" |
|||
android:paddingRight="20dp" /> |
|||
|
|||
<!-- 底部操作按钮 --> |
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="20dp" |
|||
android:layout_marginBottom="30dp" |
|||
android:gravity="center" |
|||
android:orientation="horizontal" |
|||
android:paddingLeft="40dp" |
|||
android:paddingRight="40dp"> |
|||
|
|||
<Button |
|||
android:id="@+id/btn_cancel" |
|||
android:layout_width="0dp" |
|||
android:layout_height="50dp" |
|||
android:layout_marginRight="20dp" |
|||
android:layout_weight="1" |
|||
android:background="@drawable/btn_cancel_bg" |
|||
android:text="取消" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="16sp" /> |
|||
|
|||
<Button |
|||
android:id="@+id/btn_confirm" |
|||
android:layout_width="0dp" |
|||
android:layout_height="50dp" |
|||
android:layout_weight="1" |
|||
android:background="@drawable/btn_confirm_bg" |
|||
android:text="确认核销" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="16sp" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</RelativeLayout> |
@ -0,0 +1,126 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginBottom="15dp" |
|||
android:background="@drawable/gate_radius_compare" |
|||
android:clickable="true" |
|||
android:focusable="true" |
|||
android:orientation="horizontal" |
|||
android:padding="0dp"> |
|||
|
|||
<!-- 左侧场次标识 --> |
|||
<RelativeLayout |
|||
android:layout_width="120dp" |
|||
android:layout_height="match_parent" |
|||
android:background="@drawable/gradient_button" |
|||
android:gravity="center" |
|||
android:minHeight="120dp"> |
|||
|
|||
<TextView |
|||
android:id="@+id/tv_session_label" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_centerInParent="true" |
|||
android:gravity="center" |
|||
android:text="场\n次" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="20sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
</RelativeLayout> |
|||
|
|||
<!-- 虚线分隔 --> |
|||
<View |
|||
android:layout_width="2dp" |
|||
android:layout_height="match_parent" |
|||
android:layout_marginTop="10dp" |
|||
android:layout_marginBottom="10dp" |
|||
android:background="#E0E0E0" /> |
|||
|
|||
<!-- 右侧订单信息 --> |
|||
<LinearLayout |
|||
android:layout_width="0dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:orientation="vertical" |
|||
android:padding="15dp"> |
|||
|
|||
<!-- 订单信息标题 --> |
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:gravity="center_vertical" |
|||
android:orientation="horizontal"> |
|||
|
|||
<TextView |
|||
android:id="@+id/tv_order_title" |
|||
android:layout_width="0dp" |
|||
android:layout_height="wrap_content" |
|||
android:layout_weight="1" |
|||
android:text="订单信息 (共4场次)" |
|||
android:textColor="@android:color/black" |
|||
android:textSize="16sp" |
|||
android:textStyle="bold" /> |
|||
|
|||
<!-- 去核销按钮 --> |
|||
<TextView |
|||
android:id="@+id/tv_verify_button" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:background="@drawable/primary_color_rounded_background" |
|||
android:clickable="true" |
|||
android:focusable="true" |
|||
android:paddingLeft="20dp" |
|||
android:paddingTop="8dp" |
|||
android:paddingRight="20dp" |
|||
android:paddingBottom="8dp" |
|||
android:text="去核销" |
|||
android:textColor="@android:color/white" |
|||
android:textSize="14sp" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
<!-- 订单编号 --> |
|||
<TextView |
|||
android:id="@+id/tv_order_number" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="8dp" |
|||
android:text="订单编号:CC20250904093324823098" |
|||
android:textColor="#666666" |
|||
android:textSize="14sp" /> |
|||
|
|||
<!-- 预订信息 --> |
|||
<TextView |
|||
android:id="@+id/tv_booking_info" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="4dp" |
|||
android:text="预订信息:篮球2号馆 16:30-17:00;" |
|||
android:textColor="#666666" |
|||
android:textSize="14sp" /> |
|||
|
|||
<!-- 预订项目 --> |
|||
<TextView |
|||
android:id="@+id/tv_project_name" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="4dp" |
|||
android:text="预订项目:篮球" |
|||
android:textColor="#666666" |
|||
android:textSize="14sp" /> |
|||
|
|||
<!-- 使用日期 --> |
|||
<TextView |
|||
android:id="@+id/tv_usage_date" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginTop="4dp" |
|||
android:text="使用日期:2025-09-04 (今天)" |
|||
android:textColor="#666666" |
|||
android:textSize="14sp" /> |
|||
|
|||
</LinearLayout> |
|||
|
|||
</LinearLayout> |
@ -0,0 +1,173 @@ |
|||
# 订单核销选择页面实现说明 |
|||
|
|||
## 概述 |
|||
|
|||
已成功实现订单核销选择列表页面,该页面作为传入订单核销列表数据进行选择验证的弹窗页面,在人脸识别界面执行checkOrder请求并获取到列表数据后弹出,覆盖在视频流上。 |
|||
|
|||
## 实现的文件 |
|||
|
|||
### 1. 布局文件 |
|||
- **activity_order_selection.xml** - 主页面布局 |
|||
- **item_order_selection.xml** - 订单列表项布局 |
|||
|
|||
### 2. Java类文件 |
|||
- **OrderSelectionActivity.java** - 主Activity类 |
|||
- **OrderVerificationData.java** - 数据模型类 |
|||
- **OrderSelectionAdapter.java** - RecyclerView适配器 |
|||
|
|||
### 3. 配置文件 |
|||
- **AndroidManifest.xml** - 添加了OrderSelectionActivity注册 |
|||
|
|||
## 功能特性 |
|||
|
|||
### 1. 弹窗样式设计 |
|||
- **透明背景**: 使用透明主题,覆盖在视频流上 |
|||
- **居中显示**: 弹窗居中显示,符合UI设计要求 |
|||
- **圆角设计**: 使用现有的drawable资源创建美观界面 |
|||
|
|||
### 2. 数据处理 |
|||
- **JSON解析**: 自动解析人脸验证接口返回的JSON数据 |
|||
- **数据模型**: 完整的订单数据模型,支持所有字段 |
|||
- **格式化显示**: 自动格式化时间、日期等信息 |
|||
|
|||
### 3. 交互功能 |
|||
- **订单选择**: 点击订单卡片进行选择 |
|||
- **去核销按钮**: 每个订单都有独立的核销按钮 |
|||
- **倒计时返回**: 6秒倒计时自动返回 |
|||
- **手动返回**: 支持取消和返回首页操作 |
|||
|
|||
### 4. 集成支持 |
|||
- **网络请求集成**: 与现有的网络请求管理器完美集成 |
|||
- **结果处理**: 自动处理选择结果并跳转到核销结果页 |
|||
- **摄像头控制**: 自动暂停和恢复摄像头预览 |
|||
|
|||
## 使用流程 |
|||
|
|||
### 1. 触发条件 |
|||
```java |
|||
// 在人脸验证成功后自动触发 |
|||
modeType = OrderVerificationManager.TYPE_FACE_VERIFICATION; |
|||
verifyCode = faceBase64; // 人脸base64数据 |
|||
getCheckOrder(); // 执行订单查验 |
|||
``` |
|||
|
|||
### 2. 数据流转 |
|||
``` |
|||
人脸验证 → 网络请求 → JSON数据解析 → 显示选择页面 → 用户选择 → 核销结果 |
|||
``` |
|||
|
|||
### 3. 页面跳转 |
|||
```java |
|||
// 自动跳转到订单选择页面 |
|||
Intent intent = new Intent(this, OrderSelectionActivity.class); |
|||
intent.putExtra(OrderSelectionActivity.EXTRA_ORDER_DATA, orderDataJson); |
|||
intent.putExtra(OrderSelectionActivity.EXTRA_VERIFICATION_TYPE, verificationType); |
|||
startActivityForResult(intent, 1002); |
|||
``` |
|||
|
|||
## JSON数据格式支持 |
|||
|
|||
页面完全支持您提供的JSON格式: |
|||
|
|||
```json |
|||
{ |
|||
"code": 0, |
|||
"data": { |
|||
"result": [ |
|||
{ |
|||
"order_no": "MC20250313171548535218", |
|||
"start_time": "2025-03-13 17:15:51", |
|||
"end_time": "2026-03-13 17:15:51", |
|||
"order_type": 3, |
|||
"project": "测试年卡", |
|||
"number": 100, |
|||
"v_code": ["2503215744"], |
|||
"info": { |
|||
"card_no": "250313397", |
|||
"rest_number": 100, |
|||
"status": 0, |
|||
"user_face_id": "" |
|||
}, |
|||
"success": 0, |
|||
"pv_usage_duration": 0, |
|||
"many_enter": false |
|||
} |
|||
], |
|||
"skip": 0 |
|||
}, |
|||
"message": "", |
|||
"extension": "extension_fixed" |
|||
} |
|||
``` |
|||
|
|||
## 页面展示效果 |
|||
|
|||
### 1. 头部区域 |
|||
- 店铺图标和名称 |
|||
- 返回首页按钮(带倒计时) |
|||
|
|||
### 2. 标题区域 |
|||
- "请选择订单核销" 标题 |
|||
- 当前核销日期显示 |
|||
|
|||
### 3. 订单列表 |
|||
- 左侧场次标识(橙色背景) |
|||
- 右侧订单详细信息: |
|||
- 订单信息(场次数量) |
|||
- 订单编号 |
|||
- 预订信息(时间段) |
|||
- 预订项目 |
|||
- 使用日期 |
|||
- 右上角"去核销"按钮 |
|||
|
|||
### 4. 底部操作 |
|||
- 取消按钮 |
|||
- 确认核销按钮 |
|||
|
|||
## 技术特点 |
|||
|
|||
### 1. 响应式设计 |
|||
- 支持不同屏幕尺寸 |
|||
- 列表最大高度限制,超出时可滚动 |
|||
- 自适应内容高度 |
|||
|
|||
### 2. 状态管理 |
|||
- 选中状态高亮显示 |
|||
- 按钮启用/禁用状态控制 |
|||
- 倒计时状态更新 |
|||
|
|||
### 3. 错误处理 |
|||
- JSON解析异常处理 |
|||
- 数据为空的处理 |
|||
- 网络错误的友好提示 |
|||
|
|||
### 4. 性能优化 |
|||
- RecyclerView复用机制 |
|||
- 内存泄漏防护 |
|||
- 生命周期管理 |
|||
|
|||
## 扩展性 |
|||
|
|||
### 1. 样式定制 |
|||
- 可通过修改drawable资源调整样式 |
|||
- 支持主题色彩定制 |
|||
- 布局参数易于调整 |
|||
|
|||
### 2. 功能扩展 |
|||
- 支持添加更多订单字段显示 |
|||
- 可扩展筛选和搜索功能 |
|||
- 支持批量操作 |
|||
|
|||
### 3. 数据适配 |
|||
- 模型类支持扩展新字段 |
|||
- 适配器支持不同数据类型 |
|||
- 格式化方法可自定义 |
|||
|
|||
## 注意事项 |
|||
|
|||
1. **权限要求**: 确保应用有必要的网络和相机权限 |
|||
2. **主题配置**: 使用了Theme.Transparent主题,确保主题文件存在 |
|||
3. **资源依赖**: 依赖现有的drawable资源,确保资源文件完整 |
|||
4. **内存管理**: 页面销毁时会自动清理资源和停止倒计时 |
|||
|
|||
这个实现完全符合您的需求,提供了完整的订单选择功能,并与现有的网络请求架构完美集成。 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue