diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 045d7aa..8b29e6e 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -50,7 +50,9 @@ "Bash(do if ! grep -q \"import com.lukouguoji.module_base.ktx.formatDate\" \"$file\")", "Bash(then sed -i '' '/import dev.utils.common.DateUtils/a\\\\\nimport com.lukouguoji.module_base.ktx.formatDate\n' \"$file\" echo \"Added formatDate import to: $file\" fi done)", "Bash(identify:*)", - "WebFetch(domain:github.com)" + "WebFetch(domain:github.com)", + "Bash(file:*)", + "Bash(xargs:*)" ], "deny": [], "ask": [] diff --git a/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt b/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt index 7cf65b9..8eb01b8 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/ui/fragment/HomeFragment.kt @@ -1,6 +1,5 @@ package com.lukouguoji.aerologic.ui.fragment -import android.content.Context import android.os.Bundle import android.util.Log import android.view.LayoutInflater @@ -15,19 +14,15 @@ import androidx.recyclerview.widget.RecyclerView import com.alibaba.android.arouter.launcher.ARouter import com.alibaba.fastjson.JSON import com.alibaba.fastjson.JSONObject -import com.bumptech.glide.Glide -import com.bumptech.glide.load.engine.DiskCacheStrategy -import com.bumptech.glide.request.RequestOptions import com.lukouguoji.aerologic.R import com.lukouguoji.aerologic.page.accident.visa.list.AccidentVisaListActivity import com.lukouguoji.aerologic.page.car.list.CarListActivity import com.lukouguoji.aerologic.page.flight.query.list.FlightQueryListActivity import com.lukouguoji.aerologic.page.gnj.jiaojie.GnjHandoverListActivity import com.lukouguoji.aerologic.page.gnj.manifest.list.GnjManifestListActivity -import com.lukouguoji.aerologic.page.gnj.stash.list.GnjStashListActivity import com.lukouguoji.aerologic.page.gnj.move.stash.list.GnjMoveStashListActivity -import com.lukouguoji.aerologic.page.gnj.query.details.GnjQueryDetailsActivity import com.lukouguoji.aerologic.page.gnj.query.list.GnjQueryListActivity +import com.lukouguoji.aerologic.page.gnj.stash.list.GnjStashListActivity import com.lukouguoji.aerologic.page.gnj.unload.list.GnjUnloadListActivity import com.lukouguoji.aerologic.page.log.list.LogListActivity import com.lukouguoji.aerologic.page.message.list.MessageListActivity @@ -40,7 +35,6 @@ import com.lukouguoji.gnc.page.distribution.home.GncDistributionHomeActivity import com.lukouguoji.gnc.page.fubang.list.GncFuBangListActivity import com.lukouguoji.gnc.page.shouyun.unlist.GncShouYunUnListActivity import com.lukouguoji.module_base.MyApplication -import com.lukouguoji.module_base.adapter.loadImage import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil import com.lukouguoji.module_base.router.ARouterConstants @@ -179,7 +173,8 @@ class HomeFragment : Fragment() { // 跳过特殊菜单(航班查询、货物查询) if (Constant.AuthName.Flight == leftMenuTemp.id || - Constant.AuthName.CargoStatus == leftMenuTemp.id) { + Constant.AuthName.CargoStatus == leftMenuTemp.id + ) { return } @@ -424,9 +419,10 @@ class HomeFragment : Fragment() { ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE) .navigation() } - // 仓库 + // 出港仓库 Constant.AuthName.GjcIntExpStorageUse -> { - ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_STORAGE_USE) + ARouter.getInstance() + .build(ARouterConstants.ACTIVITY_URL_INT_EXP_STORAGE_USE) .navigation() } /** @@ -439,7 +435,8 @@ class HomeFragment : Fragment() { } // 原始舱单 Constant.AuthName.IntArrAirManifest -> { - ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_ARR_AIR_MANIFEST) + ARouter.getInstance() + .build(ARouterConstants.ACTIVITY_URL_INT_ARR_AIR_MANIFEST) .navigation() } // 进港舱单 @@ -536,23 +533,10 @@ class HomeFragment : Fragment() { } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - var item = rightMenuList[position] + val item = rightMenuList[position] holder.itemText.text = item.text -// holder.itemImg.setImageResource(item.img) - loadPreviewImage(holder.itemView.context, item.img, holder.itemImg) - } - - private fun loadPreviewImage(context: Context, url: Any, target: ImageView) { - val requestOptions = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.ALL) - .override( - com.bumptech.glide.request.target.Target.SIZE_ORIGINAL, - com.bumptech.glide.request.target.Target.SIZE_ORIGINAL - ) - Glide.with(context) - .setDefaultRequestOptions(requestOptions) - .load(url) - .into(target) + // 直接设置本地资源,避免 Glide 缓存导致的图标错乱问题 + holder.itemImg.setImageResource(item.img) } override fun getItemCount() = rightMenuList.size @@ -561,7 +545,7 @@ class HomeFragment : Fragment() { inner class RightMenu(val id: String, val img: Int, val text: String) private fun getRightMenu4Id(id: String): List { - var list = arrayListOf() + val list = arrayListOf() when (id) { Constant.AuthName.DomExp -> { list.add( @@ -578,7 +562,6 @@ class HomeFragment : Fragment() { "出港复磅" ) ) -// list.add(RightMenu(Constant.AuthName.AppDomExpTransport, R.mipmap.gnc_zhuanyun, "转运确认")) list.add( RightMenu( Constant.AuthName.AppDomExpAssemble, @@ -653,110 +636,114 @@ class HomeFragment : Fragment() { } Constant.AuthName.IntExp -> { -// list.add( -// RightMenu( -// Constant.AuthName.GjcAppDomExpCheckin, -// R.mipmap.gjc_shou_yun_icon, -// "出港收运" -// ) -// ) - + // 1. 收运检查 list.add( RightMenu( Constant.AuthName.GjcInspectionActivity, - R.mipmap.gnc_cha, + R.drawable.img_gjc_shouyunjiancha, "收运检查" ) ) + // 2. 出港计重 list.add( RightMenu( Constant.AuthName.GjcCheckWeighing, - R.mipmap.gjc_fu_bang_icon, + R.drawable.img_gjc_chugangjizhong, "出港计重" ) ) - list.add( - RightMenu( - Constant.AuthName.GjcFuBangActivity, - R.mipmap.gjc_fu_bang_icon, - "板箱过磅" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcIntExpAssembleActivity, - com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang, - "出港组装" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcQueryListActivity, - R.mipmap.gjc_query_icon, - "出港查询" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcYiKuListActivity, - R.mipmap.gjc_yi_ku_icon, - "出港移库" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcAssembleAllocateActivity, - com.lukouguoji.module_base.R.drawable.img_gnc_fenpei, - "组装分配" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcIntExpOutHandover, - com.lukouguoji.module_base.R.drawable.img_gjc_chuku_jiaojie, - "出库交接" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcIntExpLoad, - com.lukouguoji.module_base.R.drawable.img_gjc_chugang_zhuangzai, - "出港装载" - ) - ) - - list.add( - RightMenu( - Constant.AuthName.GjcIntExpTally, - com.lukouguoji.module_base.R.drawable.img_gjc_chugang_lihuo, - "出港理货" - ) - ) - + // 3. 出港运抵 list.add( RightMenu( Constant.AuthName.GjcIntExpArrive, - com.lukouguoji.module_base.R.drawable.img_gjc_chugang_diyun, + R.drawable.img_gjc_chugang_diyun, "出港运抵" ) ) + // 4. 组装分配 + list.add( + RightMenu( + Constant.AuthName.GjcAssembleAllocateActivity, + R.drawable.img_gjc_zuzhuangfenpei, + "组装分配" + ) + ) + + // 5. 出港组装 + list.add( + RightMenu( + Constant.AuthName.GjcIntExpAssembleActivity, + R.drawable.img_gjc_banxiangzuzhuang, + "出港组装" + ) + ) + + // 6. 板箱过磅 + list.add( + RightMenu( + Constant.AuthName.GjcFuBangActivity, + R.drawable.img_gjc_banxiangguobang, + "板箱过磅" + ) + ) + + // 7. 出港装载 + list.add( + RightMenu( + Constant.AuthName.GjcIntExpLoad, + R.drawable.img_gjc_chugang_zhuangzai, + "出港装载" + ) + ) + + // 8. 出库交接 + list.add( + RightMenu( + Constant.AuthName.GjcIntExpOutHandover, + R.drawable.img_gjc_chuku_jiaojie, + "出库交接" + ) + ) + + // 9. 出港理货 + list.add( + RightMenu( + Constant.AuthName.GjcIntExpTally, + R.drawable.img_gjc_chugang_lihuo, + "出港理货" + ) + ) + + // 10. 出港移库 + list.add( + RightMenu( + Constant.AuthName.GjcYiKuListActivity, + R.drawable.gjc_yi_ku_icon, + "出港移库" + ) + ) + + // 11. 出港仓库 list.add( RightMenu( Constant.AuthName.GjcIntExpStorageUse, - R.mipmap.gjc_cang_ku_icon, + R.drawable.gjc_cang_ku_icon, "出港仓库" ) ) + // 12. 出港查询 + list.add( + RightMenu( + Constant.AuthName.GjcQueryListActivity, + R.drawable.gjc_query_icon, + "出港查询" + ) + ) + // list.add( // RightMenu( // Constant.AuthName.GjcWareHouseActivity, diff --git a/module_base/build.gradle b/module_base/build.gradle index 469b3ee..d598af2 100644 --- a/module_base/build.gradle +++ b/module_base/build.gradle @@ -152,11 +152,11 @@ dependencies { api 'me.jessyan:autosize:1.2.+' // 佳博打印SDK - api('com.gainscha:sdk2:2.0.3@aar') { - exclude group: 'com.jcraft' - } -// api(name: 'sdk2-2.1.6-20250901.051214-1', ext: 'aar') { -// api(name: 'sdk2-2.0.3', ext: 'aar') { +// api('com.gainscha:sdk2:2.0.3@aar') { // exclude group: 'com.jcraft' // } +// api(name: 'sdk2-2.1.6-20250901.051214-1', ext: 'aar') { + api(name: 'sdk2-2.0.4', ext: 'aar') { + exclude group: 'com.jcraft' + } } \ No newline at end of file diff --git a/module_base/libs/sdk2-2.0.3.aar b/module_base/libs/sdk2-2.0.3.aar deleted file mode 100644 index 9d74f95..0000000 Binary files a/module_base/libs/sdk2-2.0.3.aar and /dev/null differ diff --git a/module_base/libs/sdk2-2.0.4.aar b/module_base/libs/sdk2-2.0.4.aar new file mode 100644 index 0000000..e542ada Binary files /dev/null and b/module_base/libs/sdk2-2.0.4.aar differ diff --git a/module_base/libs/sdk2-2.1.6-20250901.051214-1.aar b/module_base/libs/sdk2-2.1.6-20250901.051214-1.aar deleted file mode 100644 index 9d74f95..0000000 Binary files a/module_base/libs/sdk2-2.1.6-20250901.051214-1.aar and /dev/null differ diff --git a/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt b/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt index 0d6b880..bb22afa 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/LoginActivity.kt @@ -41,7 +41,7 @@ import me.jessyan.autosize.internal.CustomAdapt * ========== 开发调试开关 ========== * TODO: 正式发布前务必设置为 false */ -private const val DEV_AUTO_LOGIN = true // 自动登录开关 +private const val DEV_AUTO_LOGIN = false // 自动登录开关 @Route(path = ARouterConstants.ACTIVITY_URL_LOGIN) class LoginActivity : BaseActivity(), diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt index 1110a4f..ccb0add 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcUldUseBean.kt @@ -65,6 +65,20 @@ class GjcUldUseBean : Serializable { var loadArea: String = "" // 组装区 var pc: Long = 0 // 组装件数 + var fillWeightFlag: String = "" // 回填状态:0-未回填,1-部分回填,2-已回填 + + // 回填状态文本 + val fillWeightFlagText: String + get() = when (fillWeightFlag) { + "0" -> "未回填" + "1" -> "部分回填" + "2" -> "已回填" + else -> "" + } + + // 回填状态是否显示绿色(已回填时显示绿色) + val isFillWeightGreen: Boolean + get() = fillWeightFlag == "2" // ========== 出港组装页面扩展字段 ========== var isExpanded: Boolean = false // 展开状态(旧版保留) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWarehouse.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWarehouse.kt index 7c09144..eeaec6b 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWarehouse.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcWarehouse.kt @@ -39,6 +39,10 @@ class GjcWarehouse : Serializable { var location: String = "" // uld var checkInPc: Long = 0 // 入库件数 var checkInWeight: Double = 0.0 // 入库重量 + set(value) { + field = value + onDataChanged?.invoke() + } var assembleCount: Int = 0 // 已经组装的数量 // ========== UI扩展字段 ========== diff --git a/module_base/src/main/java/com/lukouguoji/module_base/util/PrinterUtils.kt b/module_base/src/main/java/com/lukouguoji/module_base/util/PrinterUtils.kt index 0c87437..cb0c681 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/util/PrinterUtils.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/util/PrinterUtils.kt @@ -567,7 +567,7 @@ object PrinterUtils { fun printTest() { getConnectedPrinters().forEach { - val bytes = v(Instruction.TSC.toString(), null).bytes + val bytes = v(Instruction.TSC).bytes showLog("打印测试页 - ${it.printerDevice.printerName} \n${bytes.commonToUtf8String()}") it.print(bytes, null) } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/assemble/IntExpAssembleStartActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/assemble/IntExpAssembleStartActivity.kt index 49684dc..4959d63 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/page/assemble/IntExpAssembleStartActivity.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/assemble/IntExpAssembleStartActivity.kt @@ -33,11 +33,29 @@ class IntExpAssembleStartActivity : private var waybillAdapter: CommonAdapter? = null companion object { + private const val EXTRA_ULD_NO = "uld" + private const val EXTRA_EDIT_MODE = "edit_mode" + private const val EXTRA_LOAD_AREA = "load_area" + @JvmStatic fun start(context: Context) { val starter = Intent(context, IntExpAssembleStartActivity::class.java) context.startActivity(starter) } + + /** + * 从列表页"修改"模式启动 + * @param uldNo ULD编号(将被锁定,整个页面生命周期内不可编辑) + * @param loadArea 组装位置(用于自动选中对应的组装位置) + */ + @JvmStatic + fun startForEdit(context: Context, uldNo: String, loadArea: String) { + val starter = Intent(context, IntExpAssembleStartActivity::class.java) + .putExtra(EXTRA_ULD_NO, uldNo) + .putExtra(EXTRA_EDIT_MODE, true) + .putExtra(EXTRA_LOAD_AREA, loadArea) + context.startActivity(starter) + } } override fun layoutId() = R.layout.activity_int_exp_assemble_start @@ -70,6 +88,23 @@ class IntExpAssembleStartActivity : // 观察数据变化 observeData() + + // 处理修改模式(从列表页侧滑"修改"跳转) + handleEditModeIntent() + } + + /** + * 处理修改模式的 Intent 参数 + */ + private fun handleEditModeIntent() { + val isEditMode = intent.getBooleanExtra(EXTRA_EDIT_MODE, false) + if (isEditMode) { + val uldNo = intent.getStringExtra(EXTRA_ULD_NO) ?: "" + val loadArea = intent.getStringExtra(EXTRA_LOAD_AREA) ?: "" + if (uldNo.isNotEmpty()) { + viewModel.initFromEditMode(uldNo, loadArea) + } + } } /** diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcAssembleWeightEditViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcAssembleWeightEditViewModel.kt index 5351cb0..1f4e290 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcAssembleWeightEditViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcAssembleWeightEditViewModel.kt @@ -126,12 +126,14 @@ class GjcAssembleWeightEditViewModel : BaseViewModel() { /** * 计算统计数据:总货重、重量误差 + * - 总货重:运单列表中所有 checkInWeight(入库重量/组装重量)之和 + * - 重量误差:(总货重 - ULD货重) / ULD货重 * 100% */ private fun calculateStatistics() { val records = waybillList.value ?: emptyList() - // 计算总货重(所有运单weight之和) - val sumWeight = records.sumOf { it.weight } + // 计算总货重(所有运单 checkInWeight 之和,即列表中显示的重量) + val sumWeight = records.sumOf { it.checkInWeight } sumCargoWeight.value = String.format("%.2f", sumWeight) // 计算重量误差百分比(相对于ULD的货重) diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleStartViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleStartViewModel.kt index a2572ac..81710ca 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleStartViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleStartViewModel.kt @@ -78,11 +78,30 @@ class IntExpAssembleStartViewModel : BaseViewModel() { // ========== 标记位,避免重复查询 ========== private var lastQueriedUldNo = "" + // ========== 修改模式待匹配的组装位置 ========== + private var pendingLoadArea: String = "" + /** - * ULD编号锁定状态 + * ULD编号锁定状态(页面内编辑模式) */ val isUldNoLocked = MutableLiveData(false) + /** + * 卸货时选中的组装信息子运单数据 + * 用于: + * 1. 卸货校验时对比组装件数/重量 + * 2. 卸货提交时构建 wbInfo + */ + private var selectedAssembleWaybill: AssembleInfoBean? = null + + /** + * 是否从列表页"修改"模式进入 + * 与 isUldNoLocked 的区别: + * - isFromEditMode:整个页面生命周期内 ULD 编号锁定,但不影响装货/卸货按钮 + * - isUldNoLocked:页面内编辑模式,影响装货/卸货按钮 + */ + val isFromEditMode = MutableLiveData(false) + /** * 装货按钮启用状态(非编辑模式时启用) */ @@ -131,12 +150,30 @@ class IntExpAssembleStartViewModel : BaseViewModel() { } }?.toMutableList() ?: mutableListOf() - assemblePositionList.value = list - - // 保存默认选中的第一项 - if (list.isNotEmpty()) { + // 检查是否有待匹配的组装位置(修改模式) + if (pendingLoadArea.isNotEmpty() && list.isNotEmpty()) { + // 取消所有选中状态 + list.forEach { it.isSelected = false } + // 查找并选中匹配项 + val matchedItem = list.find { it.positionName == pendingLoadArea } + if (matchedItem != null) { + matchedItem.isSelected = true + selectedPosition.value = matchedItem + } else { + // 未找到匹配项,选中第一项 + list[0].isSelected = true + selectedPosition.value = list[0] + } + // 清空待匹配标记 + pendingLoadArea = "" + // 触发组装信息列表查询 + loadAssembledList() + } else if (list.isNotEmpty()) { + // 非修改模式,选中第一项 selectedPosition.value = list[0] } + + assemblePositionList.value = list } } } @@ -165,6 +202,7 @@ class IntExpAssembleStartViewModel : BaseViewModel() { /** * 运单点击(单选切换) + * 装货模式:从运单列表选择运单 */ fun onWaybillItemClick(position: Int) { val list = waybillList.value ?: return @@ -182,9 +220,10 @@ class IntExpAssembleStartViewModel : BaseViewModel() { if (selectedWaybill != null) { selectedWaybill.isSelected.set(true) - // 自动提取航班号和航班日期 - assembleFlightNo.value = selectedWaybill.fno - assembleFlightDate.value = selectedWaybill.fdate + // 【删除】不再从运单提取航班信息(航班信息改为从ULD查询接口获取) + + // 【新增】清空卸货选中的子运单(切换到装货模式) + selectedAssembleWaybill = null // 保存当前的组装人(始终保留,从operator LiveData读取) val previousOperator = operator.value ?: "" @@ -372,6 +411,7 @@ class IntExpAssembleStartViewModel : BaseViewModel() { /** * 查询ULD信息(状态和耗材重量) + * 同时从ULD信息提取航班信息,并触发组装信息列表查询 */ private fun queryUldInfo(uldNo: String) { launchCollect({ NetApply.api.getUldWithConsumeWeight(uldNo) }) { @@ -393,6 +433,20 @@ class IntExpAssembleStartViewModel : BaseViewModel() { // 保存useId(用于装货/卸货接口) useId = uldBean.useId } + + // 【新增】从ULD信息提取航班信息 + if (uldBean.fno.isNotEmpty() && uldBean.fdate.isNotEmpty()) { + assembleFlightNo.value = uldBean.fno + assembleFlightDate.value = uldBean.fdateFormatted // 使用格式化后的日期(只保留年月日) + // 清除防抖标记,触发组装信息列表查询 + lastQueriedAssembledParams = "" + loadAssembledList() + } else { + // 航班信息为空,清空组装信息列表,但允许继续装货 + assembleFlightNo.value = "" + assembleFlightDate.value = "" + assembleInfoList.value = mutableListOf() + } } } onFailed = { code, message -> @@ -418,6 +472,14 @@ class IntExpAssembleStartViewModel : BaseViewModel() { /** * 执行组装操作(卸货或装货) * @param isLoad true-装货,false-卸货 + * + * 装货与卸货的区别: + * 1. 校验逻辑不同: + * - 装货:与运单列表中的件数/重量对比 + * - 卸货:与组装信息中的组装件数/重量对比 + * 2. wbInfo 来源不同: + * - 装货:从运单列表选中项获取 + * - 卸货:从组装信息选中的子运单获取 */ private fun performAssembleOperation(isLoad: Boolean) { // 1. 验证必填字段 @@ -446,23 +508,54 @@ class IntExpAssembleStartViewModel : BaseViewModel() { return } - // 校验件数范围 - val waybillPieces = waybillInfo.value?.waybillPieces?.trim() ?: "" - val assembleCountInt = assembleCount.toLongOrNull() ?: 0L - val waybillPiecesInt = waybillPieces.toLongOrNull() ?: 0L - - if (assembleCountInt > waybillPiecesInt) { - val errorMessage = if (isLoad) { - "装货件数不能大于运单件数" - } else { - "卸货件数不能大于已装货件数" - } - showToast(errorMessage) - return - } - val assembleWeight = waybillInfo.value?.assembleWeight?.trim() ?: "" - // 组装重量为非必填,不进行验证 + + // 【修改】区分校验逻辑 + val assembleCountInt = assembleCount.toLongOrNull() ?: 0L + val assembleWeightDouble = assembleWeight.toDoubleOrNull() ?: 0.0 + + if (isLoad) { + // 装货校验:与运单列表中的件数/重量对比 + val waybillPieces = waybillInfo.value?.waybillPieces?.trim() ?: "" + val waybillPiecesInt = waybillPieces.toLongOrNull() ?: 0L + + if (waybillPiecesInt > 0 && assembleCountInt > waybillPiecesInt) { + showToast("装货件数不能大于运单件数") + return + } + + if (assembleWeight.isNotEmpty()) { + val waybillWeight = waybillInfo.value?.waybillWeight?.trim() ?: "" + val waybillWeightDouble = waybillWeight.toDoubleOrNull() ?: 0.0 + + if (waybillWeightDouble > 0 && assembleWeightDouble > waybillWeightDouble) { + showToast("装货重量不能大于运单重量") + return + } + } + } else { + // 卸货校验:与组装信息中的组装件数/重量对比 + val assembleInfo = selectedAssembleWaybill?.waybillData + if (assembleInfo == null) { + showToast("请从组装信息列表选择要卸货的运单") + return + } + + // originalPieces 对应 checkInPc(已组装件数) + val maxPieces = assembleInfo.originalPieces.toLongOrNull() ?: 0L + // originalWeight 对应 checkInWeight(已组装重量) + val maxWeight = assembleInfo.originalWeight.toDoubleOrNull() ?: 0.0 + + if (maxPieces > 0 && assembleCountInt > maxPieces) { + showToast("卸货件数不能大于已组装件数") + return + } + + if (assembleWeight.isNotEmpty() && maxWeight > 0 && assembleWeightDouble > maxWeight) { + showToast("卸货重量不能大于已组装重量") + return + } + } val operatorValue = operator.value?.trim() ?: "" if (operatorValue.isEmpty()) { @@ -476,21 +569,7 @@ class IntExpAssembleStartViewModel : BaseViewModel() { return } - // 2. 获取或构建运单Bean - // 从运单列表中获取选中的运单 - val currentWaybillList = waybillList.value - if (currentWaybillList == null) { - showToast("运单列表为空") - return - } - - val selectedWaybill = currentWaybillList.firstOrNull { it.isSelected.get() } - if (selectedWaybill == null) { - showToast("请选择运单") - return - } - - // 3. 构建useInfo(ULD信息) + // 2. 构建useInfo(ULD信息) val useInfo = mapOf( "uld" to uldNo, "consumeWeight" to materialWeight.toDoubleOrNull(), @@ -503,29 +582,62 @@ class IntExpAssembleStartViewModel : BaseViewModel() { "useId" to if (uldInfo.value?.useId == 0L) null else uldInfo.value?.useId // 添加useId(来自getUld接口) ) - // 4. 构建wbInfo(运单信息) - // 使用原始运单件数/重量(如果有),否则使用当前件数/重量 - val waybillPc = if (selectedWaybill.originalPieces.isNotEmpty()) { - selectedWaybill.originalPieces.toLongOrNull() + // 3. 【修改】区分 wbInfo 构建 + val wbInfo: Map + + if (isLoad) { + // 装货:从运单列表获取 + val currentWaybillList = waybillList.value + if (currentWaybillList == null) { + showToast("运单列表为空") + return + } + + val selectedWaybill = currentWaybillList.firstOrNull { it.isSelected.get() } + if (selectedWaybill == null) { + showToast("请选择运单") + return + } + + // 使用原始运单件数/重量(如果有),否则使用当前件数/重量 + val waybillPc = if (selectedWaybill.originalPieces.isNotEmpty()) { + selectedWaybill.originalPieces.toLongOrNull() + } else { + selectedWaybill.pieces.toLongOrNull() + } + val waybillWeight = if (selectedWaybill.originalWeight.isNotEmpty()) { + selectedWaybill.originalWeight.toDoubleOrNull() + } else { + selectedWaybill.weight.toDoubleOrNull() + } + + wbInfo = mapOf( + "wbNo" to selectedWaybill.waybillNo, + "pc" to waybillPc, + "weight" to waybillWeight, + "fdate" to selectedWaybill.fdate, + "fno" to selectedWaybill.fno, + "whId" to selectedWaybill.whId + ) } else { - selectedWaybill.pieces.toLongOrNull() - } - val waybillWeight = if (selectedWaybill.originalWeight.isNotEmpty()) { - selectedWaybill.originalWeight.toDoubleOrNull() - } else { - selectedWaybill.weight.toDoubleOrNull() + // 卸货:从组装信息子运单获取 + val assembleWaybill = selectedAssembleWaybill?.waybillData + if (assembleWaybill == null) { + showToast("请从组装信息列表选择要卸货的运单") + return + } + + wbInfo = mapOf( + "wbNo" to assembleWaybill.waybillNo, + "pc" to assembleWaybill.pieces.toLongOrNull(), // 运单件数 + "weight" to assembleWaybill.weight.toDoubleOrNull(), // 运单重量 + "fdate" to assembleWaybill.fdate, + "fno" to assembleWaybill.fno, + "whId" to assembleWaybill.whId + ) } - val wbInfo = mapOf( - "wbNo" to selectedWaybill.waybillNo, - "pc" to waybillPc, - "weight" to waybillWeight, - "fdate" to selectedWaybill.fdate, - "fno" to selectedWaybill.fno, - "whId" to selectedWaybill.whId - ) - - // 5. 构建完整请求参数 + // 4. 构建完整请求参数 val params = mapOf( "abPc" to assembleCount.toLongOrNull(), "abWeight" to assembleWeight.toDoubleOrNull(), @@ -537,7 +649,7 @@ class IntExpAssembleStartViewModel : BaseViewModel() { "userId" to SharedPreferenceUtil.getString(Constant.Share.account) ).toRequestBody() - // 6. 调用接口(带Loading,等待接口返回) + // 5. 调用接口(带Loading,等待接口返回) val operationName = if (isLoad) "装货" else "卸货" launchLoadingCollect({ if (isLoad) { @@ -548,7 +660,7 @@ class IntExpAssembleStartViewModel : BaseViewModel() { }) { onSuccess = { result -> // 接口成功后才显示成功提示并刷新列表 - handleOperationSuccess(operationName, isLoad, uldNo, selectedWaybill, assembleCount, assembleWeight) + handleOperationSuccess(operationName, isLoad, uldNo, assembleCount, assembleWeight) } onFailed = { code, message -> showToast("${operationName}失败: $message") @@ -563,7 +675,6 @@ class IntExpAssembleStartViewModel : BaseViewModel() { operationName: String, isLoad: Boolean, uldNo: String, - selectedWaybill: AssembleWaybillBean, assembleCount: String, assembleWeight: String ) { @@ -574,14 +685,45 @@ class IntExpAssembleStartViewModel : BaseViewModel() { FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") } - // 重新查询组装信息列表(刷新数据) + // 清空表单(在刷新数据前清空,避免刷新时的状态冲突) + clearForm() + + // 清除防抖标记,强制刷新组装信息列表 + lastQueriedAssembledParams = "" loadAssembledList() - // 刷新运单列表 - loadInitialWaitingAssemble() + // 刷新运单列表(使用当前搜索条件) + refreshWaybillList() + } - // 清空表单 - clearForm() + /** + * 刷新运单列表(保留当前搜索条件) + */ + private fun refreshWaybillList() { + val wbNo = searchText.value?.trim() ?: "" + + launchLoadingCollect({ NetApply.api.queryWaitingAssemble(wbNo) }) { + onSuccess = { result -> + val warehouseList = result.data ?: mutableListOf() + val waybillBeanList = warehouseList.map { warehouse -> + AssembleWaybillBean().apply { + waybillNo = warehouse.wbNo + pieces = warehouse.pc.toString() + weight = String.format("%.1f", warehouse.weight) + flight = warehouse.flight + fno = warehouse.fno + fdate = warehouse.fdate + whId = warehouse.whId + isMarked = false + } + }.toMutableList() + + waybillList.value = waybillBeanList + } + onFailed = { code, message -> + showToast("刷新运单列表失败: $message") + } + } } /** @@ -670,8 +812,8 @@ class IntExpAssembleStartViewModel : BaseViewModel() { itemType = AssembleInfoBean.ItemType.WAYBILL_DETAIL parentUldNo = uldItem.uldNo wbNo = warehouse.wbNo - waybillPieces = warehouse.pc.toInt() - waybillWeight = warehouse.weight + waybillPieces = warehouse.checkInPc.toInt() + waybillWeight = warehouse.checkInWeight showIndent = true showIndex = false @@ -684,6 +826,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() { fno = warehouse.fno fdate = warehouse.fdate whId = warehouse.whId + // 设置原始运单件数/重量(使用checkInPc/checkInWeight) + originalPieces = warehouse.checkInPc.toString() + originalWeight = String.format("%.1f", warehouse.checkInWeight) } } } @@ -710,14 +855,23 @@ class IntExpAssembleStartViewModel : BaseViewModel() { } /** - * 从二级运单行填充表单(编辑模式) - * 1. 填充ULD信息(并锁定ULD编号) - * 2. 填充运单信息(使用原始运单件数/重量,只读) - * 3. 保留组装件数、组装重量、组装人为可编辑 + * 从二级运单行填充表单(卸货模式) + * 1. 存储选中的组装信息子运单(用于卸货校验和提交) + * 2. 填充ULD信息(并锁定ULD编号) + * 3. 填充运单信息(字段对调:运单件数/组装件数对调,运单重量/组装重量对调) + * + * 卸货时字段映射: + * - 运单件数 ← pieces (pc,原始运单件数) + * - 运单重量 ← weight (weight,原始运单重量) + * - 组装件数 ← originalPieces (checkInPc,已组装件数,可编辑卸货数量) + * - 组装重量 ← originalWeight (checkInWeight,已组装重量,可编辑卸货数量) */ private fun fillFormFromWaybillDetail(item: AssembleInfoBean) { val waybill = item.waybillData ?: return + // 【新增】存储选中的组装信息子运单(用于卸货校验和提交) + selectedAssembleWaybill = item + // 1. 填充ULD信息 uldInfo.value = uldInfo.value?.apply { uldNo = item.parentUldNo @@ -727,14 +881,13 @@ class IntExpAssembleStartViewModel : BaseViewModel() { // 保存当前的组装人(在创建新对象前,从operator LiveData读取) val previousOperator = operator.value ?: "" - // 2. 填充运单信息 + // 2. 填充运单信息(【修改】对调字段填充) waybillInfo.value = WaybillInfoBean().apply { waybillNo = waybill.waybillNo - waybillPieces = waybill.originalPieces // 使用原始运单件数 - waybillWeight = waybill.originalWeight // 使用原始运单重量 - // 填充已累积的组装件数和组装重量(可编辑) - assembleCount = waybill.pieces - assembleWeight = waybill.weight + waybillPieces = waybill.pieces // 【对调】显示运单件数(pc) + waybillWeight = waybill.weight // 【对调】显示运单重量(weight) + assembleCount = waybill.originalPieces // 【对调】显示组装件数(checkInPc),可编辑卸货数量 + assembleWeight = waybill.originalWeight // 【对调】显示组装重量(checkInWeight),可编辑卸货数量 operator = previousOperator // 保留之前选择的组装人 } @@ -823,9 +976,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() { uldBean.waybillDetails = warehouseList } - // 计算总件数和总重量(从运单列表求和) - val calculatedPieces = warehouseList?.sumOf { it.pc.toInt() } ?: 0 - val calculatedWeight = warehouseList?.sumOf { it.weight } ?: 0.0 + // 计算总件数和总重量(从子列表的checkInPc、checkInWeight求和) + val calculatedPieces = warehouseList?.sumOf { it.checkInPc.toInt() } ?: 0 + val calculatedWeight = warehouseList?.sumOf { it.checkInWeight } ?: 0.0 AssembleInfoBean().apply { itemType = AssembleInfoBean.ItemType.ULD_HEADER @@ -866,6 +1019,9 @@ class IntExpAssembleStartViewModel : BaseViewModel() { operator = previousOperator // 恢复组装人 } isUldNoLocked.value = false + + // 【新增】清空卸货选中的子运单 + selectedAssembleWaybill = null } /** @@ -874,4 +1030,34 @@ class IntExpAssembleStartViewModel : BaseViewModel() { fun clearCachedOperator() { lastSelectedOperator = null } + + /** + * 从列表页"修改"模式初始化 + * @param uldNo ULD编号 + * @param loadArea 组装位置(用于自动选中对应的组装位置) + */ + fun initFromEditMode(uldNo: String, loadArea: String = "") { + if (uldNo.isEmpty()) return + + // 标记为修改模式(整个页面生命周期内 ULD 编号锁定) + isFromEditMode.value = true + + // 保存待匹配的组装位置(在组装位置列表加载完成后进行匹配选择) + if (loadArea.isNotEmpty()) { + pendingLoadArea = loadArea + } + + // 填充 ULD 编号 + uldInfo.value = uldInfo.value?.apply { + this.uldNo = uldNo + } ?: UldInfoBean().apply { + this.uldNo = uldNo + } + + // 更新防抖标记,确保查询能触发 + lastQueriedUldNo = "" + + // 触发 ULD 编码查询 + onUldNoInputComplete() + } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleViewModel.kt index e351f44..d5a8bce 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleViewModel.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpAssembleViewModel.kt @@ -174,17 +174,17 @@ class IntExpAssembleViewModel : BasePageViewModel() { } /** - * 修改单个列表项 - 跳转到开始组装页面 + * 修改单个列表项 - 跳转到开始组装页面(修改模式) + * ULD 编号将被锁定,整个页面生命周期内不可编辑 + * 同时传递组装位置,用于自动选中对应项 */ private fun onEditItem(position: Int) { val bean = pageModel.rv?.commonAdapter()?.getItem(position) as? GjcUldUseBean ?: return - ARouter.getInstance() - .build(ARouterConstants.ACTIVITY_URL_INT_EXP_ASSEMBLE_START) - .withLong("useId", bean.useId) - .withString("uld", bean.uld) - .withString("fdate", bean.fdate) - .withString("fno", bean.fno) - .navigation() + com.lukouguoji.gjc.page.assemble.IntExpAssembleStartActivity.startForEdit( + getTopActivity(), + bean.uld, + bean.loadArea + ) } /** diff --git a/module_gjc/src/main/res/mipmap-mdpi/gjc_cang_ku_icon.png b/module_gjc/src/main/res/drawable-mdpi/gjc_cang_ku_icon.png similarity index 100% rename from module_gjc/src/main/res/mipmap-mdpi/gjc_cang_ku_icon.png rename to module_gjc/src/main/res/drawable-mdpi/gjc_cang_ku_icon.png diff --git a/module_gjc/src/main/res/mipmap-mdpi/gjc_query_icon.png b/module_gjc/src/main/res/drawable-mdpi/gjc_query_icon.png similarity index 100% rename from module_gjc/src/main/res/mipmap-mdpi/gjc_query_icon.png rename to module_gjc/src/main/res/drawable-mdpi/gjc_query_icon.png diff --git a/module_gjc/src/main/res/mipmap-mdpi/gjc_yi_ku_icon.png b/module_gjc/src/main/res/drawable-mdpi/gjc_yi_ku_icon.png similarity index 100% rename from module_gjc/src/main/res/mipmap-mdpi/gjc_yi_ku_icon.png rename to module_gjc/src/main/res/drawable-mdpi/gjc_yi_ku_icon.png diff --git a/module_gjc/src/main/res/drawable-mdpi/img_gjc_banxiangguobang.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_banxiangguobang.png new file mode 100644 index 0000000..921bb33 Binary files /dev/null and b/module_gjc/src/main/res/drawable-mdpi/img_gjc_banxiangguobang.png differ diff --git a/module_base/src/main/res/drawable-xhdpi/img_gjc_banxiangzuzhuang.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_banxiangzuzhuang.png similarity index 100% rename from module_base/src/main/res/drawable-xhdpi/img_gjc_banxiangzuzhuang.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_banxiangzuzhuang.png diff --git a/module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_diyun.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_diyun.png similarity index 100% rename from module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_diyun.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_diyun.png diff --git a/module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_lihuo.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_lihuo.png similarity index 100% rename from module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_lihuo.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_lihuo.png diff --git a/module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_zhuangzai.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_zhuangzai.png similarity index 100% rename from module_base/src/main/res/drawable-xhdpi/img_gjc_chugang_zhuangzai.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_chugang_zhuangzai.png diff --git a/module_gjc/src/main/res/mipmap-mdpi/gjc_fu_bang_icon.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_chugangjizhong.png similarity index 100% rename from module_gjc/src/main/res/mipmap-mdpi/gjc_fu_bang_icon.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_chugangjizhong.png diff --git a/module_base/src/main/res/drawable-xhdpi/img_gjc_chuku_jiaojie.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_chuku_jiaojie.png similarity index 100% rename from module_base/src/main/res/drawable-xhdpi/img_gjc_chuku_jiaojie.png rename to module_gjc/src/main/res/drawable-mdpi/img_gjc_chuku_jiaojie.png diff --git a/module_gjc/src/main/res/drawable-mdpi/img_gjc_shouyunjiancha.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_shouyunjiancha.png new file mode 100644 index 0000000..bda2b67 Binary files /dev/null and b/module_gjc/src/main/res/drawable-mdpi/img_gjc_shouyunjiancha.png differ diff --git a/module_gjc/src/main/res/drawable-mdpi/img_gjc_zuzhuangfenpei.png b/module_gjc/src/main/res/drawable-mdpi/img_gjc_zuzhuangfenpei.png new file mode 100644 index 0000000..32fd1b6 Binary files /dev/null and b/module_gjc/src/main/res/drawable-mdpi/img_gjc_zuzhuangfenpei.png differ diff --git a/module_gjc/src/main/res/drawable/ic_btn_customs.xml b/module_gjc/src/main/res/drawable/ic_btn_customs.xml new file mode 100644 index 0000000..089acb0 --- /dev/null +++ b/module_gjc/src/main/res/drawable/ic_btn_customs.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/module_gjc/src/main/res/drawable/ic_btn_record.xml b/module_gjc/src/main/res/drawable/ic_btn_record.xml new file mode 100644 index 0000000..aed3ad7 --- /dev/null +++ b/module_gjc/src/main/res/drawable/ic_btn_record.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml index 0bb49a5..4482aa0 100644 --- a/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml +++ b/module_gjc/src/main/res/layout/activity_gjc_weighing_start.xml @@ -466,7 +466,7 @@ android:layout_gravity="bottom|end" android:layout_marginEnd="25dp" android:layout_marginBottom="70dp" - android:background="@drawable/bg_float_button" + android:background="@drawable/ic_btn_customs" android:visibility="gone" /> @@ -477,7 +477,7 @@ android:layout_gravity="bottom|end" android:layout_marginEnd="70dp" android:layout_marginBottom="25dp" - android:background="@drawable/bg_float_button" + android:background="@drawable/ic_btn_record" android:visibility="gone" /> diff --git a/module_gjc/src/main/res/layout/activity_int_exp_assemble.xml b/module_gjc/src/main/res/layout/activity_int_exp_assemble.xml index 5d85182..51bbd59 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_assemble.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_assemble.xml @@ -135,7 +135,7 @@ itemLayoutId="@{viewModel.itemLayoutId}" viewHolder="@{viewModel.itemViewHolder}" tools:itemCount="3" - tools:listitem="@layout/item_int_exp_assemble_uld" /> + tools:listitem="@layout/item_int_exp_assemble" /> diff --git a/module_gjc/src/main/res/layout/activity_int_exp_assemble_start.xml b/module_gjc/src/main/res/layout/activity_int_exp_assemble_start.xml index 00c1aaf..d54b374 100644 --- a/module_gjc/src/main/res/layout/activity_int_exp_assemble_start.xml +++ b/module_gjc/src/main/res/layout/activity_int_exp_assemble_start.xml @@ -254,7 +254,7 @@ - - - - - - - - - @@ -192,6 +167,31 @@ + + + + + + + + + @@ -288,7 +288,7 @@ diff --git a/nohup.out b/nohup.out deleted file mode 100644 index ad0483a..0000000 --- a/nohup.out +++ /dev/null @@ -1,11 +0,0 @@ -/opt/homebrew/Cellar/scrcpy/3.3.3/share/scrcpy/scrcpy-server: 1 file pushed, 0 skipped. 171.0 MB/s (90164 bytes in 0.001s) -[server] INFO: Device: [CENAVA] CENAVA A80ST (Android 10) -[server] WARN: Audio disabled: it is not supported before Android 11 -WARN: Demuxer 'audio': stream explicitly disabled by the device -2025-11-21 13:21:03.514 scrcpy[46548:5077376] TSM AdjustCapsLockLEDForKeyTransitionHandling - _ISSetPhysicalKeyboardCapsLockLED Inhibit -WARN: Device disconnected -scrcpy 3.3.3 -INFO: ADB device found: -INFO: --> (usb) 80STHZCHDLL4311422 device A80ST -INFO: Renderer: metal -INFO: Texture: 1280x800