Files
soul-yongping/soul-api/internal/handler/mentor.go

341 lines
10 KiB
Go
Raw Normal View History

// Soul创业派对 - 导师模块stitch_soul
// 小程序GET /api/miniprogram/mentors 列表、GET /api/miniprogram/mentors/:id 详情、POST /api/miniprogram/mentors/:id/book 预约
// 管理端db 组 CRUD + 预约列表
package handler
import (
"net/http"
"strconv"
"strings"
"soul-api/internal/database"
"soul-api/internal/model"
"github.com/gin-gonic/gin"
)
// MiniprogramMentorsList GET /api/miniprogram/mentors 导师列表(支持 q 搜索、skill 筛选)
func MiniprogramMentorsList(c *gin.Context) {
db := database.DB()
q := c.Query("q")
skill := c.Query("skill")
query := db.Model(&model.Mentor{}).Where("(enabled IS NULL OR enabled = 1)")
if q != "" {
query = query.Where("name LIKE ? OR intro LIKE ? OR tags LIKE ?", "%"+q+"%", "%"+q+"%", "%"+q+"%")
}
if skill != "" {
query = query.Where("tags LIKE ?", "%"+skill+"%")
}
var list []model.Mentor
if err := query.Order("sort ASC, id ASC").Find(&list).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
// 转为前端友好格式tags 拆成数组)
type mentorItem struct {
model.Mentor
TagsArr []string `json:"tagsArr"`
}
result := make([]mentorItem, len(list))
for i, m := range list {
result[i] = mentorItem{Mentor: m}
if m.Tags != "" {
result[i].TagsArr = strings.Split(m.Tags, ",")
for j := range result[i].TagsArr {
result[i].TagsArr[j] = strings.TrimSpace(result[i].TagsArr[j])
}
}
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": result})
}
// MiniprogramMentorsDetail GET /api/miniprogram/mentors/:id 导师详情
func MiniprogramMentorsDetail(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "无效的导师ID"})
return
}
db := database.DB()
var m model.Mentor
if err := db.Where("id = ? AND (enabled IS NULL OR enabled = 1)", id).First(&m).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "导师不存在"})
return
}
tagsArr := []string{}
if m.Tags != "" {
for _, s := range strings.Split(m.Tags, ",") {
if t := strings.TrimSpace(s); t != "" {
tagsArr = append(tagsArr, t)
}
}
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"id": m.ID,
"avatar": m.Avatar,
"name": m.Name,
"intro": m.Intro,
"tags": m.Tags,
"tagsArr": tagsArr,
"priceSingle": m.PriceSingle,
"priceHalfYear": m.PriceHalfYear,
"priceYear": m.PriceYear,
"quote": m.Quote,
"whyFind": m.WhyFind,
"offering": m.Offering,
"judgmentStyle": m.JudgmentStyle,
},
})
}
// MiniprogramMentorsBook POST /api/miniprogram/mentors/:id/book 创建预约(选择咨询类型后创建,后续走支付)
func MiniprogramMentorsBook(c *gin.Context) {
idStr := c.Param("id")
mentorID, err := strconv.Atoi(idStr)
if err != nil || mentorID <= 0 {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "无效的导师ID"})
return
}
var body struct {
UserID int `json:"userId" binding:"required"`
ConsultationType string `json:"consultationType" binding:"required"` // single, half_year, year
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "参数不完整"})
return
}
if body.ConsultationType != "single" && body.ConsultationType != "half_year" && body.ConsultationType != "year" {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "consultationType 需为 single/half_year/year"})
return
}
db := database.DB()
var mentor model.Mentor
if err := db.Where("id = ? AND (enabled IS NULL OR enabled = 1)", mentorID).First(&mentor).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "导师不存在"})
return
}
var amount float64
switch body.ConsultationType {
case "single":
if mentor.PriceSingle != nil {
amount = *mentor.PriceSingle
}
case "half_year":
if mentor.PriceHalfYear != nil {
amount = *mentor.PriceHalfYear
}
case "year":
if mentor.PriceYear != nil {
amount = *mentor.PriceYear
}
}
if amount <= 0 {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "该咨询类型暂未配置价格"})
return
}
consult := model.MentorConsultation{
UserID: body.UserID,
MentorID: mentorID,
ConsultationType: body.ConsultationType,
Amount: amount,
Status: "created",
}
if err := db.Create(&consult).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
// 返回预约单,前端可据此调 pay 接口productType: mentor_consultation, productId: consult.ID
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"id": consult.ID,
"mentorId": mentorID,
"consultationType": body.ConsultationType,
"amount": amount,
"status": "created",
},
})
}
// DBMentorsList GET /api/db/mentors 管理端导师列表
func DBMentorsList(c *gin.Context) {
db := database.DB()
var list []model.Mentor
if err := db.Order("sort ASC, id ASC").Find(&list).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": list})
}
// DBMentorsAction POST 新增 / PUT 更新 / DELETE 删除 导师
func DBMentorsAction(c *gin.Context) {
db := database.DB()
method := c.Request.Method
if method == "POST" {
var body struct {
Name string `json:"name" binding:"required"`
Avatar string `json:"avatar"`
Intro string `json:"intro"`
Tags string `json:"tags"`
PriceSingle *float64 `json:"priceSingle"`
PriceHalfYear *float64 `json:"priceHalfYear"`
PriceYear *float64 `json:"priceYear"`
Quote string `json:"quote"`
WhyFind string `json:"whyFind"`
Offering string `json:"offering"`
JudgmentStyle string `json:"judgmentStyle"`
Sort int `json:"sort"`
Enabled *bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "name 不能为空"})
return
}
m := model.Mentor{
Name: body.Name,
Avatar: body.Avatar,
Intro: body.Intro,
Tags: body.Tags,
PriceSingle: body.PriceSingle,
PriceHalfYear: body.PriceHalfYear,
PriceYear: body.PriceYear,
Quote: body.Quote,
WhyFind: body.WhyFind,
Offering: body.Offering,
JudgmentStyle: body.JudgmentStyle,
Sort: body.Sort,
Enabled: body.Enabled,
}
if m.Enabled == nil {
trueVal := true
m.Enabled = &trueVal
}
if err := db.Create(&m).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": m})
return
}
if method == "PUT" {
var body struct {
ID int `json:"id" binding:"required"`
Name *string `json:"name"`
Avatar *string `json:"avatar"`
Intro *string `json:"intro"`
Tags *string `json:"tags"`
PriceSingle *float64 `json:"priceSingle"`
PriceHalfYear *float64 `json:"priceHalfYear"`
PriceYear *float64 `json:"priceYear"`
Quote *string `json:"quote"`
WhyFind *string `json:"whyFind"`
Offering *string `json:"offering"`
JudgmentStyle *string `json:"judgmentStyle"`
Sort *int `json:"sort"`
Enabled *bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "id 不能为空"})
return
}
updates := map[string]interface{}{}
if body.Name != nil {
updates["name"] = *body.Name
}
if body.Avatar != nil {
updates["avatar"] = *body.Avatar
}
if body.Intro != nil {
updates["intro"] = *body.Intro
}
if body.Tags != nil {
updates["tags"] = *body.Tags
}
if body.PriceSingle != nil {
updates["price_single"] = *body.PriceSingle
}
if body.PriceHalfYear != nil {
updates["price_half_year"] = *body.PriceHalfYear
}
if body.PriceYear != nil {
updates["price_year"] = *body.PriceYear
}
if body.Quote != nil {
updates["quote"] = *body.Quote
}
if body.WhyFind != nil {
updates["why_find"] = *body.WhyFind
}
if body.Offering != nil {
updates["offering"] = *body.Offering
}
if body.JudgmentStyle != nil {
updates["judgment_style"] = *body.JudgmentStyle
}
if body.Sort != nil {
updates["sort"] = *body.Sort
}
if body.Enabled != nil {
updates["enabled"] = *body.Enabled
}
if len(updates) == 0 {
c.JSON(http.StatusOK, gin.H{"success": true, "message": "无更新"})
return
}
if err := db.Model(&model.Mentor{}).Where("id = ?", body.ID).Updates(updates).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "message": "更新成功"})
return
}
if method == "DELETE" {
id := c.Query("id")
if id == "" {
c.JSON(http.StatusOK, gin.H{"success": false, "error": "id 不能为空"})
return
}
if err := db.Where("id = ?", id).Delete(&model.Mentor{}).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "message": "删除成功"})
return
}
c.JSON(http.StatusOK, gin.H{"success": false, "error": "不支持的请求方法"})
}
// DBMentorConsultationsList GET /api/db/mentor-consultations 预约列表(支持 status 筛选)
func DBMentorConsultationsList(c *gin.Context) {
db := database.DB()
status := c.Query("status")
query := db.Model(&model.MentorConsultation{})
if status != "" {
query = query.Where("status = ?", status)
}
var list []model.MentorConsultation
if err := query.Order("created_at DESC").Find(&list).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": list})
}