package game import ( "encoding/json" "errors" "strconv" "support-game/models" "support-game/models/model" "support-game/utils" "time" "github.com/go-xorm/xorm" ) const ( // 默认图片类型 DefaultPhotoType = "main" // 列表排序类型 OrderByDate = 1 OrderByVote = 2 // 活动限制规则 RuleOfLimitEveryday = "limiteveryday" PageNum = 10 ) var ( ErrVoteLimit = errors.New("votelimit") ErrActivityNotStart = errors.New("Activity not start") ErrActivityIsOver = errors.New("Activity is over") ) // VotingModel 当前数据库操作对象 type VotingModel struct { ctx *utils.Context db *xorm.Session } // NewVotingModel 初始化DAO func NewVotingModel(ctx *utils.Context) *VotingModel { return &VotingModel{ ctx: ctx, db: ctx.DB, } } type MemInfo struct { model.TaVotingMember `xorm:"extends"` Photo string `xorm:"TEXT"` Rank int } // List 报名列表 func (m *VotingModel) List(actID int, search string, orderby, page int) (list []MemInfo, err error) { query := ` SELECT t.*, s.photo FROM ta_voting_member t JOIN ta_voting_member_photos s ON t.member_id = s.member_id AND t.activity_id = s.activity_id AND s.type = '` + DefaultPhotoType + `' AND s.status = ` + strconv.Itoa(models.STATUS_NORMAL) + ` Where t.activity_id = '` + strconv.Itoa(actID) + `' AND ` // 依据 ID 或者 名称查询 // 全部列表的时候, 名称为空即可 if search != "" { query += `(t.member_id like '%` + search + `%' or t.name like '%` + search + `%') AND` } query += " t.status = " + strconv.Itoa(models.STATUS_NORMAL) // 排序 if orderby == OrderByVote { query += " order by t.vote desc" if page > 5 { page = 5 } } else { query += " order by t.create_date desc" } // 分页 offset := (page - 1) * PageNum if offset < 0 { offset = 0 } query += " limit " + strconv.Itoa(PageNum) + " offset " + strconv.Itoa(offset) if err = m.db.Sql(query).Find(&list); err != nil { return } return } // GetActivityInfo 查询活动 func (m *VotingModel) GetActivityInfo(actID int) (act *model.TaVotingActivities, err error) { _, err = m.db.Table("ta_voting_activities").Where("activity_id=?", actID).Get(act) if err != nil { return } return } // GetMemInfo 获取报名人员信息 func (m *VotingModel) GetMemInfo(actID, memID int) (mem *MemInfo, err error) { query := ` SELECT t.*, s.photo FROM ta_voting_member t JOIN ta_voting_member_photos s ON t.member_id = s.member_id AND t.activity_id = s.activity_id AND s.type = '` + DefaultPhotoType + `' AND s.status = ` + strconv.Itoa(models.STATUS_NORMAL) + ` Where t.activity_id = ? AND t.member_id = ? ` if _, err = m.db.SQL(query, actID, memID).Get(mem); err != nil { return } // 获取排名 cnt, e := m.db.Where("activity_id=?", actID). And("status=?", models.STATUS_NORMAL). And("vote>?", mem.Vote). Count() if e != nil { // -1 代表发生错误 mem.Rank = -1 return } mem.Rank = int(cnt) return } // Registe 报名保存 func (m *VotingModel) Registe(memInfo *MemInfo) error { if memInfo.ActivityId == 0 { return errors.New("活动报名失败, 没有指定活动内容") } // 校验活动 if err := m.checkActivity(memInfo.ActivityId); err != nil { return err } now := time.Now().Local() mem := memInfo.TaVotingMember photo := model.TaVotingMemberPhotos{ ActivityId: mem.ActivityId, Photo: memInfo.Photo, Type: DefaultPhotoType, CreateDate: now, Status: models.STATUS_NORMAL, } // 检查已有最大值 maxID, err := m.getMaxMemID(mem.ActivityId) if err != nil { return err } mem.MemberId = int(maxID + 1) mem.Vote = 0 photo.MemberId = mem.MemberId memInfo.MemberId = mem.MemberId if _, err := m.db.Insert(&photo); err != nil { return err } if _, err := m.db.Insert(&mem); err != nil { return err } // 反更新报名人数 // TODO return nil } func (m *VotingModel) getMaxMemID(actID int) (maxID int64, err error) { query := ` SELECT max(start_id) as max_id FROM ( SELECT max(t.member_id) AS start_id FROM ta_voting_member t UNION SELECT s.start_id FROM ta_voting_activities s WHERE s.activity_id = ? ) a ` if _, err = m.db.SQL(query, actID).Get(&maxID); err != nil { return } return } // Vote 投票 func (m *VotingModel) Vote(rec *model.TaVotingRecords) error { // 校验活动 if err := m.checkActivity(rec.ActivityId); err != nil { return err } rule, err := m.getActivityRule(rec.ActivityId) if err != nil { return err } var ruleParam map[string]interface{} if err := json.Unmarshal([]byte(rule.RuleValue), &ruleParam); err != nil { return err } // 如果有每天最大投票限制 if v, ok := ruleParam[RuleOfLimitEveryday]; ok { limitEveryday := int64(v.(float64)) voteNum, err := m.getVoteNumOfMember(rec) if err != nil { return err } if voteNum >= limitEveryday { return ErrVoteLimit } } // 每天投票 rec.VoteDate = time.Now().Local() if _, err := m.db.Insert(rec); err != nil { return err } // 反更新次数 if err := m.updateVoteOfMember(rec.ActivityId, rec.MemberId); err != nil { return err } return nil } // 获取投票规则 func (m *VotingModel) getActivityRule(actID int) (rule *model.TaVotingRules, err error) { query := ` SELECT t.* FROM ta_voting_rules t JOIN ta_voting_activities s ON t.rule_id = s.rule_id AND s.activity_id = ? ` if _, err = m.db.SQL(query, actID).Get(rule); err != nil { return } if rule.RuleValue == "" { rule.RuleValue = "{}" } return } // 获取当前人员投票数 func (m *VotingModel) getVoteNumOfMember(rec *model.TaVotingRecords) (num int64, err error) { query := ` SELECT * FROM ta_voting_records t WHERE t.activity_id = ? AND t.member_id = ? AND t.openid = ? AND date_format(t.vote_date, "%Y-%m-%d") = date_format(now(), "%Y-%m-%d") ` num, err = m.db.SQL(query, rec.ActivityId, rec.MemberId, rec.Openid).Count() if err != nil { return } return } // 反更新投票次数 func (m *VotingModel) updateVoteOfMember(actID, memID int) error { query := ` UPDATE ta_voting_member t SET t.vote = t.vote + 1 WHERE t.activity_id = ? AND t.member_id = ? ` if _, err := m.db.Exec(query, actID, memID); err != nil { return err } return nil } // 校验活动 // 只校验活动时间 func (m *VotingModel) checkActivity(actID int) error { act := model.TaVotingActivities{} if _, err := m.db.Where("activity_id=?", actID).Get(&act); err != nil { return err } now := time.Now().Local() if act.StartTime.After(now) { return ErrActivityNotStart } if act.EndTime.Before(now) { return ErrActivityIsOver } return nil }