Merge branch 'main' of ssh://git.njcqit.com:2222/eric/aerologic-app

This commit is contained in:
2026-02-05 14:29:18 +08:00
33 changed files with 503 additions and 247 deletions

View File

@@ -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": []

View File

@@ -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<RightMenu> {
var list = arrayListOf<RightMenu>()
val list = arrayListOf<RightMenu>()
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,

View File

@@ -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'
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -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(),

View File

@@ -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 // 展开状态(旧版保留)

View File

@@ -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扩展字段 ==========

View File

@@ -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)
}

View File

@@ -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)
}
}
}
/**

View File

@@ -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的货重

View File

@@ -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. 构建useInfoULD信息
// 2. 构建useInfoULD信息
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<String, Any?>
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<String>(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()
}
}

View File

@@ -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
)
}
/**

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1024dp"
android:height="1024dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<!-- 圆形背景 - 填满整个画布 (与 ic_btn_record 一致) -->
<path
android:fillColor="#599dff"
android:pathData="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" />
<!-- 海关图标内容 (白色,使用 group 进行缩放和居中) -->
<group
android:pivotX="512"
android:pivotY="512"
android:scaleX="0.85"
android:scaleY="0.85">
<path
android:fillColor="#FFFFFF"
android:pathData="M756.8 529.6s-12-32.8-12-77.6c0 0-2.4-8-4.8-0.8 0 0-1.6 41.6 0 44.8 0 0-11.2 0-14.4-48.8 0 0-0.8-8-2.4 0 0 0 0 42.4-7.2 16.8 0 0-6.4-23.2-7.2-37.6 0 0-4 2.4-6.4 13.6 0 0-7.2 0.8-9.6-29.6 0 0-2.4-7.2-4.8 0 0 0-3.2 11.2-1.6 16.8 0 0-10.4-1.6-9.6-32.8 0 0-6.4 3.2-4.8 14.4 0 0 0 7.2-4.8 0 0 0-13.6-12-28-7.2 0 0-4-0.8-14.4 10.4l-35.2 36.8s11.2 22.4 35.2 12.8c0 0 5.6-0.8 12-6.4 0 0 0.8-16 10.4-18.4 0 0 12.8-2.4 23.2 9.6 0 0 11.2 14.4-0.8 27.2 0 0-13.6 37.6-83.2 13.6 0 0 8.8 33.6-34.4 45.6l-3.2 3.2 61.6 52s12 11.2 26.4 0.8c0 0 41.6-26.4 77.6-3.2 0 0 53.6 35.2 31.2 107.2 0 0-27.2 88-112 73.6 0 0-73.6-31.2-56-96.8l6.4-20s8-12-8-22.4l-61.6-55.2s-12 32.8-62.4 33.6c0 0 4 61.6-64 51.2L291.2 767.2l-4-3.2 87.2-120s-16-64.8 46.4-64l4-4s-15.2-42.4 28-60l-192-166.4s-11.2-8.8 0.8-27.2c0 0 16-8.8 29.6 4l192 153.6 4.8-4.8s3.2-38.4 45.6-42.4c0 0 3.2-12.8-6.4-28.8 0 0-12.8-22.4 0-40.8 0 0 10.4-16.8 32.8-8 0 0 21.6 9.6 10.4 23.2 0 0-8.8 8-13.6 8.8 0 0-3.2 34.4 18.4 32l36.8-40.8s10.4-12-4.8-24c0 0-13.6-7.2 3.2-12 0 0 6.4 0.8 7.2-4.8 0 0 1.6-3.2-12-3.2 0 0-21.6 2.4-20-5.6l19.2-3.2s7.2-3.2-2.4-3.2l-21.6-0.8s-11.2 0.8-16-6.4l24-0.8s6.4 0 4.8-5.6c0 0 0-2.4-8-2.4l-49.6-1.6s-3.2-4.8 10.4-5.6l24.8-0.8s6.4-0.8-0.8-4.8c0 0 1.6-0.8-9.6-2.4l-46.4-3.2s-11.2-6.4-0.8-8l50.4-1.6s6.4-4 0-7.2H478.4s-4.8 1.6-9.6-6.4c0 0-1.6-4.8 7.2-6.4l114.4-2.4s37.6 0.8 44 36.8c0 0 2.4 11.2 1.6 27.2 0 0 4 11.2 12 8.8 0 0 8 3.2 17.6-9.6 0 0 2.4-8 3.2-13.6 0 0 0.8-16.8 25.6-15.2 0 0 17.6 7.2 25.6 23.2 0 0 8.8 9.6-3.2 20 0 0-7.2 10.4-21.6 10.4 0 0-15.2 4-14.4 18.4 0 0 0.8 21.6 24.8 18.4 0 0 17.6-12 31.2-4.8 0 0 21.6 8.8 21.6 46.4L768 540s-5.6 6.4-11.2-10.4z" />
</group>
</vector>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="1024dp"
android:height="1024dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#599dff"
android:pathData="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M716.731364 238.0814H307.26683c-19.711273 0-35.840813 16.127734-35.840813 35.840813v476.157381c0 19.713079 16.12954 35.840813 35.840813 35.840812h409.464534c19.711273 0 35.840813-16.127734 35.840812-35.840812V273.920406c0-19.713079-16.127734-35.839007-35.840812-35.839006z m-339.422956 78.156922H660.137089c11.263585 0 20.480722 7.828155 20.480723 17.397506 0 9.567544-9.217138 17.3957-20.480723 17.3957H377.308408c-11.263585 0-20.480722-7.828155-20.480722-17.3957 0-9.569351 9.215332-17.397506 20.480722-17.397506z m301.486928 96.883806c0 9.569351-9.217138 17.399312-20.480722 17.399312H378.24403c-11.263585 0-20.480722-7.829961-20.480722-17.399312s9.217138-17.399312 20.480722-17.399312h280.070584c11.263585 0 20.480722 7.829961 20.480722 17.399312z m-321.032028 77.147246c0-9.569351 9.217138-17.399312 20.480722-17.399312h98.372131c11.263585 0 20.480722 7.829961 20.480722 17.399312 0 9.567544-9.217138 17.397506-20.480722 17.397506h-98.372131c-11.263585-0.001806-20.480722-7.831768-20.480722-17.397506z m173.897391 204.287033c-18.475819 6.856409-36.964281 13.705593-55.53583 20.314551-6.9991 2.494389-11.191336 0.986196-7.961815-7.562641 7.127342-18.864156 14.272746-37.726506 21.627671-56.502158 2.483552-6.350668 6.852797-8.960655 12.55142-3.424592 11.514649 11.184111 22.799908 22.60303 34.061686 34.040012 1.497356 1.526255 2.27403 3.767774 2.992906 5.005035-0.827249 5.364472-4.315058 6.856409-7.736038 8.129793z m126.229453-122.947552c-31.709989 31.58536-63.241162 63.344117-94.905995 94.9656-2.209006 2.201782-5.026709 3.803898-6.84196 5.149532-4.790094 0.211328-6.950332-2.423947-9.193657-4.641984-10.174434-10.047999-20.095998-20.372349-30.429379-30.254176-6.224232-5.956912-5.033934-10.687401 0.559928-16.254169a17171.620059 17171.620059 0 0 0 94.80846-95.072168c5.581218-5.644436 10.149147-6.854603 16.116896-0.541865 9.822221 10.387568 19.974981 20.489754 30.302944 30.373386 6.161015 5.902725 5.200106 10.680176-0.417237 16.275844z m24.620578-25.568843c-5.438527 3.514903-8.615667 0.825442-11.958979-2.45104-10.210559-10.006456-20.04723-20.412086-30.525109-30.133159-6.926852-6.415692-5.732941-11.352089 0.648433-17.052518 6.881696-6.151983 12.887376-13.555677 21.838999-12.847639 12.423177 0.149916 33.456603 18.168762 36.724054 30.095229 2.94775 10.784936-4.520967 24.485111-16.727398 32.389127z" />
</vector>

View File

@@ -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" />
<!-- 子按钮2 -->
@@ -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" />
<!-- 主浮动按钮 -->

View File

@@ -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" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>

View File

@@ -254,7 +254,7 @@
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayoutNew
android:id="@+id/uldNoInput"
enable="@{!viewModel.isUldNoLocked}"
enable="@{!viewModel.isUldNoLocked &amp;&amp; !viewModel.isFromEditMode}"
required="@{false}"
setRefreshCallBack="@{viewModel::onUldNoInputComplete}"
title='@{"ULD编号"}'

View File

@@ -92,31 +92,6 @@
</LinearLayout>
<!-- 总重 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
android:text="总重:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf((int)bean.totalWeight)}"
android:textColor="@color/text_normal"
android:textSize="16sp" />
</LinearLayout>
<!-- 货重 -->
<LinearLayout
android:layout_width="0dp"
@@ -171,7 +146,7 @@
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="0.8"
android:gravity="center_vertical"
android:orientation="horizontal">
@@ -192,6 +167,31 @@
</LinearLayout>
<!-- 回填状态 -->
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{5}"
android:text="回填状态:"
android:textColor="@color/text_normal"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bean.fillWeightFlagText}"
android:textColor="@{bean.isFillWeightGreen ? @color/text_green : @color/text_normal}"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
<!-- 第二行:航班日期、航班号、组装人、组装区、组装时间 -->
@@ -288,7 +288,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
completeSpace="@{4}"
completeSpace="@{5}"
android:text="组装区:"
android:textColor="@color/text_normal"
android:textSize="16sp" />

View File

@@ -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 <https://github.com/Genymobile/scrcpy>
INFO: ADB device found:
INFO: --> (usb) 80STHZCHDLL4311422 device A80ST
INFO: Renderer: metal
INFO: Texture: 1280x800