Files
pj0235-eai_agentplatform/eai_ap_app/backend-go/internal/api/courses.go
T
eaiadmin 4e8817d768 init: 数字员工平台初始代码
包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。
- 工作台画布:节点拖放、连线模式、右键菜单、AI 助手
- 后端:连接器 API、专员种子数据
- 导航:左侧导航、工坊、市场、控制台
2026-08-18 20:19:58 +08:00

170 lines
4.6 KiB
Go

package api
import (
"strconv"
"github.com/gin-gonic/gin"
"eaisalestrain/backend/internal/model"
"eaisalestrain/backend/internal/store"
"eaisalestrain/backend/internal/web"
)
// courseView 课程详情视图(含绑定产品)
func courseView(c *gin.Context, co model.Course) {
out := gin.H{
"id": co.ID,
"code": co.Code,
"name": co.Name,
"category": co.Category,
"target_customers": co.TargetCustomers,
"forbidden_customers": co.ForbiddenCustomers,
"scripts": co.Scripts,
"sales_process": co.SalesProcess,
"objection_handling": co.ObjectionHandling,
"delivery_pitfalls": co.DeliveryPitfalls,
"report_rules": co.ReportRules,
"related_product_id": co.RelatedProductID,
"status": co.Status,
"created_at": co.CreatedAt,
"updated_at": co.UpdatedAt,
}
if co.RelatedProductID != nil {
var p model.Product
if store.DB.Where("id = ? AND status != ?", *co.RelatedProductID, "inactive").First(&p).Error == nil {
out["product"] = gin.H{"id": p.ID, "code": p.Code, "name": p.Name, "category": p.Category}
}
}
var medias []model.MediaFile
store.DB.Where("bind_type = ? AND bind_id = ? AND status = ?", "course", co.ID, "approved").
Order("id ASC").Find(&medias)
if len(medias) > 0 {
items := make([]gin.H, 0, len(medias))
for _, m := range medias {
items = append(items, gin.H{
"id": m.ID,
"filename": m.Filename,
"file_ext": m.FileExt,
"preview_url": "/api/media/preview/" + strconv.FormatUint(uint64(m.ID), 10),
})
}
out["medias"] = items
}
web.OK(c, out)
}
// ListCourses GET /api/courses?category=&status=
func ListCourses(c *gin.Context) {
q := store.DB.Model(&model.Course{})
if cat := c.Query("category"); cat != "" {
q = q.Where("category = ?", cat)
}
switch st := c.Query("status"); st {
case "": // 默认仅 active(员工浏览)
q = q.Where("status = ?", "active")
case "all": // 管理员维护全量
default:
q = q.Where("status = ?", st)
}
var items []model.Course
if err := q.Order("id ASC").Find(&items).Error; err != nil {
web.Fail(c, web.NewBadRequest("查询课程失败"))
return
}
web.OK(c, items)
}
// GetCourse GET /api/courses/{id}
func GetCourse(c *gin.Context) {
id, ok := parseID(c, "id")
if !ok {
return
}
var co model.Course
if err := store.DB.First(&co, id).Error; err != nil {
web.Fail(c, web.NewNotFoundError("课程不存在"))
return
}
courseView(c, co)
}
// CreateCourse POST /api/courses (admin)
func CreateCourse(c *gin.Context) {
var co model.Course
if err := c.ShouldBindJSON(&co); err != nil {
web.Fail(c, web.NewBadRequest("请求参数错误"))
return
}
if co.Code == "" || co.Name == "" || co.Category == "" {
web.Fail(c, web.NewBadRequest("编号、名称、分类为必填"))
return
}
var count int64
store.DB.Model(&model.Course{}).Where("code = ?", co.Code).Count(&count)
if count > 0 {
web.Fail(c, web.NewConflictError("课程编号已存在"))
return
}
if co.Status == "" {
co.Status = "active"
}
if err := store.DB.Create(&co).Error; err != nil {
web.Fail(c, web.NewBadRequest("创建课程失败"))
return
}
web.OK(c, co)
}
// UpdateCourse PUT /api/courses/{id} (admin) —— 支持绑定/解绑产品
func UpdateCourse(c *gin.Context) {
id, ok := parseID(c, "id")
if !ok {
return
}
var co model.Course
if err := store.DB.First(&co, id).Error; err != nil {
web.Fail(c, web.NewNotFoundError("课程不存在"))
return
}
var req model.Course
if err := c.ShouldBindJSON(&req); err != nil {
web.Fail(c, web.NewBadRequest("请求参数错误"))
return
}
if req.Name == "" || req.Category == "" {
web.Fail(c, web.NewBadRequest("名称、分类为必填"))
return
}
if req.Status == "" {
req.Status = "active"
}
if req.Code != "" && req.Code != co.Code {
var count int64
store.DB.Model(&model.Course{}).Where("code = ? AND id <> ?", req.Code, id).Count(&count)
if count > 0 {
web.Fail(c, web.NewConflictError("课程编号已存在"))
return
}
co.Code = req.Code
}
co.Name = req.Name
co.Category = req.Category
co.TargetCustomers = req.TargetCustomers
co.ForbiddenCustomers = req.ForbiddenCustomers
co.Scripts = req.Scripts
co.SalesProcess = req.SalesProcess
co.ObjectionHandling = req.ObjectionHandling
co.DeliveryPitfalls = req.DeliveryPitfalls
co.ReportRules = req.ReportRules
co.RelatedProductID = req.RelatedProductID
co.Status = req.Status
if err := store.DB.Save(&co).Error; err != nil {
web.Fail(c, web.NewBadRequest("更新课程失败"))
return
}
courseView(c, co)
}