Compare commits
92 Commits
938f7dca32
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c6fe8f5310 | |||
| b8fbc304f1 | |||
| 3df9a9f73f | |||
| 222ae8a0f5 | |||
| 1906e7ce65 | |||
| 01306d1302 | |||
| e208d54a3c | |||
| 2664cc7c69 | |||
| 644c937476 | |||
| ced24685ee | |||
| fafe092b3c | |||
| eb1d356bd2 | |||
| f3056d3807 | |||
| 1eadb9043e | |||
| bd8d6f683a | |||
| 1cfcb3fe97 | |||
| b4238a04d0 | |||
| d1ed050c76 | |||
| d600cbe4f1 | |||
| 20bab628ee | |||
| 7fb91d29b2 | |||
| 746e4cce03 | |||
| 54ea9dbe75 | |||
| 7650a835f2 | |||
| 0531f5e0c4 | |||
| 2fa567f2d2 | |||
| 23185616d1 | |||
| 5c7284e617 | |||
| 2721e36dc1 | |||
| 9129ccfb88 | |||
| fa79b7d9f3 | |||
| 77d79c4251 | |||
| 6b79433557 | |||
| d9fb950b79 | |||
| d1e54b540c | |||
| 9e0cae4321 | |||
| 38e336842a | |||
| 48abc944f0 | |||
| 82fc593497 | |||
| a81567f10b | |||
| 7d39cbf70f | |||
| 2871cbf784 | |||
| 249b5a4e87 | |||
| 6ebedc7366 | |||
| a3b8746264 | |||
| 424755298a | |||
| ee2bfe02a7 | |||
| 37ffc539c9 | |||
| 9149d1ad35 | |||
| 5fc51e7af3 | |||
| 2be3cf5251 | |||
| 7752954d1b | |||
| ccd93a14bb | |||
| d401f849c8 | |||
| 09d04cf539 | |||
| 21e0857790 | |||
| f72f853fb7 | |||
| f17b68a94c | |||
| d5bc14f0f1 | |||
| bf1d897044 | |||
| e1e16fbd9e | |||
| c0c19c8453 | |||
| bcc4bada25 | |||
| 6073010531 | |||
| d67c5edb19 | |||
| 7f7ffcccac | |||
| 22adce2964 | |||
| 6f89ad0520 | |||
| 266fafb898 | |||
| 18e6258a40 | |||
| 0723f7382e | |||
| 8e1d716159 | |||
| 08f814531c | |||
| 247b72b7e8 | |||
| 829a6328aa | |||
| f1abc3ddfc | |||
| be0541f522 | |||
| 0c3c78b42e | |||
| ea6b2f08a7 | |||
| 35a9ee145a | |||
| f797767919 | |||
| d69f964464 | |||
| 0fbb9c3704 | |||
| 29b1875fa5 | |||
| bea8a8c8c8 | |||
| 7e80d0e789 | |||
| 83ccad4171 | |||
| ec9818e267 | |||
| c002f1172a | |||
| 4a3b8a85eb | |||
| a01b17dd8f | |||
| 8a30f0079a |
3
.claude/commands/build-debug.md
Normal file
3
.claude/commands/build-debug.md
Normal file
@@ -0,0 +1,3 @@
|
||||
构建项目的 Debug 版本 APK
|
||||
|
||||
./gradlew assembleDebug
|
||||
3
.claude/commands/build-release.md
Normal file
3
.claude/commands/build-release.md
Normal file
@@ -0,0 +1,3 @@
|
||||
构建项目的 Release 版本 APK (已签名)
|
||||
|
||||
./gradlew assembleRelease
|
||||
6
.claude/commands/check-modules.md
Normal file
6
.claude/commands/check-modules.md
Normal file
@@ -0,0 +1,6 @@
|
||||
显示项目中所有模块的列表和基本信息
|
||||
|
||||
echo "=== 项目模块列表 ===" && \
|
||||
cat settings.gradle | grep "include" && \
|
||||
echo "\n=== 模块目录 ===" && \
|
||||
ls -la | grep "^d" | grep "module_"
|
||||
3
.claude/commands/clean-build.md
Normal file
3
.claude/commands/clean-build.md
Normal file
@@ -0,0 +1,3 @@
|
||||
清理构建缓存并重新构建 Debug 版本
|
||||
|
||||
./gradlew clean && ./gradlew assembleDebug
|
||||
3
.claude/commands/devices.md
Normal file
3
.claude/commands/devices.md
Normal file
@@ -0,0 +1,3 @@
|
||||
列出所有已连接的 Android 设备和模拟器
|
||||
|
||||
adb devices -l
|
||||
3
.claude/commands/install.md
Normal file
3
.claude/commands/install.md
Normal file
@@ -0,0 +1,3 @@
|
||||
构建并安装 Debug 版本到连接的 Android 设备或模拟器
|
||||
|
||||
./gradlew installDebug
|
||||
3
.claude/commands/lint.md
Normal file
3
.claude/commands/lint.md
Normal file
@@ -0,0 +1,3 @@
|
||||
运行 Android Lint 代码质量检查
|
||||
|
||||
./gradlew lint
|
||||
3
.claude/commands/logs.md
Normal file
3
.claude/commands/logs.md
Normal file
@@ -0,0 +1,3 @@
|
||||
实时查看应用日志 (过滤应用包名)
|
||||
|
||||
adb logcat | grep "com.lukouguoji.aerologic"
|
||||
@@ -20,7 +20,24 @@
|
||||
"Bash(xargs -I {} sh -c 'echo \"\"\"\"=== {} ===\"\"\"\" && jar tf {} 2>/dev/null | grep -i \"\"\"\"gprinter\"\"\"\" | head -5')",
|
||||
"Bash(xmllint:*)",
|
||||
"Bash(xargs cat:*)",
|
||||
"mcp__chrome-devtools__evaluate_script"
|
||||
"mcp__chrome-devtools__evaluate_script",
|
||||
"WebSearch",
|
||||
"Bash(chmod:*)",
|
||||
"Bash(xargs ls:*)",
|
||||
"Bash(xargs rm -rf)",
|
||||
"Bash(for module in module_gnc module_gnj module_gjc module_gjj module_hangban module_cargo module_mit module_p Printer MPChartLib)",
|
||||
"Bash(do echo '=== $module ===' ls -la /Users/kid/Development/Fusion/Projects/aerologic-app/$module/)",
|
||||
"Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app log --oneline)",
|
||||
"Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app branch -a)",
|
||||
"Bash(adb:*)",
|
||||
"Bash(emulator:*)",
|
||||
"Bash(logcat:*)",
|
||||
"Bash(grep:*)",
|
||||
"Bash(sort:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(xargs rm:*)",
|
||||
"Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app stash)",
|
||||
"WebFetch(domain:api.apifox.cn)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
246
.docs/大写字母数字输入过滤器使用指南.md
Normal file
246
.docs/大写字母数字输入过滤器使用指南.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# 大写字母数字输入过滤器使用指南
|
||||
|
||||
## 功能说明
|
||||
|
||||
为 EditText 提供输入过滤功能:
|
||||
- ✅ 只允许输入大写字母(A-Z)和数字(0-9)
|
||||
- ✅ 小写字母自动转为大写
|
||||
- ✅ 自动过滤中文、特殊符号、空格等所有非法字符
|
||||
|
||||
## 核心实现
|
||||
|
||||
**位置**: `module_base/src/main/java/com/lukouguoji/module_base/ktx/EditTextKtx.kt`
|
||||
|
||||
```kotlin
|
||||
/**
|
||||
* 大写字母和数字输入过滤器
|
||||
*/
|
||||
class UpperCaseAlphanumericInputFilter : InputFilter {
|
||||
// 实现细节...
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 EditText 设置大写字母和数字输入过滤器
|
||||
*/
|
||||
fun EditText.setUpperCaseAlphanumericFilter() {
|
||||
this.filters = arrayOf(UpperCaseAlphanumericInputFilter())
|
||||
}
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 方式一:直接为 EditText 设置(最简单)
|
||||
|
||||
```kotlin
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
|
||||
// Activity 中
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
// 为普通 EditText 设置
|
||||
binding.editText.setUpperCaseAlphanumericFilter()
|
||||
}
|
||||
```
|
||||
|
||||
### 方式二:为 PadDataLayoutNew 内部的 EditText 设置
|
||||
|
||||
```kotlin
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
|
||||
// Activity 中
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
// PadDataLayoutNew 内部有一个 et 属性,是 EditText
|
||||
binding.carIdInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.uldNoInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.impCodeInput.et.setUpperCaseAlphanumericFilter()
|
||||
}
|
||||
```
|
||||
|
||||
### 方式三:在自定义 View 中设置
|
||||
|
||||
```kotlin
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
|
||||
class CustomView : FrameLayout {
|
||||
private val editText: EditText
|
||||
|
||||
init {
|
||||
// 初始化后设置
|
||||
editText.setUpperCaseAlphanumericFilter()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 实际应用案例
|
||||
|
||||
### 案例1:板箱过磅页面(GjcBoxWeighingAddActivity)
|
||||
|
||||
**需求**: 架子车号、ULD编码、IMP代码只允许输入大写字母和数字
|
||||
|
||||
**实现**:
|
||||
|
||||
```kotlin
|
||||
// GjcBoxWeighingAddActivity.kt
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("板箱过磅")
|
||||
binding.viewModel = viewModel
|
||||
viewModel.initOnCreated(this)
|
||||
|
||||
// 为架子车号、ULD编码、IMP代码添加大写字母和数字的输入限制
|
||||
binding.carIdInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.uldNoInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.impCodeInput.et.setUpperCaseAlphanumericFilter()
|
||||
}
|
||||
```
|
||||
|
||||
**效果**:
|
||||
- 输入 `abc123` → 自动变成 `ABC123`
|
||||
- 输入 `板箱_88` → 自动变成 `88`
|
||||
- 输入 `test@#456` → 自动变成 `TEST456`
|
||||
|
||||
### 案例2:其他可能需要的场景
|
||||
|
||||
**航班号输入框**:
|
||||
```kotlin
|
||||
binding.flightNoInput.et.setUpperCaseAlphanumericFilter()
|
||||
```
|
||||
|
||||
**运单号输入框**:
|
||||
```kotlin
|
||||
binding.waybillNoInput.et.setUpperCaseAlphanumericFilter()
|
||||
```
|
||||
|
||||
**任何需要大写字母+数字的输入框**:
|
||||
```kotlin
|
||||
binding.anyInput.et.setUpperCaseAlphanumericFilter()
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
### 1. Import 路径
|
||||
|
||||
```kotlin
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
```
|
||||
|
||||
### 2. 调用时机
|
||||
|
||||
必须在 View 初始化完成后调用,通常在 Activity 的 `initOnCreate` 或 Fragment 的 `onViewCreated` 中。
|
||||
|
||||
### 3. 与其他 Filter 组合使用
|
||||
|
||||
如果需要同时使用多个 Filter:
|
||||
|
||||
```kotlin
|
||||
val filters = arrayOf(
|
||||
UpperCaseAlphanumericInputFilter(),
|
||||
InputFilter.LengthFilter(20) // 同时限制长度
|
||||
)
|
||||
editText.filters = filters
|
||||
```
|
||||
|
||||
### 4. 覆盖已有 Filter
|
||||
|
||||
调用 `setUpperCaseAlphanumericFilter()` 会覆盖已有的 Filter。如果需要保留原有 Filter,请手动组合:
|
||||
|
||||
```kotlin
|
||||
val existingFilters = editText.filters
|
||||
val newFilters = existingFilters + UpperCaseAlphanumericInputFilter()
|
||||
editText.filters = newFilters
|
||||
```
|
||||
|
||||
## 扩展建议
|
||||
|
||||
如果需要其他类型的输入过滤器,可以参考 `UpperCaseAlphanumericInputFilter` 的实现:
|
||||
|
||||
### 示例1:只允许数字
|
||||
|
||||
```kotlin
|
||||
class DigitsOnlyInputFilter : InputFilter {
|
||||
override fun filter(
|
||||
source: CharSequence?,
|
||||
start: Int,
|
||||
end: Int,
|
||||
dest: Spanned?,
|
||||
dstart: Int,
|
||||
dend: Int
|
||||
): CharSequence? {
|
||||
if (source.isNullOrEmpty()) return null
|
||||
|
||||
val filtered = StringBuilder()
|
||||
for (i in start until end) {
|
||||
val char = source[i]
|
||||
if (char in '0'..'9') {
|
||||
filtered.append(char)
|
||||
}
|
||||
}
|
||||
|
||||
return if (filtered.toString() == source.subSequence(start, end).toString()) {
|
||||
null
|
||||
} else {
|
||||
filtered.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun EditText.setDigitsOnlyFilter() {
|
||||
this.filters = arrayOf(DigitsOnlyInputFilter())
|
||||
}
|
||||
```
|
||||
|
||||
### 示例2:只允许小写字母和数字
|
||||
|
||||
```kotlin
|
||||
class LowerCaseAlphanumericInputFilter : InputFilter {
|
||||
override fun filter(
|
||||
source: CharSequence?,
|
||||
start: Int,
|
||||
end: Int,
|
||||
dest: Spanned?,
|
||||
dstart: Int,
|
||||
dend: Int
|
||||
): CharSequence? {
|
||||
if (source.isNullOrEmpty()) return null
|
||||
|
||||
val filtered = StringBuilder()
|
||||
for (i in start until end) {
|
||||
val char = source[i]
|
||||
if (char in 'A'..'Z' || char in 'a'..'z' || char in '0'..'9') {
|
||||
filtered.append(char.lowercaseChar())
|
||||
}
|
||||
}
|
||||
|
||||
return if (filtered.toString() == source.subSequence(start, end).toString()) {
|
||||
null
|
||||
} else {
|
||||
filtered.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun EditText.setLowerCaseAlphanumericFilter() {
|
||||
this.filters = arrayOf(LowerCaseAlphanumericInputFilter())
|
||||
}
|
||||
```
|
||||
|
||||
## 测试建议
|
||||
|
||||
在使用前建议测试以下场景:
|
||||
|
||||
1. 输入小写字母是否自动转大写
|
||||
2. 输入中文是否被过滤
|
||||
3. 输入特殊符号是否被过滤
|
||||
4. 输入空格是否被过滤
|
||||
5. 粘贴文本是否正确处理
|
||||
6. 与软键盘的兼容性
|
||||
|
||||
## 相关文件
|
||||
|
||||
- **核心实现**: `module_base/src/main/java/com/lukouguoji/module_base/ktx/EditTextKtx.kt`
|
||||
- **使用示例**: `module_gjc/src/main/java/com/lukouguoji/gjc/activity/GjcBoxWeighingAddActivity.kt`
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-12-16
|
||||
**维护人员**: 开发团队
|
||||
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@@ -4,6 +4,14 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-11-27T08:04:42.915090Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=80STHZCHDLL4311422" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
|
||||
101
CHANGELOG.md
Normal file
101
CHANGELOG.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# 版本变更日志 (Changelog)
|
||||
|
||||
本文档记录 AirLogistics 项目的所有重要变更。
|
||||
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||
|
||||
## [1.8.4] - 2024-12-02
|
||||
|
||||
### 新增 (Added)
|
||||
- 完善 Claude Code 配置,添加 Android 开发权限
|
||||
- 创建 8 个快捷命令 (/build-debug, /install, /logs 等)
|
||||
- 定制 CLAUDE.md 为 Android 项目专用开发指南
|
||||
- 添加 CONTRIBUTING.md 贡献指南文档
|
||||
- 添加 CHANGELOG.md 版本变更日志
|
||||
|
||||
### 改进 (Changed)
|
||||
- 优化首页菜单交互体验
|
||||
- 改进 UI 界面显示效果
|
||||
|
||||
### 技术栈
|
||||
- Kotlin 1.6.21
|
||||
- Android Gradle Plugin 7.2.0
|
||||
- Gradle 7.3.3
|
||||
- minSdk 24, targetSdk 30, compileSdk 31
|
||||
|
||||
---
|
||||
|
||||
## [1.8.x] - 之前版本
|
||||
|
||||
### 主要功能
|
||||
- 国内出港业务模块 (货物收运、复磅称重、转运管理、出库装机)
|
||||
- 国内进港业务模块 (舱单管理、卸机入库、出库提货、移库管理)
|
||||
- 国际出港业务模块 (国际货物收运、板箱组装、ULD容器管理)
|
||||
- 国际进港业务模块 (国际舱单管理、报文解析、理货管理)
|
||||
- 航班管理模块 (航班查询、航班统计)
|
||||
- 货物追踪模块 (货物状态追踪、运输日志)
|
||||
- 监装监卸模块 (监装监卸管理)
|
||||
- PDA功能模块 (PDA专用功能)
|
||||
- 蓝牙打印模块 (佳博打印机集成)
|
||||
|
||||
### 核心架构
|
||||
- MVVM 架构模式
|
||||
- 组件化模块设计 (11个业务模块 + 1个基础库)
|
||||
- DataBinding 双向绑定
|
||||
- Kotlin Coroutines + Flow 异步处理
|
||||
- ARouter 模块间通信
|
||||
- Retrofit + OkHttp 网络请求
|
||||
- Glide 图片加载
|
||||
- MPAndroidChart 图表展示
|
||||
|
||||
### 开发基础设施
|
||||
- BaseActivity/BaseBindingActivity 基类
|
||||
- BaseViewModel/BasePageViewModel 基类
|
||||
- CommonAdapter + BaseViewHolder 列表适配
|
||||
- PadSearchLayout/PadDataLayout 自定义组件
|
||||
- 完整的 Kotlin 扩展函数库
|
||||
- DataBinding 适配器集合
|
||||
|
||||
---
|
||||
|
||||
## 版本说明
|
||||
|
||||
### 版本号规则
|
||||
- **Major.Minor.Patch** (例: 1.8.4)
|
||||
- **Major**: 重大架构变更或不兼容的 API 修改
|
||||
- **Minor**: 新功能添加,向下兼容
|
||||
- **Patch**: Bug 修复和小的改进
|
||||
|
||||
### 变更类型
|
||||
- **Added**: 新增功能
|
||||
- **Changed**: 功能改进或变更
|
||||
- **Deprecated**: 即将废弃的功能
|
||||
- **Removed**: 已移除的功能
|
||||
- **Fixed**: Bug 修复
|
||||
- **Security**: 安全性修复
|
||||
|
||||
---
|
||||
|
||||
## 未来计划
|
||||
|
||||
### 待开发功能
|
||||
- [ ] 优化数据同步机制
|
||||
- [ ] 增强离线模式支持
|
||||
- [ ] 改进用户权限管理
|
||||
- [ ] 优化蓝牙打印稳定性
|
||||
- [ ] 添加数据导出功能
|
||||
- [ ] 性能监控和分析
|
||||
|
||||
### 技术改进
|
||||
- [ ] 升级到 Kotlin 2.0
|
||||
- [ ] 迁移到 Jetpack Compose
|
||||
- [ ] 优化构建速度
|
||||
- [ ] 完善单元测试覆盖
|
||||
- [ ] 添加 UI 自动化测试
|
||||
|
||||
---
|
||||
|
||||
**维护**: 本文档应在每次版本发布时更新。
|
||||
**负责人**: 项目维护团队
|
||||
**最后更新**: 2024-12-02
|
||||
273
CONTRIBUTING.md
Normal file
273
CONTRIBUTING.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# 贡献指南 (Contributing Guide)
|
||||
|
||||
感谢你对 AirLogistics 项目的关注!本文档将指导你如何参与项目开发。
|
||||
|
||||
## 开发环境搭建
|
||||
|
||||
### 前置要求
|
||||
|
||||
- **IDE**: Android Studio Arctic Fox (2020.3.1) 或更高版本
|
||||
- **JDK**: JDK 1.8
|
||||
- **Gradle**: 7.3.3 (使用项目内置的 Gradle Wrapper)
|
||||
- **Kotlin**: 1.6.21 (已在项目中配置)
|
||||
- **Android SDK**: API 24-31
|
||||
|
||||
### 克隆项目
|
||||
|
||||
```bash
|
||||
git clone ssh://git@git.njcqit.com:2222/eric/aerologic-app.git
|
||||
cd aerologic-app
|
||||
```
|
||||
|
||||
### 配置 Android SDK
|
||||
|
||||
1. 创建 `local.properties` 文件 (如果不存在):
|
||||
```properties
|
||||
sdk.dir=/path/to/your/android/sdk
|
||||
```
|
||||
|
||||
2. 在 Android Studio 中:
|
||||
- 打开项目
|
||||
- 等待 Gradle 同步完成
|
||||
- 如提示 SDK 路径问题,在 Settings → Android SDK 中配置
|
||||
|
||||
### Gradle 依赖配置
|
||||
|
||||
项目已配置阿里云 Maven 镜像和私有仓库,正常情况下依赖会自动下载。
|
||||
|
||||
如遇依赖下载问题:
|
||||
1. 下载 gradle-7.3.3-bin.zip
|
||||
- 百度网盘: https://pan.baidu.com/s/18wsuGRlNxjMYbxLhBH9yeg
|
||||
- 提取码: 1029
|
||||
|
||||
2. 配置 Gradle:
|
||||
- Settings → Build, Execution, Deployment → Build Tools → Gradle
|
||||
- 解压并替换到 "Gradle user home" 目录
|
||||
|
||||
## 项目构建
|
||||
|
||||
### 首次构建
|
||||
|
||||
```bash
|
||||
# 清理并构建 Debug 版本
|
||||
./gradlew clean assembleDebug
|
||||
|
||||
# 或使用快捷命令
|
||||
/clean-build
|
||||
```
|
||||
|
||||
### 常用构建命令
|
||||
|
||||
```bash
|
||||
# 构建 Debug APK
|
||||
./gradlew assembleDebug
|
||||
# 或使用: /build-debug
|
||||
|
||||
# 构建 Release APK (已签名)
|
||||
./gradlew assembleRelease
|
||||
# 或使用: /build-release
|
||||
|
||||
# 安装到设备
|
||||
./gradlew installDebug
|
||||
# 或使用: /install
|
||||
|
||||
# 运行代码检查
|
||||
./gradlew lint
|
||||
# 或使用: /lint
|
||||
|
||||
# 查看已连接设备
|
||||
adb devices -l
|
||||
# 或使用: /devices
|
||||
|
||||
# 查看应用日志
|
||||
adb logcat | grep "com.lukouguoji.aerologic"
|
||||
# 或使用: /logs
|
||||
```
|
||||
|
||||
### 组件化开发模式
|
||||
|
||||
项目支持模块独立运行,方便单模块调试:
|
||||
|
||||
1. 编辑 `gradle.properties`
|
||||
2. 设置 `isBuildModule=true` (独立运行) 或 `false` (集成模式)
|
||||
3. Sync 项目
|
||||
4. 运行对应模块
|
||||
|
||||
**注意**: 切换模式后需要重新 Sync 项目。
|
||||
|
||||
## 分支策略
|
||||
|
||||
### 分支类型
|
||||
|
||||
- **main**: 主分支,用于发布稳定版本
|
||||
- **feature/xxx**: 功能开发分支 (例: `feature/cargo-tracking`)
|
||||
- **hotfix/xxx**: 紧急修复分支 (例: `hotfix/login-crash`)
|
||||
- **refactor/xxx**: 重构分支 (例: `refactor/network-layer`)
|
||||
|
||||
### 分支命名规范
|
||||
|
||||
- 使用小写字母和连字符
|
||||
- 功能分支: `feature/功能名称-简短描述`
|
||||
- 修复分支: `hotfix/问题简述`
|
||||
- 重构分支: `refactor/重构范围`
|
||||
|
||||
### 工作流程
|
||||
|
||||
1. 从 main 分支创建新分支:
|
||||
```bash
|
||||
git checkout main
|
||||
git pull
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
2. 在新分支上开发并提交
|
||||
|
||||
3. 推送到远程仓库:
|
||||
```bash
|
||||
git push -u origin feature/your-feature-name
|
||||
```
|
||||
|
||||
4. 创建 Pull Request,等待代码审查
|
||||
|
||||
## 提交规范
|
||||
|
||||
### Conventional Commits 格式
|
||||
|
||||
提交信息应遵循以下格式:
|
||||
|
||||
```
|
||||
<类型>: <简短描述>
|
||||
|
||||
[可选的详细说明]
|
||||
|
||||
[可选的 footer]
|
||||
```
|
||||
|
||||
### 提交类型
|
||||
|
||||
- **feat**: 新功能 (例: `feat: 添加国内出港货物复磅功能`)
|
||||
- **fix**: Bug修复 (例: `fix: 修复登录页面崩溃问题`)
|
||||
- **refactor**: 代码重构 (例: `refactor: 优化网络请求层架构`)
|
||||
- **docs**: 文档更新 (例: `docs: 更新 README 安装说明`)
|
||||
- **style**: 代码格式调整 (例: `style: 格式化 LoginActivity 代码`)
|
||||
- **test**: 测试相关 (例: `test: 添加货物追踪单元测试`)
|
||||
- **chore**: 构建/工具相关 (例: `chore: 升级 Kotlin 到 1.6.21`)
|
||||
|
||||
### 提交示例
|
||||
|
||||
```bash
|
||||
# 好的提交信息
|
||||
git commit -m "feat: 添加国际进港舱单管理功能"
|
||||
git commit -m "fix: 修复蓝牙打印机连接失败问题"
|
||||
git commit -m "refactor: 重构 BaseViewModel 生命周期管理"
|
||||
|
||||
# 不好的提交信息
|
||||
git commit -m "update"
|
||||
git commit -m "修改了一些文件"
|
||||
git commit -m "功能完成"
|
||||
```
|
||||
|
||||
## 代码审查流程
|
||||
|
||||
### 创建 Pull Request
|
||||
|
||||
1. 确保代码已推送到远程仓库
|
||||
2. 在 Git 托管平台创建 Pull Request
|
||||
3. 填写 PR 描述:
|
||||
- 功能说明
|
||||
- 变更内容
|
||||
- 测试情况
|
||||
- 相关 Issue (如有)
|
||||
|
||||
### 代码审查要点
|
||||
|
||||
审查者应关注:
|
||||
- [ ] 代码是否符合项目架构和规范
|
||||
- [ ] 是否使用了正确的基类 (BaseActivity, BaseViewModel等)
|
||||
- [ ] DataBinding 和协程使用是否正确
|
||||
- [ ] 命名是否清晰、符合约定
|
||||
- [ ] 是否有明显的性能问题
|
||||
- [ ] 是否有代码重复或可复用的逻辑
|
||||
|
||||
### 合并前检查清单
|
||||
|
||||
提交者在创建 PR 前应确保:
|
||||
- [ ] 代码编译通过,无编译错误
|
||||
- [ ] 遵循项目命名和文件组织规范
|
||||
- [ ] 使用了项目提供的基类和工具类
|
||||
- [ ] DataBinding 正确使用
|
||||
- [ ] 协程和 Flow 使用规范
|
||||
- [ ] 无明显的内存泄漏风险
|
||||
- [ ] 已在真机或模拟器上测试
|
||||
- [ ] 提交信息符合规范
|
||||
|
||||
## 开发注意事项
|
||||
|
||||
### 架构要求
|
||||
|
||||
1. **优先使用现有基类**
|
||||
- Activity 继承 `BaseActivity` 或 `BaseBindingActivity`
|
||||
- ViewModel 继承 `BaseViewModel` 或 `BasePageViewModel`
|
||||
- 列表适配器使用 `CommonAdapter` + `BaseViewHolder`
|
||||
|
||||
2. **使用统一 UI 组件**
|
||||
- 搜索输入: 使用 `PadSearchLayout`
|
||||
- 数据展示: 使用 `PadDataLayout`
|
||||
- 遵循全局样式规范 (colors, dimens, styles)
|
||||
|
||||
3. **网络请求规范**
|
||||
- 使用 `launchCollect` 或 `launchLoadingCollect` 扩展函数
|
||||
- API 定义在对应模块的 `api/` 目录下
|
||||
- 数据模型继承 `BaseResultBean` 或 `BaseListBean`
|
||||
|
||||
### 代码风格
|
||||
|
||||
- 遵循 Kotlin 官方编码规范
|
||||
- 使用有意义的变量名和函数名
|
||||
- 避免过长的函数,单个函数不超过 50 行
|
||||
- 复杂逻辑添加注释说明
|
||||
|
||||
### 安全要求
|
||||
|
||||
- **禁止提交敏感信息**:
|
||||
- API密钥
|
||||
- 密码
|
||||
- Token
|
||||
- 个人信息
|
||||
- 签名文件 (key.jks 已在 .gitignore 中)
|
||||
|
||||
- **配置信息管理**:
|
||||
- 服务器地址配置在 `module_base/res/values/strings.xml`
|
||||
- 本地开发配置使用 `local.properties`
|
||||
- 运行时配置使用 SharedPreferences
|
||||
|
||||
## 模块开发规范
|
||||
|
||||
### 新增业务页面
|
||||
|
||||
1. 在对应模块的 `ui/page/` 目录下创建 Activity
|
||||
2. 在 `service/viewModel/` 目录下创建 ViewModel
|
||||
3. 在 `bean/` 目录下定义数据模型
|
||||
4. 布局文件使用 DataBinding
|
||||
|
||||
### 模块间通信
|
||||
|
||||
- 使用 ARouter 进行页面跳转
|
||||
- 路由路径定义在 `module_base/router/` 目录
|
||||
- 事件通信使用 FlowBus 或 EventBus
|
||||
|
||||
## 获取帮助
|
||||
|
||||
如有问题或建议,可以通过以下方式:
|
||||
|
||||
1. 查看项目文档:
|
||||
- [CLAUDE.md](./CLAUDE.md) - 详细开发指南
|
||||
- [README.md](./README.md) - 项目概览
|
||||
|
||||
2. 联系项目维护者
|
||||
|
||||
3. 提交 Issue (如果支持)
|
||||
|
||||
---
|
||||
|
||||
再次感谢你的贡献!🎉
|
||||
@@ -104,6 +104,53 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcAssembleAllocateActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港出库交接 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.IntExpOutHandoverActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港装载 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.IntExpLoadActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港理货 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.IntExpTallyActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港运抵 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.IntExpArriveActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港查询 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcQueryActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港运单修改 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcQueryEditActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港查询详情 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcQueryDetailsActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcBoxWeighingActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
@@ -130,6 +177,11 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcWeighingRecordDetailsActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.activity.GjcWeighingStartActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
@@ -140,6 +192,24 @@
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港-出港组装 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.page.assemble.IntExpAssembleActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港-开始组装 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.page.assemble.IntExpAssembleStartActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<!-- 国际出港-出港移库 -->
|
||||
<activity
|
||||
android:name="com.lukouguoji.gjc.page.move.IntExpMoveActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:exported="false"
|
||||
android:screenOrientation="userLandscape" />
|
||||
<activity
|
||||
android:name=".MineActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
|
||||
@@ -51,6 +51,14 @@ class HomeFragment : Fragment() {
|
||||
|
||||
private val TAG: String = HomeFragment::class.java.simpleName
|
||||
|
||||
/**
|
||||
* ========== 开发调试开关 ==========
|
||||
* TODO: 正式发布前务必设置为 false
|
||||
*/
|
||||
companion object {
|
||||
private const val DEV_AUTO_SELECT_INT_EXP = true // 自动选择国际出港开关
|
||||
}
|
||||
|
||||
private var rvLeft: RecyclerView by Delegates.notNull()
|
||||
private var rvRight: RecyclerView by Delegates.notNull()
|
||||
|
||||
@@ -70,6 +78,10 @@ class HomeFragment : Fragment() {
|
||||
val leftMenuList = initLeftMenuData()
|
||||
rvLeft.adapter = HomeLeftAdapt(leftMenuList)
|
||||
rvRight.adapter = HomeRightAdapt(getRightMenu4Id(leftMenuList.first().id))
|
||||
|
||||
// ========== 开发调试:自动选择"国际出港"菜单 ==========
|
||||
// TODO: 正式发布前删除此行
|
||||
autoSelectIntExpForDev()
|
||||
}
|
||||
|
||||
/////////// 左边的list循环
|
||||
@@ -155,6 +167,31 @@ class HomeFragment : Fragment() {
|
||||
}
|
||||
|
||||
override fun getItemCount() = leftMenuList.size
|
||||
|
||||
/**
|
||||
* 开发调试:模拟点击菜单项
|
||||
* TODO: 正式发布前删除此方法
|
||||
*/
|
||||
fun simulateClick(position: Int) {
|
||||
if (position < 0 || position >= leftMenuList.size) return
|
||||
|
||||
val leftMenuTemp = leftMenuList[position]
|
||||
|
||||
// 跳过特殊菜单(航班查询、货物查询)
|
||||
if (Constant.AuthName.Flight == leftMenuTemp.id ||
|
||||
Constant.AuthName.CargoStatus == leftMenuTemp.id) {
|
||||
return
|
||||
}
|
||||
|
||||
// 更新选中位置
|
||||
mPosition = position
|
||||
|
||||
// 刷新右侧菜单
|
||||
refreshRight(leftMenuList[mPosition].id)
|
||||
|
||||
// 更新菜单状态
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
inner class LeftMenu(val id: String, val img: Int, val text: String)
|
||||
@@ -335,7 +372,7 @@ class HomeFragment : Fragment() {
|
||||
}
|
||||
//移库
|
||||
Constant.AuthName.GjcYiKuListActivity -> {
|
||||
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_GJC_YI_KU)
|
||||
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_MOVE)
|
||||
.navigation()
|
||||
}
|
||||
// 板箱
|
||||
@@ -353,6 +390,40 @@ class HomeFragment : Fragment() {
|
||||
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_GJC_INSPECTION)
|
||||
.navigation()
|
||||
}
|
||||
// 出港组装
|
||||
Constant.AuthName.GjcIntExpAssembleActivity -> {
|
||||
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ASSEMBLE)
|
||||
.navigation()
|
||||
}
|
||||
// 组装分配
|
||||
Constant.AuthName.GjcAssembleAllocateActivity -> {
|
||||
ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE)
|
||||
.navigation()
|
||||
}
|
||||
// 出库交接
|
||||
Constant.AuthName.GjcIntExpOutHandover -> {
|
||||
ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER)
|
||||
.navigation()
|
||||
}
|
||||
// 出港装载
|
||||
Constant.AuthName.GjcIntExpLoad -> {
|
||||
ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_LOAD)
|
||||
.navigation()
|
||||
}
|
||||
// 出港理货
|
||||
Constant.AuthName.GjcIntExpTally -> {
|
||||
ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_TALLY)
|
||||
.navigation()
|
||||
}
|
||||
// 出港运抵
|
||||
Constant.AuthName.GjcIntExpArrive -> {
|
||||
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
|
||||
.navigation()
|
||||
}
|
||||
/**
|
||||
* 国际进港
|
||||
*/
|
||||
@@ -595,20 +666,22 @@ class HomeFragment : Fragment() {
|
||||
}
|
||||
|
||||
Constant.AuthName.IntExp -> {
|
||||
// list.add(
|
||||
// RightMenu(
|
||||
// Constant.AuthName.GjcAppDomExpCheckin,
|
||||
// R.mipmap.gjc_shou_yun_icon,
|
||||
// "出港收运"
|
||||
// )
|
||||
// )
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcAppDomExpCheckin,
|
||||
R.mipmap.gjc_shou_yun_icon,
|
||||
"出港收运"
|
||||
)
|
||||
)
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcFuBangActivity,
|
||||
R.mipmap.gjc_fu_bang_icon,
|
||||
"板箱过磅"
|
||||
Constant.AuthName.GjcInspectionActivity,
|
||||
R.mipmap.gnc_cha,
|
||||
"收运检查"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcCheckWeighing,
|
||||
@@ -616,20 +689,23 @@ class HomeFragment : Fragment() {
|
||||
"出港计重"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcWareHouseActivity,
|
||||
R.mipmap.gjc_cang_ku_icon,
|
||||
"仓库管理"
|
||||
Constant.AuthName.GjcFuBangActivity,
|
||||
R.mipmap.gjc_fu_bang_icon,
|
||||
"板箱过磅"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcYiKuListActivity,
|
||||
R.mipmap.gjc_yi_ku_icon,
|
||||
"出港移库"
|
||||
Constant.AuthName.GjcIntExpAssembleActivity,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"出港组装"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcQueryListActivity,
|
||||
@@ -640,25 +716,76 @@ class HomeFragment : Fragment() {
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcBanXListActivity,
|
||||
Constant.AuthName.GjcYiKuListActivity,
|
||||
R.mipmap.gjc_yi_ku_icon,
|
||||
"出港移库"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcAssembleAllocateActivity,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"板箱组装"
|
||||
"组装分配"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcGoodsListActivity,
|
||||
R.mipmap.img_hwjj,
|
||||
"货物交接"
|
||||
Constant.AuthName.GjcIntExpOutHandover,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"出库交接"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcInspectionActivity,
|
||||
R.mipmap.gnc_cha,
|
||||
"收运检查"
|
||||
Constant.AuthName.GjcIntExpLoad,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"出港装载"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcIntExpTally,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"出港理货"
|
||||
)
|
||||
)
|
||||
|
||||
list.add(
|
||||
RightMenu(
|
||||
Constant.AuthName.GjcIntExpArrive,
|
||||
com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
"出港运抵"
|
||||
)
|
||||
)
|
||||
|
||||
// list.add(
|
||||
// RightMenu(
|
||||
// Constant.AuthName.GjcWareHouseActivity,
|
||||
// R.mipmap.gjc_cang_ku_icon,
|
||||
// "仓库管理"
|
||||
// )
|
||||
// )
|
||||
|
||||
|
||||
// list.add(
|
||||
// RightMenu(
|
||||
// Constant.AuthName.GjcBanXListActivity,
|
||||
// com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
|
||||
// "板箱组装"
|
||||
// )
|
||||
// )
|
||||
|
||||
// list.add(
|
||||
// RightMenu(
|
||||
// Constant.AuthName.GjcGoodsListActivity,
|
||||
// R.mipmap.img_hwjj,
|
||||
// "货物交接"
|
||||
// )
|
||||
// )
|
||||
}
|
||||
|
||||
Constant.AuthName.IntImp -> {
|
||||
@@ -816,4 +943,26 @@ class HomeFragment : Fragment() {
|
||||
private fun refreshRight(id: String) {
|
||||
(rvRight.adapter as? HomeRightAdapt)?.refresh(getRightMenu4Id(id))
|
||||
}
|
||||
|
||||
/**
|
||||
* 开发调试:自动选择"国际出港"菜单
|
||||
* TODO: 正式发布前删除此方法或将 DEV_AUTO_SELECT_INT_EXP 设置为 false
|
||||
*/
|
||||
private fun autoSelectIntExpForDev() {
|
||||
if (!DEV_AUTO_SELECT_INT_EXP) return
|
||||
|
||||
// 延迟执行,确保适配器已初始化
|
||||
rvLeft.postDelayed({
|
||||
val leftAdapter = rvLeft.adapter as? HomeLeftAdapt ?: return@postDelayed
|
||||
|
||||
// 查找"国际出港"在左侧菜单的位置
|
||||
val leftMenuList = initLeftMenuData()
|
||||
val intExpIndex = leftMenuList.indexOfFirst { it.id == Constant.AuthName.IntExp }
|
||||
|
||||
if (intExpIndex >= 0) {
|
||||
// 模拟点击左侧"国际出港"菜单项
|
||||
leftAdapter.simulateClick(intExpIndex)
|
||||
}
|
||||
}, 300) // 延迟300ms确保适配器已绑定数据
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,11 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import me.jessyan.autosize.internal.CustomAdapt
|
||||
|
||||
/**
|
||||
* ========== 开发调试开关 ==========
|
||||
* TODO: 正式发布前务必设置为 false
|
||||
*/
|
||||
private const val DEV_AUTO_LOGIN = true // 自动登录开关
|
||||
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_LOGIN)
|
||||
class LoginActivity : BaseActivity(),
|
||||
@@ -100,6 +105,15 @@ class LoginActivity : BaseActivity(),
|
||||
spinner.setSelection(index)
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 开发调试:角色信息获取成功后自动登录 ==========
|
||||
// TODO: 正式发布前删除此代码块
|
||||
if (DEV_AUTO_LOGIN && user.text.toString() == "ADMIN") {
|
||||
loginButton.postDelayed({
|
||||
val encodedPassword = "$2a$10$02ZpVb/bymrybmPE2Mu2C.O.JcMXTB..gkssaNn8q2EC.kUAfJP0S"
|
||||
viewModel.login(user.text.toString(), encodedPassword)
|
||||
}, 200) // 短暂延迟确保spinner更新完成
|
||||
}
|
||||
}
|
||||
bindOnSelected(spinner, object : IOnSpinnerSelected {
|
||||
override fun onSelected(position: Int) {
|
||||
@@ -183,6 +197,28 @@ class LoginActivity : BaseActivity(),
|
||||
|
||||
bindAdapter(spinner, viewModel.roleList, "请选择角色", R.layout.item_spinner_list_18sp)
|
||||
setEnable(spinner, false)
|
||||
|
||||
// ========== 开发调试:自动登录 ==========
|
||||
// TODO: 正式发布前删除此行
|
||||
autoLoginForDev()
|
||||
}
|
||||
|
||||
/**
|
||||
* 开发调试:自动登录
|
||||
* TODO: 正式发布前删除此方法或将 DEV_AUTO_LOGIN 设置为 false
|
||||
*/
|
||||
private fun autoLoginForDev() {
|
||||
if (!DEV_AUTO_LOGIN) return
|
||||
|
||||
// 延迟执行,确保UI初始化完成
|
||||
loginButton.postDelayed({
|
||||
// 设置用户名
|
||||
user.setText("ADMIN")
|
||||
|
||||
// 手动触发获取角色信息
|
||||
// 角色信息获取成功后会在userRoleBean.observe中自动执行登录
|
||||
viewModel.getUserRole("ADMIN")
|
||||
}, 500) // 延迟500ms确保ViewModel已初始化
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 组装公司Bean
|
||||
* 用于组装分配时选择分配人
|
||||
*/
|
||||
data class AssembleCompanyBean(
|
||||
val code: String = "", // 公司代码,例如 "ATR"
|
||||
val name: String = "" // 公司名称,例如 "ATR:马道"
|
||||
) {
|
||||
/**
|
||||
* 转换为 KeyValue 用于下拉列表
|
||||
* @return KeyValue(显示文本, 实际值)
|
||||
* 例如: KeyValue("ATR:马道", "ATR")
|
||||
*/
|
||||
fun toKeyValue() = KeyValue(name, code)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
|
||||
/**
|
||||
* 组装信息Bean(左侧折叠列表)
|
||||
* 支持两种行类型:
|
||||
* 1. 一级ULD行: 显示ULD编号、总件数、总重量
|
||||
* 2. 二级运单行: 显示运单号、件数、重量
|
||||
*/
|
||||
class AssembleInfoBean {
|
||||
|
||||
// ========== 层级类型 ==========
|
||||
enum class ItemType {
|
||||
ULD_HEADER, // 一级ULD行
|
||||
WAYBILL_DETAIL // 二级运单行
|
||||
}
|
||||
|
||||
var itemType: ItemType = ItemType.ULD_HEADER // 行类型
|
||||
|
||||
// ========== 一级ULD行字段 ==========
|
||||
var uldNo: String = "" // ULD编号
|
||||
var uldIndex: Int = 0 // ULD序号(用于显示1、2、3...)
|
||||
var totalPieces: Int = 0 // 总件数(二级运单件数求和)
|
||||
var totalWeight: Double = 0.0 // 总重量(二级运单重量求和)
|
||||
|
||||
// 展开/折叠状态(使用ObservableBoolean支持DataBinding)
|
||||
val isExpanded: ObservableBoolean = ObservableBoolean(false)
|
||||
|
||||
// 子运单列表(用于数据管理,不直接显示)
|
||||
var waybillChildren: MutableList<AssembleInfoBean> = mutableListOf()
|
||||
|
||||
// ========== 二级运单行字段 ==========
|
||||
var parentUldNo: String = "" // 父级ULD编号(用于关联)
|
||||
var wbNo: String = "" // 运单号(直接使用后端字段名)
|
||||
var waybillPieces: Int = 0 // 运单件数
|
||||
var waybillWeight: Double = 0.0 // 运单重量
|
||||
|
||||
// 原始运单数据(用于同步更新和填充表单)
|
||||
var waybillData: AssembleWaybillBean? = null
|
||||
|
||||
// 关联的原始数据(用于存储GjcUldUseBean等对象)
|
||||
var tag: Any? = null
|
||||
|
||||
// ========== 视觉样式字段 ==========
|
||||
var hasArrow: Boolean = false // 是否显示箭头(一级ULD行为true)
|
||||
var isOrange: Boolean = false // 是否橙色文字(暂保留)
|
||||
var showIndex: Boolean = false // 是否显示序号圆圈(改为false,不再显示序号)
|
||||
var showIndent: Boolean = false // 是否显示缩进(二级运单行为true)
|
||||
|
||||
// 保留原有的weightInfo字段(兼容性,但不再使用)
|
||||
var weightInfo: String = ""
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 组装位置Bean
|
||||
*/
|
||||
class AssemblePositionBean {
|
||||
var positionName: String = "" // 位置名称
|
||||
var isSelected: Boolean = false // 是否选中
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
|
||||
/**
|
||||
* 运单列表Bean(右侧运单列表)
|
||||
*/
|
||||
class AssembleWaybillBean {
|
||||
var waybillNo: String = "" // 运单号
|
||||
var pieces: String = "" // 件数(累积的组装件数)
|
||||
var weight: String = "" // 重量(累积的组装重量)
|
||||
var flight: String = "" // 配载航班
|
||||
var isMarked: Boolean = false // 是否标记(红色显示)
|
||||
var fno: String = ""
|
||||
var fdate: String = ""
|
||||
var whId: Long = 0 // 运单ID(用于接口调用)
|
||||
|
||||
// ========== 原始运单信息(用于编辑模式回显) ==========
|
||||
var originalPieces: String = "" // 原始运单件数
|
||||
var originalWeight: String = "" // 原始运单重量
|
||||
|
||||
val fLightInfo: String
|
||||
get() = "$fno/${fdate.replace("-", "")}"
|
||||
|
||||
// ========== UI扩展字段 ==========
|
||||
val isSelected: ObservableBoolean = ObservableBoolean(false) // 选中状态
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 字典-Location接口返回数据Bean
|
||||
*/
|
||||
data class DictLocationBean(
|
||||
var code: String = "", // 编码值 (例如: "18")
|
||||
var name: String = "" // 显示名称 (例如: "国际出港通道01")
|
||||
) {
|
||||
/**
|
||||
* 转换为KeyValue
|
||||
* KeyValue(显示名称, 编码值)
|
||||
*/
|
||||
fun toKeyValue() = KeyValue(name, code)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import com.lukouguoji.module_base.interfaces.ICheck
|
||||
|
||||
/**
|
||||
* 国际出港组装分配Bean
|
||||
*/
|
||||
data class GjcAssembleAllocate(
|
||||
val abDate: String? = null, // 组装时间
|
||||
val abName: String? = null, // 组装公司(中文)
|
||||
val abid: String? = null, // 组装公司ID
|
||||
val acDate: String? = null, // 分配时间
|
||||
val acName: String? = null, // 分配人(中文)
|
||||
val acid: String? = null, // 分配人ID
|
||||
val fdate: String? = null, // 航班日期
|
||||
val fdep: String? = null, // 始发站
|
||||
val fdest: String? = null, // 目的站
|
||||
val fid: Long? = null, // 航班id
|
||||
val fidList: List<Long>? = null, // 航班fid列表
|
||||
val fno: String? = null, // 航班号
|
||||
val id: Long? = null, // 主键
|
||||
val jtz: String? = null, // 经停站
|
||||
val range: String? = null, // 航程
|
||||
|
||||
// 用于UI的可观察选中状态
|
||||
val checked: ObservableBoolean = ObservableBoolean(false)
|
||||
) : ICheck {
|
||||
override fun getCheckObservable(): ObservableBoolean = checked
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港组装记录Bean
|
||||
* 对应API: /IntExpAssemble/queryAssembled
|
||||
*/
|
||||
class GjcAssembled {
|
||||
var uldUse: GjcUldUseBean? = null // ULD信息
|
||||
var warehouseList: MutableList<GjcWarehouse>? = null // 运单列表
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港-分页查询请求参数
|
||||
* 用于出港装载、检入记录等列表查询
|
||||
*/
|
||||
data class GjcCheckInPage(
|
||||
var fdate: String? = null, // 航班日期
|
||||
var fno: String? = null, // 航班号
|
||||
var no: String? = null, // 运单号
|
||||
var hno: String? = null, // 分单号
|
||||
var pageNum: Int = 1, // 页码
|
||||
var pageSize: Int = 10 // 每页条数
|
||||
)
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.BaseObservable
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.databinding.library.baseAdapters.BR
|
||||
|
||||
/**
|
||||
* 国际出港计重记录明细Bean
|
||||
* 用于:加载运单的所有计重记录 + 批量更新
|
||||
* 对应API:
|
||||
* - POST /IntExpCheckIn/listRecordByWh (加载)
|
||||
* - POST /IntExpCheckIn/updateRecordList (保存)
|
||||
*/
|
||||
data class GjcCheckInRecord(
|
||||
var id: Long = 0, // 收运记录id
|
||||
var maWbId: Long = 0, // GJC_MAWB.MAWBID
|
||||
var no: String = "", // 运单号
|
||||
var prefix: String = "", // 运单前缀
|
||||
var opDate: String = "", // 操作时间
|
||||
var opId: String = "", // 操作员id
|
||||
var pc: Long = 0, // 运抵件数
|
||||
var weight: Double = 0.0, // 运抵重量
|
||||
var volume: Double = 0.0, // 运抵体积
|
||||
var whId: Long = 0 // GJC_WAREHOUSE.ID
|
||||
) : BaseObservable() {
|
||||
|
||||
// 数据变化回调
|
||||
var onDataChanged: (() -> Unit)? = null
|
||||
|
||||
// 件数的字符串表示(用于双向绑定)
|
||||
@get:Bindable
|
||||
var pcStr: String
|
||||
get() = if (pc == 0L) "" else pc.toString()
|
||||
set(value) {
|
||||
val newPc = value.toLongOrNull() ?: 0L
|
||||
if (pc != newPc) {
|
||||
pc = newPc
|
||||
notifyPropertyChanged(BR.pcStr)
|
||||
onDataChanged?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
// 重量的字符串表示(用于双向绑定)
|
||||
@get:Bindable
|
||||
var weightStr: String
|
||||
get() = if (weight == 0.0) "" else weight.toString()
|
||||
set(value) {
|
||||
val newWeight = value.toDoubleOrNull() ?: 0.0
|
||||
if (weight != newWeight) {
|
||||
weight = newWeight
|
||||
notifyPropertyChanged(BR.weightStr)
|
||||
onDataChanged?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港-装载申报/状态重置/删除申报 请求参数
|
||||
*/
|
||||
data class GjcDeclareParam(
|
||||
var dcode: String? = null, // 变更原因代码
|
||||
var dcontactsName: String? = null, // 联系人姓名
|
||||
var dcontactsTel: String? = null, // 联系人电话
|
||||
var maWbList: List<GjcMaWb>? = null, // 主单列表
|
||||
var haWbList: List<GjcHaWb>? = null, // 分单列表
|
||||
var loadList: List<GjcExportLoad>? = null // 装载记录列表
|
||||
)
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载Bean
|
||||
* 对应API: IntExpLoad/pageQuery
|
||||
*/
|
||||
class GjcExportLoad {
|
||||
var activeId: String = "" // 运单活跃号
|
||||
var by1: String = "" // 第一承运人
|
||||
var dep: String = "" // 始发港
|
||||
var fdate: String = "" // 申报航班日期
|
||||
var fid: String = "" // 航班主键id
|
||||
var fno: String = "" // 申报航班号
|
||||
var goods: String = "" // 品名
|
||||
var lastLoadMsgId: String = "" // 上一次装载申报编号
|
||||
var lastLoadStatus: String = "" // 上一次装载状态
|
||||
var loadMsgId: String = "" // 报文申报编号
|
||||
var loadStatus: String = "" // 装载申报状态("01"等状态码)
|
||||
var loaddCount: Int = 0 // 装载删除计次
|
||||
var loaddRate: Double = 0.0 // 装载删除费率
|
||||
var loadsCount: Int = 0 // 装载申报计次
|
||||
var loadsRate: Double = 0.0 // 装载申报费率
|
||||
var no: String = "" // 主运单号
|
||||
var packageType: String = "" // 包装类型代码
|
||||
var pc: Int = 0 // 件数
|
||||
var prefix: String = "" // 主运单前缀
|
||||
var response: String = "" // 海关业务回执
|
||||
var spCode: String = "" // 特码
|
||||
var splitFlag: String = "" // 分批标志
|
||||
var sysId: String = "" // 系统ID
|
||||
var tallyStatus: String = "" // 理货状态
|
||||
var weight: Double = 0.0 // 重量
|
||||
|
||||
// ========== UI扩展字段 ==========
|
||||
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
|
||||
|
||||
// 兼容现有API的isSelected属性
|
||||
var isSelected: Boolean
|
||||
get() = checked.get()
|
||||
set(value) = checked.set(value)
|
||||
|
||||
/**
|
||||
* 获取格式化的运单号(prefix + no)
|
||||
*/
|
||||
fun getFullWaybillNo(): String {
|
||||
return if (prefix.isNotEmpty()) "$prefix$no" else no
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取装载状态显示文字
|
||||
*/
|
||||
fun getLoadStatusText(): String {
|
||||
return when (loadStatus) {
|
||||
"01" -> "已申报"
|
||||
"02" -> "申报中"
|
||||
"03" -> "申报失败"
|
||||
"04" -> "已删除"
|
||||
else -> loadStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港货物交接单Bean
|
||||
*/
|
||||
data class GjcHandoverSheetBean(
|
||||
// ========== API文档字段 ==========
|
||||
var id: Long? = null, // 主键id
|
||||
var maWbId: Long? = null, // 运单主键id
|
||||
var no: String? = null, // 编号
|
||||
var prefix: String? = null, // 前缀
|
||||
var chargeWeight: Double? = null, // 计费重量
|
||||
var saleAgentCode: String? = null, // 销售代理人
|
||||
var expressName: String? = null, // 平台或快递企业名称
|
||||
var cbEcFlag: String? = null, // 是否为跨境电商货物(0:否;1:是)
|
||||
var opName: String? = null, // 经办人签名
|
||||
var opCardId: String? = null, // 经办人身份证号
|
||||
|
||||
// ========== 防止隐含危险品检查单 ==========
|
||||
var goodsName: String? = null, // 申报货物的品名为确指品名(0/1)
|
||||
var danger: String? = null, // 确认货物内不含未申报的危险品(0/1)
|
||||
var fish: String? = null, // 是否非观赏鱼类货物(0/1)
|
||||
var packaging: String? = null, // 包装件没有油渍或液体渗漏(0/1)
|
||||
var labels: String? = null, // 清除或涂去无关标记或标签(0/1)
|
||||
|
||||
// ========== 高风险货物检查单 ==========
|
||||
var appearance: String? = null, // 航空货物外观显现异常(0/1)
|
||||
var threat: String? = null, // 有具体情报显示威胁(0/1)
|
||||
var highRisk: String? = null, // 结论:是否可以判定为高风险货物(0/1)
|
||||
|
||||
// ========== 跨境电商检查单 ==========
|
||||
var submitStatement: String? = null, // 是否已提交声明(0/1/2: 是/否/不适用)
|
||||
|
||||
// ========== 货站收运人员 ==========
|
||||
var staOpName: String? = null, // 货站收运人员签名
|
||||
|
||||
// ========== 安检信息(用户手动填写) ==========
|
||||
var securityChannel: String? = null, // 安检机通道号
|
||||
var securityStartTime: String? = null, // 开始过机时间
|
||||
var securityEndTime: String? = null // 结束过机时间
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港货物交接单查询接口返回Bean
|
||||
*/
|
||||
data class GjcHandoverSheetResponse(
|
||||
var maWb: GjcMaWb? = null, // 主单信息
|
||||
var handoverSheet: GjcHandoverSheetBean? = null // 交接单信息(可能为null)
|
||||
)
|
||||
@@ -2,6 +2,9 @@ package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import com.lukouguoji.module_base.interfaces.ICheck
|
||||
import com.lukouguoji.module_base.ktx.noNull
|
||||
import dev.utils.DevFinal
|
||||
import dev.utils.common.DateUtils
|
||||
|
||||
/**
|
||||
* 国际出港收运检查数据Bean
|
||||
@@ -74,4 +77,32 @@ class GjcInspectionBean : ICheck {
|
||||
else -> "#9E9E9E" // 灰色-未审核
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预计起飞时间 - 仅时分格式 (HH:mm)
|
||||
*/
|
||||
val scheduledTackOffHM: String
|
||||
get() {
|
||||
return DateUtils.parseString(
|
||||
scheduledTackOff,
|
||||
DevFinal.TIME.yyyyMMddHHmmss_HYPHEN,
|
||||
"HH:mm"
|
||||
).noNull(scheduledTackOff)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证预计起飞时间是否为次日
|
||||
*/
|
||||
fun verifyScheduledTackOffNextDay(): Boolean {
|
||||
if (fdate.isEmpty() || scheduledTackOff.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return try {
|
||||
val calendarFDate = DateUtils.getCalendar(fdate, DevFinal.TIME.yyyyMMdd_HYPHEN)
|
||||
val calendarTakeOff = DateUtils.getCalendar(scheduledTackOff, DevFinal.TIME.yyyyMMddHHmmss_HYPHEN)
|
||||
DateUtils.getDay(calendarTakeOff) > DateUtils.getDay(calendarFDate)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* 国际出港主单数据模型
|
||||
* 对应接口:/IntExpSearch/pageQuery 返回的列表项
|
||||
*/
|
||||
data class GjcMaWb(
|
||||
// ==================== 主键与基础信息 ====================
|
||||
var maWbId: Long? = null, // 主单主键ID
|
||||
var wbNo: String? = null, // 11位运单号
|
||||
var prefix: String? = null, // 运单号前缀(3位)
|
||||
var no: String? = null, // 运单号主体(8位)
|
||||
var oldPrefix: String? = null, // 旧运单前缀
|
||||
var oldNo: String? = null, // 旧运单号
|
||||
|
||||
// ==================== 航班信息 ====================
|
||||
var fid: Long? = null, // 航班主键id
|
||||
var fno: String? = null, // 航班号
|
||||
var fdate: Date? = null, // 航班日期
|
||||
var flight: String? = null, // 航班: 航班日期/航班号
|
||||
var fclose: String? = null, // 航班关闭时间
|
||||
var scheduledTackOff: Date? = null, // 计划起飞时间
|
||||
var scheduledArrival: Date? = null, // 预计到达时间
|
||||
|
||||
// ==================== 目的地信息 ====================
|
||||
var dep: String? = null, // 始发站
|
||||
var dest: String? = null, // 最终目的站
|
||||
var dest1: String? = null, // 第一目的站
|
||||
var dest2: String? = null, // 第二目的站
|
||||
var range: String? = null, // 航程
|
||||
|
||||
// ==================== 代理与承运人 ====================
|
||||
var agentCode: String? = null, // 代理人code
|
||||
var agentName: String? = null, // 代理人名称
|
||||
var customsLib: String? = null, // 代理人lib
|
||||
var by0: String? = null, // 第一承运人
|
||||
var by1: String? = null, // 第二承运人
|
||||
var by2: String? = null, // 第三承运人
|
||||
|
||||
// ==================== 货物信息 ====================
|
||||
var pc: Long? = null, // 预配件数
|
||||
var weight: Double? = null, // 预配重量(KG)
|
||||
var volume: Double? = null, // 预配体积(CBM)
|
||||
var goods: String? = null, // 品名(英)
|
||||
var goodsCn: String? = null, // 品名(中)
|
||||
var packageType: String? = null, // 包装类型
|
||||
var cargoType: String? = null, // 货物类型
|
||||
var origin: String? = null, // 货源地
|
||||
|
||||
// ==================== 运抵信息 ====================
|
||||
var arrivePc: Long? = null, // 运抵件数
|
||||
var arriveWeight: Double? = null, // 运抵重量
|
||||
var arriveVolume: Double? = null, // 运抵体积
|
||||
var arriveFlag: String? = null, // 运抵状态(0:正常运抵,1:提前运抵)
|
||||
|
||||
// ==================== 特码与收货人 ====================
|
||||
var spCode: String? = null, // 特码
|
||||
var subCode: String? = null, // 子码
|
||||
var consignee: String? = null, // 收货人
|
||||
var cneeTel: String? = null, // 收货人电话
|
||||
|
||||
// ==================== 运单类型 ====================
|
||||
var awbType: String? = null, // 运单类型code
|
||||
var awbName: String? = null, // 运单类型名称(中)
|
||||
var businessType: String? = null, // 业务类型code
|
||||
var businessName: String? = null, // 业务类型名称(中)
|
||||
|
||||
// ==================== 车辆信息 ====================
|
||||
var carId: String? = null, // 平板车号
|
||||
var carNumber: String? = null, // 车牌号
|
||||
var passageWay: String? = null, // 通道号
|
||||
|
||||
// ==================== 状态信息 ====================
|
||||
var checkIn: String? = null, // 收运状态。0:待收运,1:已收运,2:收运中
|
||||
var declareStatus: String? = null, // 申报状态
|
||||
var reviewStatus: String? = null, // 审核状态(0:未审核;1:通过;2:退回)
|
||||
var tranFlag: String? = null, // 转运标志
|
||||
|
||||
// ==================== 操作信息 ====================
|
||||
var opDate: String? = null, // 操作时间(入库时间)
|
||||
var opId: String? = null, // 操作员id
|
||||
var paperTime: Date? = null, // 单证时间
|
||||
|
||||
// ==================== 备注与其他 ====================
|
||||
var remark: String? = null, // 备注
|
||||
var ffmMemo: String? = null, // ffm备注
|
||||
var mftMemo: String? = null, // mft备注
|
||||
var unNumber: String? = null, // UN编号
|
||||
var billsNo: String? = null, // 提单号
|
||||
var recheckCount: Long? = null, // 复核次数
|
||||
|
||||
// ==================== 地区信息 ====================
|
||||
var proName: String? = null, // 省份名称
|
||||
var cityName: String? = null, // 城市名称
|
||||
var areaName: String? = null, // 区域名称
|
||||
|
||||
// ==================== 关联数据统计 ====================
|
||||
var haWbNumber: Int? = null, // 分单数
|
||||
var storageUseNumber: Int? = null, // 库位使用数
|
||||
|
||||
// ==================== 活动标识 ====================
|
||||
var activeId: Long? = null, // 有效值
|
||||
|
||||
// ==================== 关联列表(非数据库字段,用于展示) ====================
|
||||
var haWbList: List<GjcHaWb>? = null, // 分单列表
|
||||
var storageUseList: List<GjcStorageUse>? = null, // 库位使用列表
|
||||
var attachList: List<ComAttach>? = null // 附件列表
|
||||
) {
|
||||
// ==================== UI扩展字段 ====================
|
||||
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
|
||||
|
||||
// 兼容现有API的isSelected属性
|
||||
var isSelected: Boolean
|
||||
get() = checked.get()
|
||||
set(value) = checked.set(value)
|
||||
|
||||
// ==================== 状态转换扩展属性 ====================
|
||||
/**
|
||||
* 计重状态中文
|
||||
* 0-待收运,1-已计重,2-计重中
|
||||
*/
|
||||
val checkInText: String
|
||||
get() = when (checkIn) {
|
||||
"0" -> "待收运"
|
||||
"1" -> "已计重"
|
||||
"2" -> "计重中"
|
||||
else -> checkIn ?: ""
|
||||
}
|
||||
|
||||
/**
|
||||
* 运抵状态中文
|
||||
* 0-正常运抵,1-提前运抵
|
||||
*/
|
||||
val arriveFlagText: String
|
||||
get() = when (arriveFlag) {
|
||||
"0" -> "正常运抵"
|
||||
"1" -> "提前运抵"
|
||||
else -> arriveFlag ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 国际出港分单数据模型
|
||||
*/
|
||||
data class GjcHaWb(
|
||||
var haWbId: Long? = null, // 主键ID
|
||||
var fid: Long? = null, // 航班主键
|
||||
var prefix: String? = null, // 前缀
|
||||
var no: String? = null, // 编号
|
||||
var hno: String? = null, // H编号
|
||||
var pc: Long? = null, // PC数量
|
||||
var weight: Double? = null, // 重量
|
||||
var volume: Double? = null, // 体积
|
||||
var hpc: Long? = null, // 分单数量
|
||||
var hweight: Double? = null, // 分单重量
|
||||
var hvolume: Double? = null, // 分单体积
|
||||
var goods: String? = null, // 货物英文
|
||||
var goodsCn: String? = null, // 货物中文
|
||||
var billsNo: String? = null, // 提单号
|
||||
var opDate: Date? = null, // 操作日期
|
||||
var opId: String? = null, // 操作人ID
|
||||
var remark: String? = null, // 备注
|
||||
// 发货人信息
|
||||
var consignorName: String? = null, // 发货人名称
|
||||
var consignorCode: String? = null, // 发货人代码
|
||||
var consignorAddress: String? = null, // 发货人地址
|
||||
var consignorCountryCode: String? = null, // 发货人国家代码
|
||||
var consignorComType: String? = null, // 发货人公司类型
|
||||
var consignorPnum: String? = null, // 发货人电话号码
|
||||
// 收货人信息
|
||||
var consigneeName: String? = null, // 收货人名称
|
||||
var consigneeCode: String? = null, // 收货人代码
|
||||
var consigneeAddress: String? = null, // 收货人地址
|
||||
var consigneeCountryCode: String? = null, // 收货人国家代码
|
||||
var consigneeComType: String? = null, // 收货人公司类型
|
||||
var consigneePnum: String? = null, // 收货人电话号码
|
||||
// 特殊收货人信息
|
||||
var speConsigneeName: String? = null, // 特殊收货人名称
|
||||
var speConsigneeComType: String? = null, // 特殊收货人公司类型
|
||||
var speConsigneePnum: String? = null, // 特殊收货人电话号码
|
||||
// 申报状态
|
||||
var mftStatus: String? = null, // 预配状态
|
||||
var mftMsgId: String? = null, // 预配消息ID
|
||||
var arrivalStatus: String? = null, // 运抵状态
|
||||
var arrMsgId: String? = null, // 运抵消息ID
|
||||
var tallyStatus: String? = null, // 理货状态
|
||||
var tallyMsgId: String? = null, // 理货消息ID
|
||||
var transferStatus: String? = null, // 传输状态
|
||||
var tranMsgId: String? = null, // 传输消息ID
|
||||
var cmdStatus: String? = null, // 命令状态
|
||||
var response: String? = null, // 响应
|
||||
// 最后状态
|
||||
var lastMftStatus: String? = null, // 最后预配状态
|
||||
var lastMftMsgId: String? = null, // 最后预配消息ID
|
||||
var lastArrStatus: String? = null, // 最后运抵状态
|
||||
var lastArrMsgId: String? = null, // 最后运抵消息ID
|
||||
var lastTallyStatus: String? = null, // 最后理货状态
|
||||
var lastTallyMsgId: String? = null, // 最后理货消息ID
|
||||
// 费率计次
|
||||
var mftSRate: Double? = null, // 预配申报费率
|
||||
var mftSCount: Double? = null, // 预配申报计次
|
||||
var mftDRate: Double? = null, // 预配删除费率
|
||||
var mftDCount: Double? = null, // 预配删除计次
|
||||
var arrivalSRate: Double? = null, // 运抵申报费率
|
||||
var arrivalSCount: Double? = null, // 运抵申报计次
|
||||
var arrivalDRate: Double? = null, // 运抵删除费率
|
||||
var arrivalDCount: Double? = null, // 运抵删除计次
|
||||
var tallySRate: Double? = null, // 出港理货申报费率
|
||||
var tallySCount: Double? = null, // 出港理货申报计次
|
||||
var tallyDRate: Double? = null, // 出港理货删除费率
|
||||
var tallyDCount: Double? = null, // 出港理货删除计次
|
||||
// 操作信息
|
||||
var arrivalOpDate: Date? = null, // 运抵操作日期
|
||||
var arrivalOpId: String? = null, // 运抵操作人ID
|
||||
var tallyOpDate: Date? = null, // 理货操作日期
|
||||
var tallyOpId: String? = null, // 理货操作人ID
|
||||
var declareCount: Long? = null, // 申报次数
|
||||
var activeId: Long? = null // 活动ID
|
||||
) {
|
||||
// ==================== UI扩展字段 ====================
|
||||
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
|
||||
|
||||
// 兼容现有API的isSelected属性
|
||||
var isSelected: Boolean
|
||||
get() = checked.get()
|
||||
set(value) = checked.set(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 库位使用记录
|
||||
*/
|
||||
data class GjcStorageUse(
|
||||
var id: Long? = null, // 主键
|
||||
var maWbId: Long? = null, // 运单id
|
||||
var prefix: String? = null, // 运单前缀
|
||||
var no: String? = null, // 运单号
|
||||
var storageCode: String? = null, // 库位号
|
||||
var inDate: Date? = null, // 入库时间
|
||||
var inId: String? = null, // 入库人
|
||||
var outDate: Date? = null, // 出库时间
|
||||
var outId: String? = null // 出库人
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* 国际出港查询参数封装类
|
||||
* 对应接口:/IntExpSearch/pageQuery
|
||||
*/
|
||||
data class GjcMostMouldPage(
|
||||
// ==================== 分页参数 ====================
|
||||
var pageNum: Int? = null, // 页号
|
||||
var pageSize: Int? = null, // 每页显示条数
|
||||
|
||||
// ==================== 基础搜索条件 ====================
|
||||
var fdate: Date? = null, // 航班日期
|
||||
var fno: String? = null, // 航班号
|
||||
var agentCode: String? = null, // 代理人code
|
||||
var outState: Int? = null, // 出库状态(0:未出库,1:已出库)
|
||||
var wbNo: String? = null, // 运单号(11位)
|
||||
var no: String? = null, // 运单号
|
||||
|
||||
// ==================== 筛选条件 ====================
|
||||
var spCode: String? = null, // 特码
|
||||
var dest: String? = null, // 目的港
|
||||
var awbType: String? = null, // 运单类型
|
||||
var businessType: String? = null, // 业务类型
|
||||
var goodsCn: String? = null, // 品名(中)
|
||||
|
||||
// ==================== 其他可选条件 ====================
|
||||
var beginDate: Date? = null, // 航班开始时间
|
||||
var endDate: Date? = null, // 航班结束时间
|
||||
var by1: String? = null, // 承运人
|
||||
var carId: String? = null, // 板车号
|
||||
var dest1: String? = null, // 卸货站
|
||||
var fdest: String? = null, // 目的站
|
||||
var handoverState: Int? = null, // 交接状态(0:未交接,1:已交接)
|
||||
var isFclose: Boolean? = null, // 筛选航班是否关闭
|
||||
var ldId: String? = null, // 组装人
|
||||
var likeNo: String? = null, // 运单号(模糊查询)
|
||||
var moveState: Int? = null, // 移库状态
|
||||
var prefix: String? = null, // 运单号前缀
|
||||
var uld: String? = null, // uld编号
|
||||
|
||||
// 分页辅助字段
|
||||
var startIndex: Int? = null,
|
||||
var endIndex: Int? = null
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import com.lukouguoji.module_base.interfaces.ICheck
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* 国际出港移库Bean
|
||||
*/
|
||||
data class GjcMove(
|
||||
var no: String = "", // ID
|
||||
var prefix: String = "", // 运单前缀
|
||||
var wbNo: String = "", // 运单号
|
||||
var pc: Long = 0, // 件数
|
||||
var weight: Double = 0.0, // 重量
|
||||
var volume: Double = 0.0, // 体积
|
||||
|
||||
var dep: String = "", // 起运港
|
||||
var dest: String = "", // 目的港
|
||||
var dest1: String = "", // 卸货站1
|
||||
var dest2: String = "", // 卸货站2
|
||||
var by1: String = "", // 承运人1
|
||||
var by2: String = "", // 承运人2
|
||||
|
||||
var awbType: String = "", // 运单类型编码
|
||||
var awbTypeName: String = "", // 运单类型名称
|
||||
var businessType: String = "", // 业务类型
|
||||
var moveState: Int = 0, // 移库状态(0-未移交,1-已移交)
|
||||
var goods: String = "", // 品名(英文)
|
||||
var goodsCn: String = "", // 品名(中文)
|
||||
var agentName: String = "", // 代理人
|
||||
var agentCode: String = "", // 代理代码
|
||||
var spCode: String = "", // SP代码
|
||||
var subCode: String = "", // 子代码
|
||||
var packageType: String = "", // 包装类型
|
||||
var cargoType: String = "", // 货物类型
|
||||
var origin: String = "", // 始发地
|
||||
|
||||
var maWbId: Long = 0, // GJC_MAWB.MAWBID
|
||||
var moveId: String = "", // 移动ID
|
||||
var opId: String = "", // 操作人ID
|
||||
var opdate: String = "", // 操作日期
|
||||
var remark: String = "", // 备注
|
||||
var likeNo: String = "", // 部分运单号no(模糊查询)
|
||||
|
||||
// UI扩展字段 - 使用ObservableBoolean实现自动UI更新
|
||||
val checked: ObservableBoolean = ObservableBoolean(false)
|
||||
) : Serializable, ICheck {
|
||||
|
||||
// 实现ICheck接口
|
||||
override fun getCheckObservable(): ObservableBoolean = checked
|
||||
|
||||
// 兼容现有代码的属性(如果其他地方使用isSelected)
|
||||
var isSelected: Boolean
|
||||
get() = checked.get()
|
||||
set(value) = checked.set(value)
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import androidx.databinding.ObservableBoolean
|
||||
|
||||
/**
|
||||
* 国际出港板箱过磅-ULD使用记录Bean
|
||||
* 对应API: IntExpWeighting/pageQuery
|
||||
@@ -14,6 +16,7 @@ class GjcUldUseBean {
|
||||
var netWeight: Double = 0.0 // 装机重量
|
||||
var totalWeight: Double = 0.0 // 总重
|
||||
var uldWeight: Double = 0.0 // uld重量
|
||||
var consumeWeight: Double = 0.0 // 耗材重量
|
||||
var volume: Double = 0.0 // 体积
|
||||
var maxVolume: Double = 0.0 // uld最大容积
|
||||
var maxWeight: Double = 0.0 // uld最大载重
|
||||
@@ -24,6 +27,10 @@ class GjcUldUseBean {
|
||||
var fdest: String = "" // 目的港
|
||||
var fClose: String = "" // 航班关闭时间
|
||||
|
||||
// 格式化后的航班日期(只保留年月日)
|
||||
val fdateFormatted: String
|
||||
get() = if (fdate.contains(" ")) fdate.split(" ")[0] else fdate
|
||||
|
||||
var wtId: String = "" // 过磅人ID
|
||||
var wtUsername: String = "" // 过磅人
|
||||
var wtDate: String = "" // 过磅时间
|
||||
@@ -51,4 +58,14 @@ class GjcUldUseBean {
|
||||
var remark: String = "" // 备注
|
||||
var checkFlag: String = "" // 检查标记
|
||||
var emptyUld: String = "" // 空ULD
|
||||
|
||||
// ========== 出港组装页面扩展字段 ==========
|
||||
var isExpanded: Boolean = false // 展开状态
|
||||
val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态(Observable)
|
||||
var waybillDetails: MutableList<GjcWarehouse>? = null // 运单明细缓存
|
||||
|
||||
// 兼容原有代码的isSelected属性
|
||||
var isSelected: Boolean
|
||||
get() = checked.get()
|
||||
set(value) = checked.set(value)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 国际出港-运单明细Bean
|
||||
* 对应API: IntExpAssemble/queryAssembled
|
||||
*/
|
||||
class GjcWarehouse {
|
||||
var whId: Long = 0 // ID
|
||||
var no: String = "" // 运单号(11位)
|
||||
var prefix: String = "" // 运单前缀
|
||||
var wbNo: String = "" // 主运单编号
|
||||
var pc: Long = 0 // 件数
|
||||
var weight: Double = 0.0 // 重量
|
||||
var volume: Double = 0.0 // 体积
|
||||
var agentCode: String = "" // 代理code
|
||||
var agentName: String = "" // 代理名称
|
||||
var dest: String = "" // 目的港
|
||||
var dest1: String = "" // 卸货站
|
||||
var dest2: String = "" // 第二目的地
|
||||
var dep: String = "" // 始发站
|
||||
var spCode: String = "" // 特码
|
||||
var goods: String = "" // 品名(英)
|
||||
var goodsCn: String = "" // 品名(中)
|
||||
var fdate: String = "" // 航班日期
|
||||
var fno: String = "" // 航班号
|
||||
var fclose: String = "" // 航班关闭时间
|
||||
var flight: String = "" // 航班:航班日期/航班号
|
||||
var range: String = "" // 航程
|
||||
var businessType: String = "" // 业务类型
|
||||
var opId: String = "" // 收运人ID
|
||||
var userName: String = "" // 收运人
|
||||
var opDate: String = "" // 收运时间
|
||||
var location: String = "" // uld
|
||||
var checkInPc: Long = 0 // 入库件数
|
||||
var checkInWeight: Double = 0.0 // 入库重量
|
||||
var assembleCount: Int = 0 // 已经组装的数量
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import com.lukouguoji.module_base.ktx.noNull
|
||||
import dev.utils.DevFinal
|
||||
import dev.utils.common.DateUtils
|
||||
|
||||
/**
|
||||
* 国际出港待计重-列表数据Bean
|
||||
* 对应API: IntExpCheckIn/pageQuery
|
||||
@@ -91,4 +95,32 @@ class GjcWeighingBean {
|
||||
var haWbList: List<Any>? = null // 分单列表
|
||||
var storageUseList: List<Any>? = null // 库位使用列表
|
||||
var attachList: List<Any>? = null // 附件列表
|
||||
|
||||
/**
|
||||
* 预计起飞时间 - 仅时分格式 (HH:mm)
|
||||
*/
|
||||
val scheduledTackOffHM: String
|
||||
get() {
|
||||
return DateUtils.parseString(
|
||||
scheduledTackOff,
|
||||
DevFinal.TIME.yyyyMMddHHmmss_HYPHEN,
|
||||
"HH:mm"
|
||||
).noNull(scheduledTackOff)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证预计起飞时间是否为次日
|
||||
*/
|
||||
fun verifyScheduledTackOffNextDay(): Boolean {
|
||||
if (fdate.isEmpty() || scheduledTackOff.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return try {
|
||||
val calendarFDate = DateUtils.getCalendar(fdate, DevFinal.TIME.yyyyMMdd_HYPHEN)
|
||||
val calendarTakeOff = DateUtils.getCalendar(scheduledTackOff, DevFinal.TIME.yyyyMMddHHmmss_HYPHEN)
|
||||
DateUtils.getDay(calendarTakeOff) > DateUtils.getDay(calendarFDate)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* 国际出港计重记录-列表数据Bean
|
||||
* 对应API: IntExpCheckIn/checked/pageQuery
|
||||
* 对应API返回类型: GjcWarehouse
|
||||
*/
|
||||
class GjcWeighingRecordBean {
|
||||
class GjcWeighingRecordBean : Serializable {
|
||||
var whId: Long = 0 // 仓库主键ID
|
||||
var no: String = "" // 运单号
|
||||
var prefix: String = "" // 运单前缀
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* 分页响应容器 (适配MyBatis-Plus的PageInfo结构)
|
||||
* 用于适配接口返回的PageInfo<T>结构
|
||||
*/
|
||||
class PageInfo<T> {
|
||||
// 当前页号
|
||||
var pageNum: Int = 1
|
||||
|
||||
// 每页显示条数
|
||||
var pageSize: Int = 10
|
||||
|
||||
// 数据总量
|
||||
var total: Long = 0
|
||||
|
||||
// 页面总量
|
||||
var pages: Int = 1
|
||||
|
||||
// 数据列表
|
||||
var list: ArrayList<T>? = null
|
||||
|
||||
// 是否有下一页
|
||||
var hasNextPage: Boolean = false
|
||||
|
||||
// 是否有上一页
|
||||
var hasPreviousPage: Boolean = false
|
||||
|
||||
// 是否是第一页
|
||||
var isFirstPage: Boolean = true
|
||||
|
||||
// 是否是最后一页
|
||||
var isLastPage: Boolean = false
|
||||
|
||||
/**
|
||||
* 转换为项目使用的BaseListBean
|
||||
* 这是核心方法,用于适配项目中的PageModel
|
||||
*/
|
||||
fun toBaseListBean(): BaseListBean<T> {
|
||||
return BaseListBean<T>().apply {
|
||||
this.pages = this@PageInfo.pages
|
||||
this.total = this@PageInfo.total.toInt()
|
||||
this.list = this@PageInfo.list
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* ULD信息Bean
|
||||
*/
|
||||
class UldInfoBean {
|
||||
var uldNo: String = "" // ULD编号
|
||||
var materialWeight: String = "" // 耗材重量
|
||||
var uldStatus: String = "" // ULD状态
|
||||
var planeType: String = "" // 机型
|
||||
var weightLimit: String = "" // 限重
|
||||
var totalPieces: String = "" // 总件数
|
||||
var totalWeight: String = "" // 总重量
|
||||
var status: String = "" // 状态(旧字段,保留兼容)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lukouguoji.module_base.bean
|
||||
|
||||
/**
|
||||
* 运单信息Bean
|
||||
*/
|
||||
class WaybillInfoBean {
|
||||
var waybillNo: String = "" // 运单号
|
||||
var waybillPieces: String = "" // 运单件数
|
||||
var waybillWeight: String = "" // 运单重量
|
||||
var assembleCount: String = "" // 组装件数
|
||||
var assembleWeight: String = "" // 组装重量
|
||||
var operator: String = "" // 操作人
|
||||
var pieces: String = "" // 件数(旧字段,保留兼容)
|
||||
var weight: String = "" // 重量(旧字段,保留兼容)
|
||||
var destination: String = "" // 目的港
|
||||
var specialCode: String = "" // 特码
|
||||
var goodsName: String = "" // 品名
|
||||
}
|
||||
@@ -244,6 +244,12 @@ interface Constant {
|
||||
const val GjcBanXListActivity = "AppIntExpBox" //板箱
|
||||
const val GjcGoodsListActivity = "AppIntExpGoods" //货物交接
|
||||
const val GjcInspectionActivity = "AppIntExpInspection" //收运检查
|
||||
const val GjcIntExpAssembleActivity = "AppIntExpAssemble" //出港组装
|
||||
const val GjcAssembleAllocateActivity = "AppIntExpAssembleAllocate" //组装分配
|
||||
const val GjcIntExpOutHandover = "AppIntExpOutHandover" //出库交接
|
||||
const val GjcIntExpLoad = "AppIntExpLoad" //出港装载
|
||||
const val GjcIntExpTally = "AppIntExpTally" //出港理货
|
||||
const val GjcIntExpArrive = "AppIntExpArrive" //出港运抵
|
||||
|
||||
/**
|
||||
* 国际进港
|
||||
@@ -354,5 +360,17 @@ interface Constant {
|
||||
|
||||
// 运单主键ID
|
||||
const val MAWB_ID = "maWbId"
|
||||
|
||||
// 运单前缀
|
||||
const val PREFIX = "prefix"
|
||||
|
||||
// 运单号
|
||||
const val NO = "no"
|
||||
|
||||
// 操作时间
|
||||
const val OP_DATE = "opDate"
|
||||
|
||||
// Bean对象传递
|
||||
const val BEAN = "bean"
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,43 @@
|
||||
//package com.lukouguoji.module_base.http.net
|
||||
package com.lukouguoji.module_base.http.net
|
||||
|
||||
import com.alibaba.fastjson.JSONObject
|
||||
import com.lukouguoji.module_base.bean.AccidentVisaBean
|
||||
import com.lukouguoji.module_base.bean.AirportBean
|
||||
import com.lukouguoji.module_base.bean.AppUpdateResponse
|
||||
import com.lukouguoji.module_base.bean.AppUpdateResponseInfo
|
||||
import com.lukouguoji.module_base.bean.AssembleCompanyBean
|
||||
import com.lukouguoji.module_base.bean.BaseListBean
|
||||
import com.lukouguoji.module_base.bean.BaseResultBean
|
||||
import com.lukouguoji.module_base.bean.BoxDetailsForCarIdBean
|
||||
import com.lukouguoji.module_base.bean.CarBarBean
|
||||
import com.lukouguoji.module_base.bean.CarOrUldBean
|
||||
import com.lukouguoji.module_base.bean.DiBangChannelBean
|
||||
import com.lukouguoji.module_base.bean.DictBean
|
||||
import com.lukouguoji.module_base.bean.DictIdValueBean
|
||||
import com.lukouguoji.module_base.bean.DictListBean
|
||||
import com.lukouguoji.module_base.bean.DictLocationBean
|
||||
import com.lukouguoji.module_base.bean.DocumentHandoverBean
|
||||
import com.lukouguoji.module_base.bean.FlatcarBean
|
||||
import com.lukouguoji.module_base.bean.FlightBean
|
||||
import com.lukouguoji.module_base.bean.FlightFilterBean
|
||||
import com.lukouguoji.module_base.bean.GbCarOrUldBean
|
||||
import com.lukouguoji.module_base.bean.GjcAssembleAllocate
|
||||
import com.lukouguoji.module_base.bean.GjcAssembled
|
||||
import com.lukouguoji.module_base.bean.GjcBoxAddInsertBean
|
||||
import com.lukouguoji.module_base.bean.GjcBoxAssembleBean
|
||||
import com.lukouguoji.module_base.bean.GjcBoxDetailsBean
|
||||
import com.lukouguoji.module_base.bean.GjcBoxWeighingStatisticsBean
|
||||
import com.lukouguoji.module_base.bean.GjcCheckInRecord
|
||||
import com.lukouguoji.module_base.bean.GjcExportLoad
|
||||
import com.lukouguoji.module_base.bean.GjcGoodsAddBean
|
||||
import com.lukouguoji.module_base.bean.GjcGoodsBean
|
||||
import com.lukouguoji.module_base.bean.GjcGoodsDetailsBean
|
||||
import com.lukouguoji.module_base.bean.GjcHandoverSheetResponse
|
||||
import com.lukouguoji.module_base.bean.GjcInspectionBean
|
||||
import com.lukouguoji.module_base.bean.GjcMaWb
|
||||
import com.lukouguoji.module_base.bean.GjcMove
|
||||
import com.lukouguoji.module_base.bean.GjcUldUseBean
|
||||
import com.lukouguoji.module_base.bean.GjcWarehouse
|
||||
import com.lukouguoji.module_base.bean.GjcWaybillBean
|
||||
import com.lukouguoji.module_base.bean.GjcWaybillDataBean
|
||||
import com.lukouguoji.module_base.bean.GjcWeighingBean
|
||||
@@ -40,15 +51,11 @@ import com.lukouguoji.module_base.bean.GjjManifestBean
|
||||
import com.lukouguoji.module_base.bean.GjjPackTypeBean
|
||||
import com.lukouguoji.module_base.bean.GjjTallyBean
|
||||
import com.lukouguoji.module_base.bean.GjjTallyDetailsBean
|
||||
import com.lukouguoji.module_base.bean.JianDataBean
|
||||
import com.lukouguoji.module_base.bean.PacketParseBean
|
||||
import com.lukouguoji.module_base.bean.GjjTallyRecordBean
|
||||
import com.lukouguoji.module_base.bean.GncAssembleListBean
|
||||
import com.lukouguoji.module_base.bean.GncCunFangBean
|
||||
import com.lukouguoji.module_base.bean.GncDistributionBean
|
||||
import com.lukouguoji.module_base.bean.GncFuBangBean
|
||||
import com.lukouguoji.module_base.bean.GjcInspectionBean
|
||||
import com.lukouguoji.module_base.bean.ManifestTotalDto
|
||||
import com.lukouguoji.module_base.bean.GncInspectionBean
|
||||
import com.lukouguoji.module_base.bean.GncQueryBean
|
||||
import com.lukouguoji.module_base.bean.GncQueryDetailsBean
|
||||
@@ -62,10 +69,14 @@ import com.lukouguoji.module_base.bean.GnjStashBean
|
||||
import com.lukouguoji.module_base.bean.GnjUnloadListBean
|
||||
import com.lukouguoji.module_base.bean.GnjYiKuBean
|
||||
import com.lukouguoji.module_base.bean.GoodsTransportBean
|
||||
import com.lukouguoji.module_base.bean.JianDataBean
|
||||
import com.lukouguoji.module_base.bean.LogBean
|
||||
import com.lukouguoji.module_base.bean.ManifestTotalDto
|
||||
import com.lukouguoji.module_base.bean.MessageBean
|
||||
import com.lukouguoji.module_base.bean.MoveStashBean
|
||||
import com.lukouguoji.module_base.bean.PackageBean
|
||||
import com.lukouguoji.module_base.bean.PacketParseBean
|
||||
import com.lukouguoji.module_base.bean.PageInfo
|
||||
import com.lukouguoji.module_base.bean.SYWaybillBean
|
||||
import com.lukouguoji.module_base.bean.ShouYunSyncBean
|
||||
import com.lukouguoji.module_base.bean.SimpleResultBean
|
||||
@@ -81,8 +92,15 @@ import com.lukouguoji.module_base.ktx.toRequestBody
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.*
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Multipart
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Part
|
||||
import retrofit2.http.PartMap
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
|
||||
/**
|
||||
* @author:孟凡华
|
||||
@@ -144,6 +162,11 @@ interface Api {
|
||||
@GET("typeCode/searchDateType")
|
||||
suspend fun getDictList(@Query("code") code: String): BaseResultBean<List<DictIdValueBean>>
|
||||
|
||||
/**
|
||||
* 获取字典列表 - location接口
|
||||
*/
|
||||
@GET("typeCode/locationByCode")
|
||||
suspend fun getDictListByLocation(@Query("code") code: String): BaseResultBean<List<DictLocationBean>>
|
||||
|
||||
/**
|
||||
* 获取字典列表----根据用户角色选择转运类型
|
||||
@@ -276,6 +299,12 @@ interface Api {
|
||||
@POST("eqm/uld/queryUld")
|
||||
suspend fun getUldDetails(@Query("id") id: String): BaseResultBean<ULDBean>
|
||||
|
||||
/**
|
||||
* 根据ULD编号查询ULD信息(新接口)
|
||||
*/
|
||||
@GET("eqm/uld/queryUld")
|
||||
suspend fun queryUldByCode(@Query("uld") uld: String): BaseResultBean<ULDBean>
|
||||
|
||||
/**
|
||||
* 获取运单信息 - 国际出
|
||||
*/
|
||||
@@ -405,7 +434,10 @@ interface Api {
|
||||
* 接口路径: /IntExpCheckInCheck/back
|
||||
*/
|
||||
@POST("IntExpCheckInCheck/back")
|
||||
suspend fun backGjcInspection(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
suspend fun backGjcInspection(
|
||||
@Query("reason") reason: String,
|
||||
@Body data: RequestBody
|
||||
): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 条件查询-国际出港-收运审核-统计数据(总件数、总重量、运单总数)
|
||||
@@ -414,6 +446,80 @@ interface Api {
|
||||
@POST("IntExpCheckInCheck/pageQueryTotal")
|
||||
suspend fun getGjcInspectionTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港收运审核-交接单-获取交接单内容
|
||||
* 接口路径: /IntExpCheckInCheck/queryHandoverSheet
|
||||
*/
|
||||
@GET("IntExpCheckInCheck/queryHandoverSheet")
|
||||
suspend fun queryHandoverSheet(@Query("maWbId") maWbId: Long): BaseResultBean<GjcHandoverSheetResponse>
|
||||
|
||||
/**
|
||||
* 国际出港收运审核-交接单-保存
|
||||
* 接口路径: /IntExpCheckInCheck/saveHandoverSheet
|
||||
*/
|
||||
@POST("IntExpCheckInCheck/saveHandoverSheet")
|
||||
suspend fun saveHandoverSheet(@Body data: RequestBody): BaseResultBean<Long>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 国际出 - 查询
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* 国际出港查询-分页查询
|
||||
* 接口路径: /IntExpSearch/pageQuery
|
||||
*/
|
||||
@POST("IntExpSearch/pageQuery")
|
||||
suspend fun getGjcQueryList(@Body data: RequestBody): PageInfo<GjcMaWb>
|
||||
|
||||
/**
|
||||
* 国际出港查询-分页合计统计
|
||||
* 接口路径: /IntExpSearch/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpSearch/pageQueryTotal")
|
||||
suspend fun getGjcQueryTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港运单修改
|
||||
* 接口路径: /IntExpSearch/update
|
||||
*/
|
||||
@POST("IntExpSearch/update")
|
||||
suspend fun updateGjcMaWb(@Body data: RequestBody): BaseResultBean<Any>
|
||||
|
||||
/**
|
||||
* 国际出港查询-详情
|
||||
* 接口路径: /IntExpSearch/detail
|
||||
* 参数: maWbId (Long)
|
||||
*/
|
||||
@POST("IntExpSearch/detail")
|
||||
suspend fun getGjcQueryDetails(@Query("maWbId") maWbId: Long): BaseResultBean<Map<String, Any>>
|
||||
|
||||
/**
|
||||
* 国际出港组装分配-分页查询
|
||||
* 接口路径: /IntExpAssemble/allocate/pageQuery
|
||||
*/
|
||||
@POST("IntExpAssemble/allocate/pageQuery")
|
||||
suspend fun getGjcAssembleAllocateList(@Body params: RequestBody): PageInfo<GjcAssembleAllocate>
|
||||
|
||||
/**
|
||||
* 国际出港组装分配-分页合计统计
|
||||
* 接口路径: /IntExpAssemble/allocate/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpAssemble/allocate/pageQueryTotal")
|
||||
suspend fun getGjcAssembleAllocateTotal(@Body params: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港组装分配-执行分配操作
|
||||
* 接口路径: /IntExpAssemble/allocate
|
||||
*/
|
||||
@POST("IntExpAssemble/allocate")
|
||||
suspend fun allocateAssemble(@Body params: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 获取组装公司下拉列表
|
||||
* 接口路径: /typeCode/assembleCompany
|
||||
*/
|
||||
@POST("typeCode/assembleCompany")
|
||||
suspend fun getAssembleCompanyList(): BaseResultBean<List<AssembleCompanyBean>>
|
||||
|
||||
/**
|
||||
* 国际出港板箱过磅-分页搜索
|
||||
* 接口路径: /IntExpWeighting/pageQuery
|
||||
@@ -442,6 +548,263 @@ interface Api {
|
||||
@POST("IntExpWeighting/weight")
|
||||
suspend fun submitGjcBoxWeighing(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
|
||||
|
||||
// ==================== 国际出港-出港组装 ====================
|
||||
|
||||
/**
|
||||
* 国际出港组装-分页查询已组装的ULD列表
|
||||
* 接口路径: /IntExpAssemble/pageQuery
|
||||
*/
|
||||
@POST("IntExpAssemble/pageQuery")
|
||||
suspend fun getIntExpAssembleList(@Body data: RequestBody): BaseListBean<GjcUldUseBean>
|
||||
|
||||
/**
|
||||
* 国际出港组装-分页合计统计数据
|
||||
* 接口路径: /IntExpAssemble/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpAssemble/pageQueryTotal")
|
||||
suspend fun getIntExpAssembleTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港组装-根据板箱组装记录查询运单明细
|
||||
* 接口路径: /IntExpAssemble/queryAssembled
|
||||
* @param data 请求参数:useId(ULD使用ID)
|
||||
*/
|
||||
@POST("IntExpAssemble/queryAssembled")
|
||||
suspend fun getIntExpAssembleWaybillDetails(@Body data: RequestBody): BaseResultBean<MutableList<GjcWarehouse>>
|
||||
|
||||
/**
|
||||
* 国际出港组装-删除记录
|
||||
* 接口路径: /IntExpAssemble/delete
|
||||
* @param ids ULD使用记录ID,多个用逗号分隔
|
||||
*/
|
||||
@POST("IntExpAssemble/delete")
|
||||
suspend fun deleteIntExpAssemble(@Query("ids") ids: String): BaseResultBean<SimpleResultBean>
|
||||
|
||||
/**
|
||||
* 国际出港组装-回填重量
|
||||
* 接口路径: /IntExpAssemble/backfillWeight
|
||||
* @param data 请求参数:ids(ULD使用记录ID,逗号分隔)、weight(重量)
|
||||
*/
|
||||
@POST("IntExpAssemble/backfillWeight")
|
||||
suspend fun backfillIntExpAssembleWeight(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 获取组装人列表
|
||||
* 接口路径: /IntExpAssemble/pageQueryAssembler
|
||||
*/
|
||||
@GET("IntExpAssemble/pageQueryAssembler")
|
||||
suspend fun getIntExpAssemblerList(): BaseResultBean<List<String>>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 查询待组装运单列表
|
||||
* 接口路径: /IntExpAssemble/queryWaitingAssemble
|
||||
*/
|
||||
@GET("IntExpAssemble/queryWaitingAssemble")
|
||||
suspend fun queryWaitingAssemble(@Query("wbNo") wbNo: String): BaseResultBean<MutableList<GjcWarehouse>>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 根据全ULD查询ULD状态和耗材重量
|
||||
* 接口路径: /IntExpAssemble/getUld
|
||||
* @param uld ULD编号
|
||||
* @return ULD信息,包含status(0:正常,1:故障)和consumeWeight(耗材重量)
|
||||
*/
|
||||
@GET("IntExpAssemble/getUld")
|
||||
suspend fun getUldWithConsumeWeight(@Query("uld") uld: String): BaseResultBean<GjcUldUseBean>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 卸货
|
||||
* 接口路径: /IntExpAssemble/drop
|
||||
* @param data 请求参数:abPc(组装件数)、abWeight(组装重量)、consumeWeight(耗材重量)、
|
||||
* ldId(组装人)、loadArea(组装区)、useInfo(ULD信息)、wbInfo(运单信息)、userId(用户ID)
|
||||
*/
|
||||
@POST("IntExpAssemble/drop")
|
||||
suspend fun assembleDropCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 装货
|
||||
* 接口路径: /IntExpAssemble/assemble
|
||||
* @param data 请求参数:abPc(组装件数)、abWeight(组装重量)、consumeWeight(耗材重量)、
|
||||
* ldId(组装人)、loadArea(组装区)、useInfo(ULD信息)、wbInfo(运单信息)、userId(用户ID)
|
||||
*/
|
||||
@POST("IntExpAssemble/assemble")
|
||||
suspend fun assembleLoadCargo(@Body data: RequestBody): BaseResultBean<GjcWarehouse>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 查询已组装的ULD列表
|
||||
* 接口路径: /IntExpAssemble/queryAssembled
|
||||
* @param data 请求参数:fno(航班号,必填)、fdate(航班日期,必填)、
|
||||
* loadArea(组装位置,必填)、uld(ULD编号,可选)
|
||||
* @return 返回已组装的ULD列表(包含ULD信息和运单列表)
|
||||
*/
|
||||
@POST("IntExpAssemble/queryAssembled")
|
||||
suspend fun getAssembledList(@Body data: RequestBody): BaseResultBean<List<GjcAssembled>>
|
||||
|
||||
/**
|
||||
* 国际出港组装 - 根据ULD查询已组装的运单列表
|
||||
* 接口路径: /IntExpAssemble/queryAssembledByUld
|
||||
* @param data 请求参数:GjcUldUseBean对象(包含useId、uld等信息)
|
||||
* @return 返回该ULD下的运单列表
|
||||
*/
|
||||
@POST("IntExpAssemble/queryAssembledByUld")
|
||||
suspend fun getAssembledWaybillsByUld(@Body data: RequestBody): BaseResultBean<List<GjcWarehouse>>
|
||||
|
||||
/**
|
||||
* 国际出港出库交接-分页查询
|
||||
* 接口路径: /IntExpOutHandover/pageQuery
|
||||
*/
|
||||
@POST("IntExpOutHandover/pageQuery")
|
||||
suspend fun getIntExpOutHandoverList(@Body data: RequestBody): BaseListBean<GjcUldUseBean>
|
||||
|
||||
/**
|
||||
* 国际出港出库交接-分页合计
|
||||
* 接口路径: /IntExpOutHandover/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpOutHandover/pageQueryTotal")
|
||||
suspend fun getIntExpOutHandoverTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港出库交接-完成交接
|
||||
* 接口路径: /IntExpOutHandover/handover
|
||||
* @param data 请求参数:选中的ULD列表
|
||||
*/
|
||||
@POST("IntExpOutHandover/handover")
|
||||
suspend fun completeHandover(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载 分页查询
|
||||
* 接口路径: /IntExpLoad/pageQuery
|
||||
*/
|
||||
@POST("IntExpLoad/pageQuery")
|
||||
suspend fun getIntExpLoadList(@Body data: RequestBody): BaseListBean<GjcExportLoad>
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载 分页合计
|
||||
* 接口路径: /IntExpLoad/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpLoad/pageQueryTotal")
|
||||
suspend fun getIntExpLoadTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载 状态重置
|
||||
* 接口路径: /IntExpLoad/resetDeclare
|
||||
*/
|
||||
@POST("IntExpLoad/resetDeclare")
|
||||
suspend fun resetDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载 装载申报
|
||||
* 接口路径: /IntExpLoad/declare
|
||||
*/
|
||||
@POST("IntExpLoad/declare")
|
||||
suspend fun declareLoad(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港运抵-分页列表
|
||||
* 接口路径: /IntExpArrive/pageQuery
|
||||
*/
|
||||
@POST("IntExpArrive/pageQuery")
|
||||
suspend fun getIntExpArriveList(@Body data: RequestBody): BaseListBean<GjcMaWb>
|
||||
|
||||
/**
|
||||
* 国际出港运抵-分页合计
|
||||
* 接口路径: /IntExpArrive/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpArrive/pageQueryTotal")
|
||||
suspend fun getIntExpArriveTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港运抵-重置运抵申报状态
|
||||
* 接口路径: /IntExpArrive/resetDeclare
|
||||
* @param data 请求参数:选中的运单列表
|
||||
*/
|
||||
@POST("IntExpArrive/resetDeclare")
|
||||
suspend fun resetArriveDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港运抵-运抵申报(分单+主单)
|
||||
* 接口路径: /IntExpArrive/declare
|
||||
* @param data 请求参数:选中的运单列表
|
||||
*/
|
||||
@POST("IntExpArrive/declare")
|
||||
suspend fun arriveDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货-列表查询
|
||||
* 接口路径: /IntExpTally/pageQuery
|
||||
* 返回: PageInfo<GjcMaWb>
|
||||
*/
|
||||
@POST("IntExpTally/pageQuery")
|
||||
suspend fun getIntExpTallyList(@Body data: RequestBody): BaseListBean<GjcMaWb>
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货-统计查询
|
||||
* 接口路径: /IntExpTally/pageQueryTotal
|
||||
* 返回: ManifestTotalDto(合计票数、总件数、总重量)
|
||||
*/
|
||||
@POST("IntExpTally/pageQueryTotal")
|
||||
suspend fun getIntExpTallyTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货-理货申报
|
||||
* 接口路径: /IntExpTally/declare
|
||||
* @param data 请求参数:选中的GjcMaWb列表
|
||||
*/
|
||||
@POST("IntExpTally/declare")
|
||||
suspend fun declareTally(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货-状态重置
|
||||
* 接口路径: /IntExpTally/resetDeclare
|
||||
* @param data 请求参数:选中的GjcMaWb列表
|
||||
*/
|
||||
@POST("IntExpTally/resetDeclare")
|
||||
suspend fun resetTallyDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货-删除理货申报
|
||||
* 接口路径: /IntExpTally/deleteDeclare
|
||||
* @param data 请求参数:GjcDeclareParam
|
||||
*/
|
||||
@POST("IntExpTally/deleteDeclare")
|
||||
suspend fun deleteTallyDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载-删除装载申报
|
||||
* 接口路径: /IntExpLoad/deleteDeclare
|
||||
* @param data 请求参数:GjcDeclareParam
|
||||
*/
|
||||
@POST("IntExpLoad/deleteDeclare")
|
||||
suspend fun deleteLoadDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港-出港运抵-删除运抵申报
|
||||
* 接口路径: /IntExpArrive/deleteDeclare
|
||||
* @param data 请求参数:GjcDeclareParam
|
||||
*/
|
||||
@POST("IntExpArrive/deleteDeclare")
|
||||
suspend fun deleteArriveDeclare(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港移库-分页查询
|
||||
* 接口路径: /IntExpMove/pageQuery
|
||||
*/
|
||||
@POST("IntExpMove/pageQuery")
|
||||
suspend fun getIntExpMoveList(@Body data: RequestBody): BaseListBean<GjcMove>
|
||||
|
||||
/**
|
||||
* 国际出港移库-分页合计
|
||||
* 接口路径: /IntExpMove/pageQueryTotal
|
||||
*/
|
||||
@POST("IntExpMove/pageQueryTotal")
|
||||
suspend fun getIntExpMoveTotal(@Body data: RequestBody): BaseResultBean<ManifestTotalDto>
|
||||
|
||||
/**
|
||||
* 国际出港移库-批量移库
|
||||
* 接口路径: /IntExpMove/move
|
||||
*/
|
||||
@POST("IntExpMove/move")
|
||||
suspend fun submitIntExpMove(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
|
||||
|
||||
/**
|
||||
* 国际出港待计重-分页搜索
|
||||
* 接口路径: /IntExpCheckIn/pageQuery
|
||||
@@ -456,6 +819,23 @@ interface Api {
|
||||
@POST("IntExpCheckIn/pageQueryTotal")
|
||||
suspend fun getGjcWeighingStatistics(@Body data: RequestBody): BaseResultBean<GjcWeighingStatisticsBean>
|
||||
|
||||
/**
|
||||
* 国际出港待计重-开始计重-根据wbId查询详情
|
||||
* 接口路径: /IntExpCheckIn/queryWbById
|
||||
* @param maWbId 运单主键ID
|
||||
*/
|
||||
@POST("IntExpCheckIn/queryWbById")
|
||||
suspend fun getIntExpCheckInWbById(@Query("maWbId") maWbId: Long): BaseResultBean<GjcMaWb>
|
||||
|
||||
/**
|
||||
* 国际出港待计重-开始计重-根据运单id查询实时计重数据
|
||||
* 接口路径: /IntExpCheckIn/queryRecordByWh
|
||||
* @param maWbId 运单主键ID
|
||||
* @return 返回GjcCheckInRecord,包含实时的pc、weight、volume
|
||||
*/
|
||||
@POST("IntExpCheckIn/queryRecordByWh")
|
||||
suspend fun getIntExpRealTimeRecord(@Query("maWbId") maWbId: Long): BaseResultBean<GjcCheckInRecord>
|
||||
|
||||
/**
|
||||
* 国际出港计重记录-分页搜索
|
||||
* 接口路径: /IntExpCheckIn/checked/pageQuery
|
||||
@@ -477,6 +857,29 @@ interface Api {
|
||||
@POST("IntExpCheckIn/completeCheckIn")
|
||||
suspend fun completeCheckIn(@Body data: RequestBody): BaseResultBean<Boolean>
|
||||
|
||||
/**
|
||||
* 国际出港待计重-开始计重-分托计重
|
||||
* 接口路径: /IntExpCheckIn/splitCheckIn
|
||||
*/
|
||||
@POST("IntExpCheckIn/splitCheckIn")
|
||||
suspend fun splitCheckIn(@Body data: RequestBody): BaseResultBean<Long>
|
||||
|
||||
/**
|
||||
* 国际出港计重明细-根据运单号查询所有计重记录
|
||||
* 接口路径: /IntExpCheckIn/listRecordByWh
|
||||
* 参数: GjcWarehouse对象(prefix, no, opDate)
|
||||
*/
|
||||
@POST("IntExpCheckIn/listRecordByWh")
|
||||
suspend fun getGjcCheckInRecordList(@Body data: RequestBody): BaseResultBean<List<GjcCheckInRecord>>
|
||||
|
||||
/**
|
||||
* 国际出港计重明细-批量更新计重记录
|
||||
* 接口路径: /IntExpCheckIn/updateRecordList
|
||||
* 参数: List<GjcCheckInRecord>
|
||||
*/
|
||||
@POST("IntExpCheckIn/updateRecordList")
|
||||
suspend fun updateGjcCheckInRecordList(@Body data: List<GjcCheckInRecord>): BaseResultBean<Boolean>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 国际进-电报解析
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -692,6 +1095,12 @@ interface Api {
|
||||
@POST("flt/queryFlightById")
|
||||
suspend fun getFlightDetails(@Query("id") id: String): BaseResultBean<FlightBean>
|
||||
|
||||
/**
|
||||
* 根据航班日期和航班号查询航班
|
||||
*/
|
||||
@POST("flt/queryFlight")
|
||||
suspend fun queryFlightByDateAndNo(@Body data: RequestBody): BaseResultBean<FlightBean>
|
||||
|
||||
/**
|
||||
* 获取航班目的站、经停站
|
||||
*/
|
||||
@@ -969,6 +1378,7 @@ interface Api {
|
||||
*/
|
||||
@POST
|
||||
suspend fun getWbNoList(@Url url: String, @Body data: RequestBody): BaseResultBean<List<String>>
|
||||
|
||||
/**
|
||||
* 获取-国内出港-分配-列表
|
||||
*/
|
||||
@@ -987,6 +1397,7 @@ interface Api {
|
||||
*/
|
||||
@POST("flt/searchHandoverByFid")
|
||||
suspend fun getHandover(@Query("fid") fid: String): BaseResultBean<FlightBean>
|
||||
|
||||
/**
|
||||
* 获取-国内出港-存放-列表
|
||||
*/
|
||||
@@ -1043,7 +1454,6 @@ interface Api {
|
||||
fun queryWbDetailById(@Query("wbId") wbId: Int): BaseResultBean<GncShouYunBean>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取-货物转运-列表
|
||||
*/
|
||||
@@ -1091,13 +1501,19 @@ interface Api {
|
||||
*/
|
||||
@POST("DomTransportLog/search")
|
||||
suspend fun getTransportLogList(@Body data: RequestBody): BaseListBean<TransportLogBean>
|
||||
|
||||
/**
|
||||
* 国内 单证交接 列表
|
||||
*/
|
||||
@POST("flt/searchHandoverPage")
|
||||
suspend fun getDocumentHandoverList(@Body data: RequestBody): BaseListBean<DocumentHandoverBean>
|
||||
|
||||
/**
|
||||
* 获取删除原因列表
|
||||
*/
|
||||
@POST("typeCode/delReason")
|
||||
suspend fun getDelReasonList(@Query("needFormat") needFormat: Boolean = true): BaseResultBean<List<DictBean>>
|
||||
|
||||
@GET("file/verifyVersion")
|
||||
suspend fun getAppUpdate(@Query("versionCode") versionCode : Int): AppUpdateResponse<AppUpdateResponseInfo>
|
||||
suspend fun getAppUpdate(@Query("versionCode") versionCode: Int): AppUpdateResponse<AppUpdateResponseInfo>
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.lukouguoji.module_base.ktx
|
||||
|
||||
import android.text.InputFilter
|
||||
import android.text.Spanned
|
||||
import android.widget.EditText
|
||||
import androidx.databinding.BindingAdapter
|
||||
|
||||
@@ -12,4 +13,47 @@ fun setTextAllCaps(et: EditText, allCaps: Boolean) {
|
||||
} else {
|
||||
et.filters = emptyArray<InputFilter>()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 大写字母和数字输入过滤器
|
||||
* 只允许输入大写字母(A-Z)和数字(0-9),小写字母自动转为大写
|
||||
*/
|
||||
class UpperCaseAlphanumericInputFilter : InputFilter {
|
||||
override fun filter(
|
||||
source: CharSequence?,
|
||||
start: Int,
|
||||
end: Int,
|
||||
dest: Spanned?,
|
||||
dstart: Int,
|
||||
dend: Int
|
||||
): CharSequence? {
|
||||
if (source.isNullOrEmpty()) return null
|
||||
|
||||
val filtered = StringBuilder()
|
||||
for (i in start until end) {
|
||||
val char = source[i]
|
||||
// 只允许ASCII字母(A-Z, a-z)和数字(0-9)
|
||||
if (char in 'A'..'Z' || char in 'a'..'z' || char in '0'..'9') {
|
||||
// 自动转为大写
|
||||
filtered.append(char.uppercaseChar())
|
||||
}
|
||||
}
|
||||
|
||||
// 如果过滤后的内容与原内容相同,返回null表示不修改
|
||||
// 否则返回过滤后的内容
|
||||
return if (filtered.toString() == source.subSequence(start, end).toString()) {
|
||||
null
|
||||
} else {
|
||||
filtered.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 EditText 设置大写字母和数字输入过滤器
|
||||
* 使用方式: editText.setUpperCaseAlphanumericFilter()
|
||||
*/
|
||||
fun EditText.setUpperCaseAlphanumericFilter() {
|
||||
this.filters = arrayOf(UpperCaseAlphanumericInputFilter())
|
||||
}
|
||||
@@ -122,12 +122,15 @@ object ARouterConstants {
|
||||
const val ACTIVITY_URL_GJC_WEIGHING_LIST = "/gjc/GjcWeighingListActivity" //国际出港模块 出港计重
|
||||
const val ACTIVITY_URL_GJC_WEIGHING_START = "/gjc/GjcWeighingStartActivity" //国际出港模块 开始计重
|
||||
const val ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST = "/gjc/GjcWeighingRecordListActivity" //国际出港模块 计重记录
|
||||
const val ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS = "/gjc/GjcWeighingRecordDetailsActivity" //国际出港模块 计重明细
|
||||
|
||||
const val ACTIVITY_URL_GJC_WARE_HOUSE = "/gjc/GjcWareHouseActivity" //国际出港模块 仓库
|
||||
const val ACTIVITY_URL_GJC_WARE_HOUSE_INFO = "/gjc/GjcWareHouseInfoActivity" //国际出港模块 仓库详情
|
||||
|
||||
const val ACTIVITY_URL_GJC_QUERY_LIST = "/gjc/GjcQueryListActivity" //国际出港模块 查询
|
||||
const val ACTIVITY_URL_GJC_QUERY_INFO = "/gjc/GjcQueryInfoActivity" //国际出港模块 详情
|
||||
const val ACTIVITY_URL_GJC_QUERY_DETAILS = "/gjc/GjcQueryDetailsActivity" //国际出港模块 查询详情
|
||||
const val ACTIVITY_URL_GJC_QUERY_EDIT = "/gjc/GjcQueryEditActivity" //国际出港模块 运单修改
|
||||
|
||||
const val ACTIVITY_URL_GJC_YI_KU = "/gjc/GjcYiKuListActivity" //国际出港 移库
|
||||
const val ACTIVITY_URL_GJC_BOX_ASSEMBLE = "/gjc/GjcBoxAssembleListActivity" //国际出港 板箱组装
|
||||
@@ -135,6 +138,14 @@ object ARouterConstants {
|
||||
const val ACTIVITY_URL_GJC_INSPECTION = "/gjc/GjcInspectionActivity" //国际出港 收运检查
|
||||
const val ACTIVITY_URL_GJC_INSPECTION_DETAILS = "/gjc/GjcInspectionDetailsActivity" //国际出港 收运检查详情
|
||||
const val ACTIVITY_URL_GJC_HANDOVER = "/gjc/GjcHandoverActivity" //国际出港 货物交接单
|
||||
const val ACTIVITY_URL_INT_EXP_ASSEMBLE = "/gjc/IntExpAssembleActivity" //国际出港 出港组装
|
||||
const val ACTIVITY_URL_INT_EXP_ASSEMBLE_START = "/gjc/IntExpAssembleStartActivity" //国际出港 开始组装
|
||||
const val ACTIVITY_URL_INT_EXP_MOVE = "/gjc/IntExpMoveActivity" //国际出港 出港移库
|
||||
const val ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE = "/gjc/GjcAssembleAllocateActivity" //国际出港 组装分配
|
||||
const val ACTIVITY_URL_INT_EXP_OUT_HANDOVER = "/gjc/IntExpOutHandoverActivity" //国际出港 出库交接
|
||||
const val ACTIVITY_URL_INT_EXP_LOAD = "/gjc/IntExpLoadActivity" //国际出港 出港装载
|
||||
const val ACTIVITY_URL_INT_EXP_TALLY = "/gjc/IntExpTallyActivity" //国际出港 出港理货
|
||||
const val ACTIVITY_URL_INT_EXP_ARRIVE = "/gjc/IntExpArriveActivity" //国际出港 出港运抵
|
||||
|
||||
///////////////// 国际进港模块
|
||||
/**
|
||||
|
||||
@@ -152,4 +152,145 @@ fun setTextAllCaps(layout: PadDataLayout, textAllCaps: Boolean) {
|
||||
} else {
|
||||
layout.et.filters = emptyArray<InputFilter>()
|
||||
}
|
||||
}
|
||||
|
||||
// ========== PadDataLayoutNew BindingAdapters ==========
|
||||
|
||||
@BindingAdapter(
|
||||
"type",
|
||||
"title",
|
||||
"titleLength",
|
||||
"hint",
|
||||
"required",
|
||||
"icon",
|
||||
requireAll = false
|
||||
)
|
||||
fun setDataLayoutDataNew(
|
||||
dataLayout: PadDataLayoutNew,
|
||||
type: DataLayoutType?,
|
||||
title: String?,
|
||||
titleLength: Int?,
|
||||
hint: String?,
|
||||
required: Boolean?,
|
||||
icon: Any?,
|
||||
) {
|
||||
type?.let {
|
||||
dataLayout.type = it
|
||||
}
|
||||
title?.let {
|
||||
dataLayout.tvTitle.text = title
|
||||
}
|
||||
titleLength?.let {
|
||||
dataLayout.titleLength = titleLength
|
||||
}
|
||||
required?.let {
|
||||
dataLayout.required = it
|
||||
}
|
||||
hint?.let {
|
||||
dataLayout.hint = hint
|
||||
}
|
||||
dataLayout.icon = icon
|
||||
}
|
||||
|
||||
|
||||
@BindingAdapter(
|
||||
"value",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutDataValueNew(
|
||||
layout: PadDataLayoutNew,
|
||||
value: String?,
|
||||
) {
|
||||
value?.let {
|
||||
layout.value = value
|
||||
}
|
||||
}
|
||||
@BindingAdapter(
|
||||
"enable",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutDataEnableNew(
|
||||
layout: PadDataLayoutNew,
|
||||
enable: Boolean?,
|
||||
) {
|
||||
enable?.let {
|
||||
layout.enable = enable
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"list",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutDataListNew(
|
||||
layout: PadDataLayoutNew,
|
||||
list: List<KeyValue>?,
|
||||
) {
|
||||
list?.let {
|
||||
layout.list = list
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"inputHeight",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutInputHeightNew(
|
||||
layout: PadDataLayoutNew,
|
||||
inputHeight: Int?,
|
||||
) {
|
||||
inputHeight?.let {
|
||||
ViewUtils.setHeight(layout.llContainer, SizeUtils.dp2px(it.toFloat()))
|
||||
layout.et.setRawInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE)
|
||||
layout.et.gravity = Gravity.TOP
|
||||
layout.et.isSingleLine = false
|
||||
layout.et.isHorizontalScrollBarEnabled = false
|
||||
ViewUtils.setPadding(layout.et, SizeUtils.dp2px(10f))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最大长度
|
||||
* 仅对Input类型有效
|
||||
*/
|
||||
@BindingAdapter(
|
||||
"maxLength",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutMaxLengthNew(
|
||||
layout: PadDataLayoutNew,
|
||||
maxLength: Int?,
|
||||
) {
|
||||
maxLength?.let {
|
||||
EditTextUtils.setMaxLength(layout.et, maxLength)
|
||||
}
|
||||
}
|
||||
|
||||
@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged")
|
||||
fun getDataLayoutValueNew(dataLayout: PadDataLayoutNew): String {
|
||||
return dataLayout.value
|
||||
}
|
||||
|
||||
@BindingAdapter("valueAttrChanged", requireAll = false)
|
||||
fun setDataLayoutValueAttrChangedNew(dataLayout: PadDataLayoutNew, listener: InverseBindingListener) {
|
||||
dataLayout.onChangeListener = listener
|
||||
}
|
||||
|
||||
@BindingAdapter("setOnIconClickListener", requireAll = false)
|
||||
fun setOnIconClickListenerNew(layout: PadDataLayoutNew, listener: View.OnClickListener) {
|
||||
layout.iv.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
@BindingAdapter("setRefreshCallBack", requireAll = false)
|
||||
fun setRefreshCallBackNew(layout: PadDataLayoutNew, listener: (() -> Unit)?) {
|
||||
layout.refreshCallBack = listener
|
||||
}
|
||||
|
||||
@BindingAdapter("setTextAllCaps", requireAll = false)
|
||||
fun setTextAllCapsNew(layout: PadDataLayoutNew, textAllCaps: Boolean) {
|
||||
if (textAllCaps) {
|
||||
layout.et.filters = arrayOf<InputFilter>(InputFilter.AllCaps())
|
||||
} else {
|
||||
layout.et.filters = emptyArray<InputFilter>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
package com.lukouguoji.module_base.ui.weight.data.layout
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.databinding.InverseBindingListener
|
||||
import androidx.databinding.ObservableArrayList
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import androidx.databinding.ObservableField
|
||||
import androidx.databinding.ObservableInt
|
||||
import com.lukouguoji.module_base.R
|
||||
import com.lukouguoji.module_base.adapter.bindAdapter
|
||||
import com.lukouguoji.module_base.adapter.bindOnSelected
|
||||
import com.lukouguoji.module_base.adapter.completeSpace
|
||||
import com.lukouguoji.module_base.adapter.loadImage
|
||||
import com.lukouguoji.module_base.adapter.setSelectedItem
|
||||
import com.lukouguoji.module_base.adapter.visible
|
||||
import com.lukouguoji.module_base.interfaces.IOnFocusChangeListener
|
||||
import com.lukouguoji.module_base.interfaces.IOnSpinnerSelected
|
||||
import com.lukouguoji.module_base.ktx.formatDate
|
||||
import com.lukouguoji.module_base.ktx.getActivity
|
||||
import com.lukouguoji.module_base.ktx.loge
|
||||
import com.lukouguoji.module_base.util.Common
|
||||
import dev.utils.app.info.KeyValue
|
||||
import dev.utils.common.ReflectUtils
|
||||
import java.util.Calendar
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class PadDataLayoutNew : FrameLayout {
|
||||
constructor(context: Context?) : super(context!!)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
|
||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context!!,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
var onChangeListener: InverseBindingListener? = null
|
||||
|
||||
var llContainer: LinearLayout by Delegates.notNull()
|
||||
var ll: LinearLayout by Delegates.notNull()
|
||||
var tvTitle: TextView by Delegates.notNull()
|
||||
var tvM: TextView by Delegates.notNull()
|
||||
var tv: TextView by Delegates.notNull()
|
||||
var tvSpinner: TextView by Delegates.notNull()
|
||||
|
||||
var et: EditText by Delegates.notNull()
|
||||
var spinner: Spinner by Delegates.notNull()
|
||||
var iv: ImageView by Delegates.notNull()
|
||||
|
||||
var type = DataLayoutType.INPUT
|
||||
set(value) {
|
||||
field = value
|
||||
setForType()
|
||||
}
|
||||
var enable = true
|
||||
set(value) {
|
||||
field = value
|
||||
setForEnable()
|
||||
}
|
||||
var titleLength = 0
|
||||
set(value) {
|
||||
field = value
|
||||
if (value > 0) {
|
||||
completeSpace(tvTitle, value, false)
|
||||
}
|
||||
}
|
||||
|
||||
var value = ""
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
onValueSet()
|
||||
onChangeListener?.onChange()
|
||||
}
|
||||
|
||||
var show = ""
|
||||
|
||||
var title = ""
|
||||
set(value) {
|
||||
field = value
|
||||
tvTitle.text = value
|
||||
}
|
||||
|
||||
var hint = ""
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
et.hint = value
|
||||
bindAdapter(spinner, list, hint)
|
||||
}
|
||||
|
||||
var required = false
|
||||
set(value) {
|
||||
field = value
|
||||
tvM.visibility = if (value) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
var list = emptyList<KeyValue>()
|
||||
set(value) {
|
||||
field = value
|
||||
bindAdapter(spinner, value, hint)
|
||||
onValueSet()
|
||||
}
|
||||
|
||||
var icon: Any? = null
|
||||
set(value) {
|
||||
field = value
|
||||
visible(iv, value)
|
||||
loadImage(iv, value)
|
||||
}
|
||||
|
||||
var inputType: Int = android.text.InputType.TYPE_CLASS_TEXT
|
||||
set(value) {
|
||||
field = value
|
||||
et.inputType = value
|
||||
}
|
||||
|
||||
var valueTextColor: Int = 0
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != 0) {
|
||||
tv.setTextColor(value)
|
||||
et.setTextColor(value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新事件回调
|
||||
*/
|
||||
var refreshCallBack: (() -> Unit)? = {}
|
||||
|
||||
// 选择日期
|
||||
private val dateClick: (v: View) -> Unit = {
|
||||
if (enable) {
|
||||
Common.onYearMonthDay(context.getActivity(), value) { year, month, day ->
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(year, month - 1, day)
|
||||
value = calendar.time.formatDate()
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
initView()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
val view = inflate(context, R.layout.layout_pad_data_new, this)
|
||||
llContainer = view.findViewById(R.id.ll_container)
|
||||
ll = view.findViewById(R.id.ll)
|
||||
tvTitle = view.findViewById(R.id.tv_title)
|
||||
tvM = view.findViewById(R.id.tv_m)
|
||||
tv = view.findViewById(R.id.tv)
|
||||
tvSpinner = view.findViewById(R.id.tv_spinner)
|
||||
et = view.findViewById(R.id.et)
|
||||
spinner = view.findViewById(R.id.spinner)
|
||||
iv = view.findViewById(R.id.iv)
|
||||
|
||||
et.doOnTextChanged { text, _, _, _ ->
|
||||
value = text.toString()
|
||||
}
|
||||
bindOnSelected(spinner, object : IOnSpinnerSelected {
|
||||
override fun onSelected(position: Int) {
|
||||
value = list.getOrNull(position)?.value ?: ""
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
})
|
||||
// 监听输入框焦点变化
|
||||
com.lukouguoji.module_base.adapter.setOnFocusChangeListener(
|
||||
et, object : IOnFocusChangeListener {
|
||||
override fun onFocusChange(hasFocus: Boolean) {
|
||||
if (!hasFocus) {
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
setForType()
|
||||
}
|
||||
|
||||
private fun setForEnable() {
|
||||
ll.isEnabled = enable
|
||||
et.isEnabled = enable
|
||||
spinner.isEnabled = enable
|
||||
tv.isEnabled = enable
|
||||
|
||||
setForType()
|
||||
onValueSet()
|
||||
}
|
||||
|
||||
private fun setForType() {
|
||||
when (type) {
|
||||
DataLayoutType.INPUT -> {
|
||||
et.visibility = VISIBLE
|
||||
spinner.visibility = GONE
|
||||
tvSpinner.visibility = GONE
|
||||
tv.visibility = GONE
|
||||
setOnClickListener(null)
|
||||
}
|
||||
|
||||
DataLayoutType.SPINNER -> {
|
||||
et.visibility = GONE
|
||||
tv.visibility = GONE
|
||||
if (enable) {
|
||||
spinner.visibility = VISIBLE
|
||||
tvSpinner.visibility = GONE
|
||||
} else {
|
||||
tvSpinner.visibility = VISIBLE
|
||||
spinner.visibility = GONE
|
||||
}
|
||||
setOnClickListener(null)
|
||||
}
|
||||
|
||||
DataLayoutType.DATE -> {
|
||||
tv.visibility = VISIBLE
|
||||
et.visibility = GONE
|
||||
spinner.visibility = GONE
|
||||
tvSpinner.visibility = GONE
|
||||
|
||||
setOnClickListener(dateClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onValueSet() {
|
||||
if (et.text.toString() != value) {
|
||||
et.setText(value)
|
||||
}
|
||||
if (tv.text.toString() != value) {
|
||||
tv.text = value
|
||||
}
|
||||
|
||||
tvSpinner.text = list.find { b -> b.value == value }?.key ?: value
|
||||
|
||||
if (value.isNotEmpty() && list.isNotEmpty()) {
|
||||
val index = list.indexOfFirst { b -> b.value == value }
|
||||
if (index >= 0) {
|
||||
spinner.post {
|
||||
spinner.setSelection(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun setOnValueChangeListener(listener: InverseBindingListener) {
|
||||
if (onChangeListener == null) {
|
||||
this.onChangeListener = listener
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package com.lukouguoji.module_base.ui.weight.search.layout
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.databinding.InverseBindingListener
|
||||
import com.lukouguoji.module_base.R
|
||||
import com.lukouguoji.module_base.adapter.bindAdapter
|
||||
import com.lukouguoji.module_base.adapter.bindOnSelected
|
||||
import com.lukouguoji.module_base.adapter.loadImage
|
||||
import com.lukouguoji.module_base.adapter.visible
|
||||
import com.lukouguoji.module_base.interfaces.IOnFocusChangeListener
|
||||
import com.lukouguoji.module_base.interfaces.IOnSpinnerSelected
|
||||
import com.lukouguoji.module_base.ktx.formatDate
|
||||
import com.lukouguoji.module_base.ktx.getActivity
|
||||
import com.lukouguoji.module_base.ktx.loge
|
||||
import com.lukouguoji.module_base.ktx.tryCatch
|
||||
import com.lukouguoji.module_base.util.Common
|
||||
import dev.utils.app.info.KeyValue
|
||||
import java.util.Calendar
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class PadSearchLayoutNew : LinearLayout {
|
||||
|
||||
constructor(context: Context?) : super(context!!)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)
|
||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context!!,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
|
||||
var onChangeListener: InverseBindingListener? = null
|
||||
|
||||
var ll: LinearLayout by Delegates.notNull()
|
||||
|
||||
var tvM: TextView by Delegates.notNull()
|
||||
var tv: TextView by Delegates.notNull()
|
||||
|
||||
var et: EditText by Delegates.notNull()
|
||||
var spinner: Spinner by Delegates.notNull()
|
||||
var iv: ImageView by Delegates.notNull()
|
||||
|
||||
var type = SearchLayoutType.INPUT
|
||||
set(value) {
|
||||
field = value
|
||||
setForType()
|
||||
onValueSet()
|
||||
}
|
||||
|
||||
var enable = true
|
||||
set(value) {
|
||||
field = value
|
||||
ll.isEnabled = value
|
||||
et.isEnabled = value
|
||||
spinner.isEnabled = value
|
||||
}
|
||||
|
||||
var value = ""
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
onValueSet()
|
||||
onChangeListener?.onChange()
|
||||
}
|
||||
|
||||
var hint = ""
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
et.hint = value
|
||||
tv.hint = value
|
||||
bindAdapter(spinner, list, hint)
|
||||
}
|
||||
|
||||
var list = emptyList<KeyValue>()
|
||||
set(value) {
|
||||
field = value
|
||||
bindAdapter(spinner, value, hint)
|
||||
onValueSet()
|
||||
}
|
||||
|
||||
var required = false
|
||||
set(value) {
|
||||
field = value
|
||||
tvM.visibility = if (value) VISIBLE else GONE
|
||||
}
|
||||
|
||||
var icon: Any? = null
|
||||
set(value) {
|
||||
field = value
|
||||
visible(iv, value)
|
||||
loadImage(iv, value)
|
||||
}
|
||||
|
||||
// 选择日期
|
||||
private val dateClick: (v: View) -> Unit = {
|
||||
if (enable) {
|
||||
Common.onYearMonthDay(context.getActivity(), value) { year, month, day ->
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(year, month - 1, day)
|
||||
value = calendar.time.formatDate()
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新事件回调
|
||||
*/
|
||||
var refreshCallBack: (() -> Unit)? = {}
|
||||
|
||||
var listRefreshCallBack: (() -> Unit)? = {}
|
||||
|
||||
/**
|
||||
* 搜索事件回调(回车键或搜索按钮触发)
|
||||
*/
|
||||
var searchCallBack: (() -> Unit)? = null
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 方法区
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
init {
|
||||
val view = inflate(context, R.layout.layout_pad_search_new, this)
|
||||
|
||||
ll = view.findViewById(R.id.ll)
|
||||
tvM = view.findViewById(R.id.tv_m)
|
||||
tv = view.findViewById(R.id.tv)
|
||||
et = view.findViewById(R.id.et)
|
||||
spinner = view.findViewById(R.id.spinner)
|
||||
iv = view.findViewById(R.id.iv)
|
||||
|
||||
et.doOnTextChanged { text, _, _, _ ->
|
||||
value = text.toString()
|
||||
}
|
||||
|
||||
// 回车键监听 - 触发搜索
|
||||
et.setOnEditorActionListener { v, actionId, event ->
|
||||
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
|
||||
actionId == EditorInfo.IME_ACTION_DONE ||
|
||||
(event?.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)) {
|
||||
// 优先调用searchCallBack,如果没有则调用refreshCallBack
|
||||
searchCallBack?.invoke() ?: refreshCallBack?.invoke()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
bindOnSelected(spinner, object : IOnSpinnerSelected {
|
||||
override fun onSelected(position: Int) {
|
||||
value = list.getOrNull(position)?.value ?: ""
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
})
|
||||
|
||||
// 监听输入框焦点变化
|
||||
com.lukouguoji.module_base.adapter.setOnFocusChangeListener(
|
||||
et, object : IOnFocusChangeListener {
|
||||
override fun onFocusChange(hasFocus: Boolean) {
|
||||
if (!hasFocus) {
|
||||
refreshCallBack?.invoke()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
setForType()
|
||||
}
|
||||
|
||||
private fun setForType() {
|
||||
when (type) {
|
||||
SearchLayoutType.INPUT -> {
|
||||
et.visibility = VISIBLE
|
||||
spinner.visibility = GONE
|
||||
tv.visibility = GONE
|
||||
setOnClickListener(null)
|
||||
}
|
||||
SearchLayoutType.INTEGER -> {
|
||||
et.visibility = VISIBLE
|
||||
spinner.visibility = GONE
|
||||
tv.visibility = GONE
|
||||
setOnClickListener(null)
|
||||
}
|
||||
|
||||
SearchLayoutType.SPINNER -> {
|
||||
spinner.visibility = VISIBLE
|
||||
et.visibility = GONE
|
||||
tv.visibility = GONE
|
||||
setOnClickListener(null)
|
||||
}
|
||||
|
||||
SearchLayoutType.DATE -> {
|
||||
tv.visibility = VISIBLE
|
||||
spinner.visibility = GONE
|
||||
et.visibility = GONE
|
||||
|
||||
setOnClickListener(dateClick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onValueSet() {
|
||||
when (type) {
|
||||
SearchLayoutType.INPUT -> {
|
||||
if (et.text.toString() != value) {
|
||||
et.setText(value)
|
||||
}
|
||||
}
|
||||
|
||||
SearchLayoutType.INTEGER -> {
|
||||
var stringAnInt = isStringAnInt(et.text.toString())
|
||||
if (stringAnInt && et.text.toString() != value ) {
|
||||
et.setText(value)
|
||||
}
|
||||
}
|
||||
|
||||
SearchLayoutType.SPINNER -> {
|
||||
if (value.isNotEmpty()) {
|
||||
val position = list.indexOfFirst { it.value == value }
|
||||
if (position >= 0) {
|
||||
spinner.setSelection(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SearchLayoutType.DATE -> {
|
||||
tv.text = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是数字
|
||||
*/
|
||||
fun isStringAnInt(str: String?): Boolean {
|
||||
return str?.toIntOrNull() != null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重置数据
|
||||
*/
|
||||
fun reset() {
|
||||
value = ""
|
||||
if (type == SearchLayoutType.SPINNER && list.isNotEmpty()) {
|
||||
spinner.setSelection(
|
||||
if (hint.isEmpty()) list.size - 1 else list.size
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,4 +138,154 @@ fun setInputWaybill(layout: PadSearchLayout, isWaybill: Boolean) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置搜索监听器(回车键或搜索按钮触发)
|
||||
*/
|
||||
@BindingAdapter("setOnSearchListener", requireAll = false)
|
||||
fun setSearchLayoutNewOnSearchListener(layout: PadSearchLayoutNew, listener: (() -> Unit)?) {
|
||||
layout.searchCallBack = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置搜索图标点击为搜索功能
|
||||
*/
|
||||
@BindingAdapter("setSearchIconClickListener", requireAll = false)
|
||||
fun setSearchLayoutNewSearchIconClickListener(layout: PadSearchLayoutNew, listener: (() -> Unit)?) {
|
||||
layout.iv.setOnClickListener {
|
||||
listener?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// PadSearchLayoutNew 的绑定适配器
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@BindingAdapter(
|
||||
"type",
|
||||
"hint",
|
||||
"required",
|
||||
"icon",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutNewData(
|
||||
layout: PadSearchLayoutNew,
|
||||
type: SearchLayoutType?,
|
||||
hint: String?,
|
||||
required: Boolean?,
|
||||
icon: Any?,
|
||||
) {
|
||||
type?.let {
|
||||
layout.type = type
|
||||
}
|
||||
required?.let {
|
||||
layout.required = required
|
||||
}
|
||||
hint?.let {
|
||||
layout.hint = hint
|
||||
}
|
||||
icon?.let {
|
||||
layout.icon = icon
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"value",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutNewDataValue(
|
||||
layout: PadSearchLayoutNew,
|
||||
value: String?,
|
||||
) {
|
||||
value?.let {
|
||||
layout.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"enable",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutNewDataEnable(
|
||||
layout: PadSearchLayoutNew,
|
||||
enable: Boolean?,
|
||||
) {
|
||||
enable?.let {
|
||||
layout.enable = enable
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"list",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutNewDataList(
|
||||
layout: PadSearchLayoutNew,
|
||||
list: List<KeyValue>?,
|
||||
) {
|
||||
list?.let {
|
||||
layout.list = list
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter(
|
||||
"bgDrawable",
|
||||
requireAll = false
|
||||
)
|
||||
fun setSearchLayoutNewDataBackground(
|
||||
layout: PadSearchLayoutNew,
|
||||
bgDrawable: Drawable,
|
||||
) {
|
||||
layout.ll.setBackgroundDrawable(bgDrawable)
|
||||
}
|
||||
|
||||
@InverseBindingAdapter(attribute = "value", event = "valueAttrChanged")
|
||||
fun getSearchLayoutNewValue(layout: PadSearchLayoutNew): String {
|
||||
return layout.value
|
||||
}
|
||||
|
||||
@BindingAdapter("valueAttrChanged", requireAll = false)
|
||||
fun setSearchLayoutNewValueAttrChanged(layout: PadSearchLayoutNew, listener: InverseBindingListener) {
|
||||
layout.onChangeListener = listener
|
||||
}
|
||||
|
||||
@BindingAdapter("setOnIconClickListener", requireAll = false)
|
||||
fun setSearchLayoutNewOnIconClickListener(layout: PadSearchLayoutNew, listener: View.OnClickListener?) {
|
||||
layout.iv.setOnClickListener(listener)
|
||||
}
|
||||
|
||||
@BindingAdapter("setRefreshCallBack", requireAll = false)
|
||||
fun setSearchLayoutNewRefreshCallBack(layout: PadSearchLayoutNew, listener: (() -> Unit)?) {
|
||||
layout.refreshCallBack = listener
|
||||
}
|
||||
|
||||
@BindingAdapter("setSearchListRefresh")
|
||||
fun setSearchLayoutNewListRefreshCallBack(layout: PadSearchLayoutNew, listener: (() -> Unit)?) {
|
||||
layout.listRefreshCallBack = listener
|
||||
}
|
||||
|
||||
@BindingAdapter("setTextAllCaps", requireAll = false)
|
||||
fun setSearchLayoutNewTextAllCaps(layout: PadSearchLayoutNew, textAllCaps: Boolean) {
|
||||
if (textAllCaps) {
|
||||
layout.et.filters = arrayOf<InputFilter>(InputFilter.AllCaps())
|
||||
} else {
|
||||
layout.et.filters = emptyArray<InputFilter>()
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("setInputWaybill", requireAll = false)
|
||||
fun setSearchLayoutNewInputWaybill(layout: PadSearchLayoutNew, isWaybill: Boolean) {
|
||||
if (isWaybill) {
|
||||
EditTextUtils.setMaxLength(layout.et, 11)
|
||||
EditTextUtils.setInputType(layout.et, InputType.TYPE_CLASS_NUMBER)
|
||||
layout.et.doOnTextChanged { text, _, _, _ ->
|
||||
if (text.toString().length == 11) {
|
||||
layout.refreshCallBack?.invoke()
|
||||
}
|
||||
if (text.toString().length in 4..8){
|
||||
layout.listRefreshCallBack?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
package com.lukouguoji.module_base.util
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.module_base.bean.DictBean
|
||||
import com.lukouguoji.module_base.bean.DictListBean
|
||||
import com.lukouguoji.module_base.http.net.NetApply
|
||||
import com.lukouguoji.module_base.ktx.launchCollect
|
||||
import com.lukouguoji.module_base.ktx.toMap
|
||||
import com.lukouguoji.module_base.ktx.toRequestBody
|
||||
import dev.utils.app.info.KeyValue
|
||||
import java.util.Collections.emptyList
|
||||
|
||||
@@ -179,7 +176,7 @@ object DictUtils {
|
||||
) {
|
||||
launchCollect({
|
||||
NetApply.api
|
||||
.getSpecialCodeList(flag, ieFlag,parentcode)
|
||||
.getSpecialCodeList(flag, ieFlag, parentcode)
|
||||
}) {
|
||||
onSuccess = {
|
||||
handleCallBack(it, checkedValue, addAll, callBack)
|
||||
@@ -404,6 +401,22 @@ object DictUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 国际出港通道号列表
|
||||
*/
|
||||
fun getGjcChannelList(
|
||||
callBack: (List<KeyValue>) -> Unit
|
||||
) {
|
||||
launchCollect({
|
||||
NetApply.api
|
||||
.getDictListByLocation("GJCPASSAGEWAY")
|
||||
}) {
|
||||
onSuccess = {
|
||||
callBack((it.data ?: emptyList()).map { b -> b.toKeyValue() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 货物类型
|
||||
@@ -510,7 +523,7 @@ object DictUtils {
|
||||
.getDictList("DGRDETAIL")
|
||||
}) {
|
||||
onSuccess = {
|
||||
callBack((it.data ?: emptyList()).map { b -> KeyValue(b.value,b.value) })
|
||||
callBack((it.data ?: emptyList()).map { b -> KeyValue(b.value, b.value) })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -629,12 +642,14 @@ object DictUtils {
|
||||
NetApply.api.getUserByRoleId("6")
|
||||
}) {
|
||||
onSuccess = {
|
||||
val jbDrivers = (it.data ?: emptyList()).map { b -> KeyValue(b.username, b.username) }
|
||||
val jbDrivers =
|
||||
(it.data ?: emptyList()).map { b -> KeyValue(b.username, b.username) }
|
||||
launchCollect({
|
||||
NetApply.api.getUserByRoleId("7")
|
||||
}) {
|
||||
onSuccess = {iit ->
|
||||
val shDrivers = (iit.data ?: emptyList()).map { b -> KeyValue(b.username, b.username) }
|
||||
onSuccess = { iit ->
|
||||
val shDrivers =
|
||||
(iit.data ?: emptyList()).map { b -> KeyValue(b.username, b.username) }
|
||||
callBack(jbDrivers + shDrivers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.lukouguoji.module_base.util
|
||||
|
||||
import android.Manifest
|
||||
import android.graphics.Typeface
|
||||
import android.util.Log
|
||||
import com.gainscha.sdk2.ConnectType
|
||||
import com.gainscha.sdk2.ConnectionListener
|
||||
import com.gainscha.sdk2.Printer
|
||||
@@ -18,23 +17,39 @@ import com.gprinter.io.PortManager
|
||||
import com.gprinter.utils.CallbackListener
|
||||
import com.gprinter.utils.Command
|
||||
import com.gprinter.utils.ConnMethod
|
||||
import com.lukouguoji.module_base.bean.FlatcarBean
|
||||
import com.lukouguoji.module_base.bean.GjcUldUseBean
|
||||
import com.lukouguoji.module_base.bean.GncFuBangBean
|
||||
import com.lukouguoji.module_base.bean.GncShouYunBean
|
||||
import com.lukouguoji.module_base.http.net.NetApply
|
||||
import com.lukouguoji.module_base.ktx.launchCollect
|
||||
import com.lukouguoji.module_base.ktx.launchLoadingCollect
|
||||
import com.lukouguoji.module_base.ktx.loge
|
||||
import com.lukouguoji.module_base.ktx.permission
|
||||
import com.lukouguoji.module_base.ktx.showToast
|
||||
import com.lukouguoji.module_base.model.LoadingModel
|
||||
import dev.DevUtils
|
||||
import dev.utils.app.SizeUtils
|
||||
import okio.internal.commonToUtf8String
|
||||
|
||||
|
||||
object PrinterUtils {
|
||||
|
||||
/**
|
||||
* 打印单元格数据
|
||||
*/
|
||||
private data class CellData(
|
||||
val title: String, // 中文标签(大字)
|
||||
val subtitle: String, // 英文标签(小字)
|
||||
val value: String // 值(大字,垂直居中)
|
||||
)
|
||||
|
||||
/**
|
||||
* 打印表格行数据
|
||||
*/
|
||||
private data class GridRow(
|
||||
val left: CellData? = null,
|
||||
val right: CellData? = null,
|
||||
val merged: CellData? = null // 合并单元格数据
|
||||
)
|
||||
|
||||
private val loading by lazy {
|
||||
LoadingModel()
|
||||
}
|
||||
@@ -133,7 +148,8 @@ object PrinterUtils {
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
) {
|
||||
finder.searchPrinters(ConnectType.BLUETOOTH,
|
||||
finder.searchPrinters(
|
||||
ConnectType.BLUETOOTH,
|
||||
object : PrinterFinder.SimpleSearchPrinterResultListener() {
|
||||
override fun onSearchBluetoothPrinter(device: BluetoothPrinterDevice?) {
|
||||
if (device == null) return
|
||||
@@ -218,28 +234,28 @@ object PrinterUtils {
|
||||
var fDestinationCn = ""
|
||||
launchCollect({
|
||||
NetApply.api.getAirportByCode(bean.dest1)
|
||||
}){
|
||||
}) {
|
||||
onSuccess = {
|
||||
destinationCn = it.data?.nameCn ?: ""
|
||||
rowItem.add(listOf("日期", "航班号", "目的站"))
|
||||
rowItem.add(listOf( bean.fdate, bean.fno, bean.dest1 + destinationCn ))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf( bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf( "", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息","备注"))
|
||||
rowItem.add(listOf(bean.fdate, bean.fno, bean.dest1 + destinationCn))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf(bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf("", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息", "备注"))
|
||||
if (bean.dest2 != "") {
|
||||
launchCollect({
|
||||
NetApply.api.getAirportByCode(bean.dest2)
|
||||
}){
|
||||
}) {
|
||||
onSuccess = { it2 ->
|
||||
fDestinationCn = it2.data?.nameCn ?: ""
|
||||
rowItem.add(listOf( "", bean.dest2 + fDestinationCn, ""))
|
||||
rowItem.add(listOf("", bean.dest2 + fDestinationCn, ""))
|
||||
printCommonGridNew(rowItem)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rowItem.add(listOf( "", "", ""))
|
||||
rowItem.add(listOf("", "", ""))
|
||||
printCommonGridNew(rowItem)
|
||||
}
|
||||
}
|
||||
@@ -259,35 +275,35 @@ object PrinterUtils {
|
||||
var fDestinationCn = ""
|
||||
launchCollect({
|
||||
NetApply.api.getAirportByCode(bean.fdest)
|
||||
}){
|
||||
}) {
|
||||
onSuccess = {
|
||||
fDestinationCn = it.data?.nameCn ?: ""
|
||||
if (bean.dest != "") {
|
||||
launchCollect({
|
||||
NetApply.api.getAirportByCode(bean.dest)
|
||||
}){
|
||||
}) {
|
||||
onSuccess = { it2 ->
|
||||
destinationCn = it2.data?.nameCn ?: ""
|
||||
rowItem.add(listOf("日期", "航班号", "目的站"))
|
||||
rowItem.add(listOf( bean.fdate, bean.fno, bean.fdest + fDestinationCn ))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf( bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf( "", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息","备注"))
|
||||
rowItem.add(listOf( "", bean.dest + destinationCn, ""))
|
||||
rowItem.add(listOf(bean.fdate, bean.fno, bean.fdest + fDestinationCn))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf(bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf("", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息", "备注"))
|
||||
rowItem.add(listOf("", bean.dest + destinationCn, ""))
|
||||
printCommonGridNew(rowItem)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rowItem.add(listOf("日期", "航班号", "目的站"))
|
||||
rowItem.add(listOf( bean.fdate, bean.fno, bean.fdest + fDestinationCn ))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf( bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf( "", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息","备注"))
|
||||
rowItem.add(listOf( "", "", ""))
|
||||
rowItem.add(listOf(bean.fdate, bean.fno, bean.fdest + fDestinationCn))
|
||||
rowItem.add(listOf("斗号", "计重", "仓管"))
|
||||
rowItem.add(listOf(bean.location, bean.username, ""))
|
||||
rowItem.add(listOf("装机仓位", "机位", "特车司机"))
|
||||
rowItem.add(listOf("", "", ""))
|
||||
rowItem.add(listOf("监装监卸", "中转信息", "备注"))
|
||||
rowItem.add(listOf("", "", ""))
|
||||
printCommonGridNew(rowItem)
|
||||
}
|
||||
|
||||
@@ -295,6 +311,43 @@ object PrinterUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印国际出港板箱过磅挂签(2列布局,支持合并单元格)
|
||||
*/
|
||||
fun printGjcBoxWeighing(bean: GjcUldUseBean) {
|
||||
val rows = arrayListOf<GridRow>()
|
||||
|
||||
// 第1行:日期 | 航班号
|
||||
rows.add(GridRow(
|
||||
left = CellData("日期:", "DATA:", bean.fdate),
|
||||
right = CellData("航班号:", "FLIGHT NO.:", bean.fno)
|
||||
))
|
||||
|
||||
// 第2行:目的站 | 板型
|
||||
rows.add(GridRow(
|
||||
left = CellData("目的站:", "DESTINATION:", bean.fdest),
|
||||
right = CellData("板型:", "PALLET TYPE:", bean.boardType)
|
||||
))
|
||||
|
||||
// 第3行:集装器编号(合并两列)
|
||||
rows.add(GridRow(
|
||||
merged = CellData("集装器编号:", "ULD NO.:", bean.uld)
|
||||
))
|
||||
|
||||
// 第4行:件数 | 重量
|
||||
rows.add(GridRow(
|
||||
left = CellData("件数:", "PIECES:", bean.pieces.ifEmpty { "0" }),
|
||||
right = CellData("重量:", "GROSS WEIGHT:", bean.totalWeight.toInt().toString())
|
||||
))
|
||||
|
||||
// 第5行:备注(合并两列)
|
||||
rows.add(GridRow(
|
||||
merged = CellData("备注:", "NOTES:", bean.remark)
|
||||
))
|
||||
|
||||
printMergedGrid(rows)
|
||||
}
|
||||
|
||||
private fun printCommonGrid(rowItem: ArrayList<List<String>>) {
|
||||
val gridStartX = 80
|
||||
val gridStartY = 300
|
||||
@@ -370,10 +423,10 @@ object PrinterUtils {
|
||||
if (index % 2 == 0) {
|
||||
padding = 15
|
||||
}
|
||||
if (str.length == 2){
|
||||
if (str.length == 2) {
|
||||
padding += 60
|
||||
}
|
||||
if (str.length == 3){
|
||||
if (str.length == 3) {
|
||||
padding += 30
|
||||
}
|
||||
if (str.length == 7) {
|
||||
@@ -391,6 +444,127 @@ object PrinterUtils {
|
||||
portManager?.writeDataImmediately(bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印支持合并单元格的表格
|
||||
*/
|
||||
private fun printMergedGrid(rows: ArrayList<GridRow>) {
|
||||
val gridStartX = 30
|
||||
val gridStartY = 250
|
||||
val columnWidth = 570
|
||||
val rowHeight = 240
|
||||
val gridWidth = columnWidth * 2
|
||||
val gridHeight = rowHeight * rows.size
|
||||
|
||||
val bytes = Tspl().apply {
|
||||
addSize(100, 100)
|
||||
addGap(3)
|
||||
addCls()
|
||||
addTextByBitmap(80, 80, 0, 130, "扬州泰州机场", Typeface.DEFAULT)
|
||||
|
||||
// 绘制表格横线
|
||||
for (i in 0..rows.size) {
|
||||
addBar(gridStartX, gridStartY + (i * rowHeight), gridWidth, 2)
|
||||
}
|
||||
|
||||
// 绘制表格竖线(需要根据是否合并单元格决定)
|
||||
rows.forEachIndexed { rowIndex, row ->
|
||||
val yTop = gridStartY + (rowIndex * rowHeight)
|
||||
|
||||
// 左边线(总是绘制)
|
||||
addBar(gridStartX, yTop, 2, rowHeight)
|
||||
|
||||
// 中间分隔线(非合并单元格才绘制)
|
||||
if (row.merged == null) {
|
||||
addBar(gridStartX + columnWidth, yTop, 2, rowHeight)
|
||||
}
|
||||
|
||||
// 右边线(总是绘制)
|
||||
if (rowIndex == rows.size - 1) {
|
||||
addBar(gridStartX + gridWidth, yTop, 2, rowHeight)
|
||||
}
|
||||
}
|
||||
|
||||
// 填充单元格内容
|
||||
rows.forEachIndexed { rowIndex, row ->
|
||||
val yBase = gridStartY + (rowIndex * rowHeight)
|
||||
|
||||
if (row.merged != null) {
|
||||
// 合并单元格
|
||||
renderCell(
|
||||
cell = row.merged,
|
||||
x = gridStartX + 30,
|
||||
y = yBase,
|
||||
cellWidth = gridWidth,
|
||||
cellHeight = rowHeight
|
||||
)
|
||||
} else {
|
||||
// 左列单元格
|
||||
row.left?.let { cell ->
|
||||
renderCell(
|
||||
cell = cell,
|
||||
x = gridStartX + 30,
|
||||
y = yBase,
|
||||
cellWidth = columnWidth,
|
||||
cellHeight = rowHeight
|
||||
)
|
||||
}
|
||||
// 右列单元格
|
||||
row.right?.let { cell ->
|
||||
renderCell(
|
||||
cell = cell,
|
||||
x = gridStartX + columnWidth + 30,
|
||||
y = yBase,
|
||||
cellWidth = columnWidth,
|
||||
cellHeight = rowHeight
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addPrint(1)
|
||||
}.bytes
|
||||
|
||||
portManager?.writeDataImmediately(bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染单元格内容
|
||||
* @param cell 单元格数据
|
||||
* @param x 起始X坐标
|
||||
* @param y 起始Y坐标
|
||||
* @param cellWidth 单元格宽度(用于计算右侧对齐)
|
||||
* @param cellHeight 单元格高度(用于计算垂直居中)
|
||||
*/
|
||||
private fun Tspl.renderCell(
|
||||
cell: CellData,
|
||||
x: Int,
|
||||
y: Int,
|
||||
cellWidth: Int,
|
||||
cellHeight: Int
|
||||
) {
|
||||
// 左上角:中文标签和英文标签
|
||||
val titleY = y + 30 // 中文标签Y位置
|
||||
val subtitleY = y + 80 // 英文标签Y位置(中文下方)
|
||||
|
||||
// 中文标签(大字,左上)
|
||||
addText(x, titleY, Tspl.FONT_TSS24, 0, 3, 3, cell.title)
|
||||
|
||||
// 英文标签(小字,左上)
|
||||
addText(x, subtitleY, Tspl.FONT_TSS24, 0, 2, 2, cell.subtitle)
|
||||
|
||||
// 右侧:值(大字,垂直居中)
|
||||
// 计算垂直居中的Y坐标:y + (cellHeight / 2) - (文字高度 / 2)
|
||||
// 假设size=3的文字高度约为80像素
|
||||
val valueY = y + (cellHeight / 2) - 40 // 垂直居中
|
||||
|
||||
// 计算右侧X坐标:中文标签宽度 + 间距
|
||||
// 假设"目的站:"宽度约为180像素,"DESTINATION:"宽度约为240像素
|
||||
val valueX = x + 280 // 右侧偏移量
|
||||
|
||||
// 值(大字,垂直居中,右侧)
|
||||
addText(valueX, valueY, Tspl.FONT_TSS24, 0, 3, 3, cell.value)
|
||||
}
|
||||
|
||||
fun printTest() {
|
||||
getConnectedPrinters().forEach {
|
||||
val bytes = v(Instruction.TSC.toString(), null).bytes
|
||||
|
||||
8
module_base/src/main/res/drawable/bg_blue_radius_4.xml
Normal file
8
module_base/src/main/res/drawable/bg_blue_radius_4.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#1C8CF5" />
|
||||
<corners android:radius="4dp" />
|
||||
|
||||
</shape>
|
||||
7
module_base/src/main/res/drawable/bg_circle_gray.xml
Normal file
7
module_base/src/main/res/drawable/bg_circle_gray.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="@color/color_f2" />
|
||||
|
||||
</shape>
|
||||
7
module_base/src/main/res/drawable/bg_circle_green.xml
Normal file
7
module_base/src/main/res/drawable/bg_circle_green.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="@color/colorPrimary" />
|
||||
|
||||
</shape>
|
||||
7
module_base/src/main/res/drawable/bg_circle_yellow.xml
Normal file
7
module_base/src/main/res/drawable/bg_circle_yellow.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<solid android:color="#FFC107" />
|
||||
|
||||
</shape>
|
||||
@@ -2,6 +2,6 @@
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/bg_data_layout_s" android:state_enabled="true" />
|
||||
<item android:drawable="@drawable/bg_data_layout_n" android:state_enabled="false" />
|
||||
<item android:drawable="@drawable/bg_data_layout_readonly" android:state_enabled="false" />
|
||||
|
||||
</selector>
|
||||
5
module_base/src/main/res/drawable/bg_data_layout_new.xml
Normal file
5
module_base/src/main/res/drawable/bg_data_layout_new.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_data_layout_new_s" android:state_enabled="true" />
|
||||
<item android:drawable="@drawable/bg_data_layout_new_readonly" android:state_enabled="false" />
|
||||
</selector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f2f2f2"/>
|
||||
<corners android:radius="5dp"/>
|
||||
<stroke android:width="1px" android:color="#e4e4e4"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/white"/>
|
||||
<stroke android:width="1dp" android:color="#e4e4e4"/>
|
||||
<corners android:radius="5dp"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#F5F5F5"/>
|
||||
<corners android:radius="4dp"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/backgroud_gray" />
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
||||
8
module_base/src/main/res/drawable/bg_green_light.xml
Normal file
8
module_base/src/main/res/drawable/bg_green_light.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#E8F5E9" />
|
||||
<corners android:radius="4dp" />
|
||||
|
||||
</shape>
|
||||
5
module_base/src/main/res/drawable/bg_green_radius_4.xml
Normal file
5
module_base/src/main/res/drawable/bg_green_radius_4.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#4CAF50" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
||||
5
module_base/src/main/res/drawable/bg_red_btn_bottom.xml
Normal file
5
module_base/src/main/res/drawable/bg_red_btn_bottom.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_red_radius_4" android:state_enabled="true" />
|
||||
<item android:drawable="@drawable/bg_gray_radius_4" android:state_enabled="false" />
|
||||
</selector>
|
||||
7
module_base/src/main/res/drawable/bg_red_radius_4.xml
Normal file
7
module_base/src/main/res/drawable/bg_red_radius_4.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<solid android:color="#dc7771" />
|
||||
<corners android:radius="4dp" />
|
||||
|
||||
</shape>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#E0E0E0" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@drawable/bg_search_layout_s_new" android:state_enabled="true" />
|
||||
<item android:drawable="@drawable/bg_search_layout_n_new" android:state_enabled="false" />
|
||||
|
||||
</selector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/color_f2" />
|
||||
<corners android:radius="20dp" />
|
||||
</shape>
|
||||
9
module_base/src/main/res/drawable/bg_spinner_pda_new.xml
Normal file
9
module_base/src/main/res/drawable/bg_spinner_pda_new.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:width="8.7dp"
|
||||
android:height="6dp"
|
||||
android:drawable="@drawable/img_sp_down"
|
||||
android:gravity="center_vertical|right"
|
||||
android:right="10dp" />
|
||||
</layer-list>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners
|
||||
android:bottomLeftRadius="8dp"
|
||||
android:bottomRightRadius="8dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners
|
||||
android:topLeftRadius="8dp"
|
||||
android:topRightRadius="8dp" />
|
||||
</shape>
|
||||
9
module_base/src/main/res/drawable/ic_arrow_right.xml
Normal file
9
module_base/src/main/res/drawable/ic_arrow_right.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="#999999"
|
||||
android:pathData="M8,4L8,16L12,10L8,4Z"/>
|
||||
</vector>
|
||||
9
module_base/src/main/res/drawable/ic_check_green.xml
Normal file
9
module_base/src/main/res/drawable/ic_check_green.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:fillColor="#4CAF50"
|
||||
android:pathData="M7.5,14.5L3,10L4.4,8.6L7.5,11.7L15.6,3.6L17,5L7.5,14.5Z"/>
|
||||
</vector>
|
||||
10
module_base/src/main/res/drawable/img_add.xml
Normal file
10
module_base/src/main/res/drawable/img_add.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#1C8CF5"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||
</vector>
|
||||
94
module_base/src/main/res/layout/layout_pad_data_new.xml
Normal file
94
module_base/src/main/res/layout/layout_pad_data_new.xml
Normal file
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="4dp"
|
||||
android:focusableInTouchMode="false"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="标题:"
|
||||
android:textColor="@color/text_gray"
|
||||
tools:text="标题" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_data_layout_new"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:paddingStart="10dp"
|
||||
android:textColor="@color/text_normal"
|
||||
android:textColorHint="@color/text_gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_spinner_pda_new"
|
||||
android:overlapAnchor="false"
|
||||
android:spinnerMode="dropdown" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="10dp"
|
||||
android:textColor="@color/text_normal"
|
||||
android:textColorHint="@color/text_gray_l"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_spinner_pda_new"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="10dp"
|
||||
android:textColor="@color/text_normal"
|
||||
android:textColorHint="@color/text_gray"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/scan_code"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_m"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:text="*"
|
||||
android:textColor="@color/red"
|
||||
android:textSize="16sp"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</LinearLayout>
|
||||
64
module_base/src/main/res/layout/layout_pad_search_new.xml
Normal file
64
module_base/src/main/res/layout/layout_pad_search_new.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_margin="5dp"
|
||||
android:background="@drawable/bg_search_layout_new"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:paddingStart="10dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_normal"
|
||||
android:textColorHint="@color/text_gray_l"
|
||||
android:textSize="14sp"
|
||||
tools:text="edittext" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_spinner_pda_new"
|
||||
android:overlapAnchor="false"
|
||||
android:spinnerMode="dropdown" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="10dp"
|
||||
android:textColor="@color/text_normal"
|
||||
android:textColorHint="@color/text_gray_l"
|
||||
android:textSize="14sp"
|
||||
tools:text="textView" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="10dp"
|
||||
android:src="@mipmap/scan_code"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_m"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:text="*"
|
||||
android:textColor="@color/red"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -14,6 +14,7 @@
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/tool_iv_back"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:src="@mipmap/left_icon"
|
||||
|
||||
@@ -32,8 +32,13 @@
|
||||
<color name="text_pink">#EA6BE1</color>
|
||||
<color name="text_red">#d9001b</color>
|
||||
<color name="text_green">#4CAF50</color>
|
||||
<color name="text_orange">#FF9800</color>
|
||||
|
||||
<color name="color_bottom_layout">#5c6890</color>
|
||||
<color name="color_f2">#F2F2F2</color>
|
||||
<color name="line">#EEEEEE</color>
|
||||
<color name="transparent">#00000000</color>
|
||||
|
||||
<color name="bottom_tool_tips_text_color">#797979</color>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcAssembleAllocateBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcAssembleAllocateViewModel
|
||||
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.getLifecycleOwner
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港组装分配列表页
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE)
|
||||
class GjcAssembleAllocateActivity :
|
||||
BaseBindingActivity<ActivityGjcAssembleAllocateBinding, GjcAssembleAllocateViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_assemble_allocate
|
||||
|
||||
override fun viewModelClass() = GjcAssembleAllocateViewModel::class.java
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("组装分配")
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 绑定分页逻辑
|
||||
viewModel.pageModel
|
||||
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
|
||||
|
||||
// 监听刷新事件
|
||||
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH)
|
||||
.observe(this) {
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
// 监听checkbox状态变化事件
|
||||
FlowBus.with<String>(ConstantEvent.EVENT_CHECK_CHANGED)
|
||||
.observe(this) {
|
||||
viewModel.onItemCheckChanged()
|
||||
}
|
||||
|
||||
// 监听全选状态变化,更新图标
|
||||
viewModel.isAllChecked.observe(this) { isAllChecked ->
|
||||
// 通过alpha值表示全选状态:全选时alpha=1.0,未全选时alpha=0.5
|
||||
binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f
|
||||
}
|
||||
|
||||
// 初始化:获取分配人列表
|
||||
viewModel.getAssembleCompanyList()
|
||||
|
||||
// 初始加载
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context) {
|
||||
val starter = Intent(context, GjcAssembleAllocateActivity::class.java)
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcBoxWeighingAddBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcBoxWeighingAddViewModel
|
||||
import com.lukouguoji.module_base.base.BaseBindingActivity
|
||||
import com.lukouguoji.module_base.ktx.setUpperCaseAlphanumericFilter
|
||||
|
||||
/**
|
||||
* 国际出港板箱过磅添加页面
|
||||
@@ -22,6 +23,11 @@ class GjcBoxWeighingAddActivity :
|
||||
setBackArrow("板箱过磅")
|
||||
binding.viewModel = viewModel
|
||||
viewModel.initOnCreated(this)
|
||||
|
||||
// 为架子车号、ULD编码、IMP代码添加大写字母和数字的输入限制
|
||||
binding.carIdInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.uldNoInput.et.setUpperCaseAlphanumericFilter()
|
||||
binding.impCodeInput.et.setUpperCaseAlphanumericFilter()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcHandoverBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcHandoverViewModel
|
||||
import com.lukouguoji.module_base.base.BaseBindingActivity
|
||||
import com.lukouguoji.module_base.common.Constant
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
@@ -25,12 +26,16 @@ class GjcHandoverActivity :
|
||||
setBackArrow("货物交接单")
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化数据
|
||||
viewModel.initOnCreated(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context) {
|
||||
fun start(context: Context, maWbId: Long) {
|
||||
val starter = Intent(context, GjcHandoverActivity::class.java)
|
||||
.putExtra(Constant.Key.MAWB_ID, maWbId)
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ class GjcInspectionDetailsActivity :
|
||||
|
||||
// 右侧文档按钮点击事件
|
||||
findViewById<android.widget.ImageView>(R.id.ivDocument).setOnClickListener {
|
||||
GjcHandoverActivity.start(this)
|
||||
val maWbId = viewModel.dataBean.value?.maWbId ?: 0L
|
||||
GjcHandoverActivity.start(this, maWbId)
|
||||
}
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcQueryBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcQueryViewModel
|
||||
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.getLifecycleOwner
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港查询列表页
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_LIST)
|
||||
class GjcQueryActivity :
|
||||
BaseBindingActivity<ActivityGjcQueryBinding, GjcQueryViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_query
|
||||
|
||||
override fun viewModelClass() = GjcQueryViewModel::class.java
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("国际出港查询")
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 绑定分页逻辑
|
||||
viewModel.pageModel
|
||||
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
|
||||
|
||||
// 监听刷新事件
|
||||
FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
// 初始化代理列表
|
||||
viewModel.initAgentList()
|
||||
|
||||
// 初始加载
|
||||
viewModel.refresh()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context) {
|
||||
val starter = Intent(context, GjcQueryActivity::class.java)
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcQueryDetailsBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcQueryDetailsViewModel
|
||||
import com.lukouguoji.module_base.base.BaseBindingActivity
|
||||
import com.lukouguoji.module_base.base.CustomVP2Adapter
|
||||
import com.lukouguoji.module_base.common.Constant
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港查询详情页面
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_DETAILS)
|
||||
class GjcQueryDetailsActivity :
|
||||
BaseBindingActivity<ActivityGjcQueryDetailsBinding, GjcQueryDetailsViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_query_details
|
||||
override fun viewModelClass() = GjcQueryDetailsViewModel::class.java
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("国际出港查询详情")
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化ViewModel(传入maWbId)
|
||||
viewModel.initOnCreated(intent)
|
||||
|
||||
// 配置ViewPager2
|
||||
binding.vp.adapter = CustomVP2Adapter(
|
||||
viewModel.fragmentList,
|
||||
supportFragmentManager,
|
||||
lifecycle
|
||||
)
|
||||
binding.vp.isUserInputEnabled = false // 禁用滑动
|
||||
binding.vp.offscreenPageLimit = 3 // 预加载3个Fragment
|
||||
|
||||
// 监听Tab索引变化,切换Fragment
|
||||
viewModel.currentTab.observe(this) {
|
||||
binding.vp.setCurrentItem(it, false) // false:无动画
|
||||
}
|
||||
|
||||
// 加载详情数据
|
||||
viewModel.loadDetails()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context, maWbId: Long?) {
|
||||
val starter = Intent(context, GjcQueryDetailsActivity::class.java)
|
||||
.putExtra(Constant.Key.ID, maWbId?.toString() ?: "")
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.google.gson.Gson
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcQueryEditBinding
|
||||
import com.lukouguoji.gjc.viewModel.GjcQueryEditViewModel
|
||||
import com.lukouguoji.module_base.base.BaseBindingActivity
|
||||
import com.lukouguoji.module_base.bean.GjcMaWb
|
||||
import com.lukouguoji.module_base.common.Constant
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港运单修改页
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_EDIT)
|
||||
class GjcQueryEditActivity :
|
||||
BaseBindingActivity<ActivityGjcQueryEditBinding, GjcQueryEditViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_query_edit
|
||||
|
||||
override fun viewModelClass() = GjcQueryEditViewModel::class.java
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("国际出港运单修改")
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化数据
|
||||
viewModel.initOnCreated(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context, bean: GjcMaWb) {
|
||||
val starter = Intent(context, GjcQueryEditActivity::class.java)
|
||||
.putExtra(Constant.Key.DATA, Gson().toJson(bean))
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,8 @@ import com.scwang.smart.refresh.layout.api.RefreshLayout
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_LIST)
|
||||
@Deprecated(message = "废弃的国际出港查询页面,由GjcQueryActivity 接管")
|
||||
//@Route(path = ARouterConstants.ACTIVITY_URL_GJC_QUERY_LIST)
|
||||
class GjcQueryListActivity : BaseActivity(), View.OnClickListener {
|
||||
private val currentTitleName = "国际出港查询"
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@ class GjcWeighingListActivity :
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化代理人列表(从API获取)
|
||||
viewModel.initAgentList()
|
||||
|
||||
// 初始化特码列表(从API获取)
|
||||
viewModel.initSpecialCodeList()
|
||||
|
||||
// 绑定分页逻辑
|
||||
viewModel.pageModel
|
||||
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingRecordDetailsBinding
|
||||
import com.lukouguoji.gjc.holder.GjcCheckInRecordViewHolder
|
||||
import com.lukouguoji.gjc.viewModel.GjcWeighingRecordDetailsViewModel
|
||||
import com.lukouguoji.module_base.base.BaseBindingActivity
|
||||
import com.lukouguoji.module_base.base.CommonAdapter
|
||||
import com.lukouguoji.module_base.bean.GjcWeighingRecordBean
|
||||
import com.lukouguoji.module_base.common.Constant
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港计重明细页
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_DETAILS)
|
||||
class GjcWeighingRecordDetailsActivity :
|
||||
BaseBindingActivity<ActivityGjcWeighingRecordDetailsBinding, GjcWeighingRecordDetailsViewModel>() {
|
||||
|
||||
private lateinit var adapter: CommonAdapter
|
||||
|
||||
// 当前编辑模式(供ViewHolder获取)
|
||||
var currentEditMode = false
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_weighing_record_details
|
||||
|
||||
override fun viewModelClass() = GjcWeighingRecordDetailsViewModel::class.java
|
||||
|
||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||
setBackArrow("计重明细")
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化RecyclerView
|
||||
val layoutManager = LinearLayoutManager(this)
|
||||
binding.recyclerView.layoutManager = layoutManager
|
||||
|
||||
// 添加分割线
|
||||
val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
|
||||
binding.recyclerView.addItemDecoration(divider)
|
||||
|
||||
adapter = CommonAdapter(
|
||||
this,
|
||||
R.layout.item_gjc_check_in_record,
|
||||
GjcCheckInRecordViewHolder::class.java
|
||||
)
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
// 监听数据变化更新RecyclerView
|
||||
viewModel.recordList.observe(this) { records ->
|
||||
adapter.refresh(records)
|
||||
}
|
||||
|
||||
// 监听编辑模式变化,更新当前编辑模式并刷新列表
|
||||
viewModel.isEditMode.observe(this) { isEditMode ->
|
||||
// 更新当前编辑模式状态
|
||||
currentEditMode = isEditMode
|
||||
|
||||
// 刷新所有可见的 ViewHolder
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
viewModel.initOnCreated(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun start(context: Context, bean: GjcWeighingRecordBean) {
|
||||
val starter = Intent(context, GjcWeighingRecordDetailsActivity::class.java)
|
||||
.putExtra(Constant.Key.BEAN, bean)
|
||||
context.startActivity(starter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,12 @@ class GjcWeighingRecordListActivity :
|
||||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
// 初始化代理人列表
|
||||
viewModel.initAgentList()
|
||||
|
||||
// 初始化特码列表
|
||||
viewModel.initSpecialCodeList()
|
||||
|
||||
// 绑定分页逻辑
|
||||
viewModel.pageModel
|
||||
.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, getLifecycleOwner())
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityGjcWeighingStartBinding
|
||||
@@ -18,6 +23,8 @@ import com.lukouguoji.module_base.router.ARouterConstants
|
||||
class GjcWeighingStartActivity :
|
||||
BaseBindingActivity<ActivityGjcWeighingStartBinding, GjcWeighingStartViewModel>() {
|
||||
|
||||
private var isExpanded = false
|
||||
|
||||
override fun layoutId() = R.layout.activity_gjc_weighing_start
|
||||
|
||||
override fun viewModelClass() = GjcWeighingStartViewModel::class.java
|
||||
@@ -26,16 +33,163 @@ class GjcWeighingStartActivity :
|
||||
setBackArrow("开始计重")
|
||||
binding.viewModel = viewModel
|
||||
viewModel.initOnCreated(this, intent)
|
||||
|
||||
setupFloatButtons()
|
||||
}
|
||||
|
||||
private fun setupFloatButtons() {
|
||||
// 主按钮点击事件
|
||||
binding.mainFloatButton.setOnClickListener {
|
||||
if (!isExpanded) {
|
||||
expandButtons()
|
||||
}
|
||||
}
|
||||
|
||||
// 遮罩层点击事件
|
||||
binding.maskView.setOnClickListener {
|
||||
collapseButtons()
|
||||
}
|
||||
|
||||
// 子按钮1点击事件 - 跳转到出港运抵页面
|
||||
binding.subButton1.setOnClickListener {
|
||||
com.alibaba.android.arouter.launcher.ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
|
||||
.navigation()
|
||||
collapseButtons()
|
||||
}
|
||||
|
||||
// 子按钮2点击事件 - 跳转到计重记录
|
||||
binding.subButton2.setOnClickListener {
|
||||
com.alibaba.android.arouter.launcher.ARouter.getInstance()
|
||||
.build(ARouterConstants.ACTIVITY_URL_GJC_WEIGHING_RECORD_LIST)
|
||||
.navigation()
|
||||
collapseButtons()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 展开子按钮
|
||||
*/
|
||||
private fun expandButtons() {
|
||||
isExpanded = true
|
||||
|
||||
// 显示遮罩层
|
||||
binding.maskView.visibility = View.VISIBLE
|
||||
binding.maskView.alpha = 0f
|
||||
binding.maskView.animate().alpha(0.3f).setDuration(200).start()
|
||||
|
||||
// 显示子按钮
|
||||
binding.subButton1.visibility = View.VISIBLE
|
||||
binding.subButton2.visibility = View.VISIBLE
|
||||
|
||||
// 子按钮1动画(向左上方移动: 左移15dp, 上移55dp)
|
||||
val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", 0f, -5f)
|
||||
val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", 0f, -25f)
|
||||
val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 0f, 1f)
|
||||
val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 0f, 1f)
|
||||
val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 0f, 1f)
|
||||
|
||||
val animSet1 = AnimatorSet()
|
||||
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
|
||||
animSet1.duration = 200
|
||||
|
||||
// 子按钮2动画(向左下方移动: 左移55dp, 下移15dp)
|
||||
val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", 0f, -25f)
|
||||
val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", 0f, -5f)
|
||||
val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 0f, 1f)
|
||||
val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 0f, 1f)
|
||||
val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 0f, 1f)
|
||||
|
||||
val animSet2 = AnimatorSet()
|
||||
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
|
||||
animSet2.duration = 200
|
||||
animSet2.startDelay = 50
|
||||
|
||||
// 主按钮隐藏动画
|
||||
binding.mainFloatButton.animate()
|
||||
.scaleX(0f)
|
||||
.scaleY(0f)
|
||||
.alpha(0f)
|
||||
.setDuration(150)
|
||||
.setListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.mainFloatButton.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
.start()
|
||||
|
||||
animSet1.start()
|
||||
animSet2.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* 收起子按钮
|
||||
*/
|
||||
private fun collapseButtons() {
|
||||
isExpanded = false
|
||||
|
||||
// 隐藏遮罩层
|
||||
binding.maskView.animate().alpha(0f).setDuration(200).withEndAction {
|
||||
binding.maskView.visibility = View.GONE
|
||||
}.start()
|
||||
|
||||
// 子按钮1动画(回到原位)
|
||||
val sub1TransX = ObjectAnimator.ofFloat(binding.subButton1, "translationX", binding.subButton1.translationX, 0f)
|
||||
val sub1TransY = ObjectAnimator.ofFloat(binding.subButton1, "translationY", binding.subButton1.translationY, 0f)
|
||||
val sub1Alpha = ObjectAnimator.ofFloat(binding.subButton1, "alpha", 1f, 0f)
|
||||
val sub1Scale = ObjectAnimator.ofFloat(binding.subButton1, "scaleX", 1f, 0f)
|
||||
val sub1ScaleY = ObjectAnimator.ofFloat(binding.subButton1, "scaleY", 1f, 0f)
|
||||
|
||||
val animSet1 = AnimatorSet()
|
||||
animSet1.playTogether(sub1TransX, sub1TransY, sub1Alpha, sub1Scale, sub1ScaleY)
|
||||
animSet1.duration = 200
|
||||
|
||||
// 子按钮2动画(回到原位)
|
||||
val sub2TransX = ObjectAnimator.ofFloat(binding.subButton2, "translationX", binding.subButton2.translationX, 0f)
|
||||
val sub2TransY = ObjectAnimator.ofFloat(binding.subButton2, "translationY", binding.subButton2.translationY, 0f)
|
||||
val sub2Alpha = ObjectAnimator.ofFloat(binding.subButton2, "alpha", 1f, 0f)
|
||||
val sub2Scale = ObjectAnimator.ofFloat(binding.subButton2, "scaleX", 1f, 0f)
|
||||
val sub2ScaleY = ObjectAnimator.ofFloat(binding.subButton2, "scaleY", 1f, 0f)
|
||||
|
||||
val animSet2 = AnimatorSet()
|
||||
animSet2.playTogether(sub2TransX, sub2TransY, sub2Alpha, sub2Scale, sub2ScaleY)
|
||||
animSet2.duration = 200
|
||||
|
||||
animSet1.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.subButton1.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
animSet2.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
binding.subButton2.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
// 主按钮显示动画
|
||||
binding.mainFloatButton.visibility = View.VISIBLE
|
||||
binding.mainFloatButton.animate()
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f)
|
||||
.setDuration(200)
|
||||
.setStartDelay(100)
|
||||
.setListener(null)
|
||||
.start()
|
||||
|
||||
animSet1.start()
|
||||
animSet2.start()
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 启动开始计重页面
|
||||
* @param context 上下文
|
||||
* @param maWbId 运单ID
|
||||
* @param maWbId 运单ID,默认为0(新增模式)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun startForAdd(context: Context, maWbId: Long) {
|
||||
fun startForAdd(context: Context, maWbId: Long = 0) {
|
||||
val starter = Intent(context, GjcWeighingStartActivity::class.java)
|
||||
.putExtra(Constant.Key.MAWB_ID, maWbId)
|
||||
context.startActivity(starter)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityIntExpArriveBinding
|
||||
import com.lukouguoji.gjc.viewModel.IntExpArriveViewModel
|
||||
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.ktx.addOnItemClickListener
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港-出港运抵页面
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
|
||||
class IntExpArriveActivity :
|
||||
BaseBindingActivity<ActivityIntExpArriveBinding, IntExpArriveViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_int_exp_arrive
|
||||
override fun viewModelClass() = IntExpArriveViewModel::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)
|
||||
|
||||
// 设置item点击监听
|
||||
binding.rv.addOnItemClickListener(viewModel)
|
||||
|
||||
// 监听刷新事件
|
||||
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)
|
||||
when (requestCode) {
|
||||
Constant.RequestCode.WAYBILL -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
viewModel.waybillNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
|
||||
viewModel.searchClick()
|
||||
}
|
||||
}
|
||||
Constant.RequestCode.CODE -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
viewModel.hno.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
|
||||
viewModel.searchClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityIntExpLoadBinding
|
||||
import com.lukouguoji.gjc.viewModel.IntExpLoadViewModel
|
||||
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.ktx.addOnItemClickListener
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港-出港装载页面
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_LOAD)
|
||||
class IntExpLoadActivity :
|
||||
BaseBindingActivity<ActivityIntExpLoadBinding, IntExpLoadViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_int_exp_load
|
||||
override fun viewModelClass() = IntExpLoadViewModel::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)
|
||||
|
||||
// 设置item点击监听
|
||||
binding.rv.addOnItemClickListener(viewModel)
|
||||
|
||||
// 监听刷新事件
|
||||
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 (resultCode == Activity.RESULT_OK) {
|
||||
val codedContent = data?.getStringExtra(Constant.Result.CODED_CONTENT) ?: return
|
||||
when (requestCode) {
|
||||
// 扫码运单号
|
||||
Constant.RequestCode.WAYBILL -> {
|
||||
viewModel.waybillNo.value = codedContent
|
||||
viewModel.searchClick()
|
||||
}
|
||||
// 扫码分单号
|
||||
Constant.RequestCode.CODE -> {
|
||||
viewModel.houseWaybillNo.value = codedContent
|
||||
viewModel.searchClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityIntExpOutHandoverBinding
|
||||
import com.lukouguoji.gjc.viewModel.IntExpOutHandoverViewModel
|
||||
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.ktx.addOnItemClickListener
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港-出库交接页面
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_OUT_HANDOVER)
|
||||
class IntExpOutHandoverActivity :
|
||||
BaseBindingActivity<ActivityIntExpOutHandoverBinding, IntExpOutHandoverViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_int_exp_out_handover
|
||||
override fun viewModelClass() = IntExpOutHandoverViewModel::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)
|
||||
|
||||
// 设置item点击监听
|
||||
binding.rv.addOnItemClickListener(viewModel)
|
||||
|
||||
// 监听刷新事件
|
||||
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.ULD && resultCode == Activity.RESULT_OK) {
|
||||
viewModel.uldNo.value = data?.getStringExtra(Constant.Result.CODED_CONTENT)
|
||||
viewModel.searchClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.lukouguoji.gjc.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.ActivityIntExpTallyBinding
|
||||
import com.lukouguoji.gjc.viewModel.IntExpTallyViewModel
|
||||
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.ktx.addOnItemClickListener
|
||||
import com.lukouguoji.module_base.router.ARouterConstants
|
||||
|
||||
/**
|
||||
* 国际出港-出港理货
|
||||
*/
|
||||
@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_TALLY)
|
||||
class IntExpTallyActivity :
|
||||
BaseBindingActivity<ActivityIntExpTallyBinding, IntExpTallyViewModel>() {
|
||||
|
||||
override fun layoutId() = R.layout.activity_int_exp_tally
|
||||
override fun viewModelClass() = IntExpTallyViewModel::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)
|
||||
|
||||
// 设置item点击监听
|
||||
binding.rv.addOnItemClickListener(viewModel)
|
||||
|
||||
// 监听刷新事件
|
||||
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 (resultCode == Activity.RESULT_OK) {
|
||||
val codedContent = data?.getStringExtra(Constant.Result.CODED_CONTENT) ?: return
|
||||
when (requestCode) {
|
||||
Constant.RequestCode.WAYBILL -> { // 运单号
|
||||
viewModel.waybillNo.value = codedContent
|
||||
viewModel.searchClick()
|
||||
}
|
||||
Constant.RequestCode.CODE -> { // 分单号
|
||||
viewModel.houseWaybillNo.value = codedContent
|
||||
viewModel.searchClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogGjcAssembleAllocateBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际出港组装分配 - 分配人选择对话框
|
||||
*/
|
||||
class GjcAssembleAllocateDialogModel(
|
||||
val flightInfo: String, // 航班信息(用于显示)
|
||||
val assembleCompanyList: List<KeyValue>, // 分配人列表
|
||||
private val callback: (GjcAssembleAllocateDialogModel) -> Unit
|
||||
) : BaseDialogModel<DialogGjcAssembleAllocateBinding>(DIALOG_TYPE_CENTER) {
|
||||
|
||||
// 选中的分配人(存储的是 code,例如 "ATR")
|
||||
val allocator = MutableLiveData("")
|
||||
|
||||
override fun layoutId(): Int {
|
||||
return R.layout.dialog_gjc_assemble_allocate
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认按钮点击
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
if (allocator.value.verifyNullOrEmpty("请选择分配人")) {
|
||||
return
|
||||
}
|
||||
dismiss()
|
||||
callback(this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogGjcInspectionRejectBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
|
||||
|
||||
/**
|
||||
* 国际出港收运检查 - 退回原因对话框
|
||||
*/
|
||||
class GjcInspectionRejectDialogModel(
|
||||
private val callback: (String) -> Unit // 回调传递退回原因
|
||||
) : BaseDialogModel<DialogGjcInspectionRejectBinding>(DIALOG_TYPE_CENTER) {
|
||||
|
||||
// 退回原因
|
||||
val rejectReason = MutableLiveData("")
|
||||
|
||||
override fun layoutId(): Int {
|
||||
return R.layout.dialog_gjc_inspection_reject
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存按钮点击
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
// 验证退回原因
|
||||
if (rejectReason.value.verifyNullOrEmpty("请输入退回原因")) {
|
||||
return
|
||||
}
|
||||
|
||||
dismiss()
|
||||
callback(rejectReason.value!!)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogGjcQueryFilterBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lxj.xpopup.XPopup
|
||||
import com.lxj.xpopup.enums.PopupPosition
|
||||
import dev.DevUtils
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际出港查询筛选抽屉
|
||||
*/
|
||||
class GjcQueryFilterDialogModel(
|
||||
val spCode: MutableLiveData<String>, // 特码
|
||||
val flightNo: MutableLiveData<String>, // 航班号
|
||||
val dest: MutableLiveData<String>, // 目的港
|
||||
val awbType: MutableLiveData<String>, // 运单类型
|
||||
val businessType: MutableLiveData<String>, // 业务类型
|
||||
val goodsCn: MutableLiveData<String>, // 品名(中)
|
||||
private val onConfirm: () -> Unit
|
||||
) : BaseDialogModel<DialogGjcQueryFilterBinding>(DIALOG_TYPE_DRAWER) {
|
||||
|
||||
// 运单类型列表
|
||||
val awbTypeList = MutableLiveData(
|
||||
listOf(
|
||||
KeyValue("全部", ""),
|
||||
KeyValue("主单", "1"),
|
||||
KeyValue("分单", "2")
|
||||
)
|
||||
)
|
||||
|
||||
// 业务类型列表
|
||||
val businessTypeList = MutableLiveData(
|
||||
listOf(
|
||||
KeyValue("全部", ""),
|
||||
KeyValue("普货", "1"),
|
||||
KeyValue("特货", "2")
|
||||
)
|
||||
)
|
||||
|
||||
override fun layoutId() = R.layout.dialog_gjc_query_filter
|
||||
|
||||
override fun onBuild(builder: XPopup.Builder) {
|
||||
super.onBuild(builder)
|
||||
// 设置从右边弹出
|
||||
builder.popupPosition(PopupPosition.Right)
|
||||
|
||||
// 设置抽屉宽度为 Activity contentView 宽度的1/3(横屏长边)
|
||||
val activity = DevUtils.getTopActivity()
|
||||
val activityWidth = activity.window.decorView.width
|
||||
builder.maxWidth(activityWidth / 3)
|
||||
builder.popupWidth(activityWidth / 3)
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
binding.lifecycleOwner = context as? androidx.lifecycle.LifecycleOwner
|
||||
|
||||
val titleColor = Color.parseColor("#666666")
|
||||
|
||||
// 设置标题
|
||||
binding.root.findViewById<TextView>(R.id.title_name)?.text = "筛选条件"
|
||||
binding.root.findViewById<TextView>(R.id.title_name)?.setTextColor(titleColor)
|
||||
binding.root.findViewById<TextView>(R.id.tool_tv_back)?.setTextColor(titleColor)
|
||||
binding.root.findViewById<ImageView>(R.id.tool_iv_back)?.imageTintList = ColorStateList.valueOf(titleColor)
|
||||
binding.root.findViewById<View>(R.id.toolbar)?.setBackgroundColor(Color.WHITE)
|
||||
|
||||
// 返回按钮
|
||||
binding.root.findViewById<View>(R.id.tool_back)?.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置筛选条件
|
||||
*/
|
||||
fun onResetClick() {
|
||||
spCode.value = ""
|
||||
flightNo.value = ""
|
||||
dest.value = ""
|
||||
awbType.value = ""
|
||||
businessType.value = ""
|
||||
goodsCn.value = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认筛选
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
dismiss()
|
||||
onConfirm()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogIntExpArriveDeleteBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际出港运抵 - 删除申报对话框
|
||||
*/
|
||||
class IntExpArriveDeleteDialogModel(
|
||||
val changeReasonList: List<KeyValue>, // 变更原因列表
|
||||
private val callback: (IntExpArriveDeleteDialogModel) -> Unit
|
||||
) : BaseDialogModel<DialogIntExpArriveDeleteBinding>(DIALOG_TYPE_CENTER) {
|
||||
|
||||
// 变更原因代码(存储的是 code)
|
||||
val changeReason = MutableLiveData("")
|
||||
|
||||
// 联系人姓名
|
||||
val contactName = MutableLiveData("")
|
||||
|
||||
// 联系人电话
|
||||
val contactPhone = MutableLiveData("")
|
||||
|
||||
override fun layoutId(): Int {
|
||||
return R.layout.dialog_int_exp_arrive_delete
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认按钮点击
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
// 验证变更原因
|
||||
if (changeReason.value.verifyNullOrEmpty("请选择变更原因")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人姓名
|
||||
if (contactName.value.verifyNullOrEmpty("请输入联系人姓名")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人电话
|
||||
if (contactPhone.value.verifyNullOrEmpty("请输入联系人电话")) {
|
||||
return
|
||||
}
|
||||
|
||||
dismiss()
|
||||
callback(this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogIntExpLoadDeleteBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际出港装载 - 删除申报对话框
|
||||
*/
|
||||
class IntExpLoadDeleteDialogModel(
|
||||
val changeReasonList: List<KeyValue>, // 变更原因列表
|
||||
private val callback: (IntExpLoadDeleteDialogModel) -> Unit
|
||||
) : BaseDialogModel<DialogIntExpLoadDeleteBinding>(DIALOG_TYPE_CENTER) {
|
||||
|
||||
// 变更原因代码(存储的是 code)
|
||||
val changeReason = MutableLiveData("")
|
||||
|
||||
// 联系人姓名
|
||||
val contactName = MutableLiveData("")
|
||||
|
||||
// 联系人电话
|
||||
val contactPhone = MutableLiveData("")
|
||||
|
||||
override fun layoutId(): Int {
|
||||
return R.layout.dialog_int_exp_load_delete
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认按钮点击
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
// 验证变更原因
|
||||
if (changeReason.value.verifyNullOrEmpty("请选择变更原因")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人姓名
|
||||
if (contactName.value.verifyNullOrEmpty("请输入联系人姓名")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人电话
|
||||
if (contactPhone.value.verifyNullOrEmpty("请输入联系人电话")) {
|
||||
return
|
||||
}
|
||||
|
||||
dismiss()
|
||||
callback(this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.lukouguoji.gjc.dialog
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.lukouguoji.gjc.R
|
||||
import com.lukouguoji.gjc.databinding.DialogIntExpTallyDeleteBinding
|
||||
import com.lukouguoji.module_base.base.BaseDialogModel
|
||||
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
|
||||
import dev.utils.app.info.KeyValue
|
||||
|
||||
/**
|
||||
* 国际出港理货 - 删除申报对话框
|
||||
*/
|
||||
class IntExpTallyDeleteDialogModel(
|
||||
val changeReasonList: List<KeyValue>, // 变更原因列表
|
||||
private val callback: (IntExpTallyDeleteDialogModel) -> Unit
|
||||
) : BaseDialogModel<DialogIntExpTallyDeleteBinding>(DIALOG_TYPE_CENTER) {
|
||||
|
||||
// 变更原因代码(存储的是 code)
|
||||
val changeReason = MutableLiveData("")
|
||||
|
||||
// 联系人姓名
|
||||
val contactName = MutableLiveData("")
|
||||
|
||||
// 联系人电话
|
||||
val contactPhone = MutableLiveData("")
|
||||
|
||||
override fun layoutId(): Int {
|
||||
return R.layout.dialog_int_exp_tally_delete
|
||||
}
|
||||
|
||||
override fun onDialogCreated(context: Context) {
|
||||
binding.model = this
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认按钮点击
|
||||
*/
|
||||
fun onConfirmClick() {
|
||||
// 验证变更原因
|
||||
if (changeReason.value.verifyNullOrEmpty("请选择变更原因")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人姓名
|
||||
if (contactName.value.verifyNullOrEmpty("请输入联系人姓名")) {
|
||||
return
|
||||
}
|
||||
|
||||
// 验证联系人电话
|
||||
if (contactPhone.value.verifyNullOrEmpty("请输入联系人电话")) {
|
||||
return
|
||||
}
|
||||
|
||||
dismiss()
|
||||
callback(this)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user