feat: ui opt

This commit is contained in:
2025-11-26 19:39:05 +08:00
parent ec9818e267
commit 83ccad4171
13 changed files with 697 additions and 4 deletions

View File

@@ -0,0 +1,233 @@
package com.lukouguoji.gjc.viewModel
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.GjcCheckInRecord
import com.lukouguoji.module_base.bean.GjcWeighingRecordBean
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import kotlinx.coroutines.launch
/**
* 国际出港计重明细 ViewModel
* 严格按照设计图实现三个独立部分:运单信息、计重记录列表、底部统计与按钮
*/
class GjcWeighingRecordDetailsViewModel : BaseViewModel() {
///////////////////////////////////////////////////////////////////////////
// 数据字段
///////////////////////////////////////////////////////////////////////////
// 运单信息Bean从列表页传入
val waybillBean = MutableLiveData<GjcWeighingRecordBean>()
// 编辑模式false=只读true=编辑
val isEditMode = MutableLiveData(false)
// 计重记录列表
val recordList = MutableLiveData<List<GjcCheckInRecord>>(emptyList())
// 备份数据(用于取消时恢复)
private var backupList: List<GjcCheckInRecord> = emptyList()
///////////////////////////////////////////////////////////////////////////
// 第一部分:运单信息字段(顶部显示区域)
///////////////////////////////////////////////////////////////////////////
val waybillNo = MutableLiveData("") // 运单号prefix-no
val prePc = MutableLiveData("") // 预配件数
val preWeight = MutableLiveData("") // 预配重量
val goodsName = MutableLiveData("") // 品名(中文)
///////////////////////////////////////////////////////////////////////////
// 第三部分:底部统计字段
///////////////////////////////////////////////////////////////////////////
val totalPc = MutableLiveData("0") // 总件数
val totalWeight = MutableLiveData("0.0") // 总重量
val weightError = MutableLiveData("0.0%") // 重量误差百分比
// 传递参数用于API调用
private var prefix = ""
private var no = ""
private var opDate = ""
init {
// 监听 recordList 变化,自动触发统计计算
recordList.observeForever {
calculateStatistics()
}
}
///////////////////////////////////////////////////////////////////////////
// 初始化
///////////////////////////////////////////////////////////////////////////
fun initOnCreated(intent: Intent) {
// 接收传入的完整 Bean 对象
val bean = intent.getSerializableExtra(Constant.Key.BEAN) as? GjcWeighingRecordBean
bean?.let {
waybillBean.value = it
// 提取运单信息字段
waybillNo.value = "${it.prefix}-${it.no}"
prePc.value = it.pc.toString()
preWeight.value = it.weight.toString()
goodsName.value = it.goodsCn
// 保存参数用于API调用
prefix = it.prefix
no = it.no
opDate = it.opDate
// 加载计重记录数据
loadData()
} ?: run {
showToast("参数错误")
}
}
///////////////////////////////////////////////////////////////////////////
// 数据加载
///////////////////////////////////////////////////////////////////////////
private fun loadData() {
val params = mapOf(
"prefix" to prefix,
"no" to no,
"opDate" to opDate
).toRequestBody()
launchLoadingCollect({ NetApply.api.getGjcCheckInRecordList(params) }) {
onSuccess = { result ->
val list = result.data ?: emptyList()
recordList.value = list
if (list.isEmpty()) {
showToast("暂无计重记录")
}
}
onFailed = { code, msg ->
showToast("加载失败:$msg")
}
}
}
/**
* 计算统计数据:总件数、总重量、重量误差
*/
private fun calculateStatistics() {
val records = recordList.value ?: emptyList()
// 计算总件数
val sumPc = records.sumOf { it.pc }
totalPc.value = sumPc.toString()
// 计算总重量
val sumWeight = records.sumOf { it.weight }
totalWeight.value = String.format("%.2f", sumWeight)
// 计算重量误差百分比
val preWeightValue = preWeight.value?.toDoubleOrNull() ?: 0.0
val error = if (preWeightValue > 0) {
((sumWeight - preWeightValue) / preWeightValue * 100)
} else {
0.0
}
weightError.value = String.format("%.1f%%", error)
}
///////////////////////////////////////////////////////////////////////////
// 按钮事件
///////////////////////////////////////////////////////////////////////////
/**
* 点击"修改"按钮
*/
fun onModifyClick() {
// 备份当前数据(深拷贝)
backupList = recordList.value?.map { it.copy() } ?: emptyList()
// 进入编辑模式
isEditMode.value = true
}
/**
* 点击"取消"按钮
*/
fun onCancelClick() {
// 恢复备份数据(深拷贝)
recordList.value = backupList.map { it.copy() }
// 退出编辑模式
isEditMode.value = false
// 重新计算统计(会自动触发)
}
/**
* 点击"保存"按钮
*/
fun onSaveClick() {
val records = recordList.value ?: return
// 验证数据
if (!validateRecords(records)) return
// 调用批量更新接口
saveRecords(records)
}
///////////////////////////////////////////////////////////////////////////
// 业务逻辑
///////////////////////////////////////////////////////////////////////////
/**
* 验证数据
*/
private fun validateRecords(records: List<GjcCheckInRecord>): Boolean {
records.forEachIndexed { index, record ->
if (record.pc <= 0) {
showToast("${index + 1}条记录的件数必须大于0")
return false
}
if (record.weight <= 0.0) {
showToast("${index + 1}条记录的重量必须大于0")
return false
}
}
return true
}
/**
* 批量保存计重记录
*/
private fun saveRecords(records: List<GjcCheckInRecord>) {
launchLoadingCollect({
NetApply.api.updateGjcCheckInRecordList(records)
}) {
onSuccess = { result ->
if (result.data == true) {
showToast("保存成功")
// 退出编辑模式
isEditMode.value = false
// 发送刷新事件通知列表页
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
// 关闭页面
getTopActivity().finish()
} else {
showToast("保存失败")
}
}
onFailed = { code, msg ->
showToast("保存失败:$msg")
}
}
}
}