地址管理

This commit is contained in:
pqcqaq 2025-10-26 11:03:09 +08:00
parent 3e87ee8567
commit 2ef1c55e5f
1 changed files with 785 additions and 0 deletions

View File

@ -0,0 +1,785 @@
# 地址管理功能文档
## 1. 功能概述
**参考路径**:
- `oak-general-business/src/entities/Address.ts`
- `oak-general-business/src/entities/Area.ts`
- `oak-general-business/src/entities/Station.ts`
- `oak-general-business/src/entities/Subway.ts`
- `oak-general-business/src/entities/SubwayStation.ts`
### 1.1 功能目的
地址管理功能为应用提供了完整的地理位置和地址信息管理能力,主要包括:
- **收货地址管理**: 用户可以创建、编辑、删除收货地址,支持设置默认地址
- **地区选择**: 提供省市区街道四级地区选择功能,数据覆盖全国
- **地铁线路查询**: 支持地铁线路和站点的管理与查询
- **地图定位**: 集成高德地图,支持地图选点和位置定位
### 1.2 应用场景
1. **电商场景**
- 用户添加收货地址
- 选择配送区域
- 根据地址计算运费
2. **O2O 服务**
- 选择服务地点
- 查找附近门店
- 地铁站点附近的商户推荐
3. **物流配送**
- 配送地址管理
- 配送范围设置
- 路线规划
4. **位置服务**
- 签到打卡
- 轨迹记录
- 地理围栏
### 1.3 核心价值
- **完整的地区数据**: 提供全国省市区街道四级地区数据,包含地区编码和中心坐标
- **地铁数据支持**: 内置主要城市的地铁线路和站点数据
- **多平台适配**: 支持 Web PC、Web Mobile、微信小程序等多平台
- **灵活的地址格式**: 支持关联任意实体的地址信息
- **地图集成**: 提供高德地图集成组件,支持可视化选址
### 1.4 与其他功能模块的关系
```mermaid
graph TB
Address[地址管理] --> User[用户系统]
Address --> Area[地区数据]
Address --> Subway[地铁数据]
Address --> Entity[任意业务实体]
Area --> Province[省份]
Area --> City[城市]
Area --> District[区县]
Area --> Street[街道]
Subway --> SubwayLine[地铁线路]
SubwayLine --> Station[地铁站点]
SubwayStation --> SubwayLine
SubwayStation --> Station
Address -.关联.-> Order[订单]
Address -.关联.-> Store[门店]
Address -.关联.-> Service[服务]
```
---
## 2. 实体定义详解
**参考路径**:
- `oak-general-business/src/entities/Address.ts`
- `oak-general-business/src/entities/Area.ts`
- `oak-general-business/src/entities/Station.ts`
- `oak-general-business/src/entities/Subway.ts`
- `oak-general-business/src/entities/SubwayStation.ts`
### 2.1 Address地址
地址实体用于存储用户的收货地址或其他类型的地址信息。
#### 字段定义
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `detail` | `String<32>` | 是 | 详细地址(街道门牌号等) |
| `area` | `Area` | 是 | 所在地区(关联到 Area 实体) |
| `phone` | `String<12>` | 是 | 联系电话 |
| `name` | `String<32>` | 是 | 收件人姓名 |
| `default` | `Boolean` | 是 | 是否为默认地址 |
| `remark` | `Text` | 否 | 备注信息 |
| `entity` | `String<32>` | 否 | 关联的实体类型(如 user、store |
| `entityId` | `String<64>` | 否 | 关联的实体 ID |
#### Action 和 State
Address 实体没有定义特殊的 Action 和 State使用标准的 CRUD 操作。
#### 业务规则
- 每个用户/实体可以有多个地址
- 只能有一个默认地址
- 通过 `entity``entityId` 可以将地址关联到任意业务实体
---
### 2.2 Area地区
地区实体存储全国的行政区划数据,包括省市区街道四级。
#### 字段定义
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `name` | `String<32>` | 是 | 地区名称 |
| `level` | `Enum` | 是 | 层级类型:`country`、`province`、`city`、`district`、`street` |
| `depth` | `0\|1\|2\|3\|4` | 是 | 深度0=国家、1=省、2=市、3=区、4=街道 |
| `parent` | `Area` | 否 | 上级地区(自关联) |
| `code` | `String<12>` | 是 | 地区编码(国家标准行政区划代码) |
| `center` | `Geo` | 是 | 中心坐标(经纬度) |
#### 层级说明
```mermaid
graph TD
Country[国家 depth=0] --> Province[省 depth=1]
Province --> City[市 depth=2]
City --> District[区/县 depth=3]
District --> Street[街道 depth=4]
```
#### 配置特性
- **actionType**: `readOnly` - 只读实体,不允许通过界面修改
- **static**: `true` - 静态数据,通常预加载到缓存
#### 颜色配置
不同层级的地区在界面上有不同的颜色标识:
- 国家country: `#2F4F4F`
- 省province: `#00FF7F`
- 市city: `#1E90FF`
- 区district: `#4682B4`
- 街道street: `#808080`
---
### 2.3 Station站点
站点实体存储交通站点信息(主要是地铁站点)。
#### 字段定义
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `name` | `String<32>` | 是 | 站点名称 |
| `area` | `Area` | 是 | 所在城市(关联到 Area |
---
### 2.4 Subway地铁线路
地铁线路实体存储城市的地铁线路信息。
#### 字段定义
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `name` | `String<32>` | 是 | 线路名称(如"1号线" |
| `area` | `Area` | 是 | 所在城市(关联到 Area |
---
### 2.5 SubwayStation地铁站点连接表
地铁站点连接表用于关联地铁线路和站点,因为一个站点可能属于多条线路(换乘站)。
#### 字段定义
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `station` | `Station` | 是 | 站点 |
| `subway` | `Subway` | 是 | 地铁线路 |
#### 关系说明
这是一个典型的多对多关系中间表:
- 一个地铁线路包含多个站点
- 一个站点可以属于多条地铁线路(换乘站)
---
### 2.6 实体关系图ER Diagram
```mermaid
erDiagram
Address ||--o{ Area : "所在地区"
Address ||--o| User : "关联用户"
Address ||--o| Entity : "关联其他实体"
Area ||--o{ Area : "上级地区"
Area ||--o{ Station : "所在城市"
Area ||--o{ Subway : "所在城市"
Subway ||--|{ SubwayStation : "包含站点"
Station ||--|{ SubwayStation : "属于线路"
SubwayStation }o--|| Subway : "地铁线路"
SubwayStation }o--|| Station : "站点"
```
### 2.7 数据示例
#### Address 示例
```typescript
{
id: "addr_001",
name: "张三",
phone: "13800138000",
area: {
id: "330106",
name: "西湖区",
parent: {
id: "330100",
name: "杭州市",
parent: {
id: "330000",
name: "浙江省"
}
}
},
detail: "文三路XX号XX室",
default: true,
entity: "user",
entityId: "user_123"
}
```
#### Area 示例
```typescript
{
id: "330106",
name: "西湖区",
level: "district",
depth: 3,
code: "330106",
center: {
lat: 30.2591,
lng: 120.1294
},
parentId: "330100"
}
```
---
## 3. 业务逻辑说明
**参考路径**:
- `oak-general-business/src/triggers/address.ts`
- `oak-general-business/src/components/address/`
- `oak-general-business/src/components/area/`
- `oak-general-business/src/components/pickers/area/`
### 3.1 核心业务流程
#### 3.1.1 添加收货地址流程
```mermaid
flowchart TD
Start[用户点击添加地址] --> Input[填写收件人和电话]
Input --> SelectArea[选择省市区]
SelectArea --> Cache{从缓存加载地区}
Cache -->|有缓存| ShowArea[显示地区列表]
Cache -->|无缓存| LoadArea[加载地区数据]
LoadArea --> ShowArea
ShowArea --> SelectProvince[选择省份]
SelectProvince --> LoadCity[加载城市列表]
LoadCity --> SelectCity[选择城市]
SelectCity --> LoadDistrict[加载区县列表]
LoadDistrict --> SelectDistrict[选择区县]
SelectDistrict --> InputDetail[填写详细地址]
InputDetail --> SetDefault{设为默认地址?}
SetDefault -->|是| CheckDefault[检查已有默认地址]
SetDefault -->|否| Save[保存地址]
CheckDefault --> UpdateOld[取消旧默认地址]
UpdateOld --> Save
Save --> Success[保存成功]
Success --> Back[返回地址列表]
```
#### 3.1.2 地区选择器逻辑
```mermaid
sequenceDiagram
participant User as 用户
participant Picker as 地区选择器
participant Cache as 缓存
participant DB as 数据库
User->>Picker: 打开地区选择
Picker->>Cache: 查询省份列表
Cache->>DB: filter: parent.level='country'
DB-->>Cache: 返回省份数据
Cache-->>Picker: 显示省份
User->>Picker: 选择省份
Picker->>Cache: 查询该省的城市
Cache->>DB: filter: parentId=省份ID
DB-->>Cache: 返回城市数据
Cache-->>Picker: 显示城市
User->>Picker: 选择城市
Picker->>Cache: 查询该市的区县
Cache->>DB: filter: parentId=城市ID
DB-->>Cache: 返回区县数据
Cache-->>Picker: 显示区县
User->>Picker: 选择区县
Picker->>User: 返回选中的地区ID
```
#### 3.1.3 默认地址管理逻辑
当用户将某个地址设为默认地址时:
1. 查询当前用户/实体的所有地址
2. 将原默认地址的 `default` 字段设为 `false`
3. 将新地址的 `default` 字段设为 `true`
4. 保存更新
**注意**: 这个逻辑通常在前端实现,也可以通过 Trigger 在后端实现。
### 3.2 地铁线路查询流程
```mermaid
flowchart TD
Start[打开地铁选择器] --> LoadCity[加载有地铁的城市]
LoadCity --> SelectCity[选择城市]
SelectCity --> LoadSubway[加载该城市的地铁线路]
LoadSubway --> ShowSubway[显示地铁线路列表]
ShowSubway --> SelectSubway[选择地铁线路]
SelectSubway --> LoadStation[加载该线路的站点]
LoadStation --> ShowStation[显示站点列表]
ShowStation --> SelectStation[用户选择站点]
SelectStation --> Return[返回选中的站点]
```
### 3.3 Trigger 逻辑
**参考路径**: `oak-general-business/src/triggers/address.ts`
当前 Address 实体没有定义特殊的 Trigger使用标准的 CRUD 操作。
如果需要实现自动设置默认地址的逻辑,可以添加如下 Trigger
```typescript
const triggers: Trigger<EntityDict, 'address', BRC<EntityDict>>[] = [
{
name: 'beforeCreate',
async handler({ data, cxt }) {
// 如果是第一个地址,自动设为默认
const existingAddresses = await cxt.ref('address').find({
filter: {
entity: data.entity,
entityId: data.entityId,
}
});
if (existingAddresses.length === 0) {
data.default = true;
}
// 如果设为默认,取消其他地址的默认状态
if (data.default) {
await cxt.ref('address').updateMany({
filter: {
entity: data.entity,
entityId: data.entityId,
default: true,
},
update: {
default: false,
}
});
}
}
}
];
```
### 3.4 Feature 和 Cache
地区数据通常会被缓存以提高性能:
```typescript
// 通过 cache feature 加载地区数据
await this.features.cache.refresh('area', {
data: {
id: 1,
name: 1,
level: 1,
},
filter: {
level: 'city',
},
});
```
---
## 4. 前端组件使用
**参考路径**:
- `oak-general-business/src/components/address/`
- `oak-general-business/src/components/area/`
- `oak-general-business/src/components/pickers/area/`
- `oak-general-business/src/components/subwayLine/`
- `oak-general-business/src/components/amap/`
### 4.1 组件列表
| 组件名称 | 导入路径 | 说明 |
|---------|---------|------|
| AddressList | `oak-general-business/es/components/address/list` | 地址列表组件 |
| AddressUpsert | `oak-general-business/es/components/address/upsert` | 地址编辑/新增组件 |
| AreaUpsert | `oak-general-business/es/components/area/upsert` | 地区编辑组件(管理端) |
| AreaPicker | `oak-general-business/es/components/pickers/area` | 地区选择器 |
| SubwayLineList | `oak-general-business/es/components/subwayLine/list` | 地铁线路列表 |
| SubwayLinePicker | `oak-general-business/es/components/subwayLine/picker` | 地铁选择器 |
| AmapLocation | `oak-general-business/es/components/amap/location` | 高德地图定位组件 |
| AmapMap | `oak-general-business/es/components/amap/map` | 高德地图组件 |
---
### 4.2 AddressList - 地址列表组件
**导入路径**: `oak-general-business/es/components/address/list`
**参考文件**: `src/components/address/list/index.ts`
#### Props 定义
该组件基于 OakComponent自动绑定 Address 实体。
#### 主要方法
| 方法名 | 参数 | 说明 |
|--------|------|------|
| `goNewAddress()` | 无 | 跳转到新增地址页面 |
| `gotoUpsert(oakId)` | `oakId: string` | 跳转到编辑地址页面 |
#### 数据结构
组件将地址数据格式化为:
```typescript
{
addresses: [
{
id: string,
name: string, // 收件人
phone: string, // 电话
districtName: string, // 区县名
areaText: string, // 完整地区(省市区)
detail: string // 详细地址
}
]
}
```
---
### 4.3 AddressUpsert - 地址编辑组件
**导入路径**: `oak-general-business/es/components/address/upsert`
**参考文件**: `src/components/address/upsert/index.ts`
#### 主要方法
| 方法名 | 参数 | 说明 |
|--------|------|------|
| `setValue(input)` | `input: CustomEvent` | 设置表单字段值 |
| `callAreaPicker()` | 无 | 调用地区选择器 |
| `confirm()` | 无 | 确认保存地址 |
| `reset()` | 无 | 重置表单 |
#### 数据结构
```typescript
{
name: string, // 收件人姓名
phone: string, // 联系电话
districtName: string, // 区县名
area: Area, // 地区对象
areaText: string, // 完整地区文本
detail: string // 详细地址
}
```
---
### 4.4 AreaPicker - 地区选择器
**导入路径**: `oak-general-business/es/components/pickers/area`
**参考文件**: `src/components/pickers/area/index.ts`
#### Props 定义
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `depth` | `number` | `3` | 地区深度1=省、2=市、3=区、4=街道 |
| `onAreaSelected` | `(id: string) => void` | - | 地区选择回调函数 |
#### 主要方法
| 方法名 | 参数 | 说明 |
|--------|------|------|
| `onItemClicked(item)` | `item: Area` | 点击地区项 |
| `onWechatMpItemClicked(input)` | `input: CustomEvent` | 小程序点击事件 |
#### 工作原理
1. 初始加载省份列表parent.level='country'
2. 用户选择省份后,加载该省的城市列表
3. 用户选择城市后,加载该市的区县列表
4. 达到指定 depth 后,触发 `onAreaSelected` 回调
---
### 4.5 SubwayLinePicker - 地铁选择器
**导入路径**: `oak-general-business/es/components/subwayLine/picker`
**参考文件**: `src/components/subwayLine/picker/index.ts`
#### Props 定义
| 属性名 | 类型 | 说明 |
|--------|------|------|
| `areaId` | `string` | 城市ID可选 |
| `selectIds` | `string[]` | 已选中的站点ID列表 |
| `onConfirm` | `(stationIds: string[]) => void` | 确认选择回调 |
| `onCancel` | `() => void` | 取消选择回调 |
#### State 数据
```typescript
{
areas: Area[], // 有地铁的城市列表
subways: Subway[], // 当前城市的地铁线路
subwayId: string, // 当前选中的地铁线路ID
stationIds: string[], // 用户选中的站点ID列表
}
```
#### 主要方法
| 方法名 | 参数 | 说明 |
|--------|------|------|
| `setAeraId(areaId)` | `areaId: string` | 设置城市 |
| `getSubways(areaId)` | `areaId: string` | 获取指定城市的地铁线路 |
| `getStations(subwayId)` | `subwayId: string` | 获取指定线路的站点 |
| `setCheckedList(value, flag)` | `value: string, flag: boolean` | 设置站点选中状态 |
#### 工作流程
```mermaid
sequenceDiagram
participant User as 用户
participant Picker as SubwayLinePicker
participant Cache as 缓存
User->>Picker: 打开选择器
Picker->>Cache: 加载有地铁的城市
Cache-->>Picker: 返回城市列表
Picker->>Cache: 加载城市的地铁线路
Cache-->>Picker: 返回地铁线路
Picker->>Cache: 加载线路的站点
Cache-->>Picker: 返回站点列表
User->>Picker: 切换城市
Picker->>Cache: 加载新城市的地铁
User->>Picker: 切换线路
Picker->>Cache: 加载新线路的站点
User->>Picker: 勾选站点
Picker->>Picker: 更新 stationIds
User->>Picker: 点击确认
Picker->>User: 触发 onConfirm(stationIds)
```
---
### 4.6 SubwayLineList - 地铁线路列表
**导入路径**: `oak-general-business/es/components/subwayLine/list`
**参考文件**: `src/components/subwayLine/list/index.ts`
#### 功能说明
展示地铁线路和站点的树形结构列表,主要用于管理端。
#### 数据结构
```typescript
{
treeData: [
{
title: '1号线',
key: 'subway_001',
isLeaf: false,
children: [
{
title: '文三路站',
key: 'subway_001/station_001',
isLeaf: true
},
// ... 更多站点
]
},
// ... 更多线路
]
}
```
---
### 4.7 高德地图组件Amap
**导入路径**:
- `oak-general-business/es/components/amap/location`
- `oak-general-business/es/components/amap/map`
**参考文件**:
- `src/components/amap/index.ts`
- `src/components/amap/amap.d.ts`
- `src/components/amap/amapUI.d.ts`
#### 说明
这两个组件提供了高德地图的集成能力,但具体实现文件未找到。通常包括:
**AmapLocation - 定位组件**
- 获取用户当前位置
- 地理编码(地址转坐标)
- 逆地理编码(坐标转地址)
**AmapMap - 地图组件**
- 地图展示
- 标记点Marker
- 地图选点
- 路径规划
#### 使用前提
需要配置高德地图的 API Key
```typescript
// Application 配置中添加
{
amap: {
key: 'your-amap-key',
securityJsCode: 'your-security-code' // 可选
}
}
```
---
## 5. 接入指南
### 5.1 前置条件
1. **安装依赖**
```bash
npm install oak-general-business
```
---
### 5.2 地区数据初始化
地区数据是静态数据,需要预先导入数据库。
**参考数据文件**:
- `oak-general-business/scripts/subway.json`
- `oak-general-business/scripts/station.json`
- `oak-general-business/scripts/subwayStation.json`
- `oak-general-business/scripts/area.json`
---
### 5.3 配置地图服务(可选)
如果需要使用地图功能,需要在 Application 配置中添加高德地图配置:
```typescript
// Application 实体的配置字段
{
amap: {
key: 'your-amap-api-key',
securityJsCode: 'your-security-js-code', // H5 平台需要
version: '2.0' // API 版本
}
}
```
获取高德地图 API Key
1. 访问 [高德开放平台](https://lbs.amap.com/)
2. 注册账号并创建应用
3. 获取 Web 端或小程序端的 Key
---
## 6. API 接口说明
### 6.1 Aspect 方法
地址管理功能没有提供专门的 Aspect 类,所有操作通过标准的 Oak Domain CRUD 方法完成。
### 6.2 Cache Feature 使用
地区和地铁数据通常会被缓存,使用 cache feature 可以提高查询性能:
```typescript
// 刷新缓存并获取数据
const { data: areas } = await this.features.cache.refresh('area', {
data: {
id: 1,
name: 1,
level: 1
},
filter: {
level: 'province'
}
});
// 从缓存获取数据(如果缓存不存在则自动查询)
const { data: subways } = await this.features.cache.get('subway', {
data: {
id: 1,
name: 1
},
filter: {
areaId: cityId
}
});
```
---
### 6.5 Endpoint API
地址管理功能没有提供外部 Endpoint API。所有操作通过前端组件或内部 Aspect 完成。
---
### 6.6 总结
地址管理功能目前已经提供了基础的收货地址管理、地区选择、地铁查询等核心能力。未来的主要方向是:
1. **完善地图功能** - 提供可视化的地址选择体验
2. **智能化增强** - 地址解析、验证、配送范围检查
3. **数据完善** - 扩展地铁数据覆盖,优化地区数据
4. **性能优化** - 缓存策略、索引优化
5. **业务集成** - 与订单、物流、门店等模块深度集成
---
*文档最后更新2025年10月26日*