diff --git a/api/controller/ErrorWord.go b/api/controller/ErrorWord.go new file mode 100644 index 0000000..0155f59 --- /dev/null +++ b/api/controller/ErrorWord.go @@ -0,0 +1,209 @@ +package controller + +import ( + "github.com/gin-gonic/gin" + "knowledge/api/dao" + "knowledge/api/dto" + "knowledge/api/model" + "knowledge/api/requests" + "knowledge/api/responses" + "knowledge/global" + "knowledge/utils" + "strconv" +) + +type BaseErrorWord struct{} + +// GetBaseErrorWordPage 获取列表-分页 +func (r *BaseErrorWord) GetBaseErrorWordPage(c *gin.Context) { + baseErrorWordRequest := requests.BaseErrorWordRequest{} + req := baseErrorWordRequest.GetBaseErrorWordPage + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + if req.Page == 0 { + req.Page = 1 + } + + if req.PageSize == 0 { + req.PageSize = 20 + } + + baseErrorWordDao := dao.BaseErrorWordDao{} + baseErrorWord, total, err := baseErrorWordDao.GetBaseErrorWordPageSearch(req.Page, req.PageSize) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 处理返回值 + g := dto.GetBaseErrorWordListDto(baseErrorWord) + + result := make(map[string]interface{}) + result["page"] = req.Page + result["page_size"] = req.PageSize + result["total"] = total + result["data"] = g + responses.OkWithData(result, c) +} + +// AddBaseErrorWord 新增 +func (r *BaseErrorWord) AddBaseErrorWord(c *gin.Context) { + baseErrorWordRequest := requests.BaseErrorWordRequest{} + req := baseErrorWordRequest.AddBaseErrorWord + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 新增 + baseErrorWordDao := dao.BaseErrorWordDao{} + baseErrorWord := &model.BaseErrorWord{ + WordOld: req.WordOld, + WordNew: req.WordNew, + OperationTime: nil, + } + baseErrorWord, err := baseErrorWordDao.AddBaseErrorWord(tx, baseErrorWord) + if err != nil { + tx.Rollback() + responses.FailWithMessage("新增失败", c) + return + } + + tx.Commit() + responses.Ok(c) +} + +// DeleteBaseErrorWord 删除 +func (r *BaseErrorWord) DeleteBaseErrorWord(c *gin.Context) { + id := c.Param("word_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + // 将 id 转换为 int64 类型 + wordId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + // 获取详情 + baseErrorWordDao := dao.BaseErrorWordDao{} + _, err = baseErrorWordDao.GetBaseErrorWordById(wordId) + if err != nil { + responses.FailWithMessage("数据不存在", c) + return + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + err = baseErrorWordDao.DeleteBaseErrorWordById(tx, wordId) + if err != nil { + responses.FailWithMessage("删除失败", c) + return + } + + tx.Commit() + + responses.Ok(c) +} + +// OperationErrorWord 一键修改错别字 +func (r *BaseErrorWord) OperationErrorWord(c *gin.Context) { + id := c.Param("word_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + // 将 id 转换为 int64 类型 + wordId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + // 获取详情 + baseErrorWordDao := dao.BaseErrorWordDao{} + baseErrorWord, err := baseErrorWordDao.GetBaseErrorWordById(wordId) + if err != nil { + responses.FailWithMessage("数据不存在", c) + return + } + + // 获取相关错别字题目 + questionDao := dao.QuestionDao{} + questions, err := questionDao.GetQuestionListByWord(baseErrorWord.WordOld) + if err == nil && len(questions) <= 0 { + responses.Ok(c) + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + for _, question := range questions { + questionName := utils.ReplaceString(question.QuestionName, baseErrorWord.WordOld, baseErrorWord.WordNew) + questionAnswer := utils.ReplaceString(question.QuestionAnswer, baseErrorWord.WordOld, baseErrorWord.WordNew) + questionAnalysis := utils.ReplaceString(question.QuestionAnalysis, baseErrorWord.WordOld, baseErrorWord.WordNew) + + datas := make(map[string]interface{}) + if question.QuestionName != questionName { + datas["question_name"] = questionName + } + + if question.QuestionAnswer != questionAnswer { + datas["question_answer"] = questionAnswer + } + + if question.QuestionAnalysis != questionAnalysis { + datas["question_analysis"] = questionAnalysis + } + + if len(datas) > 0 { + err = questionDao.EditQuestionById(tx, question.QuestionId, datas) + if err != nil { + tx.Rollback() + responses.FailWithMessage(err.Error(), c) + return + } + } + } + + tx.Commit() + responses.Ok(c) +} diff --git a/api/controller/base.go b/api/controller/base.go index 963df24..c08e0ae 100644 --- a/api/controller/base.go +++ b/api/controller/base.go @@ -14,4 +14,5 @@ type Api struct { BaseToken // 基础数据-飞花令 BaseTokenItem // 基础数据-飞花令-明细 Editor // 配置-编辑器 + BaseErrorWord // 基础数据-错别字 } diff --git a/api/dao/BaseErrorWord.go b/api/dao/BaseErrorWord.go new file mode 100644 index 0000000..8d3ffbc --- /dev/null +++ b/api/dao/BaseErrorWord.go @@ -0,0 +1,130 @@ +package dao + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" + "knowledge/api/model" + "knowledge/global" +) + +type BaseErrorWordDao struct { +} + +// GetBaseErrorWordById 获取数据-id +func (r *BaseErrorWordDao) GetBaseErrorWordById(wordId int64) (m *model.BaseErrorWord, err error) { + err = global.Db.First(&m, wordId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetBaseErrorWordPreloadById 获取数据-加载全部关联-id +func (r *BaseErrorWordDao) GetBaseErrorWordPreloadById(wordId int64) (m *model.BaseErrorWord, err error) { + err = global.Db.Preload(clause.Associations).First(&m, wordId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// DeleteBaseErrorWord 删除 +func (r *BaseErrorWordDao) DeleteBaseErrorWord(tx *gorm.DB, maps interface{}) error { + err := tx.Where(maps).Delete(&model.BaseErrorWord{}).Error + if err != nil { + return err + } + return nil +} + +// DeleteBaseErrorWordById 删除-id +func (r *BaseErrorWordDao) DeleteBaseErrorWordById(tx *gorm.DB, tokenId int64) error { + if err := tx.Delete(&model.BaseErrorWord{}, tokenId).Error; err != nil { + return err + } + return nil +} + +// EditBaseErrorWord 修改 +func (r *BaseErrorWordDao) EditBaseErrorWord(tx *gorm.DB, maps interface{}, data interface{}) error { + err := tx.Model(&model.BaseErrorWord{}).Where(maps).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// EditBaseErrorWordById 修改-id +func (r *BaseErrorWordDao) EditBaseErrorWordById(tx *gorm.DB, wordId int64, data interface{}) error { + err := tx.Model(&model.BaseErrorWord{}).Where("word_id = ?", wordId).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// GetBaseErrorWordList 获取列表 +func (r *BaseErrorWordDao) GetBaseErrorWordList(maps interface{}) (m []*model.BaseErrorWord, err error) { + err = global.Db.Where(maps).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetBaseErrorWordCount 获取数量 +func (r *BaseErrorWordDao) GetBaseErrorWordCount(maps interface{}) (total int64, err error) { + err = global.Db.Model(&model.BaseErrorWord{}).Where(maps).Count(&total).Error + if err != nil { + return 0, err + } + return total, nil +} + +// GetBaseErrorWordListRand 获取列表-随机 +func (r *BaseErrorWordDao) GetBaseErrorWordListRand(maps interface{}, limit int) (m []*model.BaseErrorWord, err error) { + err = global.Db.Where(maps).Order("rand()").Limit(limit).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddBaseErrorWord 新增 +func (r *BaseErrorWordDao) AddBaseErrorWord(tx *gorm.DB, model *model.BaseErrorWord) (*model.BaseErrorWord, error) { + if err := tx.Create(model).Error; err != nil { + return nil, err + } + return model, nil +} + +// GetBaseErrorWord 获取 +func (r *BaseErrorWordDao) GetBaseErrorWord(maps interface{}) (m *model.BaseErrorWord, err error) { + err = global.Db.Where(maps).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetBaseErrorWordPageSearch 获取列表-分页 +func (r *BaseErrorWordDao) GetBaseErrorWordPageSearch(page, pageSize int) (m []*model.BaseErrorWord, total int64, err error) { + var totalRecords int64 + + // 构建查询条件 + query := global.Db.Model(&model.BaseErrorWord{}) + + // 排序 + query = query.Order("created_at desc") + + // 查询总数量 + if err := query.Count(&totalRecords).Error; err != nil { + return nil, 0, err + } + + err = query.Scopes(model.Paginate(page, pageSize)).Find(&m).Error + if err != nil { + return nil, 0, err + } + return m, totalRecords, nil +} diff --git a/api/dao/Question.go b/api/dao/Question.go index fc919ac..3e77c08 100644 --- a/api/dao/Question.go +++ b/api/dao/Question.go @@ -270,3 +270,21 @@ func (r *QuestionDao) GetQuestionNotInListRand(maps interface{}, notQuestionId [ } return m, nil } + +// GetQuestionListByWord 获取列表-模糊查询-字 +func (r *QuestionDao) GetQuestionListByWord(word string) (m []*model.Question, err error) { + query := global.Db + + keyword := "%" + word + "%" + + query = query. + Or("question_name LIKE ?", keyword). + Or("question_answer LIKE ?", keyword). + Or("question_analysis LIKE ?", keyword) + + err = query.Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} diff --git a/api/dto/BaseErrorWord.go b/api/dto/BaseErrorWord.go new file mode 100644 index 0000000..a3d29c2 --- /dev/null +++ b/api/dto/BaseErrorWord.go @@ -0,0 +1,53 @@ +package dto + +import ( + "fmt" + "knowledge/api/model" +) + +// BaseErrorWordDto 基础数据-错别字 +type BaseErrorWordDto struct { + WordId string `json:"word_id"` // 主键id + WordOld string `json:"word_old"` // 错别字 + WordNew string `json:"word_new"` // 新字 + QuestionIds string `json:"question_ids"` // 操作关联问题id + OperationTime *model.LocalTime `json:"operation_time"` // 操作时间 + CreatedAt model.LocalTime `json:"created_at"` // 创建时间 + UpdatedAt model.LocalTime `json:"updated_at"` // 修改时间 +} + +// GetBaseErrorWordDto 详情 +func GetBaseErrorWordDto(m *model.BaseErrorWord) *BaseErrorWordDto { + return &BaseErrorWordDto{ + WordId: fmt.Sprintf("%d", m.WordId), + WordOld: m.WordOld, + WordNew: m.WordNew, + OperationTime: m.OperationTime, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, + } +} + +// GetBaseErrorWordListDto 列表 +func GetBaseErrorWordListDto(m []*model.BaseErrorWord) []*BaseErrorWordDto { + // 处理返回值 + responses := make([]*BaseErrorWordDto, len(m)) + + if len(m) > 0 { + for i, v := range m { + response := &BaseErrorWordDto{ + WordId: fmt.Sprintf("%d", v.WordId), + WordOld: v.WordOld, + WordNew: v.WordNew, + OperationTime: v.OperationTime, + CreatedAt: v.CreatedAt, + UpdatedAt: v.UpdatedAt, + } + + // 将转换后的结构体添加到新切片中 + responses[i] = response + } + } + + return responses +} diff --git a/api/model/BaseErrorWord.go b/api/model/BaseErrorWord.go new file mode 100644 index 0000000..8dd93b4 --- /dev/null +++ b/api/model/BaseErrorWord.go @@ -0,0 +1,35 @@ +package model + +import ( + "gorm.io/gorm" + "knowledge/global" + "time" +) + +// BaseErrorWord 基础数据-错别字 +type BaseErrorWord struct { + WordId int64 `gorm:"column:word_id;type:bigint(19);primary_key;comment:主键id" json:"word_id"` + WordOld string `gorm:"column:word_old;type:varchar(255);comment:错别字" json:"word_old"` + WordNew string `gorm:"column:word_new;type:varchar(255);comment:新字" json:"word_new"` + QuestionIds string `gorm:"column:question_ids;type:text;comment:操作关联问题id" json:"question_ids"` + OperationTime *LocalTime `gorm:"column:operation_time;type:datetime;comment:操作时间" json:"operation_time"` + Model +} + +func (m *BaseErrorWord) TableName() string { + return "kb_base_error_word" +} + +func (m *BaseErrorWord) BeforeCreate(tx *gorm.DB) error { + if m.WordId == 0 { + m.WordId = global.Snowflake.Generate().Int64() + } + + m.CreatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("CreatedAt", m.CreatedAt) + + m.UpdatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt) + + return nil +} diff --git a/api/requests/BaseErrorWord.go b/api/requests/BaseErrorWord.go new file mode 100644 index 0000000..080b662 --- /dev/null +++ b/api/requests/BaseErrorWord.go @@ -0,0 +1,18 @@ +package requests + +type BaseErrorWordRequest struct { + GetBaseErrorWordPage // 获取列表-分页 + AddBaseErrorWord // 新增 +} + +// GetBaseErrorWordPage 获取列表-分页 +type GetBaseErrorWordPage struct { + Page int `json:"page" form:"page" label:"页码"` + PageSize int `json:"page_size" form:"page_size" label:"每页个数"` +} + +// AddBaseErrorWord 新增 +type AddBaseErrorWord struct { + WordOld string `json:"word_old" form:"word_old" label:"错别字" validate:"required"` + WordNew string `json:"word_new" form:"word_new" label:"新字" validate:"required"` +} diff --git a/api/router/router.go b/api/router/router.go index dea5eb0..62808e4 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -244,6 +244,22 @@ func privateRouter(r *gin.Engine, api controller.Api) { itemGroup.DELETE("/:item_id", api.BaseTokenItem.DeleteBaseTokenItem) } } + + // 错别字字典 + errorGroup := baseGroup.Group("/error") + { + // 获取错别字列表 + errorGroup.GET("/list", api.BaseErrorWord.GetBaseErrorWordPage) + + // 新增错别字 + errorGroup.POST("", api.BaseErrorWord.AddBaseErrorWord) + + // 删除错别字 + errorGroup.DELETE("/:word_id", api.BaseErrorWord.DeleteBaseErrorWord) + + // 一键修改错别字 + errorGroup.POST("/:word_id", api.BaseErrorWord.OperationErrorWord) + } } // 统计 diff --git a/utils/replace.go b/utils/replace.go index 9ddae66..c47c095 100644 --- a/utils/replace.go +++ b/utils/replace.go @@ -38,3 +38,8 @@ func GetExtension(s string) string { } return "" } + +// ReplaceString 替换字符串 +func ReplaceString(str, old, new string) string { + return strings.ReplaceAll(str, old, new) +}