179 lines
4.0 KiB
Go
179 lines
4.0 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"server/models"
|
|
"server/pkg/jwtutil"
|
|
"strings"
|
|
|
|
"github.com/beego/beego/v2/client/orm"
|
|
beego "github.com/beego/beego/v2/server/web"
|
|
)
|
|
|
|
type AppActivityController struct {
|
|
beego.Controller
|
|
}
|
|
|
|
func (c *AppActivityController) activityClaims() (*jwtutil.Claims, error) {
|
|
auth := c.Ctx.Request.Header.Get("Authorization")
|
|
if auth == "" {
|
|
return nil, orm.ErrNoRows
|
|
}
|
|
parts := strings.SplitN(auth, " ", 2)
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
return nil, orm.ErrNoRows
|
|
}
|
|
claims, err := jwtutil.ParseToken(parts[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if claims.UserType != "backend" && claims.UserType != "app" && claims.UserType != "platform" {
|
|
return nil, orm.ErrNoRows
|
|
}
|
|
return claims, nil
|
|
}
|
|
|
|
// GetList GET /app/activity/list
|
|
func (c *AppActivityController) GetList() {
|
|
claims, err := c.activityClaims()
|
|
if err != nil {
|
|
c.Ctx.Output.SetStatus(401)
|
|
c.Data["json"] = map[string]interface{}{"code": 401, "msg": "未登录"}
|
|
_ = c.ServeJSON()
|
|
return
|
|
}
|
|
|
|
limit, _ := c.GetInt("limit", 10)
|
|
if limit < 1 || limit > 50 {
|
|
limit = 10
|
|
}
|
|
|
|
var logs []models.SystemOperationLog
|
|
qs := models.Orm.QueryTable(new(models.SystemOperationLog)).
|
|
Filter("user_id", claims.UserID).
|
|
Exclude("action__in", "登录", "退出", "查询").
|
|
OrderBy("-create_time").
|
|
Limit(limit)
|
|
_, err = qs.All(&logs)
|
|
if err != nil && err != orm.ErrNoRows {
|
|
c.Ctx.Output.SetStatus(500)
|
|
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "查询失败"}
|
|
_ = c.ServeJSON()
|
|
return
|
|
}
|
|
|
|
type activityItem struct {
|
|
ID uint64 `json:"id"`
|
|
Action string `json:"action"`
|
|
TargetType string `json:"target_type"`
|
|
Title string `json:"title"`
|
|
URL string `json:"url"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
list := make([]activityItem, 0, len(logs))
|
|
for _, l := range logs {
|
|
module := l.Module
|
|
action := l.Action
|
|
|
|
// 从请求体中提取标题
|
|
title := extractTitle(l.Module, l.Action, l.RequestData)
|
|
if title == "" {
|
|
title = fmt.Sprintf("您%s了:%s", actionLabel(action), moduleLabel(module))
|
|
}
|
|
|
|
list = append(list, activityItem{
|
|
ID: l.ID,
|
|
Action: action,
|
|
TargetType: module,
|
|
Title: title,
|
|
URL: l.URL,
|
|
CreatedAt: l.CreateTime.Format("2006-01-02 15:04:05"),
|
|
})
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": list}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// extractTitle 从请求数据中提取可读标题
|
|
func extractTitle(module, action string, reqData *string) string {
|
|
if reqData == nil {
|
|
return ""
|
|
}
|
|
data := strings.TrimSpace(*reqData)
|
|
if data == "" {
|
|
return ""
|
|
}
|
|
|
|
// 解析 JSON 请求体
|
|
var body map[string]interface{}
|
|
if err := json.Unmarshal([]byte(data), &body); err != nil {
|
|
return ""
|
|
}
|
|
|
|
moduleCN := moduleLabel(module)
|
|
actionCN := actionLabel(action)
|
|
|
|
// 笔记本:取 title
|
|
if module == "notebook" {
|
|
if t, ok := body["title"].(string); ok && t != "" {
|
|
return fmt.Sprintf("您%s了%s:【%s】", actionCN, moduleCN, truncateStr(t, 20))
|
|
}
|
|
}
|
|
|
|
// 日程:取 content 第一行
|
|
if module == "schedule" {
|
|
if c, ok := body["content"].(string); ok && c != "" {
|
|
firstLine := strings.SplitN(c, "\n", 2)[0]
|
|
return fmt.Sprintf("您%s了%s:【%s】", actionCN, moduleCN, truncateStr(firstLine, 20))
|
|
}
|
|
}
|
|
|
|
return fmt.Sprintf("您%s了:%s", actionCN, moduleCN)
|
|
}
|
|
|
|
func truncateStr(s string, maxLen int) string {
|
|
s = strings.TrimSpace(s)
|
|
if len([]rune(s)) > maxLen {
|
|
return string([]rune(s)[:maxLen]) + "..."
|
|
}
|
|
return s
|
|
}
|
|
|
|
func moduleLabel(m string) string {
|
|
switch m {
|
|
case "notebook":
|
|
return "记事本"
|
|
case "schedule":
|
|
return "日程提醒"
|
|
case "erp":
|
|
return "ERP"
|
|
case "file":
|
|
return "文件"
|
|
case "article":
|
|
return "文章"
|
|
default:
|
|
if m == "" {
|
|
return "系统"
|
|
}
|
|
return m
|
|
}
|
|
}
|
|
|
|
func actionLabel(a string) string {
|
|
switch a {
|
|
case "新增":
|
|
return "新增"
|
|
case "编辑":
|
|
return "编辑"
|
|
case "删除":
|
|
return "删除"
|
|
case "提交":
|
|
return "操作"
|
|
default:
|
|
return a
|
|
}
|
|
}
|