diff --git a/server/api/search_result.go b/server/api/search_result.go index ad2722f8b..164ea9e7f 100755 --- a/server/api/search_result.go +++ b/server/api/search_result.go @@ -176,7 +176,7 @@ func ExportSearchResult(c *gin.Context) { c.Header("Content-Disposition", `attachment; filename="search_results.csv"`) writer := csv.NewWriter(c.Writer) headers := []string{"Repo", "RepoUrl", "Matches", "Keyword", "SecKeyword", "Path", - "Url", "Status", "TextMatchesJson"} + "Url", "Status"} if err := writer.Write(headers); err != nil { response.FailWithMessage("导出失败", c) return @@ -198,7 +198,6 @@ func ExportSearchResult(c *gin.Context) { result.Path, result.Url, statusOptions[result.Status], - string(result.TextMatchesJson), } if err := writer.Write(row); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ diff --git a/server/source/casbin.go b/server/source/casbin.go index bfaa1cfa0..bddedaab2 100644 --- a/server/source/casbin.go +++ b/server/source/casbin.go @@ -124,6 +124,7 @@ var carbines = []gormadapter.CasbinRule{ {PType: "p", V0: "888", V1: "/searchResult/updateSearchResult", V2: "POST"}, {PType: "p", V0: "888", V1: "/searchResult/findSearchResult", V2: "GET"}, {PType: "p", V0: "888", V1: "/searchResult/getSearchResultList", V2: "GET"}, + {PType: "p", V0: "888", V1: "/searchResult/exportSearchResult", V2: "GET"}, {PType: "p", V0: "888", V1: "/searchResult/updateSearchResultStatusByIds", V2: "POST"}, {PType: "p", V0: "888", V1: "/searchResult/getTaskStatus", V2: "GET"}, {PType: "p", V0: "888", V1: "/subdomain/createSubdomain", V2: "POST"}, diff --git a/web/src/api/searchResult.js b/web/src/api/searchResult.js index 524c282d4..2c90b4064 100755 --- a/web/src/api/searchResult.js +++ b/web/src/api/searchResult.js @@ -1,13 +1,5 @@ import service from '@/utils/request' -// @Tags SearchResult -// @Summary 创建SearchResult -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body model.SearchResult true "创建SearchResult" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" -// @Router /searchResult/createSearchResult [post] export const createSearchResult = (data) => { return service({ url: "/searchResult/createSearchResult", @@ -16,15 +8,6 @@ export const createSearchResult = (data) => { }) } - -// @Tags SearchResult -// @Summary 删除SearchResult -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body model.SearchResult true "删除SearchResult" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}" -// @Router /searchResult/deleteSearchResult [delete] export const deleteSearchResult = (data) => { return service({ url: "/searchResult/deleteSearchResult", @@ -33,14 +16,6 @@ export const createSearchResult = (data) => { }) } -// @Tags SearchResult -// @Summary 删除SearchResult -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body request.IdsReq true "批量删除SearchResult" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}" -// @Router /searchResult/deleteSearchResult [delete] export const deleteSearchResultByIds = (data) => { return service({ url: "/searchResult/deleteSearchResultByIds", @@ -49,14 +24,6 @@ export const createSearchResult = (data) => { }) } -// @Tags SearchResult -// @Summary 更新SearchResult -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body model.SearchResult true "更新SearchResult" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}" -// @Router /searchResult/updateSearchResult [put] export const updateSearchResult = (data) => { return service({ url: "/searchResult/updateSearchResult", @@ -65,15 +32,6 @@ export const createSearchResult = (data) => { }) } - -// @Tags SearchResult -// @Summary 用id查询SearchResult -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body model.SearchResult true "用id查询SearchResult" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}" -// @Router /searchResult/findSearchResult [get] export const findSearchResult = (params) => { return service({ url: "/searchResult/findSearchResult", @@ -82,15 +40,6 @@ export const createSearchResult = (data) => { }) } - -// @Tags SearchResult -// @Summary 分页获取SearchResult列表 -// @Security ApiKeyAuth -// @accept application/json -// @Produce application/json -// @Param data body request.PageInfo true "分页获取SearchResult列表" -// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}" -// @Router /searchResult/getSearchResultList [get] export const getSearchResultList = (params) => { return service({ url: "/searchResult/getSearchResultList", @@ -99,6 +48,40 @@ export const createSearchResult = (data) => { }) } +export const exportSearchResult = async (params) => { + try { + const response = await service({ + url: '/searchResult/exportSearchResult', + method: 'get', + params, + responseType: 'blob', // Set response type to blob + headers: { + 'Accept': 'text/csv' + } + }); + const contentDisposition = response.headers?.['content-disposition'] || response.headers?.get('content-disposition'); + const filename = contentDisposition + ? contentDisposition.split('filename=')[1]?.replace(/"/g, '') + : 'export.csv'; + const blob = new Blob([response.data], { + type: 'text/csv;charset=utf-8;' + }); + const downloadUrl = window.URL.createObjectURL(blob); + + const link = document.createElement('a'); + link.href = downloadUrl; + link.download = filename; + document.body.appendChild(link); + link.click(); + + document.body.removeChild(link); + window.URL.revokeObjectURL(downloadUrl); + } catch (error) { + console.error('Export failed:', error); + throw error; // Propagate error to caller + } +}; + export const updateSearchResultStatusByIds = (data) => { return service({ url: '/searchResult/updateSearchResultStatusByIds', diff --git a/web/src/utils/request.js b/web/src/utils/request.js index 640985d64..62e179c8b 100644 --- a/web/src/utils/request.js +++ b/web/src/utils/request.js @@ -75,14 +75,17 @@ service.interceptors.response.use( router.push({name:"init"}) } } - if (response.data.code == 0 || response.headers.success === "true") { + if (response.data.code == 0 || response.headers.success === "true" ) { return response.data } else { - Message({ - showClose: true, - message: response.data.msg || decodeURI(response.headers.msg), - type: response.headers.msgtype||'error', - }) + if (response.headers['content-type'] !== 'text/csv') { + Message({ + showClose: true, + message: response.data.msg || decodeURI(response.headers.msg), + type: response.headers.msgtype||'error', + }) + } + if (response.data.data && response.data.data.reload) { store.commit('user/LoginOut') } diff --git a/web/src/view/searchResult/searchResult.vue b/web/src/view/searchResult/searchResult.vue index 455d3ca1f..128fdc782 100755 --- a/web/src/view/searchResult/searchResult.vue +++ b/web/src/view/searchResult/searchResult.vue @@ -27,6 +27,7 @@ 查询 + 导出 @@ -187,7 +188,7 @@ import { updateSearchResult, updateSearchResultStatusByIds, startFilterTask, - getTaskStatus + getTaskStatus, exportSearchResult } from "@/api/searchResult"; // 此处请自行替换地址 import { formatTimeToStr } from "@/utils/date"; import infoList from "@/mixins/infoList"; @@ -286,6 +287,9 @@ export default { this.pageSize = 100; this.getTableData(); }, + async exportResult() { + await exportSearchResult(this.formData); + }, secKeywordChange() { this.getTableData(); },