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