refactor: 后端仓库层更名为数据访问层(internal/repository → internal/dal)
「仓库层」是 repository 的直译,中文里与「代码仓库 / git 仓库」同词, 而这一层做的事就是数据访问。名字改成它实际在做的事。 改名口径(纯机械替换,无逻辑改动): - 包:internal/repository → internal/dal(package repository → package dal) - 类型:XxxRepo → XxxDAO(TaskRecordDAO / SpecialistDAO / PositionDAO …) - 变量:xxxRepo → xxxDAO - import 路径、包限定符、日志前缀 [repository] → [dal] 同步 - 注释里的「仓库层」→「数据访问层」;core.go 包注释补上 DAL/DAO 全称 命名规范补登(AR09 是命名问题的最高依据,改了名就得回去登记): - AR09 §3.1 术语表新增「数据访问层 dal / DAO」一行 - AR09 §5.6 缩写表新增 DAO / dal —— 原文是「只有下表内的缩写允许使用」, 不登记就是自己破自己的规矩 - PROJECT_STATE.md 新增 D27 记录本次更名决策 验证:全部在 db 副本上做,生产库 data/eai_agentplatform.db 未触碰。 - 等价性对照:拿 HEAD 源码 + 仅改名 造出第二棵树,两棵树各自起 httptest 服务跑同一份探针(60 个 GET + 13 个写/回读,覆盖专员/技能/应用/ 任务/交付物/项目/岗位/考试/知识/积分/管理端只读等),逐端点比对响应体: 73 项里 52 项字节完全一致、21 项仅运行期时间戳不同、内容差异 0。 - 探针非空:往改名后的树注入「SpecialistDAO.List 限 3 条」变异, /api/specialists 立刻被抓出 —— 证明上面那个 0 不是没测到。 - 暂存区自洽:把索引整个导出成源码树,go build / go vet / go test ./... 全绿。 - gofmt:因 import 排序变化而错位的 19 个文件已修;另 2 个文件(skill_definition.go、 seed.go)的格式问题是工作区里别人的在制品带来的,未替其改动。 未纳入本次提交:工作区里正在进行中的「文生语音技能 + 技能展示色/交互卡」 (tts_handlers.go、text_to_speech/manifest.go、skillCatalog.js 等), 以及 router.go / skill_definition.go / seed.go 三个文件里属于该在制品的改动 —— 这三个文件只把「改名那一版」放进索引,工作区原样保留。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -5,17 +5,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/jsonutil"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// actionDefinitionRepo 动作定义仓库(便于测试时覆写),包内共享。
|
||||
var actionDefinitionRepo repository.ActionDefinitionRepo
|
||||
// actionDefinitionDAO 动作定义仓库(便于测试时覆写),包内共享。
|
||||
var actionDefinitionDAO dal.ActionDefinitionDAO
|
||||
|
||||
func init() {
|
||||
actionDefinitionRepo = repository.ActionDefinitionRepo{}
|
||||
actionDefinitionDAO = dal.ActionDefinitionDAO{}
|
||||
}
|
||||
|
||||
type actionDefinitionReq struct {
|
||||
@@ -91,7 +91,7 @@ func ListActionDefinitions(c *gin.Context) {
|
||||
if state == "" {
|
||||
state = "active"
|
||||
}
|
||||
web.OK(c, actionDefinitionRepo.List(state))
|
||||
web.OK(c, actionDefinitionDAO.List(state))
|
||||
}
|
||||
|
||||
func GetActionDefinitionByKey(c *gin.Context) {
|
||||
@@ -100,7 +100,7 @@ func GetActionDefinitionByKey(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("action key 不能为空"))
|
||||
return
|
||||
}
|
||||
item, found := actionDefinitionRepo.GetByKey(key)
|
||||
item, found := actionDefinitionDAO.GetByKey(key)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("Action 定义不存在"))
|
||||
return
|
||||
@@ -134,7 +134,7 @@ func CreateActionDefinition(c *gin.Context) {
|
||||
State: req.State,
|
||||
SortOrder: req.SortOrder,
|
||||
}
|
||||
if !actionDefinitionRepo.Insert(&item) {
|
||||
if !actionDefinitionDAO.Insert(&item) {
|
||||
web.Fail(c, web.NewBadRequest("创建 Action 定义失败"))
|
||||
return
|
||||
}
|
||||
@@ -146,7 +146,7 @@ func UpdateActionDefinition(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
item, found := actionDefinitionRepo.GetByID(id)
|
||||
item, found := actionDefinitionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("Action 定义不存在"))
|
||||
return
|
||||
@@ -174,7 +174,7 @@ func UpdateActionDefinition(c *gin.Context) {
|
||||
item.OntologyBindingJSON = req.OntologyBindingJSON
|
||||
item.State = req.State
|
||||
item.SortOrder = req.SortOrder
|
||||
if !actionDefinitionRepo.Update(&item) {
|
||||
if !actionDefinitionDAO.Update(&item) {
|
||||
web.Fail(c, web.NewBadRequest("更新 Action 定义失败"))
|
||||
return
|
||||
}
|
||||
@@ -186,12 +186,12 @@ func DeleteActionDefinition(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
item, found := actionDefinitionRepo.GetByID(id)
|
||||
item, found := actionDefinitionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("Action 定义不存在"))
|
||||
return
|
||||
}
|
||||
if !actionDefinitionRepo.Delete(&item) {
|
||||
if !actionDefinitionDAO.Delete(&item) {
|
||||
web.Fail(c, web.NewBadRequest("删除 Action 定义失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
user, found := userRepo.GetByUsername(req.Username)
|
||||
user, found := userDAO.GetByUsername(req.Username)
|
||||
if !found {
|
||||
web.Fail(c, web.NewAuthError("用户名或密码错误"))
|
||||
return
|
||||
|
||||
@@ -6,17 +6,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// certRepo 证书仓库(便于测试时覆写),包内共享。
|
||||
var certRepo repository.CertificateRepo
|
||||
// certDAO 证书仓库(便于测试时覆写),包内共享。
|
||||
var certDAO dal.CertificateDAO
|
||||
|
||||
func init() {
|
||||
certRepo = repository.CertificateRepo{}
|
||||
certDAO = dal.CertificateDAO{}
|
||||
}
|
||||
|
||||
// issueCertificate 正式考试通过后颁发证书(幂等:同一 exam_record 只发一张)。
|
||||
@@ -24,11 +24,11 @@ func issueCertificate(u *model.User, rec model.ExamRecord) {
|
||||
if u == nil || !rec.Passed {
|
||||
return
|
||||
}
|
||||
if _, found := certRepo.GetByExamRecord(rec.ID); found {
|
||||
if _, found := certDAO.GetByExamRecord(rec.ID); found {
|
||||
return
|
||||
}
|
||||
certNo := fmt.Sprintf("BST-%06d", rec.ID)
|
||||
certRepo.Insert(&model.Certificate{
|
||||
certDAO.Insert(&model.Certificate{
|
||||
UserID: u.ID, ExamRecordID: rec.ID, UserName: u.FullName,
|
||||
ExamName: rec.ExamName, Score: rec.Score, TotalScore: rec.TotalScore, PassScore: rec.PassScore,
|
||||
CertNo: certNo, IssuedAt: time.Now(),
|
||||
@@ -42,7 +42,7 @@ func MyCertificates(c *gin.Context) {
|
||||
web.Fail(c, web.NewAuthError("未登录"))
|
||||
return
|
||||
}
|
||||
items := certRepo.ListByUser(u.ID)
|
||||
items := certDAO.ListByUser(u.ID)
|
||||
if items == nil {
|
||||
items = []model.Certificate{}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func CertificateDetail(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cert, found := certRepo.GetByID(id)
|
||||
cert, found := certDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("证书不存在"))
|
||||
return
|
||||
@@ -70,5 +70,5 @@ func CertificateDetail(c *gin.Context) {
|
||||
|
||||
// AdminCertificates GET /api/system/certificates —— 全员证书(管理员)
|
||||
func AdminCertificates(c *gin.Context) {
|
||||
web.OK(c, certRepo.ListAll())
|
||||
web.OK(c, certDAO.ListAll())
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ import (
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// 本文件用到的仓库:configRepo 声明在 system.go,mediaRepo 声明在 media.go。
|
||||
// 本文件用到的仓库:configDAO 声明在 system.go,mediaDAO 声明在 media.go。
|
||||
// GetCompanyTrain GET /api/company-train
|
||||
// content 取 system_config(company_intro),medias 取已审批的公司绑定素材
|
||||
func GetCompanyTrain(c *gin.Context) {
|
||||
content := configRepo.GetByKey("company_intro")
|
||||
files := mediaRepo.ListApprovedByBindType("company")
|
||||
content := configDAO.GetByKey("company_intro")
|
||||
files := mediaDAO.ListApprovedByBindType("company")
|
||||
|
||||
type mediaItem struct {
|
||||
ID uint `json:"id"`
|
||||
@@ -100,7 +100,7 @@ func SuggestMaterial(c *gin.Context) {
|
||||
BindType: "none",
|
||||
Remark: remark,
|
||||
}
|
||||
if !mediaRepo.Insert(&m) {
|
||||
if !mediaDAO.Insert(&m) {
|
||||
web.Fail(c, web.NewBadRequest("创建素材记录失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// 本文件的仓库实例:courseRepo 声明在 position.go,mediaRepo 声明在 media.go。
|
||||
// 本文件的仓库实例:courseDAO 声明在 position.go,mediaDAO 声明在 media.go。
|
||||
|
||||
// courseView 课程详情视图(含绑定产品)
|
||||
func courseView(c *gin.Context, co model.Course) {
|
||||
@@ -32,12 +32,12 @@ func courseView(c *gin.Context, co model.Course) {
|
||||
"updated_at": co.UpdatedAt,
|
||||
}
|
||||
if co.RelatedProductID != nil {
|
||||
if p, ok := productRepo.GetVisibleByID(*co.RelatedProductID); ok {
|
||||
if p, ok := productDAO.GetVisibleByID(*co.RelatedProductID); ok {
|
||||
out["product"] = gin.H{"id": p.ID, "code": p.Code, "name": p.Name, "category": p.Category}
|
||||
}
|
||||
}
|
||||
|
||||
medias := mediaRepo.ListByBind("course", co.ID)
|
||||
medias := mediaDAO.ListByBind("course", co.ID)
|
||||
if len(medias) > 0 {
|
||||
items := make([]gin.H, 0, len(medias))
|
||||
for _, m := range medias {
|
||||
@@ -55,7 +55,7 @@ func courseView(c *gin.Context, co model.Course) {
|
||||
|
||||
// ListCourses GET /api/courses?category=&status=
|
||||
func ListCourses(c *gin.Context) {
|
||||
web.OK(c, courseRepo.List(c.Query("category"), c.Query("status")))
|
||||
web.OK(c, courseDAO.List(c.Query("category"), c.Query("status")))
|
||||
}
|
||||
|
||||
// GetCourse GET /api/courses/{id}
|
||||
@@ -64,7 +64,7 @@ func GetCourse(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
co, found := courseRepo.GetByID(id)
|
||||
co, found := courseDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("课程不存在"))
|
||||
return
|
||||
@@ -83,14 +83,14 @@ func CreateCourse(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("编号、名称、分类为必填"))
|
||||
return
|
||||
}
|
||||
if courseRepo.CountByCode(co.Code, nil) > 0 {
|
||||
if courseDAO.CountByCode(co.Code, nil) > 0 {
|
||||
web.Fail(c, web.NewConflictError("课程编号已存在"))
|
||||
return
|
||||
}
|
||||
if co.Status == "" {
|
||||
co.Status = "active"
|
||||
}
|
||||
if !courseRepo.Insert(&co) {
|
||||
if !courseDAO.Insert(&co) {
|
||||
web.Fail(c, web.NewBadRequest("创建课程失败"))
|
||||
return
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func UpdateCourse(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
co, found := courseRepo.GetByID(id)
|
||||
co, found := courseDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("课程不存在"))
|
||||
return
|
||||
@@ -122,7 +122,7 @@ func UpdateCourse(c *gin.Context) {
|
||||
}
|
||||
|
||||
if req.Code != "" && req.Code != co.Code {
|
||||
if courseRepo.CountByCode(req.Code, &id) > 0 {
|
||||
if courseDAO.CountByCode(req.Code, &id) > 0 {
|
||||
web.Fail(c, web.NewConflictError("课程编号已存在"))
|
||||
return
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func UpdateCourse(c *gin.Context) {
|
||||
co.RelatedProductID = req.RelatedProductID
|
||||
co.Status = req.Status
|
||||
|
||||
if !courseRepo.Update(&co) {
|
||||
if !courseDAO.Update(&co) {
|
||||
web.Fail(c, web.NewBadRequest("更新课程失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,23 +7,23 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// deptRepo 部门仓库(便于测试时覆写),包内共享。
|
||||
var deptRepo repository.DepartmentRepo
|
||||
// deptDAO 部门仓库(便于测试时覆写),包内共享。
|
||||
var deptDAO dal.DepartmentDAO
|
||||
|
||||
func init() {
|
||||
deptRepo = repository.DepartmentRepo{}
|
||||
deptDAO = dal.DepartmentDAO{}
|
||||
}
|
||||
|
||||
// ListDepartments GET /api/departments?status= —— 部门字典列表(含成员数)
|
||||
func ListDepartments(c *gin.Context) {
|
||||
items := deptRepo.ListByStatus(c.Query("status"))
|
||||
items := deptDAO.ListByStatus(c.Query("status"))
|
||||
// 成员数按 user.department 字符串匹配(部门为字典、用户以字符串归属)
|
||||
users := userRepo.ListEmployees("active")
|
||||
users := userDAO.ListEmployees("active")
|
||||
nameCount := map[string]int{}
|
||||
for _, u := range users {
|
||||
if strings.TrimSpace(u.Department) != "" {
|
||||
@@ -55,12 +55,12 @@ func CreateDepartment(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
if deptRepo.CountByName(req.Name, nil) > 0 {
|
||||
if deptDAO.CountByName(req.Name, nil) > 0 {
|
||||
web.Fail(c, web.NewConflictError("部门名称已存在"))
|
||||
return
|
||||
}
|
||||
d := model.Department{Name: req.Name, Description: req.Description, Status: "active"}
|
||||
if !deptRepo.Insert(&d) {
|
||||
if !deptDAO.Insert(&d) {
|
||||
web.Fail(c, web.NewBadRequest("创建部门失败"))
|
||||
return
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func UpdateDepartment(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
d, found := deptRepo.GetByID(id)
|
||||
d, found := deptDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("部门不存在"))
|
||||
return
|
||||
@@ -90,7 +90,7 @@ func UpdateDepartment(c *gin.Context) {
|
||||
req.Name = strings.TrimSpace(req.Name)
|
||||
oldName := d.Name
|
||||
if req.Name != oldName {
|
||||
if deptRepo.CountByName(req.Name, &id) > 0 {
|
||||
if deptDAO.CountByName(req.Name, &id) > 0 {
|
||||
web.Fail(c, web.NewConflictError("部门名称已存在"))
|
||||
return
|
||||
}
|
||||
@@ -100,13 +100,13 @@ func UpdateDepartment(c *gin.Context) {
|
||||
if req.Status == "active" || req.Status == "inactive" {
|
||||
d.Status = req.Status
|
||||
}
|
||||
if !deptRepo.Update(&d) {
|
||||
if !deptDAO.Update(&d) {
|
||||
web.Fail(c, web.NewBadRequest("更新部门失败"))
|
||||
return
|
||||
}
|
||||
// 改名后同步员工归属,保证按部门统计与展示一致
|
||||
if req.Name != oldName {
|
||||
userRepo.RenameDepartment(oldName, req.Name)
|
||||
userDAO.RenameDepartment(oldName, req.Name)
|
||||
}
|
||||
web.OK(c, d)
|
||||
}
|
||||
@@ -117,16 +117,16 @@ func DeleteDepartment(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
d, found := deptRepo.GetByID(id)
|
||||
d, found := deptDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("部门不存在"))
|
||||
return
|
||||
}
|
||||
if n := userRepo.CountActiveByDepartment(d.Name); n > 0 {
|
||||
if n := userDAO.CountActiveByDepartment(d.Name); n > 0 {
|
||||
web.Fail(c, web.NewConflictError(fmt.Sprintf("该部门下仍有 %d 名员工,请先调整其部门", n)))
|
||||
return
|
||||
}
|
||||
if !deptRepo.Delete(id) {
|
||||
if !deptDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("删除部门失败"))
|
||||
return
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func DeleteDepartment(c *gin.Context) {
|
||||
|
||||
// DepartmentStats GET /api/system/department-stats —— 按部门学情聚合
|
||||
func DepartmentStats(c *gin.Context) {
|
||||
employees := userRepo.ListEmployees("active")
|
||||
employees := userDAO.ListEmployees("active")
|
||||
|
||||
// 每用户聚合:积分 / 考试 / 学习进度
|
||||
type userAgg struct {
|
||||
@@ -159,7 +159,7 @@ func DepartmentStats(c *gin.Context) {
|
||||
for _, e := range employees {
|
||||
get(e.ID).Points = e.LearningPoints
|
||||
}
|
||||
recs := examRecordRepo.ListAll()
|
||||
recs := examRecordDAO.ListAll()
|
||||
for _, r := range recs {
|
||||
a := get(r.UserID)
|
||||
a.FormalCount++
|
||||
@@ -168,7 +168,7 @@ func DepartmentStats(c *gin.Context) {
|
||||
}
|
||||
a.ScoreSum += r.Score
|
||||
}
|
||||
lps := learningRepo.ListAll()
|
||||
lps := learningDAO.ListAll()
|
||||
for _, lp := range lps {
|
||||
a := get(lp.UserID)
|
||||
switch lp.ItemType {
|
||||
|
||||
@@ -14,25 +14,25 @@ import (
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"eai_agentplatform/backend/internal/auth"
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// 考试域仓库,包内共享(知识源摄入也会写题目,见 knowledge.go)。
|
||||
var (
|
||||
mistakeRepo repository.MistakeRecordRepo
|
||||
questionRepo repository.QuestionRepo
|
||||
paperRepo repository.ExamPaperRepo
|
||||
examRecordRepo repository.ExamRecordRepo
|
||||
mistakeDAO dal.MistakeRecordDAO
|
||||
questionDAO dal.QuestionDAO
|
||||
paperDAO dal.ExamPaperDAO
|
||||
examRecordDAO dal.ExamRecordDAO
|
||||
)
|
||||
|
||||
func init() {
|
||||
mistakeRepo = repository.MistakeRecordRepo{}
|
||||
questionRepo = repository.QuestionRepo{}
|
||||
paperRepo = repository.ExamPaperRepo{}
|
||||
examRecordRepo = repository.ExamRecordRepo{}
|
||||
mistakeDAO = dal.MistakeRecordDAO{}
|
||||
questionDAO = dal.QuestionDAO{}
|
||||
paperDAO = dal.ExamPaperDAO{}
|
||||
examRecordDAO = dal.ExamRecordDAO{}
|
||||
}
|
||||
|
||||
// Option 题目选项
|
||||
@@ -84,7 +84,7 @@ func questionView(q model.Question) gin.H {
|
||||
// ListQuestions GET /api/exam/questions?domain=&status=
|
||||
func ListQuestions(c *gin.Context) {
|
||||
// 管理端题库:status 缺省要看到全部(含已停用),按约定传 "all"
|
||||
items := questionRepo.List(c.Query("domain"), orDefault(c.Query("status"), "all"))
|
||||
items := questionDAO.List(c.Query("domain"), orDefault(c.Query("status"), "all"))
|
||||
out := make([]gin.H, 0, len(items))
|
||||
for _, it := range items {
|
||||
out = append(out, questionView(it))
|
||||
@@ -119,7 +119,7 @@ func CreateQuestion(c *gin.Context) {
|
||||
Explanation: req.Explanation,
|
||||
Status: "active",
|
||||
}
|
||||
if !questionRepo.Insert(&q) {
|
||||
if !questionDAO.Insert(&q) {
|
||||
web.Fail(c, web.NewBadRequest("创建题目失败"))
|
||||
return
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func UpdateQuestion(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
q, found := questionRepo.GetByID(id)
|
||||
q, found := questionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("题目不存在"))
|
||||
return
|
||||
@@ -159,7 +159,7 @@ func UpdateQuestion(c *gin.Context) {
|
||||
q.Options = string(optsJSON)
|
||||
q.Answer = string(ansJSON)
|
||||
q.Explanation = req.Explanation
|
||||
if !questionRepo.Update(&q) {
|
||||
if !questionDAO.Update(&q) {
|
||||
web.Fail(c, web.NewBadRequest("更新题目失败"))
|
||||
return
|
||||
}
|
||||
@@ -172,11 +172,11 @@ func DeleteQuestion(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, found := questionRepo.GetByID(id); !found {
|
||||
if _, found := questionDAO.GetByID(id); !found {
|
||||
web.Fail(c, web.NewNotFoundError("题目不存在"))
|
||||
return
|
||||
}
|
||||
if !questionRepo.Delete(id) {
|
||||
if !questionDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("停用题目失败"))
|
||||
return
|
||||
}
|
||||
@@ -187,7 +187,7 @@ func DeleteQuestion(c *gin.Context) {
|
||||
|
||||
// ListPapers GET /api/exam/papers
|
||||
func ListPapers(c *gin.Context) {
|
||||
web.OK(c, paperRepo.List())
|
||||
web.OK(c, paperDAO.List())
|
||||
}
|
||||
|
||||
// CreatePaper POST /api/exam/papers (admin)
|
||||
@@ -208,7 +208,7 @@ func CreatePaper(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
p.Status = "active"
|
||||
if !paperRepo.Insert(&p) {
|
||||
if !paperDAO.Insert(&p) {
|
||||
web.Fail(c, web.NewBadRequest("创建考试失败"))
|
||||
return
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func UpdatePaper(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p, found := paperRepo.GetByID(id)
|
||||
p, found := paperDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("考试配置不存在"))
|
||||
return
|
||||
@@ -253,7 +253,7 @@ func UpdatePaper(c *gin.Context) {
|
||||
if req.Status != "" {
|
||||
p.Status = req.Status
|
||||
}
|
||||
if !paperRepo.Update(&p) {
|
||||
if !paperDAO.Update(&p) {
|
||||
web.Fail(c, web.NewBadRequest("更新考试失败"))
|
||||
return
|
||||
}
|
||||
@@ -266,11 +266,11 @@ func DeletePaper(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, found := paperRepo.GetByID(id); !found {
|
||||
if _, found := paperDAO.GetByID(id); !found {
|
||||
web.Fail(c, web.NewNotFoundError("考试配置不存在"))
|
||||
return
|
||||
}
|
||||
if !paperRepo.Delete(id) {
|
||||
if !paperDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("停用考试失败"))
|
||||
return
|
||||
}
|
||||
@@ -282,7 +282,7 @@ func DeletePaper(c *gin.Context) {
|
||||
// ExamList GET /api/exam/list —— 我的考试列表(含完成状态)
|
||||
func ExamList(c *gin.Context) {
|
||||
u := middleware.CurrentUser(c)
|
||||
items := paperRepo.GetActive()
|
||||
items := paperDAO.GetActive()
|
||||
|
||||
type row struct {
|
||||
ID uint `json:"id"`
|
||||
@@ -298,7 +298,7 @@ func ExamList(c *gin.Context) {
|
||||
out := make([]row, 0, len(items))
|
||||
for _, p := range items {
|
||||
st := "available"
|
||||
if p.Type == "formal" && u != nil && examRecordRepo.HasTaken(u.ID, p.ID) {
|
||||
if p.Type == "formal" && u != nil && examRecordDAO.HasTaken(u.ID, p.ID) {
|
||||
st = "completed"
|
||||
}
|
||||
out = append(out, row{
|
||||
@@ -318,7 +318,7 @@ func ExamCover(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
id := uint(id64)
|
||||
p, found := paperRepo.GetByID(id)
|
||||
p, found := paperDAO.GetByID(id)
|
||||
if !found || p.Status != "active" {
|
||||
web.Fail(c, web.NewNotFoundError("考试不存在或已停用"))
|
||||
return
|
||||
@@ -351,18 +351,18 @@ func pickQuestions(p model.ExamPaper) ([]model.Question, error) {
|
||||
var courseIDs []uint
|
||||
if p.PositionID != nil {
|
||||
// 岗位考试:优先蓝图,其次岗位知识映射
|
||||
if bps := positionRepo.Blueprints(*p.PositionID); len(bps) > 0 {
|
||||
if bps := positionDAO.Blueprints(*p.PositionID); len(bps) > 0 {
|
||||
return pickQuestionsByBlueprint(p, bps)
|
||||
}
|
||||
// 岗位考试:圈定岗位应学范围
|
||||
domains, courseIDs = positionScope(positionRepo.Knowledge(*p.PositionID))
|
||||
domains, courseIDs = positionScope(positionDAO.Knowledge(*p.PositionID))
|
||||
} else {
|
||||
// 原有逻辑:按 exam_paper.domain 抽题
|
||||
domains = splitDomains(p.Domain)
|
||||
}
|
||||
|
||||
var qs []model.Question
|
||||
if !questionRepo.ActivePool(domains, courseIDs).Order("id ASC").Find(&qs) {
|
||||
if !questionDAO.ActivePool(domains, courseIDs).Order("id ASC").Find(&qs) {
|
||||
return nil, fmt.Errorf("查询题库失败")
|
||||
}
|
||||
if len(qs) < p.QuestionCount {
|
||||
@@ -377,8 +377,8 @@ func pickQuestions(p model.ExamPaper) ([]model.Question, error) {
|
||||
// pickQuestionsByBlueprint 按岗位考试蓝图逐条抽题:先在岗位应学范围内,再按 (domain, type) 细分抽样。
|
||||
func pickQuestionsByBlueprint(p model.ExamPaper, bps []model.PositionExamBlueprint) ([]model.Question, error) {
|
||||
// 圈定岗位应学范围(与 P0 岗位知识映射抽题一致)
|
||||
domains, courseIDs := positionScope(positionRepo.Knowledge(*p.PositionID))
|
||||
base := questionRepo.ActivePool(domains, courseIDs)
|
||||
domains, courseIDs := positionScope(positionDAO.Knowledge(*p.PositionID))
|
||||
base := questionDAO.ActivePool(domains, courseIDs)
|
||||
|
||||
out := make([]model.Question, 0, p.QuestionCount)
|
||||
used := map[uint]bool{}
|
||||
@@ -456,12 +456,12 @@ func validatePaperPosition(c *gin.Context, positionID *uint) bool {
|
||||
if positionID == nil {
|
||||
return true
|
||||
}
|
||||
pos, found := positionRepo.GetByID(*positionID)
|
||||
pos, found := positionDAO.GetByID(*positionID)
|
||||
if !found || pos.Status != "active" {
|
||||
web.Fail(c, web.NewBadRequest("关联岗位不存在或已停用"))
|
||||
return false
|
||||
}
|
||||
if positionRepo.CountKnowledge(*positionID) == 0 {
|
||||
if positionDAO.CountKnowledge(*positionID) == 0 {
|
||||
web.Fail(c, web.NewBadRequest("岗位考试必须先配置岗位知识映射"))
|
||||
return false
|
||||
}
|
||||
@@ -473,7 +473,7 @@ func validatePaperBlueprintCount(c *gin.Context, p model.ExamPaper) bool {
|
||||
if p.PositionID == nil {
|
||||
return true
|
||||
}
|
||||
bps := positionRepo.Blueprints(*p.PositionID)
|
||||
bps := positionDAO.Blueprints(*p.PositionID)
|
||||
if len(bps) == 0 {
|
||||
return true
|
||||
}
|
||||
@@ -509,12 +509,12 @@ func ExamStart(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("paper_id 必填"))
|
||||
return
|
||||
}
|
||||
p, found := paperRepo.GetByID(req.PaperID)
|
||||
p, found := paperDAO.GetByID(req.PaperID)
|
||||
if !found || p.Status != "active" {
|
||||
web.Fail(c, web.NewNotFoundError("考试不存在或已停用"))
|
||||
return
|
||||
}
|
||||
if p.Type == "formal" && u != nil && examRecordRepo.HasTaken(u.ID, p.ID) {
|
||||
if p.Type == "formal" && u != nil && examRecordDAO.HasTaken(u.ID, p.ID) {
|
||||
web.Fail(c, web.NewConflictError("已参加过该正式考试"))
|
||||
return
|
||||
}
|
||||
@@ -676,7 +676,7 @@ func ExamSubmit(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("练习会话无题目"))
|
||||
return
|
||||
}
|
||||
qs := questionRepo.ListByIDs(ids)
|
||||
qs := questionDAO.ListByIDs(ids)
|
||||
qmap := make(map[uint]model.Question, len(qs))
|
||||
for _, q := range qs {
|
||||
qmap[q.ID] = q
|
||||
@@ -755,14 +755,14 @@ func ExamSubmit(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
p, found := paperRepo.GetByID(uint(pid))
|
||||
p, found := paperDAO.GetByID(uint(pid))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("考试不存在"))
|
||||
return
|
||||
}
|
||||
|
||||
// 正式考不可重复交卷
|
||||
if stype == "formal" && u != nil && examRecordRepo.HasTaken(u.ID, p.ID) {
|
||||
if stype == "formal" && u != nil && examRecordDAO.HasTaken(u.ID, p.ID) {
|
||||
web.Fail(c, web.NewConflictError("已参加过该正式考试"))
|
||||
return
|
||||
}
|
||||
@@ -772,7 +772,7 @@ func ExamSubmit(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("考试会话无题目"))
|
||||
return
|
||||
}
|
||||
questions := questionRepo.ListByIDs(ids)
|
||||
questions := questionDAO.ListByIDs(ids)
|
||||
qmap := make(map[uint]model.Question, len(questions))
|
||||
for _, q := range questions {
|
||||
qmap[q.ID] = q
|
||||
@@ -867,7 +867,7 @@ func ExamSubmit(c *gin.Context) {
|
||||
CorrectCount: correctCount, WrongCount: wrongCount,
|
||||
DetailJSON: string(detailJSON), SubmittedAt: time.Now(),
|
||||
}
|
||||
examRecordRepo.Insert(&rec)
|
||||
examRecordDAO.Insert(&rec)
|
||||
if passed {
|
||||
awardPoints(u.ID, "formal_pass", ptFormalPass, "paper", p.ID)
|
||||
issueCertificate(u, rec)
|
||||
@@ -897,7 +897,7 @@ func splitIDs(s string) []uint {
|
||||
// ExamRecordList GET /api/exam/record?page=&size= —— 我的考试记录
|
||||
func ExamRecordList(c *gin.Context) {
|
||||
u := middleware.CurrentUser(c)
|
||||
items := examRecordRepo.ListByUser(u.ID)
|
||||
items := examRecordDAO.ListByUser(u.ID)
|
||||
if items == nil {
|
||||
items = []model.ExamRecord{}
|
||||
}
|
||||
@@ -911,7 +911,7 @@ func ExamRecordDetail(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
rec, found := examRecordRepo.GetByID(id)
|
||||
rec, found := examRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("考试记录不存在"))
|
||||
return
|
||||
@@ -947,7 +947,7 @@ func mistakePayload(userID, questionID uint, source string, q model.Question, us
|
||||
|
||||
// recordMistake 答错入本:按 (user_id, question_id, source) 去重,再次答错则更新并重置为未掌握。
|
||||
func recordMistake(userID, questionID uint, q model.Question, userAns any, correct []string, source string) {
|
||||
mistakeRepo.RecordWrong(mistakePayload(userID, questionID, source, q, userAns, correct))
|
||||
mistakeDAO.RecordWrong(mistakePayload(userID, questionID, source, q, userAns, correct))
|
||||
}
|
||||
|
||||
// mistakeView 错题出参(answer 反序列化,便于前端直接展示)
|
||||
@@ -967,7 +967,7 @@ type mistakeView struct {
|
||||
// MyMistakes GET /api/exam/mistakes —— 我的错题本
|
||||
func MyMistakes(c *gin.Context) {
|
||||
u := middleware.CurrentUser(c)
|
||||
items := mistakeRepo.ListByUser(u.ID)
|
||||
items := mistakeDAO.ListByUser(u.ID)
|
||||
out := make([]mistakeView, 0, len(items))
|
||||
for _, it := range items {
|
||||
var userAns any
|
||||
@@ -994,7 +994,7 @@ func ResolveMistake(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
rec, found := mistakeRepo.GetByID(id)
|
||||
rec, found := mistakeDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("错题记录不存在"))
|
||||
return
|
||||
@@ -1013,7 +1013,7 @@ func ResolveMistake(c *gin.Context) {
|
||||
}
|
||||
wasResolved := rec.Resolved
|
||||
rec.Resolved = target
|
||||
if !mistakeRepo.Update(&rec) {
|
||||
if !mistakeDAO.Update(&rec) {
|
||||
web.Fail(c, web.NewBadRequest("更新错题状态失败"))
|
||||
return
|
||||
}
|
||||
@@ -1037,7 +1037,7 @@ func MistakePractice(c *gin.Context) {
|
||||
}
|
||||
_ = c.ShouldBindJSON(&req)
|
||||
|
||||
recs := mistakeRepo.ListForPractice(u.ID, req.Source, req.OnlyUnresolved)
|
||||
recs := mistakeDAO.ListForPractice(u.ID, req.Source, req.OnlyUnresolved)
|
||||
if len(recs) == 0 {
|
||||
web.Fail(c, web.NewBadRequest("暂无可重练的错题"))
|
||||
return
|
||||
@@ -1050,7 +1050,7 @@ func MistakePractice(c *gin.Context) {
|
||||
ids = dedupeUints(ids)
|
||||
|
||||
// 剔除已停用/删除的题目,仅下发可作答题目
|
||||
questions := questionRepo.ListActiveByIDs(ids)
|
||||
questions := questionDAO.ListActiveByIDs(ids)
|
||||
if len(questions) == 0 {
|
||||
web.Fail(c, web.NewBadRequest("错题对应题目已失效,暂无可重练题目"))
|
||||
return
|
||||
@@ -1101,11 +1101,11 @@ func MistakePractice(c *gin.Context) {
|
||||
// touchMistakeOnPractice 错题重练判分后同步错题状态:答对置为已掌握(加积分),答错重置为未掌握。
|
||||
func touchMistakeOnPractice(userID, questionID uint, q model.Question, userAns any, correct []string, resolved bool) {
|
||||
payload := mistakePayload(userID, questionID, "", q, userAns, correct)
|
||||
flipped, touched := mistakeRepo.TouchOnPractice(payload, resolved)
|
||||
flipped, touched := mistakeDAO.TouchOnPractice(payload, resolved)
|
||||
if !touched {
|
||||
// 防御性兜底:理论上重练题目均来自错题本,这里创建一条
|
||||
payload.Source = "re_practice"
|
||||
mistakeRepo.RecordWrong(payload)
|
||||
mistakeDAO.RecordWrong(payload)
|
||||
return
|
||||
}
|
||||
// 仅在「未掌握 → 已掌握」时加分,避免反复重练刷分
|
||||
|
||||
@@ -11,17 +11,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// sourceRepo 知识源仓库(便于测试时覆写),包内共享。
|
||||
var sourceRepo repository.KnowledgeSourceRepo
|
||||
// sourceDAO 知识源仓库(便于测试时覆写),包内共享。
|
||||
var sourceDAO dal.KnowledgeSourceDAO
|
||||
|
||||
func init() {
|
||||
sourceRepo = repository.KnowledgeSourceRepo{}
|
||||
sourceDAO = dal.KnowledgeSourceDAO{}
|
||||
}
|
||||
|
||||
// ============ 扫描 ============
|
||||
@@ -51,7 +51,7 @@ func KnowledgeScan(c *gin.Context) {
|
||||
continue // 非知识源文档,跳过
|
||||
}
|
||||
|
||||
if existing, found := sourceRepo.GetByFilePath(e.Name()); found {
|
||||
if existing, found := sourceDAO.GetByFilePath(e.Name()); found {
|
||||
results = append(results, gin.H{"file_path": e.Name(), "status": "skipped", "title": existing.Title})
|
||||
continue
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func KnowledgeScan(c *gin.Context) {
|
||||
AuditStatus: "pending",
|
||||
KnowledgeSpaceKey: ensureKnowledgeSpaceKeyOrDefault(orDefault(fm["knowledge_space_key"], inferKnowledgeSpaceKey(parseTitle(string(data)), fm["domain"], fm["category"]+" "+e.Name()))),
|
||||
}
|
||||
if !sourceRepo.Insert(&src) {
|
||||
if !sourceDAO.Insert(&src) {
|
||||
results = append(results, gin.H{"file_path": e.Name(), "status": "error", "title": src.Title})
|
||||
continue
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func KnowledgeAuditList(c *gin.Context) {
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
total, items := sourceRepo.ListForAudit(
|
||||
total, items := sourceDAO.ListForAudit(
|
||||
c.Query("status"), sanitizeSpaceKey(c.Query("knowledge_space_key")), page, size)
|
||||
web.OK(c, gin.H{"total": total, "items": items})
|
||||
}
|
||||
@@ -95,7 +95,7 @@ func KnowledgeAudit(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
src, found := sourceRepo.GetByID(id)
|
||||
src, found := sourceDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("知识源不存在"))
|
||||
return
|
||||
@@ -126,7 +126,7 @@ func KnowledgeAudit(c *gin.Context) {
|
||||
src.AuditAt = &now
|
||||
src.RejectReason = ""
|
||||
src.Ingested = true
|
||||
if !sourceRepo.Update(&src) {
|
||||
if !sourceDAO.Update(&src) {
|
||||
web.Fail(c, web.NewBadRequest("审批失败"))
|
||||
return
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func KnowledgeAudit(c *gin.Context) {
|
||||
src.RejectReason = req.RejectReason
|
||||
src.AuditBy = &auditBy
|
||||
src.AuditAt = &now
|
||||
if !sourceRepo.Update(&src) {
|
||||
if !sourceDAO.Update(&src) {
|
||||
web.Fail(c, web.NewBadRequest("审批失败"))
|
||||
return
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func KnowledgeStatus(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
src, found := sourceRepo.GetByID(id)
|
||||
src, found := sourceDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("知识源不存在"))
|
||||
return
|
||||
@@ -335,12 +335,12 @@ func ingestSource(src *model.KnowledgeSource) ([3]int, error) {
|
||||
ReportRules: kv["report_rules"],
|
||||
Status: "active",
|
||||
}
|
||||
if existing, found := productRepo.GetByCode(p.Code); found {
|
||||
if existing, found := productDAO.GetByCode(p.Code); found {
|
||||
p.ID = existing.ID
|
||||
p.CreatedAt = existing.CreatedAt // Save 整字段覆盖,不回填会把创建时间写成零值
|
||||
productRepo.Update(&p)
|
||||
productDAO.Update(&p)
|
||||
} else {
|
||||
productRepo.Insert(&p)
|
||||
productDAO.Insert(&p)
|
||||
}
|
||||
counts[0]++
|
||||
}
|
||||
@@ -351,7 +351,7 @@ func ingestSource(src *model.KnowledgeSource) ([3]int, error) {
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
chunkRepo.Insert(&model.KnowledgeChunk{
|
||||
chunkDAO.Insert(&model.KnowledgeChunk{
|
||||
KnowledgeSourceID: &src.ID,
|
||||
SourceType: "md",
|
||||
SourceID: strconv.FormatUint(uint64(src.ID), 10),
|
||||
@@ -383,7 +383,7 @@ func ingestSource(src *model.KnowledgeSource) ([3]int, error) {
|
||||
Explanation: kv["explanation"],
|
||||
Status: "active",
|
||||
}
|
||||
questionRepo.Insert(&q)
|
||||
questionDAO.Insert(&q)
|
||||
counts[2]++
|
||||
}
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// faqRepo FAQ 仓库(便于测试时覆写),包内共享。
|
||||
var faqRepo repository.KnowledgeFAQRepo
|
||||
// faqDAO FAQ 仓库(便于测试时覆写),包内共享。
|
||||
var faqDAO dal.KnowledgeFAQDAO
|
||||
|
||||
func init() {
|
||||
faqRepo = repository.KnowledgeFAQRepo{}
|
||||
faqDAO = dal.KnowledgeFAQDAO{}
|
||||
}
|
||||
|
||||
// ListKnowledgeFAQs GET /api/knowledge/faqs?knowledge_space_key=&status=&keyword=&page=&size=
|
||||
@@ -29,7 +29,7 @@ func ListKnowledgeFAQs(c *gin.Context) {
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
total, items := faqRepo.ListForAdmin(
|
||||
total, items := faqDAO.ListForAdmin(
|
||||
sanitizeSpaceKey(c.Query("knowledge_space_key")),
|
||||
strings.TrimSpace(c.Query("status")),
|
||||
strings.TrimSpace(c.Query("keyword")),
|
||||
@@ -71,7 +71,7 @@ func CreateKnowledgeFAQ(c *gin.Context) {
|
||||
Status: orDefault(strings.TrimSpace(req.Status), "active"),
|
||||
SortOrder: req.SortOrder,
|
||||
}
|
||||
if !faqRepo.Insert(&faq) {
|
||||
if !faqDAO.Insert(&faq) {
|
||||
web.Fail(c, web.NewBadRequest("创建 FAQ 失败"))
|
||||
return
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func UpdateKnowledgeFAQ(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
faq, found := faqRepo.GetByID(id)
|
||||
faq, found := faqDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("FAQ 不存在"))
|
||||
return
|
||||
@@ -116,7 +116,7 @@ func UpdateKnowledgeFAQ(c *gin.Context) {
|
||||
faq.Keywords = strings.Join(cleanStringList(req.Keywords), ",")
|
||||
faq.Status = orDefault(strings.TrimSpace(req.Status), "active")
|
||||
faq.SortOrder = req.SortOrder
|
||||
if !faqRepo.Update(&faq) {
|
||||
if !faqDAO.Update(&faq) {
|
||||
web.Fail(c, web.NewBadRequest("更新 FAQ 失败"))
|
||||
return
|
||||
}
|
||||
@@ -129,11 +129,11 @@ func DeleteKnowledgeFAQ(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if _, found := faqRepo.GetByID(id); !found {
|
||||
if _, found := faqDAO.GetByID(id); !found {
|
||||
web.Fail(c, web.NewNotFoundError("FAQ 不存在"))
|
||||
return
|
||||
}
|
||||
if !faqRepo.Delete(id) {
|
||||
if !faqDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("删除 FAQ 失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,10 +47,10 @@ func rebuildKnowledgeIndexNow() (int, error) {
|
||||
|
||||
func buildKnowledgeIndexItems() []ai.KnowledgeIndexItem {
|
||||
var chunks []model.KnowledgeChunk
|
||||
chunkRepo.Type(&chunks).Order("id ASC").Find(&chunks)
|
||||
chunkDAO.Type(&chunks).Order("id ASC").Find(&chunks)
|
||||
|
||||
// 与 AI 检索候选共用同一份「已审批」映射,避免两处过滤条件漂移。
|
||||
mediaMap, sourceMap := chunkRepo.ApprovedMetaMaps()
|
||||
mediaMap, sourceMap := chunkDAO.ApprovedMetaMaps()
|
||||
|
||||
items := make([]ai.KnowledgeIndexItem, 0, len(chunks))
|
||||
for _, chunk := range chunks {
|
||||
|
||||
@@ -175,7 +175,7 @@ func extractKnowledgeSpaceKey(ctx map[string]any) string {
|
||||
}
|
||||
|
||||
func matchKnowledgeFAQ(query, spaceKey string) (model.KnowledgeFAQ, bool) {
|
||||
faqs := faqRepo.ActiveCandidates(sanitizeSpaceKey(spaceKey))
|
||||
faqs := faqDAO.ActiveCandidates(sanitizeSpaceKey(spaceKey))
|
||||
queryNorm := normalizeQuestion(query)
|
||||
queryTerms := buildSearchTerms(query)
|
||||
bestScore := 0
|
||||
@@ -190,7 +190,7 @@ func matchKnowledgeFAQ(query, spaceKey string) (model.KnowledgeFAQ, bool) {
|
||||
if bestScore < 70 {
|
||||
return model.KnowledgeFAQ{}, false
|
||||
}
|
||||
faqRepo.IncrHit(best.ID)
|
||||
faqDAO.IncrHit(best.ID)
|
||||
return best, true
|
||||
}
|
||||
|
||||
@@ -295,10 +295,10 @@ type retrievalScore struct {
|
||||
|
||||
func loadKnowledgeCandidates(spaceKey string) []knowledgeCandidate {
|
||||
var chunks []model.KnowledgeChunk
|
||||
chunkRepo.Type(&chunks).Order("id ASC").Find(&chunks)
|
||||
chunkDAO.Type(&chunks).Order("id ASC").Find(&chunks)
|
||||
// 必须传入真实的已审批映射:resolveChunkMeta 查不到就丢分片,
|
||||
// 传空 map 会让所有挂素材/知识源的分片消失,AI 检索候选集只剩无指针分片。
|
||||
mediaMap, sourceMap := chunkRepo.ApprovedMetaMaps()
|
||||
mediaMap, sourceMap := chunkDAO.ApprovedMetaMaps()
|
||||
out := make([]knowledgeCandidate, 0, len(chunks))
|
||||
for _, chunk := range chunks {
|
||||
title, resolvedSpace, ok := resolveChunkMeta(chunk, mediaMap, sourceMap)
|
||||
|
||||
@@ -8,19 +8,19 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
var (
|
||||
spaceRepo repository.KnowledgeSpaceRepo
|
||||
chunkRepo repository.KnowledgeChunkRepo
|
||||
spaceDAO dal.KnowledgeSpaceDAO
|
||||
chunkDAO dal.KnowledgeChunkDAO
|
||||
)
|
||||
|
||||
func init() {
|
||||
spaceRepo = repository.KnowledgeSpaceRepo{}
|
||||
chunkRepo = repository.KnowledgeChunkRepo{}
|
||||
spaceDAO = dal.KnowledgeSpaceDAO{}
|
||||
chunkDAO = dal.KnowledgeChunkDAO{}
|
||||
}
|
||||
|
||||
type spaceMetrics struct {
|
||||
@@ -88,7 +88,7 @@ func CreateKnowledgeSpace(c *gin.Context) {
|
||||
Status: orDefault(strings.TrimSpace(req.Status), "active"),
|
||||
SortOrder: req.SortOrder,
|
||||
}
|
||||
if spaceRepo.Insert(&space) {
|
||||
if spaceDAO.Insert(&space) {
|
||||
web.OK(c, gin.H{"item": space})
|
||||
return
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func UpdateKnowledgeSpace(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
space, found := spaceRepo.GetByID(id)
|
||||
space, found := spaceDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("知识空间不存在"))
|
||||
return
|
||||
@@ -128,7 +128,7 @@ func UpdateKnowledgeSpace(c *gin.Context) {
|
||||
space.Status = strings.TrimSpace(req.Status)
|
||||
}
|
||||
space.SortOrder = req.SortOrder
|
||||
if !spaceRepo.Update(&space) {
|
||||
if !spaceDAO.Update(&space) {
|
||||
web.Fail(c, web.NewBadRequest("更新知识空间失败"))
|
||||
return
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func DeleteKnowledgeSpace(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
space, found := spaceRepo.GetByID(id)
|
||||
space, found := spaceDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("知识空间不存在"))
|
||||
return
|
||||
@@ -150,7 +150,7 @@ func DeleteKnowledgeSpace(c *gin.Context) {
|
||||
web.Fail(c, web.NewConflictError("默认知识空间不可删除"))
|
||||
return
|
||||
}
|
||||
if !spaceRepo.Type(&model.KnowledgeSpace{}).Where("id = ?", id).Delete(&model.KnowledgeSpace{}) {
|
||||
if !spaceDAO.Type(&model.KnowledgeSpace{}).Where("id = ?", id).Delete(&model.KnowledgeSpace{}) {
|
||||
web.Fail(c, web.NewBadRequest("删除知识空间失败"))
|
||||
return
|
||||
}
|
||||
@@ -172,13 +172,13 @@ func SearchKnowledge(c *gin.Context) {
|
||||
}
|
||||
|
||||
var chunks []model.KnowledgeChunk
|
||||
chunkQuery := repository.DB.Model(&model.KnowledgeChunk{}).Order("created_at DESC")
|
||||
chunkQuery := dal.DB.Model(&model.KnowledgeChunk{}).Order("created_at DESC")
|
||||
if spaceKey != "" {
|
||||
chunkQuery = chunkQuery.Where("knowledge_space_key = ? OR knowledge_space_key = '' OR knowledge_space_key IS NULL", spaceKey)
|
||||
}
|
||||
chunkQuery.Limit(400).Find(&chunks)
|
||||
|
||||
// 这里刻意不用 chunkRepo.ApprovedMetaMaps():本站已把分片限制在 400 条内,
|
||||
// 这里刻意不用 chunkDAO.ApprovedMetaMaps():本站已把分片限制在 400 条内,
|
||||
// 按需只取被引用到的素材/知识源,比整表加载已审批记录更省。
|
||||
// 未命中审批状态的记录由 resolveChunkMeta 兜底拦掉,语义与那份批量映射一致。
|
||||
mediaMap := map[uint]model.MediaFile{}
|
||||
@@ -186,14 +186,14 @@ func SearchKnowledge(c *gin.Context) {
|
||||
for _, chunk := range chunks {
|
||||
if chunk.MediaFileID != nil {
|
||||
if _, ok := mediaMap[*chunk.MediaFileID]; !ok {
|
||||
if m, ok := mediaRepo.GetByID(*chunk.MediaFileID); ok {
|
||||
if m, ok := mediaDAO.GetByID(*chunk.MediaFileID); ok {
|
||||
mediaMap[*chunk.MediaFileID] = m
|
||||
}
|
||||
}
|
||||
}
|
||||
if chunk.KnowledgeSourceID != nil {
|
||||
if _, ok := sourceMap[*chunk.KnowledgeSourceID]; !ok {
|
||||
if s, ok := sourceRepo.GetByID(*chunk.KnowledgeSourceID); ok {
|
||||
if s, ok := sourceDAO.GetByID(*chunk.KnowledgeSourceID); ok {
|
||||
sourceMap[*chunk.KnowledgeSourceID] = s
|
||||
}
|
||||
}
|
||||
@@ -265,18 +265,18 @@ func listKnowledgeSpacesWithMetrics() ([]model.KnowledgeSpace, map[string]spaceM
|
||||
return nil, nil, err
|
||||
}
|
||||
var spaces []model.KnowledgeSpace
|
||||
spaceRepo.Type(&model.KnowledgeSpace{}).Order("sort_order ASC, id ASC").Find(&spaces)
|
||||
spaceDAO.Type(&model.KnowledgeSpace{}).Order("sort_order ASC, id ASC").Find(&spaces)
|
||||
metrics, err := buildKnowledgeSpaceMetrics()
|
||||
return spaces, metrics, err
|
||||
}
|
||||
|
||||
func ensureDefaultKnowledgeSpaces() error {
|
||||
for _, item := range defaultKnowledgeSpaces {
|
||||
_, found := spaceRepo.GetByName(item.Key)
|
||||
_, found := spaceDAO.GetByName(item.Key)
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
spaceRepo.Insert(&item)
|
||||
spaceDAO.Insert(&item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -288,9 +288,9 @@ func buildKnowledgeSpaceMetrics() (map[string]spaceMetrics, error) {
|
||||
}
|
||||
|
||||
// 这里要的是「全量已审批素材」,与 ListForAudit 的分页/排序口径不同,
|
||||
// 单个调用点不值得再加一个仓库方法,直接用包级 mediaRepo 取。
|
||||
// 单个调用点不值得再加一个仓库方法,直接用包级 mediaDAO 取。
|
||||
var mediaFiles []model.MediaFile
|
||||
mediaRepo.Type(&model.MediaFile{}).Where("status = ?", "approved").Find(&mediaFiles)
|
||||
mediaDAO.Type(&model.MediaFile{}).Where("status = ?", "approved").Find(&mediaFiles)
|
||||
for _, f := range mediaFiles {
|
||||
key := resolveMediaKnowledgeSpaceKey(f)
|
||||
m := metrics[key]
|
||||
@@ -303,7 +303,7 @@ func buildKnowledgeSpaceMetrics() (map[string]spaceMetrics, error) {
|
||||
}
|
||||
}
|
||||
|
||||
sources := sourceRepo.ListApproved()
|
||||
sources := sourceDAO.ListApproved()
|
||||
for _, s := range sources {
|
||||
key := resolveKnowledgeSourceSpaceKey(s)
|
||||
m := metrics[key]
|
||||
@@ -317,15 +317,15 @@ func buildKnowledgeSpaceMetrics() (map[string]spaceMetrics, error) {
|
||||
}
|
||||
|
||||
var chunks []model.KnowledgeChunk
|
||||
repository.DB.Find(&chunks)
|
||||
dal.DB.Find(&chunks)
|
||||
for _, chunk := range chunks {
|
||||
key := ensureKnowledgeSpaceKeyOrDefault(chunk.KnowledgeSpaceKey)
|
||||
if chunk.KnowledgeSourceID != nil {
|
||||
if src, ok := sourceRepo.GetByID(*chunk.KnowledgeSourceID); ok {
|
||||
if src, ok := sourceDAO.GetByID(*chunk.KnowledgeSourceID); ok {
|
||||
key = resolveKnowledgeSourceSpaceKey(src)
|
||||
}
|
||||
} else if chunk.MediaFileID != nil {
|
||||
if media, ok := mediaRepo.GetByID(*chunk.MediaFileID); ok {
|
||||
if media, ok := mediaDAO.GetByID(*chunk.MediaFileID); ok {
|
||||
key = resolveMediaKnowledgeSpaceKey(media)
|
||||
}
|
||||
} else if key == "general" {
|
||||
@@ -349,7 +349,7 @@ func getKnowledgeSpaceDisplayName(key string) string {
|
||||
return item.Name
|
||||
}
|
||||
}
|
||||
if space, ok := spaceRepo.GetByName(key); ok && strings.TrimSpace(space.Name) != "" {
|
||||
if space, ok := spaceDAO.GetByName(key); ok && strings.TrimSpace(space.Name) != "" {
|
||||
return space.Name
|
||||
}
|
||||
return key
|
||||
@@ -394,7 +394,7 @@ func ensureKnowledgeSpaceKeyOrDefault(key string) string {
|
||||
}
|
||||
}
|
||||
}
|
||||
_, ok := spaceRepo.GetByName(key)
|
||||
_, ok := spaceDAO.GetByName(key)
|
||||
if ok {
|
||||
return key
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// learningRepo 学习进度仓库(便于测试时覆写),包内共享。
|
||||
var learningRepo repository.LearningProgressRepo
|
||||
// learningDAO 学习进度仓库(便于测试时覆写),包内共享。
|
||||
var learningDAO dal.LearningProgressDAO
|
||||
|
||||
func init() {
|
||||
learningRepo = repository.LearningProgressRepo{}
|
||||
learningDAO = dal.LearningProgressDAO{}
|
||||
}
|
||||
|
||||
var validItemTypes = map[string]bool{"company": true, "product": true, "course": true}
|
||||
@@ -40,15 +40,15 @@ func RecordLearningProgress(c *gin.Context) {
|
||||
}
|
||||
lp := model.LearningProgress{UserID: u.ID, ItemType: req.ItemType, ItemID: req.ItemID}
|
||||
// 幂等:已存在则仅刷新 updated_at;首次记录才加分(避免重复刷分)
|
||||
if _, exists := learningRepo.Get(u.ID, req.ItemType, req.ItemID); !exists {
|
||||
if !learningRepo.Insert(&lp) {
|
||||
if _, exists := learningDAO.Get(u.ID, req.ItemType, req.ItemID); !exists {
|
||||
if !learningDAO.Insert(&lp) {
|
||||
web.Fail(c, web.NewBadRequest("记录学习进度失败"))
|
||||
return
|
||||
}
|
||||
awardFirstView(u.ID, req.ItemType, req.ItemID)
|
||||
} else {
|
||||
// Upsert 命中已存在分支时只刷新 updated_at,不新增行
|
||||
learningRepo.Upsert(&lp)
|
||||
learningDAO.Upsert(&lp)
|
||||
}
|
||||
web.OK(c, gin.H{"recorded": true, "item_type": req.ItemType, "item_id": req.ItemID})
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func MyLearningProgress(c *gin.Context) {
|
||||
web.Fail(c, web.NewAuthError("未登录"))
|
||||
return
|
||||
}
|
||||
items := learningRepo.ListByUser(u.ID)
|
||||
items := learningDAO.ListByUser(u.ID)
|
||||
if items == nil {
|
||||
items = []model.LearningProgress{}
|
||||
}
|
||||
@@ -70,8 +70,8 @@ func MyLearningProgress(c *gin.Context) {
|
||||
// AdminLearningProgress GET /api/system/learning-progress —— 全员学习进度(管理员)
|
||||
func AdminLearningProgress(c *gin.Context) {
|
||||
// 管理端全员视图:不限状态,已停用的员工也要能看到其历史进度
|
||||
employees := userRepo.ListEmployees("")
|
||||
items := learningRepo.ListAll()
|
||||
employees := userDAO.ListEmployees("")
|
||||
items := learningDAO.ListAll()
|
||||
|
||||
type agg struct {
|
||||
CompanyViewed bool `json:"company_viewed"`
|
||||
|
||||
@@ -16,17 +16,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// mediaRepo 素材仓库(便于测试时覆写),包内共享。
|
||||
var mediaRepo repository.MediaFileRepo
|
||||
// mediaDAO 素材仓库(便于测试时覆写),包内共享。
|
||||
var mediaDAO dal.MediaFileDAO
|
||||
|
||||
func init() {
|
||||
mediaRepo = repository.MediaFileRepo{}
|
||||
mediaDAO = dal.MediaFileDAO{}
|
||||
}
|
||||
|
||||
var blockedUploadExt = map[string]bool{
|
||||
@@ -196,7 +196,7 @@ func Upload(c *gin.Context) {
|
||||
BindID: bindID,
|
||||
KnowledgeSpaceKey: knowledgeSpaceKey,
|
||||
}
|
||||
if !mediaRepo.Insert(&m) {
|
||||
if !mediaDAO.Insert(&m) {
|
||||
web.Fail(c, web.NewBadRequest("创建素材记录失败"))
|
||||
return
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func UploadComplete(c *gin.Context) {
|
||||
Source: source, SubmitterID: u.ID, BindType: sess.BindType, BindID: sess.BindID,
|
||||
KnowledgeSpaceKey: sess.KnowledgeSpaceKey,
|
||||
}
|
||||
if !mediaRepo.Insert(&m) {
|
||||
if !mediaDAO.Insert(&m) {
|
||||
web.Fail(c, web.NewBadRequest("创建素材记录失败"))
|
||||
return
|
||||
}
|
||||
@@ -405,7 +405,7 @@ func Preview(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
m, found := mediaRepo.GetByID(id)
|
||||
m, found := mediaDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("素材不存在"))
|
||||
return
|
||||
@@ -427,7 +427,7 @@ func MediaStatus(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
m, found := mediaRepo.GetByID(id)
|
||||
m, found := mediaDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("素材不存在"))
|
||||
return
|
||||
@@ -435,7 +435,7 @@ func MediaStatus(c *gin.Context) {
|
||||
web.OK(c, gin.H{
|
||||
"status": m.Status,
|
||||
"extracted": m.Extracted,
|
||||
"chunk_count": chunkRepo.CountByMediaFile(m.ID),
|
||||
"chunk_count": chunkDAO.CountByMediaFile(m.ID),
|
||||
"knowledge_space_key": m.KnowledgeSpaceKey,
|
||||
})
|
||||
}
|
||||
@@ -452,7 +452,7 @@ func AuditList(c *gin.Context) {
|
||||
if size < 1 || size > 100 {
|
||||
size = 20
|
||||
}
|
||||
total, items := mediaRepo.ListForAudit(
|
||||
total, items := mediaDAO.ListForAudit(
|
||||
c.Query("status"), sanitizeSpaceKey(c.Query("knowledge_space_key")), page, size)
|
||||
web.OK(c, gin.H{"total": total, "items": items})
|
||||
}
|
||||
@@ -464,7 +464,7 @@ func AuditMedia(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
m, found := mediaRepo.GetByID(id)
|
||||
m, found := mediaDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("素材不存在"))
|
||||
return
|
||||
@@ -524,7 +524,7 @@ func AuditMedia(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("action 必须为 approve 或 reject"))
|
||||
return
|
||||
}
|
||||
if !mediaRepo.Update(&m) {
|
||||
if !mediaDAO.Update(&m) {
|
||||
web.Fail(c, web.NewBadRequest("审批失败"))
|
||||
return
|
||||
}
|
||||
@@ -538,7 +538,7 @@ func AuditMedia(c *gin.Context) {
|
||||
|
||||
// runExtractPipeline 审批通过后:文档转 PDF → pdftotext → 切片入库
|
||||
func runExtractPipeline(mediaID uint) {
|
||||
m, found := mediaRepo.GetByID(mediaID)
|
||||
m, found := mediaDAO.GetByID(mediaID)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
@@ -554,7 +554,7 @@ func runExtractPipeline(mediaID uint) {
|
||||
text, err = pdftotextExtract(src)
|
||||
default:
|
||||
// 视频/图片:仅标记,不提取
|
||||
mediaRepo.MarkExtracted(m.ID)
|
||||
mediaDAO.MarkExtracted(m.ID)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
@@ -579,8 +579,8 @@ func runExtractPipeline(mediaID uint) {
|
||||
Content: chunk,
|
||||
})
|
||||
}
|
||||
chunkRepo.BulkInsert(items)
|
||||
mediaRepo.MarkExtracted(m.ID)
|
||||
chunkDAO.BulkInsert(items)
|
||||
mediaDAO.MarkExtracted(m.ID)
|
||||
triggerKnowledgeIndexRebuild()
|
||||
log.Printf("[提取完成] media_id=%d chunks=%d", mediaID, len(chunks))
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func ListMyTasks(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 置顶的排在前面,其余按最近动过的排 —— 置顶只是一个排序偏好。
|
||||
web.OK(c, taskRecordRepo.ListByOwners(specialistruntime.MyTaskOwners(user), 50))
|
||||
web.OK(c, taskRecordDAO.ListByOwners(specialistruntime.MyTaskOwners(user), 50))
|
||||
}
|
||||
|
||||
// DeleteMyTask 彻底删掉一条任务。task_record 没有软删字段,删了就是删了 ——
|
||||
@@ -54,12 +54,12 @@ func DeleteMyTask(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
task, found := taskRecordDAO.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("任务不存在"))
|
||||
return
|
||||
}
|
||||
if !taskRecordRepo.Delete(&task) {
|
||||
if !taskRecordDAO.Delete(&task) {
|
||||
web.Fail(c, web.NewBadRequest("删除任务失败"))
|
||||
return
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func CreateMyTask(c *gin.Context) {
|
||||
if specialistKey == "" {
|
||||
specialistKey = generalAssistantKey
|
||||
}
|
||||
specialist, found := specialistRepo.GetByKey(specialistKey)
|
||||
specialist, found := specialistDAO.GetByKey(specialistKey)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("专员不存在"))
|
||||
return
|
||||
@@ -113,7 +113,7 @@ func CreateMyTask(c *gin.Context) {
|
||||
task.Status = "待处理"
|
||||
}
|
||||
|
||||
if !taskRecordRepo.Insert(&task) {
|
||||
if !taskRecordDAO.Insert(&task) {
|
||||
web.Fail(c, web.NewBadRequest("创建任务失败"))
|
||||
return
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func UpdateMyTask(c *gin.Context) {
|
||||
}
|
||||
|
||||
owners := specialistruntime.MyTaskOwners(user)
|
||||
task, found := taskRecordRepo.GetByIDForOwners(id, owners)
|
||||
task, found := taskRecordDAO.GetByIDForOwners(id, owners)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("任务不存在"))
|
||||
return
|
||||
@@ -149,7 +149,7 @@ func UpdateMyTask(c *gin.Context) {
|
||||
task.Title = title
|
||||
}
|
||||
if key := strings.TrimSpace(req.SpecialistKey); key != "" && key != task.SpecialistKey {
|
||||
specialist, ok := specialistRepo.GetByKey(key)
|
||||
specialist, ok := specialistDAO.GetByKey(key)
|
||||
if !ok {
|
||||
web.Fail(c, web.NewNotFoundError("目标专员不存在"))
|
||||
return
|
||||
@@ -164,7 +164,7 @@ func UpdateMyTask(c *gin.Context) {
|
||||
if *req.ProjectID == 0 {
|
||||
task.ProjectID = nil
|
||||
} else {
|
||||
project, ok := projectRepo.GetByIDForOwners(*req.ProjectID, owners)
|
||||
project, ok := projectDAO.GetByIDForOwners(*req.ProjectID, owners)
|
||||
if !ok {
|
||||
web.Fail(c, web.NewNotFoundError("项目不存在"))
|
||||
return
|
||||
@@ -176,7 +176,7 @@ func UpdateMyTask(c *gin.Context) {
|
||||
task.Pinned = *req.Pinned
|
||||
}
|
||||
|
||||
if !taskRecordRepo.Update(&task) {
|
||||
if !taskRecordDAO.Update(&task) {
|
||||
web.Fail(c, web.NewBadRequest("更新任务失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// noteRepo 学习笔记仓库(便于测试时覆写),包内共享。
|
||||
var noteRepo repository.StudyNoteRepo
|
||||
// noteDAO 学习笔记仓库(便于测试时覆写),包内共享。
|
||||
var noteDAO dal.StudyNoteDAO
|
||||
|
||||
func init() {
|
||||
noteRepo = repository.StudyNoteRepo{}
|
||||
noteDAO = dal.StudyNoteDAO{}
|
||||
}
|
||||
|
||||
var validNoteItemTypes = map[string]bool{"company": true, "product": true, "course": true}
|
||||
@@ -37,7 +37,7 @@ func ListNotes(c *gin.Context) {
|
||||
itemID = &id
|
||||
}
|
||||
}
|
||||
web.OK(c, noteRepo.ListByUser(u.ID, c.Query("item_type"), itemID))
|
||||
web.OK(c, noteDAO.ListByUser(u.ID, c.Query("item_type"), itemID))
|
||||
}
|
||||
|
||||
// CreateNote POST /api/notes —— 新增学习笔记
|
||||
@@ -65,7 +65,7 @@ func CreateNote(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
n := model.StudyNote{UserID: u.ID, ItemType: req.ItemType, ItemID: req.ItemID, Content: strings.TrimSpace(req.Content)}
|
||||
if !noteRepo.Insert(&n) {
|
||||
if !noteDAO.Insert(&n) {
|
||||
web.Fail(c, web.NewBadRequest("保存笔记失败"))
|
||||
return
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func UpdateNote(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
n, found := noteRepo.GetByID(id)
|
||||
n, found := noteDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("笔记不存在"))
|
||||
return
|
||||
@@ -104,7 +104,7 @@ func UpdateNote(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
n.Content = strings.TrimSpace(req.Content)
|
||||
if !noteRepo.Update(&n) {
|
||||
if !noteDAO.Update(&n) {
|
||||
web.Fail(c, web.NewBadRequest("更新笔记失败"))
|
||||
return
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func DeleteNote(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
n, found := noteRepo.GetByID(id)
|
||||
n, found := noteDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("笔记不存在"))
|
||||
return
|
||||
@@ -131,7 +131,7 @@ func DeleteNote(c *gin.Context) {
|
||||
web.Fail(c, web.NewForbiddenError("无权操作他人笔记"))
|
||||
return
|
||||
}
|
||||
if !noteRepo.Delete(&n) {
|
||||
if !noteDAO.Delete(&n) {
|
||||
web.Fail(c, web.NewBadRequest("删除笔记失败"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,27 +3,27 @@ package api
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
var (
|
||||
positionRepo repository.PositionRepo
|
||||
courseRepo repository.CourseRepo // productRepo 定义在 products.go
|
||||
positionDAO dal.PositionDAO
|
||||
courseDAO dal.CourseDAO // productDAO 定义在 products.go
|
||||
)
|
||||
|
||||
func init() {
|
||||
positionRepo = repository.PositionRepo{}
|
||||
courseRepo = repository.CourseRepo{}
|
||||
positionDAO = dal.PositionDAO{}
|
||||
courseDAO = dal.CourseDAO{}
|
||||
}
|
||||
|
||||
// ============ 岗位 CRUD(管理员) ============
|
||||
|
||||
// ListPositions GET /api/positions?status= —— 岗位列表
|
||||
func ListPositions(c *gin.Context) {
|
||||
items := positionRepo.List(c.Query("status"))
|
||||
items := positionDAO.List(c.Query("status"))
|
||||
web.OK(c, items)
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ func CreatePosition(c *gin.Context) {
|
||||
if p.Status == "" {
|
||||
p.Status = "active"
|
||||
}
|
||||
if positionRepo.CountByName(p.Code, nil) > 0 {
|
||||
if positionDAO.CountByName(p.Code, nil) > 0 {
|
||||
web.Fail(c, web.NewConflictError("岗位编号已存在"))
|
||||
return
|
||||
}
|
||||
if !positionRepo.Insert(&p) {
|
||||
if !positionDAO.Insert(&p) {
|
||||
web.Fail(c, web.NewBadRequest("创建岗位失败"))
|
||||
return
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func UpdatePosition(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p, found := positionRepo.GetByID(id)
|
||||
p, found := positionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("岗位不存在"))
|
||||
return
|
||||
@@ -76,7 +76,7 @@ func UpdatePosition(c *gin.Context) {
|
||||
req.Status = "active"
|
||||
}
|
||||
if req.Code != "" && req.Code != p.Code {
|
||||
if positionRepo.CountByName(req.Code, &id) > 0 {
|
||||
if positionDAO.CountByName(req.Code, &id) > 0 {
|
||||
web.Fail(c, web.NewConflictError("岗位编号已存在"))
|
||||
return
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func UpdatePosition(c *gin.Context) {
|
||||
p.Name = req.Name
|
||||
p.Description = req.Description
|
||||
p.Status = req.Status
|
||||
if !positionRepo.Update(&p) {
|
||||
if !positionDAO.Update(&p) {
|
||||
web.Fail(c, web.NewBadRequest("更新岗位失败"))
|
||||
return
|
||||
}
|
||||
@@ -98,7 +98,7 @@ func DeletePosition(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !positionRepo.Delete(id) {
|
||||
if !positionDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("停用岗位失败"))
|
||||
return
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func ListPositionKnowledge(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
items := positionRepo.Knowledge(id)
|
||||
items := positionDAO.Knowledge(id)
|
||||
if items == nil {
|
||||
items = []model.PositionKnowledge{}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ func SavePositionKnowledge(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_, found := positionRepo.GetByID(id)
|
||||
_, found := positionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("岗位不存在"))
|
||||
return
|
||||
@@ -191,11 +191,11 @@ func SavePositionKnowledge(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
// 整表覆盖:先删旧,再批量插入
|
||||
if !positionRepo.ReplaceKnowledge(id, rows) {
|
||||
if !positionDAO.ReplaceKnowledge(id, rows) {
|
||||
web.Fail(c, web.NewBadRequest("保存岗位知识映射失败"))
|
||||
return
|
||||
}
|
||||
out := positionRepo.Knowledge(id)
|
||||
out := positionDAO.Knowledge(id)
|
||||
if out == nil {
|
||||
out = []model.PositionKnowledge{}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func SetUserPosition(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
u, found := userRepo.GetByID(id)
|
||||
u, found := userDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("用户不存在"))
|
||||
return
|
||||
@@ -223,14 +223,14 @@ func SetUserPosition(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if req.PositionID != nil {
|
||||
_, found := positionRepo.GetByID(*req.PositionID)
|
||||
_, found := positionDAO.GetByID(*req.PositionID)
|
||||
if !found {
|
||||
web.Fail(c, web.NewBadRequest("岗位不存在或已停用"))
|
||||
return
|
||||
}
|
||||
}
|
||||
u.PositionID = req.PositionID
|
||||
if !userRepo.Update(&u) {
|
||||
if !userDAO.Update(&u) {
|
||||
web.Fail(c, web.NewBadRequest("设置用户岗位失败"))
|
||||
return
|
||||
}
|
||||
@@ -246,13 +246,13 @@ func MyPosition(c *gin.Context) {
|
||||
web.OK(c, gin.H{"position": nil, "knowledge": []gin.H{}, "count": 0})
|
||||
return
|
||||
}
|
||||
pos, found := positionRepo.GetByID(*u.PositionID)
|
||||
pos, found := positionDAO.GetByID(*u.PositionID)
|
||||
if !found || pos.Status != "active" {
|
||||
web.OK(c, gin.H{"position": nil, "knowledge": []gin.H{}, "count": 0})
|
||||
return
|
||||
}
|
||||
|
||||
pks := positionRepo.Knowledge(pos.ID)
|
||||
pks := positionDAO.Knowledge(pos.ID)
|
||||
|
||||
// 批量解析课程/产品名称
|
||||
courseIDs := make([]uint, 0, len(pks))
|
||||
@@ -265,8 +265,8 @@ func MyPosition(c *gin.Context) {
|
||||
productIDs = append(productIDs, *pk.ProductID)
|
||||
}
|
||||
}
|
||||
courseName := courseRepo.NamesByIDs(courseIDs)
|
||||
productName := productRepo.NamesByIDs(productIDs)
|
||||
courseName := courseDAO.NamesByIDs(courseIDs)
|
||||
productName := productDAO.NamesByIDs(productIDs)
|
||||
|
||||
list := make([]gin.H, 0, len(pks))
|
||||
for _, pk := range pks {
|
||||
@@ -303,7 +303,7 @@ func ListPositionBlueprint(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
items := positionRepo.Blueprints(id)
|
||||
items := positionDAO.Blueprints(id)
|
||||
if items == nil {
|
||||
items = []model.PositionExamBlueprint{}
|
||||
}
|
||||
@@ -316,7 +316,7 @@ func SavePositionBlueprint(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_, found := positionRepo.GetByID(id)
|
||||
_, found := positionDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("岗位不存在"))
|
||||
return
|
||||
@@ -346,11 +346,11 @@ func SavePositionBlueprint(c *gin.Context) {
|
||||
PositionID: id, Domain: it.Domain, Type: it.Type, Count: it.Count,
|
||||
})
|
||||
}
|
||||
if !positionRepo.ReplaceBlueprints(id, rows) {
|
||||
if !positionDAO.ReplaceBlueprints(id, rows) {
|
||||
web.Fail(c, web.NewBadRequest("保存岗位考试蓝图失败"))
|
||||
return
|
||||
}
|
||||
out := positionRepo.Blueprints(id)
|
||||
out := positionDAO.Blueprints(id)
|
||||
if out == nil {
|
||||
out = []model.PositionExamBlueprint{}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,21 @@ package api
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// productRepo 产品仓库(便于测试时覆写)。
|
||||
var productRepo repository.ProductRepo
|
||||
// productDAO 产品仓库(便于测试时覆写)。
|
||||
var productDAO dal.ProductDAO
|
||||
|
||||
func init() {
|
||||
productRepo = repository.ProductRepo{}
|
||||
productDAO = dal.ProductDAO{}
|
||||
}
|
||||
|
||||
// ListProducts GET /api/products?category=&status=
|
||||
func ListProducts(c *gin.Context) {
|
||||
items := productRepo.ProductsByStatus(c.Query("status"), map[string]string{
|
||||
items := productDAO.ProductsByStatus(c.Query("status"), map[string]string{
|
||||
"category": c.Query("category"),
|
||||
})
|
||||
web.OK(c, items)
|
||||
@@ -29,7 +29,7 @@ func GetProduct(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p, found := productRepo.GetByID(id)
|
||||
p, found := productDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("产品不存在"))
|
||||
return
|
||||
@@ -51,11 +51,11 @@ func CreateProduct(c *gin.Context) {
|
||||
if p.Status == "" {
|
||||
p.Status = "active"
|
||||
}
|
||||
if productRepo.CountByCode(p.Code, nil) > 0 {
|
||||
if productDAO.CountByCode(p.Code, nil) > 0 {
|
||||
web.Fail(c, web.NewConflictError("产品编号已存在"))
|
||||
return
|
||||
}
|
||||
if !productRepo.Insert(&p) {
|
||||
if !productDAO.Insert(&p) {
|
||||
web.Fail(c, web.NewBadRequest("创建产品失败"))
|
||||
return
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func UpdateProduct(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p, found := productRepo.GetByID(id)
|
||||
p, found := productDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("产品不存在"))
|
||||
return
|
||||
@@ -87,7 +87,7 @@ func UpdateProduct(c *gin.Context) {
|
||||
}
|
||||
|
||||
if req.Code != "" && req.Code != p.Code {
|
||||
if productRepo.CountByCode(req.Code, &id) > 0 {
|
||||
if productDAO.CountByCode(req.Code, &id) > 0 {
|
||||
web.Fail(c, web.NewConflictError("产品编号已存在"))
|
||||
return
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func UpdateProduct(c *gin.Context) {
|
||||
p.ReportRules = req.ReportRules
|
||||
p.Status = req.Status
|
||||
|
||||
if !productRepo.Update(&p) {
|
||||
if !productDAO.Update(&p) {
|
||||
web.Fail(c, web.NewBadRequest("更新产品失败"))
|
||||
return
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func DeleteProduct(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !productRepo.Delete(id) {
|
||||
if !productDAO.Delete(id) {
|
||||
web.Fail(c, web.NewBadRequest("停用产品失败"))
|
||||
return
|
||||
}
|
||||
@@ -145,9 +145,9 @@ func ImportProducts(c *gin.Context) {
|
||||
it.Status = "active"
|
||||
}
|
||||
// 检查是否存在
|
||||
existing, found := productRepo.GetByCode(it.Code)
|
||||
existing, found := productDAO.GetByCode(it.Code)
|
||||
if !found {
|
||||
if productRepo.Insert(&it) {
|
||||
if productDAO.Insert(&it) {
|
||||
created++
|
||||
}
|
||||
continue
|
||||
@@ -184,7 +184,7 @@ func ImportProducts(c *gin.Context) {
|
||||
existing.ReportRules = it.ReportRules
|
||||
}
|
||||
existing.Status = it.Status
|
||||
if productRepo.Update(&existing) {
|
||||
if productDAO.Update(&existing) {
|
||||
updated++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// 本文件用到的仓库:questionRepo/examRecordRepo 声明在 exam.go,learningRepo 声明在 learning.go。
|
||||
// 本文件用到的仓库:questionDAO/examRecordDAO 声明在 exam.go,learningDAO 声明在 learning.go。
|
||||
|
||||
// domainLabels 能力雷达维度(正式考试按域聚合的掌握度)。
|
||||
var domainLabels = map[string]string{
|
||||
@@ -40,7 +40,7 @@ func MyProfile(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 学习进度(公司/产品/课程浏览)
|
||||
lps := learningRepo.ListByUser(u.ID)
|
||||
lps := learningDAO.ListByUser(u.ID)
|
||||
companyViewed := false
|
||||
productViewed, courseViewed := 0, 0
|
||||
for _, lp := range lps {
|
||||
@@ -55,18 +55,18 @@ func MyProfile(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 错题统计
|
||||
mistakeTotal := mistakeRepo.CountByUser(u.ID)
|
||||
mistakeResolved := mistakeRepo.CountResolvedByUser(u.ID)
|
||||
mistakeTotal := mistakeDAO.CountByUser(u.ID)
|
||||
mistakeResolved := mistakeDAO.CountResolvedByUser(u.ID)
|
||||
|
||||
// 自测次数(自测不落 exam_record,改由积分流水统计)
|
||||
var selfTestCount int64
|
||||
store.DB.Model(&model.PointEvent{}).Where("user_id = ? AND event_type = ?", u.ID, "self_test").Count(&selfTestCount)
|
||||
|
||||
// 正式考试记录 + 按域能力聚合(趋势图要按时间正序)
|
||||
recs := examRecordRepo.ListByUserChronological(u.ID)
|
||||
recs := examRecordDAO.ListByUserChronological(u.ID)
|
||||
|
||||
// 题目 → 域映射(用于从答题明细反推各域掌握度)
|
||||
qDomain := questionRepo.DomainMap()
|
||||
qDomain := questionDAO.DomainMap()
|
||||
|
||||
type domainAgg struct {
|
||||
Correct int `json:"correct"`
|
||||
|
||||
@@ -58,7 +58,7 @@ func ListProjects(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
web.OK(c, projectRepo.ListByOwners(specialistruntime.MyTaskOwners(user), 50))
|
||||
web.OK(c, projectDAO.ListByOwners(specialistruntime.MyTaskOwners(user), 50))
|
||||
}
|
||||
|
||||
// CreateProject 建一个项目。空 body 也收(跟「新建任务」一样,全走默认值),
|
||||
@@ -105,7 +105,7 @@ func CreateProject(c *gin.Context) {
|
||||
SkillKeys: encodeKeys(req.SkillKeys),
|
||||
ConnectorKeys: encodeKeys(req.ConnectorKeys),
|
||||
}
|
||||
if !projectRepo.Insert(&project) {
|
||||
if !projectDAO.Insert(&project) {
|
||||
web.Fail(c, web.NewBadRequest("创建项目失败"))
|
||||
return
|
||||
}
|
||||
@@ -125,7 +125,7 @@ func UpdateProject(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
project, found := projectRepo.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
project, found := projectDAO.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("项目不存在"))
|
||||
return
|
||||
@@ -169,7 +169,7 @@ func UpdateProject(c *gin.Context) {
|
||||
project.ConnectorKeys = encodeKeys(req.ConnectorKeys)
|
||||
}
|
||||
|
||||
if !projectRepo.Update(&project) {
|
||||
if !projectDAO.Update(&project) {
|
||||
web.Fail(c, web.NewBadRequest("更新项目失败"))
|
||||
return
|
||||
}
|
||||
@@ -192,16 +192,16 @@ func DeleteProject(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
project, found := projectRepo.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
project, found := projectDAO.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("项目不存在"))
|
||||
return
|
||||
}
|
||||
if !taskRecordRepo.ClearProject(project.ID) {
|
||||
if !taskRecordDAO.ClearProject(project.ID) {
|
||||
web.Fail(c, web.NewBadRequest("解除任务归属失败"))
|
||||
return
|
||||
}
|
||||
if !projectRepo.Delete(&project) {
|
||||
if !projectDAO.Delete(&project) {
|
||||
web.Fail(c, web.NewBadRequest("删除项目失败"))
|
||||
return
|
||||
}
|
||||
@@ -221,13 +221,13 @@ func ListProjectTasks(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
project, found := projectRepo.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
project, found := projectDAO.GetByIDForOwners(id, specialistruntime.MyTaskOwners(user))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("项目不存在"))
|
||||
return
|
||||
}
|
||||
|
||||
web.OK(c, taskRecordRepo.ListByProject(project.ID, 100))
|
||||
web.OK(c, taskRecordDAO.ListByProject(project.ID, 100))
|
||||
}
|
||||
|
||||
// validateSpecialistKeys 专员 key 得真实存在才让存 —— 项目卡片上要显示专员名,
|
||||
@@ -240,7 +240,7 @@ func validateSpecialistKeys(keys []string) error {
|
||||
if trimmed == "" {
|
||||
continue
|
||||
}
|
||||
if _, found := specialistRepo.GetByKey(trimmed); !found {
|
||||
if _, found := specialistDAO.GetByKey(trimmed); !found {
|
||||
return errors.New("专员不存在:" + trimmed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func loadSpecialistByKey(key string) *specialistmodel.Specialist {
|
||||
}
|
||||
// state = inactive 的专员不再接新会话,但 system(通用助手)要能查到 ——
|
||||
// 「要不要拒绝 inactive」这个口径只在这里,不去污染仓库的取数口径。
|
||||
s, found := specialistRepo.GetByKey(key)
|
||||
s, found := specialistDAO.GetByKey(key)
|
||||
if !found || s.State == "inactive" {
|
||||
return nil
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func resolveSpecialist(req ChatMessageRequest) *specialistmodel.Specialist {
|
||||
if req.TaskID > 0 {
|
||||
// 与 task_runtime.go 其余读路径一致,不按 created_by 收窄:
|
||||
// 专员目录本身就是所有登录用户可读的,这里不构成新的信息暴露。
|
||||
if task, found := taskRecordRepo.GetByID(req.TaskID); found {
|
||||
if task, found := taskRecordDAO.GetByID(req.TaskID); found {
|
||||
if s := loadSpecialistByKey(task.SpecialistKey); s != nil {
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
specialistmodel "eai_agentplatform/backend/internal/specialists/model"
|
||||
"eai_agentplatform/backend/internal/store"
|
||||
)
|
||||
@@ -125,11 +125,11 @@ func setupAPITestDB(t *testing.T) {
|
||||
store.DB = db
|
||||
t.Cleanup(func() { store.DB = prev })
|
||||
|
||||
// 取数现在走仓库层,零值仓库(repository.XxxRepo{})的 base() 会回落到
|
||||
// 包级 repository.DB —— 这根线不接,第一个查询就是 nil 解引用。
|
||||
prevRepo := repository.DB
|
||||
repository.SetDB(db)
|
||||
t.Cleanup(func() { repository.SetDB(prevRepo) })
|
||||
// 取数现在走数据访问层,零值 DAO(dal.XxxDAO{})的 base() 会回落到
|
||||
// 包级 dal.DB —— 这根线不接,第一个查询就是 nil 解引用。
|
||||
prevDAO := dal.DB
|
||||
dal.SetDB(db)
|
||||
t.Cleanup(func() { dal.SetDB(prevDAO) })
|
||||
|
||||
for _, s := range []specialistmodel.Specialist{
|
||||
{Key: "contract-review", Label: "合同审查专员", State: "active", Tier: "industry", ObjectEntryRoute: "/apps/contract-review"},
|
||||
|
||||
@@ -10,21 +10,21 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/auth"
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
)
|
||||
|
||||
// systemConfigRepo 声明在此;examRecordRepo 与考试域同属一个对象,
|
||||
// systemConfigDAO 声明在此;examRecordDAO 与考试域同属一个对象,
|
||||
// 统一声明在 exam.go 的「考试域仓库」块内,避免同一个仓库有两份变量导致覆写时行为分叉。
|
||||
var (
|
||||
userRepo repository.UserRepo
|
||||
configRepo repository.SystemConfigRepo
|
||||
userDAO dal.UserDAO
|
||||
configDAO dal.SystemConfigDAO
|
||||
)
|
||||
|
||||
func init() {
|
||||
userRepo = repository.UserRepo{}
|
||||
configRepo = repository.SystemConfigRepo{}
|
||||
userDAO = dal.UserDAO{}
|
||||
configDAO = dal.SystemConfigDAO{}
|
||||
}
|
||||
|
||||
// ============ 用户管理(管理员) ============
|
||||
@@ -32,11 +32,11 @@ func init() {
|
||||
// ListUsers GET /api/system/users —— 含考试统计(考试次数/通过数/最近成绩)
|
||||
func ListUsers(c *gin.Context) {
|
||||
var items []model.User
|
||||
userRepo.Query().Type(&model.User{}).Order("id ASC").Find(&items)
|
||||
userDAO.Query().Type(&model.User{}).Order("id ASC").Find(&items)
|
||||
|
||||
// 获取考试记录
|
||||
var recs []model.ExamRecord
|
||||
examRecordRepo.Inner().Model(&model.ExamRecord{}).Order("submitted_at DESC").Find(&recs)
|
||||
examRecordDAO.Inner().Model(&model.ExamRecord{}).Order("submitted_at DESC").Find(&recs)
|
||||
|
||||
type stat struct {
|
||||
ExamCount int
|
||||
@@ -108,7 +108,7 @@ func CreateUser(c *gin.Context) {
|
||||
if req.Role != "admin" && req.Role != "employee" {
|
||||
req.Role = "employee"
|
||||
}
|
||||
_, found := userRepo.GetByUsername(req.Username)
|
||||
_, found := userDAO.GetByUsername(req.Username)
|
||||
if found {
|
||||
web.Fail(c, web.NewConflictError("用户名已存在"))
|
||||
return
|
||||
@@ -126,7 +126,7 @@ func CreateUser(c *gin.Context) {
|
||||
if req.Role == "admin" {
|
||||
u.AiPoints = 999999
|
||||
}
|
||||
if !userRepo.Insert(&u) {
|
||||
if !userDAO.Insert(&u) {
|
||||
web.Fail(c, web.NewBadRequest("创建用户失败"))
|
||||
return
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func UpdateUser(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
u, found := userRepo.GetByID(id)
|
||||
u, found := userDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("用户不存在"))
|
||||
return
|
||||
@@ -191,7 +191,7 @@ func UpdateUser(c *gin.Context) {
|
||||
}
|
||||
u.AiPoints = *req.AiPoints
|
||||
}
|
||||
if !userRepo.Update(&u) {
|
||||
if !userDAO.Update(&u) {
|
||||
web.Fail(c, web.NewBadRequest("更新用户失败"))
|
||||
return
|
||||
}
|
||||
@@ -200,7 +200,7 @@ func UpdateUser(c *gin.Context) {
|
||||
|
||||
// defaultAiPoints 读取新用户默认 AI 算力点(system_config.ai_points_default,缺省 100)
|
||||
func defaultAiPoints() int {
|
||||
val := configRepo.GetByKey("ai_points_default")
|
||||
val := configDAO.GetByKey("ai_points_default")
|
||||
if v, err := strconv.Atoi(strings.TrimSpace(val)); err == nil {
|
||||
return v
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func defaultAiPoints() int {
|
||||
|
||||
// ListExamRecords GET /api/system/exam-records?user_id=&paper_id=
|
||||
func ListExamRecords(c *gin.Context) {
|
||||
items := examRecordRepo.List(c.Query("user_id"), c.Query("paper_id"))
|
||||
items := examRecordDAO.List(c.Query("user_id"), c.Query("paper_id"))
|
||||
web.OK(c, items)
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ func GetExamRecord(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
rec, found := examRecordRepo.GetByID(id)
|
||||
rec, found := examRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("考试记录不存在"))
|
||||
return
|
||||
@@ -254,7 +254,7 @@ func DeleteExamRecord(c *gin.Context) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !examRecordRepo.Remove(id) {
|
||||
if !examRecordDAO.Remove(id) {
|
||||
web.Fail(c, web.NewBadRequest("删除考试记录失败"))
|
||||
return
|
||||
}
|
||||
@@ -264,7 +264,7 @@ func DeleteExamRecord(c *gin.Context) {
|
||||
// ExportExamRecords GET /api/system/exam-records/export —— 导出 CSV(支持 user_id/paper_id 过滤)
|
||||
func ExportExamRecords(c *gin.Context) {
|
||||
var items []model.ExamRecord
|
||||
q := repository.DB.Model(&model.ExamRecord{})
|
||||
q := dal.DB.Model(&model.ExamRecord{})
|
||||
if uid := c.Query("user_id"); uid != "" {
|
||||
q = q.Where("user_id = ?", uid)
|
||||
}
|
||||
@@ -278,7 +278,7 @@ func ExportExamRecords(c *gin.Context) {
|
||||
|
||||
// 用户名映射
|
||||
var users []model.User
|
||||
repository.DB.Find(&users)
|
||||
dal.DB.Find(&users)
|
||||
nameMap := map[uint]model.User{}
|
||||
for _, u := range users {
|
||||
nameMap[u.ID] = u
|
||||
@@ -316,7 +316,7 @@ func ExportExamRecords(c *gin.Context) {
|
||||
|
||||
// GetConfig GET /api/system/config —— 所有系统参数
|
||||
func GetConfig(c *gin.Context) {
|
||||
items := configRepo.List()
|
||||
items := configDAO.List()
|
||||
type cfgItem struct {
|
||||
Key string `json:"config_key"`
|
||||
Value string `json:"config_value"`
|
||||
@@ -338,7 +338,7 @@ func UpdateConfig(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("configs 必填"))
|
||||
return
|
||||
}
|
||||
configRepo.BulkUpsert(toSystemConfigs(req.Configs))
|
||||
configDAO.BulkUpsert(toSystemConfigs(req.Configs))
|
||||
web.OK(c, gin.H{"updated": len(req.Configs)})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"eai_agentplatform/backend/internal/dal"
|
||||
"eai_agentplatform/backend/internal/middleware"
|
||||
"eai_agentplatform/backend/internal/model"
|
||||
"eai_agentplatform/backend/internal/repository"
|
||||
wechatofficialaccountapi "eai_agentplatform/backend/internal/specialists/packages/wechat_official_account/api"
|
||||
specialistruntime "eai_agentplatform/backend/internal/specialists/runtime"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
@@ -18,23 +18,23 @@ import (
|
||||
|
||||
// 任务域仓库,包内共享。
|
||||
//
|
||||
// specialistRepo 还被 my_task.go、project.go、specialist_prompt.go 共用,
|
||||
// projectRepo 还被 my_task.go 共用 —— 同一个仓库只声明一处:
|
||||
// specialistDAO 还被 my_task.go、project.go、specialist_prompt.go 共用,
|
||||
// projectDAO 还被 my_task.go 共用 —— 同一个仓库只声明一处:
|
||||
// 两份变量持有同一个仓库时,测试里覆写一份、另一份照旧,行为会静默分叉。
|
||||
var (
|
||||
specialistRepo repository.SpecialistRepo
|
||||
taskRecordRepo repository.TaskRecordRepo
|
||||
taskRunRepo repository.TaskRunRepo
|
||||
taskArtifactRepo repository.TaskArtifactRepo
|
||||
projectRepo repository.ProjectRepo
|
||||
specialistDAO dal.SpecialistDAO
|
||||
taskRecordDAO dal.TaskRecordDAO
|
||||
taskRunDAO dal.TaskRunDAO
|
||||
taskArtifactDAO dal.TaskArtifactDAO
|
||||
projectDAO dal.ProjectDAO
|
||||
)
|
||||
|
||||
func init() {
|
||||
specialistRepo = repository.SpecialistRepo{}
|
||||
taskRecordRepo = repository.TaskRecordRepo{}
|
||||
taskRunRepo = repository.TaskRunRepo{}
|
||||
taskArtifactRepo = repository.TaskArtifactRepo{}
|
||||
projectRepo = repository.ProjectRepo{}
|
||||
specialistDAO = dal.SpecialistDAO{}
|
||||
taskRecordDAO = dal.TaskRecordDAO{}
|
||||
taskRunDAO = dal.TaskRunDAO{}
|
||||
taskArtifactDAO = dal.TaskArtifactDAO{}
|
||||
projectDAO = dal.ProjectDAO{}
|
||||
}
|
||||
|
||||
func ListTasks(c *gin.Context) {
|
||||
@@ -43,7 +43,7 @@ func ListTasks(c *gin.Context) {
|
||||
web.Fail(c, web.NewBadRequest("specialist_key 不能为空"))
|
||||
return
|
||||
}
|
||||
web.OK(c, taskRecordRepo.ListBySpecialistKey(specialistKey))
|
||||
web.OK(c, taskRecordDAO.ListBySpecialistKey(specialistKey))
|
||||
}
|
||||
|
||||
func GetTaskDetail(c *gin.Context) {
|
||||
@@ -52,14 +52,14 @@ func GetTaskDetail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(id)
|
||||
task, found := taskRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
}
|
||||
|
||||
artifacts := taskArtifactRepo.ListByTask(id)
|
||||
runs := taskRunRepo.ListByTask(id)
|
||||
artifacts := taskArtifactDAO.ListByTask(id)
|
||||
runs := taskRunDAO.ListByTask(id)
|
||||
if task.SpecialistKey == wechatofficialaccountapi.OfficialAccountSpecialistKey {
|
||||
artifacts = wechatofficialaccountapi.CompactOfficialAccountArtifactsForResponse(artifacts)
|
||||
runs = wechatofficialaccountapi.CompactOfficialAccountRunsForResponse(runs)
|
||||
@@ -79,13 +79,13 @@ func GetArtifactDetail(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
artifact, found := taskArtifactRepo.GetByID(id)
|
||||
artifact, found := taskArtifactDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("交付物不存在"))
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(artifact.TaskID)
|
||||
task, found := taskRecordDAO.GetByID(artifact.TaskID)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
@@ -93,7 +93,7 @@ func GetArtifactDetail(c *gin.Context) {
|
||||
|
||||
var runData any
|
||||
if artifact.CreatedByRunID != nil {
|
||||
if run, ok := taskRunRepo.GetByID(*artifact.CreatedByRunID); ok {
|
||||
if run, ok := taskRunDAO.GetByID(*artifact.CreatedByRunID); ok {
|
||||
runData = run
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func CreateTask(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
specialist, found := specialistRepo.GetByKey(strings.TrimSpace(req.SpecialistKey))
|
||||
specialist, found := specialistDAO.GetByKey(strings.TrimSpace(req.SpecialistKey))
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("专员不存在"))
|
||||
return
|
||||
@@ -135,7 +135,7 @@ func CreateTask(c *gin.Context) {
|
||||
task.Status = "待处理"
|
||||
}
|
||||
|
||||
if !taskRecordRepo.Insert(&task) {
|
||||
if !taskRecordDAO.Insert(&task) {
|
||||
web.Fail(c, web.NewBadRequest("创建事项失败"))
|
||||
return
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func UpdateTask(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(id)
|
||||
task, found := taskRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
@@ -167,7 +167,7 @@ func UpdateTask(c *gin.Context) {
|
||||
}
|
||||
|
||||
if key := strings.TrimSpace(req.SpecialistKey); key != "" && key != task.SpecialistKey {
|
||||
specialist, ok := specialistRepo.GetByKey(key)
|
||||
specialist, ok := specialistDAO.GetByKey(key)
|
||||
if !ok {
|
||||
web.Fail(c, web.NewNotFoundError("目标专员不存在"))
|
||||
return
|
||||
@@ -181,7 +181,7 @@ func UpdateTask(c *gin.Context) {
|
||||
task.Status = specialistruntime.NormalizeTaskStatus(updated.Status)
|
||||
task.ContextJSON = updated.ContextJSON
|
||||
task.DueAt = updated.DueAt
|
||||
if !taskRecordRepo.Update(&task) {
|
||||
if !taskRecordDAO.Update(&task) {
|
||||
web.Fail(c, web.NewBadRequest("更新事项失败"))
|
||||
return
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func UpdateTaskStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(id)
|
||||
task, found := taskRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
@@ -211,7 +211,7 @@ func UpdateTaskStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
task.Status = status
|
||||
if !taskRecordRepo.Update(&task) {
|
||||
if !taskRecordDAO.Update(&task) {
|
||||
web.Fail(c, web.NewBadRequest("更新事项状态失败"))
|
||||
return
|
||||
}
|
||||
@@ -224,14 +224,14 @@ func DeleteTask(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(id)
|
||||
task, found := taskRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
}
|
||||
|
||||
// 交付物与运行记录跟着任务一起走,三张表在同一个事务里。
|
||||
if !taskRecordRepo.DeleteCascade(task.ID) {
|
||||
if !taskRecordDAO.DeleteCascade(task.ID) {
|
||||
web.Fail(c, web.NewBadRequest("删除事项失败"))
|
||||
return
|
||||
}
|
||||
@@ -245,12 +245,12 @@ func UpdateArtifactStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
artifact, found := taskArtifactRepo.GetByID(id)
|
||||
artifact, found := taskArtifactDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("交付物不存在"))
|
||||
return
|
||||
}
|
||||
task, found := taskRecordRepo.GetByID(artifact.TaskID)
|
||||
task, found := taskRecordDAO.GetByID(artifact.TaskID)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
@@ -267,14 +267,14 @@ func UpdateArtifactStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
artifact.Status = nextStatus
|
||||
if !taskArtifactRepo.Update(&artifact) {
|
||||
if !taskArtifactDAO.Update(&artifact) {
|
||||
web.Fail(c, web.NewBadRequest("更新交付物状态失败"))
|
||||
return
|
||||
}
|
||||
|
||||
task.Status = specialistruntime.TaskStatusFromArtifactStatus(nextStatus)
|
||||
task.CurrentResult = specialistruntime.BuildArtifactStatusSummary(artifact, strings.TrimSpace(req.Remark))
|
||||
if !taskRecordRepo.Update(&task) {
|
||||
if !taskRecordDAO.Update(&task) {
|
||||
web.Fail(c, web.NewBadRequest("更新事项状态失败"))
|
||||
return
|
||||
}
|
||||
@@ -291,12 +291,12 @@ func ExecuteTaskAction(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
task, found := taskRecordRepo.GetByID(id)
|
||||
task, found := taskRecordDAO.GetByID(id)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("事项不存在"))
|
||||
return
|
||||
}
|
||||
specialist, found := specialistRepo.GetByKey(task.SpecialistKey)
|
||||
specialist, found := specialistDAO.GetByKey(task.SpecialistKey)
|
||||
if !found {
|
||||
web.Fail(c, web.NewNotFoundError("专员不存在"))
|
||||
return
|
||||
@@ -343,7 +343,7 @@ func ExecuteTaskAction(c *gin.Context) {
|
||||
StartedAt: now,
|
||||
FinishedAt: &now,
|
||||
}
|
||||
if !taskRunRepo.Insert(&run) {
|
||||
if !taskRunDAO.Insert(&run) {
|
||||
web.Fail(c, web.NewBadRequest("执行动作失败"))
|
||||
return
|
||||
}
|
||||
@@ -362,7 +362,7 @@ func ExecuteTaskAction(c *gin.Context) {
|
||||
SourceRefsJSON: string(sourceRefsJSON),
|
||||
CreatedByRunID: &run.ID,
|
||||
}
|
||||
if !taskArtifactRepo.Insert(artifact) {
|
||||
if !taskArtifactDAO.Insert(artifact) {
|
||||
web.Fail(c, web.NewBadRequest("保存交付物失败"))
|
||||
return
|
||||
}
|
||||
@@ -372,7 +372,7 @@ func ExecuteTaskAction(c *gin.Context) {
|
||||
task.CurrentRunID = &run.ID
|
||||
task.CurrentResult = runOutput.Summary
|
||||
task.LastTriggeredAt = &now
|
||||
if !taskRecordRepo.Update(&task) {
|
||||
if !taskRecordDAO.Update(&task) {
|
||||
web.Fail(c, web.NewBadRequest("更新事项状态失败"))
|
||||
return
|
||||
}
|
||||
@@ -386,13 +386,13 @@ func ExecuteTaskAction(c *gin.Context) {
|
||||
|
||||
// ensureBootstrapTask 某专员名下一条任务都没有时,铺一条默认任务。
|
||||
//
|
||||
// 注意:目前全仓没有调用方(保留原样迁到仓库层,未删)。
|
||||
// 注意:目前全仓没有调用方(保留原样迁到数据访问层,未删)。
|
||||
func ensureBootstrapTask(specialistKey string, user *model.User) error {
|
||||
if taskRecordRepo.CountBySpecialistKey(specialistKey) > 0 {
|
||||
if taskRecordDAO.CountBySpecialistKey(specialistKey) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
specialist, found := specialistRepo.GetByKey(specialistKey)
|
||||
specialist, found := specialistDAO.GetByKey(specialistKey)
|
||||
if !found {
|
||||
return fmt.Errorf("专员不存在:%s", specialistKey)
|
||||
}
|
||||
@@ -419,7 +419,7 @@ func ensureBootstrapTask(specialistKey string, user *model.User) error {
|
||||
if user != nil {
|
||||
task.CreatedBy = &user.ID
|
||||
}
|
||||
if !taskRecordRepo.Insert(&task) {
|
||||
if !taskRecordDAO.Insert(&task) {
|
||||
return fmt.Errorf("创建铺底任务失败")
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user