PPT data review: 3-layer structure — summary bar with trust indicator
and key metrics, sorted issues checklist, collapsible detail sections.
Error state disables primary action with explanation.
Poster template: left-right layout with size selection moved upfront,
template grid with scene tags and preview, AI style presets, compliance
notice for AI copy, reference image moved to advanced settings.
PPT result: product summary chips, pre-download checklist, delivery
confirmation feel instead of bare download page.
Poster preview: fix duplicate size options, add polling timeout (3 min),
show delivery metadata (size, generation mode) on success.
PosterPage: pass size from template step to preview step, widen to 1180px.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Fix _call_provider to support custom providers (OpenAI-compatible
fallback) instead of raising ValueError for unknown providers
- Add POST /admin/ppt/sync-models endpoint that fetches available
models from the configured provider's API
- Redesign PptSettingsAdmin UI: replace Dify model dropdown with
per-provider 'sync models' button + searchable model selector
- Remove dead Dify-specific code (fetchDifyModels, applyDifyModel)
- Update deepseek default model from deepseek-chat to deepseek-v4-pro
- API Key field now always shown (not conditional on non-dify)
Add a mandatory data verification step so users can inspect and edit
LLM-extracted data before generating the PPT.
- New PptDataReview.vue: auto-validation on mount, key metrics cards,
editable benefit/withdrawal tables, inline error highlighting
- New PUT /session/<id>/extractions API endpoint for saving user edits
- Extend PptPage flow from 4 steps to 5 (upload→parse→review→generate→result)
- Update ppt-api.ts with updateExtractions() method
- Update PptParsing button text to match new flow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rewrite fast_pptx_renderer.py to read requiredPageTypes from template
config instead of hardcoding 5 slides. Add 10 slide builder functions
(cover, company, narrative, chart, timeline, table, compare, synergy,
conclusion, closing) with python-pptx native charts.
Key changes:
- Renderer reads templateConfig.requiredPageTypes and slidesConfig
from DeckContract to determine slide sequence and per-slide metadata
- routes.py loads PptTemplate and PptCompany from DB, normalizes all
PDF extractions (not just the first), passes full context to renderer
- renderer.py injects templateConfig, company info, and multi-product
data into DeckContract
- Add slides_config_json column to PptTemplate (migrate_017) for
per-slide title/narrative/chartType configuration via admin UI
- Admin template editor now supports drag-reorder slides, per-slide
title/narrative hint, chart/table type selection
- Add requiredPageTypes to savings/ink, savings/minimal, savings/business
templates (were missing, causing fallback to defaults)
- Fix IUL normalizer: add payYears and totalPremium to policy dict
- Fix CI/IUL normalizer: add totalSurrenderValue alias to benefitRows
so charts render correctly for all product types
- Port calculation functions from baodanppt: decade_rows, paid_premium,
simple_return, compound_return, find_payback_year
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a model is selected from Dify, set provider='dify' and call
through Dify Chat API (/v1/chat-messages) using the existing
DIFY_CHAT_APP_API_KEY. No separate API key configuration needed.
- Frontend: hide API Key/Base URL fields when provider is 'dify',
show 'via Dify, no API key needed' tag
- Backend: add _call_dify() to route through Dify Chat API
- Backend: _try_load_db_config supports dify provider without api_key
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Expand poster image model settings with provider, model name, API key,
and base URL fields (was only model name + API key)
- Add presets for OpenAI (gpt-image-1), Doubao (火山引擎), and Zhipu (CogView)
- Refactor image_generator.py to read config from system_settings DB instead
of hardcoding gpt-image-1 and OPENAI_API_KEY env var
- All OpenAI-compatible image APIs work via configurable base URL
- Add doubao and cogview to brand name mapping
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The axios interceptor already returns response.data, so accessing
res.data.data was one level too deep, causing the models list to
always be empty.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace hardcoded server IP 150.5.135.143 with localhost in
openDifyAdmin() to match local development environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace API-based model fetching with direct SQL query on
provider_models table (shared PostgreSQL, no auth needed)
- Frontend: auto-detect base_url from model name when selecting
a Dify model, set provider to 'custom'
- Remove unused requests import and API key fallback logic
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Backend: try DIFY_CHAT/WORKFLOW_API_KEY when workspace key is missing
- Frontend: always show '从 Dify 获取' button, not just after first fetch
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- PptSettingsAdmin.vue: full settings page with provider/model/API key
config for PPT extraction, poster copy, and poster image generation
- Backend: GET /insurance/admin/ppt/available-models to fetch models
from Dify API (falls back to builtin list when unavailable)
- LLM client: read model config from SystemSetting DB with 60s cache,
priority: database > environment variables > defaults
- ppt-admin-api.ts: add getAvailableModels() method
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- generate_ppt and validate_extraction now accept status 'cached'
alongside 'success', matching the frontend's hasSuccess logic
- PptParsing: show extraction error messages in the results table
- PptParsing: show '解析失败' icon when all extractions fail
- PptParsing: only show '下一步' button when at least one extraction succeeded
- routes.py: add error logging with stack trace in parse endpoint
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
progressStatus was referenced in the template but never defined,
causing a Vue runtime warning on every render.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>