370 lines
9.2 KiB
Go
370 lines
9.2 KiB
Go
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
|
||
}
|