Authored by 王涛

Merge branch 'master-500-dev-lushangqing' into 'master-500-dev'

【无】操作记录日志页面搭建(50%) #1



See merge request !998
<title>操作日志</title>
<iframe class="layadmin-iframe" src="/vue3/index.html#/vue3/operationLog" style="height: 99.5%!important;"/>
... ...
... ... @@ -11,6 +11,8 @@
@import "../css/cmdbdatasync.css";
/*登录logo配置*/
@import "../css/logoConfig.css";
/*lsq 操作记录日志样式 2022-09-26*/
@import "../css/operationLog.css";
.d-flex {
display: flex;
... ...
.operation-log-search{
display: flex;
align-items: center;
justify-content: center;
margin-top:6px;
}
.container-none{
width:100%;
height: 20px;
background:#fafafa;
}
.operation-log-container.container .cm-card .search-table{padding:15px;}
.echart-con{
padding:10px;
}
.echart-con .echart-title{
font-size: 16px;
color:#1e9fff;
text-align: left;
margin-bottom: 6px;
padding:10px;
}
.echart-left,.echart-right{
border:1px solid #eee;
}
.echart-chart{
height: 300px;
}
\ No newline at end of file
... ...
... ... @@ -178,6 +178,12 @@ const routes = [{
name: 'thirdSet',
component: () => myImport('views/thirdSet/index')
},
//操作日志
{
path: '/vue3/operationLog',
name: 'operationLog',
component: () => myImport('views/operationLog/index')
}
];
// hash模式: createWebHashHistory
... ...
<div :style="{'height':height+'px','max-height':height+'px'}" class="container operation-log-container">
<div :style="{'min-height':height+'px','max-height':height+'px','height':'100%'}" class="cm-card">
<el-row>
<el-col :span="14" class="search-item">
<div class="search">
<div class="operation-log-search">
<el-button-group class="ml-4">
<el-button :size="$global.elementConfig.size.button" :type="search.status == 1 ? 'primary' : ''"
@click="getDataList(1)">用户名
</el-button>
<el-button :size="$global.elementConfig.size.button" :type="search.status == 2 ? 'primary' : ''"
@click="getDataList(2)">巡检组
</el-button>
</el-button-group>
</div>
</div>
<div class="echart-con">
<div class="echart-left">
<div class="echart-title">巡检点击完成统计</div>
<div class="echart-chart">
<LineChart :optionData="optionData" v-if="optionData"></LineChart>
</div>
</div>
</div>
</el-col>
<el-col :span="10">
<div class="search">
<div class="operation-log-search">
<el-button-group class="ml-4">
<el-button :size="$global.elementConfig.size.button" :type="search.status == 'yesterday' ? 'primary' : ''"
@click="getDataList('yesterday')">昨天
</el-button>
<el-button :size="$global.elementConfig.size.button" :type="search.status == 'today' ? 'primary' : ''"
@click="getDataList('today')">今天
</el-button>
<el-button :size="$global.elementConfig.size.button" :type="search.status == 'lastWeek' ? 'primary' : ''"
@click="getDataList('lastWeek')">上周
</el-button>
<el-button :size="$global.elementConfig.size.button" :type="search.status == 'thisWeek' ? 'primary' : ''"
@click="getDataList('thisWeek')">本周
</el-button>
<el-button :size="$global.elementConfig.size.button" :type="search.status == 'thisMonth' ? 'primary' : ''"
@click="getDataList('thisMonth')">本月
</el-button>
<el-button style="border-radius: 0;" :size="$global.elementConfig.size.button" :type="search.status == 'all' ? 'primary' : ''"
@click="getDataList('all')">全部
</el-button>
</el-button-group>
<el-date-picker
:size="$global.elementConfig.size.input"
style="width:150px;border-radius: 0 4px 4px 0;"
end-placeholder="结束日期"
format="YYYY-MM-DD"
range-separator="-"
start-placeholder="开始日期"
type="daterange"
v-model="search.dateTime"
value-format="YYYY-MM-DD"
:prefix-icon="'none'"
@focus="dateFocus"
@change="dateChange"
/>
</div>
</div>
<div class="echart-con">
<div class="echart-right">
<div class="echart-title">人员功能点击量</div>
<div class="echart-chart">
<LineChart :optionData="optionDataR" v-if="optionDataR"></LineChart>
</div>
</div>
</div>
</el-col>
</el-row>
<div class="container-none"></div>
<div class="search-table">
<cm-table-page :columns="tableData.columns" :dataList="tableData.dataList"
:height="height - 110"
:loading="false"
:pageSize="pageSize"
:showBorder="true"
:showIndex="true"
:showPage="true"
:showSelection="false"
:showTools="false"
:total="tableData.count"
@loaddata="loaddata">
<template #default="{row,prop,column}">
</template>
</cm-table-page>
</div>
</div>
</div>
<!--新增编辑弹框-->
<cm-dialog :showDialogVisible="dialog.show" :showFooter="false" :title="dialog.title" @hidedialog="hideDialog">
<template v-slot>
</template>
</cm-dialog>
... ...
export default {
name: 'operationLog',
template: '',
components: {
'LineChart': Vue.defineAsyncComponent(
() => myImport('views/page/components/lineChart/index')
)
},
props: [],
setup(props, {attrs, slots, emit}) {
const {proxy} = Vue.getCurrentInstance();
let isView = Vue.ref(false);
let height = Vue.ref(window.innerHeight);
let optionData = Vue.ref('');
let optionDataR = Vue.ref('');
let series = Vue.ref([]);
let seriesR = Vue.ref([]);
let names = Vue.ref(['智能综合巡检系统', '数据中心虚拟化', '备份系统']);
let namesR = Vue.ref(['吴斌斌','袁晋鹏'])
let kpiName=Vue.ref('');
let kpiNameR = Vue.ref('');
let kpiUnit=Vue.ref('');
let kpiUnitR=Vue.ref('');
let colorsArr = Vue.ref([
{
start: '#468ced',
end: '#68a5fa'
},
{
start: '#79dda1',
end: '#9bddb5'
}
])
const optionDataInit = () => {
optionData.value = {
tooltip: {
trigger: 'axis',
formatter: function (param) {
var tips = kpiName.value + " " + param[0].name + "<br/>";
$.each(param, function (i, v) {
tips += v.marker + " " + v.seriesName + ":" + v.value + kpiUnit.value + "</br>"
});
return tips;
}
},
legend: {
show: true
},
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '5%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {
show: false
}
}
},
xAxis: {
type: 'category',
data: names.value,
axisLine: {
lineStyle: {
color: '#c9c9c9'
}
},
axisLabel: {
color: '#232425',
showMaxLabel: true,
lineHeight:18,
formatter: function (params) {
var newParamsName = '';
let paramsNameNumber = params.length;
let provideNumber = 4;
let rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let i = 0; i < rowNumber; i++) {
let tempStr = '';
let start = i * provideNumber;
let end = start + provideNumber;
if (i == rowNumber - 1) {
tempStr = params.substring(start, paramsNameNumber);
} else {
tempStr = params.substring(start, end) + "\n";
}
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
}
},
splitArea: {
show: true,
areaStyle: {
color: ['rgba(200,200,200,0.1)', 'transparent'
]
}
}
},
yAxis: {
type: 'value',
scale: true,
min:0,
boundaryGap: ['10%', '10%'],
axisLine: {
lineStyle: {
color: '#232425'
},
show: false
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: ['#ddd'],
type: 'dotted',
}
}
},
series: series.value
};
optionDataR.value= {
tooltip: {
trigger: 'axis',
formatter: function (param) {
var tips = kpiName.value + " " + param[0].name + "<br/>";
$.each(param, function (i, v) {
tips += v.marker + " " + v.seriesName + ":" + v.value + kpiUnit.value + "</br>"
});
return tips;
}
},
legend: {
show: true
},
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '5%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {
show: false
}
}
},
xAxis: {
type: 'category',
data: namesR.value,
axisLine: {
lineStyle: {
color: '#c9c9c9'
}
},
axisLabel: {
color: '#232425',
showMaxLabel: true,
lineHeight:18,
formatter: function (params) {
var newParamsName = '';
let paramsNameNumber = params.length;
let provideNumber = 4;
let rowNumber = Math.ceil(paramsNameNumber / provideNumber);
if (paramsNameNumber > provideNumber) {
for (let i = 0; i < rowNumber; i++) {
let tempStr = '';
let start = i * provideNumber;
let end = start + provideNumber;
if (i == rowNumber - 1) {
tempStr = params.substring(start, paramsNameNumber);
} else {
tempStr = params.substring(start, end) + "\n";
}
newParamsName += tempStr;
}
} else {
newParamsName = params;
}
return newParamsName;
}
},
splitArea: {
show: true,
areaStyle: {
color: ['rgba(200,200,200,0.1)', 'transparent'
]
}
}
},
yAxis: {
type: 'value',
scale: true,
boundaryGap: ['10%', '10%'],
axisLine: {
lineStyle: {
color: '#232425'
},
show: false
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: ['#ddd'],
type: 'dotted',
}
}
},
series: seriesR.value
};
}
let rateData=Vue.ref([
{name:'应点击量',data:[1,34,12]},
{name:'实际点击量',data:[15,24,10]}
])
let rateDataR=Vue.ref([
{name:'',data:[1,6,8,9,10]},
])
const setSeries = () => {
series.value = [];
$.each(rateData.value, function (i, v) {
series.value.push({
name: v.name,
type: 'bar',
barWidth: 16,//设置柱状图大小
data: v.data,
stack:'total',
symbolSize: 12,
symbol: 'circle',
itemStyle: {
normal: {
// color: colorsArr.value[i].start //图标颜色
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ //关键在这里, 设置面积渐变
offset: 0,
color: colorsArr.value[i].start //这里是我设置的渐变的颜色从线条颜色变为透明
}, {
offset: 1,
color: colorsArr.value[i].end
}])
}
}
})
});
seriesR.value = [];
$.each(rateDataR.value, function (i, v) {
seriesR.value.push({
name: v.name,
type: 'bar',
barWidth: 16,//设置柱状图大小
data: v.data,
stack:'noStack',
symbolSize: 12,
symbol: 'circle',
itemStyle: {
normal: {
// color: colorsArr.value[i].start //图标颜色
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ //关键在这里, 设置面积渐变
offset: 0,
color: colorsArr.value[i].start //这里是我设置的渐变的颜色从线条颜色变为透明
}, {
offset: 1,
color: colorsArr.value[i].end
}])
},
borderRadius:[3,3,0,0]
}
})
});
optionDataInit();
}
let search = Vue.ref({
status: 'today',
dateTime:'',
keyword: '',
page: 1,
limit: 10,
});
let dialog = Vue.ref({
title: "处理审批",
show: false,
amId: '',
amStatus: 0,
alarmId: '',
});
//表格字段
let tableData = Vue.ref({
count: 0,
dataList: [],
columns: [
{
prop: 'alarmNo',
label: '用户名',
sortable: true,
align: 'center',
width: '150'
},
{
prop: 'resName',
label: '时间',
sortable: true,
align: 'center',
width: '250',
},
{
prop: 'resTypeName',
label: 'IP地址',
sortable: true,
align: 'center',
width: '150'
}, {
prop: 'managenameName',
label: '访问位置',
sortable: true,
align: 'center',
}, {
prop: 'reason',
label: '停留总时长',
sortable: true,
align: 'center',
width: '120'
}
]
})
//点击时间选择时,其他按钮不高亮
let dateFocus=()=>{
search.value.status = 'dateRange';
}
//时间更改事件
let dateChange=(val)=>{
console.log(val,search.value.dateTime)
getDataList('dateRange')
}
//获取aj配置信息
let statusVal = Vue.ref('today');
let getDataList = (status) => {
if (status == undefined) {
status = 'today'
}
if(status != 'dateRange'){
search.value.dateTime=[];
}
statusVal.value = status;
search.value.status = status;
let startTime='';
let endTime=''
if(search.value.dateTime && search.value.dateTime.length>0){
startTime=search.value.dateTime[0];
endTime=search.value.dateTime[1];
}
let params={
page: search.value.page,
limit: search.value.limit,
keyword: search.value.keyword,
status: search.value.status,
startTime:startTime,
endTime:endTime
}
proxy.$http.get(`/api-web/bAlarmManage/page`, params, function (res) {
if (res && res.data) {
tableData.value.dataList = res.data;
tableData.value.count = res.count;
} else {
tableData.value.dataList = [];
tableData.value.count = 0;
}
});
}
let loaddata = ({page, limit}) => {
search.value.page = page;
search.value.limit = limit;
}
let hideDialog = (flg) => {
dialog.value.show = flg;
if (!flg) {
getDataList(dialog.value.amStatus)
}
}
// 处理弹框
let handle = (row, flag) => {
isView.value = flag;
hideDialog(true);
dialog.value.amId = row.id;
dialog.value.amStatus = row.status;
dialog.value.alarmId = row.alarmId;
}
//审核保存后关闭弹框
let saveback = (val) => {
hideDialog(val)
}
let loginName = Vue.ref(localStorage.getItem('lgn'));
// 挂载完
Vue.onMounted(() => {
getDataList();
setSeries();
})
return {
loginName,
height,
optionData,
optionDataInit,
series,
names,
rateData,
optionDataR,
seriesR,
namesR,
rateDataR,
setSeries,
dateFocus,
dateChange,
dialog,
hideDialog,
search,
tableData,
loaddata,
getDataList,
handle,
saveback,
statusVal,
isView
}
}
}
... ...
... ... @@ -279,6 +279,12 @@ const routes = [{
name: 'thirdSet',
component: () => myImport('views/thirdSet/index')
},
//操作日志
{
path: '/vue3/operationLog',
name: 'operationLog',
component: () => myImport('views/operationLog/index')
}
];
// hash模式: createWebHashHistory
... ...