<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SimpleGallery Android→HarmonyOS 功能覆盖追踪</title>
<style>
:root {
--primary: #007DFF;
--primary-light: #E3F2FD;
--success: #4CAF50;
--success-light: #E8F5E9;
--warning: #FF9800;
--warning-light: #FFF3E0;
--error: #E84026;
--gray-100: #F5F5F5;
--gray-200: #EEEEEE;
--gray-300: #E0E0E0;
--gray-500: #9E9E9E;
--gray-700: #616161;
--gray-900: #212121;
--radius: 8px;
--shadow: 0 2px 8px rgba(0,0,0,0.08);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
background: var(--gray-100);
color: var(--gray-900);
line-height: 1.6;
}
.header {
background: linear-gradient(135deg, var(--primary), #0056b3);
color: white;
padding: 24px 32px;
position: sticky;
top: 0;
z-index: 100;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.header h1 { font-size: 22px; font-weight: 600; }
.header .subtitle { font-size: 13px; opacity: 0.85; margin-top: 4px; }
.global-stats {
display: flex;
gap: 24px;
margin-top: 16px;
flex-wrap: wrap;
}
.stat-card {
background: rgba(255,255,255,0.15);
border-radius: var(--radius);
padding: 12px 20px;
min-width: 160px;
backdrop-filter: blur(4px);
}
.stat-card.primary {
background: rgba(255,255,255,0.25);
border: 2px solid rgba(255,255,255,0.5);
padding: 16px 28px;
min-width: 200px;
}
.stat-card.primary .label { font-size: 13px; font-weight: 600; opacity: 0.95; }
.stat-card.primary .value { font-size: 38px; }
.stat-card.primary .detail { font-size: 12px; }
.stat-card.secondary { opacity: 0.8; }
.stat-card.secondary .value { font-size: 22px; }
.stat-card .label { font-size: 12px; opacity: 0.8; }
.stat-card .value { font-size: 28px; font-weight: 700; }
.stat-card .detail { font-size: 11px; opacity: 0.7; margin-top: 2px; }
.container { max-width: 1400px; margin: 0 auto; padding: 24px; }
.spec-section {
background: white;
border-radius: var(--radius);
padding: 20px 24px;
margin-bottom: 20px;
box-shadow: var(--shadow);
}
.spec-section h2 {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
color: var(--gray-700);
display: flex;
align-items: center;
gap: 8px;
}
.spec-section h2::before { content: ''; display: inline-block; width: 4px; height: 18px; background: var(--primary); border-radius: 2px; }
.spec-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 8px;
}
.spec-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
border-radius: 6px;
cursor: pointer;
transition: all 0.15s;
border: 1px solid var(--gray-200);
user-select: none;
}
.spec-item:hover { background: var(--primary-light); border-color: var(--primary); }
.spec-item.checked { background: var(--success-light); border-color: var(--success); }
.spec-item input[type="checkbox"] {
width: 18px; height: 18px;
accent-color: var(--success);
cursor: pointer;
flex-shrink: 0;
}
.spec-item .spec-id {
font-size: 11px;
font-weight: 700;
color: var(--primary);
background: var(--primary-light);
padding: 2px 6px;
border-radius: 3px;
white-space: nowrap;
}
.spec-item.checked .spec-id { color: var(--success); background: var(--success-light); }
.spec-item .spec-name { font-size: 13px; color: var(--gray-700); }
.spec-actions {
display: flex;
gap: 8px;
margin-top: 12px;
}
.spec-actions button {
padding: 6px 16px;
border-radius: 4px;
border: 1px solid var(--gray-300);
background: white;
cursor: pointer;
font-size: 12px;
color: var(--gray-700);
transition: all 0.15s;
}
.spec-actions button:hover { background: var(--gray-100); border-color: var(--primary); color: var(--primary); }
.spec-actions button.export-btn { background: var(--primary); color: white; border-color: var(--primary); }
.spec-actions button.export-btn:hover { background: #0056b3; }
.activity-section h2 {
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
color: var(--gray-700);
display: flex;
align-items: center;
gap: 8px;
}
.activity-section h2::before { content: ''; display: inline-block; width: 4px; height: 18px; background: var(--warning); border-radius: 2px; }
.activity-card {
background: white;
border-radius: var(--radius);
margin-bottom: 8px;
box-shadow: var(--shadow);
overflow: hidden;
transition: all 0.2s;
}
.activity-card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.12); }
.activity-header {
display: flex;
align-items: center;
padding: 14px 20px;
cursor: pointer;
gap: 16px;
transition: background 0.15s;
}
.activity-header:hover { background: var(--gray-100); }
.activity-name {
font-size: 15px;
font-weight: 600;
min-width: 220px;
color: var(--gray-900);
}
.activity-progress-bar {
flex: 1;
height: 8px;
background: var(--gray-200);
border-radius: 4px;
overflow: hidden;
position: relative;
}
.activity-progress-fill {
height: 100%;
border-radius: 4px;
transition: width 0.4s ease, background 0.3s;
background: var(--primary);
}
.activity-progress-fill.full { background: var(--success); }
.activity-progress-fill.partial { background: var(--primary); }
.activity-progress-fill.none { background: var(--gray-300); width: 0!important; }
.activity-stats {
font-size: 13px;
color: var(--gray-500);
min-width: 100px;
text-align: right;
white-space: nowrap;
}
.activity-stats .pct {
font-weight: 700;
font-size: 15px;
}
.activity-stats .pct.full { color: var(--success); }
.activity-stats .pct.partial { color: var(--primary); }
.activity-stats .pct.none { color: var(--gray-500); }
.chevron {
width: 20px; height: 20px;
transition: transform 0.2s;
color: var(--gray-500);
flex-shrink: 0;
}
.chevron.open { transform: rotate(90deg); }
.activity-body {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.activity-body.open { max-height: 5000px; }
.activity-desc {
padding: 0 20px 12px;
font-size: 13px;
color: var(--gray-500);
border-bottom: 1px solid var(--gray-200);
}
.component-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.component-table th {
background: var(--gray-100);
padding: 8px 16px;
text-align: left;
font-weight: 600;
color: var(--gray-700);
font-size: 12px;
border-bottom: 1px solid var(--gray-300);
position: sticky;
top: 0;
}
.component-table td {
padding: 8px 16px;
border-bottom: 1px solid var(--gray-200);
vertical-align: top;
}
.component-table tr.covered { background: var(--success-light); }
.component-table tr.uncovered { background: white; }
.component-table tr.no-spec { background: #FFF8E1; }
.status-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 10px;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.status-badge.covered { background: var(--success); color: white; }
.status-badge.uncovered { background: var(--gray-300); color: var(--gray-700); }
.status-badge.no-spec { background: #FFE082; color: #F57F17; }
.spec-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.spec-tag {
font-size: 10px;
padding: 1px 6px;
border-radius: 3px;
background: var(--primary-light);
color: var(--primary);
font-weight: 600;
}
.spec-tag.active { background: var(--success); color: white; }
.legend {
display: flex;
gap: 20px;
margin-bottom: 16px;
font-size: 12px;
color: var(--gray-700);
flex-wrap: wrap;
}
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-dot {
width: 12px; height: 12px;
border-radius: 3px;
flex-shrink: 0;
}
@media (max-width: 768px) {
.spec-grid { grid-template-columns: 1fr; }
.activity-name { min-width: 120px; font-size: 13px; }
.container { padding: 12px; }
.header { padding: 16px; }
.global-stats { gap: 12px; }
.stat-card { min-width: 120px; padding: 8px 12px; }
}
</style>
</head>
<body>
<div class="header">
<h1>SimpleGallery Android → HarmonyOS 功能覆盖追踪</h1>
<div class="subtitle">基于 ui_navigation_analysis.md 与 SPEC-01~SPEC-20 plan 的功能点映射分析</div>
<div class="global-stats">
<div class="stat-card primary">
<div class="label">总体功能点覆盖率</div>
<div class="value" id="globalPct">0%</div>
<div class="detail" id="globalDetail">0 / 0 功能点</div>
</div>
<div class="stat-card secondary">
<div class="label">Spec 覆盖率</div>
<div class="value" id="specPct">0%</div>
<div class="detail" id="specDetail">0 / 20 Spec</div>
</div>
<div class="stat-card secondary">
<div class="label">Activity 覆盖率</div>
<div class="value" id="actPct">0%</div>
<div class="detail" id="actDetail">0 / 18 Activity</div>
</div>
</div>
</div>
<div class="container">
<div class="spec-section">
<h2>Spec 开发进度 (勾选已完成的 Spec)</h2>
<div class="spec-grid" id="specGrid"></div>
<div class="spec-actions">
<button onclick="selectAll()">全选</button>
<button onclick="deselectAll()">全部取消</button>
<button class="export-btn" onclick="exportMarkdown()">导出 Markdown</button>
</div>
</div>
<div class="activity-section">
<h2>Activity 功能覆盖详情</h2>
<div class="legend">
<div class="legend-item"><div class="legend-dot" style="background:var(--success)"></div> 已覆盖</div>
<div class="legend-item"><div class="legend-dot" style="background:var(--gray-300)"></div> 未覆盖</div>
<div class="legend-item"><div class="legend-dot" style="background:#FFE082"></div> 无对应Spec (外部/平台差异)</div>
</div>
<div id="activityList"></div>
</div>
</div>
<script>
const SPECS = [
{ id: "SPEC-01", name: "应用启动与初始化" },
{ id: "SPEC-02", name: "存储权限申请与管理" },
{ id: "SPEC-03", name: "媒体文件夹浏览" },
{ id: "SPEC-04", name: "媒体文件浏览" },
{ id: "SPEC-05", name: "图片全屏查看" },
{ id: "SPEC-06", name: "视频播放" },
{ id: "SPEC-07", name: "全景图片/视频查看" },
{ id: "SPEC-08", name: "媒体搜索" },
{ id: "SPEC-09", name: "媒体编辑" },
{ id: "SPEC-10", name: "媒体文件管理" },
{ id: "SPEC-11", name: "收藏夹管理" },
{ id: "SPEC-12", name: "回收站管理" },
{ id: "SPEC-13", name: "幻灯片播放" },
{ id: "SPEC-14", name: "壁纸设置" },
{ id: "SPEC-15", name: "第三方Want响应" },
{ id: "SPEC-16", name: "隐藏文件夹管理" },
{ id: "SPEC-17", name: "排除/包含文件夹管理" },
{ id: "SPEC-18", name: "桌面小部件" },
{ id: "SPEC-19", name: "设置与个性化" },
{ id: "SPEC-20", name: "后台媒体同步服务" }
];
const ACTIVITIES = [
{
name: "SplashActivity",
desc: "应用启动入口,执行初始化和收藏迁移后跳转至 MainActivity。",
components: [
{ id: "launchActivity()", ui: "程序化方法", desc: "初始化完成后启动 MainActivity 并 finish", target: "MainActivity", specs: ["SPEC-01"] }
]
},
{
name: "MainActivity",
desc: "主页,展示媒体文件夹网格/列表,支持 picker 模式、搜索、多选等。",
components: [
{ id: "directories_grid (item click)", ui: "DirectoryAdapter item", desc: "点击文件夹进入媒体列表或子文件夹", target: "MediaActivity", specs: ["SPEC-03"] },
{ id: "open_camera", ui: "MenuItem", desc: "启动设备相机", target: "外部应用", specs: ["SPEC-03"] },
{ id: "show_all", ui: "MenuItem", desc: "显示所有媒体模式", target: "MediaActivity", specs: ["SPEC-03", "SPEC-04"] },
{ id: "sort", ui: "MenuItem", desc: "打开排序对话框", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "filter", ui: "MenuItem", desc: "打开媒体类型过滤器", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "change_view_type", ui: "MenuItem", desc: "网格/列表视图切换", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "temporarily_show_hidden", ui: "MenuItem", desc: "临时显示隐藏文件夹", target: "MainActivity (self)", specs: ["SPEC-16"] },
{ id: "stop_showing_hidden", ui: "MenuItem", desc: "恢复隐藏文件夹", target: "MainActivity (self)", specs: ["SPEC-16"] },
{ id: "temporarily_show_excluded", ui: "MenuItem", desc: "临时显示排除文件夹", target: "MainActivity (self)", specs: ["SPEC-17"] },
{ id: "stop_showing_excluded", ui: "MenuItem", desc: "恢复排除文件夹", target: "MainActivity (self)", specs: ["SPEC-17"] },
{ id: "create_new_folder", ui: "MenuItem", desc: "创建新文件夹", target: "MainActivity (self)", specs: ["SPEC-10"] },
{ id: "open_recycle_bin", ui: "MenuItem", desc: "打开回收站", target: "MediaActivity", specs: ["SPEC-12"] },
{ id: "column_count", ui: "MenuItem", desc: "设置网格列数", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "set_as_default_folder", ui: "MenuItem", desc: "清除默认文件夹设置", target: "MainActivity (self)", specs: ["SPEC-19"] },
{ id: "settings", ui: "MenuItem", desc: "打开设置页", target: "SettingsActivity", specs: ["SPEC-19"] },
{ id: "about", ui: "MenuItem", desc: "打开关于页面", target: "AboutActivity (commons)", specs: [] },
{ id: "more_apps_from_us", ui: "MenuItem", desc: "打开应用商店", target: "外部应用", specs: [] },
{ id: "directories_switch_searching", ui: "MyTextView", desc: "切换到全局文件搜索", target: "SearchActivity", specs: ["SPEC-08"] },
{ id: "directories_empty_placeholder_2", ui: "MyTextView", desc: "空态操作(添加文件夹/过滤器)", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "directories_refresh_layout", ui: "SwipeRefreshLayout", desc: "下拉刷新文件夹列表", target: "MainActivity (self)", specs: ["SPEC-03"] },
{ id: "search_open", ui: "MySearchMenu", desc: "搜索焦点时跳转搜索页", target: "SearchActivity", specs: ["SPEC-08"] }
]
},
{
name: "MediaActivity",
desc: "显示特定文件夹内的媒体网格/列表,支持 picker/壁纸模式、回收站视图。",
components: [
{ id: "media_grid (item click, image)", ui: "RecyclerView item", desc: "点击图片进入全屏查看", target: "ViewPagerActivity", specs: ["SPEC-04"] },
{ id: "media_grid (item click, video)", ui: "RecyclerView item", desc: "点击视频使用外部播放器", target: "外部应用", specs: ["SPEC-04"] },
{ id: "media_grid (item click, pick)", ui: "RecyclerView item", desc: "Picker模式选择媒体返回URI", target: "返回调用方", specs: ["SPEC-15"] },
{ id: "media_grid (item click, wallpaper)", ui: "RecyclerView item", desc: "设置图片为壁纸", target: "返回调用方", specs: ["SPEC-14"] },
{ id: "slideshow", ui: "MenuItem", desc: "启动幻灯片播放", target: "ViewPagerActivity", specs: ["SPEC-13"] },
{ id: "folder_view", ui: "MenuItem (Show All)", desc: "切换到文件夹浏览视图", target: "MainActivity", specs: ["SPEC-04"] },
{ id: "open_camera", ui: "MenuItem (Show All)", desc: "启动设备相机", target: "外部应用", specs: [] },
{ id: "settings", ui: "MenuItem", desc: "打开设置页", target: "SettingsActivity", specs: ["SPEC-19"] },
{ id: "about", ui: "MenuItem (Show All)", desc: "打开关于页面", target: "AboutActivity (commons)", specs: [] },
{ id: "open_recycle_bin", ui: "MenuItem", desc: "打开回收站列表", target: "MediaActivity (self)", specs: ["SPEC-12"] },
{ id: "sort", ui: "MenuItem", desc: "打开排序对话框", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "filter", ui: "MenuItem", desc: "打开媒体类型过滤器", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "change_view_type", ui: "MenuItem", desc: "网格/列表视图切换", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "group", ui: "MenuItem (grid)", desc: "打开分组设置", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "toggle_filename", ui: "MenuItem (grid)", desc: "切换文件名显示", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "column_count", ui: "MenuItem (grid)", desc: "设置网格列数", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "empty_recycle_bin", ui: "MenuItem (Recycle Bin)", desc: "清空回收站", target: "返回", specs: ["SPEC-12"] },
{ id: "empty_disable_recycle_bin", ui: "MenuItem (Recycle Bin)", desc: "清空并禁用回收站", target: "返回", specs: ["SPEC-12"] },
{ id: "restore_all_files", ui: "MenuItem (Recycle Bin)", desc: "还原所有已删除文件", target: "返回", specs: ["SPEC-12"] },
{ id: "create_new_folder", ui: "MenuItem", desc: "创建子文件夹", target: "MediaActivity (self)", specs: ["SPEC-10"] },
{ id: "temporarily_show_hidden", ui: "MenuItem", desc: "临时显示隐藏文件", target: "MediaActivity (self)", specs: ["SPEC-16"] },
{ id: "stop_showing_hidden", ui: "MenuItem", desc: "恢复隐藏文件", target: "MediaActivity (self)", specs: ["SPEC-16"] },
{ id: "set_as_default_folder", ui: "MenuItem", desc: "设为默认启动文件夹", target: "MediaActivity (self)", specs: ["SPEC-19"] },
{ id: "unset_as_default_folder", ui: "MenuItem", desc: "取消默认文件夹", target: "MediaActivity (self)", specs: ["SPEC-19"] },
{ id: "media_empty_text_placeholder_2", ui: "TextView", desc: "空态打开过滤器", target: "MediaActivity (self)", specs: ["SPEC-04"] },
{ id: "media_refresh_layout", ui: "SwipeRefreshLayout", desc: "下拉刷新媒体列表", target: "MediaActivity (self)", specs: ["SPEC-04"] }
]
},
{
name: "SearchActivity",
desc: "全局全文搜索,实时过滤设备上所有媒体文件名。",
components: [
{ id: "search_grid (item click, image)", ui: "RecyclerView item", desc: "点击图片进入全屏查看", target: "ViewPagerActivity", specs: ["SPEC-08"] },
{ id: "search_grid (item click, video)", ui: "RecyclerView item", desc: "使用系统播放器打开视频", target: "外部应用", specs: ["SPEC-08"] },
{ id: "search_menu (back, empty)", ui: "MySearchMenu back", desc: "关闭搜索页", target: "返回", specs: ["SPEC-08"] },
{ id: "search_menu (back, non-empty)", ui: "MySearchMenu back", desc: "清空搜索文字", target: "SearchActivity (self)", specs: ["SPEC-08"] },
{ id: "toggle_filename", ui: "MenuItem", desc: "切换文件名显示", target: "SearchActivity (self)", specs: ["SPEC-08"] },
{ id: "search_menu (text input)", ui: "MySearchMenu", desc: "输入关键词实时过滤", target: "SearchActivity (self)", specs: ["SPEC-08"] },
{ id: "(CAB actions)", ui: "MediaAdapter CAB", desc: "多选操作(同 MediaActivity)", target: "多种", specs: ["SPEC-08", "SPEC-10"] }
]
},
{
name: "ViewPagerActivity",
desc: "全屏媒体查看器,支持横滑浏览、幻灯片、文件操作、底部快捷栏。",
components: [
{ id: "medium_viewer_toolbar (back)", ui: "Toolbar back", desc: "返回上一页", target: "返回", specs: ["SPEC-05"] },
{ id: "view_pager", ui: "MyViewPager", desc: "可滑动的图片/视频分页", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "fragment tap", ui: "PhotoFragment/VideoFragment", desc: "点击切换全屏模式", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "menu_set_as", ui: "MenuItem", desc: "设为壁纸/头像等", target: "外部应用", specs: ["SPEC-14"] },
{ id: "menu_slideshow", ui: "MenuItem", desc: "启动幻灯片播放", target: "ViewPagerActivity (self)", specs: ["SPEC-13"] },
{ id: "menu_copy_to", ui: "MenuItem", desc: "复制文件到目标目录", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_move_to", ui: "MenuItem", desc: "移动文件到目标目录", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_open_with", ui: "MenuItem", desc: "用其他应用打开", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_hide", ui: "MenuItem", desc: "隐藏文件", target: "ViewPagerActivity (self)", specs: ["SPEC-16"] },
{ id: "menu_unhide", ui: "MenuItem", desc: "取消隐藏文件", target: "ViewPagerActivity (self)", specs: ["SPEC-16"] },
{ id: "menu_share", ui: "MenuItem", desc: "通过系统分享面板分享", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_delete", ui: "MenuItem", desc: "删除文件", target: "ViewPagerActivity/返回", specs: ["SPEC-10"] },
{ id: "menu_rename", ui: "MenuItem", desc: "重命名文件", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_print", ui: "MenuItem", desc: "发送到打印服务", target: "外部应用", specs: [] },
{ id: "menu_edit", ui: "MenuItem", desc: "打开外部图片编辑器", target: "外部应用", specs: ["SPEC-09"] },
{ id: "menu_properties", ui: "MenuItem", desc: "显示文件属性对话框", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "menu_show_on_map", ui: "MenuItem", desc: "在地图上显示GPS位置", target: "外部应用", specs: [] },
{ id: "menu_rotate_right", ui: "Submenu MenuItem", desc: "顺时针旋转90\u00B0", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_rotate_left", ui: "Submenu MenuItem", desc: "逆时针旋转90\u00B0", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_rotate_one_eighty", ui: "Submenu MenuItem", desc: "旋转180\u00B0", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_add_to_favorites", ui: "MenuItem", desc: "添加到收藏", target: "ViewPagerActivity (self)", specs: ["SPEC-11"] },
{ id: "menu_remove_from_favorites", ui: "MenuItem", desc: "从收藏中移除", target: "ViewPagerActivity (self)", specs: ["SPEC-11"] },
{ id: "menu_restore_file", ui: "MenuItem", desc: "从回收站还原文件", target: "ViewPagerActivity (self)", specs: ["SPEC-12"] },
{ id: "menu_force_portrait", ui: "Submenu MenuItem", desc: "锁定竖屏方向", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "menu_force_landscape", ui: "Submenu MenuItem", desc: "锁定横屏方向", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "menu_default_orientation", ui: "Submenu MenuItem", desc: "解锁屏幕方向", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "menu_save_as", ui: "MenuItem", desc: "另存为", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_create_shortcut", ui: "MenuItem", desc: "创建桌面快捷方式", target: "ViewPagerActivity (via shortcut)", specs: [] },
{ id: "menu_resize", ui: "MenuItem", desc: "调整图片尺寸", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "menu_settings", ui: "MenuItem", desc: "打开设置", target: "SettingsActivity", specs: ["SPEC-19"] },
{ id: "bottom_favorite", ui: "ImageView", desc: "切换收藏状态", target: "ViewPagerActivity (self)", specs: ["SPEC-11"] },
{ id: "bottom_edit", ui: "ImageView", desc: "打开外部图片编辑器", target: "外部应用", specs: ["SPEC-09"] },
{ id: "bottom_share", ui: "ImageView", desc: "分享文件", target: "外部应用", specs: ["SPEC-15"] },
{ id: "bottom_delete", ui: "ImageView", desc: "删除当前文件", target: "ViewPagerActivity/返回", specs: ["SPEC-10"] },
{ id: "bottom_rotate", ui: "ImageView", desc: "旋转图片90\u00B0", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "bottom_properties", ui: "ImageView", desc: "显示文件属性", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "bottom_change_orientation", ui: "ImageView", desc: "循环切换屏幕方向", target: "ViewPagerActivity (self)", specs: ["SPEC-05"] },
{ id: "bottom_slideshow", ui: "ImageView", desc: "启动幻灯片播放", target: "ViewPagerActivity (self)", specs: ["SPEC-13"] },
{ id: "bottom_show_on_map", ui: "ImageView", desc: "在地图上显示位置", target: "外部应用", specs: [] },
{ id: "bottom_toggle_file_visibility", ui: "ImageView", desc: "切换文件可见性", target: "ViewPagerActivity (self)", specs: ["SPEC-16"] },
{ id: "bottom_rename", ui: "ImageView", desc: "重命名文件", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "bottom_set_as", ui: "ImageView", desc: "设为壁纸/头像", target: "外部应用", specs: ["SPEC-14"] },
{ id: "bottom_copy", ui: "ImageView", desc: "复制到目标目录", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "bottom_move", ui: "ImageView", desc: "移动到目标目录", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "bottom_resize", ui: "ImageView", desc: "调整图片尺寸", target: "ViewPagerActivity (self)", specs: ["SPEC-10"] },
{ id: "launchViewVideoIntent()", ui: "FragmentListener callback", desc: "启动外部视频播放器", target: "外部应用", specs: ["SPEC-06"] }
]
},
{
name: "SettingsActivity",
desc: "应用设置中心,包含颜色定制、显示、视频、缩略图、安全、回收站等设置分类。",
components: [
{ id: "settings_toolbar", ui: "MaterialToolbar (Arrow)", desc: "返回导航", target: "返回", specs: ["SPEC-19"] },
{ id: "settings_color_customization_holder", ui: "ConstraintLayout", desc: "颜色/主题定制", target: "CustomizationActivity", specs: ["SPEC-19"] },
{ id: "settings_use_english_holder", ui: "RelativeLayout (checkbox)", desc: "切换英语,重启应用", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_language_holder", ui: "RelativeLayout", desc: "打开系统语言设置", target: "外部应用", specs: ["SPEC-19"] },
{ id: "settings_change_date_time_format_holder", ui: "RelativeLayout", desc: "日期/时间格式设置", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_file_loading_priority_holder", ui: "RelativeLayout", desc: "文件加载优先级设置", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_manage_included_folders_holder", ui: "RelativeLayout", desc: "导航到包含文件夹管理", target: "IncludedFoldersActivity", specs: ["SPEC-17"] },
{ id: "settings_manage_excluded_folders_holder", ui: "RelativeLayout", desc: "导航到排除文件夹管理", target: "ExcludedFoldersActivity", specs: ["SPEC-17"] },
{ id: "settings_manage_hidden_folders_holder", ui: "RelativeLayout", desc: "导航到隐藏文件夹管理", target: "HiddenFoldersActivity", specs: ["SPEC-16"] },
{ id: "settings_show_hidden_items_holder", ui: "RelativeLayout (checkbox)", desc: "切换隐藏媒体可见性", target: "SettingsActivity (self)", specs: ["SPEC-16"] },
{ id: "settings_search_all_files_holder", ui: "RelativeLayout (checkbox)", desc: "切换全文件搜索", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_autoplay_videos_holder", ui: "RelativeLayout (checkbox)", desc: "切换视频自动播放", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_remember_last_video_position_holder", ui: "RelativeLayout (checkbox)", desc: "记住视频播放位置", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_loop_videos_holder", ui: "RelativeLayout (checkbox)", desc: "切换视频循环", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_open_videos_on_separate_screen_holder", ui: "RelativeLayout (checkbox)", desc: "切换独立视频窗口", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_video_gestures_holder", ui: "RelativeLayout (checkbox)", desc: "切换视频手势", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_crop_thumbnails_holder", ui: "RelativeLayout (checkbox)", desc: "切换缩略图裁剪", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_animate_gifs_holder", ui: "RelativeLayout (checkbox)", desc: "切换GIF缩略图动画", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_file_thumbnail_style_holder", ui: "RelativeLayout", desc: "文件缩略图样式", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_folder_thumbnail_style_holder", ui: "RelativeLayout", desc: "文件夹缩略图样式", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_scroll_horizontally_holder", ui: "RelativeLayout (checkbox)", desc: "切换水平滚动", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_enable_pull_to_refresh_holder", ui: "RelativeLayout (checkbox)", desc: "切换下拉刷新", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_max_brightness_holder", ui: "RelativeLayout (checkbox)", desc: "全屏最大亮度", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_black_background_holder", ui: "RelativeLayout (checkbox)", desc: "切换黑色背景", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_hide_system_ui_holder", ui: "RelativeLayout (checkbox)", desc: "切换系统UI隐藏", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_instant_change_holder", ui: "RelativeLayout (checkbox)", desc: "切换即时媒体切换", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_photo_gestures_holder", ui: "RelativeLayout (checkbox)", desc: "切换图片手势", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_down_gesture_holder", ui: "RelativeLayout (checkbox)", desc: "切换下滑关闭", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_show_notch_holder", ui: "RelativeLayout (checkbox)", desc: "切换刘海屏渲染", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_screen_rotation_holder", ui: "RelativeLayout", desc: "屏幕旋转设置", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_zooming_images_holder", ui: "RelativeLayout (checkbox)", desc: "切换深度缩放", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_rotating_with_gestures_holder", ui: "RelativeLayout (checkbox)", desc: "切换手势旋转", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_show_highest_quality_holder", ui: "RelativeLayout (checkbox)", desc: "切换最高画质", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_allow_one_to_one_zoom_holder", ui: "RelativeLayout (checkbox)", desc: "切换1:1像素缩放", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_show_extended_details_holder", ui: "RelativeLayout (checkbox)", desc: "切换扩展详情覆盖层", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_hide_extended_details_holder", ui: "RelativeLayout (checkbox)", desc: "切换自动隐藏扩展详情", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_manage_extended_details_holder", ui: "RelativeLayout", desc: "管理扩展详情显示项", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_app_password_protection_holder", ui: "RelativeLayout (checkbox)", desc: "切换应用密码保护", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_hidden_item_password_protection_holder", ui: "RelativeLayout (checkbox)", desc: "切换隐藏内容密码", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_excluded_item_password_protection_holder", ui: "RelativeLayout (checkbox)", desc: "切换排除文件夹密码", target: "SettingsActivity (self)", specs: ["SPEC-17", "SPEC-19"] },
{ id: "settings_file_deletion_password_protection_holder", ui: "RelativeLayout (checkbox)", desc: "切换删除密码保护", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_delete_empty_folders_holder", ui: "RelativeLayout (checkbox)", desc: "切换自动删除空文件夹", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_keep_last_modified_holder", ui: "RelativeLayout (checkbox)", desc: "切换保留时间戳", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_skip_delete_confirmation_holder", ui: "RelativeLayout (checkbox)", desc: "切换跳过删除确认", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_bottom_actions_checkbox_holder", ui: "RelativeLayout (checkbox)", desc: "切换底部操作栏", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_manage_bottom_actions_holder", ui: "RelativeLayout", desc: "管理底部操作按钮", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_use_recycle_bin_holder", ui: "RelativeLayout (checkbox)", desc: "切换回收站使用", target: "SettingsActivity (self)", specs: ["SPEC-12"] },
{ id: "settings_show_recycle_bin_holder", ui: "RelativeLayout (checkbox)", desc: "切换回收站文件夹显示", target: "SettingsActivity (self)", specs: ["SPEC-12"] },
{ id: "settings_show_recycle_bin_last_holder", ui: "RelativeLayout (checkbox)", desc: "切换回收站排列最后", target: "SettingsActivity (self)", specs: ["SPEC-12"] },
{ id: "settings_empty_recycle_bin_holder", ui: "RelativeLayout", desc: "清空回收站", target: "SettingsActivity (self)", specs: ["SPEC-12"] },
{ id: "settings_clear_cache_holder", ui: "RelativeLayout", desc: "清除应用图片缓存", target: "SettingsActivity (self)", specs: ["SPEC-19"] },
{ id: "settings_export_favorites_holder", ui: "RelativeLayout", desc: "导出收藏到文件", target: "外部文件选择器", specs: ["SPEC-11"] },
{ id: "settings_import_favorites_holder", ui: "RelativeLayout", desc: "从文件导入收藏", target: "外部文件选择器", specs: ["SPEC-11"] },
{ id: "settings_export_holder", ui: "RelativeLayout", desc: "导出所有设置", target: "外部文件选择器", specs: ["SPEC-19"] },
{ id: "settings_import_holder", ui: "RelativeLayout", desc: "导入设置", target: "外部文件选择器", specs: ["SPEC-19"] }
]
},
{
name: "IncludedFoldersActivity",
desc: "管理显式包含在扫描中的文件夹列表。",
components: [
{ id: "manage_folders_toolbar", ui: "MaterialToolbar (Arrow)", desc: "返回导航", target: "返回", specs: ["SPEC-17"] },
{ id: "add_folder", ui: "MenuItem", desc: "打开文件选择器添加文件夹", target: "IncludedFoldersActivity (self)", specs: ["SPEC-17"] },
{ id: "overflow_menu_icon (adapter)", ui: "ImageView (每行)", desc: "弹出菜单可移除", target: "IncludedFoldersActivity (self)", specs: ["SPEC-17"] },
{ id: "cab_remove", ui: "CAB MenuItem", desc: "移除选中的包含文件夹", target: "IncludedFoldersActivity (self)", specs: ["SPEC-17"] }
]
},
{
name: "ExcludedFoldersActivity",
desc: "管理从扫描中排除的文件夹列表。",
components: [
{ id: "manage_folders_toolbar", ui: "MaterialToolbar (Arrow)", desc: "返回导航", target: "返回", specs: ["SPEC-17"] },
{ id: "add_folder", ui: "MenuItem", desc: "打开文件选择器添加文件夹", target: "ExcludedFoldersActivity (self)", specs: ["SPEC-17"] },
{ id: "overflow_menu_icon (adapter)", ui: "ImageView (每行)", desc: "弹出菜单可移除", target: "ExcludedFoldersActivity (self)", specs: ["SPEC-17"] },
{ id: "cab_remove", ui: "CAB MenuItem", desc: "移除选中的排除文件夹", target: "ExcludedFoldersActivity (self)", specs: ["SPEC-17"] }
]
},
{
name: "HiddenFoldersActivity",
desc: "管理通过 .nomedia 文件隐藏的文件夹。",
components: [
{ id: "manage_folders_toolbar", ui: "MaterialToolbar (Arrow)", desc: "返回导航", target: "返回", specs: ["SPEC-16"] },
{ id: "add_folder", ui: "MenuItem", desc: "打开文件选择器隐藏文件夹", target: "HiddenFoldersActivity (self)", specs: ["SPEC-16"] },
{ id: "cab_unhide", ui: "CAB MenuItem", desc: "取消隐藏选中文件夹", target: "HiddenFoldersActivity (self)", specs: ["SPEC-16"] }
]
},
{
name: "EditActivity",
desc: "图片编辑器:滤镜、裁剪/旋转/缩放、涂鸦绘制。",
components: [
{ id: "save_as", ui: "MenuItem", desc: "保存编辑后的图片", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "edit", ui: "MenuItem", desc: "用外部编辑器打开", target: "外部应用", specs: ["SPEC-09"] },
{ id: "share", ui: "MenuItem", desc: "分享编辑后的图片", target: "外部应用", specs: ["SPEC-09"] },
{ id: "bottom_primary_filter", ui: "ImageView", desc: "切换滤镜模式", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_primary_crop_rotate", ui: "ImageView", desc: "切换裁剪/旋转模式", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_primary_draw", ui: "ImageView", desc: "切换绘画模式", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_rotate", ui: "ImageView", desc: "旋转裁剪视图90\u00B0", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_resize", ui: "ImageView", desc: "打开尺寸调整对话框", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio", ui: "ImageView", desc: "切换宽高比子栏", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_flip_horizontally", ui: "ImageView", desc: "水平翻转", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_flip_vertically", ui: "ImageView", desc: "垂直翻转", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio_free", ui: "TextView", desc: "设置自由宽高比", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio_one_one", ui: "TextView", desc: "设置1:1宽高比", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio_four_three", ui: "TextView", desc: "设置4:3宽高比", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio_sixteen_nine", ui: "TextView", desc: "设置16:9宽高比", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_aspect_ratio_other", ui: "TextView", desc: "自定义宽高比", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_draw_color_clickable", ui: "ImageView", desc: "打开画笔颜色选择器", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_draw_width", ui: "MySeekBar", desc: "调整画笔大小", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_draw_undo", ui: "ImageView", desc: "撤销上一笔", target: "EditActivity (self)", specs: ["SPEC-09"] },
{ id: "bottom_actions_filter_list", ui: "MyRecyclerView", desc: "滤镜缩略图列表", target: "EditActivity (self)", specs: ["SPEC-09"] }
]
},
{
name: "SetWallpaperActivity",
desc: "裁剪并设置图片为设备壁纸(主屏/锁屏/两者)。",
components: [
{ id: "save", ui: "MenuItem", desc: "设置为壁纸(Nougat+可选主屏/锁屏)", target: "SetWallpaperActivity (self)", specs: ["SPEC-14"] },
{ id: "allow_changing_aspect_ratio", ui: "MenuItem", desc: "清除固定宽高比", target: "SetWallpaperActivity (self)", specs: ["SPEC-14"] },
{ id: "bottom_set_wallpaper_aspect_ratio", ui: "ImageView", desc: "循环切换宽高比", target: "SetWallpaperActivity (self)", specs: ["SPEC-14"] },
{ id: "bottom_set_wallpaper_rotate", ui: "ImageView", desc: "旋转裁剪视图90\u00B0", target: "SetWallpaperActivity (self)", specs: ["SPEC-14"] },
{ id: "(implicit redirect)", ui: "程序化", desc: "无图片数据时跳转选择", target: "MainActivity", specs: ["SPEC-14"] }
]
},
{
name: "WidgetConfigureActivity",
desc: "桌面小部件配置:选择文件夹、颜色、透明度。",
components: [
{ id: "config_save", ui: "Button", desc: "保存小部件配置", target: "返回", specs: ["SPEC-18"] },
{ id: "config_bg_color", ui: "ImageView", desc: "背景颜色选择器", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] },
{ id: "config_text_color", ui: "ImageView", desc: "文字颜色选择器", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] },
{ id: "folder_picker_value", ui: "MyTextView", desc: "选择文件夹", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] },
{ id: "config_image_holder", ui: "RelativeLayout", desc: "选择文件夹", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] },
{ id: "folder_picker_show_folder_name_holder", ui: "RelativeLayout", desc: "切换文件夹名显示", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] },
{ id: "config_bg_seekbar", ui: "MySeekBar", desc: "背景透明度控制", target: "WidgetConfigureActivity (self)", specs: ["SPEC-18"] }
]
},
{
name: "PhotoVideoActivity",
desc: "外部 ACTION_VIEW 意图入口,根据文件类型路由到合适的查看器。",
components: [
{ id: "fragment_viewer_toolbar (back)", ui: "Toolbar back", desc: "关闭页面", target: "返回", specs: ["SPEC-15"] },
{ id: "menu_set_as", ui: "MenuItem", desc: "设为壁纸/头像", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_open_with", ui: "MenuItem", desc: "用其他应用打开", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_share", ui: "MenuItem", desc: "分享媒体文件", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_edit", ui: "MenuItem", desc: "打开外部编辑器", target: "外部应用", specs: ["SPEC-15"] },
{ id: "menu_properties", ui: "MenuItem", desc: "显示文件属性", target: "PhotoVideoActivity (self)", specs: ["SPEC-15"] },
{ id: "menu_show_on_map", ui: "MenuItem", desc: "地图显示GPS位置", target: "外部应用", specs: ["SPEC-15"] },
{ id: "bottom_edit", ui: "ImageView", desc: "打开外部编辑器", target: "外部应用", specs: ["SPEC-15"] },
{ id: "bottom_share", ui: "ImageView", desc: "分享媒体", target: "外部应用", specs: ["SPEC-15"] },
{ id: "bottom_set_as", ui: "ImageView", desc: "设为壁纸/头像", target: "外部应用", specs: ["SPEC-15"] },
{ id: "bottom_show_on_map", ui: "ImageView", desc: "地图显示位置", target: "外部应用", specs: ["SPEC-15"] },
{ id: "fragment_placeholder (tap)", ui: "Fragment content", desc: "切换全屏模式", target: "PhotoVideoActivity (self)", specs: ["SPEC-15"] },
{ id: "redirect: sendViewPagerIntent", ui: "程序化", desc: "有文件路径时跳转ViewPager", target: "ViewPagerActivity", specs: ["SPEC-15"] },
{ id: "redirect: launchVideoPlayer", ui: "程序化", desc: "视频跳转专用播放器", target: "VideoPlayerActivity/PanoramaVideoActivity", specs: ["SPEC-15"] },
{ id: "redirect: checkIntent fallback", ui: "程序化", desc: "无数据时跳转主页", target: "MainActivity", specs: ["SPEC-15"] }
]
},
{
name: "PhotoActivity",
desc: "PhotoVideoActivity 子类,仅处理 image/* 的 ACTION_VIEW 意图。",
components: [
{ id: "(all)", ui: "(all)", desc: "与 PhotoVideoActivity 完全一致", target: "同 PhotoVideoActivity", specs: ["SPEC-15"] }
]
},
{
name: "VideoActivity",
desc: "PhotoVideoActivity 子类,仅处理 video/* 的 ACTION_VIEW 意图。",
components: [
{ id: "(all)", ui: "(all)", desc: "与 PhotoVideoActivity 完全一致", target: "同 PhotoVideoActivity", specs: ["SPEC-15"] }
]
},
{
name: "VideoPlayerActivity",
desc: "ExoPlayer 视频播放器,支持播放控制、拖拽、手势亮度/音量调节。",
components: [
{ id: "video_toolbar (back)", ui: "Toolbar back", desc: "关闭播放器", target: "返回", specs: ["SPEC-06"] },
{ id: "menu_change_orientation", ui: "MenuItem", desc: "切换横竖屏锁定", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "menu_open_with", ui: "MenuItem", desc: "用其他应用打开", target: "外部应用", specs: ["SPEC-06"] },
{ id: "menu_share", ui: "MenuItem", desc: "分享视频", target: "外部应用", specs: ["SPEC-06"] },
{ id: "video_toggle_play_pause", ui: "ImageView", desc: "播放/暂停切换", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_curr_time", ui: "TextView", desc: "点击后退10秒", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_duration", ui: "TextView", desc: "点击前进10秒", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_seekbar", ui: "SeekBar", desc: "拖动进度条定位", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_prev_file", ui: "ImageView", desc: "返回上一个文件", target: "返回 (结果)", specs: ["SPEC-06"] },
{ id: "video_next_file", ui: "ImageView", desc: "跳转下一个文件", target: "返回 (结果)", specs: ["SPEC-06"] },
{ id: "video_surface_frame", ui: "GestureFrameLayout", desc: "点击全屏/双击跳转/拖拽快进", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_brightness_controller", ui: "MediaSideScroll", desc: "亮度手势控制", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "video_volume_controller", ui: "MediaSideScroll", desc: "音量手势控制", target: "VideoPlayerActivity (self)", specs: ["SPEC-06"] },
{ id: "swipe-down gesture", ui: "Touch gesture", desc: "下滑关闭播放器", target: "返回", specs: ["SPEC-06"] }
]
},
{
name: "PanoramaPhotoActivity",
desc: "使用 Google VR SDK 显示 360 度全景照片。",
components: [
{ id: "cardboard", ui: "ImageView", desc: "切换 Google Cardboard VR 模式", target: "PanoramaPhotoActivity (self)", specs: ["SPEC-07"] },
{ id: "explore", ui: "ImageView", desc: "切换触摸追踪平移", target: "PanoramaPhotoActivity (self)", specs: ["SPEC-07"] },
{ id: "panorama_view", ui: "VrPanoramaView", desc: "点击切换全屏模式", target: "PanoramaPhotoActivity (self)", specs: ["SPEC-07"] }
]
},
{
name: "PanoramaVideoActivity",
desc: "使用 Google VR SDK 播放 360 度全景视频。",
components: [
{ id: "cardboard", ui: "ImageView", desc: "切换 Google Cardboard VR 模式", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "explore", ui: "ImageView", desc: "切换触摸追踪平移", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "vr_video_view", ui: "VrVideoView", desc: "点击切换全屏模式", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "video_toggle_play_pause", ui: "ImageView", desc: "切换视频播放", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "video_curr_time", ui: "TextView", desc: "点击后退2%进度", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "video_duration", ui: "TextView", desc: "点击前进2%进度", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] },
{ id: "video_seekbar", ui: "SeekBar", desc: "拖动进度条定位", target: "PanoramaVideoActivity (self)", specs: ["SPEC-07"] }
]
}
];
let checkedSpecs = new Set();
function renderSpecs() {
const grid = document.getElementById('specGrid');
grid.innerHTML = SPECS.map(s => `
<label class="spec-item ${checkedSpecs.has(s.id) ? 'checked' : ''}" data-spec="${s.id}">
<input type="checkbox" ${checkedSpecs.has(s.id) ? 'checked' : ''} onchange="toggleSpec('${s.id}', this.checked)">
<span class="spec-id">${s.id}</span>
<span class="spec-name">${s.name}</span>
</label>
`).join('');
}
function getActivityStats(activity) {
const total = activity.components.length;
let covered = 0;
let noSpec = 0;
activity.components.forEach(c => {
if (c.specs.length === 0) {
noSpec++;
} else if (c.specs.some(s => checkedSpecs.has(s))) {
covered++;
}
});
const coverable = total - noSpec;
return { total, covered, noSpec, coverable };
}
function renderActivities() {
const list = document.getElementById('activityList');
list.innerHTML = ACTIVITIES.map((act, i) => {
const stats = getActivityStats(act);
const pct = stats.coverable > 0 ? Math.round(stats.covered / stats.coverable * 100) : (stats.total === stats.noSpec ? -1 : 0);
const pctClass = pct === 100 ? 'full' : pct > 0 ? 'partial' : 'none';
const pctDisplay = pct === -1 ? 'N/A' : pct + '%';
const fillClass = pct === 100 ? 'full' : pct > 0 ? 'partial' : 'none';
const fillWidth = pct === -1 ? 0 : (stats.coverable > 0 ? (stats.covered / stats.coverable * 100) : 0);
return `
<div class="activity-card" id="act-${i}">
<div class="activity-header" onclick="toggleActivity(${i})">
<svg class="chevron" id="chev-${i}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18l6-6-6-6"/></svg>
<div class="activity-name">${act.name}</div>
<div class="activity-progress-bar">
<div class="activity-progress-fill ${fillClass}" style="width:${fillWidth}%"></div>
</div>
<div class="activity-stats">
<span class="pct ${pctClass}">${pctDisplay}</span>
<div style="font-size:11px">${stats.covered}/${stats.coverable}${stats.noSpec > 0 ? ` <span style="color:#F57F17">(+${stats.noSpec} N/A)</span>` : ''}</div>
</div>
</div>
<div class="activity-body" id="body-${i}">
<div class="activity-desc">${act.desc}</div>
<table class="component-table">
<thead>
<tr>
<th style="width:50px">状态</th>
<th style="width:220px">组件 ID</th>
<th style="width:140px">UI 组件</th>
<th>功能描述</th>
<th style="width:160px">目标</th>
<th style="width:120px">关联 Spec</th>
</tr>
</thead>
<tbody>
${act.components.map(c => {
const isNoSpec = c.specs.length === 0;
const isCovered = !isNoSpec && c.specs.some(s => checkedSpecs.has(s));
const rowClass = isNoSpec ? 'no-spec' : (isCovered ? 'covered' : 'uncovered');
const badge = isNoSpec ? '<span class="status-badge no-spec">无Spec</span>'
: isCovered ? '<span class="status-badge covered">已覆盖</span>'
: '<span class="status-badge uncovered">未覆盖</span>';
const tags = c.specs.length > 0
? `<div class="spec-tags">${c.specs.map(s => `<span class="spec-tag ${checkedSpecs.has(s) ? 'active' : ''}">${s}</span>`).join('')}</div>`
: '<span style="color:#F57F17;font-size:11px">外部/平台差异</span>';
return `<tr class="${rowClass}">
<td>${badge}</td>
<td style="font-family:monospace;font-size:12px">${c.id}</td>
<td style="font-size:12px">${c.ui}</td>
<td>${c.desc}</td>
<td style="font-size:12px">${c.target}</td>
<td>${tags}</td>
</tr>`;
}).join('')}
</tbody>
</table>
</div>
</div>`;
}).join('');
}
function updateGlobalStats() {
let totalCoverable = 0, totalCovered = 0, totalAll = 0, totalNoSpec = 0;
let actFullyCovered = 0;
ACTIVITIES.forEach(act => {
const stats = getActivityStats(act);
totalAll += stats.total;
totalCoverable += stats.coverable;
totalCovered += stats.covered;
totalNoSpec += stats.noSpec;
if (stats.covered > 0) actFullyCovered++;
});
const globalPct = totalCoverable > 0 ? Math.round(totalCovered / totalCoverable * 100) : 0;
document.getElementById('globalPct').textContent = globalPct + '%';
document.getElementById('globalDetail').textContent = `${totalCovered} / ${totalCoverable} 功能点`;
const specPct = SPECS.length > 0 ? Math.round(checkedSpecs.size / SPECS.length * 100) : 0;
document.getElementById('specPct').textContent = specPct + '%';
document.getElementById('specDetail').textContent = `${checkedSpecs.size} / ${SPECS.length} Spec`;
const actPct = ACTIVITIES.length > 0 ? Math.round(actFullyCovered / ACTIVITIES.length * 100) : 0;
document.getElementById('actPct').textContent = actPct + '%';
document.getElementById('actDetail').textContent = `${actFullyCovered} / ${ACTIVITIES.length} Activity`;
}
function toggleSpec(id, checked) {
if (checked) checkedSpecs.add(id); else checkedSpecs.delete(id);
saveState();
renderAll();
}
function selectAll() {
SPECS.forEach(s => checkedSpecs.add(s.id));
saveState();
renderAll();
}
function deselectAll() {
checkedSpecs.clear();
saveState();
renderAll();
}
let openActivities = new Set();
function toggleActivity(i) {
const body = document.getElementById('body-' + i);
const chev = document.getElementById('chev-' + i);
if (openActivities.has(i)) {
openActivities.delete(i);
body.classList.remove('open');
chev.classList.remove('open');
} else {
openActivities.add(i);
body.classList.add('open');
chev.classList.add('open');
}
}
function renderAll() {
renderSpecs();
renderActivities();
updateGlobalStats();
openActivities.forEach(i => {
const body = document.getElementById('body-' + i);
const chev = document.getElementById('chev-' + i);
if (body) { body.classList.add('open'); chev.classList.add('open'); }
});
}
function saveState() {
try { localStorage.setItem('sg_checked_specs_v2', JSON.stringify([...checkedSpecs])); } catch(e) {}
}
function loadState() {
try {
const saved = localStorage.getItem('sg_checked_specs_v2');
if (saved) { JSON.parse(saved).forEach(s => checkedSpecs.add(s)); }
} catch(e) {}
}
function exportMarkdown() {
let totalCoverable = 0, totalCovered = 0, totalNoSpec = 0;
ACTIVITIES.forEach(act => {
const s = getActivityStats(act);
totalCoverable += s.coverable;
totalCovered += s.covered;
totalNoSpec += s.noSpec;
});
const globalPct = totalCoverable > 0 ? Math.round(totalCovered / totalCoverable * 100) : 0;
const checkedList = SPECS.filter(s => checkedSpecs.has(s.id)).map(s => s.id + ' ' + s.name);
let md = `# SimpleGallery Android \u2192 HarmonyOS \u529F\u80FD\u8986\u76D6\u6E05\u5355\n\n`;
md += `> \u5BFC\u51FA\u65F6\u95F4\uFF1A${new Date().toLocaleString('zh-CN')}\n\n`;
md += `**\u5DF2\u5B8C\u6210 Spec (${checkedSpecs.size}/${SPECS.length})\uFF1A** ${checkedList.length > 0 ? checkedList.join('\u3001') : '\u65E0'}\n\n`;
md += `**\u603B\u4F53\u8986\u76D6\u7387\uFF1A${globalPct}%** \uFF08${totalCovered}/${totalCoverable} \u53EF\u8986\u76D6\u529F\u80FD\u70B9\uFF0C${totalNoSpec} \u4E2A\u65E0\u5BF9\u5E94Spec\u529F\u80FD\u70B9\uFF09\n\n`;
md += `| \u9875\u9762 (Activity) | \u7EC4\u4EF6 / \u529F\u80FD\u70B9 | \u8986\u76D6\u72B6\u6001 |\n`;
md += `|---|---|---|\n`;
ACTIVITIES.forEach(act => {
const stats = getActivityStats(act);
const pct = stats.coverable > 0 ? Math.round(stats.covered / stats.coverable * 100) : (stats.total === stats.noSpec ? -1 : 0);
const pctStr = pct === -1 ? 'N/A' : pct + '%';
let first = true;
act.components.forEach(c => {
const isNoSpec = c.specs.length === 0;
const isCovered = !isNoSpec && c.specs.some(s => checkedSpecs.has(s));
const status = isNoSpec ? 'n/a' : (isCovered ? 'yes' : 'no');
const specStr = c.specs.length > 0 ? ` [${c.specs.join(', ')}]` : '';
const actCell = first ? `**${act.name}** (${pctStr})` : '';
md += `| ${actCell} | \`${c.id}\` ${c.desc}${specStr} | ${status} |\n`;
first = false;
});
});
const blob = new Blob([md], { type: 'text/markdown;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `coverage_report_${new Date().toISOString().slice(0, 10)}.md`;
a.click();
URL.revokeObjectURL(url);
}
loadState();
renderAll();
</script>
</body>
</html>