449 lines
11 KiB
Markdown
449 lines
11 KiB
Markdown
# 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
|