## 开发 3D 图片生成功能 对接 3D 图片生成接口,为当前系统添加 3D 模型生成功能,默认支持腾讯云和 Gitee 的图生 3D API 接口。 ## 要求 1. 完成数据库设计,后端 API 设计,前端页面设计。 2. 完成前端功能页面以及后台管理页面,具体设计结构可以参考即梦 AI,在对应的模块建立独立的模块 。 3. 页面设计要精美,但是整体风格要跟整站风格一致。 4. 支持前端 3D 模型预览,支持 3D 模型下载。 ## 腾讯云图生 3D API 接口文档 1. 提交任务: https://cloud.tencent.com/document/product/1804/120826 2. 查询任务: https://cloud.tencent.com/document/product/1804/120827 3. Golang SDK: https://gitee.com/TencentCloud/tencentcloud-sdk-go/blob/master/tencentcloud/ai3d/v20250513/client.go 依赖已经安装到本地了,如果你无法读取远程文件,下面是文件主要内容: client.go ```go // Copyright (c) 2017-2025 Tencent. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package v20250513 import ( "context" "errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" ) const APIVersion = "2025-05-13" type Client struct { common.Client } // Deprecated func NewClientWithSecretId(secretId, secretKey, region string) (client *Client, err error) { cpf := profile.NewClientProfile() client = &Client{} client.Init(region).WithSecretId(secretId, secretKey).WithProfile(cpf) return } func NewClient(credential common.CredentialIface, region string, clientProfile *profile.ClientProfile) (client *Client, err error) { client = &Client{} client.Init(region). WithCredential(credential). WithProfile(clientProfile) return } func NewQueryHunyuanTo3DJobRequest() (request *QueryHunyuanTo3DJobRequest) { request = &QueryHunyuanTo3DJobRequest{ BaseRequest: &tchttp.BaseRequest{}, } request.Init().WithApiInfo("ai3d", APIVersion, "QueryHunyuanTo3DJob") return } func NewQueryHunyuanTo3DJobResponse() (response *QueryHunyuanTo3DJobResponse) { response = &QueryHunyuanTo3DJobResponse{ BaseResponse: &tchttp.BaseResponse{}, } return } // QueryHunyuanTo3DJob // 混元生3D接口,基于混元大模型,根据输入的文本描述/图片智能生成3D。 // // 默认提供1个并发,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后,才能开始处理下一个任务。 func (c *Client) QueryHunyuanTo3DJob(request *QueryHunyuanTo3DJobRequest) (response *QueryHunyuanTo3DJobResponse, err error) { return c.QueryHunyuanTo3DJobWithContext(context.Background(), request) } // QueryHunyuanTo3DJob // 混元生3D接口,基于混元大模型,根据输入的文本描述/图片智能生成3D。 // // 默认提供1个并发,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后,才能开始处理下一个任务。 func (c *Client) QueryHunyuanTo3DJobWithContext(ctx context.Context, request *QueryHunyuanTo3DJobRequest) (response *QueryHunyuanTo3DJobResponse, err error) { if request == nil { request = NewQueryHunyuanTo3DJobRequest() } c.InitBaseRequest(&request.BaseRequest, "ai3d", APIVersion, "QueryHunyuanTo3DJob") if c.GetCredential() == nil { return nil, errors.New("QueryHunyuanTo3DJob require credential") } request.SetContext(ctx) response = NewQueryHunyuanTo3DJobResponse() err = c.Send(request, response) return } func NewSubmitHunyuanTo3DJobRequest() (request *SubmitHunyuanTo3DJobRequest) { request = &SubmitHunyuanTo3DJobRequest{ BaseRequest: &tchttp.BaseRequest{}, } request.Init().WithApiInfo("ai3d", APIVersion, "SubmitHunyuanTo3DJob") return } func NewSubmitHunyuanTo3DJobResponse() (response *SubmitHunyuanTo3DJobResponse) { response = &SubmitHunyuanTo3DJobResponse{ BaseResponse: &tchttp.BaseResponse{}, } return } // SubmitHunyuanTo3DJob // 混元生3D接口,基于混元大模型,根据输入的文本描述/图片智能生成3D。 // // 默认提供1个并发,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后,才能开始处理下一个任务。 func (c *Client) SubmitHunyuanTo3DJob(request *SubmitHunyuanTo3DJobRequest) (response *SubmitHunyuanTo3DJobResponse, err error) { return c.SubmitHunyuanTo3DJobWithContext(context.Background(), request) } // SubmitHunyuanTo3DJob // 混元生3D接口,基于混元大模型,根据输入的文本描述/图片智能生成3D。 // // 默认提供1个并发,代表最多能同时处理1个已提交的任务,上一个任务处理完毕后,才能开始处理下一个任务。 func (c *Client) SubmitHunyuanTo3DJobWithContext(ctx context.Context, request *SubmitHunyuanTo3DJobRequest) (response *SubmitHunyuanTo3DJobResponse, err error) { if request == nil { request = NewSubmitHunyuanTo3DJobRequest() } c.InitBaseRequest(&request.BaseRequest, "ai3d", APIVersion, "SubmitHunyuanTo3DJob") if c.GetCredential() == nil { return nil, errors.New("SubmitHunyuanTo3DJob require credential") } request.SetContext(ctx) response = NewSubmitHunyuanTo3DJobResponse() err = c.Send(request, response) return } ``` model.go ```go // Copyright (c) 2017-2025 Tencent. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package v20250513 import ( tcerr "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/json" ) type File3D struct { // 文件格式 Type *string `json:"Type,omitnil,omitempty" name:"Type"` // 文件的Url(有效期24小时) Url *string `json:"Url,omitnil,omitempty" name:"Url"` // 预览图片Url PreviewImageUrl *string `json:"PreviewImageUrl,omitnil,omitempty" name:"PreviewImageUrl"` } // Predefined struct for user type QueryHunyuanTo3DJobRequestParams struct { // 任务ID。 JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"` } type QueryHunyuanTo3DJobRequest struct { *tchttp.BaseRequest // 任务ID。 JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"` } func (r *QueryHunyuanTo3DJobRequest) ToJsonString() string { b, _ := json.Marshal(r) return string(b) } // FromJsonString It is highly **NOT** recommended to use this function // because it has no param check, nor strict type check func (r *QueryHunyuanTo3DJobRequest) FromJsonString(s string) error { f := make(map[string]interface{}) if err := json.Unmarshal([]byte(s), &f); err != nil { return err } delete(f, "JobId") if len(f) > 0 { return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "QueryHunyuanTo3DJobRequest has unknown keys!", "") } return json.Unmarshal([]byte(s), &r) } // Predefined struct for user type QueryHunyuanTo3DJobResponseParams struct { // 任务状态。WAIT:等待中,RUN:执行中,FAIL:任务失败,DONE:任务成功 Status *string `json:"Status,omitnil,omitempty" name:"Status"` // 错误码 ErrorCode *string `json:"ErrorCode,omitnil,omitempty" name:"ErrorCode"` // 错误信息 ErrorMessage *string `json:"ErrorMessage,omitnil,omitempty" name:"ErrorMessage"` // 生成的3D文件数组。 ResultFile3Ds []*File3D `json:"ResultFile3Ds,omitnil,omitempty" name:"ResultFile3Ds"` // 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。 RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"` } type QueryHunyuanTo3DJobResponse struct { *tchttp.BaseResponse Response *QueryHunyuanTo3DJobResponseParams `json:"Response"` } func (r *QueryHunyuanTo3DJobResponse) ToJsonString() string { b, _ := json.Marshal(r) return string(b) } // FromJsonString It is highly **NOT** recommended to use this function // because it has no param check, nor strict type check func (r *QueryHunyuanTo3DJobResponse) FromJsonString(s string) error { return json.Unmarshal([]byte(s), &r) } // Predefined struct for user type SubmitHunyuanTo3DJobRequestParams struct { // 文生3D,3D内容的描述,中文正向提示词。 // 最多支持1024个 utf-8 字符。 // 文生3D, image、image_url和 prompt必填其一,且prompt和image/image_url不能同时存在。 Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"` // 输入图 Base64 数据。 // 大小:单边分辨率要求不小于128,不大于5000。大小不超过8m(base64编码后会大30%左右,建议实际输入图片不超过6m) // 格式:jpg,png,jpeg,webp。 // ImageBase64、ImageUrl和 Prompt必填其一,且Prompt和ImageBase64/ImageUrl不能同时存在。 ImageBase64 *string `json:"ImageBase64,omitnil,omitempty" name:"ImageBase64"` // 输入图Url。 // 大小:单边分辨率要求不小于128,不大于5000。大小不超过8m(base64编码后会大30%左右,建议实际输入图片不超过6m) // 格式:jpg,png,jpeg,webp。 // ImageBase64/ImageUrl和 Prompt必填其一,且Prompt和ImageBase64/ImageUrl不能同时存在。 ImageUrl *string `json:"ImageUrl,omitnil,omitempty" name:"ImageUrl"` // 多视角的模型图片,视角参考值: // left:左视图; // right:右视图; // back:后视图; // // 每个视角仅限制一张图片。 // ●图片大小限制:编码后大小不可超过8M。 // ●图片分辨率限制:单边分辨率小于5000且大于128。 // ●支持图片格式:支持jpg或png MultiViewImages []*ViewImage `json:"MultiViewImages,omitnil,omitempty" name:"MultiViewImages"` // 生成模型的格式,仅限制生成一种格式。 // 生成模型文件组默认返回obj格式。 // 可选值:OBJ,GLB,STL,USDZ,FBX,MP4。 ResultFormat *string `json:"ResultFormat,omitnil,omitempty" name:"ResultFormat"` // 是否开启 PBR材质生成,默认 false。 EnablePBR *bool `json:"EnablePBR,omitnil,omitempty" name:"EnablePBR"` } type SubmitHunyuanTo3DJobRequest struct { *tchttp.BaseRequest // 文生3D,3D内容的描述,中文正向提示词。 // 最多支持1024个 utf-8 字符。 // 文生3D, image、image_url和 prompt必填其一,且prompt和image/image_url不能同时存在。 Prompt *string `json:"Prompt,omitnil,omitempty" name:"Prompt"` // 输入图 Base64 数据。 // 大小:单边分辨率要求不小于128,不大于5000。大小不超过8m(base64编码后会大30%左右,建议实际输入图片不超过6m) // 格式:jpg,png,jpeg,webp。 // ImageBase64、ImageUrl和 Prompt必填其一,且Prompt和ImageBase64/ImageUrl不能同时存在。 ImageBase64 *string `json:"ImageBase64,omitnil,omitempty" name:"ImageBase64"` // 输入图Url。 // 大小:单边分辨率要求不小于128,不大于5000。大小不超过8m(base64编码后会大30%左右,建议实际输入图片不超过6m) // 格式:jpg,png,jpeg,webp。 // ImageBase64/ImageUrl和 Prompt必填其一,且Prompt和ImageBase64/ImageUrl不能同时存在。 ImageUrl *string `json:"ImageUrl,omitnil,omitempty" name:"ImageUrl"` // 多视角的模型图片,视角参考值: // left:左视图; // right:右视图; // back:后视图; // // 每个视角仅限制一张图片。 // ●图片大小限制:编码后大小不可超过8M。 // ●图片分辨率限制:单边分辨率小于5000且大于128。 // ●支持图片格式:支持jpg或png MultiViewImages []*ViewImage `json:"MultiViewImages,omitnil,omitempty" name:"MultiViewImages"` // 生成模型的格式,仅限制生成一种格式。 // 生成模型文件组默认返回obj格式。 // 可选值:OBJ,GLB,STL,USDZ,FBX,MP4。 ResultFormat *string `json:"ResultFormat,omitnil,omitempty" name:"ResultFormat"` // 是否开启 PBR材质生成,默认 false。 EnablePBR *bool `json:"EnablePBR,omitnil,omitempty" name:"EnablePBR"` } func (r *SubmitHunyuanTo3DJobRequest) ToJsonString() string { b, _ := json.Marshal(r) return string(b) } // FromJsonString It is highly **NOT** recommended to use this function // because it has no param check, nor strict type check func (r *SubmitHunyuanTo3DJobRequest) FromJsonString(s string) error { f := make(map[string]interface{}) if err := json.Unmarshal([]byte(s), &f); err != nil { return err } delete(f, "Prompt") delete(f, "ImageBase64") delete(f, "ImageUrl") delete(f, "MultiViewImages") delete(f, "ResultFormat") delete(f, "EnablePBR") if len(f) > 0 { return tcerr.NewTencentCloudSDKError("ClientError.BuildRequestError", "SubmitHunyuanTo3DJobRequest has unknown keys!", "") } return json.Unmarshal([]byte(s), &r) } // Predefined struct for user type SubmitHunyuanTo3DJobResponseParams struct { // 任务ID(有效期24小时) JobId *string `json:"JobId,omitnil,omitempty" name:"JobId"` // 唯一请求 ID,由服务端生成,每次请求都会返回(若请求因其他原因未能抵达服务端,则该次请求不会获得 RequestId)。定位问题时需要提供该次请求的 RequestId。 RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"` } type SubmitHunyuanTo3DJobResponse struct { *tchttp.BaseResponse Response *SubmitHunyuanTo3DJobResponseParams `json:"Response"` } func (r *SubmitHunyuanTo3DJobResponse) ToJsonString() string { b, _ := json.Marshal(r) return string(b) } // FromJsonString It is highly **NOT** recommended to use this function // because it has no param check, nor strict type check func (r *SubmitHunyuanTo3DJobResponse) FromJsonString(s string) error { return json.Unmarshal([]byte(s), &r) } type ViewImage struct { // 视角类型。 // 取值:back、left、right ViewType *string `json:"ViewType,omitnil,omitempty" name:"ViewType"` // 图片Url地址 ViewImageUrl *string `json:"ViewImageUrl,omitnil,omitempty" name:"ViewImageUrl"` } ``` ## Gitee 图生 3D API 接口文档 1. 提交任务: https://ai.gitee.com/docs/openapi/v1#tag/3d-%E7%94%9F%E6%88%90/post/async/image-to-3d 2. 查询任务:https://ai.gitee.com/docs/openapi/v1#tag/%E5%BC%82%E6%AD%A5%E4%BB%BB%E5%8A%A1/get/task/{task_id}/get 首先,你需要认真阅读上述接口文档,然后按照接口文档的示例代码实现腾讯云和 Gitee 的图生 3D API 接口,并且将接口集成到现有的系统中。 📋 功能概述 为现有的GeekAI-Plus系统添加3D图片生成功能,集成腾讯云和Gitee的图生3D API接口,包含完整的前后端功能和管理界面。 🗄️ 数据库设计 新增数据表:geekai_3d_jobs - id (uint): 主键 - type (string): API类型 (tencent/gitee) - user_id (uint): 用户ID - power (int): 消耗算力 - task_id (string): 第三方任务ID - img_url (string): 生成的3D模型文件地址 - model (string): 使用的3D模型类型 - status (string): 任务状态 - err_msg (string): 错误信息 - params (JSON): 任务参数(包含输入图片、提示词等所有参数) - created_at (int64): 创建时间 🔧 后端API实现 路由结构:/api/3d/* - POST /api/3d/generate - 创建3D生成任务 - GET /api/3d/jobs - 获取任务列表 - GET /api/3d/job/{id} - 获取任务详情 - GET /api/3d/download/{id} - 下载3D模型 - DELETE /api/3d/job/{id} - 删除任务 核心服务: - service/3d/tencent_client.go - 腾讯云3D API客户端 - service/3d/gitee_client.go - Gitee 3D API客户端 - service/3d/service.go - 3D生成服务统一接口 - handler/3d_handler.go - HTTP处理器 - store/vo/3d_job.go - 数据模型 🎨 前端界面设计 用户端页面:/3d - 3D生成主页面 - 参考JiMeng.vue的设计风格和布局 - 使用CustomTab组件分离平台参数: - Tab 1: "魔力方舟" (Gitee平台参数) - Tab 2: "腾讯混元" (腾讯云平台参数) - 每个Tab内包含: - 图片上传区域 - 模型选择下拉框 - 算力消耗实时显示 - 平台特定的参数配置 - 生成按钮 - 任务列表和状态显示 - 集成3D模型预览器 (three.js) - 模型下载功能 移动端适配: - mobile/3dCreate.vue - 移动端3D生成页面 - 保持Tab切换功能 - 响应式设计,触控优化 🛠️ 管理后台 管理功能: - admin/3d/3dJobs.vue - 任务管理列表 - admin/3d/3dSetting.vue - API配置页面 - 模型配置管理: - 分平台配置API秘钥和模型列表 - 设置每个模型的算力消耗值 - API密钥和端点配置 🔌 API集成方案 腾讯云集成: - 使用官方Golang SDK - 支持异步任务提交和状态查询 Gitee集成: - HTTP客户端实现 - 标准化响应处理 🎯 核心功能特性 - 平台切换:通过CustomTab在魔力方舟和腾讯混元间切换 - 模型选择:每个平台支持不同的3D模型 - 动态算力:切换模型时实时更新算力消耗显示 - 参数隔离:不同平台的参数配置完全分离 - 3D预览:集成Three.js实现模型预览 - 统一体验:保持与JiMeng.vue相似的交互风格 📱 用户体验 - JiMeng.vue风格的简洁界面 - Tab切换流畅的平台选择 - 模型选择时算力消耗实时更新 - 支持拖拽上传图片 - 实时任务状态显示 - 3D模型交互式预览 这个设计将创建一个与现有JiMeng功能风格一致的3D生成模块,通过Tab分离实现平台参数的清晰管理。 整个实现严格按照现有系统的代码规范和架构模式,与 JiMeng 等模块保持一致的用户体验!