baodan/frontend/src/utils/ppt-api.ts
wsb1224 25c6f2a3b7 阶段 3 剩余:编辑与版本化
功能	文件	说明
幻灯片显隐	routes.py, PptResult.vue, ppt-api.ts	每页可点击隐藏/恢复,隐藏页在缩略图中半透明显示,页码标注隐藏数量
DeckContract 快照	renderer.py, celery_tasks.py, ppt_session.py	生成时保存完整 deck JSON 到文件系统,供版本化回溯
版本化生成	celery_tasks.py, task_service.py, routes.py	POST /preview/:id/regenerate → 递增版本号 → 用 deck 重新渲染 → 追加到版本历史,不覆盖旧版
版本历史 UI	PptResult.vue	右栏显示版本列表(版本号/页数/时间),当前版本高亮标记
数据库迁移	migrate_025.py	新增 deck_contract_path、versions_json 字段
阶段 4:UI 重构
功能	文件	说明
保险绿主题	PptPage.vue, PptGenerate.vue, PptResult.vue, PptSlideCanvas.vue	主色从 #2563eb 蓝改为 #3B7A57 保险绿,背景暖灰 #f0f7f3
生成决策展示	PptGenerate.vue	新增"系统决策"区域,展示检测场景、选用模板、计划书数量、险种类型、保司
骨架屏加载	PptResult.vue	preview_status=none/generating 时显示骨架屏 + 加载动画,不再显示静态 fallback
新增后端接口(本轮)
方法	路径	功能
POST	/ppt/preview/:id/regenerate	基于编辑内容生成新版本
PUT	/ppt/preview/:id/slide/:index	增加 hidden 字段支持
新增 Celery 任务
任务名	说明
insurance.regenerate_ppt	读取 DeckContract → 应用编辑 → 重新渲染 → 保存新版本
2026-07-29 21:41:28 +08:00

221 lines
5.3 KiB
TypeScript

/**
* PPT 生成模块 API 封装
*/
import api from './api'
export interface PptSession {
id: string
user_id: string
status: string
files: Array<{ path: string; name: string; type: string }>
extractions: Array<{
pdfName: string
planType: string
status: string
productName: string
data: any
error?: string
yearCount: number
}>
chatHistory: Array<{ role: string; content: string }>
ppt_path?: string
slide_count?: number
preview_status?: 'none' | 'generating' | 'ready' | 'failed'
slides_json_path?: string
quality_report?: QualityReport
created_at: string
}
export interface SlideShape {
id: string
type: 'textbox' | 'rect' | 'image' | 'table' | 'group'
x: number
y: number
w: number
h: number
fill?: string
lineColor?: string
lineWidth?: number
paragraphs?: SlideParagraph[]
rows?: Array<Array<{ text: string; bold: boolean; fontSize: number }>>
children?: SlideShape[]
}
export interface SlideParagraph {
text: string
fontSize: number
bold: boolean
color: string
align: 'left' | 'center' | 'right' | 'justify'
}
export interface SlideData {
index: number
background: string
shapes: SlideShape[]
hidden?: boolean
}
export interface SlidesJson {
width: number
height: number
slideCount: number
slides: SlideData[]
}
export interface QualityCheckItem {
key: string
status: 'pass' | 'fail' | 'warn'
message: string
page: number | null
}
export interface QualityManualItem {
key: string
confirmed: boolean
message: string
}
export interface QualityReport {
auto: QualityCheckItem[]
manual: QualityManualItem[]
summary: { pass: number; fail: number; warn: number; manualPending: number }
}
export interface ExtractionResult {
sessionId: string
status: string
extractions: Array<{
pdfName: string
planType: string
status: string
productName: string
yearCount: number
error?: string
}>
message: string
}
export interface GenerateResult {
sessionId: string
status: string
downloadUrl?: string
slideCount: number
}
export const pptApi = {
/** 上传 PDF 文件 */
upload(formData: FormData) {
return api.post('/ppt/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
})
},
/** 触发 AI 解析 */
parse(sessionId: string) {
return api.post(`/ppt/parse/${sessionId}`)
},
/** 获取 AI 解析进度 */
getParseStatus(sessionId: string) {
return api.get(`/ppt/parse/${sessionId}/status`)
},
/** 获取会话状态 */
getSession(sessionId: string) {
return api.get(`/ppt/session/${sessionId}`)
},
/** AI 对话 */
chat(sessionId: string, message: string) {
return api.post(`/ppt/chat/${sessionId}`, { message })
},
/** 生成 PPT */
generate(sessionId: string, params: {
theme?: string
templateId?: string
companyId?: string
style?: string
useMaskedData?: boolean
}) {
return api.post(`/ppt/generate/${sessionId}`, params)
},
/** 验证提取数据 */
validate(sessionId: string) {
return api.get(`/ppt/validate/${sessionId}`)
},
/** 保存用户修改后的提取数据 */
updateExtractions(sessionId: string, extractions: any[]) {
return api.put(`/ppt/session/${sessionId}/extractions`, { extractions })
},
/** 获取渲染选项 */
getRenderOptions() {
return api.get('/ppt/render-options')
},
/** 匹配公司知识库 */
matchCompany(params: { productName?: string; companyHint?: string; companyId?: string }) {
return api.post('/ppt/company-kb/match', params)
},
/** 获取下载链接 */
getDownloadUrl(sessionId: string) {
return `/insurance/ppt/download/${sessionId}`
},
/** 下载 PPT 文件(带认证) */
async downloadPpt(sessionId: string): Promise<Blob> {
const response = await api.get(`/ppt/download/${sessionId}`, {
responseType: 'blob',
})
return response.data
},
/** 获取历史记录列表 */
getHistory(params?: { page?: number; page_size?: number; company_id?: string; action_type?: string }) {
return api.get('/ppt/history', { params })
},
/** 获取历史详情 */
getHistoryDetail(id: number) {
return api.get(`/ppt/history/${id}`)
},
/** 重新下载历史文件 */
async reDownloadHistory(id: number): Promise<Blob> {
const response = await api.get(`/ppt/history/${id}/re-download`, {
responseType: 'blob',
})
return response.data
},
/** 获取幻灯片预览数据(结构化 JSON + 质量报告) */
getPreview(sessionId: string) {
return api.get(`/ppt/preview/${sessionId}`)
},
/** 更新指定页的编辑内容 */
updateSlideEdit(sessionId: string, slideIndex: number, shapes: any[]) {
return api.put(`/ppt/preview/${sessionId}/slide/${slideIndex}`, { shapes })
},
/** 更新幻灯片显隐状态 */
updateSlideHidden(sessionId: string, slideIndex: number, hidden: boolean) {
return api.put(`/ppt/preview/${sessionId}/slide/${slideIndex}`, { hidden })
},
/** 更新人工质量确认项 */
updateQualityConfirm(sessionId: string, key: string, confirmed: boolean) {
return api.put(`/ppt/preview/${sessionId}/quality-confirm`, { key, confirmed })
},
/** 基于当前编辑内容重新生成新版本 */
regenerateVersion(sessionId: string) {
return api.post(`/ppt/preview/${sessionId}/regenerate`)
},
}