total.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. package controllers
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "math/rand"
  7. "net/http"
  8. "path/filepath"
  9. "shudao-chat-go/models"
  10. "shudao-chat-go/utils"
  11. "strings"
  12. "time"
  13. "github.com/beego/beego/v2/server/web"
  14. )
  15. type TotalController struct {
  16. web.Controller
  17. }
  18. // 随机返回5条推荐问题
  19. func (c *TotalController) GetRecommendQuestion() {
  20. //获取limit数量
  21. limit, _ := c.GetInt("limit")
  22. if limit == 0 {
  23. limit = 5
  24. }
  25. // 先获取总数
  26. var count int64
  27. models.DB.Model(&models.RecommendQuestion{}).Where("is_deleted = ?", 0).Count(&count)
  28. var result []map[string]interface{}
  29. if count == 0 {
  30. c.Data["json"] = map[string]interface{}{
  31. "statusCode": 200,
  32. "msg": "success",
  33. "data": result,
  34. }
  35. c.ServeJSON()
  36. return
  37. }
  38. // 生成随机偏移量,避免使用 ORDER BY rand()
  39. if int64(limit) >= count {
  40. // 数据量小于等于limit,直接查询全部
  41. models.DB.Model(&models.RecommendQuestion{}).
  42. Select("question").
  43. Where("is_deleted = ?", 0).
  44. Find(&result)
  45. } else {
  46. // 使用随机偏移量方式获取随机记录
  47. rand.Seed(time.Now().UnixNano())
  48. offset := rand.Intn(int(count) - limit + 1)
  49. models.DB.Model(&models.RecommendQuestion{}).
  50. Select("question").
  51. Where("is_deleted = ?", 0).
  52. Offset(offset).
  53. Limit(limit).
  54. Find(&result)
  55. }
  56. c.Data["json"] = map[string]interface{}{
  57. "statusCode": 200,
  58. "msg": "success",
  59. "data": result,
  60. }
  61. c.ServeJSON()
  62. }
  63. // 提交意见反馈
  64. func (c *TotalController) SubmitFeedback() {
  65. var feedback models.FeedbackQuestion
  66. // 尝试解析JSON数据
  67. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &feedback); err != nil {
  68. c.Data["json"] = map[string]interface{}{
  69. "statusCode": 400,
  70. "msg": "JSON解析失败: " + err.Error(),
  71. }
  72. c.ServeJSON()
  73. return
  74. }
  75. // 打印解析后的数据
  76. fmt.Println("解析后的数据:", feedback)
  77. tx := models.DB.Begin()
  78. if err := tx.Create(&feedback).Error; err != nil {
  79. tx.Rollback()
  80. c.Data["json"] = map[string]interface{}{
  81. "statusCode": 500,
  82. "msg": "fail",
  83. }
  84. c.ServeJSON()
  85. return
  86. }
  87. tx.Commit()
  88. c.Data["json"] = map[string]interface{}{
  89. "statusCode": 200,
  90. "msg": "success",
  91. }
  92. c.ServeJSON()
  93. }
  94. // 返回政策文件
  95. func (c *TotalController) GetPolicyFile() {
  96. policy_type, _ := c.GetInt("policy_type")
  97. search := c.GetString("search")
  98. page, _ := c.GetInt("page")
  99. pageSize, _ := c.GetInt("pageSize")
  100. var policyFile []models.PolicyFile
  101. offset := (page - 1) * pageSize
  102. if policy_type == 0 {
  103. models.DB.Model(&models.PolicyFile{}).Where("is_deleted = ? AND policy_name LIKE ?", 0, "%"+search+"%").Offset(offset).Limit(pageSize).Order("-updated_at").Find(&policyFile)
  104. } else {
  105. models.DB.Model(&models.PolicyFile{}).Where("is_deleted = ? AND policy_type = ? AND policy_name LIKE ?", 0, policy_type, "%"+search+"%").Offset(offset).Limit(pageSize).Order("-updated_at").Find(&policyFile)
  106. }
  107. // 将原始OSS URL转换为代理URL
  108. for i := range policyFile {
  109. if policyFile[i].PolicyFileUrl != "" {
  110. // 检查是否已经是代理URL格式
  111. if !strings.Contains(policyFile[i].PolicyFileUrl, "/apiv1/oss/parse/?url=") {
  112. policyFile[i].PolicyFileUrl = utils.GetProxyURL(policyFile[i].PolicyFileUrl)
  113. }
  114. }
  115. }
  116. c.Data["json"] = map[string]interface{}{
  117. "statusCode": 200,
  118. "msg": "success",
  119. "data": policyFile,
  120. }
  121. c.ServeJSON()
  122. }
  123. // 随机返回四条功能卡片
  124. func (c *TotalController) GetFunctionCard() {
  125. //问题类型,0为AI问答,1为安全培训
  126. functionType, _ := c.GetInt("function_type")
  127. limit := 4
  128. var count int64
  129. models.DB.Model(&models.FunctionCard{}).Where("function_type = ? AND is_deleted = ?", functionType, 0).Count(&count)
  130. var functionCard []models.FunctionCard
  131. if count == 0 {
  132. c.Data["json"] = map[string]interface{}{
  133. "statusCode": 200,
  134. "msg": "success",
  135. "data": functionCard,
  136. }
  137. c.ServeJSON()
  138. return
  139. }
  140. if int64(limit) >= count {
  141. models.DB.Model(&models.FunctionCard{}).Where("function_type = ? AND is_deleted = ?", functionType, 0).Find(&functionCard)
  142. } else {
  143. offset := rand.Intn(int(count) - limit + 1)
  144. models.DB.Model(&models.FunctionCard{}).Where("function_type = ? AND is_deleted = ?", functionType, 0).Offset(offset).Limit(limit).Find(&functionCard)
  145. }
  146. c.Data["json"] = map[string]interface{}{
  147. "statusCode": 200,
  148. "msg": "success",
  149. "data": functionCard,
  150. }
  151. c.ServeJSON()
  152. }
  153. // 随机返回四条热点问题
  154. func (c *TotalController) GetHotQuestion() {
  155. //问题类型,0为AI问答,1为安全培训
  156. questionType, _ := c.GetInt("question_type")
  157. limit := 4
  158. var count int64
  159. models.DB.Model(&models.HotQuestion{}).Where("question_type = ? AND is_deleted = ?", questionType, 0).Count(&count)
  160. var hotQuestion []models.HotQuestion
  161. if count == 0 {
  162. c.Data["json"] = map[string]interface{}{
  163. "statusCode": 200,
  164. "msg": "success",
  165. "data": hotQuestion,
  166. }
  167. c.ServeJSON()
  168. return
  169. }
  170. if int64(limit) >= count {
  171. models.DB.Model(&models.HotQuestion{}).Where("question_type = ? AND is_deleted = ?", questionType, 0).Find(&hotQuestion)
  172. } else {
  173. offset := rand.Intn(int(count) - limit + 1)
  174. models.DB.Model(&models.HotQuestion{}).Where("question_type = ? AND is_deleted = ?", questionType, 0).Offset(offset).Limit(limit).Find(&hotQuestion)
  175. }
  176. c.Data["json"] = map[string]interface{}{
  177. "statusCode": 200,
  178. "msg": "success",
  179. "data": hotQuestion,
  180. }
  181. c.ServeJSON()
  182. }
  183. type LikeAndDislikeRequest struct {
  184. ID uint `json:"id"`
  185. UserFeedback int `json:"user_feedback"`
  186. }
  187. // 点赞和踩
  188. func (c *TotalController) LikeAndDislike() {
  189. var likeAndDislike LikeAndDislikeRequest
  190. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &likeAndDislike); err != nil {
  191. c.Data["json"] = map[string]interface{}{
  192. "statusCode": 400,
  193. "msg": "JSON解析失败: " + err.Error(),
  194. }
  195. c.ServeJSON()
  196. return
  197. }
  198. id := likeAndDislike.ID
  199. userFeedback := likeAndDislike.UserFeedback
  200. models.DB.Model(&models.AIMessage{}).Where("id = ?", id).Update("user_feedback", userFeedback)
  201. c.Data["json"] = map[string]interface{}{
  202. "statusCode": 200,
  203. "msg": "success",
  204. }
  205. c.ServeJSON()
  206. }
  207. // 下载文件接口,支持从OSS链接下载文件并返回给前端
  208. func (c *TotalController) GetPdfOssDownloadLink() {
  209. pdfOssDownloadLink := c.GetString("pdf_oss_download_link")
  210. customFileName := c.GetString("file_name") // 支持自定义文件名
  211. // 验证URL是否为空
  212. if pdfOssDownloadLink == "" {
  213. c.Data["json"] = map[string]interface{}{
  214. "statusCode": 400,
  215. "msg": "下载链接不能为空",
  216. }
  217. c.ServeJSON()
  218. return
  219. }
  220. // 如果是代理URL格式,需要解密获取真实URL
  221. if strings.Contains(pdfOssDownloadLink, "/apiv1/oss/parse/?url=") {
  222. // 提取加密的URL参数
  223. parsedURL, err := url.Parse(pdfOssDownloadLink)
  224. if err == nil {
  225. encryptedURL := parsedURL.Query().Get("url")
  226. if encryptedURL != "" {
  227. // 解密URL
  228. realURL, err := utils.DecryptURL(encryptedURL)
  229. if err == nil && realURL != "" {
  230. pdfOssDownloadLink = realURL
  231. }
  232. }
  233. }
  234. }
  235. // 创建HTTP客户端,设置超时时间
  236. client := &http.Client{
  237. Timeout: 30 * time.Second,
  238. }
  239. // 发送GET请求下载文件
  240. resp, err := client.Get(pdfOssDownloadLink)
  241. if err != nil {
  242. c.Data["json"] = map[string]interface{}{
  243. "statusCode": 500,
  244. "msg": "下载文件失败: " + err.Error(),
  245. }
  246. c.ServeJSON()
  247. return
  248. }
  249. defer resp.Body.Close()
  250. // 检查HTTP状态码
  251. if resp.StatusCode != http.StatusOK {
  252. c.Data["json"] = map[string]interface{}{
  253. "statusCode": 500,
  254. "msg": "文件下载失败,状态码: " + fmt.Sprintf("%d", resp.StatusCode),
  255. }
  256. c.ServeJSON()
  257. return
  258. }
  259. // 从URL中提取文件名
  260. fileName := filepath.Base(pdfOssDownloadLink)
  261. if fileName == "." || fileName == "/" {
  262. fileName = "download_file_" + fmt.Sprintf("%d", time.Now().Unix())
  263. }
  264. // 如果提供了自定义文件名,使用自定义文件名
  265. if customFileName != "" {
  266. fileName = customFileName
  267. }
  268. // 从Content-Disposition头中获取文件名(如果存在)
  269. if contentDisposition := resp.Header.Get("Content-Disposition"); contentDisposition != "" {
  270. if strings.Contains(contentDisposition, "filename=") {
  271. parts := strings.Split(contentDisposition, "filename=")
  272. if len(parts) > 1 {
  273. fileName = strings.Trim(parts[1], "\"")
  274. }
  275. }
  276. }
  277. // 获取文件大小
  278. contentLength := resp.Header.Get("Content-Length")
  279. // 设置文件下载响应头
  280. c.Ctx.Output.Header("Content-Type", "application/octet-stream")
  281. c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName))
  282. if contentLength != "" {
  283. c.Ctx.Output.Header("Content-Length", contentLength)
  284. }
  285. c.Ctx.Output.Header("Cache-Control", "no-cache")
  286. // 将文件内容写入响应(流式传输)
  287. _, err = io.Copy(c.Ctx.ResponseWriter, resp.Body)
  288. if err != nil {
  289. c.Data["json"] = map[string]interface{}{
  290. "statusCode": 500,
  291. "msg": "文件传输失败: " + err.Error(),
  292. }
  293. c.ServeJSON()
  294. return
  295. }
  296. // 注意:文件下载成功后,响应已经通过io.Copy发送给客户端
  297. // 此时不能再调用c.ServeJSON(),因为响应已经完成
  298. }
  299. // 政策文件查看和下载查看次数+1
  300. func (c *TotalController) GetPolicyFileViewAndDownloadCount() {
  301. // 定义请求结构体
  302. type PolicyFileCountRequest struct {
  303. PolicyFileID int `json:"policy_file_id"`
  304. ActionType int `json:"action_type"`
  305. }
  306. var request PolicyFileCountRequest
  307. // 解析JSON请求体
  308. if err := json.Unmarshal(c.Ctx.Input.RequestBody, &request); err != nil {
  309. c.Data["json"] = map[string]interface{}{
  310. "statusCode": 400,
  311. "msg": "JSON解析失败: " + err.Error(),
  312. }
  313. c.ServeJSON()
  314. return
  315. }
  316. policyFileID := request.PolicyFileID
  317. actionType := request.ActionType
  318. fmt.Println("policyFileID", policyFileID)
  319. if policyFileID <= 0 {
  320. c.Data["json"] = map[string]interface{}{
  321. "statusCode": 400,
  322. "msg": "政策文件ID不能为空或无效",
  323. }
  324. c.ServeJSON()
  325. return
  326. }
  327. fmt.Println("actionType", actionType)
  328. if actionType != 1 && actionType != 2 {
  329. c.Data["json"] = map[string]interface{}{
  330. "statusCode": 400,
  331. "msg": "操作类型无效,1-查看,2-下载",
  332. }
  333. c.ServeJSON()
  334. return
  335. }
  336. // 检查政策文件是否存在
  337. var policyFile models.PolicyFile
  338. if err := models.DB.Where("id = ? AND is_deleted = ?", policyFileID, 0).First(&policyFile).Error; err != nil {
  339. c.Data["json"] = map[string]interface{}{
  340. "statusCode": 404,
  341. "msg": "政策文件不存在",
  342. }
  343. c.ServeJSON()
  344. return
  345. }
  346. // 更新查看次数
  347. if err := models.DB.Model(&models.PolicyFile{}).Where("id = ?", policyFileID).Update("view_count", policyFile.ViewCount+1).Error; err != nil {
  348. c.Data["json"] = map[string]interface{}{
  349. "statusCode": 500,
  350. "msg": "更新查看次数失败: " + err.Error(),
  351. }
  352. c.ServeJSON()
  353. return
  354. }
  355. // 返回成功响应
  356. var actionText string
  357. if actionType == 1 {
  358. actionText = "查看"
  359. } else {
  360. actionText = "下载"
  361. }
  362. c.Data["json"] = map[string]interface{}{
  363. "statusCode": 200,
  364. "msg": fmt.Sprintf("政策文件%s次数更新成功", actionText),
  365. "data": map[string]interface{}{
  366. "policy_file_id": policyFileID,
  367. "action_type": actionType,
  368. "action_text": actionText,
  369. "view_count": policyFile.ViewCount + 1,
  370. },
  371. }
  372. c.ServeJSON()
  373. }
  374. // GetUserDataID 从token中获取用户信息并返回用户数据
  375. func (c *TotalController) GetUserDataID() {
  376. // 从token中获取用户信息
  377. userInfo, err := utils.GetUserInfoFromContext(c.Ctx.Input.GetData("userInfo"))
  378. if err != nil {
  379. c.Data["json"] = map[string]interface{}{
  380. "statusCode": 401,
  381. "msg": "获取用户信息失败: " + err.Error(),
  382. }
  383. c.ServeJSON()
  384. return
  385. }
  386. accountID := userInfo.AccountID
  387. if accountID == "" {
  388. c.Data["json"] = map[string]interface{}{
  389. "statusCode": 400,
  390. "msg": "account_id不能为空",
  391. }
  392. c.ServeJSON()
  393. return
  394. }
  395. // 查询用户数据
  396. var userData models.UserData
  397. if err := models.DB.Where("accountID = ?", accountID).First(&userData).Error; err != nil {
  398. c.Data["json"] = map[string]interface{}{
  399. "statusCode": 404,
  400. "msg": "未找到对应的用户数据",
  401. }
  402. c.ServeJSON()
  403. return
  404. }
  405. // 返回主键id
  406. c.Data["json"] = map[string]interface{}{
  407. "statusCode": 200,
  408. "msg": "success",
  409. "data": map[string]interface{}{
  410. "id": userData.ID,
  411. },
  412. }
  413. c.ServeJSON()
  414. }