2025-12-19 22:36:48 +08:00
|
|
|
|
package controller
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"ai_xhs/common"
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"ai_xhs/database"
|
|
|
|
|
|
"ai_xhs/models"
|
2025-12-19 22:36:48 +08:00
|
|
|
|
"ai_xhs/service"
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"ai_xhs/utils"
|
|
|
|
|
|
"bytes"
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
|
"fmt"
|
2026-01-07 22:55:12 +08:00
|
|
|
|
"net/http"
|
2025-12-19 22:36:48 +08:00
|
|
|
|
"strconv"
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"strings"
|
|
|
|
|
|
"time"
|
2025-12-19 22:36:48 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
2025-12-20 01:05:46 +08:00
|
|
|
|
|
2025-12-19 22:36:48 +08:00
|
|
|
|
type EmployeeController struct {
|
|
|
|
|
|
service *service.EmployeeService
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewEmployeeController() *EmployeeController {
|
|
|
|
|
|
return &EmployeeController{
|
|
|
|
|
|
service: &service.EmployeeService{},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SendXHSCode 发送小红书验证码
|
|
|
|
|
|
func (ctrl *EmployeeController) SendXHSCode(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
XHSPhone string `json:"xhs_phone" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误:手机号不能为空")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 19:36:42 +08:00
|
|
|
|
// 获取当前登录用户ID
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
2026-01-09 23:27:52 +08:00
|
|
|
|
data, err := ctrl.service.SendXHSCode(req.XHSPhone, employeeID)
|
2025-12-19 22:36:48 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-09 23:27:52 +08:00
|
|
|
|
// 检查是否需要扫码验证
|
|
|
|
|
|
if needCaptcha, ok := data["need_captcha"].(bool); ok && needCaptcha {
|
|
|
|
|
|
// 发送验证码时触发风控,返回二维码
|
|
|
|
|
|
common.SuccessWithMessage(c, "需要扫码验证", data)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "验证码已发送,请在小红书APP中查看", data)
|
2025-12-19 22:36:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetProfile 获取员工个人信息
|
|
|
|
|
|
func (ctrl *EmployeeController) GetProfile(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
employee, err := ctrl.service.GetProfile(employeeID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeNotFound, "员工不存在")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户显示名称(优先使用真实姓名,其次用户名)
|
|
|
|
|
|
displayName := employee.RealName
|
|
|
|
|
|
if displayName == "" {
|
|
|
|
|
|
displayName = employee.Username
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data := map[string]interface{}{
|
|
|
|
|
|
"id": employee.ID,
|
|
|
|
|
|
"name": displayName,
|
|
|
|
|
|
"username": employee.Username,
|
|
|
|
|
|
"real_name": employee.RealName,
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"nickname": employee.Nickname,
|
|
|
|
|
|
"email": employee.Email,
|
2025-12-19 22:36:48 +08:00
|
|
|
|
"phone": employee.Phone,
|
|
|
|
|
|
"role": employee.Role,
|
|
|
|
|
|
"enterprise_id": employee.EnterpriseID,
|
|
|
|
|
|
"enterprise_name": employee.Enterprise.Name,
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"avatar": employee.Icon,
|
2025-12-19 22:36:48 +08:00
|
|
|
|
"is_bound_xhs": employee.IsBoundXHS,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 19:36:42 +08:00
|
|
|
|
// 如果已绑定,从 ai_authors 表获取小红书账号信息(根据 created_user_id 查询)
|
|
|
|
|
|
if employee.IsBoundXHS == 1 {
|
|
|
|
|
|
var author models.Author
|
|
|
|
|
|
err := database.DB.Where(
|
|
|
|
|
|
"created_user_id = ? AND enterprise_id = ? AND channel = 1 AND status = 'active'",
|
|
|
|
|
|
employeeID, employee.EnterpriseID,
|
|
|
|
|
|
).First(&author).Error
|
|
|
|
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
data["xhs_account"] = author.XHSAccount
|
|
|
|
|
|
data["xhs_phone"] = author.XHSPhone
|
|
|
|
|
|
data["has_xhs_cookie"] = author.XHSCookie != ""
|
|
|
|
|
|
if author.BoundAt != nil {
|
|
|
|
|
|
data["bound_at"] = author.BoundAt.Format("2006-01-02 15:04:05")
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 没有找到author记录,返回默认值
|
|
|
|
|
|
data["xhs_account"] = ""
|
|
|
|
|
|
data["xhs_phone"] = ""
|
|
|
|
|
|
data["has_xhs_cookie"] = false
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
data["xhs_account"] = ""
|
|
|
|
|
|
data["xhs_phone"] = ""
|
|
|
|
|
|
data["has_xhs_cookie"] = false
|
2025-12-19 22:36:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 19:36:42 +08:00
|
|
|
|
// UpdateProfile 更新个人资料(昵称、邮箱、头像)
|
|
|
|
|
|
func (ctrl *EmployeeController) UpdateProfile(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Nickname *string `json:"nickname"`
|
|
|
|
|
|
Email *string `json:"email"`
|
|
|
|
|
|
Avatar *string `json:"avatar"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if req.Nickname == nil && req.Email == nil && req.Avatar == nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "没有可更新的字段")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 简单校验邮箱格式
|
|
|
|
|
|
if req.Email != nil && *req.Email != "" {
|
|
|
|
|
|
if !strings.Contains(*req.Email, "@") {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "邮箱格式不正确")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := ctrl.service.UpdateProfile(employeeID, req.Nickname, req.Email, req.Avatar); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "更新成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UploadAvatar 上传头像
|
|
|
|
|
|
func (ctrl *EmployeeController) UploadAvatar(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
// 获取上传的文件
|
|
|
|
|
|
file, err := c.FormFile("file")
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "请选择要上传的图片")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 校验文件类型
|
|
|
|
|
|
contentType := file.Header.Get("Content-Type")
|
|
|
|
|
|
if !strings.HasPrefix(contentType, "image/") {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "只能上传图片文件")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 校验文件大小(5MB)
|
|
|
|
|
|
if file.Size > 5*1024*1024 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "图片大小不能超过5MB")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 打开文件
|
|
|
|
|
|
src, err := file.Open()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, "打开文件失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
defer src.Close()
|
|
|
|
|
|
|
|
|
|
|
|
// 读取文件内容
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
|
_, err = buf.ReadFrom(src)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, "读取文件失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 上传到 OSS
|
|
|
|
|
|
fileExt := ".jpg"
|
|
|
|
|
|
if strings.Contains(contentType, "png") {
|
|
|
|
|
|
fileExt = ".png"
|
|
|
|
|
|
} else if strings.Contains(contentType, "webp") {
|
|
|
|
|
|
fileExt = ".webp"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fileName := fmt.Sprintf("avatar_%d_%d%s", employeeID, time.Now().Unix(), fileExt)
|
|
|
|
|
|
ossURL, err := utils.UploadToOSS(bytes.NewReader(buf.Bytes()), fileName)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, fmt.Sprintf("上传失败: %s", err.Error()))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新数据库
|
|
|
|
|
|
if err := ctrl.service.UpdateProfile(employeeID, nil, nil, &ossURL); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, "更新头像失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, map[string]interface{}{
|
|
|
|
|
|
"url": ossURL,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// BindXHS 绑定小红书账号(异步处理)
|
2025-12-19 22:36:48 +08:00
|
|
|
|
func (ctrl *EmployeeController) BindXHS(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
2026-01-07 22:55:12 +08:00
|
|
|
|
XHSPhone string `json:"xhs_phone" binding:"required"`
|
|
|
|
|
|
Code string `json:"code" binding:"required"`
|
|
|
|
|
|
SessionID string `json:"session_id"` // 发送验证码时返回的session_id,用于复用浏览器
|
2025-12-19 22:36:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-07 22:55:12 +08:00
|
|
|
|
_, err := ctrl.service.BindXHS(employeeID, req.XHSPhone, req.Code, req.SessionID)
|
2025-12-19 22:36:48 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeBindXHSFailed, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 19:36:42 +08:00
|
|
|
|
// 立即返回成功,告知前端正在处理
|
|
|
|
|
|
common.SuccessWithMessage(c, "正在验证登录,请稍候...", map[string]interface{}{
|
|
|
|
|
|
"status": "processing",
|
2025-12-19 22:36:48 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 19:36:42 +08:00
|
|
|
|
// GetBindXHSStatus 获取小红书绑定状态
|
|
|
|
|
|
func (ctrl *EmployeeController) GetBindXHSStatus(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
status, err := ctrl.service.GetBindXHSStatus(employeeID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, status)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-19 22:36:48 +08:00
|
|
|
|
// UnbindXHS 解绑小红书账号
|
|
|
|
|
|
func (ctrl *EmployeeController) UnbindXHS(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
if err := ctrl.service.UnbindXHS(employeeID); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "解绑成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetAvailableCopies 获取可领取文案列表
|
|
|
|
|
|
func (ctrl *EmployeeController) GetAvailableCopies(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
productID, err := strconv.Atoi(c.Query("product_id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "产品ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.GetAvailableCopies(employeeID, productID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ClaimCopy 领取文案
|
|
|
|
|
|
func (ctrl *EmployeeController) ClaimCopy(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
CopyID int `json:"copy_id" binding:"required"`
|
|
|
|
|
|
ProductID int `json:"product_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.ClaimCopy(employeeID, req.CopyID, req.ProductID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeAlreadyClaimed, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "领取成功", data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ClaimRandomCopy 随机领取文案
|
|
|
|
|
|
func (ctrl *EmployeeController) ClaimRandomCopy(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
ProductID int `json:"product_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.ClaimRandomCopy(employeeID, req.ProductID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeCopyNotAvailable, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "领取成功", data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Publish 发布内容
|
|
|
|
|
|
func (ctrl *EmployeeController) Publish(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req service.PublishRequest
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
recordID, err := ctrl.service.Publish(employeeID, req)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "发布成功", map[string]interface{}{
|
|
|
|
|
|
"record_id": recordID,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetMyPublishRecords 获取我的发布记录
|
|
|
|
|
|
func (ctrl *EmployeeController) GetMyPublishRecords(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
|
|
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.GetMyPublishRecords(employeeID, page, pageSize)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetPublishRecordDetail 获取发布记录详情
|
|
|
|
|
|
func (ctrl *EmployeeController) GetPublishRecordDetail(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
recordID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "记录ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.GetPublishRecordDetail(employeeID, recordID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeNotFound, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CheckXHSStatus 检查小红书绑定与Cookie状态
|
|
|
|
|
|
func (ctrl *EmployeeController) CheckXHSStatus(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
status, err := ctrl.service.CheckXHSStatus(employeeID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, status)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetProducts 获取产品列表
|
|
|
|
|
|
func (ctrl *EmployeeController) GetProducts(c *gin.Context) {
|
2026-01-06 19:36:42 +08:00
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
if employeeID == 0 {
|
|
|
|
|
|
common.Error(c, common.CodeUnauthorized, "未登录或token无效")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
|
|
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
|
|
|
|
|
|
|
|
|
|
|
data, hasMore, err := ctrl.service.GetProducts(employeeID, page, pageSize)
|
2025-12-19 22:36:48 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.Success(c, map[string]interface{}{
|
2026-01-06 19:36:42 +08:00
|
|
|
|
"list": data,
|
|
|
|
|
|
"has_more": hasMore,
|
2025-12-19 22:36:48 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-12-20 01:05:46 +08:00
|
|
|
|
|
|
|
|
|
|
// UpdateArticleStatus 更新文案状态(通过/拒绝)
|
|
|
|
|
|
func (ctrl *EmployeeController) UpdateArticleStatus(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
articleID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "文案ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Status string `json:"status" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证status值
|
|
|
|
|
|
if req.Status != "approved" && req.Status != "rejected" {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "status只能为approved或rejected")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = ctrl.service.UpdateArticleStatus(employeeID, articleID, req.Status)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
message := "已通过"
|
|
|
|
|
|
if req.Status == "rejected" {
|
|
|
|
|
|
message = "已拒绝"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, message, nil)
|
|
|
|
|
|
}
|
2026-01-06 19:36:42 +08:00
|
|
|
|
|
|
|
|
|
|
// UpdateArticleContent 更新文案内容(标题、正文)
|
|
|
|
|
|
func (ctrl *EmployeeController) UpdateArticleContent(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
articleID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "文案ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Title string `json:"title" binding:"required"`
|
|
|
|
|
|
Content string `json:"content" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证标题和内容字数
|
|
|
|
|
|
if len([]rune(req.Title)) > 20 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "标题最多20字")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if len([]rune(req.Content)) > 1000 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "内容最多1000字")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = ctrl.service.UpdateArticleContent(employeeID, articleID, req.Title, req.Content)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "更新成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UpdatePublishRecord 编辑发布记录(修改标题、内容、图片、标签)
|
|
|
|
|
|
func (ctrl *EmployeeController) UpdatePublishRecord(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
recordID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "记录ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req service.UpdatePublishRecordRequest
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证标题和内容字数
|
|
|
|
|
|
if req.Title != nil && len([]rune(*req.Title)) > 20 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "标题最多20字")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if req.Content != nil && len([]rune(*req.Content)) > 1000 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "内容最多1000字")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := ctrl.service.UpdatePublishRecord(employeeID, recordID, req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "更新成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RepublishRecord 重新发布种草内容
|
|
|
|
|
|
func (ctrl *EmployeeController) RepublishRecord(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
recordID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "记录ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
publishLink, err := ctrl.service.RepublishRecord(employeeID, recordID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "重新发布成功", map[string]interface{}{
|
|
|
|
|
|
"publish_link": publishLink,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// AddArticleImage 添加文案图片
|
|
|
|
|
|
func (ctrl *EmployeeController) AddArticleImage(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
articleID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "文案ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
ImageURL string `json:"image_url" binding:"required"`
|
|
|
|
|
|
ImageThumbURL string `json:"image_thumb_url"`
|
|
|
|
|
|
KeywordsName string `json:"keywords_name"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有缩略图,使用原图
|
|
|
|
|
|
if req.ImageThumbURL == "" {
|
|
|
|
|
|
req.ImageThumbURL = req.ImageURL
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
image, err := ctrl.service.AddArticleImage(employeeID, articleID, req.ImageURL, req.ImageThumbURL, req.KeywordsName)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "添加成功", image)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// DeleteArticleImage 删除文案图片
|
|
|
|
|
|
func (ctrl *EmployeeController) DeleteArticleImage(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
imageID, err := strconv.Atoi(c.Param("imageId"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "图片ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = ctrl.service.DeleteArticleImage(employeeID, imageID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "删除成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateArticleImagesOrder 更新文案图片排序
|
|
|
|
|
|
func (ctrl *EmployeeController) UpdateArticleImagesOrder(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
articleID, err := strconv.Atoi(c.Param("id"))
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "文案ID参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
ImageOrders []map[string]int `json:"image_orders" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = ctrl.service.UpdateArticleImagesOrder(employeeID, articleID, req.ImageOrders)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "更新成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// UploadImage 上传图片(支持base64和multipart/form-data)
|
|
|
|
|
|
func (ctrl *EmployeeController) UploadImage(c *gin.Context) {
|
|
|
|
|
|
// 尝试从表单获取文件
|
|
|
|
|
|
file, header, err := c.Request.FormFile("file")
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
// 处理文件上传
|
|
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
|
|
|
|
// 验证文件类型
|
|
|
|
|
|
contentType := header.Header.Get("Content-Type")
|
|
|
|
|
|
if !strings.HasPrefix(contentType, "image/") {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "只支持图片文件")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 上传到OSS
|
|
|
|
|
|
imageURL, err := utils.UploadToOSS(file, header.Filename)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, fmt.Sprintf("上传失败: %v", err))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "上传成功", map[string]interface{}{
|
|
|
|
|
|
"image_url": imageURL,
|
|
|
|
|
|
"image_thumb_url": imageURL, // 简化处理,缩略图与原图相同
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试介ase64获取
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
Base64 string `json:"base64" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "请上传文件或base64数据")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 解析base64
|
|
|
|
|
|
var imageData []byte
|
|
|
|
|
|
if strings.Contains(req.Base64, "base64,") {
|
|
|
|
|
|
// 移除data:image/xxx;base64,前缀
|
|
|
|
|
|
parts := strings.Split(req.Base64, "base64,")
|
|
|
|
|
|
if len(parts) != 2 {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "base64格式错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
imageData, err = base64.StdEncoding.DecodeString(parts[1])
|
|
|
|
|
|
} else {
|
|
|
|
|
|
imageData, err = base64.StdEncoding.DecodeString(req.Base64)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "base64解码失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 上传到OSS
|
|
|
|
|
|
reader := bytes.NewReader(imageData)
|
|
|
|
|
|
imageURL, err := utils.UploadToOSS(reader, "image.jpg")
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, fmt.Sprintf("上传失败: %v", err))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "上传成功", map[string]interface{}{
|
|
|
|
|
|
"image_url": imageURL,
|
|
|
|
|
|
"image_thumb_url": imageURL,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RevokeUserToken 禁用用户(撤销Token)
|
|
|
|
|
|
func (ctrl *EmployeeController) RevokeUserToken(c *gin.Context) {
|
|
|
|
|
|
// 只有管理员可以禁用用户
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前用户信息,检查是否为管理员
|
|
|
|
|
|
var currentUser models.User
|
|
|
|
|
|
if err := database.DB.Where("id = ?", employeeID).First(¤tUser).Error; err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeUnauthorized, "用户不存在")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if currentUser.Role != "admin" {
|
|
|
|
|
|
common.Error(c, common.CodeUnauthorized, "无权操作,只有管理员可以禁用用户")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
TargetUserID int `json:"target_user_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误:需要提供目标用户ID")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 不能禁用自己
|
|
|
|
|
|
if req.TargetUserID == employeeID {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "不能禁用自己")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查目标用户是否存在
|
|
|
|
|
|
var targetUser models.User
|
|
|
|
|
|
if err := database.DB.Where("id = ?", req.TargetUserID).First(&targetUser).Error; err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeNotFound, "目标用户不存在")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 撤销该用户的Token
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
if err := utils.RevokeToken(ctx, req.TargetUserID); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, fmt.Sprintf("禁用失败: %v", err))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, fmt.Sprintf("已禁用用户 %s (手机号: %s),该用户需要重新登录", targetUser.Username, targetUser.Phone), nil)
|
|
|
|
|
|
}
|
2026-01-07 22:55:12 +08:00
|
|
|
|
|
|
|
|
|
|
// SaveQRCodeLogin 保存扫码登录的绑定信息
|
|
|
|
|
|
// 由Python后端调用,不需要认证
|
|
|
|
|
|
func (ctrl *EmployeeController) SaveQRCodeLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
EmployeeID int `json:"employee_id" binding:"required"`
|
|
|
|
|
|
CookiesFull []interface{} `json:"cookies_full"`
|
|
|
|
|
|
UserInfo map[string]interface{} `json:"user_info"`
|
|
|
|
|
|
LoginState map[string]interface{} `json:"login_state"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用service层直接保存,与验证码登录相同的逻辑
|
|
|
|
|
|
err := ctrl.service.SaveQRCodeLogin(req.EmployeeID, req.CookiesFull, req.UserInfo, req.LoginState)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "绑定成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-10 21:46:50 +08:00
|
|
|
|
// SaveLogin 保存验证码登录的绑定信息
|
|
|
|
|
|
func (ctrl *EmployeeController) SaveLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
EmployeeID int `json:"employee_id" binding:"required"`
|
|
|
|
|
|
CookiesFull []interface{} `json:"cookies_full"`
|
|
|
|
|
|
StorageState map[string]interface{} `json:"storage_state"`
|
|
|
|
|
|
StorageStatePath string `json:"storage_state_path"`
|
|
|
|
|
|
UserInfo map[string]interface{} `json:"user_info"` // 新增: 用户信息
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用service层保存
|
|
|
|
|
|
err := ctrl.service.SaveLogin(req.EmployeeID, req.CookiesFull, req.StorageState, req.StorageStatePath, req.UserInfo)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
common.SuccessWithMessage(c, "绑定成功", nil)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-07 22:55:12 +08:00
|
|
|
|
// StartQRCodeLogin 启动扫码登录,转发到Python服务
|
|
|
|
|
|
func (ctrl *EmployeeController) StartQRCodeLogin(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.StartQRCodeLogin(employeeID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 直接返回Python的响应格式,保持code=0
|
|
|
|
|
|
c.JSON(http.StatusOK, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetQRCodeStatus 获取扫码状态,转发到Python服务
|
|
|
|
|
|
func (ctrl *EmployeeController) GetQRCodeStatus(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
SessionID string `json:"session_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.GetQRCodeStatus(employeeID, req.SessionID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 直接返回Python的响应格式,保持code=0或code=2
|
|
|
|
|
|
c.JSON(http.StatusOK, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RefreshQRCode 刷新二维码,转发到Python服务
|
|
|
|
|
|
func (ctrl *EmployeeController) RefreshQRCode(c *gin.Context) {
|
|
|
|
|
|
employeeID := c.GetInt("employee_id")
|
|
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
SessionID string `json:"session_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.RefreshQRCode(employeeID, req.SessionID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 直接返回Python的响应格式,保持code=0或code=3
|
|
|
|
|
|
c.JSON(http.StatusOK, data)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CancelQRCodeLogin 取消扫码登录,释放浏览器资源
|
|
|
|
|
|
func (ctrl *EmployeeController) CancelQRCodeLogin(c *gin.Context) {
|
|
|
|
|
|
var req struct {
|
|
|
|
|
|
SessionID string `json:"session_id" binding:"required"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInvalidParams, "参数错误")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
data, err := ctrl.service.CancelQRCodeLogin(req.SessionID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
common.Error(c, common.CodeInternalError, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 直接返回Python的响应格式
|
|
|
|
|
|
c.JSON(http.StatusOK, data)
|
|
|
|
|
|
}
|