diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/FlightBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/FlightBean.kt index edd2cc7..d0e75a3 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/FlightBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/FlightBean.kt @@ -234,7 +234,10 @@ class FlightBean : ICheck { return when (countryType) { "0" -> "国内" "1" -> "国际" - else -> "" + "2" -> "地区" + "3" -> "混合" + // 部分接口直接返回中文名,原样显示 + else -> countryType } } 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 1d4dd56..4d24163 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 @@ -1391,6 +1391,24 @@ interface Api { @POST("flt/listFlightDest") suspend fun listFlightDest(@Body data: RequestBody): BaseResultBean> + /** + * 航班管理-新增航班 + */ + @POST("flt/saveFlight") + suspend fun saveFlight(@Body data: RequestBody): BaseResultBean + + /** + * 航班管理-修改航班 + */ + @POST("flt/updateFlight") + suspend fun updateFlight(@Body data: RequestBody): BaseResultBean + + /** + * 航班管理-删除航班(请求体为航班对象数组) + */ + @POST("flt/delete") + suspend fun deleteFlightList(@Body data: RequestBody): BaseResultBean + /** * 新增或修航司屏蔽 */ diff --git a/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditActivity.kt b/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditActivity.kt new file mode 100644 index 0000000..63c56c0 --- /dev/null +++ b/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditActivity.kt @@ -0,0 +1,53 @@ +package com.lukouguoji.hangban.page.edit + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.hangban.R +import com.lukouguoji.hangban.databinding.ActivityHbFlightEditBinding +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.setUpperCaseAlphanumericFilter + +class HbFlightEditActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_hb_flight_edit + + override fun viewModelClass() = HbFlightEditViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + binding.viewModel = viewModel + + binding.flightNoInput.et.setUpperCaseAlphanumericFilter() + binding.fdepInput.et.setUpperCaseAlphanumericFilter() + binding.fdestInput.et.setUpperCaseAlphanumericFilter() + binding.registrationInput.et.setUpperCaseAlphanumericFilter() + + viewModel.initOnCreated(intent) + + // 动态设置标题(必须在 initOnCreated 之后,pageType 已从 Intent 解析) + val title = when (viewModel.pageType.value) { + DetailsPageType.Modify -> "编辑航班" + else -> "新增航班" + } + setBackArrow(title) + } + + companion object { + /** + * fid 为空表示新增,非空表示编辑 + */ + @JvmStatic + fun start(context: Context, fid: String = "") { + val pageType = + if (fid.isEmpty()) DetailsPageType.Add.name else DetailsPageType.Modify.name + context.startActivity( + Intent(context, HbFlightEditActivity::class.java) + .putExtra(Constant.Key.PAGE_TYPE, pageType) + .putExtra(Constant.Key.ID, fid) + ) + } + } +} diff --git a/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditViewModel.kt b/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditViewModel.kt new file mode 100644 index 0000000..7f51c9d --- /dev/null +++ b/module_hangban/src/main/java/com/lukouguoji/hangban/page/edit/HbFlightEditViewModel.kt @@ -0,0 +1,280 @@ +package com.lukouguoji.hangban.page.edit + +import android.content.Intent +import android.view.View +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.lukouguoji.module_base.base.BaseViewModel +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.ktx.formatDate +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.DictUtils +import dev.DevUtils +import dev.utils.app.info.KeyValue +import dev.utils.common.DateUtils +import kotlinx.coroutines.launch + +class HbFlightEditViewModel : BaseViewModel() { + + val pageType = MutableLiveData(DetailsPageType.Add) + + // 航班主键(编辑模式) + private var fid = "" + + /////////////////////////////////////////////////////////////////////////// + // 表单字段 + /////////////////////////////////////////////////////////////////////////// + + val flightDate = MutableLiveData("") + val flightNo = MutableLiveData("") + val aircraftCode = MutableLiveData("") + val fdep = MutableLiveData("") + val jtz = MutableLiveData("") + val fdest = MutableLiveData("") + val countryType = MutableLiveData("") + val serviceType = MutableLiveData("") + val status = MutableLiveData("") + val scheduledTackOff = MutableLiveData("") + val estimatedTakeOff = MutableLiveData("") + val actualTakeOff = MutableLiveData("") + val scheduledArrival = MutableLiveData("") + val estimatedArrival = MutableLiveData("") + val actualArrival = MutableLiveData("") + val standId = MutableLiveData("") + val registration = MutableLiveData("") + val prefix = MutableLiveData("") + val flightStatus = MutableLiveData("") + val cmFlag = MutableLiveData("") + val delayFreeText = MutableLiveData("") + + /////////////////////////////////////////////////////////////////////////// + // 下拉列表 + /////////////////////////////////////////////////////////////////////////// + + val countryTypeList = MutableLiveData>(emptyList()) + val serviceTypeList = MutableLiveData>(emptyList()) + val statusList = MutableLiveData>(emptyList()) + val flightStatusList = MutableLiveData>(emptyList()) + val cmFlagList = MutableLiveData>(emptyList()) + + /////////////////////////////////////////////////////////////////////////// + // 选项定义(服务端入库/过滤用 code,详情接口返回中文名,回填时需反查) + /////////////////////////////////////////////////////////////////////////// + + private val countryTypeOptions = listOf( + KeyValue("国内", "0"), + KeyValue("国际", "1"), + KeyValue("地区", "2"), + KeyValue("混合", "3"), + ) + + private val serviceTypeOptions = listOf( + KeyValue("客机", "0"), + KeyValue("货机", "1"), + KeyValue("卡车", "2"), + ) + + private val statusOptions = listOf( + KeyValue("出港", "0"), + KeyValue("进港", "1"), + ) + + private val flightStatusOptions = listOf( + KeyValue("正常", "0"), + KeyValue("登机", "1"), + KeyValue("登机结束", "2"), + KeyValue("起飞", "3"), + KeyValue("到达", "4"), + KeyValue("取消", "5"), + KeyValue("备降", "6"), + KeyValue("删除发布", "7"), + KeyValue("延误", "8"), + KeyValue("未知", "9"), + ) + + private val cmFlagOptions = listOf( + KeyValue("有货邮", "0"), + KeyValue("无货邮", "1"), + ) + + /////////////////////////////////////////////////////////////////////////// + // 方法区 + /////////////////////////////////////////////////////////////////////////// + + fun initOnCreated(intent: Intent) { + pageType.value = + if (intent.getStringExtra(Constant.Key.PAGE_TYPE) == DetailsPageType.Modify.name) + DetailsPageType.Modify else DetailsPageType.Add + fid = intent.getStringExtra(Constant.Key.ID) ?: "" + + if (pageType.value == DetailsPageType.Modify && fid.isNotEmpty()) { + loadDetails() + } else { + flightDate.value = DateUtils.getCurrentTime().formatDate() + loadDictLists() + } + } + + /** + * 编辑模式:加载航班详情 + */ + private fun loadDetails() { + launchLoadingCollect({ + NetApply.api.getFlightDetails(fid) + }) { + onSuccess = { + it.data?.let { bean -> + flightDate.value = bean.fdate + flightNo.value = bean.fno + aircraftCode.value = bean.aircraftCode + fdep.value = bean.fdep + jtz.value = bean.jtz + fdest.value = bean.fdest + countryType.value = toCode(countryTypeOptions, bean.countryType) + serviceType.value = toCode(serviceTypeOptions, bean.serviceType) + status.value = toCode(statusOptions, bean.status) + scheduledTackOff.value = bean.scheduledTackOff + estimatedTakeOff.value = bean.estimatedTakeOff + actualTakeOff.value = bean.actualTakeOff + scheduledArrival.value = bean.scheduledArrival + estimatedArrival.value = bean.estimatedArrival + actualArrival.value = bean.actualArrival + standId.value = bean.standId + registration.value = bean.registration + prefix.value = bean.prefix + flightStatus.value = toCode(flightStatusOptions, bean.flightStatus) + cmFlag.value = toCode(cmFlagOptions, bean.cmFlag) + delayFreeText.value = bean.delayFreeText + } + // 字典加载必须在编辑数据回填之后,保证 checkedValue 可用 + loadDictLists() + } + } + } + + /** + * 加载下拉列表(编辑模式传 checkedValue 置顶选中项) + */ + private fun loadDictLists() { + val isModify = pageType.value == DetailsPageType.Modify + + DictUtils.getCountryTypeList( + addAll = false, + checkedValue = if (isModify) countryType.value else null + ) { + countryTypeList.postValue(if (isModify) it else listOf(KeyValue("", "")) + it) + } + + serviceTypeList.value = + buildStaticList(serviceTypeOptions, if (isModify) serviceType.value else null) + + statusList.value = + buildStaticList(statusOptions, if (isModify) status.value else null) + + flightStatusList.value = + buildStaticList(flightStatusOptions, if (isModify) flightStatus.value else null) + + cmFlagList.value = + buildStaticList(cmFlagOptions, if (isModify) cmFlag.value else null) + } + + /** + * 值转 code:详情接口可能返回中文名(如“国际”“客机”),统一转为 code 用于回填与提交 + */ + private fun toCode(options: List, raw: String?): String { + if (raw.isNullOrEmpty()) return "" + return options.firstOrNull { it.value == raw }?.value + ?: options.firstOrNull { it.key == raw }?.value + ?: raw + } + + /** + * 静态下拉列表:新增模式首位置空项;编辑模式将选中项置顶 + */ + private fun buildStaticList(list: List, checkedValue: String?): List { + if (checkedValue.isNullOrEmpty()) { + return listOf(KeyValue("", "")) + list + } + return list.filter { it.value == checkedValue } + list.filter { it.value != checkedValue } + } + + /** + * 保存 点击 + */ + fun onSaveClick(view: View) { + if (flightDate.value.verifyNullOrEmpty("请选择航班日期")) return + if (flightNo.value.verifyNullOrEmpty("请输入航班号")) return + if (fdep.value.verifyNullOrEmpty("请输入始发港")) return + if (fdest.value.verifyNullOrEmpty("请输入目的港")) return + + val isModify = pageType.value == DetailsPageType.Modify + val dep = fdep.value?.trim().noNull() + val dest = fdest.value?.trim().noNull() + + val params = mutableMapOf( + "fdate" to flightDate.value, + "fno" to flightNo.value?.trim(), + "aircraftCode" to aircraftCode.value?.trim(), + "fdep" to dep, + "jtz" to jtz.value?.trim(), + "fdest" to dest, + "range" to "$dep-$dest", + "countryType" to countryType.value, + "countryName" to countryTypeList.value + ?.firstOrNull { it.value == countryType.value }?.key, + "serviceType" to serviceType.value, + "status" to status.value, + "scheduledTackOff" to scheduledTackOff.value, + "estimatedTakeOff" to estimatedTakeOff.value, + "actualTakeOff" to actualTakeOff.value, + "scheduledArrival" to scheduledArrival.value, + "estimatedArrival" to estimatedArrival.value, + "actualArrival" to actualArrival.value, + "standId" to standId.value?.trim(), + "registration" to registration.value?.trim(), + "prefix" to prefix.value?.trim(), + "flightStatus" to flightStatus.value, + "cmFlag" to cmFlag.value, + "delayFreeText" to delayFreeText.value?.trim(), + ) + if (isModify) { + params["fid"] = fid.toLongOrNull() ?: fid + } + + launchLoadingCollect({ + if (isModify) { + NetApply.api.updateFlight(params.toRequestBody()) + } else { + NetApply.api.saveFlight(params.toRequestBody()) + } + }) { + onSuccess = { + if (it.verifySuccess()) { + showToast(if (isModify) "修改成功" else "新增成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } + DevUtils.getTopActivity().finish() + } else { + showToast(it.msg.noNull("保存失败")) + } + } + } + } + + /** + * 取消 点击 + */ + fun onCancelClick(view: View) { + DevUtils.getTopActivity().finish() + } + +} diff --git a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListActivity.kt b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListActivity.kt index 30f3b22..530d7ef 100644 --- a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListActivity.kt +++ b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListActivity.kt @@ -5,6 +5,9 @@ import com.alibaba.android.arouter.facade.annotation.Route import com.lukouguoji.hangban.R import com.lukouguoji.hangban.databinding.ActivityHbQueryListBinding import com.lukouguoji.module_base.base.BaseBindingActivity +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.ktx.addOnItemClickListener import com.lukouguoji.module_base.ktx.getLifecycleOwner import com.lukouguoji.module_base.router.ARouterConstants @@ -26,6 +29,11 @@ class HbQueryListActivity : binding.rv.addOnItemClickListener(viewModel) + // 新增、编辑保存后刷新列表 + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + viewModel.refresh() } diff --git a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewHolder.kt b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewHolder.kt index 88b039e..b3ed813 100644 --- a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewHolder.kt +++ b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewHolder.kt @@ -28,6 +28,8 @@ class HbQueryListViewHolder(view: View) : } notifyItemClick(position, binding.ll) + notifyItemClick(position, binding.tvModify) + notifyItemClick(position, binding.tvDelete) } private fun setTextColorRecursive(view: View, color: Int) { diff --git a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewModel.kt b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewModel.kt index a7b0192..4a6bba2 100644 --- a/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewModel.kt +++ b/module_hangban/src/main/java/com/lukouguoji/hangban/page/query/list/HbQueryListViewModel.kt @@ -3,6 +3,7 @@ package com.lukouguoji.hangban.page.query.list import androidx.lifecycle.MutableLiveData import com.alibaba.android.arouter.launcher.ARouter import com.lukouguoji.hangban.R +import com.lukouguoji.hangban.page.edit.HbFlightEditActivity import com.lukouguoji.module_base.base.BasePageViewModel import com.lukouguoji.module_base.bean.FlightBean import com.lukouguoji.module_base.common.Constant @@ -10,9 +11,13 @@ import com.lukouguoji.module_base.http.net.NetApply import com.lukouguoji.module_base.ktx.commonAdapter import com.lukouguoji.module_base.ktx.formatDate 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.ConfirmDialogModel import com.lukouguoji.module_base.router.ARouterConstants import com.lukouguoji.module_base.util.DictUtils +import dev.DevUtils import dev.utils.app.info.KeyValue import dev.utils.common.DateUtils @@ -80,11 +85,55 @@ class HbQueryListViewModel : BasePageViewModel() { return "${d ?: ""}-${a ?: ""}" } + /** + * 新增 点击 + */ + fun addClick() { + HbFlightEditActivity.start(DevUtils.getTopActivity()) + } + override fun onItemClick(position: Int, type: Int) { val bean = pageModel.rv!!.commonAdapter()!!.getItem(position) as FlightBean - ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_FLIGHT_QUERY_DETAILS) - .withString(Constant.Key.ID, bean.fid) - .navigation() + when (type) { + R.id.tv_modify -> { + HbFlightEditActivity.start(DevUtils.getTopActivity(), bean.fid) + } + + R.id.tv_delete -> { + ConfirmDialogModel( + message = "是否确认删除航班【${bean.fno}】?", + ) { + onDelete(bean) + }.show(DevUtils.getTopActivity()) + } + + else -> { + ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_FLIGHT_QUERY_DETAILS) + .withString(Constant.Key.ID, bean.fid) + .navigation() + } + } + } + + /** + * 删除航班 + */ + private fun onDelete(bean: FlightBean) { + launchLoadingCollect({ + NetApply.api.deleteFlightList( + listOf(mapOf("fid" to bean.fid)).toRequestBody() + ) + }) { + onSuccess = { + if (it.verifySuccess()) { + // 服务端删除接口的 msg 为“修改成功”,此处固定提示删除成功 + showToast("删除成功") + refresh() + } else { + showToast(it.msg.noNull("删除失败")) + } + } + } } } diff --git a/module_hangban/src/main/release/AndroidManifest.xml b/module_hangban/src/main/release/AndroidManifest.xml index 268892c..ceccc24 100644 --- a/module_hangban/src/main/release/AndroidManifest.xml +++ b/module_hangban/src/main/release/AndroidManifest.xml @@ -18,6 +18,11 @@ android:configChanges="orientation|keyboardHidden" android:screenOrientation="userLandscape" android:exported="false" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_hangban/src/main/res/layout/activity_hb_query_list.xml b/module_hangban/src/main/res/layout/activity_hb_query_list.xml index 5bcb3fe..39913ef 100644 --- a/module_hangban/src/main/res/layout/activity_hb_query_list.xml +++ b/module_hangban/src/main/res/layout/activity_hb_query_list.xml @@ -104,6 +104,14 @@ android:padding="2dp" android:src="@drawable/img_search" /> + + + diff --git a/module_hangban/src/main/res/layout/item_hb_query_list.xml b/module_hangban/src/main/res/layout/item_hb_query_list.xml index b414f14..31791c3 100644 --- a/module_hangban/src/main/res/layout/item_hb_query_list.xml +++ b/module_hangban/src/main/res/layout/item_hb_query_list.xml @@ -10,16 +10,26 @@ type="com.lukouguoji.module_base.bean.FlightBean" /> - + + android:orientation="vertical"> + + + + - + + + + + + + + + + + + + +