mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-20 18:14:28 +08:00
remove AI3D module files
This commit is contained in:
@@ -1,222 +0,0 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service/ai3d"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// AI3DHandler 3D管理处理器
|
||||
type AI3DHandler struct {
|
||||
app *core.AppServer
|
||||
db *gorm.DB
|
||||
service *ai3d.Service
|
||||
}
|
||||
|
||||
// NewAI3DHandler 创建3D管理处理器
|
||||
func NewAI3DHandler(app *core.AppServer, db *gorm.DB, service *ai3d.Service) *AI3DHandler {
|
||||
return &AI3DHandler{
|
||||
app: app,
|
||||
db: db,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (h *AI3DHandler) RegisterRoutes() {
|
||||
admin := h.app.Engine.Group("/api/admin/ai3d")
|
||||
{
|
||||
admin.GET("/jobs", h.GetJobList)
|
||||
admin.GET("/jobs/:id", h.GetJobDetail)
|
||||
admin.DELETE("/jobs/:id", h.DeleteJob)
|
||||
admin.GET("/stats", h.GetStats)
|
||||
admin.GET("/models", h.GetModels)
|
||||
admin.POST("/config", h.SaveConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// GetJobList 获取任务列表
|
||||
func (h *AI3DHandler) GetJobList(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
status := c.Query("status")
|
||||
jobType := c.Query("type")
|
||||
userIdStr := c.Query("user_id")
|
||||
|
||||
var userId uint
|
||||
if userIdStr != "" {
|
||||
if id, err := strconv.ParseUint(userIdStr, 10, 32); err == nil {
|
||||
userId = uint(id)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
query := h.db.Model(&model.AI3DJob{})
|
||||
|
||||
if status != "" {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
|
||||
if jobType != "" {
|
||||
query = query.Where("type = ?", jobType)
|
||||
}
|
||||
|
||||
if userId > 0 {
|
||||
query = query.Where("user_id = ?", userId)
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
var total int64
|
||||
query.Count(&total)
|
||||
|
||||
// 获取分页数据
|
||||
var jobs []model.AI3DJob
|
||||
offset := (page - 1) * pageSize
|
||||
err := query.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&jobs).Error
|
||||
|
||||
if err != nil {
|
||||
resp.ERROR(c, "获取任务列表失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 转换为VO
|
||||
var jobList []vo.AI3DJob
|
||||
for _, job := range jobs {
|
||||
var jobVo vo.AI3DJob
|
||||
err = utils.CopyObject(job, &jobVo)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
utils.JsonDecode(job.Params, &jobVo.Params)
|
||||
jobVo.CreatedAt = job.CreatedAt.Unix()
|
||||
jobVo.UpdatedAt = job.UpdatedAt.Unix()
|
||||
jobList = append(jobList, jobVo)
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, page, pageSize, jobList))
|
||||
}
|
||||
|
||||
// GetJobDetail 获取任务详情
|
||||
func (h *AI3DHandler) GetJobDetail(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "无效的任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
var job model.AI3DJob
|
||||
err = h.db.First(&job, uint(id)).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
resp.ERROR(c, "任务不存在")
|
||||
} else {
|
||||
resp.ERROR(c, "获取任务详情失败")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var jobVo vo.AI3DJob
|
||||
err = utils.CopyObject(job, &jobVo)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "获取任务详情失败")
|
||||
return
|
||||
}
|
||||
utils.JsonDecode(job.Params, &jobVo.Params)
|
||||
jobVo.CreatedAt = job.CreatedAt.Unix()
|
||||
jobVo.UpdatedAt = job.UpdatedAt.Unix()
|
||||
resp.SUCCESS(c, jobVo)
|
||||
}
|
||||
|
||||
// DeleteJob 删除任务
|
||||
func (h *AI3DHandler) DeleteJob(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "无效的任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查任务是否存在
|
||||
var job model.AI3DJob
|
||||
err = h.db.First(&job, uint(id)).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
resp.ERROR(c, "任务不存在")
|
||||
} else {
|
||||
resp.ERROR(c, "获取任务失败")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 删除任务
|
||||
err = h.db.Delete(&job).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, "删除任务失败")
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, "删除成功")
|
||||
}
|
||||
|
||||
// GetStats 获取统计数据
|
||||
func (h *AI3DHandler) GetStats(c *gin.Context) {
|
||||
var stats struct {
|
||||
Pending int64 `json:"pending"`
|
||||
Processing int64 `json:"processing"`
|
||||
Success int64 `json:"success"`
|
||||
Failed int64 `json:"failed"`
|
||||
}
|
||||
|
||||
// 统计各状态的任务数量
|
||||
h.db.Model(&model.AI3DJob{}).Where("status = ?", "pending").Count(&stats.Pending)
|
||||
h.db.Model(&model.AI3DJob{}).Where("status = ?", "processing").Count(&stats.Processing)
|
||||
h.db.Model(&model.AI3DJob{}).Where("status = ?", "success").Count(&stats.Success)
|
||||
h.db.Model(&model.AI3DJob{}).Where("status = ?", "failed").Count(&stats.Failed)
|
||||
|
||||
resp.SUCCESS(c, stats)
|
||||
}
|
||||
|
||||
// GetModels 获取配置
|
||||
func (h *AI3DHandler) GetModels(c *gin.Context) {
|
||||
models := h.service.GetSupportedModels()
|
||||
resp.SUCCESS(c, models)
|
||||
}
|
||||
|
||||
// SaveGlobalSettings 保存全局配置
|
||||
func (h *AI3DHandler) SaveConfig(c *gin.Context) {
|
||||
var config types.AI3DConfig
|
||||
err := c.ShouldBindJSON(&config)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "参数错误")
|
||||
return
|
||||
}
|
||||
var exist model.Config
|
||||
err = h.db.Where("name", types.ConfigKeyAI3D).First(&exist).Error
|
||||
if err != nil {
|
||||
exist.Name = types.ConfigKeyAI3D
|
||||
exist.Value = utils.JsonEncode(config)
|
||||
err = h.db.Create(&exist).Error
|
||||
} else {
|
||||
exist.Value = utils.JsonEncode(config)
|
||||
err = h.db.Updates(&exist).Error
|
||||
}
|
||||
if err != nil {
|
||||
resp.ERROR(c, "保存配置失败")
|
||||
return
|
||||
}
|
||||
|
||||
h.service.UpdateConfig(config)
|
||||
h.app.SysConfig.AI3D = config
|
||||
|
||||
resp.SUCCESS(c, "保存成功")
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/middleware"
|
||||
"geekai/core/types"
|
||||
"geekai/service/ai3d"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AI3DHandler struct {
|
||||
BaseHandler
|
||||
service *ai3d.Service
|
||||
}
|
||||
|
||||
func NewAI3DHandler(app *core.AppServer, db *gorm.DB, service *ai3d.Service) *AI3DHandler {
|
||||
return &AI3DHandler{
|
||||
service: service,
|
||||
BaseHandler: BaseHandler{
|
||||
App: app,
|
||||
DB: db,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (h *AI3DHandler) RegisterRoutes() {
|
||||
group := h.App.Engine.Group("/api/ai3d/")
|
||||
|
||||
// 公开接口,不需要授权
|
||||
group.GET("configs", h.GetConfigs)
|
||||
|
||||
// 需要用户授权的接口
|
||||
group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis))
|
||||
{
|
||||
group.POST("generate", h.Generate)
|
||||
group.GET("jobs", h.JobList)
|
||||
group.GET("jobs/mock", h.ListMock) // 演示数据接口
|
||||
group.GET("job/delete", h.DeleteJob)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate 创建3D生成任务
|
||||
func (h *AI3DHandler) Generate(c *gin.Context) {
|
||||
var request vo.AI3DJobParams
|
||||
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
resp.ERROR(c, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
// 提示词和图片不能同时为空
|
||||
if request.Prompt == "" && request.ImageURL == "" {
|
||||
resp.ERROR(c, "提示词和图片不能同时为空")
|
||||
return
|
||||
}
|
||||
|
||||
// Gitee 只支持图片
|
||||
if request.Type == types.AI3DTaskTypeGitee && request.ImageURL == "" {
|
||||
resp.ERROR(c, "Gitee 只支持图生3D")
|
||||
return
|
||||
}
|
||||
|
||||
logger.Infof("request: %+v", request)
|
||||
|
||||
// 获取用户ID
|
||||
userId := h.GetLoginUserId(c)
|
||||
// 创建任务
|
||||
job, err := h.service.CreateJob(uint(userId), request)
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("创建任务失败: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, gin.H{
|
||||
"job_id": job.Id,
|
||||
"message": "任务创建成功",
|
||||
})
|
||||
}
|
||||
|
||||
// JobList 获取任务列表
|
||||
func (h *AI3DHandler) JobList(c *gin.Context) {
|
||||
userId := h.GetLoginUserId(c)
|
||||
if userId == 0 {
|
||||
resp.ERROR(c, "用户未登录")
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
jobList, err := h.service.GetJobList(uint(userId), page, pageSize)
|
||||
if err != nil {
|
||||
resp.ERROR(c, fmt.Sprintf("获取任务列表失败: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, jobList)
|
||||
}
|
||||
|
||||
// DeleteJob 删除任务
|
||||
func (h *AI3DHandler) DeleteJob(c *gin.Context) {
|
||||
userId := h.GetLoginUserId(c)
|
||||
id := h.GetInt(c, "id", 0)
|
||||
if id == 0 {
|
||||
resp.ERROR(c, "任务ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
err := h.service.DeleteUserJob(uint(id), uint(userId))
|
||||
if err != nil {
|
||||
resp.ERROR(c, "删除任务失败")
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, gin.H{"message": "删除成功"})
|
||||
}
|
||||
|
||||
// GetConfigs 获取3D生成配置
|
||||
func (h *AI3DHandler) GetConfigs(c *gin.Context) {
|
||||
var config model.Config
|
||||
err := h.DB.Where("name", types.ConfigKeyAI3D).First(&config).Error
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
var config3d types.AI3DConfig
|
||||
err = utils.JsonDecode(config.Value, &config3d)
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
models := h.service.GetSupportedModels()
|
||||
if len(config3d.Gitee.Models) == 0 {
|
||||
config3d.Gitee.Models = models["gitee"]
|
||||
}
|
||||
if len(config3d.Tencent.Models) == 0 {
|
||||
config3d.Tencent.Models = models["tencent"]
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, config3d)
|
||||
}
|
||||
|
||||
// ListMock 返回演示数据
|
||||
func (h *AI3DHandler) ListMock(c *gin.Context) {
|
||||
// 创建各种状态的演示数据
|
||||
mockJobs := []vo.AI3DJob{
|
||||
{
|
||||
Id: 1,
|
||||
UserId: 1,
|
||||
Type: "gitee",
|
||||
Power: 10,
|
||||
TaskId: "mock_task_1",
|
||||
FileURL: "https://img.r9it.com/R03TQZ7PZ386RGL7PTMNGFOHAJW15WYF.glb",
|
||||
PreviewURL: "/static/upload/2025/9/1756873317505073.png",
|
||||
Model: "gitee-3d-v1",
|
||||
Status: types.AI3DJobStatusSuccess,
|
||||
ErrMsg: "",
|
||||
Params: vo.AI3DJobParams{Prompt: "一只可爱的小猫", ImageURL: "", Texture: true, Seed: 42},
|
||||
CreatedAt: 1704067200, // 2024-01-01 00:00:00
|
||||
UpdatedAt: 1704067800, // 2024-01-01 00:10:00
|
||||
},
|
||||
{
|
||||
Id: 2,
|
||||
UserId: 1,
|
||||
Type: "tencent",
|
||||
Power: 15,
|
||||
TaskId: "mock_task_2",
|
||||
FileURL: "",
|
||||
PreviewURL: "/static/upload/2025/9/1756873317505073.png",
|
||||
Model: "tencent-3d-v2",
|
||||
Status: types.AI3DJobStatusProcessing,
|
||||
ErrMsg: "",
|
||||
Params: vo.AI3DJobParams{Prompt: "一个现代建筑模型", ImageURL: "", EnablePBR: true},
|
||||
CreatedAt: 1704070800, // 2024-01-01 01:00:00
|
||||
UpdatedAt: 1704070800, // 2024-01-01 01:00:00
|
||||
},
|
||||
{
|
||||
Id: 3,
|
||||
UserId: 1,
|
||||
Type: "gitee",
|
||||
Power: 8,
|
||||
TaskId: "mock_task_3",
|
||||
FileURL: "",
|
||||
PreviewURL: "",
|
||||
Model: "gitee-3d-v1",
|
||||
Status: types.AI3DJobStatusPending,
|
||||
ErrMsg: "",
|
||||
Params: vo.AI3DJobParams{Prompt: "一辆跑车模型", ImageURL: "https://example.com/car.jpg", Texture: false},
|
||||
CreatedAt: 1704074400, // 2024-01-01 02:00:00
|
||||
UpdatedAt: 1704074400, // 2024-01-01 02:00:00
|
||||
},
|
||||
{
|
||||
Id: 4,
|
||||
UserId: 1,
|
||||
Type: "tencent",
|
||||
Power: 12,
|
||||
TaskId: "mock_task_4",
|
||||
FileURL: "",
|
||||
PreviewURL: "",
|
||||
Model: "tencent-3d-v1",
|
||||
Status: types.AI3DJobStatusFailed,
|
||||
ErrMsg: "模型生成失败:输入图片质量不符合要求",
|
||||
Params: vo.AI3DJobParams{Prompt: "一个机器人模型", ImageURL: "https://example.com/robot.jpg", EnablePBR: false},
|
||||
CreatedAt: 1704078000, // 2024-01-01 03:00:00
|
||||
UpdatedAt: 1704078600, // 2024-01-01 03:10:00
|
||||
},
|
||||
{
|
||||
Id: 5,
|
||||
UserId: 1,
|
||||
Type: "gitee",
|
||||
Power: 20,
|
||||
TaskId: "mock_task_5",
|
||||
FileURL: "https://ai.gitee.com/a8c1af8e-26e9-4ca6-aa5c-6d4ba86bfdac",
|
||||
PreviewURL: "https://ai.gitee.com/a8c1af8e-26e9-4ca6-aa5c-6d4ba86bfdac",
|
||||
Model: "gitee-3d-v2",
|
||||
Status: types.AI3DJobStatusSuccess,
|
||||
ErrMsg: "",
|
||||
Params: vo.AI3DJobParams{Prompt: "一个复杂的机械装置", ImageURL: "", Texture: true, OctreeResolution: 512},
|
||||
CreatedAt: 1704081600, // 2024-01-01 04:00:00
|
||||
UpdatedAt: 1704082200, // 2024-01-01 04:10:00
|
||||
},
|
||||
{
|
||||
Id: 6,
|
||||
UserId: 1,
|
||||
Type: "tencent",
|
||||
Power: 18,
|
||||
TaskId: "mock_task_6",
|
||||
FileURL: "",
|
||||
PreviewURL: "",
|
||||
Model: "tencent-3d-v2",
|
||||
Status: types.AI3DJobStatusProcessing,
|
||||
ErrMsg: "",
|
||||
Params: vo.AI3DJobParams{Prompt: "一个科幻飞船", ImageURL: "", EnablePBR: true},
|
||||
CreatedAt: 1704085200, // 2024-01-01 05:00:00
|
||||
UpdatedAt: 1704085200, // 2024-01-01 05:00:00
|
||||
},
|
||||
}
|
||||
|
||||
// 创建分页响应
|
||||
mockResponse := vo.Page{
|
||||
Page: 1,
|
||||
PageSize: 10,
|
||||
Total: int64(len(mockJobs)),
|
||||
Items: mockJobs,
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, mockResponse)
|
||||
}
|
||||
Reference in New Issue
Block a user