Skip to content

Document-to-Form Implementation Plan ​

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 把 Word/Excel/图片/PDF 首页变成可确认的表单草案,并可选用现有 AI 助理补校验和选项。

Architecture: 解析仍在客户端。Word/Excel 复用 wordParser / excelParser。图片和 PDF 抽文本或缩略图后走 config.ai。所有来源先产出 IngestDraft(字段数组),确认页再 setRule。不在解析失败时直接覆盖画布。

Tech Stack: 现有 ImportDialog、mammoth/xlsx、config.ai、可选 pdfjs(按需 CDN,与 echarts 同一模式)。

Depends on: 现有 AI 面板;不强制 shared foundation,但确认后应 getSnapshot() 正常。


File map ​

  • Create: designer3.0/src/modules/ingest/types.js
  • Create: designer3.0/src/modules/ingest/draftFromRules.js
  • Create: designer3.0/src/modules/ingest/imagePrompt.js
  • Create: designer3.0/src/modules/ingest/polishPrompt.js
  • Create: designer3.0/tests/modules/ingest/draft.spec.js
  • Create: designer3.0/src/designer/ingest/IngestConfirm.vue
  • Modify: designer3.0/src/designer/ImportDialog.vue
  • Modify: designer3.0/src/locale/zh-cn.js / en.js / jp.js
  • Modify: fc-design-pro/src/help/interface/toolbar.md(导入一节)

Task 1: IngestDraft 模型 ​

Files:

  • Create: designer3.0/src/modules/ingest/types.js

  • Create: designer3.0/src/modules/ingest/draftFromRules.js

  • Create: designer3.0/tests/modules/ingest/draft.spec.js

  • [ ] Step 1: 写失败测试

js
import { describe, it, expect } from 'vitest';
import { rulesToDraft, draftToRules } from '../../../src/modules/ingest/draftFromRules.js';

describe('draft roundtrip', () => {
    it('keeps field title type required', () => {
        const rules = [
            { type: 'input', field: 'mobile', title: '手机号', $required: true, _fc_drag_tag: 'input' },
        ];
        const draft = rulesToDraft(rules);
        expect(draft.fields[0]).toMatchObject({ field: 'mobile', title: '手机号', type: 'input', required: true });
        const back = draftToRules(draft);
        expect(back[0].field).toBe('mobile');
        expect(back[0].title).toBe('手机号');
    });
});

$required 以设计器真实必填存储为准(可能是 validate: [{required:true}])。实现必须读真实结构,测试跟着改。

  • [ ] Step 2: 实现

IngestDraft 固定为:

js
export function createEmptyDraft(source) {
    return { source, fields: [] };
}

// field: { field, title, type, required, options }

draftToRules 只生成白名单类型:input textarea number select radio checkbox date switch。未知 type 降级为 input。

  • [ ] Step 3: 跑测试并提交
bash
pnpm test tests/modules/ingest/draft.spec.js

Expected: PASS

bash
git add src/modules/ingest tests/modules/ingest
git commit -m "feat: add ingest draft model"

Task 2: AI 提示词(图片 / 润色) ​

Files:

  • Create: designer3.0/src/modules/ingest/imagePrompt.js

  • Create: designer3.0/src/modules/ingest/polishPrompt.js

  • Modify: designer3.0/tests/modules/ingest/draft.spec.js

  • [ ] Step 1: 写失败测试

js
import { buildImageToFormMessages } from '../../../src/modules/ingest/imagePrompt.js';
import { buildPolishMessages } from '../../../src/modules/ingest/polishPrompt.js';

it('asks AI to return JSON draft only', () => {
    const msgs = buildImageToFormMessages({ imageDataUrl: 'data:image/png;base64,xx' });
    expect(msgs[0].role).toBe('system');
    expect(msgs[0].content).toContain('IngestDraft');
    expect(JSON.stringify(msgs)).toContain('data:image/png;base64,xx');
});

it('sends current draft for polish', () => {
    const msgs = buildPolishMessages({ fields: [{ field: 'mobile', title: '手机', type: 'input', required: false }] });
    expect(msgs[1].content).toContain('mobile');
    expect(msgs[0].content).toContain('validate');
});
  • [ ] Step 2: 实现提示词

系统提示必须要求:

  • 只返回 JSON:{"source":"image","fields":[...]}
  • fields 的 type 只能是白名单
  • 手机/邮箱要标 required 并在 validateHint 里写 mobile / email
  • 不要解释性文字

图片消息用 OpenAI vision 兼容格式(image_url)。若客户模型不支持视觉,imagePrompt.js 同时导出 buildOcrTextToFormMessages(text) 作为降级。

  • [ ] Step 3: 解析 AI 输出

在 draftFromRules.js 增加:

js
export function parseDraftResponse(text) {
    const json = String(text).replace(/^```json\s*|\s*```$/g, '').trim();
    const data = JSON.parse(json);
    if (!Array.isArray(data.fields)) {
        throw new Error('invalid ingest draft');
    }
    return data;
}

补测试:输入带 markdown 围栏的字符串,解析出 fields。

  • [ ] Step 4: 跑测试并提交
bash
pnpm test tests/modules/ingest/draft.spec.js

Expected: PASS

bash
git add src/modules/ingest tests/modules/ingest
git commit -m "feat: add ingest AI prompts and draft parser"

Task 3: 改造 ImportDialog ​

Files:

  • Create: designer3.0/src/designer/ingest/IngestConfirm.vue

  • Modify: designer3.0/src/designer/ImportDialog.vue

  • [ ] Step 1: 扩大 acceptTypes

js
acceptTypes: '.docx,.csv,.tsv,.xls,.xlsx,.xlsm,.xlsb,.json,.png,.jpg,.jpeg,.pdf',

processSelectedFile 增加:

  • 图片:FileReader.readAsDataURL → 调 config.ai(与 AiPanel 同一 api/token)→ parseDraftResponse → 打开确认页。

  • PDF:第一页用 pdf.js 渲染到 canvas 再当图片。pdf.js 按 开发环境与依赖说明.md 的 CDN 按需加载;失败则提示「请上传图片或 Word」。

  • Word/Excel:解析出 rule 后先 rulesToDraft,确认页可勾选「AI 润色」。

  • [ ] Step 2: IngestConfirm

表格列:标题、字段、类型(可改)、必填。底部:取消、导入、AI 润色。导入调用 draftToRules 再 setRule。取消不改画布。

  • [ ] Step 3: 无 AI 时的行为

图片/PDF:提示 t('ingest.aiRequired'),不崩溃。Word/Excel:仍可直接确认导入(现有能力不能回退)。

  • [ ] Step 4: 文案

zh-cn.js 增加 ingest.aiRequired、ingest.confirm、ingest.polish、ingest.invalidFileType(扩展原 invalidFileType 或新 key)。en/jp 同步。

  • [ ] Step 5: 手动验收
bash
pnpm run dev
  1. 导入现有请假 Excel,确认页出现字段,导入后画布有字段。
  2. 上传一张打印申请表照片(有 AI token 时),确认页至少 3 个字段。
  3. 关掉网络再导 Word,仍能导入。
  • [ ] Step 6: Commit
bash
git add src/designer/ImportDialog.vue src/designer/ingest src/locale
git commit -m "feat: confirm-page ingest for docs images and spreadsheets"