skillhub/docs/prds/file-preview-syntax-highlighting-v1.0-prd.md
XiaoSeS ee33505b7c feat: File Browser Sidebar with Preview, Security Audit UI, and Syntax Highlighting (#145)
* feat(security): extend scanner config with full analyzer options

Integrate skill-scanner's 8 analysis engines and policy configuration
into SkillHub's config system. Operators can now control behavioral,
LLM, Meta, AI Defense, VirusTotal, and trigger analyzers via
application.yml or environment variables.

Changes:
- Add Analyzers and Policy nested classes to SkillScannerProperties
- Create ScanOptions record to encapsulate analyzer flags
- Update SkillScannerService to pass options in /scan body and /scan-upload query params
- Wire ScanOptions through SkillScannerConfig and SkillScannerAdapter
- Extend application.yml with full scanner config block and env var overrides
- Update all tests to verify new configuration flow

All tests pass.

* feat(security): add domain model and integrate scan into publish flow

Add SCANNING/SCAN_FAILED status to SkillVersionStatus. Introduce
SecurityScanService, SecurityScanner port, ScanTask, SecurityAudit
and related domain types. Wire scan trigger into SkillPublishService
so non-auto-publish versions enter scanning when scanner is enabled,
falling back to review task creation when disabled.

* feat(security): add infra layer for scanner HTTP client and adapters

Add WebClient-based HttpClient abstraction with WebClientHttpClient
implementation. Add SkillScannerApiResponse record, SecurityScanException,
and SecurityAuditJpaRepository. Add webflux and test dependencies to
infra module.

* feat(security): add Redis stream consumers, audit API, and DB migration

Add AbstractStreamConsumer base class, ScanTaskConsumer for processing
scan results from Redis stream, and RedisScanTaskProducer. Add
RedisStreamConfig for stream/group initialization. Add SecurityAudit
REST controller and DTO. Add V35 Flyway migration for security_audits
table.

* feat(security): add scanner config to application profiles

Add scanner enabled flag to application-local.yml and
application-test.yml. Enable behavioral analyzer by default
in application.yml.

* feat(deploy): add skill-scanner to docker-compose and k8s manifests

Add skill-scanner service to docker-compose.yml with health check.
Add scanner k8s deployment, service, and configmap entries. Wire
scanner env vars into Makefile dev-all flow. Add verify-scanner.sh
script for post-deploy validation.

* docs(security): add scanner documentation suite

Add scanner docs: configuration guide, failure impact analysis,
monitoring guide, improvement recommendations, custom rules guide,
and skill-vetter rules conversion example. Update deployment docs
with scanner section. Add security-scanning overview and PRD.

* feat(security): add skill-vetter custom rule examples

Add example Regex and YARA rules derived from skill-vetter RED FLAGS
in scanner/examples/vetter-rules/. Includes 7 Regex rules
(signatures-append.yaml) and 3 YARA rules (skillhub_vetter.yara)
covering agent memory theft, IP-based exfiltration, and browser
data theft detection.

* feat(security): add scanner Docker build context

Add Dockerfile for cisco-ai-skill-scanner container and
.env.example with LLM configuration placeholders.

* fix(security): align Finding mapping with scanner API response schema

SkillScannerApiResponse.Finding used incorrect field names (message,
location.file, location.line, code_snippet) that did not match the
scanner's actual JSON output (description, file_path, line_number,
snippet), causing all four fields to deserialize as null.

Flatten Finding to match scanner API: remove nested Location, rename
fields to description/file_path/line_number/snippet. Add skill_name
and timestamp to SkillScannerApiResponse. Extend SecurityFinding with
remediation, analyzer, and metadata fields to capture LLM analyzer
output. Retain 8-arg compact constructor for backward compatibility.

* chore(security): add debug logging to scanner response mapping

Log raw scanner API response and mapped SecurityFinding fields
side-by-side to help verify data consistency between scanner
output and database records.

* feat(security): add multi-scanner support and soft delete for security audits

