You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

124 lines
4.0 KiB

package logic
import (
"VoteManage_Go/api/v1/vote"
"VoteManage_Go/internal/dao"
"VoteManage_Go/internal/model/dto"
"VoteManage_Go/internal/service"
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"github.com/xuri/excelize/v2"
"net/url"
"strconv"
"time"
)
type sVote struct{}
func init() {
service.RegisterVote(New())
}
func New() *sVote {
return &sVote{}
}
func (s *sVote) GetVoteByCondition(ctx context.Context, req *vote.GetVoteDetailListReq) (votes []*dto.VoteDto, total int, err error) {
query := g.Model("vote_records v").LeftJoin("member_info m", "v.jwcode = m.jwcode").
Fields("v.id, m.nickname, v.jwcode, m.dept, v.options_title, v.time").
Where("v.activity_id = ?", req.ActivityId)
// 条件1:jwcode输入(精确匹配)
if req.Jwcode != "" {
query = query.Where("v.jwcode = ?", req.Jwcode)
}
// 条件2:地区dept下拉框(精确匹配)dept是汉字
if req.Dept != "" {
query = query.Where("m.dept = ?", req.Dept)
}
// 条件3:投票日期范围(时间戳转换)
//if req.StartTime != nil && req.EndTime != nil {
// // 将前端日期字符串转为Unix时间戳(示例:2025.04.01 00:00:00 → 时间戳)
// query = query.Where("v.time BETWEEN ? AND ?", req.StartTime.Unix(), req.EndTime.Unix())
//}
if req.StartDate != "" && req.EndDate != "" {
start := gtime.New(req.StartDate + " 00:00:00").Unix()
end := gtime.New(req.EndDate + " 23:59:59").Unix()
query = query.Where("v.time BETWEEN ? AND ?", start, end)
}
// 条件4:分页
query.Page(req.PageNo, req.PageSize).ScanAndCount(&votes, &total, false)
return
}
func (s *sVote) ExportVote(r *ghttp.Request, req *vote.GetVoteDetailListReq) {
votes, _, err := s.GetVoteByCondition(r.Context(), req)
if err != nil {
r.Response.WriteJsonExit(dto.Error("查询失败:" + err.Error()))
return
}
if len(votes) == 0 {
r.Response.WriteJsonExit(dto.Error("查询结果为空"))
return
}
// 内存中创建Excel文件(不落盘)
excelFile := excelize.NewFile()
sheetName := "投票记录"
excelFile.SetSheetName("Sheet1", sheetName)
// 设置表头样式
headers := []string{"序号", "姓名", "精网号", "地区", "投票明细", "投票时间"}
for i, header := range headers {
col := string('A' + i)
excelFile.SetCellValue(sheetName, col+"1", header)
excelFile.SetColWidth(sheetName, col, col, 18) // 列宽调整
}
// 动态写入数据
for rowIdx, vote := range votes {
row := strconv.Itoa(rowIdx + 2)
excelFile.SetCellValue(sheetName, "A"+row, rowIdx+1)
excelFile.SetCellValue(sheetName, "B"+row, vote.Nickname)
excelFile.SetCellValue(sheetName, "C"+row, vote.Jwcode)
excelFile.SetCellValue(sheetName, "D"+row, vote.Dept)
excelFile.SetCellValue(sheetName, "E"+row, vote.OptionsTitle)
excelFile.SetCellValue(sheetName, "F"+row, vote.Time)
}
// 生成唯一文件名并响应流
fileName := fmt.Sprintf("投票记录_%s.xlsx",
time.Now().Format("20060102150405"),
)
r.Response.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
r.Response.Header().Set("Content-Disposition", "attachment; filename*=UTF-8''"+url.QueryEscape(fileName))
// 直接写入HTTP响应流
if buffer, err := excelFile.WriteToBuffer(); err == nil {
r.Response.Write(buffer.Bytes())
} else {
r.Response.WriteJsonExit(dto.Error("文件生成失败:" + err.Error()))
}
}
func (s *sVote) GetActivityList(ctx context.Context, req *vote.GetActivityListReq) (activities []*dto.Activity, total int, err error) {
err = g.DB("live").Model("float_window").Fields("id, title, start, end, created_at").
OrderDesc("id").Page(req.PageNo, req.PageSize).ScanAndCount(&activities, &total, false)
for _, v := range activities {
v.VoteCount, _ = dao.VoteRecords.Ctx(ctx).Where("activity_id", v.Id).Fields("DISTINCT jwcode").Count()
//fmt.Printf(strconv.Itoa(v.VoteCount))
if gtime.Date() < v.Start {
v.Status = 1
} else if gtime.Date() > v.End {
v.Status = 3
} else {
v.Status = 2
}
}
return
}