waflog.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <template>
  2. <div>
  3. <a-card>
  4. <div class="table-page-search-wrapper">
  5. <a-form layout="inline" @submit.prevent="handleSearch">
  6. <a-row :gutter="48">
  7. <a-col :md="6" :sm="24">
  8. <a-form-item label="请求IP">
  9. <a-input v-model:value="queryParam.requestIp" placeholder="请输入请求IP" />
  10. </a-form-item>
  11. </a-col>
  12. <a-col :md="6" :sm="24">
  13. <a-form-item label="用户ID">
  14. <a-input v-model:value="queryParam.uid" placeholder="请输入用户ID" />
  15. </a-form-item>
  16. </a-col>
  17. <a-col :md="6" :sm="24">
  18. <a-form-item label="规则ID">
  19. <a-input v-model:value="queryParam.ruleId" placeholder="请输入规则ID" />
  20. </a-form-item>
  21. </a-col>
  22. <a-col :md="6" :sm="24">
  23. <a-form-item label="实例ID">
  24. <a-input v-model:value="queryParam.hostId" placeholder="请输入实例ID" />
  25. </a-form-item>
  26. </a-col>
  27. <a-col :md="6" :sm="24">
  28. <a-form-item label="API">
  29. <a-input v-model:value="queryParam.api" placeholder="请输入API路径" />
  30. </a-form-item>
  31. </a-col>
  32. <a-col :md="6" :sm="24">
  33. <a-form-item label="API名称">
  34. <a-input v-model:value="queryParam.apiName" placeholder="请输入API名称" />
  35. </a-form-item>
  36. </a-col>
  37. <a-col :md="6" :sm="24">
  38. <a-form-item label="API类型">
  39. <a-select v-model:value="queryParam.apiType" placeholder="请选择API类型" allow-clear>
  40. <a-select-option value="get">get</a-select-option>
  41. <a-select-option value="add">add</a-select-option>
  42. <a-select-option value="delete">delete</a-select-option>
  43. <a-select-option value="edit">edit</a-select-option>
  44. </a-select>
  45. </a-form-item>
  46. </a-col>
  47. <a-col :md="6" :sm="24">
  48. <a-form-item label="名称">
  49. <a-input v-model:value="queryParam.name" placeholder="请输入名称" />
  50. </a-form-item>
  51. </a-col>
  52. <a-col :md="24" :sm="24">
  53. <span class="table-page-search-submitButtons">
  54. <a-button type="primary" @click="handleSearch">查询</a-button>
  55. <a-button style="margin-left: 8px" @click="resetSearch">重置</a-button>
  56. </span>
  57. </a-col>
  58. </a-row>
  59. </a-form>
  60. </div>
  61. <a-table
  62. :columns="columns"
  63. :row-key="record => record.id"
  64. :data-source="dataSource"
  65. :loading="loading"
  66. :pagination="pagination"
  67. @change="handleTableChange"
  68. :scroll="{ x: 'max-content' }"
  69. bordered
  70. size="middle"
  71. >
  72. <template #bodyCell="{ column, record }">
  73. <template v-if="column.dataIndex === 'action'">
  74. <a-button type="link" @click="goToInfo(record.id)">详情</a-button>
  75. </template>
  76. </template>
  77. </a-table>
  78. </a-card>
  79. <!-- WAF日志详情模态框 -->
  80. <waf-log-detail-modal ref="detailModalRef" />
  81. </div>
  82. </template>
  83. <script setup>
  84. import { ref, onMounted } from 'vue';
  85. import { getWafLogList } from '~/api/waf/waflog.js';
  86. import WafLogDetailModal from './components/waf-log-detail-modal.vue';
  87. const loading = ref(false);
  88. const dataSource = ref([]);
  89. const pagination = ref({
  90. current: 1,
  91. pageSize: 10,
  92. total: 0,
  93. showTotal: (total) => `共 ${total} 条`,
  94. showSizeChanger: true,
  95. pageSizeOptions: ['10', '20', '50', '100'],
  96. showQuickJumper: true,
  97. });
  98. const queryParam = ref({
  99. requestIp: '',
  100. uid: '',
  101. ruleId: '',
  102. hostId: '',
  103. api: '',
  104. apiName: '',
  105. apiType: '',
  106. name: '',
  107. });
  108. const columns = [
  109. { title: 'ID', dataIndex: 'id', fixed: 'left', width: 80 },
  110. { title: '用户ID', dataIndex: 'uid', width: 100 },
  111. { title: '名称', dataIndex: 'name', width: 150, ellipsis: true },
  112. { title: '请求IP', dataIndex: 'requestIp', width: 140 },
  113. { title: '实例ID', dataIndex: 'hostId', width: 100 },
  114. { title: '规则ID', dataIndex: 'ruleId', width: 100 },
  115. { title: 'User Agent', dataIndex: 'userAgent', width: 250, ellipsis: true },
  116. { title: 'API', dataIndex: 'api', width: 180, ellipsis: true },
  117. { title: 'API名称', dataIndex: 'apiName', width: 150, ellipsis: true },
  118. { title: 'API类型', dataIndex: 'apiType', width: 100 },
  119. { title: '创建时间', dataIndex: 'createdAt', width: 180 },
  120. { title: '更新时间', dataIndex: 'updatedAt', width: 180 },
  121. { title: '操作', dataIndex: 'action', fixed: 'right', width: 100 },
  122. ];
  123. const fetchData = () => {
  124. loading.value = true;
  125. // 构造请求参数,并处理特殊类型
  126. const params = {
  127. requestIp: queryParam.value.requestIp || '',
  128. uid: queryParam.value.uid ? parseInt(queryParam.value.uid) : '',
  129. ruleId: queryParam.value.ruleId ? parseInt(queryParam.value.ruleId) : '',
  130. hostId: queryParam.value.hostId ? parseInt(queryParam.value.hostId) : '',
  131. api: queryParam.value.api || '',
  132. apiName: queryParam.value.apiName || '',
  133. apiType: queryParam.value.apiType || '',
  134. name: queryParam.value.name || '',
  135. current: pagination.value.current,
  136. pageSize: pagination.value.pageSize,
  137. column: 'id',
  138. order: 'desc'
  139. };
  140. console.log('发送WAF日志查询参数:', params);
  141. getWafLogList(params).then(response => {
  142. // 根据实际返回格式处理数据
  143. if (response && response.code === 0 && response.data) {
  144. const apiData = response.data;
  145. if (apiData.records && Array.isArray(apiData.records)) {
  146. dataSource.value = apiData.records;
  147. pagination.value.total = apiData.total || 0;
  148. pagination.value.current = apiData.page || 1;
  149. pagination.value.pageSize = apiData.pageSize || 10;
  150. } else {
  151. dataSource.value = [];
  152. pagination.value.total = 0;
  153. console.warn('响应中无WAF日志数据记录');
  154. }
  155. } else {
  156. dataSource.value = [];
  157. pagination.value.total = 0;
  158. console.error('无效的WAF日志响应格式或响应错误', response);
  159. }
  160. loading.value = false;
  161. }).catch((error) => {
  162. console.error('WAF日志请求失败:', error);
  163. dataSource.value = [];
  164. loading.value = false;
  165. });
  166. };
  167. const handleTableChange = (pager) => {
  168. pagination.value.current = pager.current;
  169. pagination.value.pageSize = pager.pageSize;
  170. fetchData();
  171. };
  172. const handleSearch = () => {
  173. pagination.value.current = 1;
  174. fetchData();
  175. };
  176. const resetSearch = () => {
  177. queryParam.value.requestIp = '';
  178. queryParam.value.uid = '';
  179. queryParam.value.ruleId = '';
  180. queryParam.value.hostId = '';
  181. queryParam.value.api = '';
  182. queryParam.value.apiName = '';
  183. queryParam.value.apiType = '';
  184. queryParam.value.name = '';
  185. handleSearch();
  186. };
  187. const detailModalRef = ref(null);
  188. const goToInfo = (id) => {
  189. // 打开模态框而不是跳转页面
  190. detailModalRef.value?.open(id);
  191. };
  192. onMounted(() => {
  193. fetchData();
  194. });
  195. </script>
  196. <style scoped>
  197. .table-page-search-wrapper .ant-form-inline .ant-form-item {
  198. margin-bottom: 24px;
  199. }
  200. /* 表格样式优化 */
  201. :deep(.ant-table-body) {
  202. overflow-x: auto !important;
  203. }
  204. :deep(.ant-table-fixed-header .ant-table-scroll .ant-table-header) {
  205. margin-bottom: 0 !important;
  206. padding-bottom: 0 !important;
  207. overflow: hidden !important;
  208. }
  209. :deep(.ant-table-body::-webkit-scrollbar) {
  210. width: 8px;
  211. height: 8px;
  212. }
  213. :deep(.ant-table-body::-webkit-scrollbar-track) {
  214. background: #f1f1f1;
  215. border-radius: 4px;
  216. }
  217. :deep(.ant-table-body::-webkit-scrollbar-thumb) {
  218. background: #c1c1c1;
  219. border-radius: 4px;
  220. }
  221. :deep(.ant-table-body::-webkit-scrollbar-thumb:hover) {
  222. background: #a8a8a8;
  223. }
  224. </style>