Commit 65ead378 by 李君

数据重放

1 parent 4af6d4ad
...@@ -15,7 +15,7 @@ const axiosInstance = axios.create( ...@@ -15,7 +15,7 @@ const axiosInstance = axios.create(
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
config => { config => {
// Cookies.set('atoken','3f719c88-cfe6-42f6-b2c7-a6b355c46c10') // Cookies.set('atoken','1a1fea7a-7ff1-4055-811d-32603abbba06')
if(!Cookies.get('atoken')){ if(!Cookies.get('atoken')){
ElMessage({ ElMessage({
message: `登录过期,请重新登录`, message: `登录过期,请重新登录`,
......
...@@ -49,6 +49,10 @@ const menuRoute = [ ...@@ -49,6 +49,10 @@ const menuRoute = [
path: 'SystemLog', path: 'SystemLog',
component: () => import("@/views/SystemLog/index.vue"), component: () => import("@/views/SystemLog/index.vue"),
}, },
{
path: 'DataReplay',
component: () => import("@/views/DataReplay/DataReplay.vue"),
},
] ]
}, },
] ]
......
import axiosInstance from "@/Request/PublicAxiosInstance"
import {filterEmptyValueInObject} from "@/PublicUtil/PublicUtil"
class DataReplay {
getRematch(data) {
return axiosInstance.request(
{
method: 'POST',
url: `/rematch`,
data: data
}
)
}
}
const DataReplayApi = new DataReplay()
export default DataReplayApi
<template> <template>
<a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '100px' } }"> <a-form :model="queryForm" layout="inline" :label-col="{ style: { width: '100px' } }">
<a-form-item label="集团:" style="padding: 5px 0"> <a-form-item label="集团:" style="padding: 5px 0">
<a-select v-model:value="queryForm.account_id" <a-select v-model:value="queryForm.accountId" style="width: 280px" @change="onAccountChange"
style="width: 280px" :options="accountList" optionFilterProp="label" show-search>
mode="multiple"
:maxTagCount="1"
@change="onAccountChange"
:options="accountList"
optionFilterProp="label"
show-search
>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="广场:" style="padding: 5px 0"> <a-form-item label="广场:" style="padding: 5px 0">
<a-select v-model:value="queryForm.plaza_id" <a-select v-model:value="queryForm.mallId" style="width: 280px" :options="plazaList"
style="width: 280px" optionFilterProp="label" show-search>
mode="multiple"
:maxTagCount="1"
@change="onPlazaChange"
:options="plazaList"
optionFilterProp="label"
show-search
>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="监控点名称:" style="padding: 5px 0"> <a-form-item label="日期:" style="padding: 5px 0">
<a-select v-model:value="queryForm.gate_id" <a-range-picker v-model:value="queryForm.repairDate" style="width: 280px" />
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>
<a-form-item label="设备通道号:" style="padding: 5px 0"> <a-form-item label="是否重提:" style="padding: 5px 0">
<a-select v-model:value="queryForm.channel_id" <a-select v-model:value="queryForm.reExtractFeature" style="width: 280px">
style="width: 280px" <a-select-option value="true"></a-select-option>
mode="multiple" <a-select-option value="false"></a-select-option>
: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-select>
</a-form-item> </a-form-item>
<a-form-item label="修补日期:" style="padding: 5px 0"> <a-form-item label="是否重读:" style="padding: 5px 0">
<a-date-picker v-model:value="queryForm.repairDate" style="width: 280px"/> <a-select v-model:value="queryForm.reTrack" style="width: 280px">
</a-form-item> <a-select-option value="true"></a-select-option>
<a-form-item label="参考日期:" style="padding: 5px 0"> <a-select-option value="false"></a-select-option>
<a-date-picker v-model:value="queryForm.referenceDate" style="width: 280px"/> </a-select>
</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>
<a-form-item style="padding: 5px 0"> <a-form-item style="padding: 5px 0">
<a-button type="primary" @click="repair" :loading="isLoading">修补</a-button> <a-button type="primary" @click="preview" :loading="isLoading">添加</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
<!-- <a-table :dataSource="dataList" v-loading="isLoading" :columns="columns" :pagination="false">
<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 }"> <template #status="{ text }">
<span :class="getClass(text)">{{ text }}</span> <span :class="getClass(text)">{{ text }}</span>
</template> </template>
<template #operation="{ record }"> </a-table> -->
<div>
<a-button @click="deleteRecord(record)" type="primary" danger>删除任务</a-button>
</div>
</template>
</a-table>
</template> </template>
<script> <script>
import {reactive, ref, toRaw} from 'vue' import {
import moment from 'moment' reactive,
import snapshotRecordApi from '@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi' ref,
import {isArray} from '@/PublicUtil/Judgment' toRaw
import {filterEmptyValueInObject, formatDate, formatTime} from '@/PublicUtil/PublicUtil' } from 'vue'
import dataRepairApi from '@/views/DataRepair/DataRepairApi' import moment from 'moment'
import {PlusOutlined} from '@ant-design/icons-vue' import snapshotRecordApi from '@/views/SnapshotCluster/SnapshotRecord/SnapshotRecordApi'
import {
const columns = [ isArray
{ } from '@/PublicUtil/Judgment'
title: '监控点名称', import {
dataIndex: 'gatename', filterEmptyValueInObject,
align: 'center', formatDate,
}, formatTime
{ } from '@/PublicUtil/PublicUtil'
title: '设备号', import dataReplayApi from '@/views/DataReplay/DataReplay.js'
dataIndex: 'deviceSerialnum', import {
align: 'center', PlusOutlined
}, } from '@ant-design/icons-vue'
{
title: '通道号', const columns = [{
dataIndex: 'channelSerialnum', title: '监控点名称',
align: 'center', dataIndex: 'gatename',
}, 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: '设备号',
title: '操作', dataIndex: 'deviceSerialnum',
dataIndex: 'operation', align: 'center',
align: 'center',
slots: {
customRender: 'operation',
}, },
}, {
] title: '通道号',
dataIndex: 'channelSerialnum',
export default { align: 'center',
components: {
PlusOutlined,
VNodes: (_, {attrs}) => {
return attrs.vnodes
}, },
}, {
setup() { title: '参考范围数据条数',
// scalar dataIndex: 'sourceCount',
const isLoading = ref(false) align: 'center',
const isSuspended = ref(false) },
// sequence {
const resultList = ref([]) title: '修复范围数据条数',
const accountList = ref([]) dataIndex: 'targetCount',
const plazaList = ref([]) align: 'center',
const zoneList = ref([]) },
const gateList = ref([]) {
const channelList = ref([]) title: '参考范围客流量',
const dataList = ref([]) dataIndex: 'sourceInnum',
align: 'center',
const queryForm = reactive( },
{ {
account_id: [], title: '修复范围客流量',
plaza_id: [], dataIndex: 'targetInnum',
gate_id: [], align: 'center',
channel_id: [], },
repairDate: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'), {
referenceDate: moment(moment().format('YYYY-MM-DD'), 'YYYY-MM-DD'), title: '状态',
startTime: moment('00:00:00', 'HH:mm:ss'), dataIndex: 'status',
endTime: moment('23:59:59', 'HH:mm:ss'), align: 'center',
minFactor: 0.85, slots: {
maxFactor: 1.2, 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 accountList = ref([])
const plazaList = ref([])
const dataList = ref([])
const queryForm = reactive({
accountId: '',
mallId: '',
repairDate: [moment().format('YYYY-MM-DD'),moment().format('YYYY-MM-DD')],
reExtractFeature:'true',
reTrack:'true'
})
const onAccountChange = function() {
getPlazaList()
} }
)
const onAccountChange = function() {
getPlazaList()
queryForm.gate_id = [] const getPlazaList = function() {
gateList.value = [] queryForm.mallId = ''
plazaList.value = []
queryForm.channel_id = [] snapshotRecordApi.getPlazaList({
channelList.value = [] account_id: queryForm.accountId.toString()
} }).then(
(r) => {
const onPlazaChange = function() { if (isArray(r)) {
getGateList() for (const item of r) {
queryForm.channel_id = [] plazaList.value.push({
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, value: item.id,
label: item.name, label: item.name,
} })
) }
if(r&&r.length){
queryForm.mallId=r[0].id
}
} }
} }
} )
) }
}
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)) const getAccountList = function() {
{ queryForm.accountId = ''
for (const item of r) accountList.value = []
{ snapshotRecordApi.getAccountList().then(
tempList.push( (r) => {
{ if (isArray(r)) {
for (const item of r) {
accountList.value.push({
value: item.id, value: item.id,
label: item.name, label: item.name,
} })
) }
if(r&&r.length){
queryForm.accountId=r[0].id
getPlazaList()
}
} }
} }
}
}
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 = '未执行' const preview = function() {
dataList.value.push(r.data) isLoading.value = true
} const rawData = toRaw(queryForm)
isLoading.value = false console.log(rawData.repairDate)
isSuspended.value = false dataReplayApi.getRematch(filterEmptyValueInObject({
} accountId: rawData.accountId.toString(),
mallId: rawData.mallId.toString(),
const repair = async function() { reExtractFeature: rawData.reExtractFeature,
isLoading.value = true reTrack: rawData.reTrack,
isSuspended.value = false startDate:rawData.repairDate[0],
dataList.value = [] endDate:rawData.repairDate[1],
const rawData = toRaw(queryForm) })).then(
for (const channelId of rawData.channel_id) (r) => {
{ console.log(r)
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 __main = function() {
} getAccountList()
} }
}
const clearAll = function(text) { __main()
switch (text)
{ return {
case '监控点名称': // scalar
{ isLoading,
queryForm.gate_id = [] // sequence
onGateChange() accountList,
break plazaList,
} dataList,
case '设备通道号': queryForm,
{ columns,
queryForm.channel_id = [] // function
break onAccountChange,
} preview,
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> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import "./DataRepair.less";
</style> </style>
...@@ -85,6 +85,12 @@ ...@@ -85,6 +85,12 @@
<span style="padding: 0 5px">系统日志</span> <span style="padding: 0 5px">系统日志</span>
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item :key="'/Main/DataReplay'">
<div class="flex-vertical-center">
<img :src="require('./Icons/2.svg')" style="height: auto;width:20px"/>
<span style="padding: 0 5px">数据重放</span>
</div>
</a-menu-item>
</a-menu> </a-menu>
</el-aside> </el-aside>
<el-main> <el-main>
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!