吉安感知网项目-前端
shuishen
2026-01-22 7985e2bf45f01550b3edc1a3052b1d5ac263e8c2
feat:系统操作日志,菜单级增加
5 files modified
2 files added
246 ■■■■ changed files
applications/drone-command/src/api/logs.js 7 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/page/index/sidebar/sidebarItem.vue 9 ●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/common/cockpit.scss 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/api.txt 63 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/operationLog/index.vue 145 ●●●●● patch | view | raw | blame | history
packages/apis/index.js 13 ●●●●● patch | view | raw | blame | history
packages/apis/system/index.js 7 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/api/logs.js
@@ -62,6 +62,13 @@
    },
  });
};
export const getOperationLogPage = params => {
  return request({
    url: '/blade-log/log/operationLog/page',
    method: 'get',
    params: { descs: 'create_time', ...params },
  });
};
// 历史轨迹记录
export const getHistoryTrack = (params) => {
  return request({
applications/drone-command/src/page/index/sidebar/sidebarItem.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2026-01-06 09:47:09
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-07 15:01:16
 * @LastEditTime : 2026-01-22 15:00:07
 * @FilePath     : \applications\drone-command\src\page\index\sidebar\sidebarItem.vue
 * @Description  : 
 * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -47,6 +47,7 @@
import { mapGetters } from 'vuex';
import { validatenull } from 'utils/validate';
import website from '@/config/website';
import {saveOperationLog} from '@ztzf/apis'
export default {
  name: 'sidebarItem',
@@ -89,6 +90,12 @@
      return item.meta.roles ? item.meta.roles.includes(this.roles) : true;
    },
    open(item) {
      saveOperationLog({
        requestUri: item[this.pathKey],
        title: item.name,
        type: 0
      })
      this.$router.push({
        path: item[this.pathKey],
        query: item[this.queryKey],
applications/drone-command/src/styles/common/cockpit.scss
@@ -350,7 +350,7 @@
                        td.in-range div:hover,
                        &.is-week-mode .el-date-table__row.current div,
                        &.is-week-mode .el-date-table__row:hover div {
                            background-color: #284FE3 !important;
                            background-color: #4160D5 !important;
                        }
                    }
                }
applications/drone-command/src/views/api.txt
@@ -1,33 +1,22 @@
## 信号干扰,诱导驱离
## 分页
**接口地址**:`/drone-fw/cockpit/dataCockpit/interferenceAndExpulsion`
**接口地址**:`/blade-log/log/operationLog/page`
**请求方式**:`POST`
**请求方式**:`GET`
**请求数据类型**:`application/json`
**请求数据类型**:`application/x-www-form-urlencoded`
**响应数据类型**:`*/*`
**接口描述**:<p>传入fwEffectEval</p>
**接口描述**:<p>分页</p>
**请求示例**:
```javascript
{
  "alarmRecordId": 0,
  "counterWay": ""
}
```
**请求参数**:
@@ -38,9 +27,12 @@
| 参数名称 | 参数说明 | 请求类型    | 是否必须 | 数据类型 | schema |
| -------- | -------- | ----- | -------- | -------- | ------ |
|fwEffectEvalParam|fwEffectEvalParam|body|true|FwEffectEvalParam|FwEffectEvalParam|
|&emsp;&emsp;alarmRecordId|告警记录ID(ja_fw_drone_alarm_record.id)||false|integer(int64)||
|&emsp;&emsp;counterWay|反制方式:1.信号干扰/2.诱导驱离/无||false|string||
|createBy|操作人|query|false|string||
|current|当前页|query|false|integer(int32)||
|endTime|结束时间|query|false|string||
|size|每页的数量|query|false|integer(int32)||
|startTime|开始时间|query|false|string||
|title|日志类型(0菜单/1按钮)|query|false|string||
**响应状态**:
@@ -48,8 +40,7 @@
| 状态码 | 说明 | schema |
| -------- | -------- | ----- | 
|200|OK|R|
|201|Created||
|200|OK|R«IPage«OperationLogVO»»|
|401|Unauthorized||
|403|Forbidden||
|404|Not Found||
@@ -61,7 +52,18 @@
| 参数名称 | 参数说明 | 类型 | schema |
| -------- | -------- | ----- |----- | 
|code|状态码|integer(int32)|integer(int32)|
|data|承载数据|object||
|data|承载数据|IPage«OperationLogVO»|IPage«OperationLogVO»|
|&emsp;&emsp;current||integer(int64)||
|&emsp;&emsp;pages||integer(int64)||
|&emsp;&emsp;records||array|OperationLogVO|
|&emsp;&emsp;&emsp;&emsp;createBy|操作人|string||
|&emsp;&emsp;&emsp;&emsp;remoteIp|客户端IP|string||
|&emsp;&emsp;&emsp;&emsp;requestUri|请求地址|string||
|&emsp;&emsp;&emsp;&emsp;title|日志标题|string||
|&emsp;&emsp;&emsp;&emsp;type|日志类型(0菜单/1按钮)|string||
|&emsp;&emsp;&emsp;&emsp;userAgent|客户端|string||
|&emsp;&emsp;size||integer(int64)||
|&emsp;&emsp;total||integer(int64)||
|msg|返回消息|string||
|success|是否成功|boolean||
@@ -70,7 +72,22 @@
```javascript
{
    "code": 0,
    "data": {},
    "data": {
        "current": 0,
        "pages": 0,
        "records": [
            {
                "createBy": "",
                "remoteIp": "",
                "requestUri": "",
                "title": "",
                "type": "",
                "userAgent": ""
            }
        ],
        "size": 0,
        "total": 0
    },
    "msg": "",
    "success": true
}
applications/drone-command/src/views/permissionManage/operationLog/index.vue
New file
@@ -0,0 +1,145 @@
<template>
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="操作名称" prop="title">
                <el-input
                    class="command-input"
                    v-model="searchParams.title"
                    placeholder="请输入"
                    clearable
                    @clear="handleSearch"
                />
            </el-form-item>
            <el-form-item label="操作人" prop="createBy">
                <el-input
                    class="command-input"
                    v-model="searchParams.createBy"
                    placeholder="请输入"
                    clearable
                    @clear="handleSearch"
                />
            </el-form-item>
            <el-form-item label="操作类型" prop="type">
                <el-select
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.type"
                    placeholder="请选择"
                    clearable
                    @change="handleSearch"
                >
                    <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
                </el-select>
            </el-form-item>
            <el-form-item label="操作时间">
                <el-date-picker
                    popper-class="command-date-picker-popper"
                    class="command-date-picker"
                    v-model="dateRange"
                    type="daterange"
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    value-format="YYYY-MM-DD HH:mm:ss"
                    @change="handleSearch"
                />
            </el-form-item>
            <el-form-item class="history-search-actions">
                <el-button :icon="RefreshRight" @click="resetForm"></el-button>
                <el-button class="search-btn" :icon="Search" @click="handleSearch"></el-button>
            </el-form-item>
        </el-form>
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="title" show-overflow-tooltip label="操作名称" />
                    <el-table-column prop="createBy" show-overflow-tooltip label="操作人" />
                    <el-table-column prop="type" show-overflow-tooltip label="操作类型">
                        <template v-slot="{ row }">
                            {{ getTypeLabel(row.type) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="remoteIp" show-overflow-tooltip label="客户端IP" />
                    <el-table-column prop="requestUri" show-overflow-tooltip label="请求地址" />
                    <el-table-column prop="userAgent" show-overflow-tooltip label="客户端信息" />
                </el-table>
            </div>
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
                    :total="total"
                    @change="getList"
                />
            </div>
        </div>
    </basic-container>
</template>
<script setup>
import { Search, RefreshRight } from '@element-plus/icons-vue'
import { onMounted, ref } from 'vue'
import { dateRangeFormat } from '@ztzf/utils'
import { getOperationLogPage } from '@/api/logs'
const initSearchParams = () => ({
    title: '',
    createBy: '',
    type: '',
    current: 1,
    size: 10,
})
const searchParams = ref(initSearchParams())
const total = ref(0)
const loading = ref(true)
const list = ref([])
const dateRange = ref([])
const queryParamsRef = ref(null)
const typeOptions = [
    { label: '菜单', value: '1' },
    { label: '按钮', value: '2' },
]
async function getList() {
    const range = dateRangeFormat(dateRange.value)
    loading.value = true
    try {
        const params = { ...searchParams.value, startTime: range[0], endTime: range[1] }
        const res = await getOperationLogPage(params)
        list.value = res?.data?.data?.records ?? []
        total.value = res?.data?.data?.total ?? 0
    } finally {
        loading.value = false
    }
}
function handleSearch() {
    searchParams.value.current = 1
    getList()
}
function resetForm() {
    dateRange.value = []
    queryParamsRef.value?.resetFields()
    searchParams.value.current = 1
    getList()
}
function getTypeLabel(value) {
    const key = value === null || value === undefined ? '' : String(value)
    const match = typeOptions.find(item => item.value === key)
    return match?.label || value || '-'
}
onMounted(() => {
    getList()
})
</script>
<style scoped lang="scss"></style>
packages/apis/index.js
@@ -1 +1,12 @@
export * from './job';
/*
 * @Author       : yuan
 * @Date         : 2026-01-07 11:04:47
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-22 14:50:34
 * @FilePath     : \packages\apis\index.js
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-07 11:04:47
 */
export * from './job'
export * from './system'
packages/apis/system/index.js
New file
@@ -0,0 +1,7 @@
export const saveOperationLog = (data) => {
    return window._request({
        url: `/blade-log/log/operationLog/save`,
        method: 'post',
        data,
    })
}