Commit 4af6d4ad by 李君

日志

1 parent c710516d
......@@ -45,6 +45,10 @@ const menuRoute = [
path: 'MinutePassenger',
component: () => import("@/views/MinutePassenger/MinutePassenger.vue"),
},
{
path: 'SystemLog',
component: () => import("@/views/SystemLog/index.vue"),
},
]
},
]
......
<template>
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '100px' } }">
<a-form-item label="集团:" style="padding: 5px 0">
<a-select v-model:value="queryForm.account_id"
style="width: 280px"
mode="multiple"
:maxTagCount="1"
@change="onAccountChange"
:options="accountList"
optionFilterProp="label"
show-search
>
</a-select>
</a-form-item>
<a-form-item label="广场:" style="padding: 5px 0">
<a-select v-model:value="queryForm.plaza_id"
style="width: 280px"
mode="multiple"
:maxTagCount="1"
@change="onPlazaChange"
:options="plazaList"
optionFilterProp="label"
show-search
>
</a-select>
</a-form-item>
<a-form-item label="监控点名称:" style="padding: 5px 0">
<a-select v-model:value="queryForm.gate_id"
style="width: 280px"
mode="multiple"
:maxTagCount="1"
@change="onGateChange"
:options="gateList"
optionFilterProp="label"
show-search
>
<template #dropdownRender="{ menuNode: menu }">
<v-nodes :vnodes="menu"/>
<a-divider style="margin: 4px 0"/>
<div
@mousedown="e => e.preventDefault()"
>
<a-button @click="selectAll('监控点名称')" type="link">全选</a-button>
<a-button @click="clearAll('监控点名称')" type="link">清空</a-button>
</div>
</template>
</a-select>
</a-form-item>
<a-form-item label="设备通道号:" style="padding: 5px 0">
<a-select v-model:value="queryForm.channel_id"
style="width: 280px"
mode="multiple"
:maxTagCount="1"
:options="channelList"
optionFilterProp="label"
show-search
>
<template #dropdownRender="{ menuNode: menu }">
<v-nodes :vnodes="menu"/>
<a-divider style="margin: 4px 0"/>
<div
@mousedown="e => e.preventDefault()"
>
<a-button @click="selectAll('设备通道号')" type="link">全选</a-button>
<a-button @click="clearAll('设备通道号')" type="link">清空</a-button>
</div>
</template>
</a-select>
</a-form-item>
<a-form-item label="修补日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.repairDate" style="width: 280px"/>
</a-form-item>
<a-form-item label="参考日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.referenceDate" style="width: 280px"/>
</a-form-item>
<a-form-item label="开始时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.startTime" style="width: 280px"/>
</a-form-item>
<a-form-item label="结束时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.endTime" style="width: 280px"/>
</a-form-item>
<a-form-item label="数据波动比例:" style="padding: 5px 0">
<a-input v-model:value="queryForm.minFactor" style="width: 129px"/>
<a-input v-model:value="queryForm.maxFactor" style="width: 129px"/>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="preview" :loading="isLoading">预览</a-button>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="repair" :loading="isLoading">修补</a-button>
</a-form-item>
</a-form>
<div style="display:flex; justify-content: flex-end;padding: 3px">
<a-button @click="suspendRepair" type="primary">暂停修复</a-button>
</div>
<a-table :dataSource="dataList" v-loading="isLoading" :columns="columns" :pagination="false">
<template #status="{ text }">
<span :class="getClass(text)">{{ text }}</span>
</template>
<template #operation="{ record }">
<div>
<a-button @click="deleteRecord(record)" type="primary" danger>删除任务</a-button>
</div>
</template>
</a-table>
</template>
<script>
import {reactive, ref, toRaw} from 'vue'
import moment from 'moment'
import snapshotRecordApi from '@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import {isArray} from '@/PublicUtil/Judgment'
import {filterEmptyValueInObject, formatDate, formatTime} from '@/PublicUtil/PublicUtil'
import dataRepairApi from '@/views/DataRepair/DataRepairApi'
import {PlusOutlined} from '@ant-design/icons-vue'
const columns = [
{
title: '监控点名称',
dataIndex: 'gatename',
align: 'center',
},
{
title: '设备号',
dataIndex: 'deviceSerialnum',
align: 'center',
},
{
title: '通道号',
dataIndex: 'channelSerialnum',
align: 'center',
},
{
title: '参考范围数据条数',
dataIndex: 'sourceCount',
align: 'center',
},
{
title: '修复范围数据条数',
dataIndex: 'targetCount',
align: 'center',
},
{
title: '参考范围客流量',
dataIndex: 'sourceInnum',
align: 'center',
},
{
title: '修复范围客流量',
dataIndex: 'targetInnum',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
align: 'center',
slots: {
customRender: 'status',
},
},
{
title: '操作',
dataIndex: 'operation',
align: 'center',
slots: {
customRender: 'operation',
},
},
]
export default {
components: {
PlusOutlined,
VNodes: (_, {attrs}) => {
return attrs.vnodes
},
},
setup() {
// scalar
const isLoading = ref(false)
const isSuspended = ref(false)
// sequence
const resultList = ref([])
const accountList = ref([])
const plazaList = ref([])
const zoneList = ref([])
const gateList = ref([])
const channelList = ref([])
const dataList = ref([])
const queryForm = reactive(
{
account_id: [],
plaza_id: [],
gate_id: [],
channel_id: [],
repairDate: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
referenceDate: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: moment('00:00:00', 'HH:mm:ss'),
endTime: moment('23:59:59', 'HH:mm:ss'),
minFactor: 0.85,
maxFactor: 1.2,
}
)
const onAccountChange = function() {
getPlazaList()
queryForm.gate_id = []
gateList.value = []
queryForm.channel_id = []
channelList.value = []
}
const onPlazaChange = function() {
getGateList()
queryForm.channel_id = []
channelList.value = []
}
const onGateChange = function() {
getChannelList()
}
const getPlazaList = function() {
queryForm.plaza_id = []
plazaList.value = []
snapshotRecordApi.getPlazaList(
{
account_id: queryForm.account_id.toString()
}
).then(
(r) => {
if (isArray(r))
{
for (const item of r)
{
plazaList.value.push(
{
value: item.id,
label: item.name,
}
)
}
}
}
)
}
const getAccountList = function() {
queryForm.account_id = []
accountList.value = []
snapshotRecordApi.getAccountList().then(
(r) => {
if (isArray(r))
{
for (const item of r)
{
accountList.value.push(
{
value: item.id,
label: item.name,
}
)
}
}
}
)
}
const getGateList = async function() {
queryForm.gate_id = []
gateList.value = []
let tempList = []
for (const account of queryForm.account_id)
{
for (const plaza of queryForm.plaza_id)
{
const r = await dataRepairApi.getGateList(
{
accountIds: account,
mallIds: plaza,
}
)
if (isArray(r))
{
for (const item of r)
{
tempList.push(
{
value: item.id,
label: item.name,
}
)
}
}
}
}
gateList.value = [...new Set(tempList)]
}
const getChannelList = async function() {
queryForm.channel_id = []
channelList.value = []
let tempList = []
for (const gate of queryForm.gate_id)
{
const r = await dataRepairApi.getChannelList(
{
gateId: gate,
}
)
if (isArray(r))
{
for (const item of r)
{
tempList.push(
{
value: item,
label: item,
}
)
}
}
}
channelList.value = tempList
}
const floatToPercent = function(floatNum) {
if (!floatNum)
{
return 0
}
let formatNum = Math.floor(floatNum * 100)
return formatNum >= 100 ? 100 : formatNum
}
const preview = async function() {
isLoading.value = true
isSuspended.value = false
dataList.value = []
const rawData = toRaw(queryForm)
for (const channelId of rawData.channel_id)
{
if (isSuspended.value === true)
{
isLoading.value = false
return
}
const data = filterEmptyValueInObject(
{
channelSerialnum: channelId,
maxFactor: rawData.maxFactor,
minFactor: rawData.minFactor,
targetStartDate: formatDate(rawData.repairDate) + ' ' + formatTime(rawData.startTime),
targetEndDate: formatDate(rawData.repairDate) + ' ' + formatTime(rawData.endTime),
sourceStartDate: formatDate(rawData.referenceDate) + ' ' + formatTime(rawData.startTime),
sourceEndDate: formatDate(rawData.referenceDate) + ' ' + formatTime(rawData.endTime),
}
)
const r = await dataRepairApi.preview(data)
r.data.status = '未执行'
dataList.value.push(r.data)
}
isLoading.value = false
isSuspended.value = false
}
const repair = async function() {
isLoading.value = true
isSuspended.value = false
dataList.value = []
const rawData = toRaw(queryForm)
for (const channelId of rawData.channel_id)
{
if (isSuspended.value === true)
{
isLoading.value = false
return
}
const data = filterEmptyValueInObject(
{
channelSerialnum: channelId,
maxFactor: rawData.maxFactor,
minFactor: rawData.minFactor,
targetStartDate: formatDate(rawData.repairDate) + ' ' + formatTime(rawData.startTime),
targetEndDate: formatDate(rawData.repairDate) + ' ' + formatTime(rawData.endTime),
sourceStartDate: formatDate(rawData.referenceDate) + ' ' + formatTime(rawData.startTime),
sourceEndDate: formatDate(rawData.referenceDate) + ' ' + formatTime(rawData.endTime),
}
)
const r = await dataRepairApi.repair(data)
if (r.msg_code === 200)
{
r.data.status = '已修复'
}
else
{
r.data.status = '未执行'
}
dataList.value.push(r.data)
}
isLoading.value = false
isSuspended.value = false
}
const getClass = function(text) {
switch (text)
{
case '已修复':
{
return 'success'
}
case '未执行':
{
return 'failed'
}
default:
{
break
}
}
}
const deleteRecord = function({channelSerialnum}) {
if (channelSerialnum === undefined)
{
return
}
dataList.value = dataList.value.filter(
item => item.channelSerialnum !== channelSerialnum
)
queryForm.channel_id = queryForm.channel_id.filter(
item => item !== channelSerialnum
)
}
const suspendRepair = function() {
if (isLoading.value === true)
{
isSuspended.value = true
}
}
const selectAll = function(text) {
switch (text)
{
case '监控点名称':
{
queryForm.gate_id = []
for (const item of gateList.value)
{
queryForm.gate_id.push(item.value)
}
onGateChange()
break
}
case '设备通道号':
{
queryForm.channel_id = []
for (const item of channelList.value)
{
queryForm.channel_id.push(item.value)
}
break
}
default:
{
break
}
}
}
const clearAll = function(text) {
switch (text)
{
case '监控点名称':
{
queryForm.gate_id = []
onGateChange()
break
}
case '设备通道号':
{
queryForm.channel_id = []
break
}
default:
{
break
}
}
}
const __main = function() {
getAccountList()
}
__main()
return {
// scalar
isLoading,
// sequence
accountList,
plazaList,
zoneList,
gateList,
channelList,
resultList,
dataList,
queryForm,
columns,
// function
onAccountChange,
onPlazaChange,
onGateChange,
preview,
repair,
getClass,
deleteRecord,
suspendRepair,
selectAll,
clearAll,
}
}
}
</script>
<style lang="less" scoped>
@import "./DataRepair.less";
</style>
......@@ -79,6 +79,12 @@
<span style="padding: 0 5px">分钟客流数据</span>
</div>
</a-menu-item>
<a-menu-item :key="'/Main/SystemLog'">
<div class="flex-vertical-center">
<img :src="require('./Icons/7.svg')" style="height: auto;width:20px"/>
<span style="padding: 0 5px">系统日志</span>
</div>
</a-menu-item>
</a-menu>
</el-aside>
<el-main>
......
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class SystemLog {
getLogSelect(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/logs/select`,
params: filterEmptyValueInObject(
data
)
}
)
}
getLogLimits(data) {
return axiosInstance.request(
{
method: 'GET',
url: `/logs/limits`,
params: filterEmptyValueInObject(
data
)
}
)
}
}
const SystemLogApi = new SystemLog()
export default SystemLogApi
<template>
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '80px' } }">
<a-form-item label="apptype:" style="padding: 5px 0">
<a-select v-model:value="queryForm.apptype"
style="width: 280px"
:options="apptypeList"
optionFilterProp="label"
>
</a-select>
</a-form-item>
<a-form-item label="服务名称:" style="padding: 5px 0">
<a-select v-model:value="queryForm.appname"
style="width: 280px"
:options="appnameList"
optionFilterProp="label"
>
</a-select>
</a-form-item>
<a-form-item label="日志等级:" style="padding: 5px 0">
<a-select v-model:value="queryForm.level"
style="width: 280px"
:options="levelList"
optionFilterProp="label"
>
</a-select>
</a-form-item>
<a-form-item label="内容:" style="padding: 5px 0">
<a-input v-model:value="queryForm.content_like" placeholder="请输入内容" style="width: 280px"/>
</a-form-item>
<a-form-item label="选择日期:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.date" :format="'YYYY-MM-DD'" style="width: 280px"/>
</a-form-item>
<a-form-item label="选择时间:" style="padding: 5px 0">
<a-time-picker v-model:value="queryForm.startTime" style="width: 140px"/>
<a-time-picker v-model:value="queryForm.endTime" style="width: 140px"/>
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="confirmSearch(1)" :loading="isLoading">查询</a-button>
<!-- <a-button type="primary" @click="confirmSearch1">弹框</a-button> -->
</a-form-item>
</a-form>
<!-- <a-table :dataSource="dataList" v-loading="isLoading" :rowKey="dataList => dataList.id" :columns="columns" :pagination="false" :scroll="{ y: contentHeight }">
</a-table> -->
<el-table
:data="dataList"
v-loading="isLoading"
:rowKey="id"
:height="contentHeight"
style="width: 100%">
<el-table-column
prop="time"
label="时间"
width="180">
</el-table-column>
<el-table-column
prop="thread"
label="线程号"
width="180">
</el-table-column>
<el-table-column
prop="location"
label="日志位置"
width="300">
</el-table-column>
<el-table-column
prop="content"
label="日志内容">
<template #default="{ row }">
<p v-html="stringFormatter(row.content)"></p>
</template>
</el-table-column>
</el-table>
<a-pagination
v-model:current="pageNum"
v-model:pageSize="pageSize"
:total="total"
:show-total="total => `共 ${total} 条`"
:pageSizeOptions="['20', '50', '100']"
@change="onPageNumChange"
@showSizeChange="onPageSizeChange"
show-size-changer
show-quick-jumper
style="text-align:center"
/>
<!-- <moreDialog ref='moreDialogRef'></moreDialog> -->
</template>
<script>
import {reactive, ref, toRaw} from 'vue'
import moment from 'moment'
import SystemLogApi from '@/views/SystemLog/SystemLog.js'
import {isArray} from '@/PublicUtil/Judgment'
import {filterEmptyValueInObject, formatDate, formatTime} from '@/PublicUtil/PublicUtil'
import {PlusOutlined} from '@ant-design/icons-vue'
import moreDialog from './moreDialog.vue'
export default {
components: {
PlusOutlined,
VNodes: (_, {attrs}) => {
return attrs.vnodes
},
moreDialog
},
setup() {
const columns = ref([
{
title: '时间',
dataIndex: 'time',
align: 'center',
width: 220
},
{
title: '线程号',
dataIndex: 'thread',
align: 'center',
width: 120
},
{
title: '日志位置',
dataIndex: 'location',
align: 'center',
width: 300
},
{
title: '日志内容',
dataIndex: 'content',
align: 'center',
customRender:({text,record})=>{
const rawData = toRaw(queryForm)
if (rawData.content_like && rawData.content_like !== '') {
text = text.split(rawData.content_like).join("<span style='color:red;'>" + rawData.content_like + "</span>")
// console.log(str)
// let pHtml = document.createElement("p");
return (<p v-html='str'>{text}</p>)
}else{
return text
}
}
},
// {
// title: '日志标识',
// dataIndex: 'id',
// align: 'center',
// }
])
//ref
const moreDialogRef = ref()
// scalar
const isLoading = ref(false)
const isSuspended = ref(false)
const pageNum = ref(1)
const pageSize = ref(20)
const total = ref()
// sequence
const dataList = ref([])
const apptypeList = ref([{
value: 'store',
label: 'store',
},{
value: 'mall',
label: 'mall',
}])
const appnameList = ref([{
value: 'process',
label: 'process',
},{
value: 'receive',
label: 'receive',
},{
value: 'report',
label: 'report',
},{
value: 'openapi',
label: 'openapi',
}])
const levelList = ref([{
value: 'info',
label: 'info',
},{
value: 'error',
label: 'error',
},{
value: 'debug',
label: 'debug',
},{
value: 'warn',
label: 'warn',
}])
const queryForm = reactive(
{
apptype:'store',
appname: 'process',
level: 'info',
content_like: '',
date: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: moment('00:00:00', 'HH:mm:ss'),
endTime: moment('23:59:59', 'HH:mm:ss'),
}
)
const onPageNumChange = function(num) {
pageNum.value = num
confirmSearch()
}
const onPageSizeChange = function(current, size) {
pageNum.value = 1
pageSize.value = size
confirmSearch()
}
const confirmSearch = function(val){
isLoading.value = true
const rawData = toRaw(queryForm)
pageNum.value = val?1:pageNum.value
const data = filterEmptyValueInObject(
{
apptype: rawData.apptype,
appname: rawData.appname,
level: rawData.level,
content_like: rawData.content_like,
startTime: formatDate(rawData.date) + ' ' + formatTime(rawData.startTime),
endTime: formatDate(rawData.date) + ' ' + formatTime(rawData.endTime),
page: pageNum.value,
pageSize: pageSize.value,
}
)
SystemLogApi.getLogSelect(data).then(
(r) => {
isLoading.value = false
dataList.value = []
if(r.code==200){
// r.forEach((item,index)=>{
// item.index = index+1
// })
if(r.data){
dataList.value = r.data.list
total.value = r.data.total
}
}
}
)
}
const stringFormatter = function(text){
const rawData = toRaw(queryForm)
if (rawData.content_like && rawData.content_like !== '') {
let str = text.split(rawData.content_like).join("<span style='color:red;'>" + rawData.content_like + "</span>")
return str
}else{
return text
}
}
const contentHeight = ref(0)
const __main = function() {
contentHeight.value = window.innerHeight - 230
confirmSearch()
}
const confirmSearch1 = function(){
moreDialogRef.value.initDialog();
}
__main()
return {
// scalar
isLoading,
pageNum,
pageSize,
total,
contentHeight,
// sequence
apptypeList,
appnameList,
levelList,
dataList,
queryForm,
columns,
// function
confirmSearch,
confirmSearch1,
stringFormatter,
onPageNumChange,
onPageSizeChange,
//ref
moreDialogRef
}
}
}
</script>
<style lang="less" scoped>
.success {
color: #26ff29;
}
// /deep/.el-table{
// th,tr{
// background-color: #fafafa;
// }
// }
.failed {
color: red;
}
</style>
<template>
<a-modal title="查看更多"
v-if='isVisible'
v-model:visible="isVisible"
width="1200px"
height='90%'
class="detail-modal">
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '80px' } }">
<a-form-item label="前" style="padding: 5px 0">
<a-input-number v-model:value="queryForm.content_front" placeholder="请输入" style="width: 180px" :min="1" :max="20" />
</a-form-item>
<a-form-item label="后" style="padding: 5px 0">
<a-input-number v-model:value="queryForm.content_after" placeholder="请输入" style="width: 180px" :min="1" :max="20" />
</a-form-item>
<a-form-item style="padding: 5px 0">
<a-button type="primary" @click="confirmSearch" :loading="isLoading">查询</a-button>
</a-form-item>
</a-form>
<a-table :dataSource="dataList" v-loading="isLoading" :columns="columns" :pagination="false">
</a-table>
</a-modal>
</template>
<script>
import {reactive, ref, toRaw} from 'vue'
import moment from 'moment'
import SystemLogApi from '@/views/SystemLog/SystemLog.js'
import {isArray} from '@/PublicUtil/Judgment'
import {filterEmptyValueInObject, formatDate, formatTime} from '@/PublicUtil/PublicUtil'
import {PlusOutlined} from '@ant-design/icons-vue'
const columns = [
{
title: '序号',
dataIndex: 'index',
align: 'center',
width: 100
},
{
title: 'apptype',
dataIndex: 'apptype',
align: 'center',
width: 120
},
{
title: '服务名称',
dataIndex: 'appname',
align: 'center',
width: 120
},
{
title: '服务等级',
dataIndex: 'level',
align: 'center',
width: 120
},
{
title: '时间',
dataIndex: 'time',
align: 'center',
},
{
title: '线程号',
dataIndex: 'thread',
align: 'center',
},
{
title: '日志位置',
dataIndex: 'location',
align: 'center',
},
{
title: '日志内容',
dataIndex: 'content',
align: 'center',
},
{
title: '日志标识',
dataIndex: 'id',
align: 'center',
}
]
export default {
components: {
PlusOutlined,
VNodes: (_, {attrs}) => {
return attrs.vnodes
},
},
setup() {
// scalar
const isLoading = ref(false)
const isSuspended = ref(false)
// sequence
const dataList = ref([])
const isVisible = ref(false)
const queryForm = reactive(
{
apptype:'store',
appname: 'process',
level: 'info',
content_like: '',
date: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'),
startTime: moment('00:00:00', 'HH:mm:ss'),
endTime: moment('23:59:59', 'HH:mm:ss'),
content_front:10,
content_after:10,
}
)
const confirmSearch = function(){
isLoading.value = true
// SystemLogApi.getLogLimits(data).then(
// (r) => {
// isLoading.value = false
// r.forEach((item,index)=>{
// item.index = index+1
// })
// dataList.value = r
// }
// )
}
const initDialog = function() {
// confirmSearch()
isVisible.value = true;
}
return {
// scalar
isLoading,
isVisible,
// sequence
dataList,
queryForm,
columns,
// function
confirmSearch,
initDialog
}
}
}
</script>
<style lang="less" scoped>
.success {
color: #26ff29;
}
.failed {
color: red;
}
</style>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!