Files
aerologic-app/CLAUDE.md
2025-11-10 18:21:19 +08:00

449 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 项目概述
**AirLogistics (航空物流信息App)** - Android原生应用用于管理航空物流的全流程操作包括国内外货物进出港、仓储管理、车辆调度等核心业务。
- **包名**: com.lukouguoji.aerologic
- **当前版本**: 1.7.9 (versionCode 79)
- **开发语言**: Kotlin + Java混合
- **架构模式**: MVVM + 组件化
- **最低SDK**: Android 7.0 (API 24)
- **目标SDK**: Android 10 (API 30)
## 构建与运行
### 环境准备
1. **依赖下载问题解决**:
- 下载gradle-7.3.3-bin.zip: https://pan.baidu.com/s/18wsuGRlNxjMYbxLhBH9yeg (提取码: 1029)
- 打开 Settings -> Build, Execution, Deployment > Build Tools > Gradle
- 将下载的文件解压后替换到 "Gradle user home" 目录中
2. **配置IP地址**:
- 内网地址配置在 `module_base/src/main/res/values/strings.xml` 中的 `system_url_inner`
- 地磅地址: `weight_url`
- 运行时可通过SharedPreferences修改IP地址
### 构建命令
```bash
# 组件化开发模式切换
# 编辑 gradle.properties 中的 isBuildModule
# true: 模块可独立运行调试
# false: 模块作为library集成默认
# 构建Debug版本
./gradlew assembleDebug
# 构建Release版本已签名
./gradlew assembleRelease
# 安装到设备
./gradlew installDebug
# 清理构建
./gradlew clean
```
### 测试命令
```bash
# 运行单元测试
./gradlew test
# 运行特定模块的测试
./gradlew :module_base:test
./gradlew :app:test
# 运行UI测试
./gradlew connectedAndroidTest
```
## 核心架构
### 模块化结构
项目采用**组件化架构**,通过`isBuildModule`参数控制模块独立运行或作为library集成
- **app**: 应用壳层,整合所有业务模块,提供主界面框架
- **module_base**: 核心基础库(可独立运行),提供所有通用能力
- **module_gnc**: 国内出港业务(收运、复磅、装机等)
- **module_gnj**: 国内进港业务(卸机、提货、移库等)
- **module_gjc**: 国际出港业务板箱组装、ULD管理等
- **module_gjj**: 国际进港业务(舱单、理货、交接等)
- **module_hangban**: 航班查询管理
- **module_cargo**: 货物追踪查询
- **module_mit**: 监装监卸管理
- **module_p**: PDA专用功能
- **Printer**: 蓝牙打印模块佳博SDK
- **MPChartLib**: 定制图表库
### MVVM架构模式
所有业务页面遵循统一的MVVM模式
```
Activity/Fragment (View层)
↓ 继承
BaseBindingActivity<ViewDataBinding, ViewModel>
↓ 持有
ViewModel (业务逻辑层)
↓ 继承
BaseViewModel / BasePageViewModel
↓ 调用
Repository (数据层: Retrofit API)
```
**关键基类**:
- `BaseBindingActivity`: 提供DataBinding和ViewModel绑定
- `BaseViewModel`: 提供Loading管理、Lifecycle感知
- `BasePageViewModel`: 扩展分页列表功能
- `CommonAdapter + BaseViewHolder`: 列表适配器统一封装
### 网络请求架构
**核心组件**:
- `ServiceCreator`: Retrofit实例创建管理BaseURL和拦截器
- `NetApply.api`: 统一的API调用入口
- `RequestKtx.kt`: 协程+Flow的扩展函数封装
**标准请求模式**:
```kotlin
// 使用launchCollect扩展函数无Loading
launchCollect({
NetApply.api.simplePost("endpoint", params.toRequestBody())
}) {
onSuccess = { result: BaseResultBean<T> ->
// 成功处理result.data为返回数据
}
onFailed = { code, message ->
// 失败处理默认会showToast(message)
}
onComplete = {
// 请求完成(无论成功失败)
}
}
// 使用launchLoadingCollect带Loading弹窗
launchLoadingCollect({
NetApply.api.simplePost("endpoint", params.toRequestBody())
}) {
onSuccess = { result -> }
onFailed = { code, message -> }
}
```
**API接口定义** (在 `module_base/http/user/interface/CommonService.kt`):
```kotlin
@POST("{url}")
suspend fun simplePost(
@Path("url", encoded = true) url: String,
@Body data: RequestBody
): BaseResultBean<T>
```
### 路由系统
使用**ARouter**进行模块间页面跳转:
```kotlin
// 路由常量定义在 ARouterConstants
ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_XXX)
.withString("key", value)
.navigation()
// 获取参数
@Autowired(name = "key")
@JvmField
var param: String? = null
// 在onCreate中调用
ARouter.getInstance().inject(this)
```
### 事件通信
**FlowBus** (module_base/impl/FlowBus.kt) - 基于Kotlin Flow的事件总线
```kotlin
// 发送事件
FlowBus.post(ConstantEvent.EVENT_NAME, data)
// 接收事件在ViewModel中
FlowBus.on<T>(ConstantEvent.EVENT_NAME).collect { data ->
// 处理事件
}
```
常用事件常量定义在 `ConstantEvent.kt`
### 数据模型规范
所有API返回数据统一使用 `BaseResultBean<T>`:
```kotlin
data class BaseResultBean<T>(
val status: Int, // 状态码
val msg: String, // 消息
val data: T // 实际数据
)
```
业务Bean统一定义在 `module_base/bean/` 目录下使用Kotlin data class。
## 关键技术点
### 屏幕适配
- **横屏设计尺寸**: 1152dp × 720dp主要场景
- **竖屏设计尺寸**: 720dp × 1280dp
- **强制横屏**: 所有Activity在AndroidManifest中配置 `android:screenOrientation="userLandscape"`
- **适配库**: AutoSize 1.2.+
### 蓝牙打印
**核心类**:
- `Printer` 模块:独立的打印服务
- `PrinterService`: 后台打印服务
- `PrinterConfig`: 打印机配置管理
- 使用佳博SDK 2.0.4
**打印流程**:
1. 启动PrinterService
2. 扫描/绑定蓝牙打印机
3. 构建打印数据(DataForSendToPrinter)
4. 发送打印任务
### 扫码功能
- 使用 ZXing 2.2.9 库
- 扫描条形码/二维码
- 主要用于运单号、ULD编号、车辆编号、板箱编号
### 权限管理
使用 AndPermission 2.0.2
```kotlin
AndPermission.with(this)
.runtime()
.permission(Permission.CAMERA)
.onGranted { }
.onDenied { }
.start()
```
### 图片选择
使用 PictureSelector v3.11.2 + Glide 4.15.1
```kotlin
PictureSelector.create(this)
.openGallery(SelectMimeType.ofImage())
.setImageEngine(GlideEngine.createGlideEngine())
.forResult { result -> }
```
## 开发规范
### 新增功能页面
1. **创建页面结构** (按 list/details/add 组织):
```
page/
└── feature/
├── list/
│ ├── FeatureListActivity.kt
│ ├── FeatureListViewModel.kt
│ └── FeatureListViewHolder.kt
├── details/
│ ├── FeatureDetailsActivity.kt
│ └── FeatureDetailsViewModel.kt
└── add/
├── FeatureAddActivity.kt
└── FeatureAddViewModel.kt
```
2. **在ARouterConstants中注册路由**:
```kotlin
const val ACTIVITY_URL_FEATURE_LIST = "/feature/list"
```
3. **在CommonService中添加API接口**:
```kotlin
@POST("api/feature/list")
suspend fun getFeatureList(@Body data: RequestBody): BaseResultBean<List<FeatureBean>>
```
4. **创建数据Bean** (在module_base/bean/):
```kotlin
data class FeatureBean(
val id: String,
val name: String
// 其他字段...
)
```
### Activity开发模板
```kotlin
@Route(path = ARouterConstants.ACTIVITY_URL_XXX)
class XxxActivity : BaseBindingActivity<ActivityXxxBinding, XxxViewModel>() {
override fun getViewBinding() = ActivityXxxBinding.inflate(layoutInflater)
override fun getViewModel() = ViewModelProvider(this)[XxxViewModel::class.java]
override fun initView() {
// 初始化UI
binding.apply {
viewModel = this@XxxActivity.viewModel
}
}
override fun initData() {
// 加载数据
viewModel.loadData()
}
override fun addListener() {
// 添加监听器
}
override fun addObserver() {
// 观察LiveData/Flow
}
}
```
### ViewModel开发模板
```kotlin
class XxxViewModel : BasePageViewModel() {
// LiveData定义
val dataList = MutableLiveData<List<DataBean>>()
fun loadData() {
launchLoadingCollect({
NetApply.api.simplePost("endpoint", params.toRequestBody())
}) {
onSuccess = { result ->
dataList.value = result.data
}
}
}
}
```
### 列表开发模板
```kotlin
// ViewHolder
class XxxViewHolder(itemView: View) : BaseViewHolder<XxxBean>(itemView) {
override fun onBindViewHolder(item: XxxBean, position: Int) {
// 绑定数据到视图
}
}
// Activity中使用
val adapter = CommonAdapter(
R.layout.item_xxx,
dataList
) { XxxViewHolder(it) }
binding.recyclerView.adapter = adapter
```
## 常见业务场景
### 扫码后查询
```kotlin
// 启动扫码
ARouter.getInstance()
.build(ARouterConstants.ACTIVITY_URL_SCAN)
.navigation(this, REQUEST_CODE_SCAN)
// 处理扫码结果
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_CODE_SCAN && resultCode == RESULT_OK) {
val code = data?.getStringExtra("code")
// 调用查询接口
}
}
```
### 打印标签
```kotlin
// 绑定打印服务
bindService(Intent(this, PrinterService::class.java), serviceConnection, BIND_AUTO_CREATE)
// 打印
val printData = DataForSendToPrinter()
// 构建打印内容...
printerService?.sendPrintData(printData)
```
### 图片上传
```kotlin
// 选择图片
PictureSelector.create(this)
.openGallery(SelectMimeType.ofImage())
.forResult { result ->
val path = result[0].realPath
uploadImage(path)
}
// 上传接口
@Multipart
@POST("api/upload")
suspend fun uploadImage(@Part file: MultipartBody.Part): BaseResultBean<FileBean>
```
## 重要配置文件
### 签名配置
- **KeyStore**: `key.jks` (项目根目录)
- **密码**: storePassword/keyPassword均为 `123321`
- **别名**: `key`
### 网络配置
- **超时时间**: 30秒连接/读取/写入)
- **认证方式**: Bearer Token通过拦截器自动添加
- **Token存储**: SharedPreferences (key: Constant.Share.token)
- **网络安全配置**: `res/xml/network_security_config.xml` (支持HTTP)
### 数据持久化
- **SharedPreferences**: IP地址、Token、用户信息、角色
- **关键常量**: 定义在 `Constant.kt` 和 `ConstantEvent.kt`
## Git分支管理
- **当前开发分支**: feature/hefei
- **主分支**: develop用于PR
- **提交前**: 确保代码通过编译,无明显错误
## 技术栈速查
- **协程**: kotlinx-coroutines 1.6.0
- **网络**: Retrofit 2.6.1 + OkHttp 3.12.12
- **JSON**: FastJSON 1.2.73 + Gson 2.10.1
- **路由**: ARouter 1.5.2
- **下拉刷新**: SmartRefreshLayout 2.0.3
- **图表**: MPAndroidChart (定制版)
- **弹窗**: XPopup 2.9.19
- **图片**: Glide 4.15.1 + PictureSelector v3.11.2
- **扫码**: ZXing 2.2.9
- **权限**: AndPermission 2.0.2
- **打印**: 佳博SDK 2.0.4
- **日志**: Timber 5.0.1
- **事件**: EventBus 3.1.1 + FlowBus