init: init proj
This commit is contained in:
448
CLAUDE.md
Normal file
448
CLAUDE.md
Normal file
@@ -0,0 +1,448 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user