feat: 新增图片选择控件并修正事故签证字段

- 新增 ImageSelectNewViewHolder 和 item_image_select_new 布局,支持正方形缩略图、
  加号按钮始终在末尾、详情模式隐藏加号及"暂无图片"占位
- 国际事故签证编辑页和国内进港移交页应用新图片选择控件
- 修正事故签证字段:reweight → reWeight,opName/opDate → opId/opdate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 12:02:16 +08:00
parent 88bbd73fa1
commit 3918ad64d6
18 changed files with 1311 additions and 573 deletions

View File

@@ -0,0 +1,64 @@
package com.lukouguoji.gnj.page.yiku.handover
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.alibaba.android.arouter.facade.annotation.Route
import com.lukouguoji.gnj.R
import com.lukouguoji.gnj.databinding.ActivityGnjYikuHandoverBinding
import com.lukouguoji.module_base.base.BaseBindingActivity
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.DetailsPageType
import com.lukouguoji.module_base.ktx.addOnItemClickListener
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.router.ARouterConstants
/**
* 国内进港移交编辑/详情页
*/
@Route(path = ARouterConstants.ACTIVITY_URL_GNJ_YIKU_HANDOVER)
class GnjYiKuHandoverActivity :
BaseBindingActivity<ActivityGnjYikuHandoverBinding, GnjYiKuHandoverViewModel>() {
override fun layoutId() = R.layout.activity_gnj_yiku_handover
override fun viewModelClass() = GnjYiKuHandoverViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
viewModel.initOnCreated(intent)
when (viewModel.pageType.value) {
DetailsPageType.Modify -> setBackArrow("国内进港移交编辑")
DetailsPageType.Details -> setBackArrow("国内进港移交详情")
else -> setBackArrow("国内进港移交")
}
binding.viewModel = viewModel
// 绑定图片列表点击事件(编辑模式下可删除图片)
binding.rvImages.addOnItemClickListener(viewModel)
// 监听图片列表变化并更新 adapter
viewModel.imageList.observe(this) { images ->
binding.rvImages.commonAdapter()?.refresh(images)
}
}
companion object {
@JvmStatic
fun startForEdit(context: Context, id: String) {
val starter = Intent(context, GnjYiKuHandoverActivity::class.java)
.putExtra(Constant.Key.PAGE_TYPE, DetailsPageType.Modify.name)
.putExtra(Constant.Key.ID, id)
context.startActivity(starter)
}
@JvmStatic
fun startForDetails(context: Context, id: String) {
val starter = Intent(context, GnjYiKuHandoverActivity::class.java)
.putExtra(Constant.Key.PAGE_TYPE, DetailsPageType.Details.name)
.putExtra(Constant.Key.ID, id)
context.startActivity(starter)
}
}
}

View File

