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

646 lines
14 KiB
Go

package service
import (
"joybuywork/internal/repository/cache"
"joybuywork/internal/repository/dbcheck"
"joybuywork/internal/repository/finder"
"joybuywork/internal/repository/model"
"joybuywork/internal/repository/mtype"
"joybuywork/internal/repository/withdefault"
"joybuywork/internal/service/containers"
"joybuywork/internal/utils"
pb "joybuywork/proto/go_proto/w_library"
"joybuywork/proto/go_proto/workerr"
"time"
"gorm.io/gen"
)
type WLibrary struct {
Service
}
// QaGroup 题库列表
func (s *WLibrary) QaGroup(req *pb.QaGroupReq, res *pb.QaGroupRes) (err error) {
defer s.checkErr()
project, err := finder.Project(s.ctx, req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
return
}
m := s.GetDao().LibraryQaGroup
var cond = []gen.Condition{
m.DelTime.Eq(0),
m.ProjectID.Eq(project.ID),
}
if req.GetTitle() != "" {
cond = append(cond, m.Title.Like(utils.DbAllLike(req.GetTitle())))
}
offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage())
list, total, err := m.WithContext(s.ctx).Where(cond...).Order(m.ID.Desc()).FindByPage(offset, limit)
if err != nil {
return s.BE().MysqlError(err)
}
*res = pb.QaGroupRes{
List: make([]*pb.QaGroupRes_One, 0, len(list)),
Total: total,
}
if total == 0 {
return
}
var ids []int64
for _, item := range list {
ids = append(ids, item.ID)
}
type num struct {
GroupID int64 `json:"group_id"`
Num int64 `json:"num"`
}
var nums []*num
qaM := s.GetDao().LibraryQa
err = qaM.WithContext(s.ctx).Select(qaM.GroupID, qaM.ID.Count().As("num")).Where(qaM.GroupID.In(ids...)).Group(qaM.GroupID).Scan(&nums)
if err != nil {
return s.BE().MysqlError(err)
}
var numMap = make(map[int64]int64, len(list))
for _, v := range nums {
numMap[v.GroupID] = v.Num
}
for _, v := range list {
res.List = append(res.List, &pb.QaGroupRes_One{
Id: v.ID,
HashId: v.HashID,
Title: v.Title,
CreatedAt: v.CreatedAt,
QaCount: numMap[v.ID],
})
}
return
}
// StoreQaGroup 创建题库
func (s *WLibrary) StoreQaGroup(req *pb.StoreQaGroupReq, res *pb.StoreQaGroupRes) (err error) {
defer s.checkErr()
project, err := finder.Project(s.ctx, req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
err = workerr.NotFound("not found project")
return
}
m := s.GetDao().LibraryQaGroup
exist, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.Title.Eq(req.GetTitle()), m.DelTime.Eq(0)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if exist != nil {
err = workerr.VerifyError("title exist")
return
}
err = m.WithContext(s.ctx).Create(withdefault.LibraryQaGroup(&model.LibraryQaGroup{
ProjectID: project.ID,
Title: req.GetTitle(),
DelTime: 0,
}))
if err != nil {
err = s.BE().MysqlError(err)
return
}
*res = pb.StoreQaGroupRes{}
return
}
// UpdateQaGroup 更新题库
func (s *WLibrary) UpdateQaGroup(req *pb.UpdateQaGroupReq, res *pb.UpdateQaGroupRes) (err error) {
defer s.checkErr()
project, err := finder.Project(s.ctx, req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
err = workerr.NotFound("not found project")
return
}
group, err := cache.NewLibraryQaGroup(s.ctx).FindByHashId(req.GetHashId())
if err != nil {
err = s.BE().MysqlError(err)
return
}
if group == nil || group.DelTime > 0 || group.ProjectID != project.ID {
err = workerr.NotFound("not found qa group")
return
}
m := s.GetDao().LibraryQaGroup
exist, err := m.WithContext(s.ctx).Where(m.ProjectID.Eq(project.ID), m.Title.Eq(req.GetTitle()), m.ID.Neq(group.ID), m.DelTime.Eq(0)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if exist != nil {
err = workerr.VerifyError("title exist")
return
}
_, err = m.WithContext(s.ctx).Where(m.ID.Eq(group.ID)).UpdateSimple(m.Title.Value(req.GetTitle()))
if err != nil {
err = s.BE().MysqlError(err)
return
}
_ = cache.NewLibraryQaGroup(s.ctx).Clear(group)
*res = pb.UpdateQaGroupRes{}
return
}
// DestroyQaGroup 删除题库
func (s *WLibrary) DestroyQaGroup(req *pb.DestroyQaGroupReq, res *pb.DestroyQaGroupRes) (err error) {
defer s.checkErr()
project, err := finder.Project(s.ctx, req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
err = workerr.NotFound("not found project")
return
}
group, err := cache.NewLibraryQaGroup(s.ctx).FindByHashId(req.GetHashId())
if err != nil {
err = s.BE().MysqlError(err)
return
}
if group == nil || group.DelTime > 0 || group.ProjectID != project.ID {
return
}
m := s.GetDao().LibraryQaGroup
_, err = m.WithContext(s.ctx).Where(m.ID.Eq(group.ID)).UpdateSimple(m.DelTime.Value(time.Now().Unix()))
if err != nil {
err = s.BE().MysqlError(err)
return
}
_ = cache.NewLibraryQaGroup(s.ctx).Clear(group)
*res = pb.DestroyQaGroupRes{}
return
}
// QaList 问题列表
func (s *WLibrary) QaList(req *pb.QaListReq, res *pb.QaListRes) (err error) {
defer s.checkErr()
groupM := s.GetDao().LibraryQaGroup
group, err := groupM.WithContext(s.ctx).Where(groupM.HashID.Eq(req.GetGroupHashId()), groupM.DelTime.Eq(0)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if group == nil {
return
}
m := s.GetDao().LibraryQa
var cond = []gen.Condition{
m.IsDel.Eq(mtype.No),
m.GroupID.Eq(group.ID),
}
if req.GetTitle() != "" {
cond = append(cond, m.Title.Like(utils.DbAllLike(req.GetTitle())))
}
if req.GetMark() != "" {
cond = append(cond, m.Mark.Eq(req.GetMark()))
}
offset, limit := utils.PpDbLo(req.GetPage(), req.GetPerPage())
list, total, err := m.WithContext(s.ctx).Where(cond...).Order(m.ID.Desc()).FindByPage(offset, limit)
if err != nil {
return s.BE().MysqlError(err)
}
*res = pb.QaListRes{
List: make([]*pb.QaListRes_One, 0, len(list)),
Total: total,
}
if total == 0 {
return
}
var ids []int64
for _, v := range list {
ids = append(ids, v.ID)
}
optionM := s.GetDao().LibraryQaOption
options, err := optionM.WithContext(s.ctx).Where(optionM.QaID.In(ids...), optionM.IsDel.Eq(mtype.No)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
var opMap = make(map[int64][]*model.LibraryQaOption)
for _, v := range options {
opMap[v.QaID] = append(opMap[v.QaID], v)
}
for _, v := range list {
one := &pb.QaListRes_One{
Id: v.ID,
HashId: v.HashID,
Mark: v.Mark,
Title: v.Title,
CoverUrl: v.CoverURL,
LinkUrl: v.LinkURL,
ExplainText: v.ExplainText,
ExplainImg: v.ExplainImg,
Options: make([]*pb.QaListRes_Option, 0, len(opMap[v.ID])),
CreatedAt: v.CreatedAt,
AnswerMark: v.AnswerMark,
}
for _, option := range opMap[v.ID] {
one.Options = append(one.Options, &pb.QaListRes_Option{
Id: option.ID,
Title: option.Title,
ImgUrl: option.ImgURL,
IsRight: int32(option.IsRight),
})
}
res.List = append(res.List, one)
}
return
}
// StoreQa 创建题目
func (s *WLibrary) StoreQa(req *pb.StoreQaReq, res *pb.StoreQaRes) (err error) {
defer s.checkErr()
groupM := s.GetDao().LibraryQaGroup
group, err := groupM.WithContext(s.ctx).Where(groupM.HashID.Eq(req.GetGroupHashId()), groupM.DelTime.Eq(0)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if group == nil {
err = workerr.NotFound("not found qa group")
return
}
tx := s.GetDao().Begin()
defer func() {
if err != nil {
_ = tx.Rollback()
return
}
_ = tx.Commit()
}()
m := tx.LibraryQa
qa := withdefault.LibraryQa(&model.LibraryQa{
ProjectID: group.ProjectID,
GroupID: group.ID,
Mark: req.GetMark(),
Title: req.GetTitle(),
LinkURL: req.GetLinkUrl(),
CoverURL: req.GetCoverUrl(),
ExplainText: req.GetExplainText(),
ExplainImg: req.GetExplainImg(),
AnswerMark: req.GetAnswerMark(),
})
if err = m.WithContext(s.ctx).Create(qa); err != nil {
err = s.BE().MysqlError(err)
return
}
var options []*model.LibraryQaOption
optionM := tx.LibraryQaOption
for _, v := range req.GetOptions() {
options = append(options, withdefault.LibraryQaOption(&model.LibraryQaOption{
QaID: qa.ID,
Title: v.GetTitle(),
ImgURL: v.GetImgUrl(),
IsRight: int8(v.GetIsRight()),
}))
}
if len(options) > 0 {
if err = optionM.WithContext(s.ctx).Create(options...); err != nil {
err = s.BE().MysqlError(err)
return
}
}
*res = pb.StoreQaRes{}
return
}
// UpdateQa 更新题目
func (s *WLibrary) UpdateQa(req *pb.UpdateQaReq, res *pb.UpdateQaRes) (err error) {
defer s.checkErr()
m := s.GetDao().LibraryQa
qa, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetHashId()), m.IsDel.Eq(mtype.No)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if qa == nil {
err = workerr.NotFound("not found question")
return
}
tx := s.GetDao().Begin()
defer func() {
if err != nil {
_ = tx.Rollback()
return
}
_ = tx.Commit()
}()
mtx := tx.LibraryQa
_, err = mtx.WithContext(s.ctx).Where(mtx.ID.Eq(qa.ID)).UpdateSimple(
mtx.Mark.Value(req.GetMark()),
mtx.Title.Value(req.GetTitle()),
mtx.LinkURL.Value(req.GetLinkUrl()),
mtx.CoverURL.Value(req.GetCoverUrl()),
mtx.ExplainText.Value(req.GetExplainText()),
mtx.ExplainImg.Value(req.GetExplainImg()),
mtx.AnswerMark.Value(req.GetAnswerMark()),
)
if err != nil {
err = s.BE().MysqlError(err)
return
}
optionTx := tx.LibraryQaOption
old, err := optionTx.WithContext(s.ctx).Where(optionTx.QaID.Eq(qa.ID), optionTx.IsDel.Eq(mtype.No)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
var oldMap = make(map[int64]struct{}, len(old))
for _, v := range old {
oldMap[v.ID] = struct{}{}
}
var newMap = make(map[int64]struct{})
var add []*model.LibraryQaOption
for _, v := range req.GetOptions() {
_, ok := oldMap[v.GetId()]
if !ok {
add = append(add, withdefault.LibraryQaOption(&model.LibraryQaOption{
QaID: qa.ID,
Title: v.GetTitle(),
ImgURL: v.GetImgUrl(),
IsRight: int8(v.GetIsRight()),
}))
continue
}
newMap[v.GetId()] = struct{}{}
_, err = optionTx.WithContext(s.ctx).Where(optionTx.ID.Eq(v.GetId())).UpdateSimple(
optionTx.Title.Value(v.GetTitle()),
optionTx.ImgURL.Value(v.GetImgUrl()),
optionTx.IsRight.Value(int8(v.GetIsRight())),
)
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
var delIds []int64
for _, v := range old {
if _, ok := newMap[v.ID]; !ok {
delIds = append(delIds, v.ID)
}
}
if len(add) > 0 {
if err = optionTx.WithContext(s.ctx).Create(add...); err != nil {
err = s.BE().MysqlError(err)
return
}
}
if len(delIds) > 0 {
_, err = optionTx.WithContext(s.ctx).Where(optionTx.ID.In(delIds...), optionTx.QaID.Eq(qa.ID)).UpdateSimple(optionTx.IsDel.Value(mtype.Yes))
if err != nil {
err = s.BE().MysqlError(err)
return
}
}
*res = pb.UpdateQaRes{}
return
}
// DestroyQa 删除题目
func (s *WLibrary) DestroyQa(req *pb.DestroyQaReq, res *pb.DestroyQaRes) (err error) {
defer s.checkErr()
m := s.GetDao().LibraryQa
qa, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetHashId()), m.IsDel.Eq(mtype.No)).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if qa == nil {
return
}
_, err = m.WithContext(s.ctx).Where(m.ID.Eq(qa.ID)).UpdateSimple(m.IsDel.Value(mtype.Yes))
if err != nil {
err = s.BE().MysqlError(err)
return
}
*res = pb.DestroyQaRes{}
return
}
// QaGroupSelect 题库选项
func (s *WLibrary) QaGroupSelect(req *pb.QaGroupSelectReq, res *pb.QaGroupSelectRes) (err error) {
defer s.checkErr()
project, err := finder.Project(s.ctx, req.GetProjectHashId())
if err != nil {
err = s.BE().CacheError(err)
return
}
if project == nil || project.IsDel == mtype.Yes {
return
}
groupM := s.GetDao().LibraryQaGroup
list, err := groupM.WithContext(s.ctx).Where(groupM.ProjectID.Eq(project.ID), groupM.DelTime.Eq(0)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
if len(list) == 0 {
return
}
var ids = make([]int64, 0, len(list))
for _, v := range list {
ids = append(ids, v.ID)
}
var total []struct {
GroupId int64 `json:"group_id"`
Num int64 `json:"num"`
}
m := s.GetDao().LibraryQa
var cond = []gen.Condition{
m.IsDel.Eq(mtype.No),
m.GroupID.In(ids...),
}
if req.GetMark() != "" {
cond = append(cond, m.Mark.Eq(req.GetMark()))
}
err = m.WithContext(s.ctx).
Select(m.GroupID, m.ID.Count().As("num")).
Where(cond...).
Group(m.GroupID).
Scan(&total)
if err != nil {
err = s.BE().MysqlError(err)
return
}
var totalMap = make(map[int64]int64, len(total))
for _, v := range total {
totalMap[v.GroupId] = v.Num
}
*res = pb.QaGroupSelectRes{
List: make([]*pb.QaGroupSelectRes_One, 0),
}
for _, v := range list {
res.List = append(res.List, &pb.QaGroupSelectRes_One{
Id: v.ID,
HashId: v.HashID,
Title: v.Title,
QaNum: totalMap[v.ID],
})
}
return
}
// QaRand 随机问题
func (s *WLibrary) QaRand(req *pb.QaRandReq, res *pb.QaRandRes) (err error) {
defer s.checkErr()
container := new(containers.LibraryQaRand)
{
container.Init(s.ctx)
container.Req = req
container.Res = res
}
return container.Run()
}
// QaShow 问题详情
func (s *WLibrary) QaShow(req *pb.QaShowReq, res *pb.QaShowRes) (err error) {
defer s.checkErr()
m := s.GetDao().LibraryQa
qa, err := m.WithContext(s.ctx).Where(m.HashID.Eq(req.GetHashId())).Take()
if err = dbcheck.DbError(err); err != nil {
err = s.BE().MysqlError(err)
return
}
if qa == nil {
err = workerr.NotFound("not found qa")
return
}
optionM := s.GetDao().LibraryQaOption
options, err := optionM.WithContext(s.ctx).Where(optionM.QaID.Eq(qa.ID), optionM.IsDel.Eq(mtype.No)).Find()
if err != nil {
err = s.BE().MysqlError(err)
return
}
*res = pb.QaShowRes{
Id: qa.ID,
HashId: qa.HashID,
Mark: qa.Mark,
Title: qa.Title,
CoverUrl: qa.CoverURL,
LinkUrl: qa.LinkURL,
ExplainText: qa.ExplainText,
ExplainImg: qa.ExplainImg,
Options: make([]*pb.QaShowRes_Option, 0, len(options)),
CreatedAt: qa.CreatedAt,
AnswerMark: qa.AnswerMark,
}
for _, v := range options {
res.Options = append(res.Options, &pb.QaShowRes_Option{
Id: v.ID,
Title: v.Title,
ImgUrl: v.ImgURL,
IsRight: int32(v.IsRight),
})
}
return
}