- Add ScannerType enum for type-safe scanner identification
- Update V35 migration to support multiple scanners and soft delete
- Remove CASCADE delete, use code-level soft delete (deleted_at)
- Add repository methods for querying latest audit by scanner type
- Update SecurityScanService to handle scanner type parameter
- Integrate soft delete in SkillHardDeleteService
- Update all tests to use ScannerType enum

This enables multiple scanner integrations (skill-scanner, future LLM/compliance scanners)
and preserves complete audit history through soft deletion.

* feat(security): add security audit UI to review detail and skill detail pages

Display security scan results on the review detail page (full audit
section with collapsible findings) and the skill detail sidebar (compact
summary with dialog for details).  Handles empty/404 gracefully by
returning null, avoids loading shimmer flicker, and separates lifecycle
action buttons with a visual divider.

* docs(security): add security audit UI PRD

* docs(prd): add related documents section to file browser sidebar PRD

* feat(skill): add file tree builder utility

Implement buildFileTree function to convert flat SkillFile[] into hierarchical tree structure.
- Nodes sorted alphabetically by path
- Support for nested directories
- Each node includes depth, type, and path information
- Includes comprehensive test coverage

* feat(skill): add file type detection utilities

Implement utilities for file type detection and preview capability checks:
- isPreviewable: checks if file can be previewed based on extension and size
- canPreviewFile: provides detailed reason when file cannot be previewed
- getFileTypeLabel: returns human-readable file type labels
- getFileIcon: maps file types to appropriate Lucide icons
- Supports 1MB max file size limit
- Comprehensive test coverage for all functions

* feat(skill): add file tree node component

Implement recursive FileTreeNodeComponent with:
- Expand/collapse functionality for directories
- File and directory icons from Lucide React
- Hover effects showing file sizes
- Proper indentation based on depth
- Support for nested directory structures

* refactor(skill): upgrade file tree to hierarchical structure

Replace flat file list with tree structure:
- Use buildFileTree to convert flat files into hierarchy
- Integrate FileTreeNodeComponent for rendering
- Update onFileClick to accept FileTreeNode instead of SkillFile
- Add file count badge in header
- Root-level directories expanded by default

* feat(skill): add file preview dialog component

Implement FilePreviewDialog with:
- Markdown rendering via existing MarkdownRenderer
- Plain text/code display with monospace font
- Non-previewable file message with download button
- Copy-to-clipboard and download actions in header
- File path display in footer
- Loading and error states

* feat(i18n): add file tree and preview translations

Add Chinese and English translations for:
- File browser title
- Preview error messages (load failure, too large, binary, unsupported)
- Download file button

* feat(skill): integrate file preview into skill detail page

- Add useSkillFile hook for fetching arbitrary file content
- Add file preview state, click handler, and download handler
- Pass onFileClick to FileTree for opening preview dialog
- Add FilePreviewDialog to skill detail page

* feat(review): add file reading API endpoint

Add GET /api/v1/reviews/{id}/file?path=... for reading single files
from the review-bound skill version:
- ReviewController: new endpoint with path traversal validation
- GovernanceWorkflowAppService: route method for review file access
- ReviewSkillDetailAppService: authorization and delegation
- SkillQueryService: getFileContentByVersionId for direct version access

* feat(review): integrate file preview into review detail

- Add useReviewFile hook for fetching review file content
- Add file preview state and handlers to ReviewSkillDetailSection
- Pass reviewId prop for API calls
- Add FilePreviewDialog to review detail expanded section
- Update review-detail.tsx to pass taskId as reviewId

* fix(test): update test mocks for file preview hooks

- Add useSkillFile mock to skill-detail.test.tsx
- Add useQuery mock to @tanstack/react-query mock
- Add useReviewFile mock to review-skill-detail-section.test.tsx
- Fix SkillFile test fixtures to include all required properties
- Remove unused imports in test and component files

* fix(skill): use DomainBadRequestException for version not found

Replace DomainNotFoundException with DomainBadRequestException in
getFileContentByVersionId to match existing patterns and imports.

