total.go 12 KB

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