Commit Graph

40 Commits

Author SHA1 Message Date
hailin f13ebe97be fix: add customImageUrl to wordcloud config type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:48:51 -07:00
hailin 579ed2d174 feat: custom image mask for wordcloud shape
- Select '自定义图片' from shape dropdown
- Upload any silhouette image (black=words, white=empty)
- Image preview with delete button
- maskImage passed to echarts-wordcloud with keepAspect

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:47:39 -07:00
hailin fa8e2714ca fix: use conditional require for echarts-wordcloud instead of dynamic import
Dynamic import was async and wordcloud plugin wasn't loaded before
setOption was called. Now uses synchronous require() guarded by
typeof window check to avoid SSR crash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:43:05 -07:00
hailin a359965bff fix: dynamic import echarts-wordcloud to avoid SSR window crash
echarts-wordcloud accesses window at import time, causing 500 error
during server-side rendering. Moved to dynamic import() inside
useEffect which only runs on the client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:38:57 -07:00
hailin 2d5dfae835 fix: wordcloud auto-fit all words with shrinkToFit
- shrinkToFit: true — auto-shrink words that don't fit
- width/height: 95% — use nearly full container
- keepAspect: false — let shape stretch to fill container
- Combined with ellipse mask radii, all words should now display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:35:02 -07:00
hailin f8ef83506a fix: stretch wordcloud shapes to fill container using ellipse radii
Changed from square min(w,h) radius to separate rx/ry that use
the full width and height of the container. Shapes now fill the
entire chart area instead of being constrained to a small square.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:33:16 -07:00
hailin e7d7745f74 fix: use 1024x700 mask canvas for better shape coverage
Previous 512x512 square mask was too small, causing most words to
be excluded. Now uses 1024x700 (16:11 ratio) to match typical chart
containers, with r=48% fill for maximum word area.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:28:10 -07:00
hailin 8fb5caef07 fix: enlarge cardioid (heart) shape mask for better visibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:21:59 -07:00
hailin 1a0abaa453 feat: wordcloud shapes via canvas maskImage
Shape presets (circle/heart/diamond/triangle/star/pentagon) now
render correctly using dynamically generated canvas mask images.
Added rectangle option. Mask images are cached for performance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:19:37 -07:00
hailin e515aed960 fix: preserve wordcloud config in EChartsOptionBuilder ensureStyle
Same bug as chartSlice - the builder's ensureStyle was stripping
custom properties like wordcloud. Now preserves all non-standard keys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 21:10:00 -07:00
hailin b124bae83c fix: import echarts-wordcloud plugin in EChartsBase
Without this import, the wordCloud series type is not registered
with echarts, causing wordcloud charts to render blank.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:29:56 -07:00
hailin 3bb6dc85c0 fix: preserve custom style extensions (wordcloud config) in ensureStyle
ensureStyle() was stripping unknown properties like 'wordcloud'.
Now collects and preserves all non-standard style keys so chart-type
specific configs survive Redux state updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:13:00 -07:00
hailin 026fe11dff feat: complete wordcloud chart with config panel
- WordcloudOptionBuilder: shape, font size range, rotation range,
  grid size, font family/weight, 3 color modes (palette/random/gradient)
- WordcloudConfig panel: full UI for all wordcloud settings
- StyleConfig: conditionally shows wordcloud/axis/legend panels
  based on chart type (wordcloud hides axes, KPI hides legend, etc.)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 19:57:11 -07:00
hailin dc6ac54c86 feat: client-side chart export (PNG/JPG/SVG/PDF/Excel/PPT/HTML)
Replaced backend export polling with direct browser-side export:
- PNG/JPG: ECharts getDataURL() with configurable pixelRatio
- SVG: ECharts SVG renderer output
- PDF: jsPDF with chart images (dynamic import)
- Excel: SheetJS json_to_sheet (dynamic import)
- PPT: PptxGenJS with chart slides (dynamic import)
- HTML: Standalone page with ECharts CDN + inline options
- Template: JSON config export

Added global ECharts instance registry for export access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 04:57:03 -07:00
hailin b3098eefbd fix: percent labels, background opacity, border radius
- Percent label format: calculate actual % from total instead of {d}
- Value labels: use toLocaleString for thousand separators
- Background opacity: convert hex+opacity to rgba
- Border radius: apply to ECharts container div

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 04:07:55 -07:00
hailin 49ed6a9bcb fix: axis title auto-visible on input + add show/hide switches
- Typing axis title text auto-sets titleVisible=true
- Added switches for: show axis, show axis title, show grid lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 03:13:14 -07:00
hailin 541440be8a fix: title and legend auto-avoid overlap
Legend moves below title when both are at top. Grid top adjusts
dynamically based on title/legend presence to prevent overlap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 03:09:29 -07:00
hailin f203904aa8 feat: single-series bar chart uses different color per category
Each bar gets a different color from the palette, making color
palette changes immediately visible for all chart configurations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 03:07:02 -07:00
hailin 2c4b1be806 fix: title auto-visible when text entered + add show/hide switch
Typing title text now auto-sets visible=true so the title appears
immediately. Also added a Switch to toggle title visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 03:03:32 -07:00
hailin 7e9957806e fix: force chart re-render when style/bindings change
Use JSON.stringify as useMemo key to detect deep changes in chart
config. Also removed redundant ensureStyle (now handled in Redux).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 03:00:36 -07:00
hailin e12f169319 fix: normalize style with full defaults when chart enters Redux
All style sub-objects (title, legend, xAxis, yAxis, dataLabel,
background, border, animation) are guaranteed to exist in Redux.
This fixes:
- Style config panels showing blank (returned null for missing fields)
- Style changes not applying (updateStyle now deep-merges sub-objects)
- Color palette changes not persisting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:56:09 -07:00
hailin 1ee9d57222 fix: color palette properly applied to bar charts
- ensureStyle: handle empty colors array (use defaults)
- barOptionBuilder: set option.color = style.colors globally
  so ECharts auto-assigns palette colors to all series
