package services import ( "fmt" "server/models" "strings" "time" "github.com/beego/beego/v2/client/orm" ) // GetModuleName 根据module代码获取模块中文名称 // 首先从菜单表查询,如果找不到则使用默认映射 func GetModuleName(module string) string { if module == "" { return "" } // 从菜单表中查询:优先匹配 permission,其次尝试匹配 path 的最后一段(如 /system/dict -> dict) o := orm.NewOrm() var menuName string // 先尝试通过 permission 精准匹配 err := o.Raw( "SELECT name FROM yz_menus WHERE permission = ? AND delete_time IS NULL LIMIT 1", module, ).QueryRow(&menuName) if err == nil && menuName != "" { return menuName } // 再尝试通过 path 末段匹配(例如 /system/dict -> dict)或 path 包含该段 err = o.Raw( "SELECT name FROM yz_menus WHERE (path LIKE CONCAT('%/', ?, '/%') OR path LIKE CONCAT('%/', ?)) AND delete_time IS NULL LIMIT 1", module, module, ).QueryRow(&menuName) if err == nil && menuName != "" { return menuName } // 如果菜单表中找不到,使用默认映射 defaultMap := map[string]string{ "auth": "登录模块", "dict": "字典管理", "user": "用户管理", "role": "角色管理", "permission": "权限管理", "department": "部门管理", "employee": "员工管理", "position": "职位管理", "tenant": "租户管理", "system": "系统设置", "oa": "OA", "menu": "菜单管理", "knowledge": "知识库", } if name, exists := defaultMap[module]; exists { return name } return module } // GetModuleNames 批量获取模块名称,返回 module->name 映射 func GetModuleNames(modules []string) (map[string]string, error) { result := make(map[string]string) if len(modules) == 0 { return result, nil } o := orm.NewOrm() // 1. 尝试通过 permission 精准匹配 placeholders := make([]string, 0) args := make([]interface{}, 0) for _, m := range modules { if m == "" { continue } placeholders = append(placeholders, "?") args = append(args, m) } if len(args) > 0 { query := "SELECT permission, name FROM yz_menus WHERE permission IN (" + strings.Join(placeholders, ",") + ") AND delete_time IS NULL" rows := make([]struct { Permission string Name string }, 0) _, err := o.Raw(query, args...).QueryRows(&rows) if err == nil { for _, r := range rows { if r.Permission != "" { result[r.Permission] = r.Name } } } } // 2. 对于仍未匹配的模块,尝试通过 path 的末段进行模糊匹配 missing := make([]string, 0) for _, m := range modules { if m == "" { continue } if _, ok := result[m]; !ok { missing = append(missing, m) } } if len(missing) > 0 { // 使用 OR 组合 path LIKE '%/m' OR path LIKE '%/m/%' conds := make([]string, 0) args2 := make([]interface{}, 0) for _, m := range missing { conds = append(conds, "path LIKE ? OR path LIKE ?") args2 = append(args2, "%/"+m, "%/"+m+"/%") } query2 := "SELECT path, name FROM yz_menus WHERE (" + strings.Join(conds, " OR ") + ") AND delete_time IS NULL" rows2 := make([]struct { Path string Name string }, 0) _, err := o.Raw(query2, args2...).QueryRows(&rows2) if err == nil { for _, r := range rows2 { // extract last segment from path parts := strings.Split(strings.Trim(r.Path, "/"), "/") if len(parts) > 0 { key := parts[len(parts)-1] if key != "" { if _, exists := result[key]; !exists { result[key] = r.Name } } } } } } // 3. 对于仍然没有匹配的,使用默认映射 defaultMap := map[string]string{ "auth": "登录模块", "dict": "字典管理", "user": "用户管理", "role": "角色管理", "permission": "权限管理", "department": "部门管理", "employee": "员工管理", "position": "职位管理", "tenant": "租户管理", "system": "系统设置", "oa": "OA", "menu": "菜单管理", "knowledge": "知识库", } for _, m := range modules { if m == "" { continue } if _, exists := result[m]; !exists { if v, ok := defaultMap[m]; ok { result[m] = v } else { result[m] = m } } } return result, nil } // AddOperationLog 添加操作日志 func AddOperationLog(log *models.OperationLog) error { o := orm.NewOrm() log.CreateTime = time.Now() _, err := o.Insert(log) if err != nil { return fmt.Errorf("添加操作日志失败: %v", err) } return nil } // AddAccessLog 添加访问日志(用于记录 GET / READ 行为) func AddAccessLog(log *models.AccessLog) error { o := orm.NewOrm() log.CreateTime = time.Now() _, err := o.Insert(log) if err != nil { return fmt.Errorf("添加访问日志失败: %v", err) } return nil } // GetOperationLogs 获取操作日志列表 func GetOperationLogs(tenantId int, userId int, module string, operation string, startTime *time.Time, endTime *time.Time, pageNum int, pageSize int) ([]*models.OperationLog, int64, error) { o := orm.NewOrm() qs := o.QueryTable("sys_operation_log").Filter("tenant_id", tenantId) // 用户过滤 if userId > 0 { qs = qs.Filter("user_id", userId) } // 模块过滤 if module != "" { qs = qs.Filter("module", module) } // 操作类型过滤 if operation != "" { qs = qs.Filter("operation", operation) } // 时间范围过滤 if startTime != nil { qs = qs.Filter("create_time__gte", startTime) } if endTime != nil { qs = qs.Filter("create_time__lte", endTime) } // 获取总数 total, err := qs.Count() if err != nil { return nil, 0, fmt.Errorf("查询日志总数失败: %v", err) } // 分页查询 var logs []*models.OperationLog offset := (pageNum - 1) * pageSize _, err = qs.OrderBy("-create_time").Offset(offset).Limit(pageSize).All(&logs) if err != nil { return nil, 0, fmt.Errorf("查询操作日志失败: %v", err) } return logs, total, nil } // GetOperationLogById 根据ID获取操作日志 func GetOperationLogById(id int64) (*models.OperationLog, error) { o := orm.NewOrm() log := &models.OperationLog{Id: id} err := o.Read(log) if err != nil { return nil, fmt.Errorf("日志不存在: %v", err) } return log, nil } // GetUserOperationStats 获取用户操作统计 func GetUserOperationStats(tenantId int, userId int, days int) (map[string]interface{}, error) { o := orm.NewOrm() startTime := time.Now().AddDate(0, 0, -days) // 获取总操作数 var totalCount int64 err := o.Raw( "SELECT COUNT(*) FROM sys_operation_log WHERE tenant_id = ? AND user_id = ? AND create_time >= ?", tenantId, userId, startTime, ).QueryRow(&totalCount) if err != nil { return nil, err } // 获取按模块分组的操作数 type ModuleCount struct { Module string Count int } var moduleCounts []ModuleCount _, err = o.Raw( "SELECT module, COUNT(*) as count FROM sys_operation_log WHERE tenant_id = ? AND user_id = ? AND create_time >= ? GROUP BY module", tenantId, userId, startTime, ).QueryRows(&moduleCounts) if err != nil { return nil, err } // 构建结果 stats := map[string]interface{}{ "total_operations": totalCount, "module_stats": moduleCounts, "period_days": days, "from_time": startTime, "to_time": time.Now(), } return stats, nil } // GetTenantOperationStats 获取租户操作统计 func GetTenantOperationStats(tenantId int, days int) (map[string]interface{}, error) { o := orm.NewOrm() startTime := time.Now().AddDate(0, 0, -days) // 获取总操作数 var totalCount int64 err := o.Raw( "SELECT COUNT(*) FROM sys_operation_log WHERE tenant_id = ? AND create_time >= ?", tenantId, startTime, ).QueryRow(&totalCount) if err != nil { return nil, err } // 获取按用户分组的操作数(Top 10) type UserCount struct { UserId int Username string Count int } var userCounts []UserCount _, err = o.Raw( "SELECT user_id, username, COUNT(*) as count FROM sys_operation_log WHERE tenant_id = ? AND create_time >= ? GROUP BY user_id, username ORDER BY count DESC LIMIT 10", tenantId, startTime, ).QueryRows(&userCounts) if err != nil { return nil, err } // 获取按操作类型分组的操作数 type OperationCount struct { Operation string Count int } var operationCounts []OperationCount _, err = o.Raw( "SELECT operation, COUNT(*) as count FROM sys_operation_log WHERE tenant_id = ? AND create_time >= ? GROUP BY operation", tenantId, startTime, ).QueryRows(&operationCounts) if err != nil { return nil, err } // 构建结果 stats := map[string]interface{}{ "total_operations": totalCount, "top_users": userCounts, "operation_breakdown": operationCounts, "period_days": days, "from_time": startTime, "to_time": time.Now(), } return stats, nil } // DeleteOldLogs 删除旧日志(保留指定天数) func DeleteOldLogs(keepDays int) (int64, error) { o := orm.NewOrm() cutoffTime := time.Now().AddDate(0, 0, -keepDays) result, err := o.Raw("DELETE FROM sys_operation_log WHERE create_time < ?", cutoffTime).Exec() if err != nil { return 0, fmt.Errorf("删除旧日志失败: %v", err) } rowsAffected, err := result.RowsAffected() if err != nil { return 0, fmt.Errorf("获取受影响行数失败: %v", err) } return rowsAffected, nil } // GetAccessLogs 获取访问日志列表 func GetAccessLogs(tenantId int, userId int, module string, resourceType string, startTime *time.Time, endTime *time.Time, pageNum int, pageSize int) ([]*models.AccessLog, int64, error) { o := orm.NewOrm() qs := o.QueryTable("sys_access_log") // 租户过滤 if tenantId > 0 { qs = qs.Filter("tenant_id", tenantId) } // 用户过滤 if userId > 0 { qs = qs.Filter("user_id", userId) } // 模块过滤 if module != "" { qs = qs.Filter("module", module) } // 资源类型过滤 if resourceType != "" { qs = qs.Filter("resource_type", resourceType) } // 时间范围过滤 if startTime != nil { qs = qs.Filter("create_time__gte", startTime) } if endTime != nil { qs = qs.Filter("create_time__lte", endTime) } // 获取总数 total, err := qs.Count() if err != nil { return nil, 0, fmt.Errorf("查询日志总数失败: %v", err) } // 分页查询 var logs []*models.AccessLog offset := (pageNum - 1) * pageSize _, err = qs.OrderBy("-create_time").Offset(offset).Limit(pageSize).All(&logs) if err != nil { return nil, 0, fmt.Errorf("查询访问日志失败: %v", err) } return logs, total, nil } // GetAccessLogById 根据ID获取访问日志 func GetAccessLogById(id int64) (*models.AccessLog, error) { o := orm.NewOrm() log := &models.AccessLog{Id: id} err := o.Read(log) if err != nil { return nil, fmt.Errorf("日志不存在: %v", err) } return log, nil } // GetUserAccessStats 获取用户访问统计 func GetUserAccessStats(tenantId int, userId int, days int) (map[string]interface{}, error) { o := orm.NewOrm() startTime := time.Now().AddDate(0, 0, -days) // 获取总访问数 var totalCount int64 err := o.Raw( "SELECT COUNT(*) FROM sys_access_log WHERE tenant_id = ? AND user_id = ? AND create_time >= ?", tenantId, userId, startTime, ).QueryRow(&totalCount) if err != nil { return nil, err } // 获取按模块分组的访问数 type ModuleCount struct { Module string Count int } var moduleCounts []ModuleCount _, err = o.Raw( "SELECT module, COUNT(*) as count FROM sys_access_log WHERE tenant_id = ? AND user_id = ? AND create_time >= ? GROUP BY module", tenantId, userId, startTime, ).QueryRows(&moduleCounts) if err != nil { return nil, err } // 获取按状态分组的访问数 type StatusCount struct { Status int Count int } var statusCounts []StatusCount _, err = o.Raw( "SELECT status, COUNT(*) as count FROM sys_access_log WHERE tenant_id = ? AND user_id = ? AND create_time >= ? GROUP BY status", tenantId, userId, startTime, ).QueryRows(&statusCounts) if err != nil { return nil, err } // 构建结果 stats := map[string]interface{}{ "total_access": totalCount, "module_stats": moduleCounts, "status_stats": statusCounts, "period_days": days, "from_time": startTime, "to_time": time.Now(), } return stats, nil } // ClearOldAccessLogs 清除旧访问日志(保留指定天数) func ClearOldAccessLogs(keepDays int) (int64, error) { o := orm.NewOrm() cutoffTime := time.Now().AddDate(0, 0, -keepDays) result, err := o.Raw("DELETE FROM sys_access_log WHERE create_time < ?", cutoffTime).Exec() if err != nil { return 0, fmt.Errorf("删除旧访问日志失败: %v", err) } rowsAffected, err := result.RowsAffected() if err != nil { return 0, fmt.Errorf("获取受影响行数失败: %v", err) } return rowsAffected, nil }