增加模板

This commit is contained in:
geting 2024-12-25 17:51:08 +08:00
parent 85fde3f2ac
commit e410e6f496
6 changed files with 223 additions and 62 deletions

View File

@ -39,7 +39,7 @@ export const runAirBlowerReq = (
}) })
} }
export const getReportTemplateListReq = (data: { category: '单机报表' | '多机报表'; pageNum: number; pageSize: number }) => { export const getReportTemplateListReq = (data: { category: '单机报表' | '多机报表' | '统计查询'; pageNum: number; pageSize: number }) => {
return createAxios< return createAxios<
never, never,
Promise<{ Promise<{
@ -47,7 +47,7 @@ export const getReportTemplateListReq = (data: { category: '单机报表' | '多
msg: string msg: string
data: { data: {
total: number total: number
rows: { id: string; category: '单机报表' | '多机报表'; template: string }[] rows: { id: string; category: '单机报表' | '多机报表' | '统计查询'; template: string }[]
code: number code: number
msg: string msg: string
} }
@ -60,7 +60,7 @@ export const getReportTemplateListReq = (data: { category: '单机报表' | '多
}) })
} }
export const addReportTemplateListReq = (data: { category: '单机报表' | '多机报表'; template: string }) => { export const addReportTemplateListReq = (data: { category: '单机报表' | '多机报表' | '统计查询'; template: string }) => {
return createAxios< return createAxios<
never, never,
Promise<{ Promise<{

View File

@ -94,13 +94,16 @@
@change="getcurrentPage" @change="getcurrentPage"
></el-pagination> ></el-pagination>
</div> </div>
<el-dialog v-model="malFunctionVisible" title="故障录波" width="1000" :destroy-on-close="true">
<MalFunction v-model:visible="malFunctionVisible" :alarms="alarms" class="malDialog"></MalFunction>
</el-dialog>
</el-main> </el-main>
</el-container> </el-container>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, onMounted, computed } from 'vue' import { reactive, ref, onMounted, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { AlarmsFieldsEnums, AlarmsTableType, GetAlarmsTableParam } from './type' import { AlarmsFieldsEnums, AlarmsTableType, GetAlarmsTableParam } from './type'
@ -108,14 +111,16 @@ import { getAlarmListReq, eventComfirm } from '/@/api/backend/alarms/request'
import { queryfaultCodeDict, theoreticalpowerCurveList } from '/@/api/backend/theoreticalpowerCurve/request' import { queryfaultCodeDict, theoreticalpowerCurveList } from '/@/api/backend/theoreticalpowerCurve/request'
import { equipList } from '/@/api/backend/realData/request' import { equipList } from '/@/api/backend/realData/request'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRouter, useRoute } from 'vue-router' import MalFunction from '/@/views/backend/malfunction/index.vue'
const router = useRouter()
const { t } = useI18n() const { t } = useI18n()
import { useAdminInfo } from '/@/stores/adminInfo' import { useAdminInfo } from '/@/stores/adminInfo'
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const malFunctionVisible = ref(false)
// //
const alarms = ref({
eventTime: '',
deviceId: '',
})
const timeRange = ref([new Date().setHours(0, 0, 0, 0), new Date()]) const timeRange = ref([new Date().setHours(0, 0, 0, 0), new Date()])
const shortcuts = [ const shortcuts = [
@ -395,13 +400,9 @@ const getfaultCodeDict = async (data: any) => {
} }
const openDefalt = (row: any) => { const openDefalt = (row: any) => {
router.push({ const { eventTime, deviceId } = row
name: 'faultRecord', alarms.value = { eventTime, deviceId }
query: { malFunctionVisible.value = true
eventTime: row.eventTime,
deviceId: row.deviceId,
},
})
} }
</script> </script>
@ -511,6 +512,9 @@ $paginationHeight: 32px;
justify-content: right; justify-content: right;
background-color: #fff; background-color: #fff;
} }
.malDialog {
height: 540px;
}
} }
} }
.modelOperate { .modelOperate {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="malfunction"> <div class="malfunction">
<el-container class="container"> <el-container class="container">
<el-aside class="aside"> <el-aside class="aside" v-show="!props.visible">
<div class="searchTree"> <div class="searchTree">
<el-input v-model="searchTreeValue" clearable placeholder="搜索" :suffix-icon="Search" @change="searchTree"> </el-input> <el-input v-model="searchTreeValue" clearable placeholder="搜索" :suffix-icon="Search" @change="searchTree"> </el-input>
</div> </div>
@ -179,6 +179,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, PropType } from 'vue'
import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue' import { ref, reactive, computed, onMounted, nextTick, onUnmounted } from 'vue'
import { dayjs, ElMessage, FormInstance, TreeInstance } from 'element-plus' import { dayjs, ElMessage, FormInstance, TreeInstance } from 'element-plus'
import { Search, Setting } from '@element-plus/icons-vue' import { Search, Setting } from '@element-plus/icons-vue'
@ -194,15 +195,26 @@ import { equipList } from '/@/api/backend/temperature/request'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { tableItemData } from './type' import { tableItemData } from './type'
import ContextMenu from '/@/views/backend/auth/model/contextMenu.vue' import ContextMenu from '/@/views/backend/auth/model/contextMenu.vue'
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const defaultProps = { const defaultProps = {
children: 'children', children: 'children',
label: 'label', label: 'label',
} }
const props = defineProps({
alarms: {
type: Object as PropType<{ eventTime: string; deviceId: string }>,
default: () => ({
eventTime: undefined,
deviceId: undefined,
}),
},
visible: {
type: Boolean,
default: false,
},
})
const contextMenuInfo = reactive({ const contextMenuInfo = reactive({
visible: false, visible: false,
pos: { pos: {
@ -313,8 +325,8 @@ const getTreeDataList = () => {
}) })
}) })
} }
const initDatestart = route.query.eventTime ? dayjs(Number(route.query.eventTime)) : dayjs().startOf('month') const initDatestart = props.alarms.eventTime ? dayjs(Number(props.alarms.eventTime)) : dayjs().startOf('month')
const initDateend = route.query.eventTime ? dayjs(Number(route.query.eventTime)) : dayjs() const initDateend = props.alarms.eventTime ? dayjs(Number(props.alarms.eventTime)) : dayjs()
const searchData = reactive<{ fileName: ''; date: Date[] }>({ const searchData = reactive<{ fileName: ''; date: Date[] }>({
fileName: '', fileName: '',
@ -907,7 +919,7 @@ const checkTab = () => {
onMounted(() => { onMounted(() => {
getTreeDataList().then((data: any) => { getTreeDataList().then((data: any) => {
const queryId = route.query.deviceId ?? data.id const queryId = props.alarms.deviceId ?? data.id
treeRef.value && treeRef.value.setCurrentKey(queryId, true) treeRef.value && treeRef.value.setCurrentKey(queryId, true)
curTreeData.value = treeRef.value?.getCurrentNode() curTreeData.value = treeRef.value?.getCurrentNode()
getListForAirBlower() getListForAirBlower()

View File

@ -393,6 +393,7 @@ const statAnalysisOperate = () => {
const statAnalysisExport = () => { const statAnalysisExport = () => {
const params = statAnalysisFatory.value ? statAnalysisFatory.value : statAnalysisDeviceId.value const params = statAnalysisFatory.value ? statAnalysisFatory.value : statAnalysisDeviceId.value
const windSource = statAnalysisSelectOptions.speedSource.filter((item: any) => item.value == statAnalysisSpeedSource.value)
const requestData = { const requestData = {
devices: [ devices: [
{ {
@ -404,6 +405,8 @@ const statAnalysisExport = () => {
endTime: new Date(statAnalysisTime.value[1]).getTime(), endTime: new Date(statAnalysisTime.value[1]).getTime(),
madeinfactory: params.split(':')[0], madeinfactory: params.split(':')[0],
model: params.split(':')[1], model: params.split(':')[1],
windSource: windSource[0]['label'],
displayCurve: AvgWindSpeedSwitch ? 0 : 1,
} }
powerCurveExport(requestData).then((res: any) => { powerCurveExport(requestData).then((res: any) => {
const downloadUrl = window.URL.createObjectURL(res) const downloadUrl = window.URL.createObjectURL(res)

View File

@ -588,6 +588,7 @@ const statAnalysisExport = () => {
startTime: new Date(time[0]).getTime(), startTime: new Date(time[0]).getTime(),
endTime: new Date(time[1]).getTime(), endTime: new Date(time[1]).getTime(),
timeName: customName[index], timeName: customName[index],
calFunction: statAnalysisSelect.calFunction,
} }
requestData.push(devices) requestData.push(devices)
} }

View File

@ -1,6 +1,7 @@
<template> <template>
<div class="contain"> <div class="contain">
<el-header class="headerPart"> <el-header>
<div class="headerPart">
<div class="topLeft"> <div class="topLeft">
<div class="selectPart"> <div class="selectPart">
<span>{{ t('statAnalysis.time') }}</span> <span>{{ t('statAnalysis.time') }}</span>
@ -28,7 +29,12 @@
:placeholder="'请选择' + t('statAnalysis.calFunction')" :placeholder="'请选择' + t('statAnalysis.calFunction')"
class="statAnalysisSelect" class="statAnalysisSelect"
> >
<el-option v-for="v in statAnalysisSelectOptions.calFunction" :key="v.value" :label="v.label" :value="v.value"></el-option> <el-option
v-for="v in statAnalysisSelectOptions.calFunction"
:key="v.value"
:label="v.label"
:value="v.value"
></el-option>
</el-select> </el-select>
</div> </div>
<el-button type="primary" :icon="Crop" class="addline" @click="openMeasure">测点选择</el-button> <el-button type="primary" :icon="Crop" class="addline" @click="openMeasure">测点选择</el-button>
@ -36,16 +42,34 @@
<div class="topRight"> <div class="topRight">
<el-button type="primary" :loading="isLoading" @click="statAnalysisOperate()">{{ t('statAnalysis.search') }}</el-button> <el-button type="primary" :loading="isLoading" @click="statAnalysisOperate()">{{ t('statAnalysis.search') }}</el-button>
<el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button> <el-button style="color: #0064aa" @click="statAnalysisExport()">{{ t('statAnalysis.export') }}</el-button>
<el-button class="button" :icon="Notebook" type="primary" @click="addReportTemplate" plain>保存为模板</el-button>
</div>
</div>
<div>
<el-space style="margin: 10px 20px">
<div style="min-width: 30px">模板</div>
<el-select v-model="template" placeholder="请选择模板" class="templateSelect" @change="changeTemplate" clearable>
<el-option v-for="v in reportTemplateList" :key="v.id" :label="v.name" :value="v.id">
<template #default>
<div class="tamplateOption">
<span>{{ v.name }}</span>
<el-icon style="color: red" @click="delReportTemplate(v.id)">
<Delete />
</el-icon>
</div>
</template>
</el-option>
</el-select>
</el-space>
</div> </div>
</el-header> </el-header>
<div class="main"> <div class="main">
<div <div
ref="chartContainer" ref="chartContainer"
style="height: calc(100% - 140px); width: calc(100% - 60px); border: 1px solid rgb(217, 217, 217); margin: 40px" style="height: calc(100% - 140px); width: calc(100% - 60px); border: 1px solid rgb(217, 217, 217); margin: 80px 40px"
></div> ></div>
</div> </div>
<el-dialog v-model="showMeasure" title="选择测点" width="1200" top="0" :destroy-on-close="true">
<el-dialog v-model="showMeasure" title="选择测点" width="1200" top="0">
<div class="measureSlot"> <div class="measureSlot">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
@ -66,6 +90,7 @@
<el-table-column prop="name" label="风机名称" /> <el-table-column prop="name" label="风机名称" />
</el-table> </el-table>
<el-table <el-table
ref="tableDataMidRef"
:data="tableDataMid" :data="tableDataMid"
v-model:selection="selectedMid" v-model:selection="selectedMid"
@selection-change="handleSelectionChange2" @selection-change="handleSelectionChange2"
@ -76,6 +101,7 @@
<el-table-column prop="name" label="风机名称" /> <el-table-column prop="name" label="风机名称" />
</el-table> </el-table>
<el-table <el-table
ref="tableDataRightRef"
:data="tableDataRight" :data="tableDataRight"
v-model:selection="selectedRight" v-model:selection="selectedRight"
@selection-change="handleSelectionChange1" @selection-change="handleSelectionChange1"
@ -140,13 +166,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { markRaw, reactive, ref, watch, nextTick, onMounted, computed } from 'vue' import { markRaw, reactive, ref, watch, nextTick, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { queryWindTurbinesPages, historyReq, trendContrastExport, windowReq } from '/@/api/backend/statAnalysis/request' import {
import { ElMessage, ElMenu } from 'element-plus' queryWindTurbinesPages,
import { DArrowRight, Plus, Crop, Close } from '@element-plus/icons-vue' historyReq,
trendContrastExport,
windowReq,
getReportTemplateListReq,
addReportTemplateListReq,
delReportTemplateListReq,
} from '/@/api/backend/statAnalysis/request'
import { ElMessage, ElMenu, ElMessageBox, backtopEmits } from 'element-plus'
import { DArrowRight, Plus, Crop, Notebook, Delete } from '@element-plus/icons-vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { getModelAttributeListReq } from '/@/api/backend/deviceModel/request' import { getModelAttributeListReq } from '/@/api/backend/deviceModel/request'
import { getCutDecimalsValue } from '/@/views/backend/equipment/airBlower/utils' import { getCutDecimalsValue } from '/@/views/backend/equipment/airBlower/utils'
const { t } = useI18n() const { t } = useI18n()
const statAnalysisInterval = ref('1h') const statAnalysisInterval = ref('1h')
@ -236,6 +269,8 @@ onMounted(() => {
statAnalysisOperate() statAnalysisOperate()
}) })
}) })
getReportTemplateList()
}) })
const tableDataLeft = ref([]) const tableDataLeft = ref([])
const tableDataRight = ref([]) const tableDataRight = ref([])
@ -414,6 +449,8 @@ const getDateRange = (type: 'week' | 'month') => {
} }
const tableDataLeftRef = ref() const tableDataLeftRef = ref()
const tableDataMidRef = ref()
const tableDataRightRef = ref()
const openMeasure = () => { const openMeasure = () => {
showMeasure.value = true showMeasure.value = true
pageSetting.current = 1 pageSetting.current = 1
@ -421,6 +458,12 @@ const openMeasure = () => {
selectedLeft.value.forEach((item) => { selectedLeft.value.forEach((item) => {
tableDataLeftRef.value?.toggleRowSelection(item, true) tableDataLeftRef.value?.toggleRowSelection(item, true)
}) })
selectedMid.value.forEach((item) => {
tableDataMidRef.value?.toggleRowSelection(item, true)
})
selectedRight.value.forEach((item) => {
tableDataRightRef.value?.toggleRowSelection(item, true)
})
initSelect() initSelect()
}) })
} }
@ -587,6 +630,96 @@ const timestampToTime = (timestamp: any) => {
let m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() let m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
return Y + M + D + h + m return Y + M + D + h + m
} }
const addReportTemplate = () => {
ElMessageBox.prompt('请输入模板名称', '添加模板', {
confirmButtonText: '提交',
cancelButtonText: '取消',
inputPattern: /\S/,
inputErrorMessage: '模板名称不能为空',
}).then(({ value }) => {
const tem = {
name: value,
interval: statAnalysisInterval.value,
calFunction: statAnalysisSelectcalFunction.value,
multipleSelection: multipleSelection.value,
selectedLeft: selectedLeft.value,
selectedMid: selectedMid.value,
selectedRight: selectedRight.value,
}
const data = {
category: '统计查询' as const,
template: JSON.stringify(tem),
}
addReportTemplateListReq(data).then((res) => {
if (res.success) {
ElMessage.success('添加成功!')
getReportTemplateList()
}
})
})
}
const template = ref('')
const reportTemplateList = ref([
{
name: '',
id: '',
interval: '',
calFunction: '',
},
])
const getReportTemplateList = () => {
getReportTemplateListReq({
pageNum: 1,
pageSize: 1000,
category: '统计查询',
}).then((res) => {
if (res.success) {
reportTemplateList.value = res.data.rows.map((item) => {
const tem = item.template ? JSON.parse(item.template) : {}
return {
name: tem.name,
id: item.id,
interval: tem.interval,
calFunction: tem.calFunction,
multipleSelection: tem.multipleSelection,
selectedLeft: tem.selectedLeft,
selectedMid: tem.selectedMid,
selectedRight: tem.selectedRight,
}
})
}
})
}
const delReportTemplate = (id: string) => {
ElMessageBox.confirm('确定删除该模板吗?', '删除模板', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
delReportTemplateListReq({ id }).then((res) => {
if (res.success) {
ElMessage.success('删除成功!')
getReportTemplateList()
template.value = ''
}
})
})
}
const changeTemplate = (val: string) => {
const target: any = reportTemplateList.value.find((item) => item.id === val)
if (target) {
multipleSelection.value = target.multipleSelection
statAnalysisInterval.value = target.interval
statAnalysisSelectcalFunction.value = target.calFunction
selectedLeft.value = tableDataLeft.value.filter((item: any) => target.selectedLeft.some((selected: any) => selected.irn === item.irn))
selectedMid.value = tableDataMid.value.filter((item: any) => target.selectedMid.some((selected: any) => selected.irn === item.irn))
selectedRight.value = tableDataRight.value.filter((item: any) => target.selectedRight.some((selected: any) => selected.irn === item.irn))
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.statAnalysis { .statAnalysis {
@ -633,6 +766,9 @@ const timestampToTime = (timestamp: any) => {
} }
} }
} }
.templateSelect {
width: 200px;
}
.selectPart { .selectPart {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -746,4 +882,9 @@ const timestampToTime = (timestamp: any) => {
} }
} }
} }
.tamplateOption {
display: flex;
align-items: center;
justify-content: space-between;
}
</style> </style>