diff --git a/dashboard/frontend/src/views/www/components/SectionManager.vue b/dashboard/frontend/src/views/www/components/SectionManager.vue index d0222f9..7e65fd9 100644 --- a/dashboard/frontend/src/views/www/components/SectionManager.vue +++ b/dashboard/frontend/src/views/www/components/SectionManager.vue @@ -51,7 +51,8 @@ const layoutOptions: LayoutOption[] = [ { label: '标题+媒体', value: 'title_media', desc: '顶部标题文案 + 下方图片/视频,对齐方向可配置' }, { label: '马赛克拼贴', value: 'mosaic', desc: '一大带多小的不规则网格,每个槽位支持图片/视频、中英双素材' }, { label: '跑马灯', value: 'marquee', desc: '图片/视频轮播,可自定义切换间隔,最多 5 个素材' }, - { label: '参数规格表', value: 'spec_table', desc: '产品技术参数规格表格' } + { label: '参数规格表', value: 'spec_table', desc: '产品技术参数规格表格' }, + { label: '3D 模型展示', value: 'model3d', desc: 'three.js 交互式 3D 模型(素材库上传 .glb),支持拖拽旋转/缩放/自动旋转' } ]; function layoutLabel(value: string) { @@ -366,7 +367,7 @@ function handleAdd() { formData.media_url_en = ''; formData.video_url = ''; formData.is_visible = true; - formData.config = { text_position: 'middle_left', width_percent: 100, container_width: '1200', border_radius: 0, padding_y: null, margin_y: null, title_font_size: null, bg_fit: 'cover', media_position: 'left', split_ratio: 50, mosaic_pattern: 'big_3', mosaic_items: emptyMosaicItems(4), marquee_items: emptyMarqueeItems(1), marquee_interval: 3, min_height: null }; + formData.config = { text_position: 'middle_left', width_percent: 100, container_width: '1200', border_radius: 0, padding_y: null, margin_y: null, title_font_size: null, bg_fit: 'cover', media_position: 'left', split_ratio: 50, mosaic_pattern: 'big_3', mosaic_items: emptyMosaicItems(4), marquee_items: emptyMarqueeItems(1), marquee_interval: 3, min_height: null, model_url: '', model_height: 480, auto_rotate: true }; dialogVisible.value = true; } @@ -412,7 +413,10 @@ function fillFormFromRow(row: Api.Www.SectionBlock) { split_ratio: [30, 40, 50, 60, 70].includes(Number(cfg.split_ratio)) ? Number(cfg.split_ratio) : 50, min_height: typeof cfg.min_height === 'number' && cfg.min_height >= 0 ? cfg.min_height : null, mosaic_pattern: ['big_3', 'half_2', 'big_4', 'big_2'].includes(String(cfg.mosaic_pattern)) ? String(cfg.mosaic_pattern) : 'big_3', - marquee_interval: typeof cfg.marquee_interval === 'number' && cfg.marquee_interval >= 1 ? Math.min(cfg.marquee_interval, 60) : 3 + marquee_interval: typeof cfg.marquee_interval === 'number' && cfg.marquee_interval >= 1 ? Math.min(cfg.marquee_interval, 60) : 3, + model_url: typeof cfg.model_url === 'string' ? cfg.model_url : '', + model_height: typeof cfg.model_height === 'number' && cfg.model_height >= 200 ? cfg.model_height : 480, + auto_rotate: cfg.auto_rotate !== false }; formData.config.mosaic_items = normalizeMosaicItems(cfg.mosaic_items, String(formData.config.mosaic_pattern)); formData.config.marquee_items = normalizeMarqueeItems(cfg.marquee_items); @@ -835,6 +839,28 @@ onMounted(loadData); + 添加素材({{ marqueeItems.length }}/5) +