package controllers import ( "ERP_salary/Nats/NatsServer" "ERP_salary/conf" "ERP_salary/dto" "ERP_salary/logs" "ERP_salary/models/Account" "ERP_salary/models/Performance" "ERP_salary/services" "encoding/json" "fmt" "io" "math" "net/http" "net/url" "strconv" "strings" "time" "github.com/robfig/cron/v3" "github.com/xuri/excelize/v2" beego "github.com/beego/beego/v2/server/web" userlibs "gogs.baozhida.cn/zoie/ERP_libs/User" "gogs.baozhida.cn/zoie/ERP_libs/lib" ) type PerformanceController struct { beego.Controller User userlibs.User } // calculateTotalScore 计算总得分百分比 func calculateTotalScore(perf Performance.Perf) float64 { if perf.T_assess_points == 0 { return 0 } return (perf.T_workload / float64(perf.T_assess_points)) * 100 } // calculatePerfTotal 计算应发绩效 func calculatePerfTotal(perf Performance.Perf) float64 { score := calculateTotalScore(perf) if score >= 100 { return perf.T_perf } return (score / 100) * perf.T_perf } func (c *PerformanceController) Prepare() { c.User = *Account.User_r } func (c *PerformanceController) Points_List() { s := services.PerformancePoints{} reqData := dto.PerformancePointsPageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } R_List, R_cnt := s.GetPage(&reqData) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = reqData.Page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *PerformanceController) Points_Add() { s := services.PerformancePoints{} reqData := dto.PerformancePointsInsertReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } Id, err := s.Insert(&reqData) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "添加", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id} c.ServeJSON() return } func (c *PerformanceController) Points_Edit() { s := services.PerformancePoints{} reqData := dto.PerformancePointsUpdateReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Update(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "修改", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *PerformanceController) Points_Del() { s := services.PerformancePoints{} reqData := dto.PerformancePointsDeleteReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Delete(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "删除", strconv.Itoa(reqData.T_id)) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *PerformanceController) Target_List() { s := services.PerformanceTarget{} reqData := dto.PerformanceTargetPageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } R_List, R_cnt := s.GetPage(&reqData) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = reqData.Page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *PerformanceController) Target_Add() { s := services.PerformanceTarget{} reqData := dto.PerformanceTargetInsertReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } Id, err := s.Insert(&reqData) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "添加", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id} c.ServeJSON() return } func (c *PerformanceController) Target_Edit() { s := services.PerformanceTarget{} reqData := dto.PerformanceTargetUpdateReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Update(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "修改", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *PerformanceController) Target_Del() { s := services.PerformanceTarget{} reqData := dto.PerformanceTargetDeleteReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Delete(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "删除", strconv.Itoa(reqData.T_id)) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } // 绩效-用户 func (c *PerformanceController) List() { s := services.Performance{} reqData := dto.PerformancePageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) R_List, R_cnt := s.GetManagerPage(&reqData) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = reqData.Page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *PerformanceController) Excel() { s := services.Performance{} reqData := dto.PerformancePageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } reqData.PageSize = 9999 userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) R_List, R_cnt := s.GetManagerPage(&reqData) // 创建Excel文件 f := excelize.NewFile() defer func() { if err := f.Close(); err != nil { logs.Error("关闭Excel文件失败: %s", err) } }() // 设置工作表名称 sheetName := "绩效管理" index, err := f.NewSheet(sheetName) if err != nil { logs.Error("创建工作表失败: %s", err) c.Data["json"] = lib.JSONS{Code: 500, Msg: "创建Excel文件失败"} c.ServeJSON() return } f.SetActiveSheet(index) // 设置表头 headers := []string{"序号", "姓名", "工资级别", "绩效工资(元)", "所属月份", "工作量", "考核工作量", "得分", "应发绩效"} for i, header := range headers { cell := fmt.Sprintf("%c1", 'A'+i) f.SetCellValue(sheetName, cell, header) } // 设置表头样式 headerStyle, err := f.NewStyle(&excelize.Style{ Font: &excelize.Font{ Bold: true, }, Alignment: &excelize.Alignment{ Horizontal: "center", Vertical: "center", }, Fill: excelize.Fill{ Type: "pattern", Color: []string{"#E6F3FF"}, Pattern: 1, }, }) if err == nil { f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), headerStyle) } // 填充数据 for i, perf := range R_List { row := i + 2 // 从第2行开始(第1行是表头) // 序号 f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), i+1) // 姓名 f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), perf.T_submit_name) // 工资级别 f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), perf.Target.T_name) // 绩效工资(元) f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), perf.T_perf) // 所属月份 f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), perf.T_date) // 工作量 f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), perf.T_workload) // 考核工作量 f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), perf.T_assess_points) // 得分 score := calculateTotalScore(perf) f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("%.1f%%", score)) // 应发绩效 perfTotal := calculatePerfTotal(perf) f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), fmt.Sprintf("%.2f", perfTotal)) } // 设置列宽 f.SetColWidth(sheetName, "A", "A", 8) // 序号 f.SetColWidth(sheetName, "B", "B", 12) // 姓名 f.SetColWidth(sheetName, "C", "C", 12) // 工资级别 f.SetColWidth(sheetName, "D", "D", 15) // 绩效工资(元) f.SetColWidth(sheetName, "E", "E", 12) // 所属月份 f.SetColWidth(sheetName, "F", "F", 12) // 工作量 f.SetColWidth(sheetName, "G", "G", 15) // 考核工作量 f.SetColWidth(sheetName, "H", "H", 12) // 得分 f.SetColWidth(sheetName, "I", "I", 15) // 应发绩效 // 设置数据区域样式 dataStyle, err := f.NewStyle(&excelize.Style{ Alignment: &excelize.Alignment{ Horizontal: "center", Vertical: "center", }, Border: []excelize.Border{ {Type: "left", Color: "CCCCCC", Style: 1}, {Type: "top", Color: "CCCCCC", Style: 1}, {Type: "bottom", Color: "CCCCCC", Style: 1}, {Type: "right", Color: "CCCCCC", Style: 1}, }, }) if err == nil && len(R_List) > 0 { f.SetCellStyle(sheetName, "A2", fmt.Sprintf("I%d", len(R_List)+1), dataStyle) } // 生成文件名 fileName := fmt.Sprintf("绩效管理_%s.xlsx", time.Now().Format("20060102_150405")) // 设置响应头 c.Ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) c.Ctx.Output.Header("Content-Transfer-Encoding", "binary") // 写入响应 if err := f.Write(c.Ctx.ResponseWriter); err != nil { logs.Error("写入Excel文件失败: %s", err) c.Data["json"] = lib.JSONS{Code: 500, Msg: "导出Excel失败"} c.ServeJSON() return } logs.Println(fmt.Sprintf("成功导出绩效管理Excel文件,共%d条记录", R_cnt)) } func (c *PerformanceController) User_List() { s := services.Performance{} reqData := dto.PerformanceUserPageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) reqData.T_submit = c.User.T_uuid R_List, R_cnt := s.GetPage(&reqData) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = reqData.Page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *PerformanceController) User_Excel() { s := services.Performance{} reqData := dto.PerformanceUserPageReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } reqData.PageSize = 9999 reqData.T_submit = c.User.T_uuid userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) R_List, R_cnt := s.GetPage(&reqData) // 创建Excel文件 f := excelize.NewFile() defer func() { if err := f.Close(); err != nil { logs.Error("关闭Excel文件失败: %s", err) } }() // 设置工作表名称 sheetName := "绩效管理" index, err := f.NewSheet(sheetName) if err != nil { logs.Error("创建工作表失败: %s", err) c.Data["json"] = lib.JSONS{Code: 500, Msg: "创建Excel文件失败"} c.ServeJSON() return } f.SetActiveSheet(index) // 设置表头 headers := []string{"序号", "姓名", "工资级别", "绩效工资(元)", "所属月份", "工作量", "考核工作量", "得分", "应发绩效"} for i, header := range headers { cell := fmt.Sprintf("%c1", 'A'+i) f.SetCellValue(sheetName, cell, header) } // 设置表头样式 headerStyle, err := f.NewStyle(&excelize.Style{ Font: &excelize.Font{ Bold: true, }, Alignment: &excelize.Alignment{ Horizontal: "center", Vertical: "center", }, Fill: excelize.Fill{ Type: "pattern", Color: []string{"#E6F3FF"}, Pattern: 1, }, }) if err == nil { f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), headerStyle) } // 填充数据 for i, perf := range R_List { row := i + 2 // 从第2行开始(第1行是表头) // 序号 f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), i+1) // 姓名 f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), perf.T_submit_name) // 工资级别 f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), perf.Target.T_name) // 绩效工资(元) f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), perf.T_perf) // 所属月份 f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), perf.T_date) // 工作量 f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), perf.T_workload) // 考核工作量 f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), perf.T_assess_points) // 得分 score := calculateTotalScore(perf) f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("%.1f%%", score)) // 应发绩效 perfTotal := calculatePerfTotal(perf) f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), fmt.Sprintf("%.2f", perfTotal)) } // 设置列宽 f.SetColWidth(sheetName, "A", "A", 8) // 序号 f.SetColWidth(sheetName, "B", "B", 12) // 姓名 f.SetColWidth(sheetName, "C", "C", 12) // 工资级别 f.SetColWidth(sheetName, "D", "D", 15) // 绩效工资(元) f.SetColWidth(sheetName, "E", "E", 12) // 所属月份 f.SetColWidth(sheetName, "F", "F", 12) // 工作量 f.SetColWidth(sheetName, "G", "G", 15) // 考核工作量 f.SetColWidth(sheetName, "H", "H", 12) // 得分 f.SetColWidth(sheetName, "I", "I", 15) // 应发绩效 // 设置数据区域样式 dataStyle, err := f.NewStyle(&excelize.Style{ Alignment: &excelize.Alignment{ Horizontal: "center", Vertical: "center", }, Border: []excelize.Border{ {Type: "left", Color: "CCCCCC", Style: 1}, {Type: "top", Color: "CCCCCC", Style: 1}, {Type: "bottom", Color: "CCCCCC", Style: 1}, {Type: "right", Color: "CCCCCC", Style: 1}, }, }) if err == nil && len(R_List) > 0 { f.SetCellStyle(sheetName, "A2", fmt.Sprintf("I%d", len(R_List)+1), dataStyle) } // 生成文件名 fileName := fmt.Sprintf("绩效管理_%s.xlsx", time.Now().Format("20060102_150405")) // 设置响应头 c.Ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) c.Ctx.Output.Header("Content-Transfer-Encoding", "binary") // 写入响应 if err := f.Write(c.Ctx.ResponseWriter); err != nil { logs.Error("写入Excel文件失败: %s", err) c.Data["json"] = lib.JSONS{Code: 500, Msg: "导出Excel失败"} c.ServeJSON() return } logs.Println(fmt.Sprintf("成功导出绩效管理Excel文件,共%d条记录", R_cnt)) } func (c *PerformanceController) Submit_User() { s := services.Performance{} page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) uuidList := s.GetSubmitUserPage() R_List, R_cnt, err := NatsServer.Read_User_List_T_uuid(T_name, uuidList, page, page_z) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败"} c.ServeJSON() return } var U_List []userlibs.User for _, user := range R_List { U_List = append(U_List, user) } var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = U_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *PerformanceController) Add() { s := services.Performance{} reqData := dto.PerformanceInsertReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := json.Unmarshal([]byte(reqData.Points), &reqData.PointList); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细 参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } reqData.T_submit = c.User.T_uuid // 如传入绩效点,则校验非空 if len(reqData.PointList) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细不能为空"} c.ServeJSON() return } Id, err := s.Insert(&reqData) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "添加", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id} c.ServeJSON() return } func (c *PerformanceController) Edit() { s := services.Performance{} reqData := dto.PerformanceUpdateReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := json.Unmarshal([]byte(reqData.Points), &reqData.PointList); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细 参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Update(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "修改", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *PerformanceController) Edit_Audit() { s := services.Performance{} reqData := dto.PerformanceUpdateAuditReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.UpdateAudit(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "修改状态", reqData) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *PerformanceController) Del() { s := services.Performance{} reqData := dto.PerformanceDeleteReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if err := Validate(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } if err := s.Delete(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "删除", strconv.Itoa(reqData.T_id)) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } // GetPerformanceDetail 根据ID获取绩效详情 func (c *PerformanceController) GetPerformanceDetail() { s := services.Performance{} reqData := dto.PerformanceGetReq{} if err := c.ParseForm(&reqData); err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"} c.ServeJSON() return } if reqData.T_id <= 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "ID参数无效"} c.ServeJSON() return } perf, err := s.Get(reqData) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取绩效详情失败: " + err.Error()} c.ServeJSON() return } // 获取关联的绩效点详情 pointList, err := s.GetPerfPointsByPerfId(reqData.T_id) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取绩效点详情失败: " + err.Error()} c.ServeJSON() return } // 组装返回数据 result := map[string]interface{}{ "perf": perf, "pointList": pointList, } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: result} c.ServeJSON() return } func Cron_Percentage() { time.Sleep(10 * time.Second) // 等待10秒,确保数据库初始化完成 //创建一个定时任务对象 c := cron.New(cron.WithSeconds()) //给对象增加定时任务 - 测试用:每分钟执行一次 c.AddFunc("0 0 1 * *", SyncVerifyPercentage) // 生产环境:每月1日凌晨0点0分执行 //启动定时任务 c.Start() defer c.Stop() //查询语句,阻塞,让main函数不退出,保持程序运行 select {} } // VerifyTaskResponse 冷链验证任务响应结构 type VerifyTaskResponse struct { Data []Performance.VerifyTask Code int64 Msg string } // buildVerifyRequest 构建冷链验证请求并处理响应 func GetTaskList(startTime, endTime, requestType string) (*VerifyTaskResponse, error) { urls := "/openapi/task/list2" signature, timestamp := lib.GenColdVerifySignature() // 使用标准HTTP库替换resty formData := url.Values{} formData.Set("T_start_time", startTime) formData.Set("T_end_time", endTime) formData.Set("T_type", requestType) formData.Set("X-API-KEY", lib.ColdVerify_OpenApi_Key) formData.Set("X-API-SIGNATURE", signature) formData.Set("X-API-TIMESTAMP", timestamp) // 构建完整URL fullURL := conf.ColdVerify_OpenApi_Host + urls // 创建POST请求 req, err := http.NewRequest("POST", fullURL, strings.NewReader(formData.Encode())) if err != nil { logs.Error("创建HTTP请求失败: %v", err) return nil, err } // 设置请求头 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") // 创建HTTP客户端 client := &http.Client{ Timeout: 30 * time.Second, } // 发送请求 resp, err := client.Do(req) if err != nil { logs.Error("请求冷链验证任务列表接口失败: %v", err) return nil, err } defer resp.Body.Close() // 读取响应体 body, err := io.ReadAll(resp.Body) if err != nil { logs.Error("读取响应体失败: %v", err) return nil, err } // 检查响应状态码 if resp.StatusCode != http.StatusOK { logs.Error("请求冷链验证任务列表接口失败,状态码: %d", resp.StatusCode) return nil, fmt.Errorf("请求失败,状态码: %d", resp.StatusCode) } // 解析响应 var res VerifyTaskResponse if err = json.Unmarshal(body, &res); err != nil { logs.Error("解析响应数据失败: %v", err) return nil, err } return &res, nil } // processWorkloadStats 处理工作量统计逻辑 func processWorkloadStats(res *VerifyTaskResponse, workType string) map[string]map[int]int { pointsMap := GetPerformancePointsMap() coldVerifyUUIDMap := GetColdVerifyUUIDMap() // 创建统计映射 stat := map[string]map[int]int{} // 遍历所有任务,统计指定类型的工作量 for _, task := range res.Data { verifyItem := GetPerformancePoints(Performance.DeviceTypeMap[task.T_device_type], task.T_verify_type, pointsMap) if verifyItem.Id == 0 { continue } var userUUID string if workType == "reporting" { // 报告编写人员统计 userUUID = coldVerifyUUIDMap[task.T_reporting] } else if workType == "collection" { // 数据采集人员统计 userUUID = coldVerifyUUIDMap[task.T_collection] } if userUUID != "" { updateWorkloadStat(stat, userUUID, verifyItem.Id) } } return stat } func SyncVerifyPercentage() { // 构建请求数据 start_time := lib.GetFirstDayOfLastMonth() + " 00:00:00" end_time := lib.GetLastDayOfLastMonth() + " 23:59:59" // 请求报告编写类型的数据 reportingRes, err := GetTaskList(start_time, end_time, "reporting") if err != nil { logs.Error("请求报告编写任务列表失败: %v", err) return } // 请求数据采集类型的数据 collectionRes, err := GetTaskList(start_time, end_time, "collection") if err != nil { logs.Error("请求数据采集任务列表失败: %v", err) return } // 初始化绩效目标 Performance.Read_PerformanceTarget_All_Map() userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) // 处理报告编写人员统计 reportingStat := processWorkloadStats(reportingRes, "reporting") // 处理数据采集人员统计 collectionStat := processWorkloadStats(collectionRes, "collection") // 保存统计结果到数据库 saveReportingStatsToDB(reportingStat, "reporting") saveCollectionStatsToDB(collectionStat, "collection") } // updateWorkloadStat 更新工作量统计的辅助函数 func updateWorkloadStat(stat map[string]map[int]int, userUUID string, pointID int) { // 如果UUID为空则跳过 if userUUID == "" { return } // 初始化用户映射表 if stat[userUUID] == nil { stat[userUUID] = make(map[int]int) } // 增加工作量计数 stat[userUUID][pointID]++ } // saveReportingStatsToDB 保存报告编写人员统计结果到数据库 func saveReportingStatsToDB(stat map[string]map[int]int, workType string) { s := services.Performance{} // 获取当前日期(用于T_date字段) currentDate := time.Now().Format("2006-01") // 遍历统计结果并保存到数据库 for userUUID, points := range stat { // 计算总工作量 totalWorkload := 0.0 totalPoints := 0 // 总绩效点 // 收集所有绩效点信息用于创建PerfPoint列表 var pointList []Performance.PerfPoint for pointID, count := range points { // 获取绩效点信息以计算工作量 pointsInfo := getPerformancePointsInfo(pointID) if pointsInfo.Id > 0 { // 计算工作量:T_points_numerator/T_points_denominator*统计出来的工作量 workload := float64(pointsInfo.T_points_numerator) / float64(pointsInfo.T_points_denominator) * float64(count) totalWorkload += workload // 累计总绩效点和总数量 totalPoints += pointsInfo.T_points_numerator // 创建绩效点记录 point := Performance.PerfPoint{ T_performance_points_id: pointID, T_quantity: count, T_points_numerator: pointsInfo.T_points_numerator, T_points_denominator: pointsInfo.T_points_denominator, T_type: workType, } pointList = append(pointList, point) } } User := Account.Read_User_Get(userUUID) target := Performance.Read_PerformanceTarget_Get(User.T_verify_perf_target) // 创建Perf记录 perf := Performance.Perf{ T_date: currentDate, T_submit: userUUID, T_workload: totalWorkload, T_audit: 1, // 待提交状态 T_State: 1, // 正常状态 T_assess_points: target.T_assess_points, // 考核绩效点 T_perf: target.T_perf, // 考核绩效点 T_performance_target_id: target.Id, // 考核绩效点 } // 保存到数据库 _, err := s.InsertFromStats(&perf, pointList) if err != nil { logs.Error("保存报告编写人员统计结果失败: %v", err) } else { logs.Info("成功保存报告编写人员 %s 的统计结果", userUUID) } } } // saveCollectionStatsToDB 保存数据采集人员统计结果到数据库 func saveCollectionStatsToDB(stat map[string]map[int]int, workType string) { s := services.Performance{} // 获取当前日期(用于T_date字段) currentDate := time.Now().AddDate(0, -1, 0).Format("2006-01") // 遍历统计结果并保存到数据库 for userUUID, points := range stat { // 计算总工作量 totalWorkload := 0.0 totalPoints := 0 // 总绩效点 totalCount := 0 // 总数量 // 收集所有绩效点信息用于创建PerfPoint列表 var pointList []Performance.PerfPoint for pointID, count := range points { // 获取绩效点信息以计算工作量 pointsInfo := getPerformancePointsInfo(pointID) if pointsInfo.Id > 0 { // 计算工作量:T_points_numerator/T_points_denominator*统计出来的工作量 workload := float64(pointsInfo.T_points_numerator) / float64(pointsInfo.T_points_denominator) * float64(count) totalWorkload += workload // 累计总绩效点和总数量 totalPoints += pointsInfo.T_points_numerator totalCount += count // 创建绩效点记录 point := Performance.PerfPoint{ T_performance_points_id: pointID, T_quantity: count, T_points_numerator: pointsInfo.T_points_numerator, T_points_denominator: pointsInfo.T_points_denominator, T_type: workType, } pointList = append(pointList, point) } } User := Account.Read_User_Get(userUUID) target := Performance.Read_PerformanceTarget_Get(User.T_verify_perf_target) // 创建Perf记录 perf := Performance.Perf{ T_date: currentDate, T_submit: userUUID, T_workload: totalWorkload, T_audit: 1, // 待提交状态 T_State: 1, // 正常状态 T_assess_points: target.T_assess_points, // 考核绩效点 T_perf: target.T_perf, // 考核绩效 T_performance_target_id: target.Id, // 工资级别id } // 保存到数据库 _, err := s.InsertFromStats(&perf, pointList) if err != nil { logs.Error("保存数据采集人员统计结果失败: %v", err) } else { logs.Info(fmt.Sprintf("成功保存数据采集人员 %s 的统计结果", userUUID)) } } } // getPerformancePointsInfo 获取绩效点信息 func getPerformancePointsInfo(pointID int) Performance.PerformancePoints { s := services.PerformancePoints{} points, err := s.Get(pointID) if err != nil { logs.Error("获取绩效点信息失败: %v", err) return Performance.PerformancePoints{} } return points } func GetPerformancePointsMap() map[string]Performance.PerformancePoints { s := services.PerformancePoints{} reqData := dto.PerformancePointsPageReq{} reqData.PageSize = 9999 performancePointsList, _ := s.GetPage(&reqData) var pointsMap = make(map[string]Performance.PerformancePoints) // 实施 for _, item := range performancePointsList { pointsMap[item.T_name] = item } return pointsMap } func GetColdVerifyUUIDMap() (uuidMap map[string]string) { uuidMap = make(map[string]string) userList, _ := NatsServer.Read_User_List_All() for _, user := range userList { uuidMap[user.T_verify_cold_uuid] = user.T_uuid } return uuidMap } // 获取实施提成金额 func GetPerformancePoints(T_device_type, T_verify_type string, pointsMap map[string]Performance.PerformancePoints) (money Performance.PerformancePoints) { if strings.Contains(T_device_type, "箱") { return pointsMap["箱"] } if strings.Contains(T_device_type, "车") { if strings.Contains(T_verify_type, "空载") { return pointsMap["车(空载)"] } else { return pointsMap["车(满载)"] } } if strings.Contains(T_device_type, "柜") { if strings.Contains(T_verify_type, "空载") { return pointsMap["库(空载)"] } else { return pointsMap["库(满载)"] } } if strings.Contains(T_device_type, "库") { if strings.Contains(T_verify_type, "空载") { return pointsMap["库(空载)"] } else { return pointsMap["库(满载)"] } } if strings.Contains(T_device_type, "系统") { return pointsMap["系统"] } if strings.Contains(T_device_type, "位置") { return pointsMap["位置"] } if strings.Contains(T_device_type, "巡检") { return pointsMap["巡检"] } if strings.Contains(T_device_type, "培训") { return pointsMap["培训"] } return Performance.PerformancePoints{} }