package export import ( "database/sql" "io" "strconv" "github.com/xuri/excelize/v2" "git.yeij.top/AskaEth/Scoreboard/server/internal/domain" ) // TeamDetailRow 是单位积分明细的一行:一分一行的得分来源。 type TeamDetailRow struct { SportName string EventName string Category string AthleteName string Rank int ResultText string Source string Points float64 Remark string // individual 标记该条流水记到个人:合计要按 individual_to_team_weight 折算。 individual bool } // TeamDetailWorkbook 是「单位积分明细」的内容。 type TeamDetailWorkbook struct { Meta Meta Team domain.Team Rows []TeamDetailRow // IndividualToTeamWeight 与总积分榜同源,用于把个人分折算进「合计」。 IndividualToTeamWeight float64 } var teamDetailColumns = []column{ {"序号", 6, kindInt}, {"大项", 14, kindText}, {"小项", 18, kindText}, {"组别", 14, kindText}, {"运动员", 14, kindText}, {"名次", 7, kindCenter}, {"成绩", 12, kindCenter}, {"来源", 12, kindCenter}, {"积分", 8, kindNumber}, {"备注", 20, kindText}, } // ExportTeamDetailXLSX 导出某单位的积分明细(逐项列出得分来源)。 func ExportTeamDetailXLSX(db *sql.DB, teamID int64, dst string, opts Options) error { wb, err := LoadTeamDetailWorkbook(db, teamID, opts) if err != nil { return err } f, err := teamDetailFile(wb) if err != nil { return err } return saveWorkbook(f, dst) } // WriteTeamDetailXLSX 把单位积分明细写成 xlsx 流。 func WriteTeamDetailXLSX(w io.Writer, wb TeamDetailWorkbook) error { f, err := teamDetailFile(wb) if err != nil { return err } return f.Write(w) } func teamDetailFile(wb TeamDetailWorkbook) (*excelize.File, error) { return buildWorkbook("积分明细", func(f *excelize.File, st *styleSet) error { meta := wb.Meta.normalized() name := sanitizeSheetName(displayName(wb.Team.Name, wb.Team.ShortName) + "积分明细") if err := addSheet(f, name); err != nil { return err } title := sheetTitle(meta, displayName(wb.Team.Name, wb.Team.ShortName)+" · 积分明细") return writeSheet(f, st, name, meta, title, teamDetailColumns, teamDetailRows(wb.Rows, wb.IndividualToTeamWeight)) }) } // teamDetailRows 把明细行排成表格。与 REST 的单位积分明细同口径: // 记到个人的流水按 individual_to_team_weight 折算后展示,合计即各行之和。 func teamDetailRows(rows []TeamDetailRow, weight float64) [][]any { if weight <= 0 { weight = 1 } out := make([][]any, 0, len(rows)+1) var total float64 for i, r := range rows { points := r.Points if r.individual { points *= weight } total += points rank := "" if r.Rank > 0 { rank = strconv.Itoa(r.Rank) } out = append(out, []any{ i + 1, r.SportName, r.EventName, r.Category, r.AthleteName, rank, r.ResultText, r.Source, points, r.Remark, }) } if len(rows) > 0 { out = append(out, []any{"合计", "", "", "", "", "", "", "", total, ""}) } return out }