## Context

企业微信资产目前只能分页查询；手机号资产仅能在自己的页面创建。`as_phone_asset` 尚未保存号码类型和外部来源，企业微信列表也不能按注册手机号筛选。仓库没有可执行的数据库迁移目录，因此数据库变更只作为受控 SQL 交付，绝不在应用启动或本次任务中直接执行。

## Goals / Non-Goals

**Goals:**

- 提供企业微信资产新增表单、关联查询和手机号自动创建。
- 在手机号资产中长期保存并显示“自有号码”或“外部号码”。
- 让外部号码链接到对应来源资产列表，并按手机号资产筛选。
- 用可复用的来源类型字段为后续微信、抖音等页面预留接入点。

**Non-Goals:**

- 不实现设备资产选择或企业微信资产编辑页。
- 不直接连接、修改或迁移任何数据库。
- 不在本次开发中实现尚无创建页面的微信、抖音等资产页。

## Decisions

### 手机号号码类型与来源分开保存

手机号资产新增 `number_type`、`source_asset_type` 和 `source_asset_id`。`number_type` 只表示号码归属：手机号资产页直接创建为 `SELF`（自有号码），其他资产流程自动创建为 `EXTERNAL`（外部号码）；来源字段记录创建它的资产类型和主键。相比把“已有/新建”写入手机号资产，这能避免把一次关联动作误当成号码自身属性。

### 企业微信关联方式单独展示

企业微信资产新增 `phone_link_mode`。选择已有手机号资产时保存 `EXISTING`（已有号码）；自动创建手机号资产时保存 `CREATED`（新建号码）。这与手机号资产的号码类型是两条不同维度的信息。

### 原子保存

企业微信资产服务使用事务（把自动创建手机号、创建企微资产、回填来源主键当成一组操作；任一步失败就全部撤销）。相比前端连续调用，可避免只有手机号、没有企微资产的孤立记录。

### 搜索接口按最小字段返回

新增注册主体、手机号和公司人员的只读搜索接口；注册主体返回 ID、名称和简称，手机号返回 ID、号码和号码类型，人员返回 ID 和姓名。前端不直接读取数据库，也不为选择器加载全部数据。

## Risks / Trade-offs

- [历史手机号没有来源] → 数据库交付将历史记录初始化为 `SELF`，与“非手机号资产创建才是外部号码”的规则一致。
- [并发提交同一新号码] → 复用手机号资产表既有“号码 + 删除状态”的唯一约束，并将重复键错误转换为重新读取已有号码。
- [未来来源页面尚未实现] → 当前仅企业微信具备完整跳转；来源类型字段和前端映射为未来页面预留扩展点。
- [数据库脚本不在仓库] → 交付明确的字段与回填要求，实际执行必须获得目标数据库和执行窗口的单独授权。

## Migration Plan

1. 在受控数据库变更中为手机号资产增加号码类型、来源资产类型、来源资产 ID，为企业微信资产增加手机号关联方式。
2. 将历史手机号资产初始化为 `SELF`，并为新字段建立筛选索引。
3. 发布后先验证现有列表仍可正常查询，再验证新建企微资产的已有号码和新建号码两条流程。
4. 回滚时保留新列但停止写入；前后端对空值回退为“自有号码”，避免旧数据不可读。

## Open Questions

- 无。数据库执行时间和目标库授权不属于本次代码实施范围。
