# 详情图集功能使用指南 ## 🎯 功能概述 详情图集功能允许为工作流和课程添加多张详情展示图片,为用户提供更丰富的视觉内容介绍。 ## 🔧 技术实现 ### 数据库字段 ```sql -- 工作流表 ALTER TABLE workflow ADD COLUMN detail_gallery longtext DEFAULT NULL COMMENT '详情图集(JSON格式存储多张图片URL)'; -- 课程表 ALTER TABLE course ADD COLUMN detail_gallery longtext DEFAULT NULL COMMENT '详情图集(JSON格式存储多张图片URL)'; ``` ### 存储格式 ```json // 详情图集字段存储格式 "detailGallery": "[\"https://oss.../image1.jpg\",\"https://oss.../image2.jpg\",\"https://oss.../image3.jpg\"]" ``` ## 📱 前端集成 ### 1. 图片上传流程 ```javascript /** * 上传详情图集 * @param {FileList} files - 选择的图片文件 * @param {string} userId - 用户ID * @returns {Promise} 详情图集JSON字符串 */ async function uploadDetailGallery(files, userId) { const uploadPromises = Array.from(files).map(async (file) => { // 1. 获取OSS上传签名 const signResponse = await fetch('/user/oss/post-signature/json', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fileName: file.name, userId: userId }) }); if (!signResponse.ok) { throw new Error('获取上传签名失败'); } const signResult = await signResponse.json(); const signData = signResult.data; // 2. 构建上传表单 const formData = new FormData(); const objectKey = signData.dir + file.name; formData.append('key', objectKey); formData.append('policy', signData.policy); formData.append('x-oss-credential', signData.x_oss_credential); formData.append('x-oss-date', signData.x_oss_date); formData.append('x-oss-signature-version', signData.version); formData.append('x-oss-signature', signData.signature); formData.append('success_action_status', '200'); formData.append('file', file); // 3. 上传到OSS const uploadResponse = await fetch(signData.url, { method: 'POST', body: formData }); if (!uploadResponse.ok) { throw new Error('文件上传失败'); } // 4. 返回完整的文件URL return `${signData.url}/${objectKey}`; }); try { const imageUrls = await Promise.all(uploadPromises); return JSON.stringify(imageUrls); } catch (error) { console.error('上传详情图集失败:', error); throw error; } } ``` ### 2. 解析详情图集 ```javascript /** * 解析详情图集 * @param {string} detailGallery - 详情图集JSON字符串 * @returns {string[]} 图片URL数组 */ function parseDetailGallery(detailGallery) { if (!detailGallery || detailGallery.trim() === '') { return []; } try { const urls = JSON.parse(detailGallery); return Array.isArray(urls) ? urls : []; } catch (error) { console.error('解析详情图集失败:', error); return []; } } /** * 渲染详情图集 * @param {string} detailGallery - 详情图集JSON字符串 * @param {HTMLElement} container - 容器元素 */ function renderDetailGallery(detailGallery, container) { const imageUrls = parseDetailGallery(detailGallery); container.innerHTML = ''; if (imageUrls.length === 0) { container.innerHTML = '

暂无详情图片

'; return; } imageUrls.forEach((url, index) => { const img = document.createElement('img'); img.src = url; img.alt = `详情图片 ${index + 1}`; img.className = 'detail-gallery-image'; img.style.cssText = ` width: 100%; max-width: 400px; height: auto; margin: 10px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); cursor: pointer; `; // 点击预览 img.addEventListener('click', () => { showImagePreview(url); }); container.appendChild(img); }); } ``` ### 3. 完整使用示例 ```html
``` ## 🚀 后端接口支持 ### 1. 工作流相关接口 **上传工作流** - `POST /user/workflow/submit` ```json { "name": "工作流名称", "detailGallery": "[\"url1\",\"url2\"]", "vodVideoId": "视频ID", "data": "工作流JSON数据" } ``` **更新工作流** - `PUT /user/content/workflows/{id}` ```json { "name": "更新的名称", "detailGallery": "[\"new_url1\",\"new_url2\"]" } ``` ### 2. 课程相关接口 **更新课程** - `PUT /user/course/{id}` ```json { "title": "课程标题", "detailGallery": "[\"url1\",\"url2\"]", "price": 99.99 } ``` **用户内容管理** - `PUT /user/content/courses` ```json { "id": 1, "title": "课程标题", "detailGallery": "[\"url1\",\"url2\"]" } ``` ## 📋 响应示例 ### 工作流详情API响应 ```json { "code": 200, "message": "success", "data": { "workflow": { "id": 1, "name": "智能图像生成工作流", "coverUrl": "https://oss.../cover.jpg", "detailGallery": "[\"https://oss.../detail1.jpg\",\"https://oss.../detail2.jpg\",\"https://oss.../detail3.jpg\"]", "vodVideoId": "a0776b0179bf71f0bea45017f1e90102", "price": 29.99 } } } ``` ### 课程详情API响应 ```json { "id": 1, "title": "AI图像处理入门课程", "coverUrl": "https://oss.../cover.jpg", "detailGallery": "[\"https://oss.../detail1.jpg\",\"https://oss.../detail2.jpg\"]", "price": 99.99, "chapters": [...] } ``` ## ⚙️ 最佳实践 ### 1. 图片要求 - **尺寸**: 建议 1200x800px 或同等比例 - **格式**: 推荐 JPG/PNG - **大小**: 单张图片不超过 5MB - **数量**: 建议 2-5 张图片 ### 2. 用户体验 - **预览功能**: 支持图片点击放大预览 - **加载优化**: 使用懒加载和图片压缩 - **错误处理**: 提供友好的错误提示 - **进度显示**: 显示上传进度 ### 3. 性能优化 ```javascript // 图片压缩示例 function compressImage(file, maxWidth = 1200, quality = 0.8) { return new Promise((resolve) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = () => { const ratio = Math.min(maxWidth / img.width, maxWidth / img.height); canvas.width = img.width * ratio; canvas.height = img.height * ratio; ctx.drawImage(img, 0, 0, canvas.width, canvas.height); canvas.toBlob(resolve, 'image/jpeg', quality); }; img.src = URL.createObjectURL(file); }); } ``` ## 🔍 测试验证 ### 1. 功能测试清单 - [ ] 单张图片上传 - [ ] 多张图片批量上传 - [ ] 图片格式验证 - [ ] 文件大小限制 - [ ] 详情图集解析 - [ ] 详情图集渲染 - [ ] 接口响应验证 ### 2. 兼容性测试 - [ ] 现有工作流不受影响 - [ ] 现有课程不受影响 - [ ] API响应格式保持一致 - [ ] 数据库操作正常 ## 🆘 常见问题 **Q: 详情图集是必填字段吗?** A: 不是,详情图集是可选字段,不影响现有功能。 **Q: 如何清空详情图集?** A: 设置 `detailGallery` 为空字符串 `""` 或 `null`。 **Q: 支持的最大图片数量?** A: 理论上无限制,但建议2-5张以获得最佳体验。 **Q: 上传失败如何处理?** A: 实现重试机制,并提供详细的错误信息。 --- **更新时间**: 2024-12-01 **版本**: v1.0