@@ -0,0 +1,136 @@
package com.lukouguoji.gnj.page.yiku.handover
import android.content.Intent
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.gnj.R
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.FileBean
import com.lukouguoji.module_base.bean.GnjYiKuBean
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.common.DetailsPageType
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.impl.ImageSelectNewViewHolder
import com.lukouguoji.module_base.interfaces.IOnItemClickListener
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.util.UploadUtil
import kotlinx.coroutines.launch
/**
* 国内进港移交编辑/详情 ViewModel
*/
class GnjYiKuHandoverViewModel : BaseViewModel(), IOnItemClickListener {
val pageType = MutableLiveData(DetailsPageType.Modify)
var mawbId = ""
val dataBean = MutableLiveData(GnjYiKuBean())
// 图片列表
val imageList = MutableLiveData<MutableList<FileBean>>(mutableListOf())
// 图片适配器配置
val imageItemLayoutId = R.layout.item_image_select_new
val imageItemViewHolder = ImageSelectNewViewHolder::class.java
// 详情模式下无图片时显示占位提示
val showNoImage = MutableLiveData(false)
fun initOnCreated(intent: Intent) {
pageType.value = DetailsPageType.valueOf(
intent.getStringExtra(Constant.Key.PAGE_TYPE) ?: DetailsPageType.Modify.name
)
mawbId = intent.getStringExtra(Constant.Key.ID) ?: ""
loadData()
}
private fun loadData() {
launchLoadingCollect({
NetApply.api.getGnjMoveStashDetail(mawbId)
}) {
onSuccess = {
val bean = it.data ?: GnjYiKuBean()
dataBean.value = bean
// 处理图片列表
val images = bean.getImageList().map { url ->
FileBean(path = url)
}.toMutableList()
// 编辑模式添加空 FileBean 用于显示"添加照片"按钮
if (pageType.value == DetailsPageType.Modify) {
images.add(FileBean())
}
imageList.value = images
// 详情模式下无图片时显示占位提示
if (pageType.value == DetailsPageType.Details && bean.getImageList().isEmpty()) {
showNoImage.value = true
}
}
}
}
/**
* 提交保存(只保存备注和图片)
*/
fun submit() {
val bean = dataBean.value ?: return
// 获取所有非空图片
val images = imageList.value!!.filter { it.path.isNotEmpty() }
if (images.size > 7) {
showToast("最多上传7张图片")
return
}
launchLoadingCollect({
// 上传图片
val uploadedUrls = mutableListOf<String>()
images.forEach { fileBean ->
if (fileBean.path.startsWith("http")) {
uploadedUrls.add(fileBean.path)
} else {
val result = UploadUtil.upload(fileBean.path)
if (result.verifySuccess()) {
uploadedUrls.add(result.data?.newName ?: "")
}
}
}
// 提交(只更新备注和图片)
val params = mapOf(
"mawbId" to mawbId,
"remark" to bean.remark,
"originalPic" to uploadedUrls.joinToString(","),
).toRequestBody(removeEmptyOrNull = true)
NetApply.api.modifyGnjMoveStash(params)
}) {
onSuccess = {
showToast("保存成功")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH_GNJ_YIKU_LIST).emit("refresh")
}
getTopActivity().finish()
}
}
}
/**
* 处理图片删除点击事件
*/
override fun onItemClick(position: Int, type: Int) {
val list = imageList.value!!
if (type == R.id.iv_delete && position < list.size) {
list.removeAt(position)
imageList.value = list
}
}
}

View File

@@ -1,23 +1,35 @@
package com.lukouguoji.gnj.page.yiku.list
import android.view.View
import com.lukouguoji.gnj.databinding.ItemGnjYikuListBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GnjYiKuBean
/**
* 国内进港移库列表 ViewHolder
*/
class GnjYiKuListViewHolder(view: View) :
BaseViewHolder<GnjYiKuBean, ItemGnjYikuListBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item)!!
binding.bean = bean
// 点击checkbox切换选中状态
binding.ivIcon.setOnClickListener {
bean.checked.set(!bean.checked.get())
}
}
}
package com.lukouguoji.gnj.page.yiku.list
import android.view.View
import com.lukouguoji.gnj.databinding.ItemGnjYikuListBinding
import com.lukouguoji.gnj.page.yiku.handover.GnjYiKuHandoverActivity
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.GnjYiKuBean
/**
* 国内进港移库列表 ViewHolder
*/
class GnjYiKuListViewHolder(view: View) :
BaseViewHolder<GnjYiKuBean, ItemGnjYikuListBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item)!!
binding.bean = bean
// 点击 checkbox 切换选中状态
binding.ivIcon.setOnClickListener {
bean.checked.set(!bean.checked.get())
}
// 点击列表项进入移交详情
binding.ll.setOnClickListener {
GnjYiKuHandoverActivity.startForDetails(itemView.context, bean.id)
}
// 侧滑菜单 - 编辑按钮
binding.btnEdit.setOnClickListener {
binding.swipeMenu.quickClose()
GnjYiKuHandoverActivity.startForEdit(itemView.context, bean.id)
}
}
}