package handler import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/yuxingu/digital-psychology/apps/api/internal/middleware" "github.com/yuxingu/digital-psychology/apps/api/internal/service/consult" "github.com/yuxingu/digital-psychology/apps/api/pkg/response" ) // ConsultHandler serves /api/v1/psychic/* (ECR-050). type ConsultHandler struct { Svc *consult.Service } func (h *ConsultHandler) Register(api *gin.RouterGroup) { g := api.Group("/psychic") g.POST("/banner/all", h.banners) g.GET("/news/page", h.newsPage) g.GET("/news/get", h.newsGet) g.POST("/procotol/getByCode", h.protocol) g.POST("/study/list", h.studyList) g.POST("/study/getSingleDetail", h.studyDetail) g.POST("/user-choice/save", h.choiceSave) g.POST("/user-choice/getResult", h.choiceResult) g.POST("/user-choice/my-test", h.myTest) g.GET("/doctor-info/business-scope-list", h.scopes) g.GET("/doctor-info/page", h.doctorPage) g.GET("/doctor-info/get", h.doctorGet) g.POST("/doctor-info/focus", h.focusOn) g.POST("/doctor-info/cancel-focus", h.focusOff) g.GET("/doctor-info/get-show-info", h.showInfo) g.POST("/appointment/remain-list", h.remain) g.POST("/appointment/date-detail-list", h.dateDetail) g.POST("/order/create", h.orderCreate) g.GET("/order/get-pay-param", h.payParam) g.POST("/order/order-list", h.orderList) g.POST("/order/order-detail", h.orderDetail) g.POST("/order/cancel", h.orderCancel) g.POST("/order/delete-order", h.orderDelete) g.POST("/pay/createOrder", h.payDemo) g.POST("/pay/refund", h.payRefund) g.POST("/pay/notify", h.payNotify) g.GET("/platform-user/getSelfInfo", h.selfInfo) g.POST("/platform-user/update", h.updateSelf) g.GET("/platform-user/not-read-num", h.notRead) g.POST("/platform-user/focus-to-read", h.focusRead) g.POST("/platform-user/order-to-read", h.orderRead) g.POST("/platform-user/focus-all", h.focusAll) g.POST("/platform-user/user-feedback", h.feedback) g.POST("/platform-user/feedback-flag", h.feedbackFlag) } func (h *ConsultHandler) banners(c *gin.Context) { data, err := h.Svc.Banners(c.Request.Context()) h.ok(c, data, err) } func (h *ConsultHandler) newsPage(c *gin.Context) { data, err := h.Svc.NewsPage(c.Request.Context(), qInt(c, "type", 0), qInt(c, "showMain", -1), qInt(c, "pageNo", 1), qInt(c, "pageSize", 20)) h.ok(c, data, err) } func (h *ConsultHandler) ok(c *gin.Context, data any, err error) { if err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, data) } func (h *ConsultHandler) newsGet(c *gin.Context) { data, err := h.Svc.NewsGet(c.Request.Context(), qInt64(c, "id")) h.ok(c, data, err) } func (h *ConsultHandler) protocol(c *gin.Context) { data, err := h.Svc.ProtocolByCode(c.Request.Context(), c.Query("code")) h.ok(c, data, err) } func (h *ConsultHandler) studyList(c *gin.Context) { data, err := h.Svc.TestList(c.Request.Context(), qInt(c, "showMain", -1)) h.ok(c, data, err) } func (h *ConsultHandler) studyDetail(c *gin.Context) { data, err := h.Svc.TestDetail(c.Request.Context(), qInt64(c, "studyId")) h.ok(c, data, err) } func (h *ConsultHandler) choiceSave(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var in consult.ChoiceIn if err := c.ShouldBindJSON(&in); err != nil { response.Fail(c, http.StatusBadRequest, 10000, "invalid request") return } data, err := h.Svc.SaveChoice(c.Request.Context(), uid, in) h.ok(c, data, err) } func (h *ConsultHandler) choiceResult(c *gin.Context) { data, err := h.Svc.GetResult(c.Request.Context(), qInt64(c, "resultId")) h.ok(c, data, err) } func (h *ConsultHandler) myTest(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var p struct { PageNo int `json:"pageNo"` PageSize int `json:"pageSize"` } _ = c.ShouldBindJSON(&p) data, err := h.Svc.MyTests(c.Request.Context(), uid, p.PageNo, p.PageSize) h.ok(c, data, err) } func (h *ConsultHandler) scopes(c *gin.Context) { data, err := h.Svc.Scopes(c.Request.Context()) h.ok(c, data, err) } func (h *ConsultHandler) doctorPage(c *gin.Context) { data, err := h.Svc.DoctorPage(c.Request.Context(), c.Query("businessScope"), qInt(c, "isTop", -1), qInt(c, "pageNo", 1), qInt(c, "pageSize", 20)) h.ok(c, data, err) } func (h *ConsultHandler) doctorGet(c *gin.Context) { uid, _ := middleware.UserIDFromContext(c) data, err := h.Svc.DoctorGet(c.Request.Context(), qInt64(c, "id"), uid) h.ok(c, data, err) } func (h *ConsultHandler) focusOn(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } if err := h.Svc.SetFocus(c.Request.Context(), uid, qInt64(c, "id"), true); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) focusOff(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } if err := h.Svc.SetFocus(c.Request.Context(), uid, qInt64(c, "id"), false); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) showInfo(c *gin.Context) { uid, _ := middleware.UserIDFromContext(c) data, err := h.Svc.ShowInfo(c.Request.Context(), qInt64(c, "id"), uid) h.ok(c, data, err) } func (h *ConsultHandler) remain(c *gin.Context) { var in struct { DoctorID int64 `json:"doctorId"` } _ = c.ShouldBindJSON(&in) data, err := h.Svc.RemainList(c.Request.Context(), in.DoctorID) h.ok(c, data, err) } func (h *ConsultHandler) dateDetail(c *gin.Context) { var in struct { DoctorID int64 `json:"doctorId"` } _ = c.ShouldBindJSON(&in) data, err := h.Svc.DateDetail(c.Request.Context(), in.DoctorID) h.ok(c, data, err) } func (h *ConsultHandler) orderCreate(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var in consult.OrderIn if err := c.ShouldBindJSON(&in); err != nil { response.Fail(c, http.StatusBadRequest, 10000, "invalid request") return } data, err := h.Svc.CreateOrder(c.Request.Context(), uid, in) h.ok(c, data, err) } func (h *ConsultHandler) payParam(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.PayParam(c.Request.Context(), uid, c.Query("orderSn")) h.ok(c, data, err) } func (h *ConsultHandler) orderList(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var p struct { PageNo int `json:"pageNo"` PageSize int `json:"pageSize"` } _ = c.ShouldBindJSON(&p) data, err := h.Svc.OrderList(c.Request.Context(), uid, p.PageNo, p.PageSize) h.ok(c, data, err) } func (h *ConsultHandler) orderDetail(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.OrderDetail(c.Request.Context(), uid, qInt64(c, "orderId")) h.ok(c, data, err) } func (h *ConsultHandler) orderCancel(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } if err := h.Svc.CancelOrder(c.Request.Context(), uid, qInt64(c, "orderId")); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) orderDelete(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } if err := h.Svc.DeleteOrder(c.Request.Context(), uid, qInt64(c, "orderId")); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) payDemo(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.DemoPay(c.Request.Context(), uid) h.ok(c, data, err) } func (h *ConsultHandler) payRefund(c *gin.Context) { response.OK(c, true) } func (h *ConsultHandler) payNotify(c *gin.Context) { raw, _ := c.GetRawData() sn := extractXML(string(raw), "out_trade_no") if sn != "" { _ = h.Svc.MarkPaid(c.Request.Context(), sn) } c.String(http.StatusOK, "") } func (h *ConsultHandler) selfInfo(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.SelfInfo(c.Request.Context(), uid) h.ok(c, data, err) } func (h *ConsultHandler) updateSelf(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var in struct { NickName string `json:"nickName"` AvatarUrl string `json:"avatarUrl"` StayPeriod string `json:"stayPeriod"` } _ = c.ShouldBindJSON(&in) if err := h.Svc.UpdateSelf(c.Request.Context(), uid, in.NickName, in.AvatarUrl, in.StayPeriod); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) notRead(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.NotRead(c.Request.Context(), uid) h.ok(c, data, err) } func (h *ConsultHandler) focusRead(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } _ = h.Svc.FocusToRead(c.Request.Context(), uid) response.OK(c, true) } func (h *ConsultHandler) orderRead(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } _ = h.Svc.OrderToRead(c.Request.Context(), uid) response.OK(c, true) } func (h *ConsultHandler) focusAll(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.FocusAll(c.Request.Context(), uid) h.ok(c, data, err) } func (h *ConsultHandler) feedback(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } var in struct { ContentText string `json:"contentText"` } _ = c.ShouldBindJSON(&in) if err := h.Svc.Feedback(c.Request.Context(), uid, in.ContentText); err != nil { response.Fail(c, http.StatusBadRequest, 40001, err.Error()) return } response.OK(c, true) } func (h *ConsultHandler) feedbackFlag(c *gin.Context) { uid, ok := h.mustUser(c) if !ok { return } data, err := h.Svc.FeedbackFlag(c.Request.Context(), uid) h.ok(c, data, err) } func (h *ConsultHandler) mustUser(c *gin.Context) (uuid.UUID, bool) { uid, ok := middleware.UserIDFromContext(c) if !ok || !h.Svc.Registered(c.Request.Context(), uid) { response.Fail(c, http.StatusUnauthorized, 40112, "请先登录后再使用") return uuid.Nil, false } return uid, true } func qInt(c *gin.Context, key string, def int) int { s := c.Query(key) if s == "" { return def } n, err := strconv.Atoi(s) if err != nil { return def } return n } func qInt64(c *gin.Context, key string) int64 { n, _ := strconv.ParseInt(c.Query(key), 10, 64) return n } func extractXML(s, tag string) string { open, close := "<"+tag+">", "" i := strings.Index(s, open) if i < 0 { open, close = "<"+tag+">" i = strings.Index(s, open) if i < 0 { return "" } } i += len(open) j := strings.Index(s[i:], close) if j < 0 { return "" } return s[i : i+j] }