课程.go 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184
  1. package controllers
  2. import (
  3. "Tech/common"
  4. "Tech/models" // 根据实际项目结构调整导入路径
  5. "encoding/json"
  6. "fmt"
  7. "os"
  8. "path"
  9. "strconv"
  10. "time"
  11. "github.com/beego/beego/v2/client/orm"
  12. beego "github.com/beego/beego/v2/server/web"
  13. "github.com/google/uuid" // 新增导入
  14. "github.com/sirupsen/logrus"
  15. )
  16. type CourseController struct {
  17. beego.Controller
  18. }
  19. // GetCourseGUIDsByJXJHID 根据培训计划ID获取课程GUID列表
  20. func GetCourseGUIDsByJXJHID(jxjhID, userName string) ([]string, error) {
  21. // 定义请求结构体
  22. type Request struct {
  23. SBID string `json:"SBID"` // 设备编号
  24. JYEMPID string `json:"JYEMPID"` // 教员GUID
  25. XYEMPID string `json:"XYEMPID"` // 学员GUID
  26. }
  27. var req Request
  28. // 从app.conf中读取SYSDEVICEID作为SBID的值
  29. sbid, err := beego.AppConfig.String("SYSDEVICEID")
  30. if err != nil {
  31. return nil, fmt.Errorf("获取设备编号失败: %v", err)
  32. }
  33. req.SBID = sbid
  34. // 从缓存中获取用户信息
  35. userInfo, exists := GetUserInfoFromCache(userName)
  36. if !exists {
  37. return nil, fmt.Errorf("用户信息不存在: ")
  38. }
  39. switch userInfo.SF {
  40. case "1": // 如果是教员,则使用当前用户的RYEMPID
  41. req.XYEMPID = userInfo.RYEMPID
  42. case "2": // 如果是学员,则使用当前用户的RYEMPID
  43. req.JYEMPID = userInfo.RYEMPID
  44. }
  45. // 调用信息化接口获取培训计划
  46. response, err := common.GetTeachPlanFromInformationSystem(req.SBID, req.JYEMPID, req.XYEMPID)
  47. if err != nil {
  48. return nil, fmt.Errorf("获取培训计划失败: %v", err)
  49. }
  50. // 判断请求是否成功
  51. if response.ResultCode != "0" {
  52. return nil, fmt.Errorf("获取培训计划失败: %s", response.ResultDesc)
  53. }
  54. // 收集匹配的培训计划下的所有课程GUID
  55. var courseGUIDs []string
  56. courseGUIDSet := make(map[string]bool) // 用于去重
  57. // 遍历所有培训实施计划
  58. for _, pxss := range response.PXSS {
  59. // 遍历所有计划
  60. for _, jh := range pxss.JH {
  61. // 检查是否是目标培训计划
  62. if jh.ID == jxjhID {
  63. // 添加SDKC中的KCGUID
  64. for _, sdkc := range jh.SDKC {
  65. if sdkc.KCGUID != "" && !courseGUIDSet[sdkc.KCGUID] {
  66. courseGUIDs = append(courseGUIDs, sdkc.KCGUID)
  67. courseGUIDSet[sdkc.KCGUID] = true
  68. }
  69. }
  70. // 添加TESTST中的KCGUID
  71. for _, testst := range jh.TESTST {
  72. if testst.KCGUID != "" && !courseGUIDSet[testst.KCGUID] {
  73. courseGUIDs = append(courseGUIDs, testst.KCGUID)
  74. courseGUIDSet[testst.KCGUID] = true
  75. }
  76. }
  77. }
  78. }
  79. }
  80. return courseGUIDs, nil
  81. }
  82. // /course/list 获取所有课程信息列表
  83. func (c *CourseController) List() {
  84. type Query struct {
  85. CourseID int `form:"courseID"`
  86. CourseName string `form:"courseName"`
  87. TypeID int `form:"typeID"`
  88. Creator string `form:"creator"`
  89. LineNo int `form:"lineNo"`
  90. JXJHID string `form:"JXJHID"` // 培训计划ID
  91. }
  92. var query Query
  93. requestBody := c.Ctx.Input.RequestBody
  94. println("Request Body:", string(requestBody))
  95. clientIP := c.Ctx.Input.IP()
  96. userAgent := c.Ctx.Request.UserAgent()
  97. // 从Header中获取用户信息用于日志记录
  98. authHeader := c.Ctx.Input.Header("userName")
  99. userName := "unknown"
  100. if authHeader != "" {
  101. userName = authHeader
  102. }
  103. common.LogDebug("课程查询请求", logrus.Fields{
  104. "module": "course",
  105. "action": "list",
  106. "user_name": userName,
  107. "ip": clientIP,
  108. "user_agent": userAgent,
  109. })
  110. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &query); err != nil {
  111. c.Ctx.Output.SetStatus(400)
  112. c.Data["json"] = map[string]interface{}{
  113. "code": 400,
  114. "msg": "请求参数格式错误: " + err.Error(),
  115. }
  116. c.ServeJSON()
  117. // 记录错误日志
  118. common.LogUserAction("", userName, "course_query_failed", "course", logrus.Fields{
  119. "reason": "invalid_request_format",
  120. "ip": clientIP,
  121. "error": err.Error(),
  122. })
  123. return
  124. }
  125. o := orm.NewOrm()
  126. qs := o.QueryTable(new(models.CourseInfo))
  127. // 编号查询
  128. if query.CourseID != 0 {
  129. qs = qs.Filter("CourseID", query.CourseID)
  130. }
  131. // 课程名称模糊查询
  132. if query.CourseName != "" {
  133. qs = qs.Filter("CourseName__icontains", query.CourseName)
  134. }
  135. // 培训类型查询(分类ID)
  136. if query.TypeID != 0 {
  137. qs = qs.Filter("TypeID", query.TypeID)
  138. }
  139. // 创建人查询
  140. if query.Creator != "" {
  141. qs = qs.Filter("Creator", query.Creator)
  142. }
  143. // 线路查询(线路号)
  144. if query.LineNo != 0 {
  145. qs = qs.Filter("LineNo", query.LineNo)
  146. }
  147. // 如果提供了培训计划ID(JXJHID),则从信息化系统获取对应的课程GUID列表
  148. var courseGUIDs []string
  149. if query.JXJHID != "" {
  150. // 从Header中获取userName
  151. authHeader := c.Ctx.Input.Header("userName")
  152. if authHeader == "" {
  153. c.Ctx.Output.SetStatus(401)
  154. c.Data["json"] = map[string]interface{}{
  155. "code": 401,
  156. "msg": "未提供认证信息",
  157. }
  158. c.ServeJSON()
  159. return
  160. }
  161. var err error
  162. courseGUIDs, err = GetCourseGUIDsByJXJHID(query.JXJHID, authHeader)
  163. if err != nil {
  164. c.Data["json"] = map[string]interface{}{
  165. "code": 500,
  166. "msg": "获取培训计划课程列表失败: " + err.Error(),
  167. }
  168. c.ServeJSON()
  169. return
  170. }
  171. // 如果找到了课程GUID列表,则添加过滤条件
  172. if len(courseGUIDs) > 0 {
  173. qs = qs.Filter("CourseGUID__in", courseGUIDs)
  174. } else {
  175. // 如果没有找到匹配的课程,则返回空结果
  176. var courses []models.CourseInfo
  177. c.Data["json"] = map[string]interface{}{"code": 200, "count": 0, "msg": "", "data": courses}
  178. c.ServeJSON()
  179. return
  180. }
  181. }
  182. var courses []models.CourseInfo
  183. count, err := qs.OrderBy("-CreateTime").All(&courses, "课程ID", "课程GUID", "课程名称", "分类ID", "外部分类ID", "虚拟起始时间",
  184. "课程总时长", "线路号", "运行图", "课程描述", "创建人", "创建时间", "修改时间", "指导描述", "指导文件地址", "虚拟角色", "课程分类ID", "课程分类名称", "创建人ID")
  185. if err != nil {
  186. c.Data["json"] = map[string]interface{}{"code": 500, "error": "查询失败: " + err.Error()}
  187. c.ServeJSON()
  188. // 记录错误日志
  189. common.LogUserAction("", userName, "course_query_failed", "course", logrus.Fields{
  190. "reason": "database_error",
  191. "ip": clientIP,
  192. "error": err.Error(),
  193. })
  194. return
  195. }
  196. // 记录查询成功日志
  197. common.LogUserAction("", userName, "course_query_success", "course", logrus.Fields{
  198. "ip": clientIP,
  199. "result_count": count,
  200. "query_params": map[string]interface{}{
  201. "course_id": query.CourseID,
  202. "course_name": query.CourseName,
  203. "type_id": query.TypeID,
  204. "creator": query.Creator,
  205. "line_no": query.LineNo,
  206. "jxjh_id": query.JXJHID,
  207. },
  208. })
  209. c.Data["json"] = map[string]interface{}{"code": 200, "count": count, "msg": "", "data": courses}
  210. c.ServeJSON()
  211. }
  212. // /course/listpage 获取所有课程信息列表
  213. func (c *CourseController) ListPage() {
  214. type Request struct {
  215. PageNum int `json:"pageNum"`
  216. PageSize int `json:"pageSize"`
  217. CourseID int `json:"courseID"`
  218. CourseName string `json:"courseName"`
  219. TypeID int `json:"typeID"`
  220. Creator string `json:"creator"`
  221. LineNo int `json:"lineNo"`
  222. }
  223. var req Request
  224. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  225. c.Ctx.Output.SetStatus(400)
  226. c.Data["json"] = map[string]interface{}{
  227. "code": 400,
  228. "msg": "请求参数格式错误: " + err.Error(),
  229. }
  230. c.ServeJSON()
  231. return
  232. }
  233. // 设置默认值
  234. if req.PageNum <= 0 {
  235. req.PageNum = 1
  236. }
  237. if req.PageSize <= 0 {
  238. req.PageSize = 10
  239. }
  240. o := orm.NewOrm()
  241. qs := o.QueryTable(new(models.CourseInfo))
  242. // 编号查询
  243. if req.CourseID != 0 {
  244. qs = qs.Filter("CourseID", req.CourseID)
  245. }
  246. // 课程名称模糊查询
  247. if req.CourseName != "" {
  248. qs = qs.Filter("CourseName__icontains", req.CourseName)
  249. }
  250. // 培训类型查询(分类ID)
  251. if req.TypeID != 0 {
  252. qs = qs.Filter("TypeID", req.TypeID)
  253. }
  254. // 创建人查询
  255. if req.Creator != "" {
  256. qs = qs.Filter("Creator__icontains", req.Creator)
  257. }
  258. // 线路查询(线路号)
  259. if req.LineNo != 0 {
  260. qs = qs.Filter("LineNo", req.LineNo)
  261. }
  262. // 获取总数
  263. totalCount, err := qs.Count()
  264. if err != nil {
  265. c.Data["json"] = map[string]interface{}{
  266. "code": 500,
  267. "msg": "查询失败: " + err.Error(),
  268. }
  269. c.ServeJSON()
  270. return
  271. }
  272. // 计算总页数
  273. totalPage := int((totalCount + int64(req.PageSize) - 1) / int64(req.PageSize))
  274. // 分页查询,按创建时间倒序排列
  275. var courses []models.CourseInfo
  276. _, err = qs.OrderBy("-CreateTime").Limit(req.PageSize).Offset((req.PageNum-1)*req.PageSize).All(&courses,
  277. "课程ID", "课程GUID", "课程名称", "分类ID", "外部分类ID", "虚拟起始时间", "课程总时长", "线路号", "运行图",
  278. "课程描述", "创建人", "创建时间", "修改时间", "指导描述", "指导文件地址", "虚拟角色", "课程分类ID", "课程分类名称", "创建人ID")
  279. if err != nil {
  280. c.Data["json"] = map[string]interface{}{
  281. "code": 500,
  282. "msg": "查询失败: " + err.Error(),
  283. }
  284. c.ServeJSON()
  285. return
  286. }
  287. // 构造分页数据
  288. pageData := map[string]interface{}{
  289. "pageNum": req.PageNum,
  290. "pageSize": req.PageSize,
  291. "totalCount": totalCount,
  292. "totalPage": totalPage,
  293. "list": courses,
  294. }
  295. c.Data["json"] = map[string]interface{}{
  296. "code": 200,
  297. "msg": "success",
  298. "data": pageData,
  299. }
  300. c.ServeJSON()
  301. }
  302. // /course/add 新增课程信息
  303. func (c *CourseController) Add() {
  304. var course models.CourseInfo
  305. requestBody := c.Ctx.Input.RequestBody
  306. println("Request Body:", string(requestBody))
  307. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &course); err != nil {
  308. c.Ctx.Output.SetStatus(400)
  309. c.Data["json"] = map[string]interface{}{
  310. "code": 400,
  311. "msg": "请求参数格式错误: " + err.Error(),
  312. }
  313. c.ServeJSON()
  314. return
  315. }
  316. course.CourseID = 0
  317. course.CourseGUID = ""
  318. o := orm.NewOrm()
  319. // 自动生成 CourseID
  320. if course.CourseID == 0 {
  321. var maxID int
  322. err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID)
  323. if err != nil {
  324. c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取最大ID失败: " + err.Error()}
  325. c.ServeJSON()
  326. return
  327. }
  328. course.CourseID = maxID + 1
  329. }
  330. // 自动生成 CourseGUID
  331. if course.CourseGUID == "" {
  332. course.CourseGUID = uuid.New().String()
  333. }
  334. course.CreateTime = time.Now().Format("2006-01-02 15:04:05")
  335. course.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  336. _, err := o.Insert(&course)
  337. if err != nil {
  338. c.Data["json"] = map[string]interface{}{"code": 500, "msg": "新增失败: " + err.Error()}
  339. c.ServeJSON()
  340. return
  341. }
  342. c.Data["json"] = map[string]interface{}{
  343. "code": 200,
  344. "msg": "新增成功",
  345. "data": map[string]interface{}{
  346. "courseID": course.CourseID,
  347. "courseGUID": course.CourseGUID,
  348. },
  349. }
  350. c.ServeJSON()
  351. }
  352. // /course/update 更新课程信息
  353. func (c *CourseController) Update() {
  354. var course models.CourseInfo
  355. requestBody := c.Ctx.Input.RequestBody
  356. println("Request Body:", string(requestBody))
  357. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &course); err != nil {
  358. c.Ctx.Output.SetStatus(400)
  359. c.Data["json"] = map[string]interface{}{
  360. "code": 400,
  361. "msg": "请求参数格式错误: " + err.Error(),
  362. }
  363. c.ServeJSON()
  364. return
  365. }
  366. o := orm.NewOrm()
  367. course.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  368. _, err := o.Update(&course, "课程名称", "分类ID", "外部分类ID", "虚拟起始时间", "课程总时长", "线路号", "运行图", "课程描述", "创建人",
  369. "修改时间", "指导描述", "指导文件地址", "课程分类ID", "课程分类名称", "创建人ID")
  370. if err != nil {
  371. c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()}
  372. c.ServeJSON()
  373. return
  374. }
  375. c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"}
  376. c.ServeJSON()
  377. }
  378. // Upload 方法处理文件上传
  379. func (c *CourseController) Upload() {
  380. // 1. 获取上传的文件
  381. file, header, err := c.GetFile("file") // "file" 是表单中文件字段的 name:cite[3]:cite[6]
  382. if err != nil {
  383. c.Ctx.Output.SetStatus(500)
  384. c.Data["json"] = map[string]interface{}{
  385. "code": 500,
  386. "msg": "获取文件失败: " + err.Error(),
  387. }
  388. c.ServeJSON()
  389. return
  390. }
  391. defer file.Close()
  392. // // 2. 获取课程ID参数
  393. // courseId, err := c.GetInt("courseId")
  394. // if err != nil {
  395. // c.Ctx.Output.SetStatus(400)
  396. // c.Data["json"] = map[string]interface{}{
  397. // "code": 400,
  398. // "msg": "缺少课程ID参数或参数格式错误: " + err.Error(),
  399. // }
  400. // c.ServeJSON()
  401. // return
  402. // }
  403. // // 2. 节点ID为0
  404. // nodeId, err := c.GetInt("nodeId")
  405. // if err != nil {
  406. // println("节点ID为null")
  407. // }
  408. // strDir := fmt.Sprintf("static/upload/%d/", courseId)
  409. // if nodeId > 0 {
  410. // strDir = fmt.Sprintf("static/upload/%d/%d/", courseId, nodeId)
  411. // }
  412. strDir := "static/upload/"
  413. if _, err := os.Stat(strDir); os.IsNotExist(err) {
  414. os.MkdirAll(strDir, os.ModePerm)
  415. }
  416. uploadPath := path.Join(strDir, header.Filename) // 文件保存路径
  417. // 3. 保存文件:cite[3]:cite[6]
  418. err = c.SaveToFile("file", uploadPath)
  419. if err != nil {
  420. c.Ctx.Output.SetStatus(500)
  421. c.Data["json"] = map[string]interface{}{
  422. "code": 500,
  423. "msg": "文件保存失败: " + err.Error(),
  424. }
  425. c.ServeJSON()
  426. return
  427. }
  428. // 4. 构建文件的访问 URL:cite[2]
  429. fileUrl := uploadPath
  430. // //保存到课程信息中 指导文件地址 字段
  431. // o := orm.NewOrm()
  432. // //保存到课程或者节点里面
  433. // if nodeId == 0 {
  434. // course := models.CourseInfo{CourseID: courseId}
  435. // if o.Read(&course, "课程ID") == nil {
  436. // course.GuideFilePath = fileUrl
  437. // course.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  438. // if _, err := o.Update(&course, "指导文件地址", "修改时间"); err != nil {
  439. // c.Ctx.Output.SetStatus(500)
  440. // c.Data["json"] = map[string]interface{}{
  441. // "code": 500,
  442. // "msg": "更新课程信息失败: " + err.Error(),
  443. // }
  444. // c.ServeJSON()
  445. // return
  446. // }
  447. // }
  448. // } else {
  449. // //保存到节点里面
  450. // node := models.CourseActionNode{NodeID: nodeId}
  451. // if o.Read(&node, "节点ID") == nil {
  452. // node.GuideFilePath = fileUrl
  453. // if _, err := o.Update(&node, "指导文件地址"); err != nil {
  454. // c.Ctx.Output.SetStatus(500)
  455. // c.Data["json"] = map[string]interface{}{
  456. // "code": 500,
  457. // "msg": "更新节点信息失败: " + err.Error(),
  458. // }
  459. // c.ServeJSON()
  460. // return
  461. // }
  462. // }
  463. // }
  464. // 5. 返回成功信息和文件 URL:cite[3]
  465. c.Data["json"] = map[string]interface{}{
  466. "code": 200,
  467. "message": "文件上传成功",
  468. "data": map[string]string{
  469. "url": fileUrl,
  470. },
  471. }
  472. c.ServeJSON()
  473. }
  474. // /course/delete 删除课程信息
  475. func (c *CourseController) Delete() {
  476. // 解析请求中的课程ID数组
  477. var req []struct {
  478. CourseID int `json:"courseId"`
  479. }
  480. requestBody := c.Ctx.Input.RequestBody
  481. println("Request Body:", string(requestBody))
  482. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  483. c.Ctx.Output.SetStatus(400)
  484. c.Data["json"] = map[string]interface{}{
  485. "code": 400,
  486. "msg": "请求参数格式错误: " + err.Error(),
  487. }
  488. c.ServeJSON()
  489. return
  490. }
  491. if len(req) == 0 {
  492. c.Data["json"] = map[string]interface{}{"code": 400, "msg": "请提供要删除的课程ID"}
  493. c.ServeJSON()
  494. return
  495. }
  496. o := orm.NewOrm()
  497. // 记录删除成功的课程数量
  498. successCount := 0
  499. failedCourses := make([]map[string]interface{}, 0)
  500. // 提取课程ID列表
  501. courseIds := make([]int, len(req))
  502. for i, item := range req {
  503. courseIds[i] = item.CourseID
  504. }
  505. for _, courseID := range courseIds {
  506. // 先删除相关的课程运行记录
  507. _, err := o.Raw("DELETE FROM CourseRunLog WHERE 运行课程ID = ?", courseID).Exec()
  508. if err != nil {
  509. failedCourses = append(failedCourses, map[string]interface{}{
  510. "courseId": courseID,
  511. "reason": "删除课程运行记录失败: " + err.Error(),
  512. })
  513. continue
  514. }
  515. // 删除课程运行操作日志记录
  516. _, err = o.Raw("DELETE FROM CourseOperLog WHERE 运行课程ID = ?", courseID).Exec()
  517. if err != nil {
  518. failedCourses = append(failedCourses, map[string]interface{}{
  519. "courseId": courseID,
  520. "reason": "删除课程操作日志失败: " + err.Error(),
  521. })
  522. continue
  523. }
  524. // 删除课程评价日志记录
  525. _, err = o.Raw("DELETE FROM CourseEvaLog WHERE 运行课程ID = ?", courseID).Exec()
  526. if err != nil {
  527. failedCourses = append(failedCourses, map[string]interface{}{
  528. "courseId": courseID,
  529. "reason": "删除课程评价日志失败: " + err.Error(),
  530. })
  531. continue
  532. }
  533. // 删除课程基本信息
  534. nCount, err := o.Delete(&models.CourseInfo{CourseID: courseID})
  535. if err != nil {
  536. failedCourses = append(failedCourses, map[string]interface{}{
  537. "courseId": courseID,
  538. "reason": "删除失败: " + err.Error(),
  539. })
  540. continue
  541. }
  542. if nCount == 0 {
  543. failedCourses = append(failedCourses, map[string]interface{}{
  544. "courseId": courseID,
  545. "reason": "课程不存在",
  546. })
  547. continue
  548. }
  549. // 成功删除课程基本信息后,清理相关节点数据
  550. ClearCourse(courseID)
  551. successCount++
  552. }
  553. // 构造返回结果
  554. result := map[string]interface{}{
  555. "code": 200,
  556. "msg": fmt.Sprintf("删除成功%d条记录,失败%d条记录", successCount, len(failedCourses)),
  557. }
  558. if len(failedCourses) > 0 {
  559. result["failed"] = failedCourses
  560. }
  561. c.Data["json"] = result
  562. c.ServeJSON()
  563. }
  564. // /course/detail/get 获取课程详细信息
  565. func (c *CourseController) GetDetail() {
  566. type Query struct {
  567. CourseId int `json:"courseId"`
  568. }
  569. var query Query
  570. requestBody := c.Ctx.Input.RequestBody
  571. println("Request Body:", string(requestBody))
  572. if err := json.Unmarshal(requestBody, &query); err != nil {
  573. c.Ctx.Output.SetStatus(400)
  574. c.Data["json"] = map[string]interface{}{
  575. "code": 400,
  576. "msg": "请求参数格式错误: " + err.Error(),
  577. }
  578. c.ServeJSON()
  579. return
  580. }
  581. if query.CourseId == 0 {
  582. c.Ctx.Output.SetStatus(400)
  583. c.Data["json"] = map[string]interface{}{
  584. "code": 400,
  585. "msg": "缺少课程ID",
  586. }
  587. c.ServeJSON()
  588. return
  589. }
  590. o := orm.NewOrm()
  591. var course models.CourseInfo
  592. err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID", query.CourseId).One(&course)
  593. if err != nil {
  594. c.Ctx.Output.SetStatus(404)
  595. c.Data["json"] = map[string]interface{}{
  596. "code": 404,
  597. "msg": "课程不存在: " + err.Error(),
  598. }
  599. c.ServeJSON()
  600. return
  601. }
  602. c.Data["json"] = map[string]interface{}{
  603. "code": 200,
  604. "data": course,
  605. }
  606. c.ServeJSON()
  607. }
  608. // /course/detail/set 设置课程详细信息
  609. func (c *CourseController) SetDetail() {
  610. type Query struct {
  611. CourseId int `json:"courseId"`
  612. CourseDataStream string `json:"courseDataStream"`
  613. }
  614. var query Query
  615. requestBody := c.Ctx.Input.RequestBody
  616. // println("Request Body:", string(requestBody))
  617. if err := json.Unmarshal(requestBody, &query); err != nil {
  618. c.Ctx.Output.SetStatus(400)
  619. c.Data["json"] = map[string]interface{}{
  620. "code": 400,
  621. "msg": "传输的JSON格式不正确: " + err.Error(),
  622. }
  623. c.ServeJSON()
  624. return
  625. }
  626. if query.CourseId == 0 {
  627. c.Ctx.Output.SetStatus(400)
  628. c.Data["json"] = map[string]interface{}{
  629. "code": 400,
  630. "msg": "缺少课程ID",
  631. }
  632. c.ServeJSON()
  633. return
  634. }
  635. o := orm.NewOrm()
  636. var course models.CourseInfo
  637. err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID", query.CourseId).One(&course)
  638. if err != nil {
  639. c.Ctx.Output.SetStatus(404)
  640. c.Data["json"] = map[string]interface{}{
  641. "code": 404,
  642. "msg": "课程不存在: " + err.Error(),
  643. }
  644. c.ServeJSON()
  645. return
  646. }
  647. // 更新 FlowData 字段
  648. course.CourseDataStream = query.CourseDataStream
  649. course.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  650. _, err = o.Update(&course, "课程数据流", "修改时间")
  651. if err != nil {
  652. c.Ctx.Output.SetStatus(500)
  653. c.Data["json"] = map[string]interface{}{
  654. "code": 500,
  655. "msg": "更新失败: " + err.Error(),
  656. }
  657. c.ServeJSON()
  658. return
  659. }
  660. //保存数据
  661. isRet, errmsg := ParserAndSaveNode(query.CourseId, query.CourseDataStream)
  662. if !isRet {
  663. c.Ctx.Output.SetStatus(500)
  664. c.Data["json"] = map[string]interface{}{
  665. "code": 500,
  666. "msg": "更新节点失败: " + errmsg,
  667. }
  668. c.ServeJSON()
  669. return
  670. }
  671. c.Data["json"] = map[string]interface{}{
  672. "code": 200,
  673. "msg": "课程数据流更新成功",
  674. }
  675. c.ServeJSON()
  676. }
  677. // /coursetype/list 获取课程分类列表
  678. func (c *CourseController) GetCourseTypeList() {
  679. o := orm.NewOrm()
  680. // 查询所有课程分类
  681. var courseTypes []*models.CourseType
  682. count, err := o.QueryTable(new(models.CourseType)).All(&courseTypes)
  683. if err != nil {
  684. c.Data["json"] = map[string]interface{}{
  685. "code": 500,
  686. "msg": "查询课程分类失败: " + err.Error(),
  687. }
  688. c.ServeJSON()
  689. return
  690. }
  691. c.Data["json"] = map[string]interface{}{
  692. "code": 200,
  693. "count": count,
  694. "msg": "",
  695. "data": courseTypes,
  696. }
  697. c.ServeJSON()
  698. }
  699. // /role/list 获取所有通讯角色列表
  700. func (c *CourseController) GetRoleList() {
  701. o := orm.NewOrm()
  702. // 查询所有通讯角色
  703. var roleInfos []*models.RoleInfo
  704. count, err := o.QueryTable(new(models.RoleInfo)).All(&roleInfos)
  705. if err != nil {
  706. c.Data["json"] = map[string]interface{}{
  707. "code": 500,
  708. "msg": "查询通讯角色失败: " + err.Error(),
  709. }
  710. c.ServeJSON()
  711. return
  712. }
  713. c.Data["json"] = map[string]interface{}{
  714. "code": 200,
  715. "count": count,
  716. "msg": "",
  717. "data": roleInfos,
  718. }
  719. c.ServeJSON()
  720. }
  721. // /templateoperation/list 获取所有操作类型模板列表
  722. func (c *CourseController) GetTemplateOperationList() {
  723. o := orm.NewOrm()
  724. // 查询所有操作类型模板
  725. var templates []*models.TemplateOperation
  726. count, err := o.QueryTable(new(models.TemplateOperation)).All(&templates)
  727. if err != nil {
  728. c.Data["json"] = map[string]interface{}{
  729. "code": 500,
  730. "msg": "查询操作类型模板失败: " + err.Error(),
  731. }
  732. c.ServeJSON()
  733. return
  734. }
  735. c.Data["json"] = map[string]interface{}{
  736. "code": 200,
  737. "count": count,
  738. "msg": "",
  739. "data": templates,
  740. }
  741. c.ServeJSON()
  742. }
  743. // /templatevoice/list 获取所有语音类型模板列表
  744. func (c *CourseController) GetTemplateVoiceList() {
  745. o := orm.NewOrm()
  746. // 查询所有语音类型模板
  747. var templates []*models.TemplateVoice
  748. count, err := o.QueryTable(new(models.TemplateVoice)).All(&templates)
  749. if err != nil {
  750. c.Data["json"] = map[string]interface{}{
  751. "code": 500,
  752. "msg": "查询语音类型模板失败: " + err.Error(),
  753. }
  754. c.ServeJSON()
  755. return
  756. }
  757. c.Data["json"] = map[string]interface{}{
  758. "code": 200,
  759. "count": count,
  760. "msg": "",
  761. "data": templates,
  762. }
  763. c.ServeJSON()
  764. }
  765. // /templatefault/list 获取所有故障类型模板列表
  766. func (c *CourseController) GetTemplateFaultList() {
  767. o := orm.NewOrm()
  768. // 查询所有故障类型模板
  769. var templates []*models.TemplateFault
  770. count, err := o.QueryTable(new(models.TemplateFault)).All(&templates)
  771. if err != nil {
  772. c.Data["json"] = map[string]interface{}{
  773. "code": 500,
  774. "msg": "查询故障类型模板失败: " + err.Error(),
  775. }
  776. c.ServeJSON()
  777. return
  778. }
  779. c.Data["json"] = map[string]interface{}{
  780. "code": 200,
  781. "count": count,
  782. "msg": "",
  783. "data": templates,
  784. }
  785. c.ServeJSON()
  786. }
  787. // /dict/list 获取所有字典列表
  788. func (c *CourseController) GetDictList() {
  789. type Query struct {
  790. DictionaryType int `json:"dictionaryType"`
  791. DictionarySubType int `json:"dictionarySubType"`
  792. }
  793. var query Query
  794. requestBody := c.Ctx.Input.RequestBody
  795. println("Request Body:", string(requestBody))
  796. if err := json.Unmarshal(requestBody, &query); err != nil {
  797. c.Ctx.Output.SetStatus(400)
  798. c.Data["json"] = map[string]interface{}{
  799. "code": 400,
  800. "msg": "请求参数格式错误: " + err.Error(),
  801. }
  802. c.ServeJSON()
  803. return
  804. }
  805. o := orm.NewOrm()
  806. var dicts []*models.TypeMapList
  807. qs := o.QueryTable(new(models.TypeMapList))
  808. if query.DictionaryType != 0 {
  809. qs = qs.Filter("DictionaryType", query.DictionaryType)
  810. }
  811. if query.DictionarySubType != 0 {
  812. qs = qs.Filter("DictionarySubType", query.DictionarySubType)
  813. }
  814. count, err := qs.All(&dicts)
  815. if err != nil {
  816. c.Data["json"] = map[string]interface{}{
  817. "code": 500,
  818. "msg": "查询字典列表失败: " + err.Error(),
  819. }
  820. c.ServeJSON()
  821. return
  822. }
  823. c.Data["json"] = map[string]interface{}{
  824. "code": 200,
  825. "count": count,
  826. "msg": "",
  827. "data": dicts,
  828. }
  829. c.ServeJSON()
  830. }
  831. // /dict/listall 获取所有字典列表
  832. func (c *CourseController) GetDictListAll() {
  833. o := orm.NewOrm()
  834. var dicts []*models.TypeMapList
  835. qs := o.QueryTable(new(models.TypeMapList))
  836. count, err := qs.All(&dicts)
  837. if err != nil {
  838. c.Data["json"] = map[string]interface{}{
  839. "code": 500,
  840. "msg": "查询字典列表失败: " + err.Error(),
  841. }
  842. c.ServeJSON()
  843. return
  844. }
  845. // 按照指定格式组织数据
  846. type Item struct {
  847. KeyParam int `json:"keyParam"`
  848. ValueParam string `json:"valueParam"`
  849. }
  850. type Dict struct {
  851. DictionaryType int `json:"dictionaryType"`
  852. DictionaryTypeName string `json:"dictionaryTypeName"`
  853. DictionarySubType int `json:"dictionarySubType"`
  854. DictionarySubTypeName string `json:"dictionarySubTypeName"`
  855. KeyType string `json:"keyType"`
  856. Items []Item `json:"items"`
  857. }
  858. // 将数据转换为所需的格式
  859. dictMap := make(map[string]*Dict)
  860. for _, dict := range dicts {
  861. key := fmt.Sprintf("%d_%d", dict.DictionaryType, dict.DictionarySubType)
  862. if d, exists := dictMap[key]; exists {
  863. // 如果已存在该字典类型,则添加item
  864. d.Items = append(d.Items, Item{
  865. KeyParam: dict.KeyParam,
  866. ValueParam: dict.ValueParam,
  867. })
  868. } else {
  869. // 创建新的字典类型
  870. dictMap[key] = &Dict{
  871. DictionaryType: dict.DictionaryType,
  872. DictionaryTypeName: dict.DictionaryTypeName,
  873. DictionarySubType: dict.DictionarySubType,
  874. DictionarySubTypeName: dict.DictionarySubTypeName,
  875. KeyType: fmt.Sprintf("%d_%d", dict.DictionaryType, dict.DictionarySubType),
  876. Items: []Item{{
  877. KeyParam: dict.KeyParam,
  878. ValueParam: dict.ValueParam,
  879. }},
  880. }
  881. }
  882. }
  883. // 将map转换为slice
  884. result := make([]Dict, 0, len(dictMap))
  885. for _, dict := range dictMap {
  886. result = append(result, *dict)
  887. }
  888. c.Data["json"] = map[string]interface{}{
  889. "code": 200,
  890. "count": count,
  891. "msg": "",
  892. "data": map[string]interface{}{
  893. "dicts": result,
  894. },
  895. }
  896. c.ServeJSON()
  897. }
  898. // /course/copy 课程复制
  899. func (c *CourseController) CourseCopy() {
  900. // 解析请求中的课程ID数组
  901. var req []struct {
  902. CourseID int `json:"courseId"`
  903. }
  904. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  905. c.Ctx.Output.SetStatus(400)
  906. c.Data["json"] = map[string]interface{}{
  907. "code": 400,
  908. "msg": "请求参数格式错误: " + err.Error(),
  909. }
  910. c.ServeJSON()
  911. return
  912. }
  913. if len(req) == 0 {
  914. c.Ctx.Output.SetStatus(400)
  915. c.Data["json"] = map[string]interface{}{
  916. "code": 400,
  917. "msg": "请提供要复制的课程ID",
  918. }
  919. c.ServeJSON()
  920. return
  921. }
  922. o := orm.NewOrm()
  923. // 存储复制成功的课程信息
  924. successCourses := make([]map[string]interface{}, 0)
  925. // 存储复制失败的课程信息
  926. failedCourses := make([]map[string]interface{}, 0)
  927. // 提取课程ID列表
  928. courseIds := make([]int, len(req))
  929. for i, item := range req {
  930. courseIds[i] = item.CourseID
  931. }
  932. for _, courseID := range courseIds {
  933. // 获取原课程信息
  934. var originalCourse models.CourseInfo
  935. err := o.QueryTable(new(models.CourseInfo)).Filter("CourseID", courseID).One(&originalCourse)
  936. if err != nil {
  937. failedCourses = append(failedCourses, map[string]interface{}{
  938. "courseID": courseID,
  939. "reason": "未找到要复制的课程: " + err.Error(),
  940. })
  941. continue
  942. }
  943. // 创建新课程
  944. newCourse := originalCourse
  945. newCourse.CourseID = 0 // 让ORM自动生成新的ID
  946. newCourse.CourseGUID = uuid.New().String()
  947. newCourse.CreateTime = time.Now().Format("2006-01-02 15:04:05")
  948. newCourse.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  949. // 自动生成 CourseID
  950. if newCourse.CourseID == 0 {
  951. var maxID int
  952. err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID)
  953. if err != nil {
  954. failedCourses = append(failedCourses, map[string]interface{}{
  955. "courseID": courseID,
  956. "reason": "获取最大ID失败: " + err.Error(),
  957. })
  958. continue
  959. }
  960. newCourse.CourseID = maxID + 1
  961. }
  962. // 插入新课程
  963. _, err = o.Insert(&newCourse)
  964. if err != nil {
  965. failedCourses = append(failedCourses, map[string]interface{}{
  966. "courseID": courseID,
  967. "reason": "创建新课程失败: " + err.Error(),
  968. })
  969. continue
  970. }
  971. // 复制课程相关的节点数据
  972. // 复制 CourseActionNode
  973. var actionNodes []models.CourseActionNode
  974. _, err = o.QueryTable(new(models.CourseActionNode)).Filter("CourseID", courseID).All(&actionNodes)
  975. if err != nil && err != orm.ErrNoRows {
  976. failedCourses = append(failedCourses, map[string]interface{}{
  977. "courseID": courseID,
  978. "reason": "查询动作节点失败: " + err.Error(),
  979. })
  980. // 回滚已创建的新课程
  981. o.Delete(&newCourse)
  982. continue
  983. }
  984. for _, node := range actionNodes {
  985. node.CourseID = newCourse.CourseID
  986. _, err = o.Insert(&node)
  987. if err != nil {
  988. failedCourses = append(failedCourses, map[string]interface{}{
  989. "courseID": courseID,
  990. "reason": "复制动作节点失败: " + err.Error(),
  991. })
  992. // 回滚已创建的新课程和节点数据
  993. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  994. o.Delete(&newCourse)
  995. break
  996. }
  997. }
  998. // 如果复制动作节点失败,则跳过该课程
  999. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1000. continue
  1001. }
  1002. // 复制 CourseOperationNode
  1003. var operationNodes []models.CourseOperationNode
  1004. _, err = o.QueryTable(new(models.CourseOperationNode)).Filter("CourseID", courseID).All(&operationNodes)
  1005. if err != nil && err != orm.ErrNoRows {
  1006. failedCourses = append(failedCourses, map[string]interface{}{
  1007. "courseID": courseID,
  1008. "reason": "查询操作节点失败: " + err.Error(),
  1009. })
  1010. // 回滚已创建的数据
  1011. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1012. o.Delete(&newCourse)
  1013. continue
  1014. }
  1015. for _, node := range operationNodes {
  1016. node.CourseID = newCourse.CourseID
  1017. // 如果主观评价标记未设置,默认为0(客观评价)
  1018. if node.SubjectiveEvaluation == 0 {
  1019. node.SubjectiveEvaluation = 0 // 默认为客观评价
  1020. }
  1021. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1022. if err != nil {
  1023. failedCourses = append(failedCourses, map[string]interface{}{
  1024. "courseID": courseID,
  1025. "reason": "复制操作节点失败: " + err.Error(),
  1026. })
  1027. // 回滚已创建的数据
  1028. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1029. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1030. o.Delete(&newCourse)
  1031. break
  1032. }
  1033. }
  1034. // 如果复制操作节点失败,则跳过该课程
  1035. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1036. continue
  1037. }
  1038. // 复制 CourseFaultNode
  1039. var faultNodes []models.CourseFaultNode
  1040. _, err = o.QueryTable(new(models.CourseFaultNode)).Filter("CourseID", courseID).All(&faultNodes)
  1041. if err != nil && err != orm.ErrNoRows {
  1042. failedCourses = append(failedCourses, map[string]interface{}{
  1043. "courseID": courseID,
  1044. "reason": "查询故障节点失败: " + err.Error(),
  1045. })
  1046. // 回滚已创建的数据
  1047. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1048. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1049. o.Delete(&newCourse)
  1050. continue
  1051. }
  1052. for _, node := range faultNodes {
  1053. node.CourseID = newCourse.CourseID
  1054. // 注意:CourseFaultNode的CourseID和NodeID是联合主键
  1055. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1056. if err != nil {
  1057. failedCourses = append(failedCourses, map[string]interface{}{
  1058. "courseID": courseID,
  1059. "reason": "复制故障节点失败: " + err.Error(),
  1060. })
  1061. // 回滚已创建的数据
  1062. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1063. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1064. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1065. o.Delete(&newCourse)
  1066. break
  1067. }
  1068. }
  1069. // 如果复制故障节点失败,则跳过该课程
  1070. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1071. continue
  1072. }
  1073. // 复制 CourseVoiceNode
  1074. var voiceNodes []models.CourseVoiceNode
  1075. _, err = o.QueryTable(new(models.CourseVoiceNode)).Filter("CourseID", courseID).All(&voiceNodes)
  1076. if err != nil && err != orm.ErrNoRows {
  1077. failedCourses = append(failedCourses, map[string]interface{}{
  1078. "courseID": courseID,
  1079. "reason": "查询语音节点失败: " + err.Error(),
  1080. })
  1081. // 回滚已创建的数据
  1082. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1083. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1084. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1085. o.Delete(&newCourse)
  1086. continue
  1087. }
  1088. for _, node := range voiceNodes {
  1089. node.CourseID = newCourse.CourseID
  1090. // 注意:CourseVoiceNode的CourseID和NodeID是联合主键
  1091. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1092. if err != nil {
  1093. failedCourses = append(failedCourses, map[string]interface{}{
  1094. "courseID": courseID,
  1095. "reason": "复制语音节点失败: " + err.Error(),
  1096. })
  1097. // 回滚已创建的数据
  1098. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1099. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1100. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1101. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1102. o.Delete(&newCourse)
  1103. break
  1104. }
  1105. }
  1106. // 如果复制语音节点失败,则跳过该课程
  1107. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1108. continue
  1109. }
  1110. // 复制 CourseNodeTrigger
  1111. var triggers []models.CourseNodeTrigger
  1112. _, err = o.QueryTable(new(models.CourseNodeTrigger)).Filter("CourseID", courseID).All(&triggers)
  1113. if err != nil && err != orm.ErrNoRows {
  1114. failedCourses = append(failedCourses, map[string]interface{}{
  1115. "courseID": courseID,
  1116. "reason": "查询节点触发器失败: " + err.Error(),
  1117. })
  1118. // 回滚已创建的数据
  1119. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1120. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1121. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1122. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1123. o.Delete(&newCourse)
  1124. continue
  1125. }
  1126. for _, trigger := range triggers {
  1127. trigger.CourseID = newCourse.CourseID
  1128. // 注意:CourseNodeTrigger的CourseID和NodeID是联合主键
  1129. _, _, err = o.ReadOrCreate(&trigger, "CourseID", "NodeID")
  1130. if err != nil {
  1131. failedCourses = append(failedCourses, map[string]interface{}{
  1132. "courseID": courseID,
  1133. "reason": "复制节点触发器失败: " + err.Error(),
  1134. })
  1135. // 回滚已创建的数据
  1136. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1137. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1138. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1139. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1140. o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1141. o.Delete(&newCourse)
  1142. break
  1143. }
  1144. }
  1145. // 如果复制节点触发器失败,则跳过该课程
  1146. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1147. continue
  1148. }
  1149. // 复制 CourseEvaList
  1150. var evals []models.CourseEvaList
  1151. _, err = o.QueryTable(new(models.CourseEvaList)).Filter("CourseID", courseID).All(&evals)
  1152. if err != nil && err != orm.ErrNoRows {
  1153. failedCourses = append(failedCourses, map[string]interface{}{
  1154. "courseID": courseID,
  1155. "reason": "查询评价列表失败: " + err.Error(),
  1156. })
  1157. // 回滚已创建的数据
  1158. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1159. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1160. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1161. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1162. o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1163. o.Delete(&newCourse)
  1164. continue
  1165. }
  1166. for _, eval := range evals {
  1167. eval.CourseID = newCourse.CourseID
  1168. // 查询当前最大的序号
  1169. var maxSeqNo int
  1170. err = o.Raw("SELECT COALESCE(MAX(序号), 0) FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).QueryRow(&maxSeqNo)
  1171. if err != nil {
  1172. failedCourses = append(failedCourses, map[string]interface{}{
  1173. "courseID": courseID,
  1174. "reason": "查询评价序号失败: " + err.Error(),
  1175. })
  1176. // 回滚已创建的数据
  1177. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1178. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1179. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1180. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1181. o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1182. o.Raw("DELETE FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1183. o.Delete(&newCourse)
  1184. break
  1185. }
  1186. eval.SeqNo = maxSeqNo + 1
  1187. _, err = o.Insert(&eval)
  1188. if err != nil {
  1189. failedCourses = append(failedCourses, map[string]interface{}{
  1190. "courseID": courseID,
  1191. "reason": "复制评价项失败: " + err.Error(),
  1192. })
  1193. // 回滚已创建的数据
  1194. o.Raw("DELETE FROM CourseActionNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1195. o.Raw("DELETE FROM CourseOperationNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1196. o.Raw("DELETE FROM CourseFaultNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1197. o.Raw("DELETE FROM CourseVoiceNode WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1198. o.Raw("DELETE FROM CourseNodeTrigger WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1199. o.Raw("DELETE FROM CourseEvaList WHERE 课程ID = ?", newCourse.CourseID).Exec()
  1200. o.Delete(&newCourse)
  1201. break
  1202. }
  1203. }
  1204. // 如果复制评价项失败,则跳过该课程
  1205. if len(failedCourses) > 0 && failedCourses[len(failedCourses)-1]["courseID"] == courseID {
  1206. continue
  1207. }
  1208. // 所有复制操作都成功完成
  1209. successCourses = append(successCourses, map[string]interface{}{
  1210. "originalCourseID": courseID,
  1211. "newCourseID": newCourse.CourseID,
  1212. "newCourseGUID": newCourse.CourseGUID,
  1213. "newCourseName": newCourse.CourseName,
  1214. })
  1215. }
  1216. // 构造返回结果
  1217. data := map[string]interface{}{}
  1218. if len(successCourses) > 0 {
  1219. data["success"] = successCourses
  1220. }
  1221. if len(failedCourses) > 0 {
  1222. data["failed"] = failedCourses
  1223. }
  1224. response := map[string]interface{}{
  1225. "code": 200,
  1226. "msg": fmt.Sprintf("批量复制完成,成功%d条,失败%d条", len(successCourses), len(failedCourses)),
  1227. "data": data,
  1228. }
  1229. c.Data["json"] = response
  1230. c.ServeJSON()
  1231. }
  1232. // /course/import 课程导入
  1233. func (c *CourseController) CourseImport() {
  1234. // 获取上传的文件
  1235. file, header, err := c.GetFile("file")
  1236. if err != nil {
  1237. c.Ctx.Output.SetStatus(500)
  1238. c.Data["json"] = map[string]interface{}{
  1239. "code": 500,
  1240. "msg": "获取文件失败: " + err.Error(),
  1241. }
  1242. c.ServeJSON()
  1243. return
  1244. }
  1245. defer file.Close()
  1246. // 检查文件扩展名
  1247. ext := path.Ext(header.Filename)
  1248. if ext != ".json" {
  1249. c.Data["json"] = map[string]interface{}{
  1250. "code": 400,
  1251. "msg": "只支持导入JSON格式文件",
  1252. }
  1253. c.ServeJSON()
  1254. return
  1255. }
  1256. // 读取文件内容
  1257. fileSize := header.Size
  1258. buffer := make([]byte, fileSize)
  1259. _, err = file.Read(buffer)
  1260. if err != nil {
  1261. c.Data["json"] = map[string]interface{}{
  1262. "code": 500,
  1263. "msg": "读取文件失败: " + err.Error(),
  1264. }
  1265. c.ServeJSON()
  1266. return
  1267. }
  1268. // 解析JSON内容 - 支持多个课程
  1269. var importData []struct {
  1270. CourseInfo models.CourseInfo `json:"courseInfo"`
  1271. ActionNodes []models.CourseActionNode `json:"actionNodes"`
  1272. OperationNodes []models.CourseOperationNode `json:"operationNodes"`
  1273. FaultNodes []models.CourseFaultNode `json:"faultNodes"`
  1274. VoiceNodes []models.CourseVoiceNode `json:"voiceNodes"`
  1275. NodeTriggers []models.CourseNodeTrigger `json:"nodeTriggers"`
  1276. EvalLists []models.CourseEvaList `json:"evalLists"`
  1277. }
  1278. err = json.Unmarshal(buffer, &importData)
  1279. if err != nil {
  1280. c.Data["json"] = map[string]interface{}{
  1281. "code": 500,
  1282. "msg": "解析JSON文件失败: " + err.Error(),
  1283. }
  1284. c.ServeJSON()
  1285. return
  1286. }
  1287. o := orm.NewOrm()
  1288. // 存储导入结果
  1289. importResults := make([]map[string]interface{}, 0)
  1290. // 遍历所有要导入的课程
  1291. for _, courseData := range importData {
  1292. // 创建新课程
  1293. newCourse := courseData.CourseInfo
  1294. newCourse.CourseID = 0 // 让ORM生成新的ID
  1295. newCourse.CourseGUID = uuid.New().String()
  1296. newCourse.CreateTime = time.Now().Format("2006-01-02 15:04:05")
  1297. newCourse.ModifyTime = time.Now().Format("2006-01-02 15:04:05")
  1298. // 检查是否已存在同名课程,如果存在则添加序号进行区分
  1299. originalName := newCourse.CourseName
  1300. duplicateIndex := 1
  1301. for {
  1302. var existingCourse models.CourseInfo
  1303. err := o.QueryTable(new(models.CourseInfo)).Filter("CourseName", newCourse.CourseName).One(&existingCourse)
  1304. if err != nil && err != orm.ErrNoRows {
  1305. importResults = append(importResults, map[string]interface{}{
  1306. "courseName": originalName,
  1307. "status": "failed",
  1308. "msg": "检查课程名称唯一性失败: " + err.Error(),
  1309. })
  1310. break
  1311. }
  1312. // 如果没有找到同名课程,则可以使用该名称
  1313. if err == orm.ErrNoRows {
  1314. break
  1315. }
  1316. // 如果找到同名课程,则在名称后添加序号
  1317. newCourse.CourseName = fmt.Sprintf("%s(%d)", originalName, duplicateIndex)
  1318. duplicateIndex++
  1319. }
  1320. // 自动生成 CourseID
  1321. if newCourse.CourseID == 0 {
  1322. var maxID int
  1323. err := o.Raw("SELECT MAX(课程ID) FROM CourseInfo").QueryRow(&maxID)
  1324. if err != nil {
  1325. c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取最大ID失败: " + err.Error()}
  1326. c.ServeJSON()
  1327. return
  1328. }
  1329. newCourse.CourseID = maxID + 1
  1330. }
  1331. _, err = o.Insert(&newCourse)
  1332. if err != nil {
  1333. importResults = append(importResults, map[string]interface{}{
  1334. "courseName": courseData.CourseInfo.CourseName,
  1335. "status": "failed",
  1336. "msg": "创建课程失败: " + err.Error(),
  1337. })
  1338. continue
  1339. }
  1340. // 导入 CourseActionNode
  1341. for _, node := range courseData.ActionNodes {
  1342. node.CourseID = newCourse.CourseID
  1343. _, err = o.Insert(&node)
  1344. if err != nil {
  1345. importResults = append(importResults, map[string]interface{}{
  1346. "courseName": courseData.CourseInfo.CourseName,
  1347. "status": "failed",
  1348. "msg": "导入动作节点失败: " + err.Error(),
  1349. })
  1350. continue
  1351. }
  1352. }
  1353. // 导入 CourseOperationNode
  1354. for _, node := range courseData.OperationNodes {
  1355. node.CourseID = newCourse.CourseID
  1356. // 如果主观评价标记未设置,默认为0(客观评价)
  1357. if node.SubjectiveEvaluation == 0 {
  1358. node.SubjectiveEvaluation = 0 // 默认为客观评价
  1359. }
  1360. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1361. if err != nil {
  1362. importResults = append(importResults, map[string]interface{}{
  1363. "courseName": courseData.CourseInfo.CourseName,
  1364. "status": "failed",
  1365. "msg": "导入操作节点失败: " + err.Error(),
  1366. })
  1367. continue
  1368. }
  1369. }
  1370. // 导入 CourseFaultNode
  1371. for _, node := range courseData.FaultNodes {
  1372. node.CourseID = newCourse.CourseID
  1373. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1374. if err != nil {
  1375. importResults = append(importResults, map[string]interface{}{
  1376. "courseName": courseData.CourseInfo.CourseName,
  1377. "status": "failed",
  1378. "msg": "导入故障节点失败: " + err.Error(),
  1379. })
  1380. continue
  1381. }
  1382. }
  1383. // 导入 CourseVoiceNode
  1384. for _, node := range courseData.VoiceNodes {
  1385. node.CourseID = newCourse.CourseID
  1386. _, _, err = o.ReadOrCreate(&node, "CourseID", "NodeID")
  1387. if err != nil {
  1388. importResults = append(importResults, map[string]interface{}{
  1389. "courseName": courseData.CourseInfo.CourseName,
  1390. "status": "failed",
  1391. "msg": "导入语音节点失败: " + err.Error(),
  1392. })
  1393. continue
  1394. }
  1395. }
  1396. // 导入 CourseNodeTrigger
  1397. for _, trigger := range courseData.NodeTriggers {
  1398. trigger.CourseID = newCourse.CourseID
  1399. _, _, err = o.ReadOrCreate(&trigger, "CourseID", "NodeID")
  1400. if err != nil {
  1401. importResults = append(importResults, map[string]interface{}{
  1402. "courseName": courseData.CourseInfo.CourseName,
  1403. "status": "failed",
  1404. "msg": "导入节点触发器失败: " + err.Error(),
  1405. })
  1406. continue
  1407. }
  1408. }
  1409. // 导入 CourseEvaList
  1410. for i, eval := range courseData.EvalLists {
  1411. eval.CourseID = newCourse.CourseID
  1412. eval.SeqNo = i + 1 // 重新编号
  1413. _, err = o.Insert(&eval)
  1414. if err != nil {
  1415. importResults = append(importResults, map[string]interface{}{
  1416. "courseName": courseData.CourseInfo.CourseName,
  1417. "status": "failed",
  1418. "msg": "导入评价项失败: " + err.Error(),
  1419. })
  1420. continue
  1421. }
  1422. }
  1423. importResults = append(importResults, map[string]interface{}{
  1424. "courseName": newCourse.CourseName,
  1425. "status": "success",
  1426. "data": map[string]interface{}{
  1427. "courseID": newCourse.CourseID,
  1428. "courseGUID": newCourse.CourseGUID,
  1429. "courseName": newCourse.CourseName,
  1430. },
  1431. })
  1432. }
  1433. c.Data["json"] = map[string]interface{}{
  1434. "code": 200,
  1435. "msg": "课程导入完成",
  1436. "data": importResults,
  1437. "counts": map[string]int{
  1438. "total": len(importData),
  1439. "success": len(importResults) - failedCount(importResults),
  1440. "failed": failedCount(importResults),
  1441. },
  1442. }
  1443. c.ServeJSON()
  1444. }
  1445. // 辅助函数:计算导入失败的数量
  1446. func failedCount(results []map[string]interface{}) int {
  1447. count := 0
  1448. for _, result := range results {
  1449. if status, ok := result["status"].(string); ok && status == "failed" {
  1450. count++
  1451. }
  1452. }
  1453. return count
  1454. }
  1455. // // course/export 课程导出
  1456. func (c *CourseController) CourseExport() {
  1457. // 解析请求中的课程ID数组
  1458. var req []struct {
  1459. CourseID int `json:"courseId"`
  1460. }
  1461. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  1462. c.Ctx.Output.SetStatus(400)
  1463. c.Data["json"] = map[string]interface{}{
  1464. "code": 400,
  1465. "msg": "请求参数格式错误: " + err.Error(),
  1466. }
  1467. c.ServeJSON()
  1468. return
  1469. }
  1470. if len(req) == 0 {
  1471. c.Ctx.Output.SetStatus(400)
  1472. c.Data["json"] = map[string]interface{}{
  1473. "code": 400,
  1474. "msg": "参数不完整",
  1475. }
  1476. c.ServeJSON()
  1477. return
  1478. }
  1479. o := orm.NewOrm()
  1480. // 存储所有要导出的课程数据
  1481. exportData := make([]map[string]interface{}, 0)
  1482. // 遍历所有请求的课程ID
  1483. for _, item := range req {
  1484. if item.CourseID <= 0 {
  1485. continue
  1486. }
  1487. // 获取课程信息
  1488. var course models.CourseInfo
  1489. err := o.QueryTable(new(models.CourseInfo)).Filter("CourseID", item.CourseID).One(&course)
  1490. if err != nil {
  1491. // 如果找不到课程,继续处理下一个
  1492. continue
  1493. }
  1494. // 获取 CourseActionNode
  1495. var actionNodes []models.CourseActionNode
  1496. _, err = o.QueryTable(new(models.CourseActionNode)).Filter("CourseID", item.CourseID).All(&actionNodes)
  1497. if err != nil && err != orm.ErrNoRows {
  1498. // 错误处理,但继续处理下一个课程
  1499. continue
  1500. }
  1501. // 获取 CourseOperationNode
  1502. var operationNodes []models.CourseOperationNode
  1503. _, err = o.QueryTable(new(models.CourseOperationNode)).Filter("CourseID", item.CourseID).All(&operationNodes)
  1504. if err != nil && err != orm.ErrNoRows {
  1505. // 错误处理,但继续处理下一个课程
  1506. continue
  1507. }
  1508. // 获取 CourseFaultNode
  1509. var faultNodes []models.CourseFaultNode
  1510. _, err = o.QueryTable(new(models.CourseFaultNode)).Filter("CourseID", item.CourseID).All(&faultNodes)
  1511. if err != nil && err != orm.ErrNoRows {
  1512. // 错误处理,但继续处理下一个课程
  1513. continue
  1514. }
  1515. // 获取 CourseVoiceNode
  1516. var voiceNodes []models.CourseVoiceNode
  1517. _, err = o.QueryTable(new(models.CourseVoiceNode)).Filter("CourseID", item.CourseID).All(&voiceNodes)
  1518. if err != nil && err != orm.ErrNoRows {
  1519. // 错误处理,但继续处理下一个课程
  1520. continue
  1521. }
  1522. // 获取 CourseNodeTrigger
  1523. var triggers []models.CourseNodeTrigger
  1524. _, err = o.QueryTable(new(models.CourseNodeTrigger)).Filter("CourseID", item.CourseID).All(&triggers)
  1525. if err != nil && err != orm.ErrNoRows {
  1526. // 错误处理,但继续处理下一个课程
  1527. continue
  1528. }
  1529. // 获取 CourseEvaList
  1530. var evalLists []models.CourseEvaList
  1531. _, err = o.QueryTable(new(models.CourseEvaList)).Filter("CourseID", item.CourseID).All(&evalLists)
  1532. if err != nil && err != orm.ErrNoRows {
  1533. // 错误处理,但继续处理下一个课程
  1534. continue
  1535. }
  1536. // 构造单个课程的导出数据
  1537. singleExportData := map[string]interface{}{
  1538. "courseInfo": course,
  1539. "actionNodes": actionNodes,
  1540. "operationNodes": operationNodes,
  1541. "faultNodes": faultNodes,
  1542. "voiceNodes": voiceNodes,
  1543. "nodeTriggers": triggers,
  1544. "evalLists": evalLists,
  1545. }
  1546. exportData = append(exportData, singleExportData)
  1547. }
  1548. // 转换为JSON
  1549. jsonData, err := json.Marshal(exportData)
  1550. if err != nil {
  1551. c.Data["json"] = map[string]interface{}{
  1552. "code": 500,
  1553. "msg": "序列化数据失败: " + err.Error(),
  1554. }
  1555. c.ServeJSON()
  1556. return
  1557. }
  1558. // 设置响应头,触发浏览器下载
  1559. filename := "courses_export.json"
  1560. if len(req) == 1 {
  1561. filename = fmt.Sprintf("course_%d_export.json", req[0].CourseID)
  1562. }
  1563. c.Ctx.Output.Header("Content-Type", "application/octet-stream")
  1564. c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
  1565. c.Ctx.Output.Header("Content-Length", fmt.Sprintf("%d", len(jsonData)))
  1566. c.Ctx.Output.Body(jsonData)
  1567. }
  1568. // /gettmscoursetype 获取课程分类列表
  1569. func (c *CourseController) GetTMSCourseType() {
  1570. // 调用信息化接口获取课程分类列表,传入FZXTLX参数为1
  1571. response, err := common.GetAllCourseTypeEx(1)
  1572. if err != nil {
  1573. c.Ctx.Output.SetStatus(500)
  1574. c.Data["json"] = map[string]interface{}{
  1575. "code": 500,
  1576. "msg": "获取课程分类列表失败: " + err.Error(),
  1577. }
  1578. c.ServeJSON()
  1579. return
  1580. }
  1581. // 判断请求是否成功
  1582. if response.ResultCode != "0" {
  1583. c.Ctx.Output.SetStatus(500)
  1584. c.Data["json"] = map[string]interface{}{
  1585. "code": 500,
  1586. "msg": "获取课程分类列表失败: " + response.ResultDesc,
  1587. }
  1588. c.ServeJSON()
  1589. return
  1590. }
  1591. // 返回成功数据
  1592. c.Data["json"] = map[string]interface{}{
  1593. "code": 200,
  1594. "msg": "获取课程分类列表成功",
  1595. "data": response.CourseTypes,
  1596. }
  1597. c.ServeJSON()
  1598. }
  1599. // /course/uploadtms 上传课程到信息化平台
  1600. func (c *CourseController) UploadTMS() {
  1601. // 解析请求中的课程ID数组
  1602. var req []struct {
  1603. CourseID int `json:"courseId"`
  1604. }
  1605. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  1606. c.Ctx.Output.SetStatus(400)
  1607. c.Data["json"] = map[string]interface{}{
  1608. "code": 400,
  1609. "msg": "请求参数格式错误: " + err.Error(),
  1610. }
  1611. c.ServeJSON()
  1612. return
  1613. }
  1614. if len(req) == 0 {
  1615. c.Ctx.Output.SetStatus(400)
  1616. c.Data["json"] = map[string]interface{}{
  1617. "code": 400,
  1618. "msg": "请提供要上传的课程ID",
  1619. }
  1620. c.ServeJSON()
  1621. return
  1622. }
  1623. o := orm.NewOrm()
  1624. // 准备要上传的课程信息
  1625. var coursesToUpload []common.UploadCourseInfo
  1626. // 提取课程ID列表
  1627. courseIds := make([]int, len(req))
  1628. for i, item := range req {
  1629. courseIds[i] = item.CourseID
  1630. }
  1631. // 查询课程信息
  1632. var courses []models.CourseInfo
  1633. _, err := o.QueryTable(new(models.CourseInfo)).Filter("课程ID__in", courseIds).All(&courses)
  1634. if err != nil {
  1635. c.Ctx.Output.SetStatus(500)
  1636. c.Data["json"] = map[string]interface{}{
  1637. "code": 500,
  1638. "msg": "查询课程信息失败: " + err.Error(),
  1639. }
  1640. c.ServeJSON()
  1641. return
  1642. }
  1643. // 如果没有找到任何课程
  1644. if len(courses) == 0 {
  1645. c.Data["json"] = map[string]interface{}{
  1646. "code": 200,
  1647. "msg": "没有找到指定的课程",
  1648. "data": []common.UploadCourseInfo{},
  1649. }
  1650. c.ServeJSON()
  1651. return
  1652. }
  1653. // 从配置文件中读取CLLX和SYCX
  1654. cllx, _ := beego.AppConfig.String("SYSCLLX")
  1655. if cllx == "" {
  1656. cllx = "牵引变电实训室" // 默认值
  1657. }
  1658. sycx, _ := beego.AppConfig.String("SYSSYCX")
  1659. if sycx == "" {
  1660. sycx = "SCADA系统" // 默认值
  1661. }
  1662. // 将课程信息转换为上传格式
  1663. for _, course := range courses {
  1664. // 从数据库中查询线路名称
  1665. var typeMapList []models.TypeMapList
  1666. lineName := "" // 默认线路名称
  1667. o := orm.NewOrm()
  1668. err := o.QueryTable(new(models.TypeMapList)).
  1669. Filter("DictionaryTypeName", "线路号").
  1670. Filter("KeyParam", course.LineNo).
  1671. One(&typeMapList)
  1672. if err == nil && len(typeMapList) > 0 {
  1673. lineName = typeMapList[0].ValueParam
  1674. }
  1675. uploadCourse := common.UploadCourseInfo{
  1676. KCGUID: course.CourseGUID,
  1677. KCMC: course.CourseName,
  1678. KCMS: course.CourseDesc,
  1679. KCNR: course.CourseDesc, // 课程内容暂时使用课程描述
  1680. KCFLID: course.CourseCategoryID, // 课程分类ID
  1681. CJRID: course.CreatorID, // 创建人作为创建人ID
  1682. CJSJ: course.CreateTime, // 创建时间
  1683. XGRID: course.CreatorID, // 创建人作为修改人ID
  1684. XGSJ: course.ModifyTime, // 修改时间
  1685. PXMS: "1", // 排序模式,默认为1
  1686. Alone: common.Alone{
  1687. FZXTLX: "1", // 独立系统类型,默认为1
  1688. MJ: common.MJ{
  1689. CLLX: cllx, // 车辆类型
  1690. SYCX: sycx, // 适用车型
  1691. XLBH: fmt.Sprintf("%d", course.LineNo), // 线路编号
  1692. XLMC: lineName, // 线路名称,这里使用固定值
  1693. },
  1694. },
  1695. }
  1696. coursesToUpload = append(coursesToUpload, uploadCourse)
  1697. }
  1698. // 调用信息化接口上传课程
  1699. response, err := common.UploadCourseToInformationSystem(coursesToUpload)
  1700. if err != nil {
  1701. c.Ctx.Output.SetStatus(500)
  1702. c.Data["json"] = map[string]interface{}{
  1703. "code": 500,
  1704. "msg": "上传课程到信息化平台失败: " + err.Error(),
  1705. }
  1706. c.ServeJSON()
  1707. return
  1708. }
  1709. // 判断请求是否成功
  1710. // 根据返回的SucceedCount判断是否全部成功
  1711. succeedCount := 0
  1712. if response.SucceedCount != "" {
  1713. count, err := strconv.Atoi(response.SucceedCount)
  1714. if err == nil {
  1715. succeedCount = count
  1716. }
  1717. }
  1718. totalCount := len(response.CourseResults)
  1719. // 如果有失败的课程,返回详细信息
  1720. if succeedCount < totalCount {
  1721. c.Ctx.Output.SetStatus(500)
  1722. c.Data["json"] = map[string]interface{}{
  1723. "code": 500,
  1724. "msg": fmt.Sprintf("上传课程部分失败: 成功%d个,失败%d个", succeedCount, totalCount-succeedCount),
  1725. "data": response.CourseResults,
  1726. }
  1727. c.ServeJSON()
  1728. return
  1729. }
  1730. // 返回成功数据
  1731. c.Data["json"] = map[string]interface{}{
  1732. "code": 200,
  1733. "msg": "上传课程到信息化平台成功",
  1734. "data": response.CourseResults,
  1735. }
  1736. c.ServeJSON()
  1737. }
  1738. // /course/tmsplan 获取信息化系统的课程计划
  1739. func (c *CourseController) GetTMSCoursePlan() {
  1740. // 定义请求结构体
  1741. type Request struct {
  1742. SBID string `json:"SBID"` // 设备编号
  1743. JYEMPID string `json:"JYEMPID"` // 教员GUID
  1744. XYEMPID string `json:"XYEMPID"` // 学员GUID
  1745. }
  1746. var req Request
  1747. // if CurrentLoginMode == 1 {
  1748. // c.Ctx.Output.SetStatus(500)
  1749. // c.Data["json"] = map[string]interface{}{
  1750. // "code": 500,
  1751. // "msg": "本地模式不支持该功能 ",
  1752. // }
  1753. // c.ServeJSON()
  1754. // return
  1755. // }
  1756. // 从app.conf中读取SYSDEVICEID作为SBID的值
  1757. sbid, err := beego.AppConfig.String("SYSDEVICEID")
  1758. if err != nil {
  1759. c.Ctx.Output.SetStatus(500)
  1760. c.Data["json"] = map[string]interface{}{
  1761. "code": 500,
  1762. "msg": "获取设备编号失败: " + err.Error(),
  1763. }
  1764. c.ServeJSON()
  1765. return
  1766. }
  1767. req.SBID = sbid
  1768. // 解析请求中的参数 Header 中的 userName 判断用户缓存中的是学员还是教员,将对应人员guid 传入req
  1769. // 从Header中获取userName
  1770. authHeader := c.Ctx.Input.Header("userName")
  1771. if authHeader == "" {
  1772. c.Ctx.Output.SetStatus(401)
  1773. c.Data["json"] = map[string]interface{}{
  1774. "code": 401,
  1775. "msg": "未提供认证信息",
  1776. }
  1777. c.ServeJSON()
  1778. return
  1779. }
  1780. // 从缓存中获取用户信息
  1781. userInfo, exists := GetUserInfoFromCache(authHeader)
  1782. if !exists {
  1783. c.Ctx.Output.SetStatus(401)
  1784. c.Data["json"] = map[string]interface{}{
  1785. "code": 401,
  1786. "msg": "用户信息不存在",
  1787. }
  1788. c.ServeJSON()
  1789. return
  1790. }
  1791. switch userInfo.SF {
  1792. case "1": // 如果是教员,则使用当前用户的RYEMPID
  1793. req.XYEMPID = userInfo.RYEMPID
  1794. case "2": // 如果是学员,则使用当前用户的RYEMPID
  1795. req.JYEMPID = userInfo.RYEMPID
  1796. }
  1797. // 调用信息化接口获取培训计划
  1798. response, err := common.GetTeachPlanFromInformationSystem(req.SBID, req.JYEMPID, req.XYEMPID)
  1799. if err != nil {
  1800. c.Ctx.Output.SetStatus(500)
  1801. c.Data["json"] = map[string]interface{}{
  1802. "code": 500,
  1803. "msg": "获取培训计划失败: " + err.Error(),
  1804. }
  1805. c.ServeJSON()
  1806. return
  1807. }
  1808. // 判断请求是否成功
  1809. if response.ResultCode != "0" {
  1810. c.Ctx.Output.SetStatus(500)
  1811. c.Data["json"] = map[string]interface{}{
  1812. "code": 500,
  1813. "msg": "获取培训计划失败: " + response.ResultDesc,
  1814. }
  1815. c.ServeJSON()
  1816. return
  1817. }
  1818. // 提取需要返回给前端的数据
  1819. type PlanInfo struct {
  1820. JXJHID string `json:"JXJHID"` // 培训计划ID
  1821. KMMC string `json:"KMMC"` // 科目名称
  1822. SDKCGUIDs []string `json:"SDKCGUIDs"` // 培训课程GUID列表
  1823. TESTSTGUIDs []string `json:"TESTKCGUIDs"` // 测试课程GUID列表
  1824. }
  1825. // 提取需要返回给前端的数据
  1826. type PlanDoInfo struct {
  1827. PXSSID string `json:"PXSSID"` // 培训实施ID
  1828. PXSSMC string `json:"PXSSMC"` // 培训实施名称
  1829. PXInfo []PlanInfo `json:"PlanInfo"` // 培训计划信息
  1830. }
  1831. var plans []PlanDoInfo
  1832. // 遍历所有培训实施计划
  1833. for _, pxss := range response.PXSS {
  1834. PlanDoInfo := PlanDoInfo{PXSSID: pxss.PXSSID, PXSSMC: pxss.PXSSMC}
  1835. // 遍历所有计划
  1836. for _, jh := range pxss.JH {
  1837. plan := PlanInfo{
  1838. JXJHID: jh.ID,
  1839. KMMC: jh.KMMC,
  1840. SDKCGUIDs: []string{},
  1841. TESTSTGUIDs: []string{},
  1842. }
  1843. // 添加SDKC中的KCGUID
  1844. for _, sdkc := range jh.SDKC {
  1845. if sdkc.KCGUID != "" {
  1846. plan.SDKCGUIDs = append(plan.SDKCGUIDs, sdkc.KCGUID)
  1847. }
  1848. }
  1849. // 添加TESTST中的KCGUID
  1850. for _, testst := range jh.TESTST {
  1851. if testst.KCGUID != "" {
  1852. plan.TESTSTGUIDs = append(plan.TESTSTGUIDs, testst.KCGUID)
  1853. }
  1854. }
  1855. PlanDoInfo.PXInfo = append(PlanDoInfo.PXInfo, plan)
  1856. }
  1857. plans = append(plans, PlanDoInfo)
  1858. }
  1859. // 返回成功数据
  1860. c.Data["json"] = map[string]interface{}{
  1861. "code": 200,
  1862. "msg": "获取培训计划成功",
  1863. "data": plans,
  1864. }
  1865. c.ServeJSON()
  1866. }
  1867. // /course/tmsplanstudent 获取TMS课程计划参与的学生
  1868. func (c *CourseController) GetTMSCoursePlanStudent() {
  1869. // 获取请求参数
  1870. var req struct {
  1871. PXSSID string `json:"PXSSID"`
  1872. }
  1873. // if CurrentLoginMode == 1 {
  1874. // c.Ctx.Output.SetStatus(500)
  1875. // c.Data["json"] = map[string]interface{}{
  1876. // "code": 500,
  1877. // "msg": "本地模式不支持该功能 ",
  1878. // }
  1879. // c.ServeJSON()
  1880. // return
  1881. // }
  1882. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &req); err != nil {
  1883. c.Ctx.Output.SetStatus(400)
  1884. c.Data["json"] = map[string]interface{}{
  1885. "code": 400,
  1886. "msg": "请求参数格式错误: " + err.Error(),
  1887. }
  1888. c.ServeJSON()
  1889. return
  1890. }
  1891. if req.PXSSID == "" {
  1892. c.Ctx.Output.SetStatus(400)
  1893. c.Data["json"] = map[string]interface{}{
  1894. "code": 400,
  1895. "msg": "PXSSID不能为空",
  1896. }
  1897. c.ServeJSON()
  1898. return
  1899. }
  1900. // 调用信息化系统获取培训学生信息
  1901. trainingStudentResp, err := common.GetTrainingStudentFromInformationSystem(req.PXSSID)
  1902. if err != nil {
  1903. c.Ctx.Output.SetStatus(500)
  1904. c.Data["json"] = map[string]interface{}{
  1905. "code": 500,
  1906. "msg": "获取培训学生信息失败: " + err.Error(),
  1907. }
  1908. c.ServeJSON()
  1909. return
  1910. }
  1911. // 检查返回结果
  1912. if trainingStudentResp.ResultCode != "0" {
  1913. c.Ctx.Output.SetStatus(500)
  1914. c.Data["json"] = map[string]interface{}{
  1915. "code": 500,
  1916. "msg": "获取培训学生信息失败: " + trainingStudentResp.ResultDesc,
  1917. }
  1918. c.ServeJSON()
  1919. return
  1920. }
  1921. // 构造简化版的学生信息列表,只包含XYEMPID和XYXM
  1922. type SimpleStudentInfo struct {
  1923. XYEMPID string `json:"XYEMPID"`
  1924. XYXM string `json:"XYXM"`
  1925. }
  1926. simpleStudents := make([]SimpleStudentInfo, 0)
  1927. for _, student := range trainingStudentResp.Students {
  1928. simpleStudents = append(simpleStudents, SimpleStudentInfo{
  1929. XYEMPID: student.XYEMPID,
  1930. XYXM: student.XYXM,
  1931. })
  1932. }
  1933. // 返回成功数据
  1934. c.Data["json"] = map[string]interface{}{
  1935. "code": 200,
  1936. "msg": "获取培训学生信息成功",
  1937. "data": simpleStudents,
  1938. "count": trainingStudentResp.Count,
  1939. }
  1940. c.ServeJSON()
  1941. }