package controllers import ( "encoding/json" "strings" "time" "server/models" "github.com/beego/beego/v2/client/orm" beego "github.com/beego/beego/v2/server/web" ) // ApiCursorEquipmentController 开放接口:登录器上报 Cursor 设备信息(无需登录) type ApiCursorEquipmentController struct { beego.Controller } type cursorEquipmentReportPayload struct { DeviceInfo string `json:"deviceInfo"` DeviceInfoSnake string `json:"device_info"` MachineCode string `json:"machineCode"` MachineCodeSnake string `json:"machine_code"` Status *int8 `json:"status"` System string `json:"system"` Version string `json:"version"` BindAccount string `json:"bindAccount"` BindAccountSnake string `json:"bind_account"` OwnerUserID *uint64 `json:"ownerUserId"` OwnerUserIDSnake *uint64 `json:"owner_user_id"` OwnerUserName string `json:"ownerUserName"` OwnerUserNameSnake string `json:"owner_user_name"` ActivationTime string `json:"activationTime"` ActivationTimeSnake string `json:"activation_time"` ExpireTime string `json:"expireTime"` ExpireTimeSnake string `json:"expire_time"` Remark string `json:"remark"` } func cursorFirstNonEmpty(values ...string) string { for _, v := range values { if s := strings.TrimSpace(v); s != "" { return s } } return "" } func cursorStringPtr(value string) *string { value = strings.TrimSpace(value) if value == "" { return nil } return &value } func cursorParseTimePtr(value string) *time.Time { value = strings.TrimSpace(value) if value == "" { return nil } layouts := []string{ time.RFC3339, "2006-01-02 15:04:05", "2006-01-02 15:04", "2006-01-02", } for _, layout := range layouts { if t, err := time.ParseInLocation(layout, value, time.Local); err == nil { return &t } } return nil } func cursorValidStatus(status int8) bool { return status == 0 || status == 1 || status == 2 || status == 3 } func (c *ApiCursorEquipmentController) jsonResult(code int, msg string, data interface{}) { resp := map[string]interface{}{"code": code, "msg": msg} if data != nil { resp["data"] = data } c.Data["json"] = resp _ = c.ServeJSON() } // Report POST /api/cursor/equipment/report // // JSON 示例: // // { // "machineCode": "ABC-123", // "deviceInfo": "CPU/RAM/磁盘等设备信息", // "system": "Windows", // "version": "1.0.0", // "bindAccount": "user@example.com", // "ownerUserId": 1, // "ownerUserName": "张三", // "activationTime": "2026-06-15 22:00:00", // "expireTime": "2026-07-15 22:00:00", // "remark": "登录器上报" // } // // 兼容 snake_case 字段,例如 machine_code、device_info、bind_account。 func (c *ApiCursorEquipmentController) Report() { var p cursorEquipmentReportPayload if err := json.Unmarshal(c.Ctx.Input.RequestBody, &p); err != nil { c.jsonResult(400, "参数错误", nil) return } machineCode := cursorFirstNonEmpty(p.MachineCode, p.MachineCodeSnake) if machineCode == "" { c.jsonResult(400, "缺少参数 machineCode/machine_code(机器码)", nil) return } if len(machineCode) > 128 { c.jsonResult(400, "机器码长度不能超过 128 个字符", nil) return } status := int8(0) statusProvided := p.Status != nil if statusProvided { status = *p.Status if !cursorValidStatus(status) { c.jsonResult(400, "状态不合法,支持:0 未激活、1 激活中、2 已过期、3 已禁用", nil) return } } deviceInfo := cursorFirstNonEmpty(p.DeviceInfo, p.DeviceInfoSnake) system := cursorFirstNonEmpty(p.System) version := cursorFirstNonEmpty(p.Version) bindAccount := cursorFirstNonEmpty(p.BindAccount, p.BindAccountSnake) ownerUserID := p.OwnerUserID if ownerUserID == nil { ownerUserID = p.OwnerUserIDSnake } ownerUserName := cursorFirstNonEmpty(p.OwnerUserName, p.OwnerUserNameSnake) activationTime := cursorParseTimePtr(cursorFirstNonEmpty(p.ActivationTime, p.ActivationTimeSnake)) expireTime := cursorParseTimePtr(cursorFirstNonEmpty(p.ExpireTime, p.ExpireTimeSnake)) remark := cursorFirstNonEmpty(p.Remark) now := time.Now() var row models.PlatformCursorEquipment err := models.Orm.QueryTable(new(models.PlatformCursorEquipment)). Filter("machine_code", machineCode). Filter("delete_time__isnull", true). One(&row) created := false if err == orm.ErrNoRows { row = models.PlatformCursorEquipment{ MachineCode: machineCode, Status: status, DeviceInfo: cursorStringPtr(deviceInfo), System: cursorStringPtr(system), Version: cursorStringPtr(version), BindAccount: cursorStringPtr(bindAccount), OwnerUserID: ownerUserID, OwnerUserName: cursorStringPtr(ownerUserName), ActivationTime: activationTime, ExpireTime: expireTime, Remark: cursorStringPtr(remark), CreateTime: now, } id, insertErr := models.Orm.Insert(&row) if insertErr != nil { c.jsonResult(500, "设备信息保存失败", nil) return } row.ID = uint64(id) created = true } else if err != nil { c.jsonResult(500, "设备信息查询失败", nil) return } else { update := map[string]interface{}{ "device_info": cursorStringPtr(deviceInfo), "system": cursorStringPtr(system), "version": cursorStringPtr(version), "bind_account": cursorStringPtr(bindAccount), "owner_user_id": ownerUserID, "owner_user_name": cursorStringPtr(ownerUserName), "activation_time": activationTime, "expire_time": expireTime, "remark": cursorStringPtr(remark), "update_time": now, } if statusProvided { update["status"] = status row.Status = status } if _, updateErr := models.Orm.QueryTable(new(models.PlatformCursorEquipment)). Filter("id", row.ID). Update(update); updateErr != nil { c.jsonResult(500, "设备信息更新失败", nil) return } row.DeviceInfo = cursorStringPtr(deviceInfo) row.System = cursorStringPtr(system) row.Version = cursorStringPtr(version) row.BindAccount = cursorStringPtr(bindAccount) row.OwnerUserID = ownerUserID row.OwnerUserName = cursorStringPtr(ownerUserName) row.ActivationTime = activationTime row.ExpireTime = expireTime row.Remark = cursorStringPtr(remark) row.UpdateTime = &now } c.jsonResult(200, "success", map[string]interface{}{ "id": row.ID, "machineCode": row.MachineCode, "status": row.Status, "created": created, }) }