index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  4. <el-form-item label="系统模块" prop="title">
  5. <el-input
  6. maxlength="50"
  7. v-model="queryParams.title"
  8. placeholder="请输入系统模块"
  9. clearable
  10. style="width: 240px;"
  11. />
  12. </el-form-item>
  13. <el-form-item label="操作人员" prop="operName">
  14. <el-input
  15. maxlength="50"
  16. v-model="queryParams.operName"
  17. placeholder="请输入操作人员"
  18. clearable
  19. style="width: 240px;"
  20. />
  21. </el-form-item>
  22. <el-form-item label="审计类型" prop="auditType">
  23. <el-select
  24. v-model="queryParams.auditType"
  25. placeholder="请选择审计类型"
  26. clearable
  27. style="width: 240px"
  28. >
  29. <el-option
  30. v-for="dict in auditTypeOptions"
  31. :key="dict.value"
  32. :label="dict.label"
  33. :value="dict.value"
  34. />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item label="操作类型" prop="businessType">
  38. <el-select
  39. v-model="queryParams.businessType"
  40. placeholder="请选择操作类型"
  41. clearable
  42. style="width: 240px"
  43. >
  44. <el-option
  45. v-for="dict in operTypeOptions"
  46. :key="dict.value"
  47. :label="dict.label"
  48. :value="dict.value"
  49. />
  50. </el-select>
  51. </el-form-item>
  52. <el-form-item label="操作状态" prop="status">
  53. <el-select
  54. v-model="queryParams.status"
  55. placeholder="请选择操作状态"
  56. clearable
  57. style="width: 240px"
  58. >
  59. <el-option
  60. v-for="dict in statusOptions"
  61. :key="dict.value"
  62. :label="dict.label"
  63. :value="dict.value"
  64. />
  65. </el-select>
  66. </el-form-item>
  67. <el-form-item label="操作时间">
  68. <el-date-picker
  69. v-model="dateRange"
  70. style="width: 240px"
  71. value-format="yyyy-MM-dd"
  72. type="daterange"
  73. range-separator="-"
  74. start-placeholder="开始日期"
  75. end-placeholder="结束日期"
  76. ></el-date-picker>
  77. </el-form-item>
  78. <el-form-item>
  79. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  80. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  81. </el-form-item>
  82. </el-form>
  83. <el-row :gutter="10" class="mb8">
  84. <el-col :span="1.5">
  85. <el-button
  86. style="display:none"
  87. type="danger"
  88. plain
  89. icon="el-icon-delete"
  90. size="mini"
  91. @click="handleDelete"
  92. v-hasPermi="['auditManager:operlog:remove']"
  93. >删除
  94. </el-button>
  95. </el-col>
  96. <el-col :span="1.5">
  97. <el-button
  98. style="display:none"
  99. type="danger"
  100. plain
  101. icon="el-icon-delete"
  102. size="mini"
  103. @click="handleClean"
  104. v-hasPermi="['auditManager:operlog:remove']"
  105. >清空
  106. </el-button>
  107. </el-col>
  108. </el-row>
  109. <div style="padding-top: 10px">
  110. <vxe-table
  111. ref="tables"
  112. align="center"
  113. :loading="loading"
  114. class="mytable-style"
  115. auto-resize
  116. border
  117. resizable
  118. export-config
  119. highlight-current-row
  120. show-overflow
  121. max-height="700"
  122. :data="list"
  123. :radio-config="{trigger: 'row'}"
  124. @sort-change="sortChangeEvent"
  125. :sort-config="{remote:'true'}"
  126. >
  127. <!-- <vxe-column type="radio" width="60"/>-->
  128. <vxe-table-column field="operId" title="日志编号"/>
  129. <vxe-table-column field="title" title="系统模块" :sortable="true"/>
  130. <vxe-table-column field="auditType" title="审计类型" :formatter="auditTypeFormat"/>
  131. <vxe-table-column field="businessType" title="操作类型" :formatter="operTypeFormat"/>
  132. <vxe-table-column field="operName" title="操作人员" :sortable="true"/>
  133. <vxe-table-column field="operdesc" title="操作描述"/>
  134. <!-- <vxe-table-column field="operLocation" title="操作地点"/>-->
  135. <vxe-table-column field="status" title="操作状态" :formatter="statusFormat"/>
  136. <vxe-table-column field="operTime" title="操作日期" :sortable="true"/>
  137. <vxe-table-column field="costTime" title="消耗时间(毫秒)"/>
  138. <vxe-table-column title="操作">
  139. <template slot-scope="scope">
  140. <el-button
  141. size="mini"
  142. type="text"
  143. icon="el-icon-view"
  144. @click="handleView(scope.row,scope.index)"
  145. >详细
  146. </el-button>
  147. </template>
  148. </vxe-table-column>
  149. </vxe-table>
  150. <vxe-pager
  151. perfect
  152. :current-page.sync="currentPage"
  153. :page-size.sync="pageSize"
  154. :total="total"
  155. :page-sizes="[10,50,100]"
  156. :layouts="['PrevJump', 'PrevPage','JumpNumber', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total']"
  157. @page-change="handlePageChange"
  158. >
  159. </vxe-pager>
  160. </div>
  161. <!-- 操作日志详细 -->
  162. <el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>
  163. <el-form ref="form" :model="form" label-width="100px" size="mini">
  164. <el-row>
  165. <el-col :span="12">
  166. <el-form-item label="操作模块:">{{ form.title }}</el-form-item>
  167. <el-form-item
  168. label="登录信息:"
  169. >{{ form.operName }} / {{ form.operIp }}
  170. </el-form-item>
  171. </el-col>
  172. <el-col :span="12">
  173. <el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
  174. <el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
  175. </el-col>
  176. <el-col :span="24">
  177. <el-form-item label="操作方法:">{{ form.method }}</el-form-item>
  178. </el-col>
  179. <el-col :span="24">
  180. <el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
  181. </el-col>
  182. <!-- <el-col :span="24">-->
  183. <!-- <el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>-->
  184. <!-- </el-col>-->
  185. <el-col :span="6">
  186. <el-form-item label="操作状态:">
  187. <div v-if="form.status === 0">正常</div>
  188. <div v-else-if="form.status === 1">失败</div>
  189. </el-form-item>
  190. </el-col>
  191. <el-col :span="8">
  192. <el-form-item label="消耗时间:">{{ form.costTime }}毫秒</el-form-item>
  193. </el-col>
  194. <el-col :span="10">
  195. <el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
  196. </el-col>
  197. <el-col :span="24">
  198. <el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
  199. </el-col>
  200. </el-row>
  201. </el-form>
  202. <div slot="footer" class="dialog-footer">
  203. <el-button @click="open = false">关 闭</el-button>
  204. </div>
  205. </el-dialog>
  206. </div>
  207. </template>
  208. <script>
  209. import {debounce} from "lodash";
  210. export default {
  211. name: "Operlog",
  212. dicts: ['sys_oper_type', 'sys_common_status'],
  213. data() {
  214. return {
  215. showTable: true,
  216. currentPage: 1,
  217. pageSize: 10,
  218. operTypeOptions: [
  219. {value: '0', label: '查询'},
  220. {value: '1', label: '解锁'},
  221. {value: '2', label: '越权访问'},
  222. {value: '3', label: '其它'},
  223. {value: '4', label: '初始/重置密码'},
  224. {value: '5', label: '新增'},
  225. {value: '6', label: '修改'},
  226. {value: '7', label: '个人密码修改'},
  227. {value: '8', label: '删除'},
  228. {value: '9', label: '授权'},
  229. // {value: '10', label: '获取角色信息'},
  230. // {value: '11', label: '导出'},
  231. {value: '16', label: '连接超时'},
  232. {value: '17', label: 'IP异常'}
  233. ],
  234. ///** 审计类型(0=系统,1=业务) */
  235. auditTypeOptions: [
  236. // {value: '0', label: '系统'},
  237. // {value: '1', label: '业务'}
  238. ],
  239. statusOptions: [
  240. {value: '0', label: '成功'},
  241. {value: '1', label: '失败'}
  242. ],
  243. // 遮罩层
  244. loading: true,
  245. // 选中数组
  246. ids: [],
  247. // 非多个禁用
  248. multiple: true,
  249. // 显示搜索条件
  250. showSearch: true,
  251. // 总条数
  252. total: 0,
  253. // 表格数据
  254. list: [],
  255. // 是否显示弹出层
  256. open: false,
  257. sortOrder: 'operTime&desc',
  258. // 日期范围
  259. dateRange: [],
  260. // 默认排序
  261. defaultSort: {prop: 'operTime', order: 'descending'},
  262. // 表单参数
  263. form: {},
  264. // 查询参数
  265. queryParams: {
  266. title: undefined,
  267. operName: undefined,
  268. businessType: undefined,
  269. auditType: undefined,
  270. status: undefined
  271. }
  272. };
  273. },
  274. async created() {
  275. // 获取审计类型
  276. await this.$axios.get('/sysOperlogController/getAuditType').then((res) => {
  277. this.auditTypeOptions = res.data
  278. }).catch((error) => {
  279. })
  280. await this.getList();
  281. },
  282. methods: {
  283. sortChangeEvent({column, property, order}) {
  284. if (order == null) {
  285. order = 'desc'
  286. }
  287. this.currentPage = 1
  288. this.sortOrder = property+'&'+order
  289. this.getList()
  290. },
  291. handlePageChange({currentPage, pageSize}) {
  292. this.currentPage = currentPage
  293. this.pageSize = pageSize
  294. this.getList()
  295. },
  296. // 列表状态格式化
  297. statusFormat({cellValue}) {
  298. let belongTo = '未知的类型'
  299. for (let i = 0; i < this.statusOptions.length; i++) {
  300. if (cellValue == "0") {
  301. belongTo = "成功"
  302. } else if (cellValue == "1") {
  303. belongTo = "失败"
  304. }
  305. }
  306. return belongTo
  307. },
  308. // 列表状态格式化
  309. operTypeFormat({cellValue}) {
  310. let belongTo = '未知的类型'
  311. for (let i = 0; i < this.operTypeOptions.length; i++) {
  312. if (cellValue == "0") {
  313. belongTo = "查询"
  314. } else if (cellValue == "1") {
  315. belongTo = "解锁"
  316. } else if (cellValue == "2") {
  317. belongTo = "越权访问"
  318. } else if (cellValue == "3") {
  319. belongTo = "其它"
  320. } else if (cellValue == "4") {
  321. belongTo = "初始/重置密码"
  322. } else if (cellValue == "5") {
  323. belongTo = "新增"
  324. }else if (cellValue == "6") {
  325. belongTo = "修改"
  326. }else if (cellValue == "7") {
  327. belongTo = "个人密码修改"
  328. }else if (cellValue == "8") {
  329. belongTo = "删除"
  330. }else if (cellValue == "9") {
  331. belongTo = "授权"
  332. }
  333. // else if (cellValue == "10") {
  334. // belongTo = "获取角色信息"
  335. // }
  336. // else if (cellValue == "11") {
  337. // belongTo = "导出"
  338. // }
  339. else if (cellValue == "12") {
  340. belongTo = "导入"
  341. }else if (cellValue == "13") {
  342. belongTo = "强退"
  343. }else if (cellValue == "14") {
  344. belongTo = "生成代码"
  345. }else if (cellValue == "15") {
  346. belongTo = "清空数据"
  347. }else if (cellValue == "16") {
  348. belongTo = "连接超时"
  349. }else if (cellValue == "17") {
  350. belongTo = "IP异常"
  351. }
  352. }
  353. return belongTo
  354. },
  355. // 列表状态格式化
  356. auditTypeFormat({cellValue}) {
  357. let belongTo = '未知的类型'
  358. for (let i = 0; i < this.auditTypeOptions.length; i++) {
  359. if (cellValue == "0") {
  360. belongTo = "系统"
  361. } else if (cellValue == "1") {
  362. belongTo = "业务"
  363. }
  364. }
  365. return belongTo
  366. },
  367. /** 查询操作日志列表 */
  368. getList: debounce(async function () {
  369. this.loading = true;
  370. let _startOperTime;
  371. let _endOperTime;
  372. if (this.dateRange == null) {
  373. _startOperTime = ''
  374. _endOperTime = ''
  375. } else {
  376. _startOperTime = this.dateRange[0]
  377. _endOperTime = this.dateRange[1]
  378. }
  379. var searchParams = {
  380. currentPage: this.currentPage,
  381. pageSize: this.pageSize,
  382. title: this.queryParams.title,
  383. operName: this.queryParams.operName,
  384. businessType: this.queryParams.businessType,
  385. auditType: this.queryParams.auditType,
  386. status: this.queryParams.status,
  387. startOperTime: _startOperTime,
  388. endOperTime: _endOperTime,
  389. sortOrder: this.sortOrder,
  390. }
  391. await this.$axios.get('/sysOperlogController/getAll',
  392. {params: searchParams}).then((res) => {
  393. this.list = res.data.records
  394. this.total = res.data.total
  395. if (res.data.records == '') {
  396. this.showTable = false
  397. } else {
  398. this.showTable = true
  399. }
  400. this.loading = false
  401. }).catch((error) => {
  402. this.loading = false;
  403. // this.$message.error(error)
  404. })
  405. }, 1000),
  406. // 操作日志类型字典翻译
  407. typeFormat(row, column) {
  408. // return this.selectDictLabel(this.dict.type.sys_oper_type, row.businessType);
  409. return ''
  410. },
  411. /** 搜索按钮操作 */
  412. handleQuery() {
  413. this.currentPage = 1
  414. this.pageSize = 10
  415. this.getList();
  416. },
  417. /** 重置按钮操作 */
  418. resetQuery() {
  419. this.dateRange = [];
  420. this.resetForm("queryForm");
  421. },
  422. /** 多选框选中数据 */
  423. handleSelectionChange(selection) {
  424. this.ids = selection.map(item => item.operId)
  425. this.multiple = !selection.length
  426. },
  427. /** 排序触发事件 */
  428. handleSortChange(column, prop, order) {
  429. this.queryParams.orderByColumn = column.prop;
  430. this.queryParams.isAsc = column.order;
  431. this.getList();
  432. },
  433. /** 详细按钮操作 */
  434. handleView(row) {
  435. this.open = true;
  436. this.form = row;
  437. },
  438. /** 删除按钮操作 */
  439. handleDelete() {
  440. const _selectData = this.$refs.tables.getRadioRecord(true)
  441. if (_selectData == null) {
  442. this.$message({
  443. type: 'warning',
  444. message: '请选择记录!'
  445. });
  446. return
  447. }
  448. this.$confirm('是否确认删除操作日志?', '提示', {
  449. confirmButtonText: '确定',
  450. cancelButtonText: '取消',
  451. type: 'warning'
  452. }).then(() => {
  453. this.doDelete(_selectData)
  454. }).catch(() => {
  455. });
  456. },
  457. /**
  458. * 删除提交
  459. */
  460. doDelete: debounce(function (_selectData) {
  461. const param = {
  462. operId: _selectData.operId
  463. }
  464. this.$axios.post('/sysOperlogController/delOperlog', param).then((res) => {
  465. if (res.code == 0) {
  466. this.$message({
  467. type: 'success',
  468. message: '删除成功!'
  469. });
  470. this.getList();
  471. } else {
  472. this.$message({
  473. type: 'error',
  474. message: res.data
  475. });
  476. }
  477. }).catch((error) => {
  478. this.$message({
  479. type: 'error',
  480. message: '删除失败!'
  481. });
  482. this.loading = false
  483. })
  484. }, 1000),
  485. /** 清空按钮操作 */
  486. handleClean() {
  487. if (this.list == '') {
  488. this.$message({
  489. type: 'warning',
  490. message: '没有记录不能清空!'
  491. });
  492. return
  493. }
  494. this.$confirm('是否确认清空所有操作日志数据项?', '提示', {
  495. confirmButtonText: '确定',
  496. cancelButtonText: '取消',
  497. type: 'warning'
  498. }).then(() => {
  499. this.cleanOperLog();
  500. }).catch(() => {
  501. })
  502. },
  503. /**
  504. * 清空提交
  505. */
  506. cleanOperLog: debounce(function () {
  507. this.$axios.post('/sysOperlogController/cleanOperLog', {}).then((res) => {
  508. if (res.code == 0) {
  509. this.$message({
  510. type: 'success',
  511. message: '清空成功!'
  512. });
  513. this.getList();
  514. } else {
  515. this.$message({
  516. type: 'error',
  517. message: res.data
  518. });
  519. }
  520. }).catch((error) => {
  521. this.$message({
  522. type: 'error',
  523. message: '清空失败!'
  524. });
  525. this.loading = false
  526. })
  527. }, 1000)
  528. }
  529. };
  530. </script>