From 51c5ac6e9689bb967a496fe67382a4417f1dacef Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Tue, 8 Sep 2026 16:00:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E5=87=BA=E6=B8=AF?= =?UTF-8?q?=E7=A7=BB=E5=BA=93=E6=96=B0=E5=A2=9E=E8=AF=A6=E6=83=85=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E4=B8=8E=E4=BE=A7=E6=BB=91=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 列表项右侧增加箭头,点击进入详情页;左滑显示“编辑”按钮进入编辑页。 详情与编辑复用同一表单页,编辑模式仅支持修改备注与交接图片上传/删除, 表单结构参考国内进港移交编辑。 Co-Authored-By: Claude Opus 4.6 --- app/src/main/AndroidManifest.xml | 6 + .../lukouguoji/module_base/bean/GjcMaWb.kt | 3 + .../lukouguoji/module_base/http/net/Api.kt | 14 + .../module_base/router/ARouterConstants.kt | 1 + .../gjc/holder/IntExpMoveViewHolder.kt | 12 + .../gjc/page/move/IntExpMoveEditActivity.kt | 68 +++++ .../gjc/viewModel/IntExpMoveEditViewModel.kt | 164 +++++++++++ .../res/layout/activity_int_exp_move_edit.xml | 259 ++++++++++++++++++ .../src/main/res/layout/item_int_exp_move.xml | 32 +++ 9 files changed, 559 insertions(+) create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveEditActivity.kt create mode 100644 module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveEditViewModel.kt create mode 100644 module_gjc/src/main/res/layout/activity_int_exp_move_edit.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 932eace..9a61963 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -222,6 +222,12 @@ android:configChanges="orientation|keyboardHidden" android:exported="false" android:screenOrientation="userLandscape" /> + + + /** + * 国际出港移库-详情 + * 接口路径: /IntExpMove/detail + */ + @POST("IntExpMove/detail") + suspend fun getIntExpMoveDetail(@Query("maWbId") maWbId: Long): BaseResultBean + + /** + * 国际出港移库-编辑(仅更新备注与交接图片) + * 接口路径: /IntExpMove/update + */ + @POST("IntExpMove/update") + suspend fun updateIntExpMove(@Body data: RequestBody): BaseResultBean + /** * 国际出港库位操作-清仓 * 接口路径: /IntExpStorageUse/updateClear diff --git a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt index ff0003c..8fe00d5 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt @@ -142,6 +142,7 @@ object ARouterConstants { const val ACTIVITY_URL_INT_EXP_ASSEMBLE = "/gjc/IntExpAssembleActivity" //国际出港 出港组装 const val ACTIVITY_URL_INT_EXP_ASSEMBLE_START = "/gjc/IntExpAssembleStartActivity" //国际出港 开始组装 const val ACTIVITY_URL_INT_EXP_MOVE = "/gjc/IntExpMoveActivity" //国际出港 出港移库 + const val ACTIVITY_URL_INT_EXP_MOVE_EDIT = "/gjc/IntExpMoveEditActivity" //国际出港 出港移库编辑/详情 const val ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE = "/gjc/GjcAssembleAllocateActivity" //国际出港 组装分配 const val ACTIVITY_URL_INT_EXP_OUT_HANDOVER = "/gjc/IntExpOutHandoverActivity" //国际出港 出库交接 const val ACTIVITY_URL_INT_EXP_LOAD = "/gjc/IntExpLoadActivity" //国际出港 出港装载 diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt index e94899a..0173785 100644 --- a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpMoveViewHolder.kt @@ -2,6 +2,7 @@ package com.lukouguoji.gjc.holder import android.view.View import com.lukouguoji.gjc.databinding.ItemIntExpMoveBinding +import com.lukouguoji.gjc.page.move.IntExpMoveEditActivity import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.GjcMove import com.lukouguoji.module_base.common.ConstantEvent @@ -31,6 +32,17 @@ class IntExpMoveViewHolder(view: View) : } } + // 点击列表项进入移库详情 + binding.ll.setOnClickListener { + IntExpMoveEditActivity.startForDetails(itemView.context, bean.maWbId) + } + + // 侧滑菜单 - 编辑按钮 + binding.btnEdit.setOnClickListener { + binding.swipeMenu.quickClose() + IntExpMoveEditActivity.startForEdit(itemView.context, bean.maWbId) + } + binding.executePendingBindings() } } diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveEditActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveEditActivity.kt new file mode 100644 index 0000000..46c1759 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/page/move/IntExpMoveEditActivity.kt @@ -0,0 +1,68 @@ +package com.lukouguoji.gjc.page.move + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.gjc.R +import com.lukouguoji.gjc.databinding.ActivityIntExpMoveEditBinding +import com.lukouguoji.gjc.viewModel.IntExpMoveEditViewModel +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_INT_EXP_MOVE_EDIT) +class IntExpMoveEditActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_exp_move_edit + + override fun viewModelClass() = IntExpMoveEditViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + viewModel.initOnCreated(intent) + + when (viewModel.pageType.value) { + DetailsPageType.Modify -> setBackArrow("国际出港移库编辑") + else -> setBackArrow("国际出港移库详情") + } + + binding.viewModel = viewModel + + // 绑定图片 RecyclerView 引用 + viewModel.rvImages = binding.rvImages + + // 绑定图片列表点击事件(编辑模式下可删除图片) + binding.rvImages.addOnItemClickListener(viewModel) + + // 监听图片列表变化并更新 adapter + viewModel.imageList.observe(this) { images -> + binding.rvImages.commonAdapter()?.refresh(images) + } + } + + companion object { + @JvmStatic + fun startForEdit(context: Context, maWbId: Long?) { + val starter = Intent(context, IntExpMoveEditActivity::class.java) + .putExtra(Constant.Key.PAGE_TYPE, DetailsPageType.Modify.name) + .putExtra(Constant.Key.ID, maWbId?.toString() ?: "") + context.startActivity(starter) + } + + @JvmStatic + fun startForDetails(context: Context, maWbId: Long?) { + val starter = Intent(context, IntExpMoveEditActivity::class.java) + .putExtra(Constant.Key.PAGE_TYPE, DetailsPageType.Details.name) + .putExtra(Constant.Key.ID, maWbId?.toString() ?: "") + context.startActivity(starter) + } + } +} diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveEditViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveEditViewModel.kt new file mode 100644 index 0000000..8d77367 --- /dev/null +++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpMoveEditViewModel.kt @@ -0,0 +1,164 @@ +package com.lukouguoji.gjc.viewModel + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import androidx.recyclerview.widget.RecyclerView +import com.lukouguoji.gjc.R +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.FileBean +import com.lukouguoji.module_base.bean.GjcMaWb +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.commonAdapter +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.MediaUtil +import com.lukouguoji.module_base.util.UploadUtil +import kotlinx.coroutines.launch + +/** + * 国际出港移库编辑/详情 ViewModel + * 编辑模式仅支持修改备注与交接图片 + */ +class IntExpMoveEditViewModel : BaseViewModel(), IOnItemClickListener { + + val pageType = MutableLiveData(DetailsPageType.Details) + private var maWbId: Long = 0L + + val dataBean = MutableLiveData(GjcMaWb()) + + // 备注单独用 LiveData 双向绑定,避免修改 data class 属性后需重新赋值 + val remark = MutableLiveData("") + + // 图片列表 + val imageList = MutableLiveData>(mutableListOf()) + + // 图片适配器配置 + val imageItemLayoutId = R.layout.item_image_select_new + val imageItemViewHolder = ImageSelectNewViewHolder::class.java + + // 详情模式下无图片时显示占位提示 + val showNoImage = MutableLiveData(false) + + // 图片 RecyclerView 引用(用于从 adapter 实时获取图片) + var rvImages: RecyclerView? = null + + fun initOnCreated(intent: Intent) { + pageType.value = DetailsPageType.valueOf( + intent.getStringExtra(Constant.Key.PAGE_TYPE) ?: DetailsPageType.Details.name + ) + maWbId = intent.getStringExtra(Constant.Key.ID)?.toLongOrNull() ?: 0L + loadData() + } + + private fun loadData() { + launchLoadingCollect({ NetApply.api.getIntExpMoveDetail(maWbId) }) { + onSuccess = { + val bean = it.data ?: GjcMaWb() + // 详情接口 wbNo 可能为空,回退为 前缀 + 运单号 + if (bean.wbNo.isNullOrEmpty()) { + bean.wbNo = (bean.prefix ?: "") + (bean.no ?: "") + } + dataBean.value = bean + remark.value = bean.remark ?: "" + + // 处理图片列表(同时保留缩略图和原图信息,确保二次编辑时不丢失) + val picList = (bean.pic ?: "").split(",").filter { p -> p.isNotEmpty() } + val originalPicList = (bean.originalPic ?: "").split(",").filter { p -> p.isNotEmpty() } + val images = if (picList.isNotEmpty()) { + picList.mapIndexed { index, picUrl -> + val originalUrl = originalPicList.getOrElse(index) { picUrl } + FileBean( + path = MediaUtil.fillUrl(originalUrl), + url = picUrl, + originalPic = originalUrl + ) + }.toMutableList() + } else { + originalPicList.map { url -> + FileBean(path = MediaUtil.fillUrl(url), url = url, originalPic = url) + }.toMutableList() + } + + // 编辑模式添加空 FileBean 用于显示“添加照片”按钮 + if (pageType.value == DetailsPageType.Modify) { + images.add(FileBean()) + } + + imageList.value = images + + // 详情模式下无图片时显示占位提示 + showNoImage.value = pageType.value == DetailsPageType.Details && images.isEmpty() + } + } + } + + /** + * 提交保存(只保存备注和图片) + */ + fun submit() { + // 从 adapter 实时获取所有非空图片(ViewHolder 新增图片直接操作 adapter items) + val allItems = (rvImages?.commonAdapter()?.items as? List<*>) + ?.filterIsInstance() ?: imageList.value!! + val images = allItems.filter { it.path.isNotEmpty() } + + if (images.size > 7) { + showToast("最多上传7张图片") + return + } + + launchLoadingCollect({ + // 上传本地新图片;已上传的图片保持原有 url 与 originalPic + images.forEach { fileBean -> + if (fileBean.url.isEmpty()) { + // UploadUtil 返回:newName=原图(较大),zipFileName=缩略图(较小) + // FileBean.url 用作缩略图标识,FileBean.originalPic 用作原图标识 + val data = UploadUtil.upload(fileBean.path).data + fileBean.url = data?.zipFileName ?: "" + fileBean.originalPic = data?.newName ?: "" + } + } + + val params = mapOf( + "maWbId" to maWbId, + "remark" to (remark.value ?: ""), + "picNumber" to images.size.toString(), + "pic" to images.joinToString(",") { MediaUtil.removeUrl(it.url) }, + "originalPic" to images.joinToString(",") { MediaUtil.removeUrl(it.originalPic) }, + ).toRequestBody(removeEmptyOrNull = true) + + NetApply.api.updateIntExpMove(params) + }) { + onSuccess = { + showToast("保存成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + getTopActivity().finish() + } + } + } + + fun cancel() { + getTopActivity().finish() + } + + /** + * 处理图片删除点击事件 + */ + override fun onItemClick(position: Int, type: Int) { + if (type == R.id.iv_delete) { + val adapter = rvImages?.commonAdapter() ?: return + if (position < adapter.items.size) { + adapter.removeItem(position) + } + } + } +} diff --git a/module_gjc/src/main/res/layout/activity_int_exp_move_edit.xml b/module_gjc/src/main/res/layout/activity_int_exp_move_edit.xml new file mode 100644 index 0000000..28633fd --- /dev/null +++ b/module_gjc/src/main/res/layout/activity_int_exp_move_edit.xml @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjc/src/main/res/layout/item_int_exp_move.xml b/module_gjc/src/main/res/layout/item_int_exp_move.xml index 2ecdcdf..1d8b225 100644 --- a/module_gjc/src/main/res/layout/item_int_exp_move.xml +++ b/module_gjc/src/main/res/layout/item_int_exp_move.xml @@ -21,8 +21,15 @@ android:layout_marginTop="10dp" android:orientation="vertical"> + + + + + + + + + + + + + + + +