package export import ( "database/sql" "fmt" "strings" ) // 本文件是「队名」(entries.squad,迁移 0025)在导出侧的读法。 // // 同一个单位在同一组别可以派多支队参赛(例如羽毛球双打,一个单位两个队各占一个名次), // 报名上多出一列自由文本队名,空串 = 不区分队伍 —— 那是老数据与单队单位的默认值。 // // 显示口径(与大屏、管理端同一份实现):**单位名 + 队名**,不加括号也不加分隔符,例如「第一分公司二队」。 // 现场就是把它当一个单位名念的,括号与空格只会白占列宽,还会让同一支队在两份材料里写法不一样。 // withSquad 把队名接在单位名后面;队名为空(或只有空白)时**一个字都不加**。 // // 空队名什么都不加是硬门槛:升级后导出的老赛事必须与升级前逐行一致。 // 顺带去掉队名首尾空白:它由现场自由填写,带着空格会把「第一分公司 二队」这种读法印进导出件。 func withSquad(name, squad string) string { squad = strings.TrimSpace(squad) if squad == "" { return name } return name + squad } // loadEntrySquads 读全部带队名的报名,按报名 id 归组。 // // 只取非空的行:绝大多数报名的 squad 都是空串,整表扫回来再逐行判空是白花内存。 func loadEntrySquads(db *sql.DB) (map[int64]string, error) { rows, err := db.Query(`SELECT id, squad FROM entries WHERE TRIM(COALESCE(squad, '')) <> ''`) if err != nil { return nil, fmt.Errorf("export: 读取报名队名: %w", err) } defer func() { _ = rows.Close() }() out := make(map[int64]string) for rows.Next() { var ( entryID int64 squad string ) if err := rows.Scan(&entryID, &squad); err != nil { return nil, fmt.Errorf("export: 扫描报名队名: %w", err) } out[entryID] = squad } if err := rows.Err(); err != nil { return nil, fmt.Errorf("export: 遍历报名队名: %w", err) } return out, nil }