feat: add theme toggle component and theme store for light/dark mode support

- Implemented ThemeToggle component for switching between light, dark, and system themes.
- Created themeStore for managing theme state and persisting user preferences in localStorage.
- Added utility functions for error message sanitization to prevent sensitive data leakage.
- Developed proxy utility functions for API requests, including template variable replacement.
- Enhanced layout with dark mode styles and smooth transitions for theme changes.
- Updated main layout and page components to integrate theme toggle and improve accessibility.
- Added server-side proxy handling with validation and error sanitization for API requests.
This commit is contained in:
lirui
2026-02-09 23:13:18 +08:00
parent cd6ca590b4
commit 5e20e37cda
20 changed files with 1711 additions and 290 deletions

163
demands/DEMAND-proxy.md Normal file
View File

@@ -0,0 +1,163 @@
这是一个为您准备的 **v3.0 版本需求文档**
这份文档的核心目标是**“收口”**:将之前零散开发的“前端代理 (Proxy)”功能正式集成到主流程中,确立 **“混合模式 (Hybrid Mode)”** 的架构策略。
即:**前端负责实时测试和预览(利用 Proxy后端/脚本负责全量执行(利用 Job Bundle。**
---
### 复制下面的内容发送给 Claude
---
**Role:** 资深全栈架构师 (SvelteKit + TypeScript)
**Project Context:**
我们正在开发 "Excel2JSON ETL Blueprint Generator"。
目前我们已经具备了:
1. **前端:** Excel 解析、映射配置、JSON 预览。
2. **后端能力:** 一个 `/api/proxy` 端点 (SvelteKit Endpoint),可以绕过 CORS 转发请求。
3. **输出:** `job_bundle.json` 用于给 Python 脚本跑全量数据。
**Current Goal (Phase 3 Integration):**
我们需要正式集成 `/api/proxy`,实现 **“所见即所得”** 的 API 调试体验。
用户在配置 API 字段时,可以直接点击“测试”,前端调用 Proxy 立即拿回数据并展示,确保配置无误后再导出。
### Phase 3: 在线调试与混合执行架构需求文档
#### 1. 核心架构策略:混合模式 (Hybrid Execution)
为了平衡**用户体验**与**系统性能**,我们采用以下策略:
* **调试/预览阶段 (Online Mode):**
* 使用 SvelteKit 后端代理 (`/api/proxy`)。
* **作用:** 让用户在配置界面就能实时验证 "URL 填得对不对"、"JSON Path 提取得对不对"。
* **限制:** 仅用于**单条数据**测试或**小批量 (前10条)** 预览。
* **生产/执行阶段 (Offline Mode):**
* 使用 `job_bundle.json` + Python 脚本。
* **作用:** 处理成千上万行数据的全量抓取和入库。
* **优势:** 无超时限制,无浏览器崩溃风险。
#### 2. UI/UX 交互升级
##### 2.1 API 配置面板 (Enrichment Config Modal)
`ApiConfigModal.svelte` 中增加 **"Test Connection" (测试连接)** 功能区。
* **输入区:** (已有的 URL, Method, Headers, Body 配置)
* **测试上下文 (Test Context):**
* 显示当前 Excel 的 **第一行数据** 作为测试样本。
* *示例:* `User ID: 101`, `Name: Alice`
* 用户可以手动修改这些样本值来测试不同情况。
* **操作:** 点击 **[Test Request]** 按钮。
* **逻辑:**
1. 前端将 URL 模板中的 `{{Variables}}` 替换为测试样本值。
2. 发送 POST 请求给本站的 `/api/proxy`
3. 等待响应。
* **反馈区:**
* **Status:** 显示 HTTP 状态码 (e.g., `200 OK`, `404 Not Found`)。
* **Response Preview:** 显示原始返回的 JSON (带语法高亮)。
* **Extracted Result:** 根据用户配置的 `Response Path` (e.g., `data.balance`),显示最终提取到的值。
* *交互:* 如果提取结果为 `undefined`,高亮提示用户检查 Path 配置。
##### 2.2 主界面实时预览 (Enriched Preview)
在主界面的右侧 JSON 预览区,增加一个 **"Preview Enrichment" (预览增强数据)** 开关。
* **默认状态 (Off):** 仅展示静态映射后的数据API 字段显示为 `null` 或占位符)。
* **开启状态 (On):**
* **限制:** 仅对前 **5 行** 数据生效。
* **加载:** 显示 Loading 骨架屏。
* **并发:** 并发调用 `/api/proxy` (限制并发数为 3)。
* **展示:** 成功获取后JSON 预览中的相关字段会被真实数据填充并高亮显示。
* **警告:** 在开关旁显示小字提示 *"Live preview limited to first 5 rows to prevent API abuse."*
#### 3. 数据流与接口定义 (Data Flow)
##### 3.1 前端代理调用函数
封装一个通用的 `proxyFetch` 工具函数,用于前端组件调用:
```typescript
// src/lib/utils/proxy.ts
interface ProxyOptions {
url: string;
method: string;
headers: Record<string, string>;
body?: any;
}
export async function proxyFetch(options: ProxyOptions): Promise<any> {
// 1. 调用我们自己的 SvelteKit 后端
const response = await fetch('/api/proxy', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(options)
});
if (!response.ok) {
throw new Error(`Proxy Error: ${response.statusText}`);
}
return response.json();
}
```
##### 3.2 变量替换逻辑 (Template Interpolation)
确保前端和后端(Python)使用一致的变量替换逻辑。建议实现一个简单的 `renderTemplate` 函数:
```typescript
/**
* 将 "https://api.com/users/{{id}}" 使用 { id: 123 } 替换为 "https://api.com/users/123"
*/
export function renderTemplate(template: string, context: Record<string, any>): string {
return template.replace(/\{\{\s*(\w+)\s*\}\}/g, (_, key) => {
return context[key] !== undefined ? String(context[key]) : '';
});
}
```
#### 4. 安全性与限流 (Security & Constraints)
为了防止 `/api/proxy` 被滥用或导致服务器卡死,请在服务端 (`src/routes/api/proxy/+server.ts`) 增加以下保护:
1. **超时控制:** 设置 `AbortController`,如果目标接口 10 秒未响应,强制中断并返回 504。
2. **错误屏蔽:** 如果目标接口返回敏感信息(如 Stack Trace后端应进行脱敏处理后再返回给前端。
#### 5. 开发任务清单
1. **工具库:** 实现 `src/lib/utils/proxy.ts``renderTemplate`
2. **组件升级:**
* 改造 `ApiConfigModal`:加入测试按钮和结果展示面板。
* 改造 `JsonPreview`:集成“实时预览”开关和并发请求逻辑。
3. **流程集成:** 确保在导出 `job_bundle.json` 时,不需要改动任何逻辑(导出依然是纯配置)。
---
### 给 AI 的提示 (Prompt Tip)
* **Focus on State:** 提醒 Claude 注意 Svelte 的状态管理。在测试 API 时,不要阻塞主 UI 的渲染。建议使用 `async/await` 配合局部 loading 状态变量。
* **Error Handling:** 强调错误处理。如果用户填的 API URL 是错的(比如 404前端不应该报错崩溃而是应该优雅地在“测试结果”面板里显示红色错误信息。
---
**请先实现 `src/lib/utils/proxy.ts``ApiConfigModal` 的测试功能。**

View File

@@ -0,0 +1,137 @@
**Role:** 资深前端架构师 (Svelte 5 + TypeScript)
**Project Pivot (重大架构调整):**
我们将 "Excel2JSON Mapper" 升级为一个 **"ETL 配置生成器 (ETL Blueprint Generator)"**。
前端的任务是生成一个包含 **[源数据 + 处理逻辑]** 的 **Job Bundle (JSON 文件)**,用户将使用该文件配合 Python 脚本在后端执行实际的数据抓取和入库。
### Phase 2: ETL 配置生成器需求文档
#### 1. 项目概述
这是一个基于 Svelte 5 的单页应用。用户上传 Excel配置字段映射规则包含静态重命名和动态 API 获取规则),最后导出为一个标准化的 JSON 任务包 (`job_bundle.json`)。
#### 2. 用户界面与交互 (UI/UX)
##### 2.1 顶部工具栏
* **导入/导出配置:** 支持保存当前所有的映射规则。
* **导出任务包 (Export Job Bundle):** 這是核心操作。点击后下载 `job_bundle.json` 文件(包含数据+配置)。
* **提交设置 (Submission Settings):** 一个模态框,配置最终数据推送到哪里。
* `Target URL`: 最终数据接收接口 (e.g., `https://api.db.com/bulk-insert`).
* `Method`: POST / PUT.
* `Batch Size`: 批次大小 (默认 50).
##### 2.2 主体区域 (左右分栏)
* **左侧 (Source):** Excel 表格预览。
* **右侧 (Preview):** 静态映射后的 JSON 预览(仅展示前 20 条以保证性能)。
##### 2.3 核心功能:列配置 (Column Configuration)
在左侧表格区域,除了点击现有表头修改映射外,新增 **"添加计算列 (Add Computed Column)"** 功能。
**新增类型:`API_FETCH` (动态 API 字段)**
当用户选择此类型时,弹出一个详细配置面板:
1. **Target Key:** 最终生成的 JSON 字段名 (例如 `user_balance`)。
2. **Request URL (支持模板变量):**
* 允许使用 `{{ColumnName}}` 语法引用当前行的 Excel 数据。
* *示例:* `https://api.example.com/users/{{用户ID}}/detail`
* *UI 交互:* 输入框旁应有“插入变量”按钮,点击列出所有可用 Excel 表头。
3. **Request Method:** 下拉选择 `GET` (默认) 或 `POST`
4. **Headers:** Key-Value 编辑器 (用于传 `Authorization`, `Content-Type` 等)。
5. **Request Body (仅 POST):**
* 多行文本域,支持 JSON 格式。
* 同样支持 `{{ColumnName}}` 模板变量替换。
6. **Response Extractor (取值路径):**
* 指定从接口返回的 JSON 中提取哪个字段。
* 支持 `lodash.get` 风格的点号路径。
* *示例:* 接口返回 `{ "data": { "balance": 100 } }`,用户填 `data.balance`
#### 3. 核心输出Job Bundle 数据结构
请严格按照以下 TypeScript 接口定义生成导出的 JSON 文件:
```typescript
// 1. 静态映射规则
interface StaticRule {
type: 'static';
source: string; // Excel 原表头
target: string; // JSON 目标 Key
dataType: 'string' | 'number' | 'boolean' | 'date';
format?: string; // 日期格式化字符串
}
// 2. 动态 API 获取规则 (本次新增核心)
interface ApiEnrichmentRule {
type: 'api_fetch';
target_key: string; // JSON 目标 Key
url_template: string; // "https://api.com/{{id}}"
method: 'GET' | 'POST';
headers?: Record<string, string>;
body_template?: string; // POST body 模板
response_path: string; // "data.result.value"
fallback_value?: any; // 默认值 (null/0)
}
// 3. 提交配置
interface SubmissionConfig {
target_url: string;
method: 'POST' | 'PUT';
batch_size: number;
}
// 4. 最终导出的 Job Bundle 结构
interface JobBundle {
meta: {
version: string;
generated_at: string;
};
config: {
static_rules: StaticRule[];
enrichment_rules: ApiEnrichmentRule[];
submission: SubmissionConfig;
};
source_data: Record<string, any>[]; // 经过静态映射后的基础数据列表
}
```
#### 4. 开发任务清单
1. **Store 设计:** 更新 Svelte Store 以存储 `enrichmentRules``submissionConfig`
2. **UI 组件:**
* 开发 `ApiConfigModal.svelte`: 用于录入 URL、Headers、Body 等复杂信息。
* 实现变量插入辅助功能 (点击列名自动插入 `{{...}}`)。
3. **导出逻辑:** 编写 `generateJobBundle` 函数。
* **步骤 1:** 根据 `static_rules` 转换 Excel 原始数据,生成基础 JSON 数组。
* **步骤 2:** 将基础数据、API 规则、提交配置组装成 `JobBundle` 格式。
* **步骤 3:** 触发浏览器下载 `job_bundle.json`
#### 5. 特别说明 (给 AI 的提示)
* **No Runtime Fetch:** 前端代码 **不需要** 执行 `fetch` 去调用用户配置的 API避免 CORS。前端只负责把 URL 字符串保存到 JSON 里。
* **Template Validation:** 在 UI 上简单校验 URL 模板格式(检查是否包含 `{}`),但不做逻辑校验。
* **Preview Limitations:** 右侧预览仅展示静态映射的结果。对于 API 字段,可以在预览中显示一个占位符(如 `[Pending API Fetch]`)。
---
### 后续步骤
Claude 完成这个前端代码后,你可以再发一条指令让它写对应的 Python 执行脚本:
> "前端已经完成了。现在请帮我写一个 Python 脚本 (`executor.py`)。它读取上面定义的 `job_bundle.json`,使用 http请求 执行 `enrichment_rules` 里的请求(注意替换 URL 中的 {{变量}}),最后把结果推送到 `submission` 定义的接口。"

View File

@@ -0,0 +1,162 @@
这次更新加入了 **“字典映射 (Dictionary Mapping)”** 功能,允许用户对有限的枚举值进行转换(如“是/否”转“Y/N”
我特别在文档中强调了**“自动扫描”**功能——让 UI 自动读取 Excel 列中的前几十行去重数据,自动列出所有可能的选项,用户只需要填右边的目标值即可,极大提升体验。
---
### 复制下面的内容发送给 Claude
---
**Role:** 资深前端架构师 (Svelte 5 + TypeScript)
**Project Context:**
我们正在开发 "Excel2JSON ETL Blueprint Generator"。
前端负责解析 Excel、配置映射规则含静态重命名、字典转换、动态 API、生成预览并最终导出包含 **[处理后的基础数据 + API 执行逻辑]** 的 `job_bundle.json`
**Current Task:**
我们需要在 **v2.0 (API Enrichment)** 的基础上,新增 **v2.1 (Dictionary/Enum Mapping)** 功能。
### Phase 2.1: 字典映射与高级 ETL 配置需求文档
#### 1. 核心功能变更
在静态字段映射Static Mapping阶段新增 **"值映射 (Value Map)"** 功能。
* **场景:** Excel 中某列是状态词(如 "开/关", "男/女"),目标 JSON 需要代码(如 `1/0`, `M/F`)。
* **逻辑:** 解析 Excel -> **字典替换** -> 类型转换 -> 生成基础 JSON -> (后续由 Python 处理 API).
#### 2. 用户界面与交互 (UI/UX)
##### 2.1 列配置面板升级
点击 Excel 表头配置时,除了修改 `Target Key``Data Type`,新增一个 **"Value Mapping" (值映射)** 开关/折叠面板。
**面板内容:**
1. **自动扫描 (Auto-Scan):**
* UI 自动读取该列的前 50 行数据,提取所有**唯一值 (Unique Values)**。
* 显示一个“映射表”:左侧是 `Source Value` (Excel 原值),右侧是 `Target Value` (输入框)。
2. **手动添加:** 允许用户手动增加新的映射对(防止前 50 行没覆盖到所有情况)。
3. **默认值 (Fallback):**
* 如果单元格的值不在映射表中,怎么处理?
* 选项: `Keep Original` (保留原值) / `Set to Null` / `Custom Value` (自定义默认值)。
##### 2.2 预览逻辑 (Preview Logic)
* 右侧 JSON 预览必须**实时反映**字典映射的结果。
* *示例:* 用户在左侧把 "是" 映射为 `true` (Boolean),右侧预览中原本的 "是" 应立即变为 `true`
#### 3. 核心数据结构 (Updated Interfaces)
请更新 TypeScript 接口以支持新的映射逻辑:
```typescript
// 字典映射项
interface ValueMapItem {
source: string | number; // Excel 里的原始值 (e.g., "是")
target: any; // JSON 里的目标值 (e.g., true, "Y", 1)
}
// 静态映射规则 (升级版)
interface StaticRule {
type: 'static';
source_column: string; // Excel 原表头
target_key: string; // JSON 目标 Key
data_type: 'string' | 'number' | 'boolean' | 'date' | 'array'; // 目标类型
// v2.1 新增: 字典映射配置
use_dictionary: boolean; // 是否启用字典映射
value_mapping?: ValueMapItem[];
mapping_fallback?: 'keep' | 'null' | any; // 没匹配到时的默认值
// v2.0 已有
format?: string; // 日期格式
separator?: string; // 数组分隔符
}
// 动态 API 规则 (保持 v2.0 不变)
interface ApiEnrichmentRule {
type: 'api_fetch';
target_key: string;
url_template: string; // "https://api.com/{{id}}"
method: 'GET' | 'POST';
headers?: Record<string, string>;
body_template?: string;
response_path: string; // "data.result"
}
// 提交配置 (保持 v2.0 不变)
interface SubmissionConfig {
target_url: string;
method: 'POST' | 'PUT';
batch_size: number;
}
// 最终导出的 Job Bundle
interface JobBundle {
meta: { version: string; generated_at: string };
config: {
// static_rules 仅用于前端回显Python 脚本其实只需要 enrichment 和 submission
// 但为了以后能在前端重新导入编辑,建议保留完整配置
static_rules: StaticRule[];
enrichment_rules: ApiEnrichmentRule[];
submission: SubmissionConfig;
};
// 注意: source_data 是前端已经应用了 "StaticRule" (包括字典映射) 后的干净数据
source_data: Record<string, any>[];
}
```
#### 4. 处理流程 (Processing Pipeline)
前端在生成 `source_data` 时,必须严格按照以下顺序处理每一单元格:
1. **Extract:** 读取 Excel 单元格原始值。
2. **Map (字典映射):**
* 如果启用了 `use_dictionary`:查找映射表。
* 找到 -> 替换为 Target Value。
* 没找到 -> 应用 `mapping_fallback` 策略。
3. **Cast (类型转换):**
* 将上一步的结果转换为 `data_type` 指定的类型 (e.g., String -> Boolean, String -> Number)。
* *注意:* 如果字典映射的目标值已经是正确的类型(如 `true`),则跳过此步或确保不会再次转为字符串 "true"。
4. **Format:** (如果是日期或数组) 应用格式化规则。
#### 5. 开发任务清单
1. **组件开发:**
* 修改 `ColumnConfigPanel.svelte` (或类似组件)。
* 新增 `DictionaryMapper` 子组件:包含“自动扫描”按钮和“键值对”编辑表格。
2. **逻辑核心:**
* 更新 `processRow` 函数,在类型转换前插入字典查找逻辑。
* 实现 `scanUniqueValues(columnData)` 函数,用于快速提取 Excel 列的去重值。
3. **预览同步:** 确保右侧 JSON 预览能实时响应字典配置的变更。
4. **导出验证:** 导出 `job_bundle.json`,检查 `source_data` 中的值是否已成功转换为映射后的值(例如 "Y" 而不是 "是")。
---
### 给 AI 的提示 (Prompt Tip)
* **性能注意:** 自动扫描 `scanUniqueValues` 时,如果 Excel 数据量极大(>10万行不要全量扫描。只扫描前 1000 行即可,并提示用户“仅扫描了前 1000 行,如有遗漏请手动添加”。
* **交互细节:** 字典映射的 Target Value 输入框,应该能智能识别类型。如果用户输入 `true`,应该被识别为 Boolean 而不是字符串 "true"。
---
### 执行步骤
请先基于上述文档,更新 **数据类型定义 (Interfaces)****核心处理逻辑 (`processRow` 函数)**

145
demands/DEMAND-样式.md Normal file
View File

@@ -0,0 +1,145 @@
**Role:** 资深 UI/UX 工程师 & Svelte 专家
**Current Context:**
我们已经完成了 "Excel2JSON ETL Blueprint Generator" 的核心功能Excel 解析、API 配置、JSON 导出)。
目前的界面比较原始。现在需要进行 **Phase 3: UI/UX Overhaul & Theming**
**Goal:**
全面优化应用样式,引入 **Dark Mode (夜间模式)** 支持,提升视觉层级和交互体验。目标风格是 **"Modern SaaS"** (类似 Vercel/Linear/Shadcn 的风格)。
### Phase 3: UI/UX 优化与多主题需求文档
#### 1. 技术方案 (Technical Approach)
* **Tailwind CSS Dark Mode:** 使用 `class` 策略(通过在 `<html>` 标签添加 `class="dark"` 来切换)。
* **State Management:** 创建一个 `themeStore.ts` (Svelte Store),用于管理 `light` | `dark` | `system` 状态,并持久化到 `localStorage`
* **CSS Variables:** 建议在 `app.css` 中定义语义化的 CSS 变量 (如 `--bg-primary`, `--text-secondary`),或者直接使用 Tailwind 的 `slate` 色系作为主轴。
#### 2. 设计规范 (Design System Specs)
请严格遵循以下配色逻辑,确保深色模式下的对比度和可读性。
##### 2.1 基础色盘 (Color Palette)
* **Primary Brand:** Indigo-600 (Light) / Indigo-500 (Dark)
* **Background (Canvas):**
* Light: `bg-white` (Main), `bg-slate-50` (Sidebar/Header)
* Dark: `bg-slate-950` (Main), `bg-slate-900` (Sidebar/Header)
* **Surface (Cards/Modals):**
* Light: `bg-white` + `shadow-sm` + `border-slate-200`
* Dark: `bg-slate-900` + `shadow-none` + `border-slate-800`
* **Text (Typography):**
* Primary: `text-slate-900` (Light) / `text-slate-50` (Dark)
* Secondary: `text-slate-500` (Light) / `text-slate-400` (Dark)
* Muted: `text-slate-400` (Light) / `text-slate-500` (Dark)
* **Borders:** `border-slate-200` (Light) / `border-slate-800` (Dark)
##### 2.2 交互反馈 (Interactive States)
* **Buttons:**
* Primary: Solid Indigo background. Hover: `hover:bg-indigo-700` (Light) / `hover:bg-indigo-400` (Dark).
* Ghost/Secondary: Transparent background. Hover: `hover:bg-slate-100` (Light) / `hover:bg-slate-800` (Dark).
* **Inputs:**
* Default: `bg-transparent border border-slate-300 dark:border-slate-700`.
* Focus: `ring-2 ring-indigo-500/20 border-indigo-500`.
#### 3. 组件级优化详情
##### 3.1 顶部导航栏 (Header)
* **布局:** Flexbox高度 `h-14` or `h-16`
* **功能区:**
* 左侧: Logo + Title (Bold, Tracking-tight)。
* 右侧: [Export Button] [Settings Icon] [Theme Toggle]。
* **Theme Toggle:** 实现一个图标按钮,点击在 🌞 (Sun) / 🌙 (Moon) / 💻 (System) 之间切换。切换时添加平滑的 `transition-colors` 动画。
##### 3.2 Excel 表格区域 (Left Panel)
* **容器:** 卡片式设计,圆角 `rounded-lg`,带边框。
* **表头 (Thead):**
* Light: `bg-slate-50`
* Dark: `bg-slate-900`
* 文字: `text-xs font-semibold uppercase tracking-wider text-slate-500`.
* **单元格 (Td):**
* 必须有边框:`border-r border-b border-slate-200 dark:border-slate-800`
* 斑马纹 (Zebra Striping): 偶数行在 Dark mode 下给予微弱的背景色 `dark:even:bg-slate-900/50` 增加可读性。
* **列配置按钮:** 表头上的“设置图标”在 Hover 时才显示,保持界面整洁。
##### 3.3 JSON 预览区域 (Right Panel)
* **容器:** 模拟 IDE/终端外观。
* **背景:**
* Light: `bg-slate-50` (或者纯白)
* Dark: `bg-[#0d1117]` (GitHub Dark Dimmed 风格) 或 `bg-slate-950`.
* **代码高亮:**
* **关键点:** 语法高亮需要根据主题动态切换。
* 如果没有引入重的 highlighter 库,请手动为 Key/String/Number/Boolean 定义两套颜色。
* *Example:* Keys (Blue-600/Blue-400), Strings (Green-600/Green-400), Numbers (Orange-600/Orange-400).
* **Copy 按钮:** 悬浮在右上角的绝对定位按钮,点击后显示 "Copied!" 提示。
##### 3.4 模态框 (Modals - API & Dictionary Config)
* **背景遮罩 (Backdrop):** `bg-black/50` (Light) / `bg-black/80` (Dark) with `backdrop-blur-sm`.
* **弹窗本体:** `bg-white dark:bg-slate-900`,边框 `dark:border-slate-700`
* **表单元素:** 输入框在 Dark Mode 下背景应为 `bg-slate-950` 或深灰色,避免过亮。
##### 3.5 滚动条 (Scrollbars)
* 请自定义 Webkit 滚动条样式,使其不再是默认的丑陋灰色条。
* Track: Transparent.
* Thumb: `bg-slate-300 dark:bg-slate-700`,圆角 `rounded-full`
#### 4. 开发任务清单 (Action Plan)
1. **基础建设:**
*`app.css` 中配置 Tailwind 的 `@apply` 基础样式。
* 实现 `themeStore.ts` 并处理 `onMount` 时的系统偏好检测。
*`App.svelte` 根节点绑定 `class:dark={$themeStore === 'dark'}`
2. **组件重构:**
* 重写 `Header.svelte`,加入主题切换器。
* 重构 `ExcelTable.svelte` 的 class全面加入 `dark:` 修饰符。
* 重构 `JsonPreview.svelte`,优化配色和字体 (使用 Monospace 字体)。
* 优化 `Modal``Drawer` 组件的阴影和边框。
3. **细节打磨:**
* 为所有可点击元素添加 `transition-all duration-200`
* 确保 Loading 状态(骨架屏或 Spinner在深色模式下不可见度正常。
---
### 给 AI 的提示 (Prompt Tip)
* **Syntax Highlighting:** 告诉 Claude如果目前的 JSON 预览只是纯文本 `pre` 标签,请帮我写一个简单的 `syntaxHighlight(json)` 函数,通过正则把 HTML 标签包进去,并用 Tailwind 的颜色类(如 `text-blue-600 dark:text-blue-400`)来控制颜色,从而实现轻量级的双模式高亮。
---
### 你可以期待的效果
有了这份文档Claude 会帮你把界面做得像 **VS Code****GitHub** 一样专业。
左边是清爽的表格,右边是极客风的代码预览,切换开关时,整个页面会平滑过渡(如果不做 transition 就是瞬间切换,做了就是渐变,建议做 transition

126
demands/DEMAND.md Normal file
View File

@@ -0,0 +1,126 @@
项目需求文档 (PRD): Excel 转 JSON 可视化映射工具
1. 项目概述
我们需要开发一个基于 Svelte 的单页应用。该应用允许用户上传 Excel 文件,在左侧预览数据,在右侧实时预览转换后的 JSON 数据。核心功能是用户可以自定义“Excel列”到“JSON字段”的映射规则、处理空值逻辑以及格式化特定数据类型如日期并支持将这些配置导出为模板以便下次复用。
2. 技术栈要求
框架: Svelte (推荐使用 Svelte 5 或 SvelteKit) + TypeScript
样式: TailwindCSS (用于快速构建左右分栏布局)
Excel 处理: xlsx (SheetJS) 或类似的轻量级库
图标库: Lucide-svelte (可选)
3. 界面布局 (UI Layout)
页面主要分为 顶部工具栏 和 主体内容区。
顶部工具栏 (Header):
文件上传按钮 (支持拖拽上传 Excel)。
模板操作区:[导入配置模板]、[导出当前配置]。
全局操作:[下载 JSON]、[复制 JSON]。
主体内容区 (Main Split View):
左侧 (Source Panel - 50%): 显示 Excel 解析后的表格数据。
关键交互: 表头应包含“设置”功能。用户点击表头或表头旁边的图标,可以弹出/展开该列的映射配置面板。
右侧 (Target Panel - 50%): 显示转换后的 JSON 代码预览(支持语法高亮)。
4. 核心功能细节
4.1 Excel 导入与展示
支持 .xlsx, .xls, .csv 格式。
读取 Excel 的第一行作为默认表头Key
数据以表格形式展示在左侧。
4.2 字段映射配置 (Mapping Logic)
这是本应用的核心。每一列都需要一个配置对象,包含以下属性:
Original Header (源字段): Excel 原始表头名称 (只读)。
Target Key (目标字段): 映射到 JSON 中的 Key 名称 (用户可修改)。
示例: Excel 中是 "姓名",用户输入 "userName",生成的 JSON 为 {"userName": "..."}。
Data Type (数据类型):
String (默认)
Number
Boolean
Date
Format Rules (格式化规则 - 仅针对特定类型):
如果是 Date 类型,提供格式化选项 (如 YYYY-MM-DD, YYYY/MM/DD HH:mm, Unix Timestamp)。需要引入 dayjs 或类似库处理。
Null Handling (空值处理):
开关选项Exclude if Empty (如果该单元格为空,则在生成的 JSON 对象中完全移除该 Key)。
默认值:如果未勾选“移除”,可设置一个默认值 (Default Value)。
4.3 JSON 实时预览
当用户修改映射配置(如修改 Key 名称、切换日期格式、改变空值策略)时,右侧的 JSON 预览应 实时 (Reactive) 更新。
4.4 模板系统 (Configuration Persistence)
导出模板: 将当前的映射规则数组导出为 .json 文件。
数据结构示例:
JSON
[
{ "source": "A", "target": "AAA", "type": "string", "excludeIfEmpty": false },
{ "source": "入职日期", "target": "joinDate", "type": "date", "format": "YYYY-MM-DD" }
]
导入模板: 上传上述格式的 JSON 文件,应用自动匹配当前 Excel 的表头。如果 Excel 包含模板中定义的 source 字段,则自动应用对应的规则。
5. 交互流程 (User Story)
用户打开页面,拖入 staff_data.xlsx。
左侧显示表格。用户发现“出生日期”这一列解析出来是数字Excel 时间戳)。
用户点击“出生日期”列的设置,将类型改为 Date格式选择 YYYY-MM-DD。
用户发现有一列“备注”很多是空的,点击设置,勾选 Exclude if Empty。
用户将“姓名”列的 Target Key 改为 full_name。
右侧 JSON 实时变成了期望的格式。
用户点击“导出配置”,保存为 staff_mapping.json。
下周,用户上传新的 Excel并点击“导入配置”选择 staff_mapping.json所有规则自动应用直接复制右侧 JSON。
请执行以下任务:
数据结构设计: 定义 MappingConfig 和 RowData 的 TypeScript 接口。
核心逻辑实现: 编写一个 convertData 函数,根据映射配置将 Excel 原始数据转换为最终 JSON。
组件编写:
App.svelte: 主布局和状态管理。
ExcelTable.svelte: 左侧表格,包含列头配置 UI。
JsonPreview.svelte: 右侧展示。
请确保代码不仅能运行,而且具有良好的错误处理(例如文件解析失败)。
支持嵌套对象: 如果 Target Key 包含点号(例如 user.address.city生成的 JSON 应当自动构建对应的嵌套对象结构,而不是生成一个带点的字符串键名。