* feat(skill): add file tree sidebar with file sizes

- Move file tree to right sidebar for persistent visibility
- Display file sizes always visible (not just on hover)
- Keep Files tab showing the same tree structure
- Add scrollable container with max-height for long file lists

* fix(skill): improve file tree sidebar UI and UX

- Remove redundant title from file tree sidebar
- Adjust scrollbar placement with proper flex layout
- Sort folders first, then files (both alphabetically)
- Collapse all folders by default for cleaner initial view
- Increase dialog width to max-w-5xl and height to 90vh
- Remove duplicate close button (X icon)
- Add hover effects to action buttons
- Use flexbox for proper content scrolling
- Allow .pyc files in backend configuration

Fixes:
1. File tree sidebar now has cleaner layout without title
2. Scrollbar properly contained within card
3. Folders appear before files in tree
4. All folders collapsed by default
5. Preview dialog wider and more usable
6. Single close method (ESC or click outside)
7. Action buttons have visual feedback on hover

* fix(skill): refine file tree sidebar and preview dialog

1. Default all folders to collapsed state
2. File tree sidebar now uses Card+bare pattern matching SecurityAuditSummary
   - Scrollbar inside the card content area instead of wrapping the tree
   - Consistent padding and header layout with other sidebar cards
3. Preview dialog close button fixed:
   - Hide DialogContent's built-in close button via [&>button]:hidden
   - Add X button in the header row, same level as copy/download
   - All action buttons share consistent hover animation (opacity transition)
4. Sort directories before files at every tree level
5. Update tests for new directory-first sort order

* feat(skill): collapsible file browser, wider dialog, button animations

1. File browser sidebar now supports expand/collapse toggle
   - Click the header row to toggle visibility
   - ChevronUp/Down icon indicates state
   - Default expanded on page load

2. File preview dialog widened to 72rem (was 5xl/64rem)
   - Uses w-[min(calc(100vw-2rem),72rem)] for responsive max

3. Header action buttons now have micro-interactions:
   - Copy/Download: scale up on hover, scale down on click
   - Close (X): rotates 90° on hover with destructive tint
   - All buttons: opacity 60→100 transition on hover

* feat(skill): chevron animation, button effects, download path hint, review sidebar

1. File browser chevron: single ChevronDown with rotate-180 CSS transition
   instead of swapping two icons — smooth 200ms rotation animation

2. Preview dialog action button animations:
   - Copy icon: active:scale-125 feedback on click
   - Download icon: hover:translate-y-0.5 subtle downward motion
   - Close icon: hover:rotate-90 with destructive tint (unchanged)

3. Download tooltip now shows full file path:
   "下载 src/prompts/system.md" instead of generic "下载文件"
   - New i18n keys: filePreview.downloadHint, filePreview.copy, filePreview.close

4. Review detail page now has a sidebar file browser:
   - Two-column layout (main content + lg:w-80 sidebar)
   - File tree sourced from reviewSkillDetail.files (active review version)
   - Collapsible with same chevron animation as skill detail page
   - Shows active version badge below file tree
   - File preview uses review file API (/reviews/{id}/file?path=...)
   - Test mocks updated for new useReviewFile dependency

* fix(skill): download shows filename, copy rotates with success toast

1. Download button tooltip/text now shows actual filename:
   "下载 README.md" instead of generic path
   - i18n key changed from {{path}} to {{name}}

2. Copy button animation reworked to rotation:
   - idle: hover:rotate-180 on the Copy icon
   - click: animate-spin during clipboard write
   - done: swap to green Check icon for 1.5s, then reset

3. Copy success toast notification:
   - Shows "已复制到剪贴板" / "Copied to clipboard" via toast.success
   - New i18n key: filePreview.copySuccess

* fix(skill): set download attribute so browser saves with original filename

The <a> element was missing the download attribute, causing the browser
to derive the filename from the URL path segment (/file?path=...) which
always resolved to "file". Now explicitly sets link.download = node.name
so the saved file uses the original name (e.g. README.md, config.json).

