package com.example.kucun2.ui.jinhuo;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.SearchView;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.example.kucun2.R;
import com.example.kucun2.entity.*;
import com.example.kucun2.entity.data.Data;
import com.example.kucun2.entity.data.ReflectionJsonUtils;
import com.example.kucun2.function.Adapter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
public class AddInventoryFragment extends Fragment {
// UI组件声明
private Spinner spinnerDingdan, spinnerChanpin, spinnerZujian, spinnerBancai;
private EditText etShuliang;
private RadioGroup rgType;
private Button btnNewDingdan, btnAddChanpin, btnAddZujian;
private ProgressDialog progressDialog; // 添加进度条
// 当前选中项
private Dingdan selectedDingdan;
private Chanpin selectedChanpin;
private Zujian selectedZujian;
private Bancai selectedBancai;
private View rootView;
// 日期格式化工具
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
private static final String TAG = "AddInventoryFragment";
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_add_inventory, container, false);
initViews(rootView);
setupEventListeners();
// 初始化下拉框数据(使用已加载的数据)
setupSpinnersWithExistingData();
return rootView;
}
/** 初始化UI组件 */
private void initViews(View view) {
spinnerDingdan = view.findViewById(R.id.spinner_dingdan);
spinnerChanpin = view.findViewById(R.id.spinner_chanpin);
spinnerZujian = view.findViewById(R.id.spinner_zujian);
spinnerBancai = view.findViewById(R.id.spinner_bancai);
etShuliang = view.findViewById(R.id.et_shuliang);
rgType = view.findViewById(R.id.rg_type);
btnNewDingdan = view.findViewById(R.id.btn_new_dingdan);
btnAddChanpin = view.findViewById(R.id.btn_add_chanpin);
btnAddZujian = view.findViewById(R.id.btn_add_zujian);
}
/**
* 使用已加载的数据初始化下拉框
*/
private void setupSpinnersWithExistingData() {
// 1. 设置订单下拉框
setupDingdanSpinner();
// 2. 如果存在选中的订单,设置产品下拉框
if (selectedDingdan != null) {
setupChanpinSpinner(selectedDingdan);
}
// 3. 如果存在选中的产品,设置组件下拉框
if (selectedChanpin != null) {
setupZujianSpinner(selectedChanpin);
}
// 4. 如果存在选中的产品和组件,设置板材下拉框
if (selectedChanpin != null && selectedZujian != null) {
setupBancaiSpinner(selectedChanpin, selectedZujian);
}
}
// 修改 setupDingdanSpinner 方法,使用现有数据
private void setupDingdanSpinner() {
// 过滤掉预置对象(ID=-1)
List<Dingdan> validDingdans = Data.dingdans.stream()
.filter(d -> d.getId() != null)
.collect(Collectors.toList());
Adapter.setupDingdanSpinner(spinnerDingdan, validDingdans, getContext());
// 设置默认选中项(如果有)
if (!validDingdans.isEmpty()) {
spinnerDingdan.setSelection(0);
selectedDingdan = validDingdans.get(0);
}
}
/** 设置事件监听器 */
private void setupEventListeners() {
// 新建订单按钮
btnNewDingdan.setOnClickListener(v -> showNewDingdanDialog());
// 添加产品按钮
btnAddChanpin.setOnClickListener(v -> showAddChanpinDialog());
// 添加组件按钮
btnAddZujian.setOnClickListener(v -> {
if (selectedChanpin == null) {
Toast.makeText(getContext(), "请先选择产品", Toast.LENGTH_SHORT).show();
return;
}
showCreateZujianDialog();
});
// 提交按钮
rootView.findViewById(R.id.btn_submit).setOnClickListener(v -> addInventoryRecord());
// 订单下拉框监听
spinnerDingdan.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedDingdan = (Dingdan) parent.getItemAtPosition(position);
setupChanpinSpinner(selectedDingdan);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
/** 设置产品下拉框 */
private void setupChanpinSpinner(Dingdan dingdan) {
List<Chanpin> chanpins = new ArrayList<>();
if (dingdan != null && dingdan.getDingdanChanpin() != null) {
for (Dingdan_Chanpin dc : dingdan.getDingdanChanpin()) {
if (dc != null && dc.getChanpin() != null) {
chanpins.add(dc.getChanpin());
}
}
}
Adapter.setupChanpinSpinner(spinnerChanpin, chanpins, getContext());
spinnerChanpin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedChanpin = (Chanpin) parent.getItemAtPosition(position);
if (selectedChanpin != null) {
setupZujianSpinner(selectedChanpin);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
/** 设置组件下拉框 */
private void setupZujianSpinner(Chanpin chanpin) {
List<Zujian> zujians = new ArrayList<>();
for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) {
zujians.add(cz.getZujian());
}
Adapter.setupZujianSpinner(spinnerZujian, zujians, getContext());
spinnerZujian.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedZujian = (Zujian) parent.getItemAtPosition(position);
setupBancaiSpinner(selectedChanpin, selectedZujian);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
/** 设置板材下拉框 */
private void setupBancaiSpinner(Chanpin chanpin, Zujian zujian) {
List<Bancai> bancais = new ArrayList<>();
for (Chanpin_Zujian cz : chanpin.getChanpinZujian()) {
if (cz.getZujian().getId().equals(zujian.getId())) {
bancais.add(cz.getBancai());
}
}
Adapter.setupBancaiSpinners(spinnerBancai, bancais, getContext());
spinnerBancai.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedBancai = (Bancai) parent.getItemAtPosition(position);
Log.d(TAG, "Selected bancai: " + (selectedBancai != null ? selectedBancai.TableText() : "null"));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
selectedBancai = null;
}
});
// 设置默认选中项
if (!bancais.isEmpty()) {
spinnerBancai.setSelection(0);
selectedBancai = bancais.get(0); // 确保默认选中第一项
}
}
/** 添加库存记录 */
private void addInventoryRecord() {
// 验证必填项
if (selectedDingdan == null || selectedChanpin == null ||
selectedZujian == null || selectedBancai == null) {
Log.d("addInventoryRecord","selectedDingdan:"+selectedDingdan);
Log.d("addInventoryRecord","selectedChanpin:"+selectedChanpin);
Log.d("addInventoryRecord","selectedZujian:"+selectedZujian);
Log.d("addInventoryRecord","selectedBancai:"+selectedBancai);
Toast.makeText(getContext(), "请选择订单、产品、组件和板材", Toast.LENGTH_SHORT).show();
return;
}
String shuliangStr = etShuliang.getText().toString().trim();
if (shuliangStr.isEmpty()) {
Toast.makeText(getContext(), "请输入数量", Toast.LENGTH_SHORT).show();
return;
}
try {
int shuliang = Integer.parseInt(shuliangStr);
boolean isJinhuo = rgType.getCheckedRadioButtonId() == R.id.rb_jinhuo;
User currentUser = new User(1, "当前用户", "user", "password", 1);
createRecord(selectedDingdan, selectedChanpin, selectedZujian,
selectedBancai, shuliang, isJinhuo, currentUser);
Toast.makeText(getContext(), "记录添加成功", Toast.LENGTH_SHORT).show();
etShuliang.setText("");
} catch (NumberFormatException e) {
Toast.makeText(getContext(), "请输入有效的数量", Toast.LENGTH_SHORT).show();
}
}
/** 创建库存记录 */
private void createRecord(Dingdan dingdan, Chanpin chanpin, Zujian zujian,
Bancai bancai, int shuliang, boolean isJinhuo, User user) {
if (isJinhuo) {
Jinhuo jinhuo = new Jinhuo();
jinhuo.setId(Data.jinhuos.size() + 1);
jinhuo.setDingdan(dingdan);
jinhuo.setChanpin(chanpin);
jinhuo.setZujian(zujian);
jinhuo.setBancai(bancai);
jinhuo.setShuliang(shuliang);
jinhuo.setDate(new Date());
jinhuo.setUser(user);
Data.jinhuos.add(jinhuo);
} else {
shuliang = -shuliang;
}
updateKucun(bancai, shuliang);
}
/** 更新库存 */
private void updateKucun(Bancai bancai, int changeAmount) {
for (Kucun k : Data.kucuns) {
if (k.getBancai().getId().equals(bancai.getId())) {
k.setShuliang(k.getShuliang() + changeAmount);
return;
}
}
// 创建新库存记录
Kucun newKucun = new Kucun();
newKucun.setId(Data.kucuns.size() + 1);
newKucun.setBancai(bancai);
newKucun.setShuliang(Math.max(changeAmount, 0));
Data.kucuns.add(newKucun);
}
/** 显示添加产品对话框 */
private void showAddChanpinDialog() {
if (selectedDingdan == null) {
Toast.makeText(getContext(), "请先选择订单", Toast.LENGTH_SHORT).show();
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle("添加产品到订单");
View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_add_chanpin, null);
Spinner spinnerChanpinSelection = dialogView.findViewById(R.id.spinner_chanpin_selection);
// 设置产品下拉框
if (Data.chanpins.isEmpty()) {
Toast.makeText(getContext(), "没有可用的产品,请先创建产品", Toast.LENGTH_SHORT).show();
return;
}
Adapter.setupChanpinSpinner(spinnerChanpinSelection, Data.chanpins, getContext());
builder.setView(dialogView);
builder.setPositiveButton("添加", (dialog, which) -> {
Chanpin selected = (Chanpin) spinnerChanpinSelection.getSelectedItem();
if (selected != null) addChanpinToDingdan(selected);
});
builder.setNegativeButton("取消", null);
builder.show();
}
/** 添加产品到订单 */
private void addChanpinToDingdan(Chanpin chanpin) {
// 检查是否已添加
for (Dingdan_Chanpin dc : selectedDingdan.getDingdanChanpin()) {
if (dc.getChanpin().getId().equals(chanpin.getId())) {
Toast.makeText(getContext(), "该产品已添加到订单", Toast.LENGTH_SHORT).show();
return;
}
}
// 创建关联对象
Dingdan_Chanpin dc = new Dingdan_Chanpin();
dc.setChanpin(chanpin);
dc.setDingdan(selectedDingdan);
selectedDingdan.getDingdanChanpin().add(dc);
// 刷新UI
setupChanpinSpinner(selectedDingdan);
spinnerChanpin.setSelection(selectedDingdan.getDingdanChanpin().size() - 1);
Toast.makeText(getContext(), "产品添加成功", Toast.LENGTH_SHORT).show();
}
/** 显示新建订单对话框 */
private void showNewDingdanDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle("新建订单");
View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_new_dingdan, null);
// 初始化视图
EditText etOrderNumber = dialogView.findViewById(R.id.et_order_number);
EditText etOrderDate = dialogView.findViewById(R.id.et_order_date);
EditText etdeliveryDate = dialogView.findViewById(R.id.et_delivery_date);
Button btnPickOrderDate = dialogView.findViewById(R.id.btn_pick_order_date);
Button btnPickdeliveryDate = dialogView.findViewById(R.id.btn_pick_delivery_date);
// 设置默认日期
etOrderDate.setText(dateFormat.format(new Date()));
etdeliveryDate.setText(dateFormat.format(new Date()));
// 日期选择器
btnPickOrderDate.setOnClickListener(v -> showDatePicker(etOrderDate));
btnPickdeliveryDate.setOnClickListener(v -> showDatePicker(etdeliveryDate));
builder.setView(dialogView);
builder.setPositiveButton("创建", (dialog, which) -> {
String orderNumber = etOrderNumber.getText().toString().trim();
if (orderNumber.isEmpty()) {
Toast.makeText(getContext(), "请输入订单号", Toast.LENGTH_SHORT).show();
return;
}
// 检查订单号是否重复
for (Dingdan d : Data.dingdans) {
if (d.getNumber().equals(orderNumber)) {
Toast.makeText(getContext(), "订单号已存在", Toast.LENGTH_SHORT).show();
return;
}
}
try {
Date orderDate = dateFormat.parse(etOrderDate.getText().toString());
Date deliveryDate = dateFormat.parse(etdeliveryDate.getText().toString());
createAndSaveDingdan(orderNumber, orderDate, deliveryDate);
} catch (ParseException e) {
Toast.makeText(getContext(), "日期格式错误", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", null);
builder.show();
}
/** 创建并保存订单 */
private void createAndSaveDingdan(String orderNumber, Date orderDate, Date deliveryDate) {
Dingdan newDingdan = new Dingdan();
newDingdan.setId(Data.dingdans.size() + 1);
newDingdan.setNumber(orderNumber);
newDingdan.setXiadan(orderDate);
newDingdan.setJiaohuo(deliveryDate);
newDingdan.setDingdanChanpin(new ArrayList<>());
Data.dingdans.add(newDingdan);
// 刷新UI
setupDingdanSpinner();
spinnerDingdan.setSelection(Data.dingdans.size() - 1);
Toast.makeText(getContext(), "新建订单成功", Toast.LENGTH_SHORT).show();
}
/** 显示日期选择器 */
private void showDatePicker(EditText targetField) {
Calendar cal = Calendar.getInstance();
new DatePickerDialog(requireContext(),
(view, year, month, dayOfMonth) -> {
Calendar selected = Calendar.getInstance();
selected.set(year, month, dayOfMonth);
targetField.setText(dateFormat.format(selected.getTime()));
},
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH)
).show();
}
/** 显示创建组件对话框 */
private void showCreateZujianDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
builder.setTitle("添加新组件");
View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_create_zujian_bancai, null);
// 初始化视图
Spinner etZujianName = dialogView.findViewById(R.id.et_zujian_name);
Spinner spinnerbancai = dialogView.findViewById(R.id.spinner_bancai);
SearchView searchBancai = dialogView.findViewById(R.id.search_bancai);
EditText numberOne_howmany=dialogView.findViewById(R.id.number_one_howmany);
// 设置适配器
Adapter.setupZujianSpinner(etZujianName, Data.zujians, getContext());
Adapter.setupBancaiSpinners(spinnerbancai, Data.bancais, getContext());
// 设置搜索功能
searchBancai.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) { return false; }
@Override
public boolean onQueryTextChange(String newText) {
List<Bancai> filtered = new ArrayList<>();
for (Bancai b : Data.bancais) {
if (b.TableText().toLowerCase().contains(newText.toLowerCase())) {
filtered.add(b);
}
}
Adapter.setupBancaiSpinners(spinnerbancai, filtered, getContext());
return true;
}
});
builder.setView(dialogView);
builder.setPositiveButton("创建", (dialog, which) -> {
Zujian zujian = (Zujian) etZujianName.getSelectedItem();
Bancai bancai = (Bancai) spinnerbancai.getSelectedItem();
String One_howmany= numberOne_howmany.getText().toString();
if (zujian == null || bancai == null) {
Toast.makeText(getContext(), "请选择组件和板材", Toast.LENGTH_SHORT).show();
return;
}
if (One_howmany==null){
Toast.makeText(getContext(), "请选择板材生产多少组件", Toast.LENGTH_SHORT).show();
return;
}
// 检查是否已存在相同的组合
boolean isDuplicate = false;
for (Chanpin_Zujian existing : selectedChanpin.getChanpinZujian()) {
if (existing.getZujian().equals(zujian) &&
existing.getBancai().equals(bancai)) {
isDuplicate = true;
break;
}
}
if (isDuplicate) {
Toast.makeText(getContext(), "该产品和组件组合已存在,不能重复添加", Toast.LENGTH_SHORT).show();
return;
}
// 创建关联对象
Chanpin_Zujian cz = new Chanpin_Zujian();
cz.setZujian(zujian);
cz.setBancai(bancai);
cz.setChanpin(selectedChanpin);
cz.setOne_howmany(Double.valueOf(One_howmany));//double类型
selectedChanpin.getChanpinZujian().add(cz);
Dingdan_chanpin_zujian dz=new Dingdan_chanpin_zujian();
dz.setBancai(selectedBancai);
dz.setZujian(cz);
Data.Dingdan_chanpin_zujians.add(dz);
// 刷新UI
setupZujianSpinner(selectedChanpin);
spinnerZujian.setSelection(selectedChanpin.getChanpinZujian().size() - 1);
Toast.makeText(getContext(), "组件添加成功", Toast.LENGTH_SHORT).show();
});
builder.setNegativeButton("取消", null);
builder.show();
}
}package com.example.kucun2.ui.dingdan;
import android.app.AlertDialog;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.PopupMenu;
import android.widget.SearchView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.example.kucun2.MainActivity;
import com.example.kucun2.R;
import com.example.kucun2.View.HorizontalScrollTextView;
import com.example.kucun2.entity.Bancai;
import com.example.kucun2.entity.Chanpin;
import com.example.kucun2.entity.Chanpin_Zujian;
import com.example.kucun2.entity.Dingdan;
import com.example.kucun2.entity.Dingdan_chanpin_zujian;
import com.example.kucun2.entity.Dingdan_Chanpin;
import com.example.kucun2.entity.Zujian;
import com.example.kucun2.entity.data.Data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 订单展示Fragment - 用于展示订单、产品、组件和板材的四级关系数据
*
* 主要功能:
* 1. 从全局数据源加载订单数据
* 2. 建立订单->产品->组件->板材的四级关系映射
* 3. 提供表格展示数据
* 4. 支持按列排序
* 5. 支持多列搜索过滤
* 6. 提供行操作(查看详情、编辑、删除)
*/
public class OrderDisplayFragment extends Fragment {
//=== 视图组件 ===//
private TableLayout table; // 表格布局,用于显示数据行
private HorizontalScrollView horizontalScrollView; // 水平滚动容器,容纳表格
private SearchView searchView; // 搜索框,用于数据过滤
private Spinner columnSelector; // 列选择器,指定搜索列
private View rootView; // Fragment的根视图
//=== 数据管理 ===//
private List<Object[]> allTableRowsData = new ArrayList<>(); // 所有数据行(未过滤)
private List<Object[]> filteredTableRowsData = new ArrayList<>(); // 过滤后的数据行
private boolean isDataLoaded = false; // 数据加载状态标志
//=== 排序状态 ===//
private int currentSortColumn = -1; // 当前排序列索引(-1表示未排序)
private boolean sortAscending = true; // 排序方向(true为升序)
//=== Fragment生命周期方法 ===//
/**
* 创建Fragment视图
*
* @param inflater 布局填充器
* @param container 父容器
* @param savedInstanceState 保存的状态
* @return 创建的视图
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// 1. 填充布局
rootView = inflater.inflate(R.layout.fragment_order_display, container, false);
// 2. 初始化视图组件
initViews();
// 3. 初始化列选择器
initColumnSelector();
// 4. 设置搜索功能
setupSearchFunctionality();
// 5. 数据加载逻辑
if (Data.dingdans.isEmpty()) {
// 显示加载指示器
showLoadingIndicator();
// 设置数据加载监听器
setupDataLoadListener();
} else {
// 填充表格数据
isDataLoaded = true;
}
return rootView;
}
/**
* 销毁视图时清理资源
*/
@Override
public void onDestroyView() {
super.onDestroyView();
// 1. 清除视图引用,防止内存泄漏
horizontalScrollView = null;
table = null;
rootView = null;
}
//=== 初始化方法 ===//
/**
* 初始化视图组件
*/
private void initViews() {
// 1. 查找视图组件
table = rootView.findViewById(R.id.orderTable);
horizontalScrollView = rootView.findViewById(R.id.horizontalScrollContainer);
searchView = rootView.findViewById(R.id.search_view);
columnSelector = rootView.findViewById(R.id.column_selector);
// 2. 添加表格表头
addTableHeader(table);
}
/**
* 初始化列选择器(用于指定搜索列)
*/
private void initColumnSelector() {
// 1. 创建适配器(使用资源数组)
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
requireContext(),
R.array.table_headers, // 表头字符串数组资源
android.R.layout.simple_spinner_item
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// 2. 设置适配器和默认选择
columnSelector.setAdapter(adapter);
columnSelector.setSelection(0); // 默认选择第一项(全部列)
// 3. 设置选择监听器
columnSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// 当列选择变化时应用搜索过滤
applySearchFilter();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// 无操作
}
});
}
/**
* 设置搜索功能
*/
private void setupSearchFunctionality() {
// 设置搜索查询监听器
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// 提交查询时应用过滤
applySearchFilter();
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
// 文本变化时实时应用过滤
applySearchFilter();
return true;
}
});
}
//=== 数据加载与处理 ===//
/**
* 填充表格数据 - 核心数据重组逻辑
* 建立订单->产品->组件->板材的四级关系映射
*/
private void fillTableData() {
// 1. 创建映射关系提高查询效率
Map<Integer, List<Dingdan_Chanpin>> orderProductMap = new HashMap<>();
Map<Integer, List<Chanpin_Zujian>> productComponentMap = new HashMap<>();
Map<Integer, List<Dingdan_chanpin_zujian>> componentMaterialMap = new HashMap<>();
// 2. 构建映射关系
// 2.1 订单-产品映射
for (Dingdan_Chanpin op : Data.dingdan_chanpins) {
if (op != null && op.getDingdan() != null) {
orderProductMap.computeIfAbsent(
op.getDingdan().getId(),
k -> new ArrayList<>()
).add(op);
}
}
// 2.2 产品-组件映射
for (Chanpin_Zujian cz : Data.chanpin_zujians) {
if (cz.getChanpin() != null) {
productComponentMap.computeIfAbsent(
cz.getChanpin().getId(),
k -> new ArrayList<>()
).add(cz);
}
}
// 2.3 组件-板材映射
for (Dingdan_chanpin_zujian dm : Data.Dingdan_chanpin_zujians) {
if (dm.getZujian() != null) {
componentMaterialMap.computeIfAbsent(
dm.getZujian().getId(),
k -> new ArrayList<>()
).add(dm);
}
}
// 3. 重组数据(四级关系遍历)
for (Dingdan order : Data.dingdans) {
List<Dingdan_Chanpin> products = orderProductMap.get(order.getId());
if (products != null) {
for (Dingdan_Chanpin op : products) {
Chanpin product = op.getChanpin();
if (product == null) continue;
List<Chanpin_Zujian> components = productComponentMap.get(product.getId());
if (components == null) continue;
for (Chanpin_Zujian cz : components) {
Zujian component = cz.getZujian();
if (component == null) continue;
List<Dingdan_chanpin_zujian> materials = componentMaterialMap.get(component.getId());
if (materials == null) continue;
for (Dingdan_chanpin_zujian dm : materials) {
// 创建行数据并添加到数据集
Object[] rowData = createRowData(order, product, op, cz, dm);
allTableRowsData.add(rowData);
filteredTableRowsData.add(rowData);
}
}
}
}
}
// 4. 初始排序(不指定列,保持原始顺序)
sortTableData(-1, true);
}
/**
* 创建表格行数据对象
*
* @param order 订单对象
* @param product 产品对象
* @param dingdan_chanpin 订单-产品关联对象
* @param component 产品-组件关联对象
* @param material 组件-板材关联对象
* @return 行数据数组
*/
private Object[] createRowData(Dingdan order, Chanpin product, Dingdan_Chanpin dingdan_chanpin,
Chanpin_Zujian component, Dingdan_chanpin_zujian material) {
Bancai board = material.getBancai();
return new Object[]{
order.getNumber(), // 订单号
product.getBianhao(), // 产品编号
dingdan_chanpin.getShuliang(),// 产品数量
component.getZujian().getName(), // 组件名
board != null ? board.TableText() : "N/A", // 板材信息
Math.round(component.getOne_howmany()), // 每组件所需板材数
material.getShuliang(), // 板材订购数量
"操作" // 操作按钮
};
}
//=== 表格操作 ===//
/**
* 排序表格数据
*
* @param columnIndex 列索引(-1表示初始状态)
* @param ascending 是否升序
*/
private void sortTableData(int columnIndex, boolean ascending) {
// 1. 更新排序状态
if (columnIndex >= 0) {
if (currentSortColumn == columnIndex) {
// 同一列点击切换排序方向
sortAscending = !ascending;
} else {
// 不同列点击设为升序
currentSortColumn = columnIndex;
sortAscending = true;
}
}
// 2. 创建自定义比较器
Comparator<Object[]> comparator = (row1, row2) -> {
if (currentSortColumn < 0) return 0; // 不排序
Object val1 = row1[currentSortColumn];
Object val2 = row2[currentSortColumn];
// 2.1 处理空值
if (val1 == null && val2 == null) return 0;
if (val1 == null) return -1;
if (val2 == null) return 1;
try {
// 2.2 数值列比较(第3、6、7列)
if (currentSortColumn == 2 || currentSortColumn == 5 || currentSortColumn == 6) {
double num1 = Double.parseDouble(val1.toString());
double num2 = Double.parseDouble(val2.toString());
return sortAscending ? Double.compare(num1, num2) : Double.compare(num2, num1);
}
// 2.3 字符串列比较
else {
String str1 = val1.toString().toLowerCase();
String str2 = val2.toString().toLowerCase();
return sortAscending ? str1.compareTo(str2) : str2.compareTo(str1);
}
} catch (NumberFormatException e) {
// 2.4 数值解析失败时按字符串比较
String str1 = val1.toString().toLowerCase();
String str2 = val2.toString().toLowerCase();
return sortAscending ? str1.compareTo(str2) : str2.compareTo(str1);
}
};
// 3. 执行排序或直接复制数据
if (columnIndex == -1) {
// 初始状态:复制所有数据
filteredTableRowsData.clear();
filteredTableRowsData.addAll(allTableRowsData);
} else {
// 执行排序
Collections.sort(filteredTableRowsData, comparator);
}
// 4. 刷新表格显示
refreshTableWithData(filteredTableRowsData);
}
/**
* 刷新表格显示
*
* @param dataToShow 要显示的数据集合
*/
private void refreshTableWithData(Iterable<? extends Object[]> dataToShow) {
// 1. 清除旧行(保留表头)
removeAllRowsSafely();
// 2. 添加新行
int addedRows = 0;
for (Object[] rowData : dataToShow) {
addTableRow(rowData);
addedRows++;
}
// 3. 空数据处理
if (addedRows == 0) {
addEmptyTableRow();
}
}
/**
* 添加表格行(动态创建视图)
*
* @param rowData 行数据数组
*/
private void addTableRow(Object[] rowData) {
// 1. 创建行容器
TableRow row = new TableRow(requireContext());
TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT
);
row.setLayoutParams(rowParams);
row.setMinimumHeight(dpToPx(36)); // 设置最小高度
// 2. 遍历列数据
for (int i = 0; i < rowData.length; i++) {
if (i == rowData.length - 1) {
// 2.1 操作列(按钮)
Button actionButton = new Button(requireContext());
actionButton.setText("操作");
actionButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
actionButton.setBackgroundResource(R.drawable.btn_selector); // 自定义按钮样式
// 按钮布局参数
TableRow.LayoutParams btnParams = new TableRow.LayoutParams(
0,
TableRow.LayoutParams.WRAP_CONTENT,
0.5f // 权重
);
btnParams.setMargins(dpToPx(1), dpToPx(1), dpToPx(1), dpToPx(1));
actionButton.setLayoutParams(btnParams);
// 设置点击监听
actionButton.setOnClickListener(v -> handleRowAction(rowData, v));
row.addView(actionButton);
} else {
// 2.2 数据列(文本)
HorizontalScrollTextView textView = new HorizontalScrollTextView(requireContext());
textView.setText(String.valueOf(rowData[i]));
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
// 设置内边距
int padding = dpToPx(8);
textView.setPadding(padding, padding/2, padding, padding);
textView.setBackgroundResource(R.drawable.cell_border); // 单元格边框
// 根据内容长度设置权重(长内容占更多空间)
float weight = rowData[i].toString().length() > 10 ? 2.0f : 1.0f;
TableRow.LayoutParams colParams = new TableRow.LayoutParams(
0,
TableRow.LayoutParams.MATCH_PARENT,
weight
);
textView.setLayoutParams(colParams);
row.addView(textView);
}
}
// 3. 将行添加到表格
table.addView(row);
}
//=== 用户交互处理 ===//
/**
* 处理行操作按钮点击
*
* @param rowData 行数据
* @param anchorButton 锚点按钮(用于定位弹出菜单)
*/
private void handleRowAction(Object[] rowData, View anchorButton) {
// 1. 创建弹出菜单
PopupMenu popupMenu = new PopupMenu(requireContext(), anchorButton);
popupMenu.getMenuInflater().inflate(R.menu.row_actions_menu, popupMenu.getMenu());
popupMenu.setGravity(Gravity.BOTTOM); // 菜单显示在下方
// 2. 设置菜单项点击监听
popupMenu.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
if (itemId == R.id.action_view_details) {
// 查看详情
showDetailDialog(rowData[0].toString(), rowData[1].toString());
return true;
} else if (itemId == R.id.action_edit) {
// 编辑行
editRowData(rowData);
return true;
} else if (itemId == R.id.action_delete) {
// 删除行(带确认)
deleteRowWithConfirm(rowData);
return true;
}
return false;
});
// 3. 显示菜单
popupMenu.show();
}
/**
* 删除行数据(带确认对话框)
*
* @param rowData 要删除的行数据
*/
private void deleteRowWithConfirm(Object[] rowData) {
new AlertDialog.Builder(requireContext())
.setTitle("确认删除")
.setMessage("确定要删除订单 " + rowData[0] + " 吗?")
.setPositiveButton("删除", (dialog, which) -> deleteRow(rowData))
.setNegativeButton("取消", null)
.show();
}
/**
* 实际删除逻辑
*
* @param rowData 要删除的行数据
*/
private void deleteRow(Object[] rowData) {
// 1. 从数据集中移除
allTableRowsData.removeIf(row -> Arrays.equals(row, rowData));
filteredTableRowsData.removeIf(row -> Arrays.equals(row, rowData));
// 2. 刷新表格
refreshTableWithData(filteredTableRowsData);
// 3. 显示提示
Toast.makeText(requireContext(), "已删除订单", Toast.LENGTH_SHORT).show();
}
//=== 辅助方法 ===//
/**
* 应用搜索过滤
*/
private void applySearchFilter() {
// 1. 获取搜索查询和选择的列
String query = searchView.getQuery().toString().trim().toLowerCase();
int selectedColumn = columnSelector.getSelectedItemPosition();
// 2. 清空过滤数据集
filteredTableRowsData.clear();
if (query.isEmpty()) {
// 3. 无查询时显示所有数据
filteredTableRowsData.addAll(allTableRowsData);
} else {
// 4. 有查询时过滤数据
for (Object[] row : allTableRowsData) {
if (selectedColumn == 0) {
// 4.1 全局搜索(所有列)
for (Object cell : row) {
if (cell != null && cell.toString().toLowerCase().contains(query)) {
filteredTableRowsData.add(row);
break; // 匹配任一列即可
}
}
} else if (selectedColumn > 0 && selectedColumn <= row.length) {
// 4.2 特定列搜索
int colIndex = selectedColumn - 1; // 调整索引(0是"全部")
if (row[colIndex] != null &&
row[colIndex].toString().toLowerCase().contains(query)) {
filteredTableRowsData.add(row);
}
}
}
}
// 5. 刷新表格显示
refreshTableWithData(filteredTableRowsData);
}
/**
* 添加表格表头
*
* @param table 表格布局
*/
private void addTableHeader(TableLayout table) {
// 1. 创建表头行
TableRow headerRow = new TableRow(requireContext());
headerRow.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT
));
headerRow.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.purple_500)); // 紫色背景
// 2. 获取表头文本和权重
String[] headers = getResources().getStringArray(R.array.table_headers);
float[] weights = {1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 1.0f, 1.0f}; // 各列权重
// 3. 创建表头单元格
for (int i = 0; i < headers.length; i++) {
HorizontalScrollTextView headerView = new HorizontalScrollTextView(requireContext());
headerView.setText(headers[i]);
headerView.setTextColor(Color.WHITE); // 白色文字
headerView.setTypeface(null, Typeface.BOLD); // 粗体
headerView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
headerView.setPadding(dpToPx(8), dpToPx(8), dpToPx(8), dpToPx(8)); // 内边距
// 单元格布局参数
TableRow.LayoutParams colParams = new TableRow.LayoutParams(
0,
TableRow.LayoutParams.MATCH_PARENT,
weights[i] // 使用预定义权重
);
headerView.setLayoutParams(colParams);
// 设置点击排序监听
final int columnIndex = i;
headerView.setOnClickListener(v -> sortTableData(columnIndex, sortAscending));
headerRow.addView(headerView);
}
// 4. 将表头行添加到表格
table.addView(headerRow);
}
/**
* 安全移除所有数据行(保留表头)
*/
private void removeAllRowsSafely() {
// 确保至少保留表头行
if (table.getChildCount() > 1) {
// 从后向前移除(避免索引变化问题)
for (int i = table.getChildCount() - 1; i >= 1; i--) {
View child = table.getChildAt(i);
if (child instanceof TableRow) {
// 清理行内视图资源
cleanupRowViews((TableRow) child);
}
table.removeViewAt(i);
}
}
}
/**
* 清理行视图资源
*
* @param row 表格行
*/
private void cleanupRowViews(TableRow row) {
for (int i = 0; i < row.getChildCount(); i++) {
View view = row.getChildAt(i);
if (view instanceof Button) {
// 清除按钮点击监听
((Button) view).setOnClickListener(null);
}
}
}
/**
* 添加空数据提示行
*/
private void addEmptyTableRow() {
TableRow row = new TableRow(requireContext());
TextView emptyView = new TextView(requireContext());
emptyView.setText("暂无数据");
emptyView.setGravity(Gravity.CENTER);
emptyView.setLayoutParams(new TableRow.LayoutParams(
TableRow.LayoutParams.MATCH_PARENT,
TableRow.LayoutParams.WRAP_CONTENT
));
row.addView(emptyView);
table.addView(row);
}
/**
* 显示详情对话框
*
* @param orderNumber 订单号
* @param productId 产品ID
*/
private void showDetailDialog(String orderNumber, String productId) {
new AlertDialog.Builder(requireContext())
.setTitle("订单详情")
.setMessage("订单号: " + orderNumber + "\n产品ID: " + productId)
.setPositiveButton("确定", null)
.show();
}
/**
* 编辑行数据
*
* @param rowData 行数据
*/
private void editRowData(Object[] rowData) {
// 实际项目中应实现编辑表单
Toast.makeText(requireContext(), "编辑: " + rowData[0], Toast.LENGTH_SHORT).show();
}
/**
* 显示加载指示器
*/
private void showLoadingIndicator() {
// 实际项目中应显示进度条
Toast.makeText(requireContext(), "加载中...", Toast.LENGTH_SHORT).show();
}
/**
* 设置数据加载监听器
*/
private void setupDataLoadListener() {
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).setOnDataLoadListener(new MainActivity.OnDataLoadListener() {
@Override
public void onDataLoaded() {
// 在主线程更新UI
requireActivity().runOnUiThread(() -> {
hideLoadingIndicator();
isDataLoaded = true;
fillTableData();
});
}
@Override
public void onDataError() {
requireActivity().runOnUiThread(() -> {
hideLoadingIndicator();
Toast.makeText(getContext(), "数据加载失败", Toast.LENGTH_SHORT).show();
});
}
});
}
}
/**
* 隐藏加载指示器
*/
private void hideLoadingIndicator() {
// 实际项目中应隐藏进度条
}
/**
* dp转px工具方法
*
* @param dp 设备无关像素值
* @return 像素值
*/
private int dpToPx(int dp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
getResources().getDisplayMetrics()
);
}
}package com.example.kucun2.entity.data;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.example.kucun2.entity.*;
import com.example.kucun2.function.MyAppFnction;
import com.example.kucun2.function.SafeLogger;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;
import okhttp3.*;
/**
* 核心数据管理类
* 负责:
* 1. 声明所有实体类的静态存储列表
* 2. 从服务器加载全量数据
* 3. 管理实体间的关联关系
* 4. 处理数据同步状态
*/
public class Data {
// ====================== 静态数据列表声明 ======================
public static SynchronizedList<Bancai> bancais = new SynchronizedList<>(Bancai.class);
public static SynchronizedList<Caizhi> caizhis = new SynchronizedList<>(Caizhi.class);
public static SynchronizedList<Mupi> mupis = new SynchronizedList<>(Mupi.class);
public static SynchronizedList<Chanpin> chanpins = new SynchronizedList<>(Chanpin.class);
public static SynchronizedList<Chanpin_Zujian> chanpin_zujians = new SynchronizedList<>(Chanpin_Zujian.class);
public static SynchronizedList<Dingdan> dingdans = new SynchronizedList<>(Dingdan.class);
public static SynchronizedList<Dingdan_Chanpin> dingdan_chanpins = new SynchronizedList<>(Dingdan_Chanpin.class);
public static SynchronizedList<Dingdan_chanpin_zujian> Dingdan_chanpin_zujians = new SynchronizedList<>(Dingdan_chanpin_zujian.class);
public static SynchronizedList<Kucun> kucuns = new SynchronizedList<>(Kucun.class);
public static SynchronizedList<Zujian> zujians = new SynchronizedList<>(Zujian.class);
public static SynchronizedList<User> users = new SynchronizedList<>(User.class);
public static SynchronizedList<Jinhuo> jinhuos = new SynchronizedList<>(Jinhuo.class);
private static User user;
// 实体类型与列表的映射表 <实体类, 对应的同步列表>
public static final Map<Class, SynchronizedList<SynchronizableEntity>> dataCollectionMap = new HashMap<>();
private static final Gson gson = GsonFactory.createWithIdSerialization();
private static OkHttpClient client;
private static final String TAG = "DataLoader";
// 静态初始化:建立实体类型与列表的映射关系
static {
try {
// 通过反射获取所有SynchronizedList字段
for (Field field : Data.class.getDeclaredFields()) {
if (SynchronizedList.class.equals(field.getType())) {
SynchronizedList<?> list = (SynchronizedList<?>) field.get(null);
if (list != null) {
// 将实体类型与列表关联
dataCollectionMap.put(list.getEntityType(), (SynchronizedList<SynchronizableEntity>) list);
}
}
}
} catch (IllegalAccessException e) {
throw new RuntimeException("初始化dataCollectionMap失败", e);
}
}
// ====================== 核心数据加载方法 ======================
/**
* 从服务器加载全量数据
* @param context Android上下文
* @param callback 加载结果回调
*/
public static void loadAllData(Context context, LoadDataCallback callback) {
// 主线程检查
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("必须在主线程调用Data.loadAllData");
}
ensurePreservedObjects(); // 确保存在预置对象
// 使用传入的 Context 获取主线程 Handler
Handler mainHandler = new Handler(context.getMainLooper());
// 确保使用安全的客户端
if (client == null) {
client = MyAppFnction.getClient();
}
SynchronizableEntity.setSyncEnabled(false);
String url = MyAppFnction.getStringResource("string", "url") +
MyAppFnction.getStringResource("string", "url_all");
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "Failed to load data", e);
SynchronizableEntity.setSyncEnabled(true);
mainHandler.post(() -> {
if (callback != null) callback.onFailure();
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
Log.e(TAG, "Unexpected response code: " + response.code());
SynchronizableEntity.setSyncEnabled(true);
mainHandler.post(() -> {
if (callback != null) callback.onFailure();
});
return;
}
String responseData = response.body().string();
SynchronizableEntity.setSyncEnabled(true);
ensurePreservedObjects();
// 在主线程处理解析
mainHandler.post(() -> {
parseAndAssignData(responseData, context, callback);
});
}
});
}
// ====================== 数据处理私有方法 ======================
/**
* 解析JSON数据并更新到实体列表
*/
private static void parseAndAssignData(String jsonData, Context context, LoadDataCallback callback) {
try {
// 解析顶层响应结构
Type responseType = new TypeToken<Information<AllDataResponse>>() {}.getType();
Information<AllDataResponse> info = gson.fromJson(jsonData, responseType);
// 验证响应有效性
if (info == null || info.getData() == null || info.getStatus() != 200) {
throw new IllegalStateException("无效服务器响应");
}
AllDataResponse allData = info.getData();
SafeLogger.d("data", "原始数据: " + gson.toJson(allData));
// 更新所有数据列表
updateAllLists(allData);
automaticAssociation(); // 建立实体关联
setAllEntitiesState(SynchronizableEntity.SyncState.MODIFIED); // 设置状态
safeCallback(callback, true); // 成功回调
} catch (Exception e) {
Log.e(TAG, "数据处理异常: " + e.getMessage());
safeCallback(callback, false);
} finally {
SynchronizableEntity.setSyncEnabled(true); // 重新启用同步
}
}
/**
* 批量更新所有实体列表
*/
private static void updateAllLists(AllDataResponse allData) {
updateList(bancais, allData.bancais);
updateList(caizhis, allData.caizhis);
updateList(mupis, allData.mupis);
updateList(chanpins, allData.chanpins);
updateList(chanpin_zujians, allData.chanpin_zujians);
updateList(dingdans, allData.dingdans);
updateList(dingdan_chanpins, allData.dingdan_chanpins);
updateList(Dingdan_chanpin_zujians, allData.Dingdan_chanpin_zujians);
updateList(kucuns, allData.kucuns);
updateList(zujians, allData.zujians);
updateList(users, allData.users);
updateList(jinhuos, allData.jinhuos);
}
/**
* 安全更新单个列表(保留预置对象)
*/
private static <T extends SynchronizableEntity> void updateList(
List<T> existingList,
List<T> newList
) {
if (newList == null) return;
// 保留现有列表中的预置对象
List<T> preservedItems = existingList.stream()
.filter(item -> item != null && item.isPreservedObject())
.collect(Collectors.toList());
// 清空后重新添加(预置对象 + 有效新数据)
existingList.clear();
existingList.addAll(preservedItems);
existingList.addAll(newList.stream()
.filter(item -> item != null && item.getId() != null && item.getId() != -1)
.collect(Collectors.toList())
);
}
/**
* 确保每个列表都有预置对象(用于表示空值/默认值)
*/
private static void ensurePreservedObjects() {
// 为每个实体类型检查并添加预置对象
addIfMissing(bancais, Bancai.class);
addIfMissing(caizhis, Caizhi.class);
addIfMissing(mupis, Mupi.class);
addIfMissing(chanpins, Chanpin.class);
addIfMissing(chanpin_zujians, Chanpin_Zujian.class);
addIfMissing(dingdans, Dingdan.class);
addIfMissing(kucuns, Kucun.class);
addIfMissing(zujians, Zujian.class);
addIfMissing(Dingdan_chanpin_zujians, Dingdan_chanpin_zujian.class);
addIfMissing(dingdan_chanpins, Dingdan_Chanpin.class);
addIfMissing(jinhuos, Jinhuo.class);
addIfMissing(users, User.class);
}
private static <T extends SynchronizableEntity> void addIfMissing(
List<T> list,
Class<T> clazz
) {
if (!containsPreservedObject(list)) {
list.add(createInstance(clazz));
}
}
/**
* 检查列表是否包含预置对象
*
* @param list 目标实体列表
* @return 是否包含预置对象
*/
private static <T extends SynchronizableEntity> boolean containsPreservedObject(List<T> list) {
return list.stream().anyMatch(item ->
item != null &&
item.isPreservedObject()
);
}
/**
* 自动建立实体间关联关系(通过反射实现)
*/
private static void automaticAssociation() {
for (Class<?> entityClass : dataCollectionMap.keySet()) {
try {
associateEntities(dataCollectionMap.get(entityClass));
} catch (Exception e) {
Log.e(TAG, entityClass.getSimpleName() + " 关联失败", e);
}
}
}
private static <T extends SynchronizableEntity> void associateEntities(
SynchronizedList<T> list
) throws IllegalAccessException, ClassNotFoundException {
for (T entity : list) {
if (entity == null) continue;
for (Field field : entity.getClass().getDeclaredFields()) {
field.setAccessible(true);
Class<?> fieldType = field.getType();
// 处理实体引用字段
if (SynchronizableEntity.class.isAssignableFrom(fieldType)) {
associateSingleReference(entity, field);
}
// 处理实体列表字段
else if (List.class.isAssignableFrom(fieldType)) {
associateReferenceList(entity, field);
}
// 处理基础类型字段
else {
setDefaultPrimitiveValue(entity, field);
}
}
}
}
// ====================== 关联辅助方法 ======================
private static void associateSingleReference(
SynchronizableEntity entity,
Field field
) throws IllegalAccessException {
SynchronizableEntity ref = (SynchronizableEntity) field.get(entity);
Class<?> targetType = field.getType();
// 查找目标实体
SynchronizableEntity target = findTargetEntity(ref, targetType);
field.set(entity, target);
}
private static void associateReferenceList(
SynchronizableEntity entity,
Field field
) throws IllegalAccessException, ClassNotFoundException {
// 获取列表泛型类型
Type genericType = field.getGenericType();
if (!(genericType instanceof ParameterizedType)) return;
Class<?> itemType = Class.forName(
((ParameterizedType) genericType).getActualTypeArguments()[0].getTypeName()
);
// 只处理实体列表
if (!SynchronizableEntity.class.isAssignableFrom(itemType)) return;
List<SynchronizableEntity> refList = (List<SynchronizableEntity>) field.get(entity);
if (refList == null) {
refList = new ArrayList<>();
field.set(entity, refList);
}
// 清理空值并重建引用
refList.removeAll(Collections.singleton(null));
for (int i = 0; i < refList.size(); i++) {
refList.set(i, findTargetEntity(refList.get(i), itemType));
}
}
/**
* 查找关联实体(优先匹配ID,找不到则使用预置对象)
*/
private static SynchronizableEntity findTargetEntity(
SynchronizableEntity ref,
Class<?> targetType
) {
SynchronizedList<SynchronizableEntity> targetList = dataCollectionMap.get(targetType);
if (targetList == null) return null;
// 无效引用时返回预置对象
if (ref == null || ref.getId() == null || ref.getId() < 0) {
return targetList.stream()
.filter(SynchronizableEntity::isPreservedObject)
.findFirst().orElse(null);
}
// 按ID查找目标实体
return targetList.stream()
.filter(e -> ref.getId().equals(e.getId()))
.findFirst()
.orElseGet(() -> targetList.stream() // 找不到时回退到预置对象
.filter(SynchronizableEntity::isPreservedObject)
.findFirst().orElse(null)
);
}
// ====================== 工具方法 ======================
/**
* 创建带默认值的实体实例(用作预置对象)
*/
public static <T> T createInstance(Class<T> clazz) {
try {
T instance = clazz.getDeclaredConstructor().newInstance();
// 设置基础字段默认值
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
setDefaultFieldValue(instance, field);
}
// 设置特殊字段
clazz.getMethod("setId", Integer.class).invoke(instance, -1);
clazz.getMethod("setState", SynchronizableEntity.SyncState.class)
.invoke(instance, SynchronizableEntity.SyncState.PRESERVED);
return instance;
} catch (Exception e) {
Log.e("Data", "创建实例失败: " + clazz.getName(), e);
try {
return clazz.newInstance(); // 回退创建
} catch (Exception ex) {
throw new RuntimeException("无法创建实例", ex);
}
}
}
private static <T> void setDefaultFieldValue(T instance, Field field)
throws IllegalAccessException {
Class<?> type = field.getType();
if (type == String.class) field.set(instance, "无");
else if (type == Integer.class || type == int.class) field.set(instance, -1);
else if (type == Double.class || type == double.class) field.set(instance, -1.0);
else if (type == Boolean.class || type == boolean.class) field.set(instance, false);
else if (type == Date.class) field.set(instance, new Date());
else if (SynchronizableEntity.class.isAssignableFrom(type)) {
field.set(instance, getPreservedEntity((Class<?>) type));
}
else if (List.class.isAssignableFrom(type)) {
field.set(instance, new ArrayList<>());
}
}
private static SynchronizableEntity getPreservedEntity(Class<?> type) {
return dataCollectionMap.get(type).stream()
.filter(SynchronizableEntity::isPreservedObject)
.findFirst().orElse(null);
}
private static void setDefaultPrimitiveValue(
SynchronizableEntity entity,
Field field
) throws IllegalAccessException {
if (field.get(entity) != null) return;
Class<?> type = field.getType();
if (type == String.class) field.set(entity, "无");
else if (type == Integer.class || type == int.class) field.set(entity, -1);
else if (type == Double.class || type == double.class) field.set(entity, -1.0);
else if (type == Boolean.class || type == boolean.class) field.set(entity, false);
else if (type == Date.class) field.set(entity, new Date());
}
/**
* 主线程安全回调
*/
private static void safeCallback(LoadDataCallback callback, boolean success) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callback == null) return;
if (success) callback.onSuccess();
else callback.onFailure();
});
}
/**
* 设置所有实体同步状态
*/
private static void setAllEntitiesState(SynchronizableEntity.SyncState state) {
dataCollectionMap.values().forEach(list ->
list.forEach(entity -> {
if (entity != null) entity.setState(state);
})
);
}
// ====================== 内部类/接口 ======================
public interface LoadDataCallback {
void onSuccess();
void onFailure();
}
/** JSON响应数据结构 */
public static class AllDataResponse {
public List<Bancai> bancais;
public List<Caizhi> caizhis;
public List<Mupi> mupis;
public List<Chanpin> chanpins;
public List<Chanpin_Zujian> chanpin_zujians;
public List<Dingdan> dingdans;
public List<Dingdan_Chanpin> dingdan_chanpins;
public List<Dingdan_chanpin_zujian> Dingdan_chanpin_zujians;
public List<Kucun> kucuns;
public List<Zujian> zujians;
public List<User> users;
public List<Jinhuo> jinhuos;
}
}在AddInventoryFragment中新建数据,在OrderDisplayFragment中不显示
最新发布