- Changing palette in style panel now updates chart colors immediately

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:53:10 -07:00
hailin 53669b66b8 fix: label binding auto-enables data labels on bar chart
When a field is dragged to the 'label' slot, data labels are
automatically shown on top of each bar with the value.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:47:43 -07:00
hailin 10b50bb2e0 feat: color binding splits bar chart into colored series with legend
Dragging a field to the 'color' slot now creates separate colored bars
per category value, with auto-generated legend. Also aggregates
multiple rows per category (sum) instead of taking first match only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:46:49 -07:00
hailin bb9273706e feat: redesign KPI card to enterprise standard
- Metric name (column name) as title
- Large formatted number with 万/亿 abbreviation
- Auto-detect 同比/环比 columns, show as colored trend badges
- Group label showing dimension info
- SVG sparkline for trend visualization
- Clean layout matching Tableau/Power BI KPI card patterns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:42:25 -07:00
hailin 12f7f04d82 fix: field drag uses text/plain to match DataBinding drop handler
LeftPanel was setting application/json but DataBinding reads text/plain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:37:59 -07:00
hailin 735f00cbc3 fix: KPI card label shows column name instead of first row value
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:36:12 -07:00
hailin 36c5b42f53 fix: ensure complete StyleConfig defaults in ECharts builder
Root cause: backend returns minimal style object without title/legend/axis
sub-objects, causing TypeError 'Cannot read properties of undefined'.
Fix: normalize style with full defaults at the builder entry point,
protecting ALL chart type builders uniformly.
Also fix antd deprecation warnings (destroyOnClose -> destroyOnHidden).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:31:37 -07:00
hailin b7edc7f86e fix: protect ECharts setOption from invalid data + add import debug logs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:24:25 -07:00
hailin 9b218a487a fix: wire real DataBinding/StyleConfig/InteractionConfig into RightPanel
Replaced placeholder text with actual configPanel components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:17:48 -07:00
hailin b07e8bb3d5 fix: show detailed import errors + improve KPICard
- DropZone: log actual error message instead of generic text
- KPICard: aggregate all rows, auto-detect 同比/环比 columns,
  show proper formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:16:53 -07:00
hailin e8f2554aa8 feat: Chinese chart labels + matching Ant Design icons
All 17 chart types now show Chinese names (柱状图, 折线图, 饼图, etc.)
and use specific Ant Design icons instead of generic BarChartOutlined.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 02:11:46 -07:00
hailin fe6cf014dc feat: auto-bind chart fields based on dataset columns
When creating a chart, automatically assign first text column to X axis
and first number column to Y axis (varies by chart type).
Charts now show data immediately instead of blank.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:57:54 -07:00
hailin ccbe63f9e4 fix: API path prefix + style defaults for chart rendering
- All 4 API clients now consistently use /api/v1/ prefix on all routes
- ChartRenderer fills missing style fields with defaults to prevent
  undefined property crashes when backend returns minimal style
- KPICard uses safe defaults for background/border/title

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:53:58 -07:00
hailin d03ee90f40 fix: replace WidthProvider with ResizeObserver for grid layout
react-grid-layout v2 removed WidthProvider. Use ResizeObserver to
track container width and pass it directly to Responsive component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:48:25 -07:00
hailin 28ebbbfb82 fix: critical data mapping bugs in useImportData and useCreateChart
- useImportData: use dataset_id instead of id from backend response,
  fetch rows after import, fix column type mapping
- useCreateChart: fix bindings mapper to use axis instead of fieldRole,
  graceful error handling instead of throwing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:43:16 -07:00
hailin 0c0592b511 fix: wire chart creation onClick in LeftPanel chart gallery
Clicking a chart type card now calls useCreateChart to create
a chart instance on the backend and add it to the canvas.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:39:18 -07:00
hailin b222429475 fix: dynamic import react-grid-layout to avoid SSR crash
WidthProvider is not available during SSR. Use dynamic import
inside useEffect to load it only on the client side.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:29:35 -07:00
hailin 79c144d74b fix: wire real components into AppShell instead of placeholders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 01:26:29 -07:00
hailin 6079ec8b97 feat: add frontend source code (Next.js + React + TypeScript)
Previously excluded due to nested .git from create-next-app.
Includes all Clean Architecture layers, API client integration,
and full UI component suite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:33:37 -07:00