package controllers import ( "Tech/common" "Tech/models" // 根据实际项目结构调整导入路径 "encoding/json" "fmt" "os" "path" "strconv" "time" "github.com/beego/beego/v2/client/orm" beego "github.com/beego/beego/v2/server/web" "github.com/google/uuid" // 新增导入 ) type CourseController struct { beego.Controller } // GetCourseGUIDsByJXJHID 根据培训计划ID获取课程GUID列表 func GetCourseGUIDsByJXJHID(jxjhID, userName string) ([]string, error) { // 定义请求结构体 type Request struct { SBID string `json:"SBID"` // 设备编号 JYEMPID string `json:"JYEMPID"` // 教员GUID XYEMPID string `json:"XYEMPID"` // 学员GUID } var req Request // 从app.conf中读取SYSDEVICEID作为SBID的值 sbid, err := beego.AppConfig.String("SYSDEVICEID") if err != nil { return nil, fmt.Errorf("获取设备编号失败: %v", err) } req.SBID = sbid // 从缓存中获取用户信息 userInfo, exists := GetUserInfoFromCache(userName) if !exists { return nil, fmt.Errorf("用户信息不存在: ") } switch userInfo.SF { case "1": // 如果是教员,则使用当前用户的RYEMPID req.XYEMPID = userInfo.RYEMPID case "2": // 如果是学员,则使用当前用户的RYEMPID req.JYEMPID = userInfo.RYEMPID } // 调用信息化接口获取培训计划 response, err := common.GetTeachPlanFromInformationSystem(req.SBID, req.JYEMPID, req.XYEMPID) if err != nil { return nil, fmt.Errorf("获取培训计划失败: %v", err) } // 判断请求是否成功 if response.ResultCode != "0" { return nil, fmt.Errorf("获取培训计划失败: %s", response.ResultDesc) } // 收集匹配的培训计划下的所有课程GUID var courseGUIDs []string courseGUIDSet := make(map[string]bool) // 用于去重 // 遍历所有培训实施计划 for _, pxss := range response.PXSS { // 遍历所有计划 for _, jh := range pxss.JH { // 检查是否是目标培训计划 if jh.ID == jxjhID { // 添加SDKC中的KCGUID for _, sdkc := range jh.SDKC { if sdkc.KCGUID != "" && !courseGUIDSet[sdkc.KCGUID] { courseGUIDs = append(courseGUIDs, sdkc.KCGUID) courseGUIDSet[sdkc.KCGUID] = true } } // 添加TESTST中的KCGUID for _, testst := range jh.TESTST { if testst.KCGUID != "" && !courseGUIDSet[testst.KCGUID] { courseGUIDs = append(courseGUIDs, testst.KCGUID) courseGUIDSet[testst.KCGUID] = true } } } } } return courseGUIDs, nil } // /course/list 获取所有课程信息列表 func (c *CourseController) List() { type Query struct { CourseID int `form:"courseID"` CourseName string `form:"courseName"` TypeID int `form:"typeID"` Creator string `form:"creator"` LineNo int `form:"lineNo"` JXJHID string `form:"JXJHID"` // 培训计划ID } var query Query requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(c.Ctx.Input.RequestBody, &query); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } o := orm.NewOrm() qs := o.QueryTable(new(models.CourseInfo)) // 编号查询 if query.CourseID != 0 { qs = qs.Filter("CourseID", query.CourseID) } // 课程名称模糊查询 if query.CourseName != "" { qs = qs.Filter("CourseName__icontains", query.CourseName) } // 培训类型查询(分类ID) if query.TypeID != 0 { qs = qs.Filter("TypeID", query.TypeID) } // 创建人查询 if query.Creator != "" { qs = qs.Filter("Creator", query.Creator) } // 线路查询(线路号) if query.LineNo != 0 { qs = qs.Filter("LineNo", query.LineNo) } // 如果提供了培训计划ID(JXJHID),则从信息化系统获取对应的课程GUID列表 var courseGUIDs []string if query.JXJHID != "" { // 从Header中获取userName authHeader := c.Ctx.Input.Header("userName") if authHeader == "" { c.Ctx.Output.SetStatus(401) c.Data["json"] = map[string]interface{}{ "code": 401, "msg": "未提供认证信息", } c.ServeJSON() return } var err error courseGUIDs, err = GetCourseGUIDsByJXJHID(query.JXJHID, authHeader) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取培训计划课程列表失败: " + err.Error(), } c.ServeJSON() return } // 如果找到了课程GUID列表,则添加过滤条件 if len(courseGUIDs) > 0 { qs = qs.Filter("CourseGUID__in", courseGUIDs) } else { // 如果没有找到匹配的课程,则返回空结果 var courses []models.CourseInfo c.Data["json"] = map[string]interface{}{"code": 200, "count": 0, "msg": "", "data": courses} c.ServeJSON() return } } var courses []models.CourseInfo count, err := qs.OrderBy("-CreateTime").All(&courses, "课程ID", "课程GUID", "课程名称", "分类ID", "外部分类ID", "虚拟起始时间", "课程总时长", "线路号", "运行图", "课程描述", "创建人", "创建时间", "修改时间", "指导描述", "指导文件地址", "虚拟角色", "课程分类ID", "课程分类名称", "创建人ID") if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "error": "查询失败: " + err.Error()} c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "count": count, "msg": "", "data": courses} c.ServeJSON() } // /course/listpage 获取所有课程信息列表 func (c *CourseController) ListPage() { type Request struct { PageNum int `json:"pageNum"` PageSize int `json:"pageSize"` CourseID int `json:"courseID"` CourseName string `json:"courseName"` TypeID int `json:"typeID"` Creator string `json:"creator"` LineNo int `json:"lineNo"` } var req Request if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } // 设置默认值 if req.PageNum <= 0 { req.PageNum = 1 } if req.PageSize <= 0 { req.PageSize = 10 } o := orm.NewOrm() qs := o.QueryTable(new(models.CourseInfo)) // 编号查询 if req.CourseID != 0 { qs = qs.Filter("CourseID", req.CourseID) } // 课程名称模糊查询 if req.CourseName != "" { qs = qs.Filter("CourseName__icontains", req.CourseName) } // 培训类型查询(分类ID) if req.TypeID != 0 { qs = qs.Filter("TypeID", req.TypeID) } // 创建人查询 if req.Creator != "" { qs = qs.Filter("Creator__icontains", req.Creator) } // 线路查询(线路号) if req.LineNo != 0 { qs = qs.Filter("LineNo", req.LineNo) } // 获取总数 totalCount, err := qs.Count() if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询失败: " + err.Error(), } c.ServeJSON() return } // 计算总页数 totalPage := int((totalCount + int64(req.PageSize) - 1) / int64(req.PageSize)) // 分页查询,按创建时间倒序排列 var courses []models.CourseInfo _, err = qs.OrderBy("-CreateTime").Limit(req.PageSize).Offset((req.PageNum-1)*req.PageSize).All(&courses, "课程ID", "课程GUID", "课程名称", "分类ID", "外部分类ID", "虚拟起始时间", "课程总时长", "线路号", "运行图", "课程描述", "创建人", "创建时间", "修改时间", "指导描述", "指导文件地址", "虚拟角色", "课程分类ID", "课程分类名称", "创建人ID") if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询失败: " + err.Error(), } c.ServeJSON() return } // 构造分页数据 pageData := map[string]interface{}{ "pageNum": req.PageNum, "pageSize": req.PageSize, "totalCount": totalCount, "totalPage": totalPage, "list": courses, } c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "success", "data": pageData, } c.ServeJSON() } // /course/add 新增课程信息 func (c *CourseController) Add() { var course models.CourseInfo requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(c.Ctx.Input.RequestBody, &course); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } course.CourseID = 0 course.CourseGUID = "" o := orm.NewOrm() // 自动生成 CourseID if course.CourseID == 0 { var maxID int err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取最大ID失败: " + err.Error()} c.ServeJSON() return } course.CourseID = maxID + 1 } // 自动生成 CourseGUID if course.CourseGUID == "" { course.CourseGUID = uuid.New().String() } course.CreateTime = time.Now().Format("2006-01-02 15:04:05") course.ModifyTime = time.Now().Format("2006-01-02 15:04:05") _, err := o.Insert(&course) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "新增失败: " + err.Error()} c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "新增成功", "data": map[string]interface{}{ "courseID": course.CourseID, "courseGUID": course.CourseGUID, }, } c.ServeJSON() } // /course/update 更新课程信息 func (c *CourseController) Update() { var course models.CourseInfo requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(c.Ctx.Input.RequestBody, &course); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } o := orm.NewOrm() course.ModifyTime = time.Now().Format("2006-01-02 15:04:05") _, err := o.Update(&course, "课程名称", "分类ID", "外部分类ID", "虚拟起始时间", "课程总时长", "线路号", "运行图", "课程描述", "创建人", "修改时间", "指导描述", "指导文件地址", "课程分类ID", "课程分类名称", "创建人ID") if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"} c.ServeJSON() } // Upload 方法处理文件上传 func (c *CourseController) Upload() { // 1. 获取上传的文件 file, header, err := c.GetFile("file") // "file" 是表单中文件字段的 name:cite[3]:cite[6] if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取文件失败: " + err.Error(), } c.ServeJSON() return } defer file.Close() // // 2. 获取课程ID参数 // courseId, err := c.GetInt("courseId") // if err != nil { // c.Ctx.Output.SetStatus(400) // c.Data["json"] = map[string]interface{}{ // "code": 400, // "msg": "缺少课程ID参数或参数格式错误: " + err.Error(), // } // c.ServeJSON() // return // } // // 2. 节点ID为0 // nodeId, err := c.GetInt("nodeId") // if err != nil { // println("节点ID为null") // } // strDir := fmt.Sprintf("static/upload/%d/", courseId) // if nodeId > 0 { // strDir = fmt.Sprintf("static/upload/%d/%d/", courseId, nodeId) // } strDir := "static/upload/" if _, err := os.Stat(strDir); os.IsNotExist(err) { os.MkdirAll(strDir, os.ModePerm) } uploadPath := path.Join(strDir, header.Filename) // 文件保存路径 // 3. 保存文件:cite[3]:cite[6] err = c.SaveToFile("file", uploadPath) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "文件保存失败: " + err.Error(), } c.ServeJSON() return } // 4. 构建文件的访问 URL:cite[2] fileUrl := uploadPath // //保存到课程信息中 指导文件地址 字段 // o := orm.NewOrm() // //保存到课程或者节点里面 // if nodeId == 0 { // course := models.CourseInfo{CourseID: courseId} // if o.Read(&course, "课程ID") == nil { // course.GuideFilePath = fileUrl // course.ModifyTime = time.Now().Format("2006-01-02 15:04:05") // if _, err := o.Update(&course, "指导文件地址", "修改时间"); err != nil { // c.Ctx.Output.SetStatus(500) // c.Data["json"] = map[string]interface{}{ // "code": 500, // "msg": "更新课程信息失败: " + err.Error(), // } // c.ServeJSON() // return // } // } // } else { // //保存到节点里面 // node := models.CourseActionNode{NodeID: nodeId} // if o.Read(&node, "节点ID") == nil { // node.GuideFilePath = fileUrl // if _, err := o.Update(&node, "指导文件地址"); err != nil { // c.Ctx.Output.SetStatus(500) // c.Data["json"] = map[string]interface{}{ // "code": 500, // "msg": "更新节点信息失败: " + err.Error(), // } // c.ServeJSON() // return // } // } // } // 5. 返回成功信息和文件 URL:cite[3] c.Data["json"] = map[string]interface{}{ "code": 200, "message": "文件上传成功", "data": map[string]string{ "url": fileUrl, }, } c.ServeJSON() } // /course/delete 删除课程信息 func (c *CourseController) Delete() { // 解析请求中的课程ID数组 var req []struct { CourseID int `json:"courseId"` } requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if len(req) == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "请提供要删除的课程ID"} c.ServeJSON() return } o := orm.NewOrm() // 记录删除成功的课程数量 successCount := 0 failedCourses := make([]map[string]interface{}, 0) // 提取课程ID列表 courseIds := make([]int, len(req)) for i, item := range req { courseIds[i] = item.CourseID } for _, courseID := range courseIds { // 先删除相关的课程运行记录 _, err := o.Raw("DELETE FROM CourseRunLog WHERE 运行课程ID = ?", courseID).Exec() if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseId": courseID, "reason": "删除课程运行记录失败: " + err.Error(), }) continue } // 删除课程运行操作日志记录 _, err = o.Raw("DELETE FROM CourseOperLog WHERE 运行课程ID = ?", courseID).Exec() if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseId": courseID, "reason": "删除课程操作日志失败: " + err.Error(), }) continue } // 删除课程评价日志记录 _, err = o.Raw("DELETE FROM CourseEvaLog WHERE 运行课程ID = ?", courseID).Exec() if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseId": courseID, "reason": "删除课程评价日志失败: " + err.Error(), }) continue } // 删除课程基本信息 nCount, err := o.Delete(&models.CourseInfo{CourseID: courseID}) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseId": courseID, "reason": "删除失败: " + err.Error(), }) continue } if nCount == 0 { failedCourses = append(failedCourses, map[string]interface{}{ "courseId": courseID, "reason": "课程不存在", }) continue } // 成功删除课程基本信息后,清理相关节点数据 ClearCourse(courseID) successCount++ } // 构造返回结果 result := map[string]interface{}{ "code": 200, "msg": fmt.Sprintf("删除成功%d条记录,失败%d条记录", successCount, len(failedCourses)), } if len(failedCourses) > 0 { result["failed"] = failedCourses } c.Data["json"] = result c.ServeJSON() } // /course/detail/get 获取课程详细信息 func (c *CourseController) GetDetail() { type Query struct { CourseId int `json:"courseId"` } var query Query requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(requestBody, &query); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if query.CourseId == 0 { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "缺少课程ID", } c.ServeJSON() return } o := orm.NewOrm() var course models.CourseInfo err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID", query.CourseId).One(&course) if err != nil { c.Ctx.Output.SetStatus(404) c.Data["json"] = map[string]interface{}{ "code": 404, "msg": "课程不存在: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "data": course, } c.ServeJSON() } // /course/detail/set 设置课程详细信息 func (c *CourseController) SetDetail() { type Query struct { CourseId int `json:"courseId"` CourseDataStream string `json:"courseDataStream"` } var query Query requestBody := c.Ctx.Input.RequestBody // println("Request Body:", string(requestBody)) if err := json.Unmarshal(requestBody, &query); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "传输的JSON格式不正确: " + err.Error(), } c.ServeJSON() return } if query.CourseId == 0 { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "缺少课程ID", } c.ServeJSON() return } o := orm.NewOrm() var course models.CourseInfo err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID", query.CourseId).One(&course) if err != nil { c.Ctx.Output.SetStatus(404) c.Data["json"] = map[string]interface{}{ "code": 404, "msg": "课程不存在: " + err.Error(), } c.ServeJSON() return } // 更新 FlowData 字段 course.CourseDataStream = query.CourseDataStream course.ModifyTime = time.Now().Format("2006-01-02 15:04:05") _, err = o.Update(&course, "课程数据流", "修改时间") if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "更新失败: " + err.Error(), } c.ServeJSON() return } //保存数据 isRet, errmsg := ParserAndSaveNode(query.CourseId, query.CourseDataStream) if !isRet { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "更新节点失败: " + errmsg, } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "课程数据流更新成功", } c.ServeJSON() } // /coursetype/list 获取课程分类列表 func (c *CourseController) GetCourseTypeList() { o := orm.NewOrm() // 查询所有课程分类 var courseTypes []*models.CourseType count, err := o.QueryTable(new(models.CourseType)).All(&courseTypes) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询课程分类失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": courseTypes, } c.ServeJSON() } // /role/list 获取所有通讯角色列表 func (c *CourseController) GetRoleList() { o := orm.NewOrm() // 查询所有通讯角色 var roleInfos []*models.RoleInfo count, err := o.QueryTable(new(models.RoleInfo)).All(&roleInfos) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询通讯角色失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": roleInfos, } c.ServeJSON() } // /templateoperation/list 获取所有操作类型模板列表 func (c *CourseController) GetTemplateOperationList() { o := orm.NewOrm() // 查询所有操作类型模板 var templates []*models.TemplateOperation count, err := o.QueryTable(new(models.TemplateOperation)).All(&templates) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询操作类型模板失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": templates, } c.ServeJSON() } // /templatevoice/list 获取所有语音类型模板列表 func (c *CourseController) GetTemplateVoiceList() { o := orm.NewOrm() // 查询所有语音类型模板 var templates []*models.TemplateVoice count, err := o.QueryTable(new(models.TemplateVoice)).All(&templates) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询语音类型模板失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": templates, } c.ServeJSON() } // /templatefault/list 获取所有故障类型模板列表 func (c *CourseController) GetTemplateFaultList() { o := orm.NewOrm() // 查询所有故障类型模板 var templates []*models.TemplateFault count, err := o.QueryTable(new(models.TemplateFault)).All(&templates) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询故障类型模板失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": templates, } c.ServeJSON() } // /dict/list 获取所有字典列表 func (c *CourseController) GetDictList() { type Query struct { DictionaryType int `json:"dictionaryType"` DictionarySubType int `json:"dictionarySubType"` } var query Query requestBody := c.Ctx.Input.RequestBody println("Request Body:", string(requestBody)) if err := json.Unmarshal(requestBody, &query); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } o := orm.NewOrm() var dicts []*models.TypeMapList qs := o.QueryTable(new(models.TypeMapList)) if query.DictionaryType != 0 { qs = qs.Filter("DictionaryType", query.DictionaryType) } if query.DictionarySubType != 0 { qs = qs.Filter("DictionarySubType", query.DictionarySubType) } count, err := qs.All(&dicts) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询字典列表失败: " + err.Error(), } c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": dicts, } c.ServeJSON() } // /dict/listall 获取所有字典列表 func (c *CourseController) GetDictListAll() { o := orm.NewOrm() var dicts []*models.TypeMapList qs := o.QueryTable(new(models.TypeMapList)) count, err := qs.All(&dicts) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询字典列表失败: " + err.Error(), } c.ServeJSON() return } // 按照指定格式组织数据 type Item struct { KeyParam int `json:"keyParam"` ValueParam string `json:"valueParam"` } type Dict struct { DictionaryType int `json:"dictionaryType"` DictionaryTypeName string `json:"dictionaryTypeName"` DictionarySubType int `json:"dictionarySubType"` DictionarySubTypeName string `json:"dictionarySubTypeName"` KeyType string `json:"keyType"` Items []Item `json:"items"` } // 将数据转换为所需的格式 dictMap := make(map[string]*Dict) for _, dict := range dicts { key := fmt.Sprintf("%d_%d", dict.DictionaryType, dict.DictionarySubType) if d, exists := dictMap[key]; exists { // 如果已存在该字典类型,则添加item d.Items = append(d.Items, Item{ KeyParam: dict.KeyParam, ValueParam: dict.ValueParam, }) } else { // 创建新的字典类型 dictMap[key] = &Dict{ DictionaryType: dict.DictionaryType, DictionaryTypeName: dict.DictionaryTypeName, DictionarySubType: dict.DictionarySubType, DictionarySubTypeName: dict.DictionarySubTypeName, KeyType: fmt.Sprintf("%d_%d", dict.DictionaryType, dict.DictionarySubType), Items: []Item{{ KeyParam: dict.KeyParam, ValueParam: dict.ValueParam, }}, } } } // 将map转换为slice result := make([]Dict, 0, len(dictMap)) for _, dict := range dictMap { result = append(result, *dict) } c.Data["json"] = map[string]interface{}{ "code": 200, "count": count, "msg": "", "data": map[string]interface{}{ "dicts": result, }, } c.ServeJSON() } // /course/copy 课程复制 func (c *CourseController) CourseCopy() { // 解析请求中的课程ID数组 var req []struct { CourseID int `json:"courseId"` } if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if len(req) == 0 { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请提供要复制的课程ID", } c.ServeJSON() return } o := orm.NewOrm() // 存储复制成功的课程信息 successCourses := make([]map[string]interface{}, 0) // 存储复制失败的课程信息 failedCourses := make([]map[string]interface{}, 0) // 提取课程ID列表 courseIds := make([]int, len(req)) for i, item := range req { courseIds[i] = item.CourseID } for _, courseID := range courseIds { // 获取原课程信息 var originalCourse models.CourseInfo err := o.QueryTable(new(models.CourseInfo)).Filter("CourseID", courseID).One(&originalCourse) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "未找到要复制的课程: " + err.Error(), }) continue } // 创建新课程 newCourse := originalCourse newCourse.CourseID = 0 // 让ORM自动生成新的ID newCourse.CourseGUID = uuid.New().String() newCourse.CreateTime = time.Now().Format("2006-01-02 15:04:05") newCourse.ModifyTime = time.Now().Format("2006-01-02 15:04:05") // 自动生成 CourseID if newCourse.CourseID == 0 { var maxID int err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "获取最大ID失败: " + err.Error(), }) continue } newCourse.CourseID = maxID + 1 } // 插入新课程 _, err = o.Insert(&newCourse) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "创建新课程失败: " + err.Error(), }) continue } // 复制课程相关的节点数据 // 复制 CourseActionNode var actionNodes []models.CourseActionNode _, err = o.QueryTable(new(models.CourseActionNode)).Filter("CourseID", courseID).All(&actionNodes) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询动作节点失败: " + err.Error(), }) // 回滚已创建的新课程 o.Delete(&newCourse) continue } for _, node := range actionNodes { node.CourseID = newCourse.CourseID _, err = o.Insert(&node) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制动作节点失败: " + err.Error(), }) // 回滚已创建的新课程和节点数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制动作节点失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 复制 CourseOperationNode var operationNodes []models.CourseOperationNode _, err = o.QueryTable(new(models.CourseOperationNode)).Filter("CourseID", courseID).All(&operationNodes) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询操作节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) continue } for _, node := range operationNodes { node.CourseID = newCourse.CourseID // 如果主观评价标记未设置,默认为0(客观评价) if node.SubjectiveEvaluation == 0 { node.SubjectiveEvaluation = 0 // 默认为客观评价 } _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制操作节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制操作节点失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 复制 CourseFaultNode var faultNodes []models.CourseFaultNode _, err = o.QueryTable(new(models.CourseFaultNode)).Filter("CourseID", courseID).All(&faultNodes) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询故障节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) continue } for _, node := range faultNodes { node.CourseID = newCourse.CourseID // 注意:CourseFaultNode的CourseID和NodeID是联合主键 _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制故障节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制故障节点失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 复制 CourseVoiceNode var voiceNodes []models.CourseVoiceNode _, err = o.QueryTable(new(models.CourseVoiceNode)).Filter("CourseID", courseID).All(&voiceNodes) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询语音节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) continue } for _, node := range voiceNodes { node.CourseID = newCourse.CourseID // 注意:CourseVoiceNode的CourseID和NodeID是联合主键 _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制语音节点失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制语音节点失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 复制 CourseNodeTrigger var triggers []models.CourseNodeTrigger _, err = o.QueryTable(new(models.CourseNodeTrigger)).Filter("CourseID", courseID).All(&triggers) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询节点触发器失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) continue } for _, trigger := range triggers { trigger.CourseID = newCourse.CourseID // 注意:CourseNodeTrigger的CourseID和NodeID是联合主键 _, _, err = o.ReadOrCreate(&trigger, "CourseID", "NodeID") if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制节点触发器失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制节点触发器失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 复制 CourseEvaList var evals []models.CourseEvaList _, err = o.QueryTable(new(models.CourseEvaList)).Filter("CourseID", courseID).All(&evals) if err != nil && err != orm.ErrNoRows { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询评价列表失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) continue } for _, eval := range evals { eval.CourseID = newCourse.CourseID // 查询当前最大的序号 var maxSeqNo int err = o.Raw("SELECT COALESCE(MAX(序号), 0) FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).QueryRow(&maxSeqNo) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "查询评价序号失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } eval.SeqNo = maxSeqNo + 1 _, err = o.Insert(&eval) if err != nil { failedCourses = append(failedCourses, map[string]interface{}{ "courseID": courseID, "reason": "复制评价项失败: " + err.Error(), }) // 回滚已创建的数据 o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Raw("DELETE FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).Exec() o.Delete(&newCourse) break } } // 如果复制评价项失败,则跳过该课程 if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID { continue } // 所有复制操作都成功完成 successCourses = append(successCourses, map[string]interface{}{ "originalCourseID": courseID, "newCourseID": newCourse.CourseID, "newCourseGUID": newCourse.CourseGUID, "newCourseName": newCourse.CourseName, }) } // 构造返回结果 data := map[string]interface{}{} if len(successCourses) > 0 { data["success"] = successCourses } if len(failedCourses) > 0 { data["failed"] = failedCourses } response := map[string]interface{}{ "code": 200, "msg": fmt.Sprintf("批量复制完成,成功%d条,失败%d条", len(successCourses), len(failedCourses)), "data": data, } c.Data["json"] = response c.ServeJSON() } // /course/import 课程导入 func (c *CourseController) CourseImport() { // 获取上传的文件 file, header, err := c.GetFile("file") if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取文件失败: " + err.Error(), } c.ServeJSON() return } defer file.Close() // 检查文件扩展名 ext := path.Ext(header.Filename) if ext != ".json" { c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "只支持导入JSON格式文件", } c.ServeJSON() return } // 读取文件内容 fileSize := header.Size buffer := make([]byte, fileSize) _, err = file.Read(buffer) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "读取文件失败: " + err.Error(), } c.ServeJSON() return } // 解析JSON内容 - 支持多个课程 var importData []struct { CourseInfo models.CourseInfo `json:"courseInfo"` ActionNodes []models.CourseActionNode `json:"actionNodes"` OperationNodes []models.CourseOperationNode `json:"operationNodes"` FaultNodes []models.CourseFaultNode `json:"faultNodes"` VoiceNodes []models.CourseVoiceNode `json:"voiceNodes"` NodeTriggers []models.CourseNodeTrigger `json:"nodeTriggers"` EvalLists []models.CourseEvaList `json:"evalLists"` } err = json.Unmarshal(buffer, &importData) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "解析JSON文件失败: " + err.Error(), } c.ServeJSON() return } o := orm.NewOrm() // 存储导入结果 importResults := make([]map[string]interface{}, 0) // 遍历所有要导入的课程 for _, courseData := range importData { // 创建新课程 newCourse := courseData.CourseInfo newCourse.CourseID = 0 // 让ORM生成新的ID newCourse.CourseGUID = uuid.New().String() newCourse.CreateTime = time.Now().Format("2006-01-02 15:04:05") newCourse.ModifyTime = time.Now().Format("2006-01-02 15:04:05") // 检查是否已存在同名课程,如果存在则添加序号进行区分 originalName := newCourse.CourseName duplicateIndex := 1 for { var existingCourse models.CourseInfo err := o.QueryTable(new(models.CourseInfo)).Filter("CourseName", newCourse.CourseName).One(&existingCourse) if err != nil && err != orm.ErrNoRows { importResults = append(importResults, map[string]interface{}{ "courseName": originalName, "status": "failed", "msg": "检查课程名称唯一性失败: " + err.Error(), }) break } // 如果没有找到同名课程,则可以使用该名称 if err == orm.ErrNoRows { break } // 如果找到同名课程,则在名称后添加序号 newCourse.CourseName = fmt.Sprintf("%s(%d)", originalName, duplicateIndex) duplicateIndex++ } // 自动生成 CourseID if newCourse.CourseID == 0 { var maxID int err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取最大ID失败: " + err.Error()} c.ServeJSON() return } newCourse.CourseID = maxID + 1 } _, err = o.Insert(&newCourse) if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "创建课程失败: " + err.Error(), }) continue } // 导入 CourseActionNode for _, node := range courseData.ActionNodes { node.CourseID = newCourse.CourseID _, err = o.Insert(&node) if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入动作节点失败: " + err.Error(), }) continue } } // 导入 CourseOperationNode for _, node := range courseData.OperationNodes { node.CourseID = newCourse.CourseID // 如果主观评价标记未设置,默认为0(客观评价) if node.SubjectiveEvaluation == 0 { node.SubjectiveEvaluation = 0 // 默认为客观评价 } _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入操作节点失败: " + err.Error(), }) continue } } // 导入 CourseFaultNode for _, node := range courseData.FaultNodes { node.CourseID = newCourse.CourseID _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入故障节点失败: " + err.Error(), }) continue } } // 导入 CourseVoiceNode for _, node := range courseData.VoiceNodes { node.CourseID = newCourse.CourseID _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID") if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入语音节点失败: " + err.Error(), }) continue } } // 导入 CourseNodeTrigger for _, trigger := range courseData.NodeTriggers { trigger.CourseID = newCourse.CourseID _, _, err = o.ReadOrCreate(&trigger, "CourseID", "NodeID") if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入节点触发器失败: " + err.Error(), }) continue } } // 导入 CourseEvaList for i, eval := range courseData.EvalLists { eval.CourseID = newCourse.CourseID eval.SeqNo = i + 1 // 重新编号 _, err = o.Insert(&eval) if err != nil { importResults = append(importResults, map[string]interface{}{ "courseName": courseData.CourseInfo.CourseName, "status": "failed", "msg": "导入评价项失败: " + err.Error(), }) continue } } importResults = append(importResults, map[string]interface{}{ "courseName": newCourse.CourseName, "status": "success", "data": map[string]interface{}{ "courseID": newCourse.CourseID, "courseGUID": newCourse.CourseGUID, "courseName": newCourse.CourseName, }, }) } c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "课程导入完成", "data": importResults, "counts": map[string]int{ "total": len(importData), "success": len(importResults) - failedCount(importResults), "failed": failedCount(importResults), }, } c.ServeJSON() } // 辅助函数:计算导入失败的数量 func failedCount(results []map[string]interface{}) int { count := 0 for _, result := range results { if status, ok := result["status"].(string); ok && status == "failed" { count++ } } return count } // // course/export 课程导出 func (c *CourseController) CourseExport() { // 解析请求中的课程ID数组 var req []struct { CourseID int `json:"courseId"` } if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if len(req) == 0 { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "参数不完整", } c.ServeJSON() return } o := orm.NewOrm() // 存储所有要导出的课程数据 exportData := make([]map[string]interface{}, 0) // 遍历所有请求的课程ID for _, item := range req { if item.CourseID <= 0 { continue } // 获取课程信息 var course models.CourseInfo err := o.QueryTable(new(models.CourseInfo)).Filter("CourseID", item.CourseID).One(&course) if err != nil { // 如果找不到课程,继续处理下一个 continue } // 获取 CourseActionNode var actionNodes []models.CourseActionNode _, err = o.QueryTable(new(models.CourseActionNode)).Filter("CourseID", item.CourseID).All(&actionNodes) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 获取 CourseOperationNode var operationNodes []models.CourseOperationNode _, err = o.QueryTable(new(models.CourseOperationNode)).Filter("CourseID", item.CourseID).All(&operationNodes) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 获取 CourseFaultNode var faultNodes []models.CourseFaultNode _, err = o.QueryTable(new(models.CourseFaultNode)).Filter("CourseID", item.CourseID).All(&faultNodes) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 获取 CourseVoiceNode var voiceNodes []models.CourseVoiceNode _, err = o.QueryTable(new(models.CourseVoiceNode)).Filter("CourseID", item.CourseID).All(&voiceNodes) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 获取 CourseNodeTrigger var triggers []models.CourseNodeTrigger _, err = o.QueryTable(new(models.CourseNodeTrigger)).Filter("CourseID", item.CourseID).All(&triggers) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 获取 CourseEvaList var evalLists []models.CourseEvaList _, err = o.QueryTable(new(models.CourseEvaList)).Filter("CourseID", item.CourseID).All(&evalLists) if err != nil && err != orm.ErrNoRows { // 错误处理,但继续处理下一个课程 continue } // 构造单个课程的导出数据 singleExportData := map[string]interface{}{ "courseInfo": course, "actionNodes": actionNodes, "operationNodes": operationNodes, "faultNodes": faultNodes, "voiceNodes": voiceNodes, "nodeTriggers": triggers, "evalLists": evalLists, } exportData = append(exportData, singleExportData) } // 转换为JSON jsonData, err := json.Marshal(exportData) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "序列化数据失败: " + err.Error(), } c.ServeJSON() return } // 设置响应头,触发浏览器下载 filename := "courses_export.json" if len(req) == 1 { filename = fmt.Sprintf("course_%d_export.json", req[0].CourseID) } c.Ctx.Output.Header("Content-Type", "application/octet-stream") c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) c.Ctx.Output.Header("Content-Length", fmt.Sprintf("%d", len(jsonData))) c.Ctx.Output.Body(jsonData) } // /gettmscoursetype 获取课程分类列表 func (c *CourseController) GetTMSCourseType() { // 调用信息化接口获取课程分类列表,传入FZXTLX参数为1 response, err := common.GetAllCourseTypeEx(1) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取课程分类列表失败: " + err.Error(), } c.ServeJSON() return } // 判断请求是否成功 if response.ResultCode != "0" { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取课程分类列表失败: " + response.ResultDesc, } c.ServeJSON() return } // 返回成功数据 c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "获取课程分类列表成功", "data": response.CourseTypes, } c.ServeJSON() } // /course/uploadtms 上传课程到信息化平台 func (c *CourseController) UploadTMS() { // 解析请求中的课程ID数组 var req []struct { CourseID int `json:"courseId"` } if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if len(req) == 0 { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请提供要上传的课程ID", } c.ServeJSON() return } o := orm.NewOrm() // 准备要上传的课程信息 var coursesToUpload []common.UploadCourseInfo // 提取课程ID列表 courseIds := make([]int, len(req)) for i, item := range req { courseIds[i] = item.CourseID } // 查询课程信息 var courses []models.CourseInfo _, err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID__in", courseIds).All(&courses) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "查询课程信息失败: " + err.Error(), } c.ServeJSON() return } // 如果没有找到任何课程 if len(courses) == 0 { c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "没有找到指定的课程", "data": []common.UploadCourseInfo{}, } c.ServeJSON() return } // 从配置文件中读取CLLX和SYCX cllx, _ := beego.AppConfig.String("SYSCLLX") if cllx == "" { cllx = "牵引变电实训室" // 默认值 } sycx, _ := beego.AppConfig.String("SYSSYCX") if sycx == "" { sycx = "SCADA系统" // 默认值 } // 将课程信息转换为上传格式 for _, course := range courses { // 从数据库中查询线路名称 var typeMapList []models.TypeMapList lineName := "" // 默认线路名称 o := orm.NewOrm() err := o.QueryTable(new(models.TypeMapList)). Filter("DictionaryTypeName", "线路号"). Filter("KeyParam", course.LineNo). One(&typeMapList) if err == nil && len(typeMapList) > 0 { lineName = typeMapList[0].ValueParam } uploadCourse := common.UploadCourseInfo{ KCGUID: course.CourseGUID, KCMC: course.CourseName, KCMS: course.CourseDesc, KCNR: course.CourseDesc, // 课程内容暂时使用课程描述 KCFLID: course.CourseCategoryID, // 课程分类ID CJRID: course.CreatorID, // 创建人作为创建人ID CJSJ: course.CreateTime, // 创建时间 XGRID: course.CreatorID, // 创建人作为修改人ID XGSJ: course.ModifyTime, // 修改时间 PXMS: "1", // 排序模式,默认为1 Alone: common.Alone{ FZXTLX: "1", // 独立系统类型,默认为1 MJ: common.MJ{ CLLX: cllx, // 车辆类型 SYCX: sycx, // 适用车型 XLBH: fmt.Sprintf("%d", course.LineNo), // 线路编号 XLMC: lineName, // 线路名称,这里使用固定值 }, }, } coursesToUpload = append(coursesToUpload, uploadCourse) } // 调用信息化接口上传课程 response, err := common.UploadCourseToInformationSystem(coursesToUpload) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "上传课程到信息化平台失败: " + err.Error(), } c.ServeJSON() return } // 判断请求是否成功 // 根据返回的SucceedCount判断是否全部成功 succeedCount := 0 if response.SucceedCount != "" { count, err := strconv.Atoi(response.SucceedCount) if err == nil { succeedCount = count } } totalCount := len(response.CourseResults) // 如果有失败的课程,返回详细信息 if succeedCount < totalCount { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": fmt.Sprintf("上传课程部分失败: 成功%d个,失败%d个", succeedCount, totalCount-succeedCount), "data": response.CourseResults, } c.ServeJSON() return } // 返回成功数据 c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "上传课程到信息化平台成功", "data": response.CourseResults, } c.ServeJSON() } // /course/tmsplan 获取信息化系统的课程计划 func (c *CourseController) GetTMSCoursePlan() { // 定义请求结构体 type Request struct { SBID string `json:"SBID"` // 设备编号 JYEMPID string `json:"JYEMPID"` // 教员GUID XYEMPID string `json:"XYEMPID"` // 学员GUID } var req Request // if CurrentLoginMode == 1 { // c.Ctx.Output.SetStatus(500) // c.Data["json"] = map[string]interface{}{ // "code": 500, // "msg": "本地模式不支持该功能 ", // } // c.ServeJSON() // return // } // 从app.conf中读取SYSDEVICEID作为SBID的值 sbid, err := beego.AppConfig.String("SYSDEVICEID") if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取设备编号失败: " + err.Error(), } c.ServeJSON() return } req.SBID = sbid // 解析请求中的参数 Header 中的 userName 判断用户缓存中的是学员还是教员,将对应人员guid 传入req // 从Header中获取userName authHeader := c.Ctx.Input.Header("userName") if authHeader == "" { c.Ctx.Output.SetStatus(401) c.Data["json"] = map[string]interface{}{ "code": 401, "msg": "未提供认证信息", } c.ServeJSON() return } // 从缓存中获取用户信息 userInfo, exists := GetUserInfoFromCache(authHeader) if !exists { c.Ctx.Output.SetStatus(401) c.Data["json"] = map[string]interface{}{ "code": 401, "msg": "用户信息不存在", } c.ServeJSON() return } switch userInfo.SF { case "1": // 如果是教员,则使用当前用户的RYEMPID req.XYEMPID = userInfo.RYEMPID case "2": // 如果是学员,则使用当前用户的RYEMPID req.JYEMPID = userInfo.RYEMPID } // 调用信息化接口获取培训计划 response, err := common.GetTeachPlanFromInformationSystem(req.SBID, req.JYEMPID, req.XYEMPID) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取培训计划失败: " + err.Error(), } c.ServeJSON() return } // 判断请求是否成功 if response.ResultCode != "0" { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取培训计划失败: " + response.ResultDesc, } c.ServeJSON() return } // 提取需要返回给前端的数据 type PlanInfo struct { JXJHID string `json:"JXJHID"` // 培训计划ID KMMC string `json:"KMMC"` // 科目名称 SDKCGUIDs []string `json:"SDKCGUIDs"` // 培训课程GUID列表 TESTSTGUIDs []string `json:"TESTKCGUIDs"` // 测试课程GUID列表 } // 提取需要返回给前端的数据 type PlanDoInfo struct { PXSSID string `json:"PXSSID"` // 培训实施ID PXSSMC string `json:"PXSSMC"` // 培训实施名称 PXInfo []PlanInfo `json:"PlanInfo"` // 培训计划信息 } var plans []PlanDoInfo // 遍历所有培训实施计划 for _, pxss := range response.PXSS { PlanDoInfo := PlanDoInfo{PXSSID: pxss.PXSSID, PXSSMC: pxss.PXSSMC} // 遍历所有计划 for _, jh := range pxss.JH { plan := PlanInfo{ JXJHID: jh.ID, KMMC: jh.KMMC, SDKCGUIDs: []string{}, TESTSTGUIDs: []string{}, } // 添加SDKC中的KCGUID for _, sdkc := range jh.SDKC { if sdkc.KCGUID != "" { plan.SDKCGUIDs = append(plan.SDKCGUIDs, sdkc.KCGUID) } } // 添加TESTST中的KCGUID for _, testst := range jh.TESTST { if testst.KCGUID != "" { plan.TESTSTGUIDs = append(plan.TESTSTGUIDs, testst.KCGUID) } } PlanDoInfo.PXInfo = append(PlanDoInfo.PXInfo, plan) } plans = append(plans, PlanDoInfo) } // 返回成功数据 c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "获取培训计划成功", "data": plans, } c.ServeJSON() } // /course/tmsplanstudent 获取TMS课程计划参与的学生 func (c *CourseController) GetTMSCoursePlanStudent() { // 获取请求参数 var req struct { PXSSID string `json:"PXSSID"` } // if CurrentLoginMode == 1 { // c.Ctx.Output.SetStatus(500) // c.Data["json"] = map[string]interface{}{ // "code": 500, // "msg": "本地模式不支持该功能 ", // } // c.ServeJSON() // return // } if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "请求参数格式错误: " + err.Error(), } c.ServeJSON() return } if req.PXSSID == "" { c.Ctx.Output.SetStatus(400) c.Data["json"] = map[string]interface{}{ "code": 400, "msg": "PXSSID不能为空", } c.ServeJSON() return } // 调用信息化系统获取培训学生信息 trainingStudentResp, err := common.GetTrainingStudentFromInformationSystem(req.PXSSID) if err != nil { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取培训学生信息失败: " + err.Error(), } c.ServeJSON() return } // 检查返回结果 if trainingStudentResp.ResultCode != "0" { c.Ctx.Output.SetStatus(500) c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取培训学生信息失败: " + trainingStudentResp.ResultDesc, } c.ServeJSON() return } // 构造简化版的学生信息列表,只包含XYEMPID和XYXM type SimpleStudentInfo struct { XYEMPID string `json:"XYEMPID"` XYXM string `json:"XYXM"` } simpleStudents := make([]SimpleStudentInfo, 0) for _, student := range trainingStudentResp.Students { simpleStudents = append(simpleStudents, SimpleStudentInfo{ XYEMPID: student.XYEMPID, XYXM: student.XYXM, }) } // 返回成功数据 c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "获取培训学生信息成功", "data": simpleStudents, "count": trainingStudentResp.Count, } c.ServeJSON() }