Files
ai_wht_wechat/go_backend/controller/employee_controller.go
2026-01-10 21:46:50 +08:00

889 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controller
import (
"ai_xhs/common"
"ai_xhs/database"
"ai_xhs/models"
"ai_xhs/service"
"ai_xhs/utils"
"bytes"
"context"
"encoding/base64"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
)
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
}
// 获取当前登录用户ID
employeeID := c.GetInt("employee_id")
data, err := ctrl.service.SendXHSCode(req.XHSPhone, employeeID)
if err != nil {
common.Error(c, common.CodeInternalError, err.Error())
return
}
// 检查是否需要扫码验证
if needCaptcha, ok := data["need_captcha"].(bool); ok && needCaptcha {
// 发送验证码时触发风控,返回二维码
common.SuccessWithMessage(c, "需要扫码验证", data)
return
}
common.SuccessWithMessage(c, "验证码已发送请在小红书APP中查看", data)
}
// 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,
"nickname": employee.Nickname,
"email": employee.Email,
"phone": employee.Phone,
"role": employee.Role,
"enterprise_id": employee.EnterpriseID,
"enterprise_name": employee.Enterprise.Name,
"avatar": employee.Icon,
"is_bound_xhs": employee.IsBoundXHS,
}
// 如果已绑定,从 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
}
common.Success(c, data)
}
// 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 绑定小红书账号(异步处理)
func (ctrl *EmployeeController) BindXHS(c *gin.Context) {
employeeID := c.GetInt("employee_id")
var req struct {
XHSPhone string `json:"xhs_phone" binding:"required"`
Code string `json:"code" binding:"required"`
SessionID string `json:"session_id"` // 发送验证码时返回的session_id用于复用浏览器
}
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, common.CodeInvalidParams, "参数错误")
return
}
_, err := ctrl.service.BindXHS(employeeID, req.XHSPhone, req.Code, req.SessionID)
if err != nil {
common.Error(c, common.CodeBindXHSFailed, err.Error())
return
}
// 立即返回成功,告知前端正在处理
common.SuccessWithMessage(c, "正在验证登录,请稍候...", map[string]interface{}{
"status": "processing",
})
}
// 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)
}
// 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) {
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)
if err != nil {
common.Error(c, common.CodeInternalError, err.Error())
return
}
common.Success(c, map[string]interface{}{
"list": data,
"has_more": hasMore,
})
}
// 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)
}
// 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(&currentUser).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)
}
// 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)
}
// 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)
}
// 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)
}