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
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
|
|
}
|