diff --git a/.claude/skills/phone-adapt/references/api-doc.md b/.claude/skills/phone-adapt/references/api-doc.md index eb54f1b..2354a46 100644 --- a/.claude/skills/phone-adapt/references/api-doc.md +++ b/.claude/skills/phone-adapt/references/api-doc.md @@ -115,10 +115,22 @@ curl -s -X POST "$URL" -H "$AUTH" -H "Content-Type: application/json" \ `outState`(0 未出库/1 已出库)文档为 integer,前端传字符串靠 Jackson 隐式转换;`pageQueryTotal` 出参无已入库/已出库分项计数(缺口 #30,手机三格统计为客户端计数口径:dlvTime 非空=已出库、 inDate 非空=已入库);出参含 `agentName`(中文名)+ `agentCode`,agentName 可为 null -- `IntImpMove`(进港移库,2026-07-31 文档核对):**后端整个模块不存在**(api-doc 仅有国内进港 - `DomImpMove` 与国际出港 `IntExpMove`),权限串也没有对应 key(缺口 #31)。前端按 IntExpMove - 同名约定预接 `pageQuery`/`pageQueryTotal`/`move`/`uploadPic` 四接口 + 预定义权限串 - `AppIntImpMove`,后端交付后前端零改动生效 +- 「进港移库」(设计稿 11)**归属更正(2026-08-03 用户确认):属国内进港移库 `DomImpMove`**, + 不是国际进港移库——「后端模块缺失」的旧结论(原缺口 #31)作废,原按 IntExpMove 约定预接的 + IntImpMove 前端实现已整体删除。溯源:api-doc 53 模块中移库仅 `DomImpMove`(国内进港,8 接口)与 + `IntExpMove`(国际出港,4 接口),移库按转关业务前缀划分(DomImpMove 处理 `CI**`、IntExpMove + 处理 `IO**`),设计稿详情卡的「国际进港」红标签实为 `awbType` 值(如「国际进港(国内中转)」), + 不代表页面归属 +- `DomImpMove`(国内进港移库,2026-08-03 内网实测):手机 Tab 双端点——待移库 `search` / + 已移库 `searchMoved`(同一套入参 schema,分页参数名 **`page`/`limit`**);入参 A/B 实测: + **`wbNo`、`awbType`(值为 CICO/CIII/CIIO 转关码)过滤生效;`fdate`/`fno`/`spCode` 文档有定义但 + 被静默忽略**(缺口 #32);`searchMoved`/`detail` 出参 **`opId`/`opDate` 恒 null** 且无操作人姓名 + 字段(缺口 #33,移库人/移库时间显示"-"),`moveId` 形如 `CICO240617155016` 疑似内嵌移库时间戳但无 + 文档语义;`searchMoved` 出参**无 pic 三字段**(search 有)——拍照上传页统一先调 `GET detail` + 回填已有照片(#34 前端已规避);照片提交走 `modify` 最小体 + `{mawbId, remark, picNumber, pic, originalPic}`(平板移交编辑页同链路,removeEmptyOrNull); + 批量移库 `move` 入参 `{fid:"0", ids:[mawbId]}`;国内进港特码字典 + `DictUtils.getSpecialCodeList(flag=0, ieFlag="I")` 实测取数正常 - `IntExpCheckIn`(出港计重,2026-07-29 内网实测):`likeNo` **并非任意模糊**——按 8 位 `no` 匹配(11 位 wbNo 或部分号均 0 条),11 位全号必须走 `wbNo`;`checkIn`/`checkInList` 文档有定义但 `pageQuery`/`pageQueryTotal` **均静默忽略**(缺口 #12,待计重/计重中计数依赖); diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ea617b..8777990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,28 @@ ## [Unreleased] +### 变更 (Changed) +- 【进港移库归属更正 · 2026-08-03】设计稿 11「进港移库」经确认归属**国内进港移库 + (DomImpMove,后端 8 接口齐全,Pad 首页「国内进港→进港移库」既有页面)**,此前误判为 + 国际进港并按 IntExpMove 约定预接不存在的 IntImpMove 模块(原问题清单 #31 作废)。处置: + ① 删除 module_gjj 的 IntImpMove 全套前端实现(3 Activity + 3 ViewModel + Holder + 4 布局 + + `IntImpMoveBean` + Api 4 方法 + 国际 Tab 菜单项 + 权限串/路由/双 Manifest 注册); + ② 按 phone-adapt 流程重新适配到 `GnjMoveStashListActivity`(app 模块):主列表双形态 + (Pad 布局移 layout-sw600dp 零改动;手机版 = PhoneSearchBar + 待移库/已移库 Tab + (`DomImpMove/search`/`searchMoved` 双端点,`searchMoved` 无移库标识按端点打 `isMoved`)+ + 角标(双端点 limit=1 取 total,仅手机发起)+ 筛选弹层 4 项 + 全选/已选计数 + 批量移库 + (复用平板 `move` 链路)+ 卡片长按「拍照」浮层);新增手机专属页 + `GnjMoveStashDetailActivity`(Intent 传 bean 零请求,三卡片)与 + `GnjMoveStashPhotoActivity`(先调 `detail` 回填已有照片,提交走 `modify` 最小体 + 三字段规范,与平板移交编辑页同链路);`MoveStashBean` 增 `agentName`/`isMoved`/ + `actionMenuVisible`/`agentDisplay`/`orDash`;手机首页入口改挂**国内 Tab**(`GnViewModel` + 补通用 route 跳转,权限串 `GnjYiKu=AppDomImpMove` 与 Pad 一致,新路由 + `/app/GnjMoveStashListActivity`)。 + 2026-08-03 内网真实数据双端验证通过(登录→国内 Tab→列表/Tab/详情/筛选/全选/长按拍照全链路 + crash=0;平板回归原行为零变化);Proxyman A/B:`wbNo`/`awbType` 过滤生效, + `fdate`/`fno`/`spCode` 被后端静默忽略(新缺口 #32)、`searchMoved`/`detail` 出参 + `opId`/`opDate` 恒 null 且无姓名字段(#33)、`searchMoved` 无 pic 三字段(#34,前端已规避) + ### 新增 (Added) - 「进港查询」5.5 寸手机端适配(设计稿 10_进港查询,06 出港查询的进港镜像;详情页与运单追踪 复用 08/06 已适配页零新增):列表 `IntImpQueryActivity`(module_gjj,首页菜单实际跳转页; diff --git a/CLAUDE.md b/CLAUDE.md index fdefd92..c8fec9f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1150,15 +1150,21 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = `goods`);详情页与运单追踪复用 08/06 已适配页零新增;平板侧滑筛选面板代码已判空守卫。 ⚠️ 踩坑:代理人绑定不能写 `bean.agentName ?? bean.agentCode`——转换器把 JSON null 归一成 空串,`??` 只判 null 不判空串,须用 Bean 计算属性 `agentDisplay`(06 出港查询同步修正)) - - 「进港移库」`IntImpMoveActivity` + `IntImpMoveDetailActivity` + `IntImpMovePhotoActivity` - (module_gjj,**首个后端整模块缺失的设计稿页**:api-doc 确认无 IntImpMove 模块、权限串无 - 对应 key(缺口 #31)。前端按设计稿完整实现、按 IntExpMove 同名约定预接 - pageQuery/pageQueryTotal/move/uploadPic + 预定义权限串 `AppIntImpMove`,后端交付后零改动 - 生效;权限串下发前手机首页无入口,debug 直启验证。结构镜像 05 出港移库(Tab/批量移库/筛选 - 4 项),新增交互:卡片长按浮层「拍照」(复用 04 运抵的 actionMenuVisible 模式)→ 拍照上传页 - (图片网格复用 module_base `ImageSelectNewViewHolder`,提交走 pic/originalPic/picNumber - 三字段规范);详情页三卡片:基本信息/移库信息(仅已移库)/异常照片。手机专属新页无平板变体, - 布局只放 `res/layout/`;UI 与交互已用 Proxyman Map Local mock 全量验证) + - 「进港移库」`GnjMoveStashListActivity`(app 模块,**2026-08-03 归属更正后重做**:设计稿 11 + 实际归属**国内进港移库 DomImpMove**(后端 8 接口齐全、Pad 首页「国内进港→进港移库」既有页面), + 最初误判为国际进港并按 IntExpMove 约定预接了不存在的 IntImpMove 模块(原缺口 #31),该套 + module_gjj 前端实现已整体删除。现行实现:主列表双形态(Pad 布局移 layout-sw600dp 零改动), + 待移库/已移库 Tab 走 **`search`/`searchMoved` 双端点**(`searchMoved` 出参无移库标识,前端按 + 端点给 bean 打 `isMoved`),Tab 角标 = 两端点各调一次 limit=1 取分页 total(`initPhoneExtras` + 开关,仅手机发起);手机专属新页 `GnjMoveStashDetailActivity`(Intent 传 bean 零请求,三卡片: + 基本信息/移库信息(仅已移库)/异常照片)+ `GnjMoveStashPhotoActivity`(进入先调 `detail` 回填 + 已有照片——`searchMoved` 出参无 pic 三字段 #34,提交走 **`modify` 最小体** + `{mawbId,remark,picNumber,pic,originalPic}`,与平板移交编辑页同链路);批量移库复用平板 + `moveStashClick`(`move`:fid+ids)。手机首页入口在**国内 Tab**(`GnViewModel`,权限串 + `GnjYiKu=AppDomImpMove`,需补通用 route 跳转逻辑,图标从 module_gnj 复制); + GnjMoveStashListActivity 补 @Route `/app/GnjMoveStashListActivity`。 + 2026-08-03 内网真实数据双端验证通过;筛选 A/B:`wbNo`/`awbType` 生效, + `fdate`/`fno`/`spCode` 被后端静默忽略(#32)、`opId`/`opDate` 恒 null(#33)) - 「进港仓库」`IntImpStorageUseActivity`(module_gjj,07 出港仓库的进港镜像;**首页菜单实际跳转页, 旧版 `GjjWareHouseActivity` 路由已注释弃用**。差异:卡片/筛选用始发站(fdep 入参)替代目的站; 搜索框「运单号/航班号」分流(含字母→fno、其余→wbNo,抓包证实);筛选 5 项无入参(缺口 #25, @@ -1186,7 +1192,8 @@ override fun dispatchRestoreInstanceState(container: SparseArray) = - ✅ **设计稿 11 个入口(01~11)已于 2026-07-31 全部适配完成** - ⏳ **待办**: - `PhoneSearchBar` 接入 AutoQuery 联想(`AutoQueryManager` 目前只对接了 Pad 系组件) - - 进港移库待后端交付 IntImpMove 模块(四接口 + 权限串 AppIntImpMove,缺口 #31)后联调 + - 进港移库筛选三项(航班日期/航班号/特码)待后端实装 `fdate`/`fno`/`spCode` 入参(缺口 #32)、 + 移库人/移库时间待后端回填 `opId`/`opDate` 并补姓名出参(缺口 #33)后自动生效 - 出库交接 Tab 角标恒 0:`IntExpOutHandover/pageQueryTotal` 出参恒 0(后端缺陷,问题清单 #6), 后端修复后角标自动恢复(`handoverState` 过滤本身已于 2026-07-29 实机验证通过)生效 - 📋 **接口对接**:适配中发现的后端接口缺口统一记录在 `documents/后端接口对接问题清单.xlsx` diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml index 8717d8c..cfe6128 100644 --- a/app/src/debug/AndroidManifest.xml +++ b/app/src/debug/AndroidManifest.xml @@ -158,9 +158,21 @@ android:exported="true" tools:replace="android:exported" /> - + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2a9b492..c4bb10a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -375,6 +375,20 @@ android:name=".page.gnj.move.stash.list.GnjMoveStashListActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="unspecified" /> + + + + + + - - - - - - - - - () { + + override fun layoutId() = R.layout.activity_gnj_move_stash_detail + override fun viewModelClass() = GnjMoveStashDetailViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("运单详情") + binding.viewModel = viewModel + binding.activity = this + viewModel.initOnCreated(intent) + } + + /** 「异常照片」加号槽位 → 拍照上传页 */ + fun openPhoto() { + viewModel.dataBean.value?.let { + GnjMoveStashPhotoActivity.start(this, it.mawbId, it.wbNo) + } + } + + companion object { + @JvmStatic + fun start(context: Context, bean: MoveStashBean) { + context.startActivity( + Intent(context, GnjMoveStashDetailActivity::class.java) + .putExtra(Constant.Key.DATA, Gson().toJson(bean)) + ) + } + } +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt new file mode 100644 index 0000000..4cca875 --- /dev/null +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/detail/GnjMoveStashDetailViewModel.kt @@ -0,0 +1,25 @@ +package com.lukouguoji.aerologic.page.gnj.move.stash.detail + +import android.content.Intent +import androidx.lifecycle.MutableLiveData +import com.google.gson.Gson +import com.lukouguoji.module_base.base.BaseViewModel +import com.lukouguoji.module_base.bean.MoveStashBean +import com.lukouguoji.module_base.common.Constant + +/** + * 国内进港移库「运单详情」ViewModel(5.5 寸手持端专属页面) + * + * 列表项数据已包含详情页所需全部字段(含 isMoved 端点打标),直接由列表带入,不额外请求。 + */ +class GnjMoveStashDetailViewModel : BaseViewModel() { + + val dataBean = MutableLiveData(MoveStashBean()) + + fun initOnCreated(intent: Intent) { + val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() + if (json.isNotEmpty()) { + dataBean.value = Gson().fromJson(json, MoveStashBean::class.java) + } + } +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt index 86a24b3..3f1de6c 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListActivity.kt @@ -1,36 +1,104 @@ -package com.lukouguoji.aerologic.page.gnj.move.stash.list - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.lukouguoji.aerologic.R -import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.ktx.getLifecycleOwner - -class GnjMoveStashListActivity : - BaseBindingActivity() { - override fun layoutId() = R.layout.activity_gnj_move_stash_list - - override fun viewModelClass() = GnjMoveStashListViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("国内进港移库") - - binding.viewModel = viewModel - - viewModel.pageModel - .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) - - viewModel.refresh() - } - - companion object { - @JvmStatic - fun start(context: Context) { - val starter = Intent(context, GnjMoveStashListActivity::class.java) - context.startActivity(starter) - } - } - -} \ No newline at end of file +package com.lukouguoji.aerologic.page.gnj.move.stash.list + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.databinding.ObservableBoolean +import com.alibaba.android.arouter.facade.annotation.Route +import com.lukouguoji.aerologic.R +import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashListBinding +import com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoActivity +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.bean.MoveStashBean +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.getLifecycleOwner +import com.lukouguoji.module_base.router.ARouterConstants +import com.lukouguoji.module_base.util.DeviceUtil + +@Route(path = ARouterConstants.ACTIVITY_URL_GNJ_MOVE_STASH_LIST) +class GnjMoveStashListActivity : + BaseBindingActivity() { + override fun layoutId() = R.layout.activity_gnj_move_stash_list + + override fun viewModelClass() = GnjMoveStashListViewModel::class.java + + /** 筛选弹层显隐(仅手机 UI 状态,平板布局不绑定) */ + val filterPanelVisible = ObservableBoolean(false) + + override fun initOnCreate(savedInstanceState: Bundle?) { + // 设计稿手机端标题为「进港移库」,平板保持原标题 + setBackArrow(if (DeviceUtil.isPhone()) "进港移库" else "国内进港移库") + + binding.viewModel = viewModel + binding.activity = this + + viewModel.pageModel + .bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner()) + + if (DeviceUtil.isPhone()) { + // 手机专属:Tab 角标 + 特码字典等额外请求 + viewModel.initPhoneExtras() + + // 卡片勾选变化 → 更新全选状态与已选计数 + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { + viewModel.updateCheckAllStatus() + } + } + + // 拍照上传等子页面完成后刷新列表(平板无发射方,观察无副作用) + FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { + viewModel.refresh() + } + + viewModel.refresh() + } + + // ==================== 筛选弹层(仅手机) ==================== + + fun toggleFilterPanel() { + filterPanelVisible.set(!filterPanelVisible.get()) + } + + /** 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) */ + fun resetFilter() { + viewModel.flightDate.value = "" + viewModel.flightNo.value = "" + viewModel.spCode.value = "" + viewModel.businessType.value = "" + } + + fun confirmFilter() { + filterPanelVisible.set(false) + viewModel.refresh() + } + + // ==================== 卡片长按「拍照」浮层(仅手机) ==================== + + /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ + fun showCardActionPhone(bean: MoveStashBean): Boolean { + bean.actionMenuVisible.set(true) + return true + } + + /** 点浮层空白处关闭 */ + fun hideCardActionPhone(bean: MoveStashBean) { + bean.actionMenuVisible.set(false) + } + + /** 浮层「拍照」→ 拍照上传页 */ + fun openPhoto(bean: MoveStashBean) { + bean.actionMenuVisible.set(false) + GnjMoveStashPhotoActivity.start(this, bean.mawbId, bean.wbNo) + } + + companion object { + @JvmStatic + fun start(context: Context) { + val starter = Intent(context, GnjMoveStashListActivity::class.java) + context.startActivity(starter) + } + } + +} diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt index 0304c4d..f337635 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewHolder.kt @@ -3,34 +3,64 @@ package com.lukouguoji.aerologic.page.gnj.move.stash.list import android.view.View import android.widget.Toast import com.lukouguoji.aerologic.databinding.ItemGnjMoveStashListBinding +import com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity import com.lukouguoji.gnj.page.yiku.handover.GnjYiKuHandoverActivity import com.lukouguoji.module_base.base.BaseViewHolder import com.lukouguoji.module_base.bean.MoveStashBean +import com.lukouguoji.module_base.common.ConstantEvent +import com.lukouguoji.module_base.impl.FlowBus +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +/** + * 国内进港移库列表项 ViewHolder(双形态共用) + * + * 平板/手机布局差异较大,单侧独有的控件 id 在 Binding 基类中为 @Nullable, + * 全部走判空调用(平板:swipe_menu/btn_edit/ll;手机:ll_detail)。 + */ class GnjMoveStashListViewHolder(view: View) : BaseViewHolder(view) { override fun onBind(item: Any?, position: Int) { val bean = getItemBean(item)!! binding.bean = bean + binding.position = position + binding.activity = itemView.context as? GnjMoveStashListActivity + // 勾选框(双形态共有):切换选中;手机端另行广播刷新全选/已选计数 binding.ivIcon.setOnClickListener { bean.checked.set(!bean.checked.get()) + binding.executePendingBindings() + + GlobalScope.launch { + FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed") + } } + // ===== 平板独有交互 ===== + // 点击列表项进入移交详情 - binding.ll.setOnClickListener { + binding.ll?.setOnClickListener { GnjYiKuHandoverActivity.startForDetails(itemView.context, bean.mawbId) } // 侧滑菜单 - 编辑按钮 - binding.btnEdit.setOnClickListener { - binding.swipeMenu.quickClose() + binding.btnEdit?.setOnClickListener { + binding.swipeMenu?.quickClose() if (bean.pickFlag == "1") { Toast.makeText(itemView.context, "已出库,不可编辑", Toast.LENGTH_SHORT).show() return@setOnClickListener } GnjYiKuHandoverActivity.startForEdit(itemView.context, bean.mawbId) } + + // ===== 手机独有交互 ===== + + // 「查看详情」→ 手机版运单详情页 + binding.llDetail?.setOnClickListener { + GnjMoveStashDetailActivity.start(itemView.context, bean) + } + + binding.executePendingBindings() } } diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt index 9295d2c..a9b4b21 100644 --- a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/list/GnjMoveStashListViewModel.kt @@ -49,6 +49,41 @@ class GnjMoveStashListViewModel : BasePageViewModel() { val number = MutableLiveData("0") val weight = MutableLiveData("0") + // ========== 5.5 寸手持端专属字段(平板布局不绑定,默认值保证平板行为零变化) ========== + + /** 移库状态 Tab:"0" 待移库(DomImpMove/search)/ "1" 已移库(DomImpMove/searchMoved) */ + val moveState = MutableLiveData("0") + + /** 手机筛选弹层:航班日期 / 航班号 / 特码(默认空 → 不进请求) */ + val flightDate = MutableLiveData("") + val flightNo = MutableLiveData("") + val spCode = MutableLiveData("") + val spCodeList = MutableLiveData>(emptyList()) + + val moveStateTabs = MutableLiveData( + listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) + ) + + /** 状态 Tab 角标(与 [moveStateTabs] 等长,取两端点分页 total) */ + val moveStateCounts = MutableLiveData(listOf("", "")) + + /** 底部操作条「已选 N 项」 */ + val selectedCount = MutableLiveData("0") + + /** 全选状态(手机 PhoneBottomBar 勾选图标) */ + val isAllChecked = MutableLiveData(false) + + /** 手机专属的额外请求(Tab 角标、特码字典)开关,仅手机形态在 Activity 中开启 */ + private var phoneExtrasEnabled = false + + fun initPhoneExtras() { + phoneExtrasEnabled = true + // 特码字典:flag=0 国内、ieFlag=I 进港(是否生效待实测,见问题清单) + DictUtils.getSpecialCodeList(addAll = false, flag = 0, ieFlag = "I") { list -> + spCodeList.postValue(listOf(KeyValue("全部", "")) + list) + } + } + /////////////////////////////////////////////////////////////////////////// // 方法区 /////////////////////////////////////////////////////////////////////////// @@ -95,25 +130,73 @@ class GnjMoveStashListViewModel : BasePageViewModel() { } + /** 查询条件(分页参数除外),search / searchMoved / searchTotal 三处共用同一套入参 */ + private fun buildFilterParams(): Map = mapOf( + "awbType" to businessType.value!!.ifEmpty { null }, + "wbNo" to waybill.value!!.ifEmpty { null }, + "carrier" to carrier.value!!.ifEmpty { null }, + // 以下为手机筛选弹层字段,平板恒为空串 → 恒传 null,行为不变 + "fdate" to flightDate.value?.ifEmpty { null }, + "fno" to flightNo.value?.ifEmpty { null }, + "spCode" to spCode.value?.ifEmpty { null }, + ) + override fun getData() { - val body = mapOf( + val body = (buildFilterParams() + mapOf( "page" to pageModel.page, "limit" to pageModel.limit, - "awbType" to businessType.value!!.ifEmpty { null }, - "wbNo" to waybill.value!!.ifEmpty { null }, - "carrier" to carrier.value!!.ifEmpty { null }, - ).toRequestBody() + )).toRequestBody() + val moved = moveState.value == "1" launchLoadingCollect({ - NetApply.api.getGnjMoveStashList( - body - ) + // 平板 moveState 恒为 "0" → 恒走 search(原行为);已移库 Tab 走 searchMoved + if (moved) NetApply.api.getGnjMoveStashMovedList(body) + else NetApply.api.getGnjMoveStashList(body) }) { onSuccess = { - pageModel.handleListBean(it) + // searchMoved 出参无移库标识,按端点打标(卡片形态/详情移库信息卡依赖) + it.list?.forEach { bean -> bean.isMoved = moved } + pageModel.handleListBean(it) { updateCheckAllStatus() } count.value = it.total } } getCountData(body) + if (phoneExtrasEnabled) loadTabCounts() + } + + /** Tab 角标:search / searchMoved 各以 limit=1 查一次取分页 total(仅手机形态发起) */ + private fun loadTabCounts() { + val body = (buildFilterParams() + mapOf("page" to 1, "limit" to 1)).toRequestBody() + launchCollect({ NetApply.api.getGnjMoveStashList(body) }) { + onSuccess = { updateTabCount(0, it.total) } + } + launchCollect({ NetApply.api.getGnjMoveStashMovedList(body) }) { + onSuccess = { updateTabCount(1, it.total) } + } + } + + private fun updateTabCount(index: Int, total: Int?) { + val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") + if (index < current.size) { + current[index] = (total ?: 0).toString() + moveStateCounts.value = current + } + } + + // ========== 手机端全选 / 已选计数 ========== + + fun toggleSelectAll() { + val list = pageModel.rv?.commonAdapter()?.items + ?.filterIsInstance() ?: return + CheckUtil.handleAllCheck(list) + updateCheckAllStatus() + pageModel.rv?.commonAdapter()?.notifyDataSetChanged() + } + + fun updateCheckAllStatus() { + val list = pageModel.rv?.commonAdapter()?.items + ?.filterIsInstance() ?: return + isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } + selectedCount.value = list.count { it.checked.get() }.toString() } private fun getCountData(body: RequestBody) { diff --git a/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt new file mode 100644 index 0000000..971cb30 --- /dev/null +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoActivity.kt @@ -0,0 +1,45 @@ +package com.lukouguoji.aerologic.page.gnj.move.stash.photo + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.lukouguoji.aerologic.R +import com.lukouguoji.aerologic.databinding.ActivityGnjMoveStashPhotoBinding +import com.lukouguoji.module_base.base.BaseBindingActivity +import com.lukouguoji.module_base.common.Constant +import com.lukouguoji.module_base.ktx.addOnItemClickListener + +/** + * 国内进港移库「拍照上传」(5.5 寸手持端专属页面,无平板变体) + * + * 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。 + * 已有照片经 DomImpMove/detail 回填,提交走 DomImpMove/modify + * (mawbId + pic/originalPic/picNumber 三字段规范,与平板移交编辑页同一链路)。 + */ +class GnjMoveStashPhotoActivity : + BaseBindingActivity() { + + override fun layoutId() = R.layout.activity_gnj_move_stash_photo + override fun viewModelClass() = GnjMoveStashPhotoViewModel::class.java + + override fun initOnCreate(savedInstanceState: Bundle?) { + setBackArrow("拍照上传") + binding.viewModel = viewModel + + viewModel.rv = binding.rv + binding.rv.addOnItemClickListener(viewModel) + + viewModel.initOnCreated(intent) + } + + companion object { + @JvmStatic + fun start(context: Context, mawbId: String, wbNo: String) { + context.startActivity( + Intent(context, GnjMoveStashPhotoActivity::class.java) + .putExtra(Constant.Key.ID, mawbId) + .putExtra(Constant.Key.CODE, wbNo) + ) + } + } +} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt similarity index 61% rename from module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt rename to app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt index 98a4cdd..9ad8f53 100644 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMovePhotoViewModel.kt +++ b/app/src/main/java/com/lukouguoji/aerologic/page/gnj/move/stash/photo/GnjMoveStashPhotoViewModel.kt @@ -1,19 +1,20 @@ -package com.lukouguoji.gjj.viewModel +package com.lukouguoji.aerologic.page.gnj.move.stash.photo import android.content.Intent import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.RecyclerView -import com.google.gson.Gson -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.IntImpMoveBean +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.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.launchCollect import com.lukouguoji.module_base.ktx.launchLoadingCollect import com.lukouguoji.module_base.ktx.noNull import com.lukouguoji.module_base.ktx.showToast @@ -30,17 +31,24 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.launch /** - * 国际进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) + * 国内进港移库「拍照上传」ViewModel(5.5 寸手持端专属页面) * * 图片选择/预览/删除复用 module_base 的 ImageSelectNewViewHolder(末位加号槽位)。 - * 提交走三字段规范(pic 缩略图 / originalPic 原图 / picNumber 数量)。 - * ⚠️ 后端暂无 IntImpMove 模块,提交接口按约定预接(问题清单已登记)。 + * 已有照片经 DomImpMove/detail 回填;提交走 DomImpMove/modify 最小体 + * (mawbId/remark/picNumber/pic/originalPic),与平板移交编辑页同一链路。 */ -class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { +class GnjMoveStashPhotoViewModel : BaseViewModel(), IOnItemClickListener { - val dataBean = MutableLiveData(IntImpMoveBean()) + var mawbId = "" + + /** 运单号(副标题展示,由列表带入) */ + val wbNo = MutableLiveData("") + + /** detail 回填的完整 bean(提交时保留 remark 等原值) */ + private var detailBean = GnjYiKuBean() // 图片网格适配器配置(复用公共图片选择组件) val itemViewHolder = ImageSelectNewViewHolder::class.java @@ -49,29 +57,35 @@ class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { var rv: RecyclerView? = null fun initOnCreated(intent: Intent) { - val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() - if (json.isNotEmpty()) { - dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) - } + mawbId = intent.getStringExtra(Constant.Key.ID).orEmpty() + wbNo.value = intent.getStringExtra(Constant.Key.CODE).orEmpty() // 已有照片回填(pic 缩略图 + originalPic 原图),末位补加号槽位 - val bean = dataBean.value ?: IntImpMoveBean() - val picList = bean.pic.split(",").filter { it.isNotEmpty() } - val originalList = bean.originalPic.split(",").filter { it.isNotEmpty() } - val images = picList.mapIndexed { index, picUrl -> - FileBean( - path = MediaUtil.fillUrl(picUrl), - url = picUrl, - originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl }) - ) - } - rv?.post { - rv?.commonAdapter()?.refresh(images + FileBean()) + launchCollect({ NetApply.api.getGnjMoveStashDetail(mawbId) }) { + onSuccess = { + detailBean = it.data ?: GnjYiKuBean() + val picList = detailBean.pic.split(",").filter { p -> p.isNotEmpty() } + val originalList = detailBean.originalPic.split(",").filter { p -> p.isNotEmpty() } + val images = picList.mapIndexed { index, picUrl -> + FileBean( + path = MediaUtil.fillUrl(picUrl), + url = picUrl, + originalPic = MediaUtil.fillUrl(originalList.getOrElse(index) { picUrl }) + ) + } + rv?.post { + rv?.commonAdapter()?.refresh(images + FileBean()) + } + } + onFailed = { _, _ -> + // 详情取不到也允许直接新增照片 + rv?.post { rv?.commonAdapter()?.refresh(listOf(FileBean())) } + } } } /** - * 确认提交:先补传未上传的本地图片,再按三字段规范提交 + * 确认提交:先补传未上传的本地图片,再按三字段规范提交 modify */ fun submitClick() { (rv?.commonAdapter()?.items ?: emptyList()) @@ -95,15 +109,23 @@ class IntImpMovePhotoViewModel : BaseViewModel(), IOnItemClickListener { val list = (rv?.commonAdapter()?.items ?: emptyList()) .filterIsInstance() .filter { it.path.isNotEmpty() } - val bean = dataBean.value!! - bean.picNumber = list.size.toString() - bean.pic = list.joinToString(",") { MediaUtil.removeUrl(it.url) } - bean.originalPic = list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) } - NetApply.api.submitIntImpMovePic(bean.toRequestBody()) + // 最小体提交:只更新图片三字段(remark 保留 detail 原值),与平板移交编辑页一致 + val params = mapOf( + "mawbId" to mawbId, + "remark" to detailBean.remark, + "picNumber" to list.size.toString(), + "pic" to list.joinToString(",") { MediaUtil.removeUrl(it.url) }, + "originalPic" to list.joinToString(",") { MediaUtil.removeUrl(it.originalPic) }, + ).toRequestBody(removeEmptyOrNull = true) + + NetApply.api.modifyGnjMoveStash(params) }) { onSuccess = { showToast("提交成功") + viewModelScope.launch { + FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh") + } getTopActivity().finish() } onFailed = { _, msg -> diff --git a/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml b/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml new file mode 100644 index 0000000..7582268 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_gnj_move_stash_list.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml b/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml new file mode 100644 index 0000000..b8a56ac --- /dev/null +++ b/app/src/main/res/layout-sw600dp/item_gnj_move_stash_list.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml similarity index 93% rename from module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml rename to app/src/main/res/layout/activity_gnj_move_stash_detail.xml index 1f3d243..bd97b5a 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_move_detail.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_detail.xml @@ -1,14 +1,12 @@ @@ -19,11 +17,11 @@ + type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailViewModel" /> + type="com.lukouguoji.aerologic.page.gnj.move.stash.detail.GnjMoveStashDetailActivity" /> - + @@ -94,7 +92,7 @@ android:orientation="vertical" android:padding="16dp"> - + @@ -122,7 +120,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.businessName.empty ? viewModel.dataBean.businessType : viewModel.dataBean.businessName)}" + android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.cargoType)}" android:textColor="@color/phone_text_body" android:textSize="14sp" /> @@ -134,7 +132,7 @@ android:layout_height="wrap_content" android:layout_marginTop="12dp" android:layout_marginBottom="12dp" - android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goodsName)}" + android:text="@{viewModel.dataBean.orDash(viewModel.dataBean.goods)}" android:textColor="@color/phone_text_strong" android:textSize="22sp" android:textStyle="bold" /> @@ -150,7 +148,7 @@ android:layout_height="wrap_content" android:layout_weight="1" title='@{"件数"}' - value="@{String.valueOf(viewModel.dataBean.pc)}" /> + value="@{viewModel.dataBean.orDash(viewModel.dataBean.pc)}" /> + value='@{viewModel.dataBean.orDash(viewModel.dataBean.weight) + " kg"}' /> @@ -182,7 +180,7 @@ android:layout_marginStart="32dp" android:layout_weight="1" title='@{"代理"}' - value="@{viewModel.dataBean.agentName.empty ? viewModel.dataBean.agentCode : viewModel.dataBean.agentName}" /> + value="@{viewModel.dataBean.agentDisplay}" /> @@ -254,7 +252,7 @@ android:layout_marginStart="32dp" android:layout_weight="1" title='@{"移库时间"}' - value="@{viewModel.dataBean.opdate}" /> + value="@{viewModel.dataBean.opDate}" /> diff --git a/app/src/main/res/layout/activity_gnj_move_stash_list.xml b/app/src/main/res/layout/activity_gnj_move_stash_list.xml index 1e068ef..9b9a057 100644 --- a/app/src/main/res/layout/activity_gnj_move_stash_list.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_list.xml @@ -1,148 +1,166 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml b/app/src/main/res/layout/activity_gnj_move_stash_photo.xml similarity index 93% rename from module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml rename to app/src/main/res/layout/activity_gnj_move_stash_photo.xml index 2b6a422..67215c8 100644 --- a/module_gjj/src/main/res/layout/activity_int_imp_move_photo.xml +++ b/app/src/main/res/layout/activity_gnj_move_stash_photo.xml @@ -1,12 +1,12 @@ + type="com.lukouguoji.aerologic.page.gnj.move.stash.photo.GnjMoveStashPhotoViewModel" /> diff --git a/app/src/main/res/layout/item_gnj_move_stash_list.xml b/app/src/main/res/layout/item_gnj_move_stash_list.xml index 907131a..6b2f863 100644 --- a/app/src/main/res/layout/item_gnj_move_stash_list.xml +++ b/app/src/main/res/layout/item_gnj_move_stash_list.xml @@ -1,287 +1,227 @@ + + + + + + + - - + android:layout_marginHorizontal="12dp" + android:layout_marginTop="12dp"> - - + android:layout_height="wrap_content" + android:background="@drawable/bg_phone_card" + android:onLongClick="@{()-> activity.showCardActionPhone(bean)}" + android:orientation="vertical" + android:padding="16dp"> - - + + android:gravity="center_vertical" + android:orientation="horizontal"> + + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_phone_check_round_unchecked" + android:visibility="@{bean.isMoved ? View.GONE : View.VISIBLE}" + loadImage="@{bean.checked.get() ? @drawable/ic_phone_check_round_checked : @drawable/ic_phone_check_round_unchecked}" /> - + + android:text="@{bean.wbNo}" + android:textColor="@{bean.isMoved ? @color/phone_text_title : @color/phone_primary}" + android:textSize="15sp" + android:textStyle="bold" /> - + + - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginStart="4dp" + android:text="已移库" + android:textColor="@color/phone_text_title" + android:textSize="13sp" /> - - + - - - - + - + + + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="4dp" + android:layout_weight="1" + android:text='@{"航班信息:" + bean.orDash(bean.flight)}' + android:textColor="@color/phone_text_body" + android:textSize="13sp" + tools:text="航班信息:20260709/MU2311" /> - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documents/后端接口对接问题清单.xlsx b/documents/后端接口对接问题清单.xlsx index c6cab51..fd2b823 100644 Binary files a/documents/后端接口对接问题清单.xlsx and b/documents/后端接口对接问题清单.xlsx differ diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt deleted file mode 100644 index e800406..0000000 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/IntImpMoveBean.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.lukouguoji.module_base.bean - -import androidx.databinding.ObservableBoolean -import com.lukouguoji.module_base.interfaces.ICheck -import java.io.Serializable - -/** - * 国际进港移库 Bean(5.5 寸手持端专属页面) - * - * ⚠️ 后端目前**没有**「国际进港移库」模块(api-doc 仅有国内进港 DomImpMove 与国际出港 IntExpMove, - * 2026-07-31 核对),字段按 IntExpMove 出参约定 + 设计稿展示需求镜像定义, - * 已登记《后端接口对接问题清单》。后端按同名约定交付后前端自动生效。 - */ -data class IntImpMoveBean( - var no: String = "", // 运单号主体 - var prefix: String = "", // 运单前缀 - var wbNo: String = "", // 运单号 - var pc: Long = 0, // 件数 - var weight: Double = 0.0, // 重量 - - var fdate: String = "", // 航班日期 - var fno: String = "", // 航班号 - var flight: String = "", // 航班信息(日期/航班号 组合串) - var range: String = "", // 出运路径(如 HFE-NKG-LAX) - - var by1: String = "", // 承运人 - var awbType: String = "", // 运单类型编码 - var awbTypeName: String = "", // 运单类型名称 - var businessType: String = "", // 业务类型编码 - var businessName: String = "", // 业务类型名称 - var moveState: Int = 0, // 移库状态(0-待移库,1-已移库) - var goods: String = "", // 品名(英文) - var goodsCn: String = "", // 品名(中文) - var agentName: String = "", // 代理人 - var agentCode: String = "", // 代理代码 - var spCode: String = "", // 特码 - - var maWbId: Long = 0, // 主单主键ID - var opId: String = "", // 移库人 - var opdate: String = "", // 移库时间 - var remark: String = "", // 备注 - - // 异常照片(拍照上传,三字段规范:pic 缩略图 / originalPic 原图 / picNumber 数量) - var pic: String = "", - var originalPic: String = "", - var picNumber: String = "", - - // UI扩展字段 - 使用ObservableBoolean实现自动UI更新 - val checked: ObservableBoolean = ObservableBoolean(false), - // 卡片长按操作浮层显隐(仅 UI 状态) - val actionMenuVisible: ObservableBoolean = ObservableBoolean(false) -) : Serializable, ICheck { - - override fun getCheckObservable(): ObservableBoolean = checked - - var isSelected: Boolean - get() = checked.get() - set(value) = checked.set(value) - - // ========== 5.5 寸手持端展示辅助字段(仅用于手机版布局,不参与序列化) ========== - - /** 是否已移库(moveState:0-待移库,1-已移库) */ - val isMoved: Boolean - get() = moveState == 1 - - /** 品名:优先中文,为空回退英文 */ - val goodsName: String - get() = goodsCn.ifEmpty { goods } - - /** 航班信息展示:优先组合串,其次 日期/航班号 拼接 */ - val flightInfo: String - get() = flight.ifEmpty { - if (fdate.isEmpty() && fno.isEmpty()) "" else "$fdate/$fno" - } - - /** 详情页字段统一空值占位 */ - fun orDash(value: String?): String = if (value.isNullOrEmpty()) "-" else value -} diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt index 8c151b9..34bdc63 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/MoveStashBean.kt @@ -6,6 +6,7 @@ import com.lukouguoji.module_base.interfaces.ICheck class MoveStashBean : ICheck { var activeId: String = "" // null var agentCode: String = "" // HFEXB + var agentName: String = "" // 代理人名称(search 出参有定义) var awbType: String = "" // 国际进港(国内中转) var businessType: String = "" // null var by1: String = "" // null @@ -49,4 +50,19 @@ class MoveStashBean : ICheck { override fun getCheckObservable(): ObservableBoolean { return checked } + + // ========== 5.5 寸手持端展示辅助字段(仅前端使用,不参与提交) ========== + + /** 是否已移库:由列表加载端点决定(search=待移库 / searchMoved=已移库),载入时打标 */ + var isMoved: Boolean = false + + /** 卡片长按「拍照」操作浮层显隐(仅 UI 状态) */ + val actionMenuVisible = ObservableBoolean(false) + + /** 代理显示:网络层会把 null 归一成空串,须 isNullOrEmpty 双兜底(沿用进港/出港查询口径) */ + val agentDisplay: String + get() = if (agentName.isNotEmpty()) agentName else agentCode + + /** 详情页/卡片字段统一空值占位 */ + fun orDash(value: String?): String = if (value.isNullOrEmpty()) "-" else value } \ No newline at end of file diff --git a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt index 9e23ac2..d343bce 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt @@ -274,7 +274,6 @@ interface Constant { const val IntImpPickUpDLV = "AppIntImpPickUpDLV" //提取出库 // 进港移库:后端暂无该模块与权限串(2026-07-31 api-doc 核对),按 AppIntImp* 命名约定预定义, // 权限串下发前手机首页菜单不会显示该入口(已登记后端接口对接问题清单) - const val IntImpMove = "AppIntImpMove" //进港移库 const val IntImpAccidentVisa = "AppIntImpAccidentVisa" //事故签证 const val GjjManifestListActivity = "AppIntExpManifest" //舱单 const val GjjTallyListActivity = "AppIntExpTally" //理货 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 ba750f0..00d6ad5 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 @@ -55,7 +55,6 @@ 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 -import com.lukouguoji.module_base.bean.IntImpMoveBean import com.lukouguoji.module_base.bean.IntImpQueryBean import com.lukouguoji.module_base.bean.GjjManifest import com.lukouguoji.module_base.bean.GjjManifestBean @@ -883,38 +882,6 @@ interface Api { @POST("IntExpMove/move") suspend fun submitIntExpMove(@Body data: RequestBody): BaseResultBean - /** - * 国际进港移库-分页查询 - * 接口路径: /IntImpMove/pageQuery - * ⚠️ 后端暂无该模块(2026-07-31 api-doc 核对),按 IntExpMove 命名约定预接,已登记问题清单 - */ - @POST("IntImpMove/pageQuery") - suspend fun getIntImpMoveList(@Body data: RequestBody): BaseListBean - - /** - * 国际进港移库-分页合计 - * 接口路径: /IntImpMove/pageQueryTotal - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/pageQueryTotal") - suspend fun getIntImpMoveTotal(@Body data: RequestBody): BaseResultBean - - /** - * 国际进港移库-批量移库 - * 接口路径: /IntImpMove/move - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/move") - suspend fun submitIntImpMove(@Body data: RequestBody): BaseResultBean - - /** - * 国际进港移库-异常照片上传(pic/originalPic/picNumber 三字段规范) - * 接口路径: /IntImpMove/uploadPic - * ⚠️ 后端暂无该模块,同上 - */ - @POST("IntImpMove/uploadPic") - suspend fun submitIntImpMovePic(@Body data: RequestBody): BaseResultBean - /** * 国际出港库位操作-清仓 * 接口路径: /IntExpStorageUse/updateClear @@ -1799,6 +1766,12 @@ interface Api { @POST("DomImpMove/search") suspend fun getGnjMoveStashList(@Body data: RequestBody): BaseListBean + /** + * 获取-国内进港移库-已移库列表(移库完成分页搜索,5.5 寸手机端「已移库」Tab) + */ + @POST("DomImpMove/searchMoved") + suspend fun getGnjMoveStashMovedList(@Body data: RequestBody): BaseListBean + /** * 获取-国内进港移库-列表--运单列表 */ 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 1a87ea1..8dd2500 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 @@ -104,6 +104,7 @@ object ARouterConstants { // 国内进港移库(新版本) const val ACTIVITY_URL_GNJ_YIKU_LIST = "/gnj/GnjYiKuListActivity" //国内进港 移库列表 + const val ACTIVITY_URL_GNJ_MOVE_STASH_LIST = "/app/GnjMoveStashListActivity" //国内进港 移库(首页菜单实际跳转页,双形态) const val ACTIVITY_URL_GNJ_YIKU_DETAILS = "/gnj/GnjYiKuDetailsActivity" //国内进港 移库详情 const val ACTIVITY_URL_GNJ_YIKU_EDIT = "/gnj/GnjYiKuEditActivity" //国内进港 移库编辑 const val ACTIVITY_URL_GNJ_YIKU_HANDOVER = "/gnj/GnjYiKuHandoverActivity" //国内进港 移交编辑/详情 @@ -182,7 +183,6 @@ object ARouterConstants { const val ACTIVITY_URL_INT_IMP_LOADING_LIST = "/gjj/IntImpLoadingListActivity" //国际进港 装机单(分拣理货) const val ACTIVITY_URL_INT_IMP_TALLY = "/gjj/IntImpTallyActivity" //国际进港 理货报告 const val ACTIVITY_URL_INT_IMP_PICK_UP_DLV = "/gjj/IntImpPickUpDLVActivity" //国际进港 提取出库 - const val ACTIVITY_URL_INT_IMP_MOVE = "/gjj/IntImpMoveActivity" //国际进港 进港移库(5.5寸手机端专属页) const val ACTIVITY_URL_INT_IMP_ACCIDENT_VISA = "/gjj/IntImpAccidentVisaActivity" //国际进港 事故签证 ///////////////// 航班查询模块 diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt deleted file mode 100644 index 6642ad0..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveActivity.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.databinding.ObservableBoolean -import com.alibaba.android.arouter.facade.annotation.Route -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMoveBinding -import com.lukouguoji.gjj.viewModel.IntImpMoveViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -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.ktx.addOnItemClickListener -import com.lukouguoji.module_base.ktx.showToast -import com.lukouguoji.module_base.model.ConfirmDialogModel -import com.lukouguoji.module_base.model.ScanModel -import com.lukouguoji.module_base.router.ARouterConstants - -/** - * 国际进港-进港移库(5.5 寸手持端专属页面,无平板版本) - * - * 结构镜像 IntExpMoveActivity(国际出港移库),另有卡片长按「拍照」浮层(设计稿新增交互)。 - * ⚠️ 后端目前没有 IntImpMove 模块,接口按同名约定预接(问题清单已登记)。 - */ -@Route(path = ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE) -class IntImpMoveActivity : BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move - - override fun viewModelClass() = IntImpMoveViewModel::class.java - - /** 筛选弹层显隐(仅 UI 状态,不涉及业务逻辑) */ - val filterPanelVisible = ObservableBoolean(false) - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("进港移库") - binding.viewModel = viewModel - binding.activity = this - - viewModel.initDictLists() - - viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this) - binding.rv.addOnItemClickListener(viewModel) - - // 监听item选择变化事件,更新全选状态 - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).observe(this) { - viewModel.onItemCheckChanged() - } - - // 监听刷新事件 - FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) { - viewModel.refresh() - } - - viewModel.refresh() - } - - /** - * 扫码运单号 - */ - fun scanWaybill() { - ScanModel.startScan(this, Constant.RequestCode.WAYBILL) - } - - // ==================== 筛选弹层 ==================== - - fun toggleFilterPanel() { - filterPanelVisible.set(!filterPanelVisible.get()) - } - - /** - * 筛选:重置(只清空弹层内条件,不影响 Tab 与顶部搜索框) - */ - fun resetFilter() { - viewModel.flightDate.value = "" - viewModel.flightNo.value = "" - viewModel.spCode.value = "" - viewModel.awbType.value = "" - } - - fun confirmFilter() { - filterPanelVisible.set(false) - viewModel.searchClick() - } - - // ==================== 卡片长按「拍照」浮层 ==================== - - /** 卡片长按:展开操作浮层(View.OnLongClickListener 要求返回 Boolean) */ - fun showCardActionPhone(bean: IntImpMoveBean): Boolean { - bean.actionMenuVisible.set(true) - return true - } - - /** 点浮层空白处关闭 */ - fun hideCardActionPhone(bean: IntImpMoveBean) { - bean.actionMenuVisible.set(false) - } - - /** 浮层「拍照」→ 拍照上传页 */ - fun openPhoto(bean: IntImpMoveBean) { - bean.actionMenuVisible.set(false) - IntImpMovePhotoActivity.start(this, bean) - } - - /** - * 显示移库确认对话框(底部操作条 setOnActionClick 调用) - */ - fun showMoveConfirmDialog() { - val selectedItems = viewModel.getSelectedItems() - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") - return - } - - ConfirmDialogModel( - message = "确定要移库选中的 ${selectedItems.size} 条运单吗?", - title = "移库确认" - ) { - viewModel.submitMove() - }.show() - } - - /** - * 扫码回调 - */ - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (requestCode == Constant.RequestCode.WAYBILL && resultCode == Activity.RESULT_OK) { - val code = data?.getStringExtra(Constant.Result.CODED_CONTENT) - viewModel.waybillNo.value = code - viewModel.searchClick() - } - } - - companion object { - @JvmStatic - fun start(context: Context) { - context.startActivity(Intent(context, IntImpMoveActivity::class.java)) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt deleted file mode 100644 index 183ac90..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMoveDetailActivity.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.google.gson.Gson -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMoveDetailBinding -import com.lukouguoji.gjj.viewModel.IntImpMoveDetailViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant - -/** - * 国际进港移库「运单详情」(5.5 寸手持端专属页面) - * - * 由列表卡片的「查看详情」进入;「异常照片」卡片的加号槽位跳拍照上传页。 - */ -class IntImpMoveDetailActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move_detail - override fun viewModelClass() = IntImpMoveDetailViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("运单详情") - binding.viewModel = viewModel - binding.activity = this - viewModel.initOnCreated(intent) - } - - /** 「异常照片」加号槽位 → 拍照上传页 */ - fun openPhoto() { - viewModel.dataBean.value?.let { IntImpMovePhotoActivity.start(this, it) } - } - - companion object { - @JvmStatic - fun start(context: Context, bean: IntImpMoveBean) { - context.startActivity( - Intent(context, IntImpMoveDetailActivity::class.java) - .putExtra(Constant.Key.DATA, Gson().toJson(bean)) - ) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt deleted file mode 100644 index 40aba03..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/activity/IntImpMovePhotoActivity.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.lukouguoji.gjj.activity - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import com.google.gson.Gson -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.databinding.ActivityIntImpMovePhotoBinding -import com.lukouguoji.gjj.viewModel.IntImpMovePhotoViewModel -import com.lukouguoji.module_base.base.BaseBindingActivity -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant -import com.lukouguoji.module_base.ktx.addOnItemClickListener - -/** - * 国际进港移库「拍照上传」(5.5 寸手持端专属页面) - * - * 由列表卡片长按浮层「拍照」或运单详情「异常照片」加号槽位进入。 - */ -class IntImpMovePhotoActivity : - BaseBindingActivity() { - - override fun layoutId() = R.layout.activity_int_imp_move_photo - override fun viewModelClass() = IntImpMovePhotoViewModel::class.java - - override fun initOnCreate(savedInstanceState: Bundle?) { - setBackArrow("拍照上传") - binding.viewModel = viewModel - - viewModel.rv = binding.rv - binding.rv.addOnItemClickListener(viewModel) - - viewModel.initOnCreated(intent) - } - - companion object { - @JvmStatic - fun start(context: Context, bean: IntImpMoveBean) { - context.startActivity( - Intent(context, IntImpMovePhotoActivity::class.java) - .putExtra(Constant.Key.DATA, Gson().toJson(bean)) - ) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt deleted file mode 100644 index 20aa602..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/holder/IntImpMoveViewHolder.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.lukouguoji.gjj.holder - -import android.view.View -import com.lukouguoji.gjj.activity.IntImpMoveActivity -import com.lukouguoji.gjj.activity.IntImpMoveDetailActivity -import com.lukouguoji.gjj.databinding.ItemIntImpMoveBinding -import com.lukouguoji.module_base.base.BaseViewHolder -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.ConstantEvent -import com.lukouguoji.module_base.impl.FlowBus -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch - -/** - * 国际进港移库列表项 ViewHolder(5.5 寸手持端专属页面) - * - * 卡片交互: - * · 勾选框点击 → 切换选中并通知 Activity 更新全选/已选计数 - * · 「查看详情」→ 运单详情页 - * · 卡片长按 → 「拍照」操作浮层(XML 绑定 activity 回调) - */ -class IntImpMoveViewHolder(view: View) : - BaseViewHolder(view) { - - override fun onBind(item: Any?, position: Int) { - val bean = getItemBean(item) ?: return - binding.bean = bean - binding.position = position - binding.activity = itemView.context as? IntImpMoveActivity - - // 「查看详情」→ 运单详情页 - binding.llDetail.setOnClickListener { - IntImpMoveDetailActivity.start(itemView.context, bean) - } - - // 勾选框点击 - 切换选择状态 - binding.ivIcon.setOnClickListener { - bean.checked.set(!bean.checked.get()) - binding.executePendingBindings() - - GlobalScope.launch { - FlowBus.with(ConstantEvent.EVENT_CHECK_CHANGED).emit("check_changed") - } - } - - binding.executePendingBindings() - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt deleted file mode 100644 index 9154f69..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveDetailViewModel.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.lukouguoji.gjj.viewModel - -import android.content.Intent -import androidx.lifecycle.MutableLiveData -import com.google.gson.Gson -import com.lukouguoji.module_base.base.BaseViewModel -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.common.Constant - -/** - * 国际进港移库「运单详情」ViewModel(5.5 寸手持端专属页面) - * - * 列表项数据已包含详情页所需全部字段,故直接由列表带入,不额外请求接口 - * (后端暂无 IntImpMove 模块,也没有 detail 接口可查,问题清单已登记)。 - */ -class IntImpMoveDetailViewModel : BaseViewModel() { - - val dataBean = MutableLiveData(IntImpMoveBean()) - - fun initOnCreated(intent: Intent) { - val json = intent.getStringExtra(Constant.Key.DATA).orEmpty() - if (json.isNotEmpty()) { - dataBean.value = Gson().fromJson(json, IntImpMoveBean::class.java) - } - } -} diff --git a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt b/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt deleted file mode 100644 index e9bb2de..0000000 --- a/module_gjj/src/main/java/com/lukouguoji/gjj/viewModel/IntImpMoveViewModel.kt +++ /dev/null @@ -1,187 +0,0 @@ -package com.lukouguoji.gjj.viewModel - -import androidx.lifecycle.MutableLiveData -import com.lukouguoji.gjj.R -import com.lukouguoji.gjj.holder.IntImpMoveViewHolder -import com.lukouguoji.module_base.base.BasePageViewModel -import com.lukouguoji.module_base.bean.IntImpMoveBean -import com.lukouguoji.module_base.http.net.NetApply -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.util.CheckUtil -import com.lukouguoji.module_base.util.DictUtils -import dev.utils.app.info.KeyValue - -/** - * 国际进港移库 ViewModel(5.5 寸手持端专属页面,无平板版本) - * - * 结构镜像 IntExpMoveViewModel(国际出港移库)。 - * ⚠️ 后端目前没有 IntImpMove 模块(2026-07-31 api-doc 核对),接口按同名约定预接, - * 实机会请求失败(问题清单已登记),后端交付后自动生效。 - */ -class IntImpMoveViewModel : BasePageViewModel(), IOnItemClickListener { - - // ========== 搜索字段(设计稿筛选弹层:航班日期 / 航班号 / 特码 / 运单类型) ========== - val flightDate = MutableLiveData("") // 航班日期 - val flightNo = MutableLiveData("") // 航班号 - val spCode = MutableLiveData("") // 特码 - val awbType = MutableLiveData("") // 运单类型 - val moveState = MutableLiveData("0") // 移库状态(默认「待移库」Tab) - val waybillNo = MutableLiveData("") // 运单号 - - // ========== 下拉数据 ========== - val spCodeList = MutableLiveData>(emptyList()) - val awbTypeList = MutableLiveData>(emptyList()) - - /** 状态 Tab 配置(设计稿只有两个 Tab,无「全部」) */ - val moveStateTabs = MutableLiveData( - listOf(KeyValue("待移库", "0"), KeyValue("已移库", "1")) - ) - - /** 状态 Tab 角标(与 [moveStateTabs] 等长) */ - val moveStateCounts = MutableLiveData(listOf("", "")) - - /** 已选数量(底部操作条「已选 N 项」) */ - val selectedCount = MutableLiveData("0") - - // ========== 全选状态 ========== - val isAllChecked = MutableLiveData(false) - - // ========== 适配器配置 ========== - val itemViewHolder = IntImpMoveViewHolder::class.java - val itemLayoutId = R.layout.item_int_imp_move - - /** - * 初始化下拉字典(特码 + 运单类型,type=II 国际进港) - */ - fun initDictLists() { - // flag=1 国际;ieFlag 必须留空——传值后端返回空数组(与既有国际页面口径一致) - DictUtils.getSpecialCodeList(addAll = false, flag = 1, ieFlag = "") { list -> - spCodeList.postValue(listOf(KeyValue("全部", "")) + list) - } - DictUtils.getWaybillTypeList(type = "II", addAll = true) { - awbTypeList.postValue(it) - } - } - - fun searchClick() { - refresh() - } - - /** - * 全选/取消全选 - */ - fun toggleSelectAll() { - val adapter = pageModel.rv?.commonAdapter() ?: return - val list = adapter.items.filterIsInstance() - - CheckUtil.handleAllCheck(list) - updateCheckAllStatus() - adapter.notifyDataSetChanged() - } - - /** - * 更新全选状态与已选计数 - */ - fun updateCheckAllStatus() { - val adapter = pageModel.rv?.commonAdapter() ?: return - val list = adapter.items.filterIsInstance() - - isAllChecked.value = list.isNotEmpty() && list.all { it.checked.get() } - selectedCount.value = list.count { it.checked.get() }.toString() - } - - /** - * 单个item选择变化时调用(从Activity接收事件) - */ - fun onItemCheckChanged() { - updateCheckAllStatus() - } - - /** - * 获取选中的运单 - */ - fun getSelectedItems(): List { - val adapter = pageModel.rv?.commonAdapter() ?: return emptyList() - return adapter.items.filterIsInstance().filter { it.checked.get() } - } - - /** - * 提交移库(在Activity中显示确认对话框后调用) - */ - fun submitMove() { - val selectedItems = getSelectedItems() - - if (selectedItems.isEmpty()) { - showToast("请至少选择一条运单") - return - } - - launchLoadingCollect({ NetApply.api.submitIntImpMove(selectedItems.toRequestBody()) }) { - onSuccess = { - showToast("移库成功") - refresh() - } - onFailed = { _, msg -> - showToast(msg.noNull("移库失败")) - } - } - } - - /** - * 获取列表数据 - */ - override fun getData() { - // 构建筛选参数(只传递非空值;参数名按 IntExpMove 同名约定,待后端交付核对) - val filterParams = mutableMapOf() - - flightDate.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fdate"] = it } - flightNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["fno"] = it } - spCode.value?.takeIf { it.isNotEmpty() }?.let { filterParams["spCode"] = it } - awbType.value?.takeIf { it.isNotEmpty() }?.let { filterParams["awbType"] = it } - moveState.value?.takeIf { it.isNotEmpty() }?.let { filterParams["moveState"] = it } - waybillNo.value?.takeIf { it.isNotEmpty() }?.let { filterParams["wbNo"] = it } - - val listParams = (filterParams + mapOf( - "pageNum" to pageModel.page, - "pageSize" to pageModel.limit - )).toRequestBody() - - launchLoadingCollect({ NetApply.api.getIntImpMoveList(listParams) }) { - onSuccess = { - pageModel.handleListBean(it) { updateCheckAllStatus() } - } - } - - // Tab 角标计数(复用统计接口,moveState=0/1 各查一次) - loadTabCounts(filterParams) - } - - private fun loadTabCounts(filterParams: Map) { - listOf("0", "1").forEachIndexed { index, state -> - val params = (filterParams + mapOf("moveState" to state)).toRequestBody() - launchCollect({ NetApply.api.getIntImpMoveTotal(params) }) { - onSuccess = { result -> - val count = (result.data?.wbNumber ?: 0).toString() - val current = moveStateCounts.value?.toMutableList() ?: mutableListOf("", "") - if (index < current.size) { - current[index] = count - moveStateCounts.value = current - } - } - } - } - } - - /** - * Item点击事件处理(点击已在ViewHolder中处理) - */ - override fun onItemClick(position: Int, type: Int) { - // 卡片交互均在 ViewHolder / XML 中处理 - } -} diff --git a/module_gjj/src/main/res/layout/activity_int_imp_move.xml b/module_gjj/src/main/res/layout/activity_int_imp_move.xml deleted file mode 100644 index c650e7c..0000000 --- a/module_gjj/src/main/res/layout/activity_int_imp_move.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/module_gjj/src/main/res/layout/item_int_imp_move.xml b/module_gjj/src/main/res/layout/item_int_imp_move.xml deleted file mode 100644 index 38d6bdb..0000000 --- a/module_gjj/src/main/res/layout/item_int_imp_move.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt index 2348421..45b2972 100644 --- a/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt +++ b/module_p/src/main/java/com/sixin/module_p/ui/enter/gj/GjViewModel.kt @@ -78,14 +78,6 @@ class GjViewModel : BaseViewModel() { Constant.AuthName.GjjWareHouseActivity, ARouterConstants.ACTIVITY_URL_GJJ_WARE_HOUSE ), - // 进港移库:后端暂无该模块与权限串 AppIntImpMove(问题清单已登记), - // 权限串下发前此入口不会显示;实机验证走 debug 直启 - ActionBean( - "进港移库", - R.drawable.gjc_yi_ku_icon, // 复用出港移库图标(Pad 端无进港移库菜单) - Constant.AuthName.IntImpMove, - ARouterConstants.ACTIVITY_URL_INT_IMP_MOVE - ), ActionBean( "进港查询", R.drawable.gjj_query_icon, diff --git a/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt b/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt index c4873be..907c894 100644 --- a/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt +++ b/module_p/src/main/java/com/sixin/module_p/ui/enter/gn/GnViewModel.kt @@ -1,12 +1,14 @@ package com.sixin.module_p.ui.enter.gn import android.content.Intent +import com.alibaba.android.arouter.launcher.ARouter import com.lukouguoji.module_base.base.BaseViewModel import com.lukouguoji.module_base.bean.ActionBean import com.lukouguoji.module_base.common.Constant import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil import com.lukouguoji.module_base.ktx.logd import com.lukouguoji.module_base.ktx.loge +import com.lukouguoji.module_base.router.ARouterConstants import com.sixin.module_p.R import com.sixin.module_p.ui.enter.gn.document.PdaDocumentHandoverActivity import com.sixin.module_p.ui.gnc.cunfang.list.PdaGncCunFangListActivity @@ -57,11 +59,25 @@ class GnViewModel : BaseViewModel() { R.mipmap.gnc_document_handover, Constant.AuthName.DocumentHandover ), + ActionBean( + "进港移库", + R.drawable.gnj_yi_ku_icon, // 图标复制自 module_gnj(module_p 看不到业务模块资源) + Constant.AuthName.GnjYiKu, // 权限串与 Pad 端菜单一致(AppDomImpMove) + ARouterConstants.ACTIVITY_URL_GNJ_MOVE_STASH_LIST // 与 Pad 首页菜单同一跳转页(app 模块,走路由) + ), ) .filter { SharedPreferenceUtil.getString(Constant.Share.authList).contains(it.key) } fun onItemClick(position: Int) { + val bean = actionList.getOrNull(position) ?: return + + // 配了路由的直接跳(5.5 寸适配页走这条,与 GjViewModel 同模式) + if (bean.route.isNotEmpty()) { + ARouter.getInstance().build(bean.route).navigation() + return + } + when (val title = actionList[position].title) { "出港收运" -> { GncUnShouYunActivity.start(DevUtils.getTopActivity()) diff --git a/module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png b/module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png new file mode 100644 index 0000000..26454c6 Binary files /dev/null and b/module_p/src/main/res/drawable-xxhdpi/gnj_yi_ku_icon.png differ