From 9b089d51b148a5b24dae2da2e25888ad103a63f2 Mon Sep 17 00:00:00 2001 From: YANGJIANKUAN Date: Tue, 17 Mar 2026 11:37:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=BD=E9=99=85=E4=BA=8B=E6=95=85?= =?UTF-8?q?=E7=AD=BE=E8=AF=81=E6=96=B0=E5=A2=9E/=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=8F=8A=E5=88=97=E8=A1=A8=E4=BE=A7=E6=BB=91?= =?UTF-8?q?=E8=8F=9C=E5=8D=95?= 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 + .../bean/GjAccidentVisaEditBean.kt | 26 + .../lukouguoji/module_base/http/net/Api.kt | 37 ++ .../activity/IntImpAccidentVisaActivity.kt | 20 +- .../IntImpAccidentVisaEditActivity.kt | 45 ++ .../holder/IntImpAccidentVisaViewHolder.kt | 6 + .../IntImpAccidentVisaEditViewModel.kt | 271 ++++++++++ .../viewModel/IntImpAccidentVisaViewModel.kt | 4 + .../layout/activity_int_imp_accident_visa.xml | 1 + .../activity_int_imp_accident_visa_edit.xml | 363 +++++++++++++ .../res/layout/item_int_imp_accident_visa.xml | 504 ++++++++++-------- 11 files changed, 1046 insertions(+), 237 deletions(-) create mode 100644 module_base/src/main/java/com/lukouguoji/module_base/bean/GjAccidentVisaEditBean.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaEditActivity.kt create mode 100644 module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaEditViewModel.kt create mode 100644 module_gjj/src/main/res/layout/activity_int_imp_accident_visa_edit.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 52688d9..cca2a4f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -529,6 +529,12 @@ android:exported="false" android:screenOrientation="userLandscape" /> + + diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjAccidentVisaEditBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjAccidentVisaEditBean.kt new file mode 100644 index 0000000..bb565fc --- /dev/null +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjAccidentVisaEditBean.kt @@ -0,0 +1,26 @@ +package com.lukouguoji.module_base.bean + +class GjAccidentVisaEditBean { + var id: Long = 0 + var fdate: String = "" // 航班日期 + var fno: String = "" // 航班号 + var dep: String = "" // 始发站 + var dest: String = "" // 目的站 + var wbNo: String = "" // 运单号 + var dpc: String = "" // 不正常件数 + var pc: String = "" // 运单总件数 + var weight: String = "" // 运单总重量 + var reweight: String = "" // 复称重量 + var goods: String = "" // 品名 + var opacking: String = "" // 外包装 + var damage: String = "" // 包装破损情况 + var condition: String = "" // 内容物情况 + var problem: String = "" // 不正常类型 + var seachDate: String = "" // 发现时间 + var photo: String = "" // 图片是否留底 + var remarks: String = "" // 备注 + var pic: String = "" // 缩略图 + var originalPic: String = "" // 原图 + var picNumber: String = "" // 图片数量 + var idFlag: String = "1" // 国际标志(固定为1=国际) +} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt index 70499d3..caa6a9b 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt @@ -51,6 +51,7 @@ import com.lukouguoji.module_base.bean.GjjGoodsDetailsBean import com.lukouguoji.module_base.bean.GjjGoodsTypeBean import com.lukouguoji.module_base.bean.GjjHandoverRecordBean import com.lukouguoji.module_base.bean.GjjImportTally +import com.lukouguoji.module_base.bean.GjAccidentVisaEditBean import com.lukouguoji.module_base.bean.IntImpAccidentVisaBean import com.lukouguoji.module_base.bean.IntImpPickUpDLVBean import com.lukouguoji.module_base.bean.IntImpPickUpRecordBean @@ -1962,6 +1963,42 @@ interface Api { @POST("GjAccidentVisa/delete") suspend fun deleteIntImpAccidentVisa(@Body data: RequestBody): BaseResultBean + /** + * 国际事故签证-新增 + */ + @POST("GjAccidentVisa/saveVisa") + suspend fun saveGjAccidentVisa(@Body data: RequestBody): BaseResultBean + + /** + * 国际事故签证-修改 + */ + @POST("GjAccidentVisa/modifyVisa") + suspend fun modifyGjAccidentVisa(@Body data: RequestBody): BaseResultBean + + /** + * 国际事故签证-详情 + */ + @POST("GjAccidentVisa/detail") + suspend fun getGjAccidentVisaDetail(@Query("id") id: Long): BaseResultBean + + /** + * 字典-破损情况 + */ + @POST("typeCode/damageType") + suspend fun getDamageTypeList(): DictListBean + + /** + * 字典-内容物情况 + */ + @POST("typeCode/contentType") + suspend fun getContentTypeList(): DictListBean + + /** + * 字典-不正常类型 + */ + @POST("typeCode/unusualType") + suspend fun getUnusualTypeList(): DictListBean + /////////////////////////////////////////////////////////////////////////// // ULD管理 /////////////////////////////////////////////////////////////////////////// diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaActivity.kt index e2d897e..1684886 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaActivity.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaActivity.kt @@ -8,10 +8,14 @@ import com.lukouguoji.gjj.R import com.lukouguoji.gjj.databinding.ActivityIntImpAccidentVisaBinding import com.lukouguoji.gjj.viewModel.IntImpAccidentVisaViewModel import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.IntImpAccidentVisaBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.common.ConstantEvent import com.lukouguoji.module_base.impl.FlowBus import com.lukouguoji.module_base.impl.observe +import com.lukouguoji.module_base.interfaces.IOnItemClickListener +import com.lukouguoji.module_base.ktx.addOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.router.ARouterConstants /** @@ -19,7 +23,8 @@ import com.lukouguoji.module_base.router.ARouterConstants */ @Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_ACCIDENT_VISA) class IntImpAccidentVisaActivity : - BaseBindingActivity() { + BaseBindingActivity(), + IOnItemClickListener { override fun layoutId() = R.layout.activity_int_imp_accident_visa override fun viewModelClass() = IntImpAccidentVisaViewModel::class.java @@ -34,6 +39,8 @@ class IntImpAccidentVisaActivity : viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) + binding.rv.addOnItemClickListener(this) + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { viewModel.refresh() } @@ -48,4 +55,15 @@ class IntImpAccidentVisaActivity : viewModel.searchClick() } } + + override fun onItemClick(position: Int, type: Int) { + when (type) { + 2000 -> { + // 侧滑菜单 - 修改 + val bean = binding.rv.commonAdapter()?.getItem(position) as? IntImpAccidentVisaBean + ?: return + IntImpAccidentVisaEditActivity.start(this, bean.id) + } + } + } } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaEditActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaEditActivity.kt new file mode 100644 index 0000000..e6cd53c --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpAccidentVisaEditActivity.kt @@ -0,0 +1,45 @@ +package com.lukouguoji.gjj.activity + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.gjj.R +import com.lukouguoji.gjj.databinding.ActivityIntImpAccidentVisaEditBinding +import com.lukouguoji.gjj.viewModel.IntImpAccidentVisaEditViewModel +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 + +/** + * 国际进港-事故签证新增/编辑 + */ +class IntImpAccidentVisaEditActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_int_imp_accident_visa_edit + override fun viewModelClass() = IntImpAccidentVisaEditViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + binding.viewModel = viewModel + + viewModel.rv = binding.rv + binding.rv.addOnItemClickListener(viewModel) + viewModel.initOnCreate(intent) + + viewModel.pageType.observe(this) { + val title = if (it == DetailsPageType.Add) "国际事故签证新增" else "国际事故签证修改" + setBackArrow(title) + } + } + + companion object { + @JvmStatic + fun start(context: Context, id: Long = 0) { + context.startActivity( + Intent(context, IntImpAccidentVisaEditActivity::class.java) + .putExtra(Constant.Key.ID, id) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpAccidentVisaViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpAccidentVisaViewHolder.kt index 7263206..bdc3e6d 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpAccidentVisaViewHolder.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpAccidentVisaViewHolder.kt @@ -21,5 +21,11 @@ class IntImpAccidentVisaViewHolder(view: View) : bean.checked.set(!bean.checked.get()) binding.executePendingBindings() } + + // 侧滑菜单 - 修改按钮 + binding.btnEdit.setOnClickListener { + binding.swipeMenu.quickClose() + clickListener?.onItemClick(position, 2000) // type=2000表示修改操作 + } } } diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaEditViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaEditViewModel.kt new file mode 100644 index 0000000..0d7abb6 --- /dev/null +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaEditViewModel.kt @@ -0,0 +1,271 @@ +package com.lukouguoji.gjj.viewModel + +import android.content.Intent +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import androidx.recyclerview.widget.RecyclerView +import com.lukouguoji.gjj.R +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.FileBean +import com.lukouguoji.module_base.bean.GjAccidentVisaEditBean +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.ImageSelectViewHolder +import com.lukouguoji.module_base.interfaces.IOnItemClickListener +import com.lukouguoji.module_base.ktx.commonAdapter +import com.lukouguoji.module_base.ktx.launchCollect +import com.lukouguoji.module_base.ktx.launchLoadingCollect +import com.lukouguoji.module_base.ktx.noNull +import com.lukouguoji.module_base.ktx.showToast +import com.lukouguoji.module_base.ktx.toRequestBody +import com.lukouguoji.module_base.ktx.verifyNullOrEmpty +import com.lukouguoji.module_base.util.MediaUtil +import com.lukouguoji.module_base.util.UploadUtil +import dev.utils.app.info.KeyValue +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch + +class IntImpAccidentVisaEditViewModel : BaseViewModel(), IOnItemClickListener { + + var id: Long = 0 + + val pageType = MutableLiveData(DetailsPageType.Add) + + val dataBean = MutableLiveData(GjAccidentVisaEditBean()) + + // 图片列表 + val itemLayoutId = R.layout.item_image_select + val itemViewHolder = ImageSelectViewHolder::class.java + var rv: RecyclerView? = null + + // 下拉列表 + val outerPackageList = MutableLiveData>(emptyList()) + val damageTypeList = MutableLiveData>(emptyList()) + val contentTypeList = MutableLiveData>(emptyList()) + val unusualTypeList = MutableLiveData>(emptyList()) + val photoList = MutableLiveData( + listOf(KeyValue("是", "是"), KeyValue("否", "否")) + ) + + // 航班级联查询 + private var lastQueriedFlight = "" + + /////////////////////////////////////////////////////////////////////////// + // 初始化 + /////////////////////////////////////////////////////////////////////////// + + fun initOnCreate(intent: Intent) { + id = intent.getLongExtra(Constant.Key.ID, 0) + pageType.value = if (id == 0L) DetailsPageType.Add else DetailsPageType.Modify + + loadDropdownLists() + + if (id != 0L) { + loadDetail() + } + + rv?.post { + rv?.commonAdapter()?.addItem(FileBean()) + } + } + + private fun loadDropdownLists() { + launchCollect({ NetApply.api.getPackTypeList() }) { + onSuccess = { result -> + outerPackageList.value = result.data?.mapNotNull { bean -> + bean.name?.let { name -> KeyValue(name, name) } + } ?: emptyList() + } + } + launchCollect({ NetApply.api.getDamageTypeList() }) { + onSuccess = { result -> + damageTypeList.value = result.data?.mapNotNull { bean -> + bean.name?.let { name -> KeyValue(name, name) } + } ?: emptyList() + } + } + launchCollect({ NetApply.api.getContentTypeList() }) { + onSuccess = { result -> + contentTypeList.value = result.data?.mapNotNull { bean -> + bean.name?.let { name -> KeyValue(name, name) } + } ?: emptyList() + } + } + launchCollect({ NetApply.api.getUnusualTypeList() }) { + onSuccess = { result -> + unusualTypeList.value = result.data?.mapNotNull { bean -> + bean.name?.let { name -> KeyValue(name, name) } + } ?: emptyList() + } + } + } + + private fun loadDetail() { + launchLoadingCollect({ NetApply.api.getGjAccidentVisaDetail(id) }) { + onSuccess = { + dataBean.value = it.data ?: GjAccidentVisaEditBean() + + // 渲染图片 + val bean = dataBean.value!! + val picList = bean.pic.split(",") + .filter { url -> url.isNotEmpty() } + .map { url -> FileBean(MediaUtil.fillUrl(url), url) } + val originalList = bean.originalPic.split(",") + .filter { url -> url.isNotEmpty() } + .map { url -> FileBean(MediaUtil.fillUrl(url)) } + for ((index, fileBean) in picList.withIndex()) { + if (index < originalList.size) { + picList[index].originalPic = originalList[index].path + } + } + rv?.commonAdapter()?.loadMore(picList) + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // 航班级联查询 + /////////////////////////////////////////////////////////////////////////// + + fun onFlightDateInputComplete() { + lastQueriedFlight = "" + queryFlightIfReady() + } + + fun onFlightNoInputComplete() { + queryFlightIfReady() + } + + private fun queryFlightIfReady() { + val bean = dataBean.value ?: return + val fdate = bean.fdate + val fno = bean.fno + if (fdate.isEmpty() || fno.isEmpty()) return + + val key = "$fdate-$fno" + if (key == lastQueriedFlight) return + lastQueriedFlight = key + + launchCollect({ + NetApply.api.getGjFlightBean( + mapOf( + "fdate" to fdate, + "fno" to fno, + "ieFlag" to "I", + ).toRequestBody() + ) + }) { + onSuccess = { + if (it.verifySuccess() && it.data != null) { + val flight = it.data!! + val b = dataBean.value ?: GjAccidentVisaEditBean() + b.dep = flight.fdep.noNull() + b.dest = flight.fdest.noNull() + dataBean.value = b + } else { + val b = dataBean.value ?: GjAccidentVisaEditBean() + b.dep = "" + b.dest = "" + dataBean.value = b + showToast(it.msg.noNull("获取航班信息失败")) + } + } + + onFailed = { _, _ -> + val b = dataBean.value ?: GjAccidentVisaEditBean() + b.dep = "" + b.dest = "" + dataBean.value = b + } + } + } + + /////////////////////////////////////////////////////////////////////////// + // 保存 + /////////////////////////////////////////////////////////////////////////// + + fun onSaveClick() { + val bean = dataBean.value ?: return + if (bean.fdate.verifyNullOrEmpty("请输入航班日期")) return + if (bean.fno.verifyNullOrEmpty("请输入航班号")) return + if (bean.wbNo.verifyNullOrEmpty("请输入运单号")) return + + (rv?.commonAdapter()?.items ?: emptyList()) + .asFlow() + .map { it as FileBean } + .filter { it.path.isNotEmpty() && it.url.isEmpty() } + .onEach { + val data = UploadUtil.upload(it.path).data + it.url = data?.newName ?: "" + it.originalPic = data?.zipFileName ?: "" + } + .flowOn(Dispatchers.IO) + .onStart { showLoading() } + .catch { + showToast(it.message.noNull("上传图片失败")) + dismissLoading() + } + .onCompletion { + launchLoadingCollect({ + val list = (rv?.commonAdapter()?.items as List) + .filter { it.path.isNotEmpty() } + bean.picNumber = list.size.toString() + bean.originalPic = list.joinToString(separator = ",") { MediaUtil.removeUrl(it.url) } + bean.pic = list.joinToString(separator = ",") { MediaUtil.removeUrl(it.originalPic) } + bean.idFlag = "1" + + if (pageType.value == DetailsPageType.Add) { + NetApply.api.saveGjAccidentVisa(bean.toRequestBody()) + } else { + NetApply.api.modifyGjAccidentVisa(bean.toRequestBody()) + } + }) { + onSuccess = { + showToast(it.msg.noNull("${pageType.value!!.title}成功")) + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + getTopActivity().finish() + } + } + } + .launchIn(viewModelScope) + } + + fun onCancelClick() { + getTopActivity().finish() + } + + /////////////////////////////////////////////////////////////////////////// + // 图片操作 + /////////////////////////////////////////////////////////////////////////// + + override fun onItemClick(position: Int, type: Int) { + val adapter = rv!!.commonAdapter()!! + val bean = adapter.getItem(position) as FileBean + when (type) { + R.id.rl -> { + bean.canDelete.set(!bean.canDelete.get()) + } + + R.id.iv_delete -> { + adapter.removeItem(position) + } + + else -> {} + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaViewModel.kt index 9d150a4..6dda7ab 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaViewModel.kt +++ b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpAccidentVisaViewModel.kt @@ -123,6 +123,10 @@ class IntImpAccidentVisaViewModel : BasePageViewModel() { ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL) } + fun addClick() { + com.lukouguoji.gjj.activity.IntImpAccidentVisaEditActivity.start(getTopActivity()) + } + fun searchClick() { refresh() } diff --git a/module_gjj/src/main/res/layout/activity_int_imp_accident_visa.xml b/module_gjj/src/main/res/layout/activity_int_imp_accident_visa.xml index 943af6d..d5a745f 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_accident_visa.xml +++ b/module_gjj/src/main/res/layout/activity_int_imp_accident_visa.xml @@ -102,6 +102,7 @@ android:layout_width="36dp" android:layout_height="36dp" android:layout_marginLeft="16dp" + android:onClick="@{()-> viewModel.addClick()}" android:padding="4dp" android:src="@drawable/img_add" /> diff --git a/module_gjj/src/main/res/layout/activity_int_imp_accident_visa_edit.xml b/module_gjj/src/main/res/layout/activity_int_imp_accident_visa_edit.xml new file mode 100644 index 0000000..b343cda --- /dev/null +++ b/module_gjj/src/main/res/layout/activity_int_imp_accident_visa_edit.xml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/item_int_imp_accident_visa.xml b/module_gjj/src/main/res/layout/item_int_imp_accident_visa.xml index b0d015e..80bc31c 100644 --- a/module_gjj/src/main/res/layout/item_int_imp_accident_visa.xml +++ b/module_gjj/src/main/res/layout/item_int_imp_accident_visa.xml @@ -12,283 +12,315 @@ type="Integer" /> - + + android:orientation="vertical"> - - + + - - - - + + android:background="@drawable/bg_item" + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="10dp"> - - + + + + + android:layout_marginLeft="10dp" + android:layout_weight="1" + android:orientation="vertical"> - + + android:gravity="center_vertical"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_marginTop="10dp" + android:gravity="center_vertical"> - + + - - + - + - + - + + - - + - + - + - + + - - + - + - + - + + - - + - + - + - + + + + + + + + + + + + + + + - + + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - +