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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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. **错误处理**: 所有错误都会在控制台输出,便于排查问题