feat: 国际进港新增事故签证功能页面

- 新建事故签证列表页(类型2:多选列表+批量删除)
- 搜索区支持航班日期/航班号级联查询始发站和目的站
- 对接 GjAccidentVisa/search 和 GjAccidentVisa/delete 接口
- 国际进港菜单添加"事故签证"入口

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 16:39:03 +08:00
parent 1476f1368a
commit 330b5bc28a
11 changed files with 812 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
package com.lukouguoji.gjj.activity
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import com.alibaba.android.arouter.facade.annotation.Route
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.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.router.ARouterConstants
/**
* 国际进港-事故签证
*/
@Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_ACCIDENT_VISA)
class IntImpAccidentVisaActivity :
BaseBindingActivity<ActivityIntImpAccidentVisaBinding, IntImpAccidentVisaViewModel>() {
override fun layoutId() = R.layout.activity_int_imp_accident_visa
override fun viewModelClass() = IntImpAccidentVisaViewModel::class.java
override fun initOnCreate(savedInstanceState: Bundle?) {
setBackArrow("国际事故签证")
binding.viewModel = viewModel
viewModel.isAllChecked.observe(this) { isAllChecked ->
binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f
}
viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
viewModel.refresh()
}
viewModel.refresh()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) {
viewModel.wbNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
viewModel.searchClick()
}
}
}

View File

@@ -0,0 +1,25 @@
package com.lukouguoji.gjj.holder
import android.view.View
import com.lukouguoji.gjj.databinding.ItemIntImpAccidentVisaBinding
import com.lukouguoji.module_base.base.BaseViewHolder
import com.lukouguoji.module_base.bean.IntImpAccidentVisaBean
/**
* 国际进港-事故签证 列表项ViewHolder
*/
class IntImpAccidentVisaViewHolder(view: View) :
BaseViewHolder<IntImpAccidentVisaBean, ItemIntImpAccidentVisaBinding>(view) {
override fun onBind(item: Any?, position: Int) {
val bean = getItemBean(item) ?: return
binding.bean = bean
binding.position = position
binding.executePendingBindings()
binding.ivIcon.setOnClickListener {
bean.checked.set(!bean.checked.get())
binding.executePendingBindings()
}
}
}

View File

@@ -0,0 +1,181 @@
package com.lukouguoji.gjj.viewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.gjj.R
import com.lukouguoji.gjj.holder.IntImpAccidentVisaViewHolder
import com.lukouguoji.module_base.base.BasePageViewModel
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.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.commonAdapter
import com.lukouguoji.module_base.ktx.formatDate
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.model.ScanModel
import dev.utils.app.info.KeyValue
import dev.utils.common.DateUtils
import kotlinx.coroutines.launch
/**
* 国际进港-事故签证 ViewModel
*/
class IntImpAccidentVisaViewModel : BasePageViewModel() {
// ========== 搜索条件 ==========
val flightDate = MutableLiveData<String>(DateUtils.getCurrentTime().formatDate())
val flightNo = MutableLiveData("")
val fdep = MutableLiveData("") // 始发站(下拉)
val fdepList = MutableLiveData<List<KeyValue>>(emptyList())
val fdest = MutableLiveData("") // 目的站(禁止编辑,由航班查询返回)
val wbNo = MutableLiveData("") // 运单号
// ========== 航班查询 ==========
private var fid: String = ""
private var lastQueriedFlight = ""
// ========== 统计信息 ==========
val totalCount = MutableLiveData("0")
// ========== 全选状态 ==========
val isAllChecked = MutableLiveData(false)
init {
isAllChecked.observeForever { checked ->
val list = pageModel.rv?.commonAdapter()?.items as? List<IntImpAccidentVisaBean>
?: return@observeForever
list.forEach { it.checked.set(checked) }
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
}
}
// ========== 适配器配置 ==========
val itemViewHolder = IntImpAccidentVisaViewHolder::class.java
val itemLayoutId = R.layout.item_int_imp_accident_visa
// ========== 航班级联查询 ==========
fun onFlightDateInputComplete() {
lastQueriedFlight = ""
queryFlightIfReady()
}
fun onFlightNoInputComplete() {
queryFlightIfReady()
}
private fun queryFlightIfReady() {
val fdate = flightDate.value
val fno = flightNo.value
if (fdate.isNullOrEmpty() || fno.isNullOrEmpty()) 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!!
fid = flight.fid.noNull()
fdest.value = flight.fdest.noNull()
val list = mutableListOf(
KeyValue(flight.fdep.noNull(), flight.fdep.noNull()),
)
if (!flight.jtz.isNullOrEmpty()) {
list.add(KeyValue(flight.jtz.noNull(), flight.jtz.noNull()))
}
fdepList.value = list
fdep.value = flight.fdep.noNull()
} else {
fid = ""
fdest.value = ""
fdepList.value = emptyList()
fdep.value = ""
showToast(it.msg.noNull("获取航班信息失败"))
}
}
onFailed = { _, _ ->
fid = ""
fdest.value = ""
fdepList.value = emptyList()
fdep.value = ""
}
}
}
fun scanWbNo() {
ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL)
}
fun searchClick() {
refresh()
}
fun checkAllClick() {
val list = pageModel.rv?.commonAdapter()?.items as? List<IntImpAccidentVisaBean> ?: return
val shouldCheckAll = !isAllChecked.value!!
list.forEach { it.checked.set(shouldCheckAll) }
isAllChecked.value = shouldCheckAll
pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
}
fun deleteClick() {
val list = pageModel.rv?.commonAdapter()?.items as? List<IntImpAccidentVisaBean> ?: return
val selected = list.filter { it.isSelected }
if (selected.isEmpty()) {
showToast("请选择要删除的数据")
return
}
launchLoadingCollect({ NetApply.api.deleteIntImpAccidentVisa(selected.toRequestBody()) }) {
onSuccess = {
showToast("删除成功")
viewModelScope.launch {
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
}
refresh()
}
}
}
override fun getData() {
val filterParams = mutableMapOf<String, Any?>(
"fdep" to fdep.value?.ifEmpty { null },
"fdest" to fdest.value?.ifEmpty { null },
"wbNo" to wbNo.value?.ifEmpty { null }
)
if (fid.isNotEmpty()) {
filterParams["fid"] = fid
} else {
filterParams["fdate"] = flightDate.value?.ifEmpty { null }
filterParams["fno"] = flightNo.value?.ifEmpty { null }
}
val listParams = (filterParams + mapOf(
"pageNum" to pageModel.page,
"pageSize" to pageModel.limit
)).toRequestBody()
launchLoadingCollect({ NetApply.api.getIntImpAccidentVisaList(listParams) }) {
onSuccess = { pageInfo ->
pageModel.handleListBean(pageInfo.toBaseListBean())
totalCount.value = (pageInfo.total ?: 0).toString()
}
}
}
}