You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cz-hjjc-budget/docs/attachment-file-rendering-l...

192 lines
5.4 KiB

3 months ago
# attachment/file 类型字段渲染逻辑说明
## 概述
本文档说明 `PlannedExpenditureTemplateReadonly.vue` 组件中 `attachment/file` 类型字段的完整渲染逻辑和数据流向。
## 数据流向
```
后端返回数据 (elementValues)
getFieldValue(field) - 获取原始字段值
getFileItems(field) - 处理并转换为文件项数组
模板渲染 - 显示文件列表
handleFileClick(file) - 处理文件点击事件
```
## 详细步骤
### 1. 字段值获取 (`getFieldValue`)
**位置**: `PlannedExpenditureTemplateReadonly.vue:310`
**查找顺序**:
1. **通过 field_key 查找** (`field.key` 或 `field.field_key`)
-`elementValues` 中直接查找该 key
- 如果找到的是对象且包含 `value` 属性,返回 `direct.value`
- 否则直接返回找到的值
2. **通过 element_id 查找** (`field.element_id`)
-`elementValues` 中使用 element_id 作为 key 查找
- 如果找到的是对象且包含 `value` 属性,返回 `ev.value`
- 否则直接返回找到的值
3. **兜底查找** (`element_{elementId}`)
- 尝试使用 `element_${elementId}` 作为 key 查找
- 处理方式同上
4. **遍历查找** (兼容"值对象"模式)
- 遍历 `elementValues` 的所有值
- 查找 `field_key` 匹配的对象
- 返回其 `value` 属性
**调试信息**:
- 开发环境下,会在控制台输出详细的查找过程
- 包括:使用的 key、找到的值、值的类型等
- 如果未找到值,会输出警告和所有可用的 keys
### 2. 文件项处理 (`getFileItems`)
**位置**: `PlannedExpenditureTemplateReadonly.vue:620`
**输入**: `getFieldValue(field)` 返回的原始值
**处理逻辑**:
#### 2.1 字符串类型
```javascript
// 如果值是字符串,例如: "/uploads/file.pdf"
{
name: "file.pdf", // 从路径提取文件名
url: "/uploads/file.pdf" // 原始字符串作为 URL
}
```
#### 2.2 对象类型
从对象中提取以下字段(按优先级):
- **URL 字段**: `url`, `path`, `file_url`, `download_url`, `href`, `preview_url`
- **名称字段**: `original_name`, `file_name`, `name`, `filename`, `originalName`
- 如果 URL 存在但名称不存在,从 URL 路径提取文件名
#### 2.3 数组类型
- 如果值是数组,遍历每个元素
- 每个元素按上述规则处理(字符串或对象)
- 返回处理后的文件项数组
**调试信息**:
- 输出原始值的类型、长度等信息
- 输出每个文件项的处理结果
- 如果处理失败,输出警告和可用的字段
### 3. 模板渲染
**位置**: `PlannedExpenditureTemplateReadonly.vue:150`
**渲染逻辑**:
- 如果 `getFileItems(field).length > 0`,显示文件列表
- 每个文件项:
- **有 URL**: 显示为可点击链接,点击在新窗口打开
- **无 URL**: 显示为可点击链接,点击提示"文件链接不可用"
- 如果文件列表为空,显示 "-"
**调试信息** (开发环境):
- 在页面上显示字段的调试信息框
- 包括字段ID、字段Key、字段类型、原始值、处理后的文件项数
- 每个文件项显示其 name 和 url
### 4. 文件点击处理 (`handleFileClick`)
**位置**: `PlannedExpenditureTemplateReadonly.vue:651`
**处理逻辑**:
- 如果文件有 `url`,使用 `window.open(url, '_blank')` 打开
- 如果文件没有 `url`,显示提示:"文件链接不可用"
**调试信息**:
- 输出点击的文件对象
- 输出是否有 URL
- 如果打开失败,输出错误信息
## 调试方法
### 1. 查看控制台日志
在浏览器开发者工具的控制台中,查找以下前缀的日志:
- `[getFieldValue]` - 字段值获取过程
- `[getFileItems]` - 文件项处理过程
- `[handleFileClick]` - 文件点击事件
### 2. 查看页面调试信息
在开发环境下,页面上的 attachment/file 字段会显示一个调试信息框,包含:
- 字段ID和Key
- 原始值
- 处理后的文件项数
### 3. 常见问题排查
#### 问题1: 文件列表为空
- 检查 `[getFieldValue]` 日志,确认是否找到了字段值
- 检查 `elementValues` 中是否包含该字段的数据
- 检查字段的 `field_key``element_id` 是否正确
#### 问题2: 文件有名称但没有URL
- 检查 `[getFileItems.toItem]` 日志,查看对象中有哪些字段
- 确认对象中是否包含 URL 相关字段url, path, file_url 等)
- 检查后端返回的数据结构
#### 问题3: 点击文件无反应
- 检查 `[handleFileClick]` 日志,确认文件对象的内容
- 检查浏览器是否阻止了弹窗
- 检查 URL 是否有效
## 数据结构示例
### elementValues 结构示例
**模式1: 字段键值模式**
```javascript
{
"element_123": [
{
"name": "文件1.pdf",
"url": "/uploads/file1.pdf"
}
]
}
```
**模式2: 值对象模式**
```javascript
{
"123": {
"element_id": 123,
"field_key": "element_123",
"value": [
{
"name": "文件1.pdf",
"url": "/uploads/file1.pdf"
}
]
}
}
```
**模式3: 字符串模式**
```javascript
{
"element_123": "/uploads/file1.pdf"
}
```
## 注意事项
1. **开发环境**: 调试信息只在开发环境(`config.isDevelopment === true`)下显示
2. **性能**: 调试信息可能影响性能,生产环境会自动禁用
3. **数据格式**: 组件兼容多种数据格式,但建议使用统一格式
4. **错误处理**: 所有错误都会在控制台输出,便于排查问题