init: 数字员工平台初始代码

包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。
- 工作台画布:节点拖放、连线模式、右键菜单、AI 助手
- 后端:连接器 API、专员种子数据
- 导航:左侧导航、工坊、市场、控制台
This commit is contained in:
eaiadmin
2026-08-18 20:19:58 +08:00
commit 4e8817d768
239 changed files with 48631 additions and 0 deletions
@@ -0,0 +1,69 @@
package api
import (
"fmt"
"time"
"github.com/gin-gonic/gin"
"eaisalestrain/backend/internal/middleware"
"eaisalestrain/backend/internal/model"
"eaisalestrain/backend/internal/store"
"eaisalestrain/backend/internal/web"
)
// issueCertificate 正式考试通过后颁发证书(幂等:同一 exam_record 只发一张)。
func issueCertificate(u *model.User, rec model.ExamRecord) {
if u == nil || !rec.Passed {
return
}
var n int64
store.DB.Model(&model.Certificate{}).Where("exam_record_id = ?", rec.ID).Count(&n)
if n > 0 {
return
}
certNo := fmt.Sprintf("BST-%06d", rec.ID)
store.DB.Create(&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(),
})
}
// MyCertificates GET /api/exam/certificates —— 我的证书列表
func MyCertificates(c *gin.Context) {
u := middleware.CurrentUser(c)
if u == nil {
web.Fail(c, web.NewAuthError("未登录"))
return
}
var items []model.Certificate
store.DB.Where("user_id = ?", u.ID).Order("issued_at DESC").Find(&items)
web.OK(c, items)
}
// CertificateDetail GET /api/exam/certificates/{id} —— 证书详情(本人或管理员可看,用于打印留存)
func CertificateDetail(c *gin.Context) {
u := middleware.CurrentUser(c)
id, ok := parseID(c, "id")
if !ok {
return
}
var cert model.Certificate
if err := store.DB.First(&cert, id).Error; err != nil {
web.Fail(c, web.NewNotFoundError("证书不存在"))
return
}
if u == nil || (u.Role != "admin" && cert.UserID != u.ID) {
web.Fail(c, web.NewForbiddenError("无权查看他人证书"))
return
}
web.OK(c, cert)
}
// AdminCertificates GET /api/system/certificates —— 全员证书(管理员)
func AdminCertificates(c *gin.Context) {
var items []model.Certificate
store.DB.Order("issued_at DESC").Find(&items)
web.OK(c, items)
}