Applied to all three download handlers:
- skill-detail.tsx (skill version file)
- review-detail.tsx (review sidebar file)
- review-skill-detail-section.tsx (review expanded section file)

* feat(skill): add icons to all sidebar card headers

Add Lucide icons to each sidebar section for visual consistency
with the existing SecurityAuditSummary (Shield) and file browser (Folder):

- Terminal: Install command
- Clock: Pending review (amber-colored to match card theme)
- RefreshCw: Lifecycle management
- Tag: Label management (in SkillLabelPanel component)
- ArrowUpCircle: Promotion
- ShieldCheck: Governance

All icons use the same pattern: w-4 h-4 text-muted-foreground
placed inside a flex row with gap-2 before the section title.

* fix(skill): allow owners to preview all version statuses

When a skill has only a REJECTED version, the detail page crashed with
400 "版本未发布" because assertPreviewAccessible() only allowed PUBLISHED
and PENDING_REVIEW(owner). The frontend fallback to versions[0] would
pick the REJECTED version and fail all file/readme queries.

Backend changes:
- assertPreviewAccessible(): now allows owners and namespace admins to
  preview ANY version status (DRAFT, REJECTED, YANKED, SCANNING, etc.)
  via canManageRestrictedSkill() check. Also passes userNsRoles so
  namespace admin role is respected, not just owner.
- resolveOwnerPendingPreview(): expanded from PENDING_REVIEW-only to
  include all non-published, non-yanked statuses so headlineVersion
  resolves correctly for owners with REJECTED/DRAFT/SCANNING versions.

Frontend changes:
- isOwnerPreviewResolution(): relaxed from checking PENDING_REVIEW
  specifically to checking any non-PUBLISHED status, matching the
  backend's broader projection.

Fixes: owner viewing skill with only REJECTED version → 400 error
Also fixes: DRAFT-only, SCANNING-only, SCAN_FAILED-only scenarios

* docs(requirements): add comprehensive requirements for file preview syntax highlighting

Generated complete documentation suite including:
- Core PRD (clarity score: 95/100)
- Constraints specification (8 business rules)
- Impact analysis (8 risks identified)
- Acceptance cases (25 test cases: 10 positive, 5 error, 7 boundary, 3 security)
- Test plan (100% coverage)

Mode: Quick (3 clarification rounds)
Complexity: Simple (3.5 days estimated)

* feat(skill): add syntax highlighting for code file preview

Implement syntax highlighting for code files in the file preview dialog:
- Add CodeRenderer component using lowlight (highlight.js wrapper via rehype-highlight)
- Add getLanguageForHighlight() to map file extensions to highlight.js languages
- Support 20+ languages: Python, JS/TS, Java, Go, Rust, C/C++, Ruby, PHP, Shell, JSON, YAML, XML, etc.
- Apply 500KB threshold for syntax highlighting (larger files show plain text)
- Maintain visual consistency with Markdown code blocks
- Auto-adapt to light/dark theme using existing CSS variables
- Add lowlight as direct dependency to enable programmatic syntax highlighting

Implements solution 1 from PRD (reuse rehype-highlight infrastructure).

* fix(security): resolve security audit FK constraint and stale query issues

Backend:
- Add hardDeleteByVersionId to physically remove audit records before
  deleting skill versions (fixes FK constraint violation on hard delete)
- Add softDeleteByVersionId calls in SkillGovernanceService and
  SkillPublishService version deletion paths
- Add V36 migration to convert security_audit TIMESTAMP columns to
  TIMESTAMPTZ matching project convention
- Update tests to verify audit cleanup in all deletion flows

Frontend:
- Prevent stale API calls after skill deletion by gating all query
  hooks with a skillDeleted flag that disables them immediately
- Move cache cleanup from useDeleteSkill onSuccess to the handler
  to avoid refetching while the component is still mounted

* fix(skill): handle SCANNING and SCAN_FAILED statuses across all pages

Backend:
- Include SCANNING/SCAN_FAILED in version listing filters so owners
  can see versions being scanned
