背景
我是一名视障用户,完全依赖 TalkBack(Android 屏幕阅读器)使用手机。OpenList 作为一款优秀的网盘挂载工具,功能强大且支持多种存储服务,但在 Android 端的无障碍体验存在严重问题,导致视障用户几乎无法正常使用核心功能。
OpenList 的 Android 应用采用 WebView 渲染 Web 界面的方式实现 UI。这种架构在功能上没有问题,但在无障碍方面带来了天然缺陷——Web 界面中的交互元素往往缺少 ARIA 语义标注,TalkBack 无法正确识别和操作这些元素。
源码审查说明
我们对 OpenList 后端(OpenListTeam/OpenList)和前端(OpenListTeam/OpenList-Frontend)进行了逐文件审查。后端为纯 Go API 服务,无障碍问题全部集中在前端 Web 界面。前端基于 SolidJS + Hope UI 构建,以下所有问题均基于源码实际定位。
具体问题
1. 文件列表项完全没有无障碍语义(Blocker/Critical)
源码位置:src/pages/home/folder/ListItem.tsx、src/pages/home/folder/GridItem.tsx
文件列表是 OpenList 的核心交互区域,但 TalkBack 用户几乎无法有效浏览和操作文件。具体表现为:
- 列表项容器
<HStack> 没有 role="listitem",也没有 aria-label,TalkBack 只能朗读出一堆无意义的文本碎片
- 文件名使用
<Text title={props.obj.name}> 渲染,但 title 属性 TalkBack 不会自动朗读
- 文件名、文件大小、修改时间分别是独立的
<Text> 元素,TalkBack 逐个朗读,用户无法快速定位目标文件
- 点击/双击打开文件夹的逻辑绑定在
on:click 和 on:dblclick 上,容器没有 role="link" 或 role="button",TalkBack 用户无法得知这是可操作的
- 网格视图
GridItem.tsx 中缩略图 <ImageWithError> 没有 alt 属性
- 复选框
<ItemCheckbox> 有 checked 和 onChange,但没有 aria-label 说明选中的是什么文件
2. 右键菜单 TalkBack 完全不可达(Blocker/Critical)
源码位置:src/pages/home/folder/context-menu.tsx
长按文件后弹出的操作菜单(下载、重命名、删除、复制、移动、分享等),对 TalkBack 用户完全不可达:
- 使用
solid-contextmenu 库,菜单通过 onContextMenu(右键事件)触发,Android TalkBack 没有右键事件
- 菜单项
<Item> 没有 role="menuitem",没有 aria-label
- 菜单弹出后没有焦点管理(没有自动 focus 到第一个菜单项)
- 子菜单
<Submenu> 同样缺少 ARIA 语义
3. 文件列表容器缺少语义结构(Barrier/High)
源码位置:src/pages/home/folder/List.tsx、src/pages/home/folder/Grid.tsx
- 列表容器
<VStack class="list"> 没有 role="list"
- 列表标题中的排序按钮(点击列名排序)没有
role="button" 或 aria-label,TalkBack 不知道这是可点击的排序控件
- 全选复选框没有
aria-label="全选"
4. 页面路标完全缺失(Barrier/High)
源码位置:index.html、src/pages/home/Layout.tsx、src/pages/home/header/Header.tsx、src/pages/home/Nav.tsx
整个 Web 界面缺少 WAI-ARIA 路标(landmark)标记,TalkBack 用户无法使用路标导航快速定位页面区域:
index.html 中 <html lang="en">,中文环境应设为 lang="zh-CN"
- 没有
<main> 标签,主内容区域没有 role="main"
- 没有
<nav> 标签,面包屑导航(Nav.tsx 中的 <Breadcrumb>)没有 role="navigation" + aria-label
- 没有
<header> 标签,顶部栏(Header.tsx)没有 role="banner"
- 搜索区域没有
role="search"
5. 动态内容更新无播报(Barrier/Medium)
全项目搜索发现零个 aria-live、零个 role="status"、零个 aria-busy:
- 文件上传/下载进度变化 TalkBack 不会播报
- 操作成功或失败的 Toast 通知 TalkBack 无法感知
- 加载状态(
CenterLoading 组件)没有 aria-busy 或 role="status" 标注
6. 工具栏按钮缺少标签(Barrier/High)
源码位置:src/pages/home/toolbar/Toolbar.tsx 及子组件(Upload.tsx、Mkdir.tsx、Delete.tsx、Rename.tsx、CopyMove.tsx、Download.tsx、Share.tsx 等)
- 工具栏中的上传、新建文件夹、批量重命名、复制、移动、删除等按钮
- 大量使用
Icon 组件渲染图标按钮,只有视觉图标,没有 aria-label
- TalkBack 会朗读出"按钮"但无法知道具体功能
7. 文件预览界面部分可操作但不完整(Barrier/High)
源码位置:src/pages/home/previews/ 目录下各组件
好的方面:图片预览(image.tsx)有较完善的 aria-label(缩放、旋转、翻页等),分页器(Paginator.tsx)有 aria-label="Previous" / "Next"。
问题:
- 视频播放器(
video.tsx、video_box.tsx)的播放/暂停/进度条等控件缺少无障碍标注
- 文档预览(
doc.tsx、pdf.tsx)的 iframe 缺少 title 属性
iframe.tsx 虽然有 aria-label="Open in new tab",但 iframe 本身缺少 title
8. 表单元素标签不完整(Barrier/Medium)
源码位置:src/pages/manage/storages/AddOrEdit.tsx、src/components/ModalInput.tsx 等
- 部分输入框通过 Modal 的
title 属性间接标注,但没有 aria-label 直接关联
- 存储配置页面的表单非常复杂,大量下拉框和输入框缺少无障碍标签
已有的无障碍实现(正面发现)
全项目约 25 处 aria-label,集中在:
- ✅ 图片预览控件(缩放、旋转、翻页等)——较完善
- ✅ 分页器(上一页/下一页)——有基本标注
- ✅ 搜索框——有
aria-label="search"
- ✅ 布局切换——有
aria-label="switch layout"
- ✅ 文件夹树选择器——确认/取消按钮有标注
这说明开发团队有无障碍意识,但目前覆盖范围远远不够,核心交互区域(文件列表、右键菜单、工具栏)是空白。
技术分析与修复建议
具体修复建议
| 问题 |
源码文件 |
修复方案 |
优先级 |
| 文件列表项不可读 |
ListItem.tsx、GridItem.tsx |
为容器添加 role="listitem" + aria-label="文件名,文件大小,修改时间",使用 aria-label 将多项信息合并为一个可朗读的整体 |
Critical |
| 右键菜单不可达 |
context-menu.tsx |
菜单容器添加 role="menu",菜单项添加 role="menuitem" + aria-label,弹出时自动 focus 到第一个菜单项;考虑增加长按触发的备选交互方式 |
Critical |
| 列表容器缺语义 |
List.tsx、Grid.tsx |
容器添加 role="list",排序按钮添加 role="button" + aria-label,全选复选框添加 aria-label |
High |
| 页面路标缺失 |
index.html、Layout.tsx |
添加 <main>/<nav>/<header> 语义标签或对应 role,修正 lang 属性 |
High |
| 工具栏按钮无标签 |
toolbar/*.tsx |
所有图标按钮添加 aria-label |
High |
| 动态内容无播报 |
全局通知组件 |
操作提示用 role="status" 或 aria-live="polite",错误提示用 aria-live="assertive" |
Medium |
| 表单元素无标签 |
manage/storages/AddOrEdit.tsx 等 |
所有输入框添加 aria-label,下拉框添加 aria-label 和 aria-activedescendant |
Medium |
| 文件预览不完整 |
previews/video.tsx 等 |
视频控件添加 role="slider" + aria-label,iframe 添加 title |
High |
参考资料
1. W3C WCAG 2.1 快速指南
W3C 官方的 Web 内容无障碍指南,是所有 Web 应用的无障碍标准基础。OpenList 作为 Web 界面应用,应参照 WCAG 2.1 AA 级别进行适配。
2. WAI-ARIA 最佳实践
W3C 的 ARIA 规范,为动态 Web 应用提供语义标注标准。OpenList 的文件列表、操作菜单、表单等动态交互场景都可以直接参考。
3. 国内 AI 助手无障碍横评
我们对国内主流 AI 助手的视障用户无障碍体验进行了调研:
| 产品 |
视障用户可用性 |
| 豆包(字节跳动) |
✅ 实用性强,标签全覆盖 |
| Kimi(月之暗面) |
❌ 标签缺失,无法使用 |
| 通义千问(阿里) |
❌ 支持弱 |
| 文心一言(百度) |
❌ 支持弱 |
| DeepSeek(深度求索) |
⚠️ 大量未加标签控件 |
关键发现:豆包是唯一让盲人「真正用起来」的国内 AI 助手,核心原因是按钮标签全覆盖、读屏适配完善。这说明无障碍适配并不需要推翻重构,关键是为每个交互元素添加正确的语义标注。
4. GitHub 官方开源无障碍最佳实践
GitHub 官方开源指南建议每个开源项目:
- 创建
ACCESSIBILITY.md 文件,声明无障碍承诺
- 创建无障碍 Issue 模板
- 在 PR 检查清单中加入无障碍检查项
- 优先处理阻塞性问题(Critical 级别)
来源:https://opensource.guide/accessibility-best-practices-for-your-project/
社区协作
关于我们
我们来自中国视障社区,社区中视障开发者已超 20000 人,视障用户群体已超 20 万人,覆盖国内主流读屏软件用户群体(天坦读屏、TalkBack 等)。
测试协作
如果开发组愿意推进无障碍优化,我们可以在第一版修复发布后,组织社区视障用户进行系统化测试,覆盖多设备、多读屏软件的真实使用场景,提供结构化反馈报告。
推广意愿
OpenList 作为功能最全面的开源网盘挂载工具,如果在无障碍方面率先做好,将在视障用户群体中获得显著的社区口碑与用户增长。我们愿意在视障社区内推广 OpenList 的知名度。
环境信息
- 设备:Redmi K80 Ultra (dali)
- Android 版本:16 (API 36)
- 读屏软件:天坦读屏(Tantan Screen Reader),基于 Android AccessibilityService 框架
- OpenList 部署方式:Android App
希望开发组能够重视无障碍体验,让视障用户也能顺畅使用 OpenList。感谢!
背景
我是一名视障用户,完全依赖 TalkBack(Android 屏幕阅读器)使用手机。OpenList 作为一款优秀的网盘挂载工具,功能强大且支持多种存储服务,但在 Android 端的无障碍体验存在严重问题,导致视障用户几乎无法正常使用核心功能。
OpenList 的 Android 应用采用 WebView 渲染 Web 界面的方式实现 UI。这种架构在功能上没有问题,但在无障碍方面带来了天然缺陷——Web 界面中的交互元素往往缺少 ARIA 语义标注,TalkBack 无法正确识别和操作这些元素。
源码审查说明
我们对 OpenList 后端(
OpenListTeam/OpenList)和前端(OpenListTeam/OpenList-Frontend)进行了逐文件审查。后端为纯 Go API 服务,无障碍问题全部集中在前端 Web 界面。前端基于 SolidJS + Hope UI 构建,以下所有问题均基于源码实际定位。具体问题
1. 文件列表项完全没有无障碍语义(Blocker/Critical)
源码位置:
src/pages/home/folder/ListItem.tsx、src/pages/home/folder/GridItem.tsx文件列表是 OpenList 的核心交互区域,但 TalkBack 用户几乎无法有效浏览和操作文件。具体表现为:
<HStack>没有role="listitem",也没有aria-label,TalkBack 只能朗读出一堆无意义的文本碎片<Text title={props.obj.name}>渲染,但title属性 TalkBack 不会自动朗读<Text>元素,TalkBack 逐个朗读,用户无法快速定位目标文件on:click和on:dblclick上,容器没有role="link"或role="button",TalkBack 用户无法得知这是可操作的GridItem.tsx中缩略图<ImageWithError>没有alt属性<ItemCheckbox>有checked和onChange,但没有aria-label说明选中的是什么文件2. 右键菜单 TalkBack 完全不可达(Blocker/Critical)
源码位置:
src/pages/home/folder/context-menu.tsx长按文件后弹出的操作菜单(下载、重命名、删除、复制、移动、分享等),对 TalkBack 用户完全不可达:
solid-contextmenu库,菜单通过onContextMenu(右键事件)触发,Android TalkBack 没有右键事件<Item>没有role="menuitem",没有aria-label<Submenu>同样缺少 ARIA 语义3. 文件列表容器缺少语义结构(Barrier/High)
源码位置:
src/pages/home/folder/List.tsx、src/pages/home/folder/Grid.tsx<VStack class="list">没有role="list"role="button"或aria-label,TalkBack 不知道这是可点击的排序控件aria-label="全选"4. 页面路标完全缺失(Barrier/High)
源码位置:
index.html、src/pages/home/Layout.tsx、src/pages/home/header/Header.tsx、src/pages/home/Nav.tsx整个 Web 界面缺少 WAI-ARIA 路标(landmark)标记,TalkBack 用户无法使用路标导航快速定位页面区域:
index.html中<html lang="en">,中文环境应设为lang="zh-CN"<main>标签,主内容区域没有role="main"<nav>标签,面包屑导航(Nav.tsx中的<Breadcrumb>)没有role="navigation"+aria-label<header>标签,顶部栏(Header.tsx)没有role="banner"role="search"5. 动态内容更新无播报(Barrier/Medium)
全项目搜索发现零个
aria-live、零个role="status"、零个aria-busy:CenterLoading组件)没有aria-busy或role="status"标注6. 工具栏按钮缺少标签(Barrier/High)
源码位置:
src/pages/home/toolbar/Toolbar.tsx及子组件(Upload.tsx、Mkdir.tsx、Delete.tsx、Rename.tsx、CopyMove.tsx、Download.tsx、Share.tsx等)Icon组件渲染图标按钮,只有视觉图标,没有aria-label7. 文件预览界面部分可操作但不完整(Barrier/High)
源码位置:
src/pages/home/previews/目录下各组件好的方面:图片预览(
image.tsx)有较完善的aria-label(缩放、旋转、翻页等),分页器(Paginator.tsx)有aria-label="Previous"/"Next"。问题:
video.tsx、video_box.tsx)的播放/暂停/进度条等控件缺少无障碍标注doc.tsx、pdf.tsx)的 iframe 缺少title属性iframe.tsx虽然有aria-label="Open in new tab",但 iframe 本身缺少title8. 表单元素标签不完整(Barrier/Medium)
源码位置:
src/pages/manage/storages/AddOrEdit.tsx、src/components/ModalInput.tsx等title属性间接标注,但没有aria-label直接关联已有的无障碍实现(正面发现)
全项目约 25 处
aria-label,集中在:aria-label="search"aria-label="switch layout"这说明开发团队有无障碍意识,但目前覆盖范围远远不够,核心交互区域(文件列表、右键菜单、工具栏)是空白。
技术分析与修复建议
具体修复建议
ListItem.tsx、GridItem.tsxrole="listitem"+aria-label="文件名,文件大小,修改时间",使用aria-label将多项信息合并为一个可朗读的整体context-menu.tsxrole="menu",菜单项添加role="menuitem"+aria-label,弹出时自动 focus 到第一个菜单项;考虑增加长按触发的备选交互方式List.tsx、Grid.tsxrole="list",排序按钮添加role="button"+aria-label,全选复选框添加aria-labelindex.html、Layout.tsx<main>/<nav>/<header>语义标签或对应role,修正lang属性toolbar/*.tsxaria-labelrole="status"或aria-live="polite",错误提示用aria-live="assertive"manage/storages/AddOrEdit.tsx等aria-label,下拉框添加aria-label和aria-activedescendantpreviews/video.tsx等role="slider"+aria-label,iframe 添加title参考资料
1. W3C WCAG 2.1 快速指南
W3C 官方的 Web 内容无障碍指南,是所有 Web 应用的无障碍标准基础。OpenList 作为 Web 界面应用,应参照 WCAG 2.1 AA 级别进行适配。
2. WAI-ARIA 最佳实践
W3C 的 ARIA 规范,为动态 Web 应用提供语义标注标准。OpenList 的文件列表、操作菜单、表单等动态交互场景都可以直接参考。
3. 国内 AI 助手无障碍横评
我们对国内主流 AI 助手的视障用户无障碍体验进行了调研:
关键发现:豆包是唯一让盲人「真正用起来」的国内 AI 助手,核心原因是按钮标签全覆盖、读屏适配完善。这说明无障碍适配并不需要推翻重构,关键是为每个交互元素添加正确的语义标注。
4. GitHub 官方开源无障碍最佳实践
GitHub 官方开源指南建议每个开源项目:
ACCESSIBILITY.md文件,声明无障碍承诺来源:https://opensource.guide/accessibility-best-practices-for-your-project/
社区协作
关于我们
我们来自中国视障社区,社区中视障开发者已超 20000 人,视障用户群体已超 20 万人,覆盖国内主流读屏软件用户群体(天坦读屏、TalkBack 等)。
测试协作
如果开发组愿意推进无障碍优化,我们可以在第一版修复发布后,组织社区视障用户进行系统化测试,覆盖多设备、多读屏软件的真实使用场景,提供结构化反馈报告。
推广意愿
OpenList 作为功能最全面的开源网盘挂载工具,如果在无障碍方面率先做好,将在视障用户群体中获得显著的社区口碑与用户增长。我们愿意在视障社区内推广 OpenList 的知名度。
环境信息
希望开发组能够重视无障碍体验,让视障用户也能顺畅使用 OpenList。感谢!