# Home Tree 版本对象展开下级 — 技术方案
## 问题描述
在 Active Workspace Client (AWC) 的 Home Tree(左侧对象导航树)中,当树节点为**版本对象**(如 `ItemRevision`、`Item` 等 `WorkspaceObject` 子类型)时,节点显示为叶子节点,无法展开加载下级数据。
## 根因分析
### 数据流
```
用户展开树节点
↓
_buildTreeTableStructure() [objectNavigationTreeService.js]
↓
getTableSummary() [objectNavigationTreeService.js]
↓
performSearchViewModel5 [SOA 调用, 携带 policyIOverride]
↓ 返回结果
createVMNodeUsingObjectInfo() [objectNavigationTreeService.js]
↓
containChildren(obj.props) [判断是否有子节点]
↓
vmNode.isLeaf = !hasChildren [决定是否可展开]
```
### 关键代码位置
| 文件 | 行号 | 职责 |
|---|---|---|
| `src/repo/tc-aw-framework/src/assets/js/objectNavigationTreeService.js` | 31–44 | `policyIOverride` — SOA 查询策略定义 |
| same file | 560–583 | `createVMNodeUsingObjectInfo` — 创建树节点对象 |
| same file | 614–629 | `containChildren` — 判断节点是否有子节点 |
| same file | 675–694 | `_buildTreeTableStructure` — 构建树结构(发起 SOA 调用) |
### 根因
**SOA 查询策略 `policyIOverride` 只对 `Folder` 类型请求了 `awp0HasChildren` 属性**,导致版本对象(`ItemRevision` 等非 Folder 类型)的响应中不含 `awp0HasChildren`。
`containChildren()` 检查 `props.awp0HasChildren.dbValues[0] === '1'`,由于该属性不存在,返回 `false`,节点被标记为 `isLeaf: true`,无法展开。
```javascript
// BUG: policyIOverride 只对 Folder 请求 awp0HasChildren
var policyIOverride = {
types: [ {
name: 'WorkspaceObject',
properties: [ {
name: 'object_name' // ← 只请求了名称
} ]
}, {
name: 'Folder',
properties: [ {
name: 'awp0HasChildren' // ← 只有文件夹才请求
} ]
} ]
};
```
## 解决方案
### 方案一:Policy 修正(核心修复)✅ 已实施
在 `WorkspaceObject` 类型的属性列表中添加 `awp0HasChildren`。所有版本类型(`ItemRevision`、`Item` 等)均继承自 `WorkspaceObject`,SOA 策略引擎会根据类型层级下发该属性。
**修改文件**:`src/repo/tc-aw-framework/src/assets/js/objectNavigationTreeService.js`
**修改内容**(第 31–44 行):
```diff
var policyIOverride = {
types: [ {
name: 'WorkspaceObject',
properties: [ {
name: 'object_name'
+ }, {
+ name: 'awp0HasChildren'
} ]
}, {
name: 'Folder',
properties: [ {
name: 'awp0HasChildren'
} ]
} ]
};
```
### 方案二:代码级别增强(已在代码中存在,无需额外操作)
当前 `containChildren` 函数已经包含了基于类型层级的回退判断逻辑:
```javascript
function containChildren( props, modelType ) {
// 首选:通过 awp0HasChildren 属性判断
if( props && props.awp0HasChildren && props.awp0HasChildren.dbValues[ 0 ] === '1' ) {
return true;
}
// 回退方案:通过类型层级判断(版本对象也可展开)
if( modelType && modelType.typeHierarchyArray ) {
var typeHierarchy = modelType.typeHierarchyArray;
if( typeHierarchy.indexOf( 'Folder' ) === -1 &&
( typeHierarchy.indexOf( 'ItemRevision' ) > -1 || typeHierarchy.indexOf( 'Item' ) > -1 ) ) {
return true;
}
}
return false;
}
```
调用处也已更新(第 564 行):
```javascript
var hasChildren = containChildren( obj.props, obj.modelType );
// 之前:containChildren( obj.props )
```
此回退逻辑作为 Policy 方案的补充,在服务器端未正确返回 `awp0HasChildren` 时仍能基于类型信息判断。
## 涉及的修改汇总
| 修改类型 | 文件 | 行号 | 状态 |
|---|---|---|---|
| 🔧 Policy 修正 | `src/repo/tc-aw-framework/src/assets/js/objectNavigationTreeService.js` | 35–36 插入 | ✅ 已实施 |
| ✅ 代码增强(已有) | 同上 | 614–629 `containChildren` | 已存在 |
| ✅ 调用处更新(已有) | 同上 | 564 `containChildren(obj.props, obj.modelType)` | 已存在 |
## 影响范围
| 范围 | 说明 |
|---|---|
| Home Tree(对象导航树) | 所有 `WorkspaceObject` 子类型的节点均可正常展开/折叠 |
| Folder 类型节点 | 不受影响,`awp0HasChildren` 策略仍然存在且优先 |
| 其他树组件 | Schedule 树、Plan 树、Organization 树各有自己的 `policyIOverride`,不在此次修改范围内(如需类似修复需单独评估) |
| VMAX 自定义模块 | 未覆盖此逻辑,直接复用框架层策略 |
## 验证方式
1. 部署修改后的代码
2. 打开 AWC Home 页面
3. 在左侧导航树中导航到版本对象(`ItemRevision`)节点
4. 确认节点旁出现展开/折叠图标
5. 点击展开,确认下级数据正常加载
6. 确认 Folder 类型节点的展开行为无异常
## 相关文件索引
| 文件 | 说明 |
|---|---|
| `src/repo/tc-aw-framework/src/assets/js/objectNavigationTreeService.js` | **核心修改文件** — Home Tree 的树服务,包含 Policy、节点创建、子节点判断 |
| `src/repo/tc-aw-framework/src/assets/js/objectNavigationService.js` | 对象导航服务 — 搜索上下文管理、选择跟踪、状态管理 |
| `src/repo/tc-aw-framework/src/assets/viewmodel/AwStandardObjectNavigationTreeViewModel.json` | Home Tree ViewModel — 数据提供器、事件处理、生命周期 |
| `src/repo/tc-aw-framework/src/assets/html/AwStandardObjectNavigationTreeView.html` | Home Tree 视图模板 |
| `src/repo/tc-aw-framework/src/assets/js/AwGatewayLocationService.js` | Gateway(Home 页)初始化服务 |
| `src/repo/tc-aw-framework/states.json` | 状态定义 — `showHome` 等路由配置 |
| `src/repo/tc-aw-framework/hosting.json` | Hosting 配置 — 组件位置等 |
