2
0

sys_export_template.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. package system
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "sync"
  7. "time"
  8. "github.com/flipped-aurora/gin-vue-admin/server/global"
  9. "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
  10. "github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
  11. "github.com/flipped-aurora/gin-vue-admin/server/model/system"
  12. systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
  13. "github.com/flipped-aurora/gin-vue-admin/server/service"
  14. "github.com/flipped-aurora/gin-vue-admin/server/utils"
  15. "github.com/gin-gonic/gin"
  16. "go.uber.org/zap"
  17. )
  18. // 用于token一次性存储
  19. var (
  20. exportTokenCache = make(map[string]interface{})
  21. exportTokenExpiration = make(map[string]time.Time)
  22. tokenMutex sync.RWMutex
  23. )
  24. // 五分钟检测窗口过期
  25. func cleanupExpiredTokens() {
  26. for {
  27. time.Sleep(5 * time.Minute)
  28. tokenMutex.Lock()
  29. now := time.Now()
  30. for token, expiry := range exportTokenExpiration {
  31. if now.After(expiry) {
  32. delete(exportTokenCache, token)
  33. delete(exportTokenExpiration, token)
  34. }
  35. }
  36. tokenMutex.Unlock()
  37. }
  38. }
  39. func init() {
  40. go cleanupExpiredTokens()
  41. }
  42. type SysExportTemplateApi struct {
  43. }
  44. var sysExportTemplateService = service.ServiceGroupApp.SystemServiceGroup.SysExportTemplateService
  45. // CreateSysExportTemplate 创建导出模板
  46. // @Tags SysExportTemplate
  47. // @Summary 创建导出模板
  48. // @Security ApiKeyAuth
  49. // @accept application/json
  50. // @Produce application/json
  51. // @Param data body system.SysExportTemplate true "创建导出模板"
  52. // @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
  53. // @Router /sysExportTemplate/createSysExportTemplate [post]
  54. func (sysExportTemplateApi *SysExportTemplateApi) CreateSysExportTemplate(c *gin.Context) {
  55. var sysExportTemplate system.SysExportTemplate
  56. err := c.ShouldBindJSON(&sysExportTemplate)
  57. if err != nil {
  58. response.FailWithMessage(err.Error(), c)
  59. return
  60. }
  61. verify := utils.Rules{
  62. "Name": {utils.NotEmpty()},
  63. }
  64. if err := utils.Verify(sysExportTemplate, verify); err != nil {
  65. response.FailWithMessage(err.Error(), c)
  66. return
  67. }
  68. if err := sysExportTemplateService.CreateSysExportTemplate(&sysExportTemplate); err != nil {
  69. global.GVA_LOG.Error("创建失败!", zap.Error(err))
  70. response.FailWithMessage("创建失败", c)
  71. } else {
  72. response.OkWithMessage("创建成功", c)
  73. }
  74. }
  75. // DeleteSysExportTemplate 删除导出模板
  76. // @Tags SysExportTemplate
  77. // @Summary 删除导出模板
  78. // @Security ApiKeyAuth
  79. // @accept application/json
  80. // @Produce application/json
  81. // @Param data body system.SysExportTemplate true "删除导出模板"
  82. // @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
  83. // @Router /sysExportTemplate/deleteSysExportTemplate [delete]
  84. func (sysExportTemplateApi *SysExportTemplateApi) DeleteSysExportTemplate(c *gin.Context) {
  85. var sysExportTemplate system.SysExportTemplate
  86. err := c.ShouldBindJSON(&sysExportTemplate)
  87. if err != nil {
  88. response.FailWithMessage(err.Error(), c)
  89. return
  90. }
  91. if err := sysExportTemplateService.DeleteSysExportTemplate(sysExportTemplate); err != nil {
  92. global.GVA_LOG.Error("删除失败!", zap.Error(err))
  93. response.FailWithMessage("删除失败", c)
  94. } else {
  95. response.OkWithMessage("删除成功", c)
  96. }
  97. }
  98. // DeleteSysExportTemplateByIds 批量删除导出模板
  99. // @Tags SysExportTemplate
  100. // @Summary 批量删除导出模板
  101. // @Security ApiKeyAuth
  102. // @accept application/json
  103. // @Produce application/json
  104. // @Param data body request.IdsReq true "批量删除导出模板"
  105. // @Success 200 {string} string "{"success":true,"data":{},"msg":"批量删除成功"}"
  106. // @Router /sysExportTemplate/deleteSysExportTemplateByIds [delete]
  107. func (sysExportTemplateApi *SysExportTemplateApi) DeleteSysExportTemplateByIds(c *gin.Context) {
  108. var IDS request.IdsReq
  109. err := c.ShouldBindJSON(&IDS)
  110. if err != nil {
  111. response.FailWithMessage(err.Error(), c)
  112. return
  113. }
  114. if err := sysExportTemplateService.DeleteSysExportTemplateByIds(IDS); err != nil {
  115. global.GVA_LOG.Error("批量删除失败!", zap.Error(err))
  116. response.FailWithMessage("批量删除失败", c)
  117. } else {
  118. response.OkWithMessage("批量删除成功", c)
  119. }
  120. }
  121. // UpdateSysExportTemplate 更新导出模板
  122. // @Tags SysExportTemplate
  123. // @Summary 更新导出模板
  124. // @Security ApiKeyAuth
  125. // @accept application/json
  126. // @Produce application/json
  127. // @Param data body system.SysExportTemplate true "更新导出模板"
  128. // @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
  129. // @Router /sysExportTemplate/updateSysExportTemplate [put]
  130. func (sysExportTemplateApi *SysExportTemplateApi) UpdateSysExportTemplate(c *gin.Context) {
  131. var sysExportTemplate system.SysExportTemplate
  132. err := c.ShouldBindJSON(&sysExportTemplate)
  133. if err != nil {
  134. response.FailWithMessage(err.Error(), c)
  135. return
  136. }
  137. verify := utils.Rules{
  138. "Name": {utils.NotEmpty()},
  139. }
  140. if err := utils.Verify(sysExportTemplate, verify); err != nil {
  141. response.FailWithMessage(err.Error(), c)
  142. return
  143. }
  144. if err := sysExportTemplateService.UpdateSysExportTemplate(sysExportTemplate); err != nil {
  145. global.GVA_LOG.Error("更新失败!", zap.Error(err))
  146. response.FailWithMessage("更新失败", c)
  147. } else {
  148. response.OkWithMessage("更新成功", c)
  149. }
  150. }
  151. // FindSysExportTemplate 用id查询导出模板
  152. // @Tags SysExportTemplate
  153. // @Summary 用id查询导出模板
  154. // @Security ApiKeyAuth
  155. // @accept application/json
  156. // @Produce application/json
  157. // @Param data query system.SysExportTemplate true "用id查询导出模板"
  158. // @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
  159. // @Router /sysExportTemplate/findSysExportTemplate [get]
  160. func (sysExportTemplateApi *SysExportTemplateApi) FindSysExportTemplate(c *gin.Context) {
  161. var sysExportTemplate system.SysExportTemplate
  162. err := c.ShouldBindQuery(&sysExportTemplate)
  163. if err != nil {
  164. response.FailWithMessage(err.Error(), c)
  165. return
  166. }
  167. if resysExportTemplate, err := sysExportTemplateService.GetSysExportTemplate(sysExportTemplate.ID); err != nil {
  168. global.GVA_LOG.Error("查询失败!", zap.Error(err))
  169. response.FailWithMessage("查询失败", c)
  170. } else {
  171. response.OkWithData(gin.H{"resysExportTemplate": resysExportTemplate}, c)
  172. }
  173. }
  174. // GetSysExportTemplateList 分页获取导出模板列表
  175. // @Tags SysExportTemplate
  176. // @Summary 分页获取导出模板列表
  177. // @Security ApiKeyAuth
  178. // @accept application/json
  179. // @Produce application/json
  180. // @Param data query systemReq.SysExportTemplateSearch true "分页获取导出模板列表"
  181. // @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
  182. // @Router /sysExportTemplate/getSysExportTemplateList [get]
  183. func (sysExportTemplateApi *SysExportTemplateApi) GetSysExportTemplateList(c *gin.Context) {
  184. var pageInfo systemReq.SysExportTemplateSearch
  185. err := c.ShouldBindQuery(&pageInfo)
  186. if err != nil {
  187. response.FailWithMessage(err.Error(), c)
  188. return
  189. }
  190. if list, total, err := sysExportTemplateService.GetSysExportTemplateInfoList(pageInfo); err != nil {
  191. global.GVA_LOG.Error("获取失败!", zap.Error(err))
  192. response.FailWithMessage("获取失败", c)
  193. } else {
  194. response.OkWithDetailed(response.PageResult{
  195. List: list,
  196. Total: total,
  197. Page: pageInfo.Page,
  198. PageSize: pageInfo.PageSize,
  199. }, "获取成功", c)
  200. }
  201. }
  202. // ExportExcel 导出表格token
  203. // @Tags SysExportTemplate
  204. // @Summary 导出表格
  205. // @Security ApiKeyAuth
  206. // @accept application/json
  207. // @Produce application/json
  208. // @Router /sysExportTemplate/exportExcel [get]
  209. func (sysExportTemplateApi *SysExportTemplateApi) ExportExcel(c *gin.Context) {
  210. templateID := c.Query("templateID")
  211. if templateID == "" {
  212. response.FailWithMessage("模板ID不能为空", c)
  213. return
  214. }
  215. queryParams := c.Request.URL.Query()
  216. //创造一次性token
  217. token := utils.RandomString(32) // 随机32位
  218. // 记录本次请求参数
  219. exportParams := map[string]interface{}{
  220. "templateID": templateID,
  221. "queryParams": queryParams,
  222. }
  223. // 参数保留记录完成鉴权
  224. tokenMutex.Lock()
  225. exportTokenCache[token] = exportParams
  226. exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
  227. tokenMutex.Unlock()
  228. // 生成一次性链接
  229. exportUrl := fmt.Sprintf("/sysExportTemplate/exportExcelByToken?token=%s", token)
  230. response.OkWithData(exportUrl, c)
  231. }
  232. // ExportExcelByToken 导出表格
  233. // @Tags ExportExcelByToken
  234. // @Summary 导出表格
  235. // @Security ApiKeyAuth
  236. // @accept application/json
  237. // @Produce application/json
  238. // @Router /sysExportTemplate/exportExcelByToken [get]
  239. func (sysExportTemplateApi *SysExportTemplateApi) ExportExcelByToken(c *gin.Context) {
  240. token := c.Query("token")
  241. if token == "" {
  242. response.FailWithMessage("导出token不能为空", c)
  243. return
  244. }
  245. // 获取token并且从缓存中剔除
  246. tokenMutex.RLock()
  247. exportParamsRaw, exists := exportTokenCache[token]
  248. expiry, _ := exportTokenExpiration[token]
  249. tokenMutex.RUnlock()
  250. if !exists || time.Now().After(expiry) {
  251. global.GVA_LOG.Error("导出token无效或已过期!")
  252. response.FailWithMessage("导出token无效或已过期", c)
  253. return
  254. }
  255. // 从token获取参数
  256. exportParams, ok := exportParamsRaw.(map[string]interface{})
  257. if !ok {
  258. global.GVA_LOG.Error("解析导出参数失败!")
  259. response.FailWithMessage("解析导出参数失败", c)
  260. return
  261. }
  262. // 获取导出参数
  263. templateID := exportParams["templateID"].(string)
  264. queryParams := exportParams["queryParams"].(url.Values)
  265. // 清理一次性token
  266. tokenMutex.Lock()
  267. delete(exportTokenCache, token)
  268. delete(exportTokenExpiration, token)
  269. tokenMutex.Unlock()
  270. // 导出
  271. if file, name, err := sysExportTemplateService.ExportExcel(templateID, queryParams); err != nil {
  272. global.GVA_LOG.Error("获取失败!", zap.Error(err))
  273. response.FailWithMessage("获取失败", c)
  274. } else {
  275. c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+utils.RandomString(6)+".xlsx"))
  276. c.Header("success", "true")
  277. c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", file.Bytes())
  278. }
  279. }
  280. // ExportTemplate 导出表格模板
  281. // @Tags SysExportTemplate
  282. // @Summary 导出表格模板
  283. // @Security ApiKeyAuth
  284. // @accept application/json
  285. // @Produce application/json
  286. // @Router /sysExportTemplate/exportTemplate [get]
  287. func (sysExportTemplateApi *SysExportTemplateApi) ExportTemplate(c *gin.Context) {
  288. templateID := c.Query("templateID")
  289. if templateID == "" {
  290. response.FailWithMessage("模板ID不能为空", c)
  291. return
  292. }
  293. // 创造一次性token
  294. token := utils.RandomString(32) // 随机32位
  295. // 记录本次请求参数
  296. exportParams := map[string]interface{}{
  297. "templateID": templateID,
  298. "isTemplate": true,
  299. }
  300. // 参数保留记录完成鉴权
  301. tokenMutex.Lock()
  302. exportTokenCache[token] = exportParams
  303. exportTokenExpiration[token] = time.Now().Add(30 * time.Minute)
  304. tokenMutex.Unlock()
  305. // 生成一次性链接
  306. exportUrl := fmt.Sprintf("/sysExportTemplate/exportTemplateByToken?token=%s", token)
  307. response.OkWithData(exportUrl, c)
  308. }
  309. // ExportTemplateByToken 通过token导出表格模板
  310. // @Tags ExportTemplateByToken
  311. // @Summary 通过token导出表格模板
  312. // @Security ApiKeyAuth
  313. // @accept application/json
  314. // @Produce application/json
  315. // @Router /sysExportTemplate/exportTemplateByToken [get]
  316. func (sysExportTemplateApi *SysExportTemplateApi) ExportTemplateByToken(c *gin.Context) {
  317. token := c.Query("token")
  318. if token == "" {
  319. response.FailWithMessage("导出token不能为空", c)
  320. return
  321. }
  322. // 获取token并且从缓存中剔除
  323. tokenMutex.RLock()
  324. exportParamsRaw, exists := exportTokenCache[token]
  325. expiry, _ := exportTokenExpiration[token]
  326. tokenMutex.RUnlock()
  327. if !exists || time.Now().After(expiry) {
  328. global.GVA_LOG.Error("导出token无效或已过期!")
  329. response.FailWithMessage("导出token无效或已过期", c)
  330. return
  331. }
  332. // 从token获取参数
  333. exportParams, ok := exportParamsRaw.(map[string]interface{})
  334. if !ok {
  335. global.GVA_LOG.Error("解析导出参数失败!")
  336. response.FailWithMessage("解析导出参数失败", c)
  337. return
  338. }
  339. // 检查是否为模板导出
  340. isTemplate, _ := exportParams["isTemplate"].(bool)
  341. if !isTemplate {
  342. global.GVA_LOG.Error("token类型错误!")
  343. response.FailWithMessage("token类型错误", c)
  344. return
  345. }
  346. // 获取导出参数
  347. templateID := exportParams["templateID"].(string)
  348. // 清理一次性token
  349. tokenMutex.Lock()
  350. delete(exportTokenCache, token)
  351. delete(exportTokenExpiration, token)
  352. tokenMutex.Unlock()
  353. // 导出模板
  354. if file, name, err := sysExportTemplateService.ExportTemplate(templateID); err != nil {
  355. global.GVA_LOG.Error("获取失败!", zap.Error(err))
  356. response.FailWithMessage("获取失败", c)
  357. } else {
  358. c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", name+"模板.xlsx"))
  359. c.Header("success", "true")
  360. c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", file.Bytes())
  361. }
  362. }
  363. // ImportExcel 导入表格
  364. // @Tags SysImportTemplate
  365. // @Summary 导入表格
  366. // @Security ApiKeyAuth
  367. // @accept application/json
  368. // @Produce application/json
  369. // @Router /sysExportTemplate/importExcel [post]
  370. func (sysExportTemplateApi *SysExportTemplateApi) ImportExcel(c *gin.Context) {
  371. templateID := c.Query("templateID")
  372. if templateID == "" {
  373. response.FailWithMessage("模板ID不能为空", c)
  374. return
  375. }
  376. file, err := c.FormFile("file")
  377. if err != nil {
  378. global.GVA_LOG.Error("文件获取失败!", zap.Error(err))
  379. response.FailWithMessage("文件获取失败", c)
  380. return
  381. }
  382. if err := sysExportTemplateService.ImportExcel(templateID, file); err != nil {
  383. global.GVA_LOG.Error(err.Error(), zap.Error(err))
  384. response.FailWithMessage(err.Error(), c)
  385. } else {
  386. response.OkWithMessage("导入成功", c)
  387. }
  388. }