- Add explicit lifecycle sort priority for scanner statuses
- Allow deletion of SCAN_FAILED versions alongside DRAFT and REJECTED

Frontend:
- Add i18n labels and CSS classes for SCANNING/SCAN_FAILED in my-skills
- Add localized version status labels in skill-detail version list
- Hide archive button when no published version exists (my-skills and
  skill-detail)
- Allow deleting SCAN_FAILED versions from skill-detail

* gitignore
2026-03-23 14:38:47 +08:00

11 KiB
Raw Permalink Blame History

文件预览语法高亮 - 产品需求文档 (PRD)

需求描述

背景

  • 业务问题:当前文件预览功能仅对 Markdown 文件提供语法高亮渲染其他代码文件Python、Shell、Java、TypeScript 等)只显示纯文本,用户体验不佳,无法快速理解代码结构。
  • 目标用户:技能开发者、审核人员、技能使用者
  • 价值主张:提供与 Markdown 代码块一致的高质量语法高亮,提升代码可读性,加速代码审查和理解效率。

功能概述

  • 核心功能

    1. 为常见编程语言Python, Shell, Java, JS/TS, Go, Rust, C/C++, Ruby, PHP提供语法高亮
    2. 为配置文件JSON, YAML, TOML, XML提供语法高亮
    3. 复用现有的 rehype-highlight基于 highlight.js渲染引擎
    4. 保持与 Markdown 代码块一致的视觉样式
    5. 支持 dark/light 主题自动切换
  • 功能边界

    • 包含:常见编程语言和配置文件的语法高亮、错误降级处理、性能优化
    • 不包含:行号显示、代码折叠、语法错误检测、自定义主题配置
  • 用户场景

    1. 技能审核人员查看提交的 Python 脚本,快速识别代码逻辑
    2. 开发者预览技能包中的配置文件(如 skill.yaml确认参数配置
    3. 用户浏览技能源码,了解实现细节

详细需求

  • 输入/输出

    • 输入文件路径、文件内容InputStream、文件扩展名
    • 输出:带语法高亮的 HTML通过 highlight.js 渲染)
  • 用户交互

    1. 用户点击文件树中的代码文件节点
    2. 前端显示 loading 状态
    3. 后端返回文件内容和元数据(大小、类型)
    4. 前端根据文件大小和类型决定渲染策略:
      • ≤ 500KB语法高亮渲染
      • 500KB < size ≤ 1MB纯文本渲染无高亮
      • 1MB仅显示下载按钮

  • 数据要求

    • 文件大小:通过 SkillFile.fileSize 字段获取
    • 文件类型:通过文件扩展名推断(.py → Python
    • 语言映射:使用 file-type-utils.ts 中的映射表
  • 边界情况

    1. 无法识别的语言:显示纯文本(无高亮),不报错
    2. 语法高亮失败:降级到纯文本显示,记录错误日志
    3. 内存不足:降级到纯文本显示,显示提示信息
    4. 大文件(> 500KB:跳过语法高亮,直接显示纯文本
    5. 超大文件(> 1MB:不预览,仅提供下载

设计决策

技术方案

  • 架构选择:复用现有的 rehype-highlight基于 highlight.js

    • 理由
      1. 零额外依赖,不增加包体积
      2. 样式与 Markdown 代码块完全一致
      3. 已有的语言支持190+ 种语言)
      4. 维护成本低
  • 关键组件

    1. CodeRenderer 组件(新增):

      • 位置:web/src/features/skill/code-renderer.tsx
      • 职责:接收代码字符串和语言类型,调用 highlight.js 渲染
      • 依赖:highlight.js/lib/core + 按需导入的语言包
    2. file-type-utils.ts(扩展):

      • 新增 getLanguageForHighlight(extension: string): string | null 函数
      • 映射文件扩展名到 highlight.js 语言标识符
    3. file-preview-dialog.tsx(修改):

      • 根据文件大小和类型选择渲染器:
        • Markdown → MarkdownRenderer
        • 代码文件(≤ 500KBCodeRenderer
        • 代码文件(> 500KB→ 纯文本 <pre><code>
        • 其他 → 下载提示
  • 数据存储

    • 无需新增数据库字段
    • 文件内容从云存储ObjectStorageService读取
    • 文件大小已存储在 SkillFile.fileSize 字段
  • 接口设计

    • 复用现有 APIGET /api/v1/reviews/{id}/file?path={filePath}
    • 响应格式:InputStream(保持不变)
    • 前端根据 Content-Length 响应头判断文件大小

约束条件

  • 性能要求

    • 语法高亮渲染时间:< 500ms对于 500KB 文件)
    • 首次加载时间:< 1s包括网络请求
    • 内存占用:单个文件渲染 < 50MB
  • 兼容性

    • 浏览器Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
    • 移动端:支持响应式布局,但不优化触摸交互
  • 安全性

    • 使用 dangerouslySetInnerHTML 时,确保 highlight.js 输出已转义
    • 防止 XSS 攻击:不允许用户自定义语法高亮规则
    • 文件路径验证:复用现有的路径遍历防护(禁止 .. 和绝对路径)
  • 可扩展性

    • 语言支持:通过按需导入语言包扩展,不影响初始包体积
    • 主题支持:预留主题切换接口,当前仅支持跟随系统主题

风险评估

  • 技术风险

    • 风险:大文件语法高亮导致浏览器卡顿
    • 概率:中
    • 影响:高
    • 缓解措施
      1. 设置 500KB 阈值,超过则不高亮
      2. 增加 loading 状态提示用户
      3. 提供"取消加载"按钮(后续优化)
  • 依赖风险

    • 风险highlight.js 无法识别某些语言
    • 概率:低
    • 影响:低
    • 缓解措施:降级到纯文本显示,不影响核心功能
  • 进度风险

    • 风险:后端缓存和限流实现延期
    • 概率:中
    • 影响:中
    • 缓解措施
      1. 前端功能可独立上线
      2. 后端优化作为独立任务,分阶段实施

验收标准

功能验收

  • 功能 1Python 文件(.py显示语法高亮关键字、字符串、注释着色
  • 功能 2Shell 脚本(.sh, .bash显示语法高亮
  • 功能 3配置文件JSON, YAML, TOML, XML显示语法高亮
  • 功能 4Java/TypeScript/JavaScript 文件显示语法高亮
  • 功能 5无法识别的语言显示纯文本不报错
  • 功能 6大文件> 500KB显示纯文本无高亮
  • 功能 7超大文件> 1MB仅显示下载按钮
  • 功能 8语法高亮样式与 Markdown 代码块一致
  • 功能 9支持 dark/light 主题自动切换
  • 功能 10复制代码按钮正常工作

质量标准

  • 代码质量:通过 ESLint 和 TypeScript 类型检查
  • 测试覆盖核心逻辑CodeRenderer, getLanguageForHighlight单元测试覆盖率 > 80%
  • 性能指标:
    • 500KB 文件渲染时间 < 500msP95
    • 首次加载时间 < 1sP95
    • Lighthouse 性能评分不下降
  • 安全审查:代码审查确认无 XSS 风险

用户验收

  • 用户体验:审核人员反馈代码可读性提升
  • 文档:更新用户文档,说明支持的文件类型
  • 无障碍:键盘导航正常,屏幕阅读器可访问

执行阶段

阶段 1准备工作

目标:环境准备和技术验证

  • 任务 1调研 highlight.js 语言包按需导入方案
  • 任务 2验证 rehype-highlight 的 CSS 样式可复用性
  • 任务 3确认文件大小字段SkillFile.fileSize)已存在
  • 任务 4设计 CodeRenderer 组件 API
  • 交付物:技术方案文档、组件 API 设计
  • 时间0.5 天

阶段 2核心开发

目标:实现语法高亮核心功能

  • 任务 1创建 CodeRenderer 组件
    • 导入 highlight.js 核心库
    • 按需导入常见语言包Python, Shell, Java, JS/TS, Go, Rust, C/C++, Ruby, PHP
    • 按需导入配置文件语言包JSON, YAML, TOML, XML
    • 实现 highlightCode(code: string, language: string) 函数
    • 复用 Markdown 代码块的 CSS 样式
  • 任务 2扩展 file-type-utils.ts
    • 新增 getLanguageForHighlight(extension: string) 函数
    • 映射文件扩展名到 highlight.js 语言标识符
  • 任务 3修改 file-preview-dialog.tsx
    • 根据文件大小和类型选择渲染器
    • 实现 500KB 和 1MB 阈值逻辑
    • 集成 CodeRenderer 组件
  • 任务 4主题适配
    • 确保语法高亮样式跟随 dark/light 主题
    • 测试主题切换时的视觉一致性
  • 交付物:可运行的语法高亮功能
  • 时间1.5 天

阶段 3集成与测试

目标:集成测试和质量保证

  • 任务 1单元测试
    • CodeRenderer 组件测试(不同语言、边界情况)
    • getLanguageForHighlight 函数测试
  • 任务 2集成测试
    • 技能详情页文件预览测试
    • 审核详情页文件预览测试
  • 任务 3性能测试
    • 测试 500KB 文件渲染时间
    • 测试内存占用
  • 任务 4浏览器兼容性测试
    • Chrome, Firefox, Safari, Edge
  • 任务 5用户验收测试
    • 邀请审核人员试用,收集反馈
  • 交付物:测试报告、性能基准数据
  • 时间1 天

阶段 4部署与监控

目标:上线发布和效果监控

  • 任务 1代码审查
    • 安全审查XSS 风险)
    • 性能审查(包体积、渲染性能)
  • 任务 2部署到生产环境
    • 前端构建和部署
    • 验证生产环境功能正常
  • 任务 3监控指标
    • 文件预览 API 响应时间
    • 前端渲染性能(通过 RUM
    • 错误率监控
  • 任务 4文档更新
    • 更新用户文档,说明支持的文件类型
    • 更新开发者文档,说明如何添加新语言支持
  • 交付物:生产环境部署、监控仪表板、用户文档
  • 时间0.5 天

文档版本1.0 创建时间2026-03-22 澄清轮次3 质量评分95/100

附录:后端优化方案(后续实施)

以下优化方案已记录在文档中,但不在本次实施范围内,将作为独立任务后续统一实现。

1. 后端缓存策略

  • 目标:减少云存储读取次数,降低响应时间
  • 方案
    • 使用 Redis 缓存文件内容
    • 缓存键:file:content:{storageKey}
    • TTL1 小时
    • 缓存策略LRU最近最少使用
  • 预期效果
    • 缓存命中率 > 60%
    • 响应时间降低 50%

2. 限流策略

  • 目标:防止文件预览 API 被滥用,保护后端服务
  • 方案
    • 使用 @RateLimit 注解
    • 配置:
      @RateLimit(
          category = "file-preview",
          authenticated = 60,    // 认证用户:每分钟 60 次
          anonymous = 20,        // 匿名用户:每分钟 20 次
          windowSeconds = 60
      )
      
    • 限流粒度:按用户 ID认证用户或 IP匿名用户
    • 超出限流响应:返回 429 状态码 + {"code": 429, "message": "error.rateLimit.exceeded"}
  • 预期效果
    • 防止单用户/IP 过度请求
    • 保护云存储 API 配额

3. 监控指标

  • 目标:实时监控文件预览功能的健康状况
  • 指标
    • 文件预览 API 响应时间P50, P95, P99
    • 文件预览 API 错误率
    • 缓存命中率
    • 限流触发次数
    • 云存储 API 调用次数
  • 告警规则
    • P95 响应时间 > 2s警告
    • 错误率 > 5%:严重
    • 缓存命中率 < 40%:警告

4. 实施优先级

  1. P0本次实施:前端语法高亮功能
  2. P1下个迭代:后端缓存策略
  3. P2后续优化:限流策略、监控指标