复刻冀北地图

This commit is contained in:
GGJ
2025-01-15 10:44:57 +08:00
parent 72f2c5d0f3
commit 9c688c3bd3
30 changed files with 5996 additions and 174 deletions

View File

@@ -0,0 +1,42 @@
import createAxios from '@/utils/request'
//删除列表
export function deleteByIds(data: any) {
return createAxios({
url: '/advance-boot/responsibility/deleteByIds',
method: 'post',
data
})
}
//上传用采数据
export function uploadUserData(data: any) {
return createAxios({
url: '/advance-boot/responsibility/uploadUserData',
method: 'post',
data
})
}
//负荷数据
export function userDataList(data: any) {
return createAxios({
url: '/advance-boot/responsibility/userDataList',
method: 'post',
data
})
}
//执行
export function getHistoryHarmData(data: any) {
return createAxios({
url: '/harmonic-boot/harmonic/getHistoryHarmData',
method: 'post',
data
})
}
//责任详情
export function displayHistoryData(data: any) {
return createAxios({
url: '/advance-boot/responsibility/displayHistoryData',
method: 'GET',
params: data
})
}

View File

@@ -100,3 +100,19 @@ export const deleteTimer = (data: any) => {
data: data
})
}
// 关闭任务
export const stop = (params: any) => {
return request({
url: '/system-boot/timer/stop',
method: 'get',
params
})
}
// 启动任务
export const start = (params: any) => {
return request({
url: '/system-boot/timer/start',
method: 'get',
params
})
}

View File

@@ -205,7 +205,7 @@ export default {
" 发生时刻:" +
this.boxoList.startTime +
" 暂降(骤升)幅值:" +
(this.boxoList.featureAmplitude * 1).toFixed(0) +
(this.boxoList.featureAmplitude * 100).toFixed(2) +
"% 持续时间:" +
this.boxoList.duration +
"s";
@@ -231,7 +231,7 @@ export default {
" 发生时刻:" +
this.boxoList.startTime +
" 暂降(骤升)幅值:" +
(this.boxoList.featureAmplitude * 1).toFixed(0) +
(this.boxoList.featureAmplitude * 100).toFixed(2) +
"% 持续时间:" +
this.boxoList.duration +
"s";
@@ -925,7 +925,7 @@ export default {
},
title: {
left: "center",
text: "电网侧-电压 " + title,
text: title,
subtitle: {
text: "电压",
align: "left",

View File

@@ -162,7 +162,7 @@ export default {
' 发生时刻:' +
this.boxoList.startTime +
' 暂降(骤升)幅值:' +
(this.boxoList.featureAmplitude * 1).toFixed(0) +
(this.boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
this.boxoList.duration +
's'
@@ -188,7 +188,7 @@ export default {
' 发生时刻:' +
this.boxoList.startTime +
' 暂降(骤升)幅值:' +
(this.boxoList.featureAmplitude * 1).toFixed(0) +
(this.boxoList.featureAmplitude * 100).toFixed(2) +
'% 持续时间:' +
this.boxoList.duration +
's'
@@ -597,7 +597,7 @@ export default {
},
title: {
left: 'center',
text: '电网侧-电压 ' + title,
text: title,
textStyle: {
fontSize: '0.8rem',
color: _this.DColor ? '#fff' : echartsColor.WordColor

View File

@@ -8,8 +8,8 @@
<el-option v-for="item in options" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
<el-button v-if="view2 && senior" class="ml10" type="primary"
@click="AdvancedAnalytics">高级分析</el-button>
<!-- <el-button v-if="view2 && senior" class="ml10" type="primary"
@click="AdvancedAnalytics">高级分析</el-button> -->
</el-col>
<el-col :span="12">
<el-button @click="backbxlb" class="el-icon-refresh-right" icon="el-icon-CloseBold"

View File

@@ -8,8 +8,8 @@
<!-- switch -->
<el-switch v-if="field.render == 'switch'" @change="onChangeField(field, $event)"
:model-value="fieldValue.toString()" :loading="row.loading" :active-value="field.activeValue"
:inactive-value="field.inactiveValue" />
:model-value="fieldValue.toString()" :loading="row.loading" inline-prompt :active-value="field.activeValue"
:active-text="field.activeText" :inactive-value="field.inactiveValue" :inactive-text="field.inactiveText" />
<!-- image -->
<div v-if="field.render == 'image' && fieldValue" class="ba-render-image">

View File

@@ -2,7 +2,7 @@
<div :style="{ height: tableStore.table.height }">
<vxe-table ref="tableRef" height="auto" :data="tableStore.table.data" v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)" @checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent" :showOverflow="showOverflow">
@checkbox-change="selectChangeEvent" :showOverflow="showOverflow" @sort-change="handleSortChange">
<!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" />
@@ -94,6 +94,21 @@ const selectChangeEvent: VxeTableEvents.CheckboxChange<any> = ({ checked }) => {
const getRef = () => {
return tableRef.value
}
// 排序
const handleSortChange = ({ column, order }: { column: TableColumn; order: 'asc' | 'desc' | null }) => {
// console.log('排序列:', column?.property);
// console.log('排序顺序:', order);
// tableStore.onTableAction('sortable', { column, order })
tableStore.table.params.sortBy = column?.property
tableStore.table.params.orderBy = order
tableStore.table.params.pageNum = 1
tableStore.index()
// // 在这里可以根据 column 和 order 进行相应的数据排序操作
// if (order === 'asc') {
// } else if (order === 'desc') {
// }
}
watch(
() => tableStore.table.allFlag,
newVal => {

View File

@@ -1,17 +1,9 @@
<template>
<div class="point-tree">
<el-select
v-model="formData.statisticalType"
placeholder="请选择"
style="min-width: unset; padding: 10px 10px 0"
@change="loadData"
>
<el-option
v-for="item in classificationData"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
<el-select v-model="formData.statisticalType" placeholder="请选择" style="min-width: unset; padding: 10px 10px 0"
@change="loadData" v-if="props.showSelect">
<el-option v-for="item in classificationData" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
<div style="flex: 1; overflow: hidden">
<Tree ref="treeRef" :data="tree" style="width: 100%; height: 100%" :canExpand="false" v-bind="$attrs" />
@@ -26,9 +18,19 @@ import { useAdminInfo } from '@/stores/adminInfo'
import { useDictData } from '@/stores/dictData'
import { getTerminalTreeForFive } from '@/api/device-boot/terminalTree'
import { useConfig } from '@/stores/config'
import { defineProps } from 'vue'
defineOptions({
name: 'pms/pointTree'
})
interface Props {
showSelect?: boolean
}
const props = withDefaults(defineProps<Props>(), {
showSelect: true,
})
const emit = defineEmits(['init'])
const attrs = useAttrs()

View File

@@ -8,9 +8,14 @@
size="18"
/>
</div>
<span class="nav-bar-title">{{ getTheme.name }} <span style="font-size: 14px;" v-if="Version?.versionName">
<span class="nav-bar-title">{{ getTheme.name }}
<span style="font-size: 14px;" >
(v1.0.0)
</span>
<!-- <span style="font-size: 14px;" v-if="Version?.versionName">
({{ Version?.versionName }})
</span></span>
</span> -->
</span>
<NavMenus />
</div>
</template>

View File

@@ -161,6 +161,41 @@ export const adminBaseRoute = {
// },
]
},
{
path: 'division',
name: '谐波责任划分页面',
meta: {
title: pageTitle('division'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'aListOfLoadData',
component: () => import('@/views/pqs/harmonicMonitoring/detailed/division/components/aListOfLoadData.vue'),
name: '负荷数据列表页面',
meta: {
title: pageTitle('router.aListOfLoadData')
}
},{
path: 'compute',
component: () => import('@/views/pqs/harmonicMonitoring/detailed/division/components/compute.vue'),
name: '贡献度计算页面',
meta: {
title: pageTitle('router.compute')
}
},
{
path: 'detail',
component: () => import('@/views/pqs/harmonicMonitoring/detailed/division/components/detail.vue'),
name: 'detail',
meta: {
title: pageTitle('router.detail')
}
},
]
},
{
path: '/boX',
name: 'boX',

View File

@@ -93,11 +93,11 @@ const tableStore = new TableStore({
return eventList.filter(item => item.id === row.cellValue)[0]?.name
}
},
{
field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => {
return row.cellValue.toFixed(2)
}
},
// {
// field: 'severity', title: '严重度', minWidth: "80", formatter: (row: any) => {
// return row.cellValue.toFixed(2)
// }
// },
{
field: 'featureAmplitude', title: '暂降幅值(%)',minWidth: "90", formatter: (row: any) => {
return (row.cellValue * 100).toFixed(2)

View File

@@ -0,0 +1,164 @@
<!-- 负荷数据列表 -->
<template>
<div class="default-main" :style="height">
<div class="title">
负荷数据列表
<back-component />
</div>
<TableHeader :showReset="false" ref="TableHeaderRef">
<template #select>
<el-form-item label="关键字">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
</el-form-item>
</template>
<template #operation>
<el-button type="primary" icon="el-icon-Plus" @click="dialogVisible = true">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef"></Table>
<!-- 详情 -->
<completenessDetails ref="completenessDetailsRef" />
<el-dialog v-model="dialogVisible" title="上传数据" width="500" :before-close="handleClose">
<el-upload ref="upload" action="" v-model:file-list="fileList" accept=".xlsx,.xls" :auto-upload="false"
:on-change="choose" :limit="2">
<el-button type="primary" class="ml10" icon="el-icon-Upload">上传文件</el-button>
</el-upload>
<template #footer>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="submitupload">
确认
</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang='ts'>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { mainHeight } from '@/utils/layout'
import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import Table from '@/components/table/index.vue'
import BackComponent from '@/components/icon/back/index.vue'
import completenessDetails from './completenessDetails.vue'
import { genFileId, ElMessage } from 'element-plus'
import { uploadUserData } from '@/api/advance-boot/division'
import type { UploadInstance, UploadProps, UploadRawFile, } from 'element-plus'
const height = mainHeight(20)
const completenessDetailsRef = ref()
const dialogVisible = ref(false)
const upload = ref<UploadInstance>()
const fileList = ref([])
const tableStore = new TableStore({
url: '/advance-boot/responsibility/userDataList',
method: 'POST',
publicHeight: 52,
column: [
{ title: '表名', field: 'name' },
{ title: '起始时间', field: 'startTime' },
{ title: '截止时间', field: 'endTime' },
{ title: '更新时间', field: 'updateTime' },
{
title: '操作',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '完整性详情',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
completenessDetailsRef.value.open(row.id)
}
},
{
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除吗?'
},
click: row => {
// deleteByIds([row.id]).then(() => {
// ElMessage.success('删除成功')
// tableStore.index()
// })
}
}
]
}
],
loadCallback: () => { }
})
const handleClose = () => {
fileList.value = []
dialogVisible.value = false
}
// 上传
const choose = (e: any) => {
upload.value!.clearFiles()
setTimeout(() => {
if (e.name.includes('.xls')) {
fileList.value = [e]
} else {
ElMessage.warning('请上传Excel文件')
}
}, 0)
}
// 上传
const submitupload = () => {
if (fileList.value.length == 0) {
ElMessage.warning('请上传文件!')
return
}
const formData = new FormData()
formData.append('file', fileList.value[0].raw)
uploadUserData(formData).then(res => {
ElMessage.success('上传成功')
handleClose()
tableStore.index()
})
}
provide('tableStore', tableStore)
tableStore.table.params.searchValue = ''
onMounted(() => {
tableStore.index()
})
</script>
<style lang="scss" scoped>
.title {
display: flex;
justify-content: space-between;
padding: 10px;
font-size: 16px;
font-weight: 550;
}
:deep(.upload-demo) {
display: flex;
.el-upload-list__item-info {
width: 300px;
}
}
</style>

View File

@@ -0,0 +1,65 @@
<template>
<el-dialog v-model="dialogVisible" title="完整性不足详情" width="1000">
<TableHeader :showReset="false" ref="TableHeaderRef">
<template #select>
<el-form-item label="关键字">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
</el-form-item>
</template>
<template #operation>
<!-- <el-button type="primary" icon="el-icon-Plus">新增</el-button> -->
<!-- <back-component /> -->
</template>
</TableHeader>
<Table ref="tableRef"></Table>
</el-dialog>
</template>
<script setup lang='ts'>
import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import Table from '@/components/table/index.vue'
import { mainHeight } from '@/utils/layout'
import { ref, reactive } from 'vue'
const num = ref(0)
const dialogVisible = ref(false)
const tableStore = new TableStore({
url: '/advance-boot/responsibility/userDataIntegrityList',
method: 'POST',
publicHeight: 547,
column: [
{ title: '数据名', field: 'name' },
{ title: '用户名', field: 'userName' },
{ title: '测量点局号', field: 'lineNo' },
{ title: '日期', field: 'upDataTime' },
{ title: '完整性', field: 'integrity' },
],
loadCallback: () => {
setTimeout(() => {
tableStore.table.height = mainHeight(0,2).height as any
// console.log("🚀 ~ setTimeout ~ tableStore.table.height:", tableStore.table.height)
}, 0)
// setTimeout(() => { tableStore.table.height = 'calc((100vh) / 2)'}, 1000)
}
})
provide('tableStore', tableStore)
tableStore.table.params.searchValue = ''
const open = (id: string) => {
tableStore.table.params.userDataId = id
dialogVisible.value = true
tableStore.index()
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,199 @@
<!-- 贡献度计算 -->
<template>
<div class="default-main" :style="height">
<div class="title">
贡献度计算
<div style="font-size: 14px;font-weight: 500;">
{{ dotList.alias || '' }}
<back-component />
</div>
</div>
<splitpanes :style='heightB' class='default-theme' id='navigation-splitpanes'>
<pane :size='size'>
<PointTree :showSelect="false" :default-expand-all='false' @node-click='handleNodeClick'
@init='handleNodeClick'>
</PointTree>
</pane>
<pane style='background: #fff' :style='heightB' :size="100 - size">
<el-form :model="form" inline label-width="auto">
<el-form-item label="谐波类型:">
<el-radio-group v-model="form.type">
<el-radio-button label="谐波电压" value="1" />
<el-radio-button label="谐波电流" value="0" />
</el-radio-group>
</el-form-item>
<el-form-item label="谐波次数:">
<el-select v-model="form.index" filterable multiple :multiple-limit="5" collapse-tags
collapse-tags-tooltip clearable placeholder="请选择次数">
<el-option v-for="item in harmonic" :key="item.value" :label="item.label"
:value="item.value"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="负荷数据:">
<el-select v-model="form.loadData" clearable filterable placeholder="请选择负荷数据">
<el-option v-for="item in loadDataOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-Plus"
@click="push('/admin/division/aListOfLoadData')">新增</el-button>
<el-button type="primary" icon="el-icon-Select" @click="submit">确定</el-button>
</el-form-item>
</el-form>
<el-tabs v-model="activeName" type="card" class="demo-tabs" v-if="showTabs">
<el-tab-pane v-for="(item, index) in tabList" :key="item" :label="item.label" :name="index">
<div class="pd10">
<div>
<span style="color: var(--el-text-color-regular);">时间范围:</span>
<el-date-picker v-model="item.time" class="mr10 ml10" type="daterange"
start-placeholder="起始时间" end-placeholder="结束时间" format="YYYY-MM-DD"
date-format="YYYY-MM-DD" time-format="YYYY-MM-DD" />
<el-button type="primary" icon="el-icon-CaretRight" @click="execute(item,index)">执行</el-button>
</div>
<div v-if="item.showExecute">
<el-form :inline="true" v-model="item.form" class="mt10">
<el-form-item label="限值:">
<el-input v-model="item.form.limit" placeholder="请输入限值" />
</el-form-item>
<el-form-item label="时间点一:"> <el-input v-model="item.form.time1"
placeholder="请输入时间点一" /></el-form-item>
<el-form-item label="时间点二:"> <el-input v-model="item.form.time2"
placeholder="请输入时间点二" /></el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-Document">
生成动态谐波责任数据
</el-button>
<el-button type="primary" icon="el-icon-Document">
生成谐波责任指标
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</el-tab-pane>
</el-tabs>
</pane>
</splitpanes>
</div>
</template>
<script setup lang='ts'>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { mainHeight } from '@/utils/layout'
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes'
import PointTree from '@/components/tree/pqs/pointTree.vue'
import BackComponent from '@/components/icon/back/index.vue'
import { harmonicOptions, } from '@/utils/dictionary'
import { userDataList } from '@/api/advance-boot/division'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { formatDate } from '@/utils/formatTime'
import {getHistoryHarmData} from '@/api/advance-boot/division';
const { push } = useRouter()
const dotList: any = ref({})
const height = mainHeight(20)
const heightB = mainHeight(70)
const harmonic = harmonicOptions.slice(1)
const size = ref(0)
const showTabs = ref(false)
const loadDataOptions: any = ref([])
const form: any = reactive({
type: '0',
index: [],
loadData: ''
})
const tabList: any = ref([])
const activeName = ref(0)
const handleNodeClick = (data: any, node: any) => {
console.log("🚀 ~ handleNodeClick ~ data:", data)
if (data.level == 6) {
dotList.value = data
}
}
// 确定
const submit = () => {
if (form.loadData == '') {
return ElMessage.warning('请选择负荷数据')
}
if (form.index.length == 0) {
showTabs.value = false
} else {
let timeList = loadDataOptions.value.filter((item: any) => item.id == form.loadData)[0]
console.log("🚀 ~ submit ~ timeList:", timeList)
showTabs.value = true
let list = JSON.parse(JSON.stringify(form.index))
tabList.value = []
list.forEach((item: any) => {
tabList.value.push({
label: item + '次谐波',
key: item,
time: [timeList.startTime, timeList.endTime],
showExecute: false,
form: {
limit: '',
time1: '',
time2: ''
}
})
})
// tabList.value =
activeName.value = 0
}
}
// 执行
const execute = (item: any, index: number) => {
getHistoryHarmData({
searchBeginTime:item.time[0],
searchEndTime:item.time[1],
type:form.type,
time:item.key,
// userDataId:form.loadData,
lineId:dotList.value.id
}).then((res: any) => {
})
tabList.value[index].showExecute = true
}
onMounted(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = Math.round((180 / dom.offsetHeight) * 100)
}
userDataList({
pageNum: 1,
pageSize: 10000,
searchValue: ""
}).then((res: any) => {
loadDataOptions.value = res.data.records
})
})
</script>
<style lang="scss" scoped>
.title {
display: flex;
justify-content: space-between;
padding: 10px;
font-size: 16px;
font-weight: 550;
}
:deep(.upload-demo) {
display: flex;
.el-upload-list__item-info {
width: 300px;
}
}
</style>

View File

@@ -0,0 +1,53 @@
<!-- 详情 -->
<template>
<div class="default-main" :style="height">
<div class="title">
详情
<div style="font-size: 14px;font-weight: 500;">
{{ query.name || '' }}
<back-component />
</div>
</div>
</div>
</template>
<script setup lang='ts'>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { mainHeight } from '@/utils/layout'
import { displayHistoryData } from '@/api/advance-boot/division';
import BackComponent from '@/components/icon/back/index.vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { id } from 'element-plus/es/locale';
const { query } = useRoute() // 查询参数
const dotList: any = ref({})
const height = mainHeight(20)
const tabList: any = ref([])
const init = () => {
displayHistoryData({
id: query.id,
time:query.time
})
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
.title {
display: flex;
justify-content: space-between;
padding: 10px;
font-size: 16px;
font-weight: 550;
}
</style>

View File

@@ -0,0 +1,115 @@
<template>
<div class="default-main">
<!-- 模版 -->
<TableHeader datePicker showExport :showReset="false" ref="TableHeaderRef">
<template #select>
<el-form-item label="关键字">
<el-input v-model="tableStore.table.params.searchValue" clearable placeholder="请输入关键字" />
</el-form-item>
</template>
<template #operation>
<el-button type="primary" icon="el-icon-CreditCard"
@click="push('/admin/division/compute')">谐波贡献度计算</el-button>
<el-button type="primary" icon="el-icon-Tickets"
@click="push('/admin/division/aListOfLoadData')">负荷数据列表</el-button>
</template>
</TableHeader>
<Table ref="tableRef"></Table>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import { ElMessage } from 'element-plus'
import Table from '@/components/table/index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { deleteByIds } from '@/api/advance-boot/division'
import { useRouter } from 'vue-router'
const { push } = useRouter()
defineOptions({
name: 'liabiiyty'
})
const TableHeaderRef = ref()
const tableStore = new TableStore({
url: '/advance-boot/responsibility/responsibilityList',
method: 'POST',
column: [
{ title: '供电公司', field: 'gdName' },
{ title: '变电站', field: 'subName' },
{ title: '终端名称', field: 'devName' },
{ title: 'IP', field: 'ip' },
{ title: '监测点名称', field: 'lineName' },
{ title: '类型', field: 'dataType' },
{ title: '谐波次数', field: 'dataTimes' },
{ title: '用采数据', field: 'userDataName' },
{ title: '计算时间', field: 'updateTime' },
{ title: '计算窗口', field: 'timeWindow' },
{
title: '操作',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '查看详情 ',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
console.log("🚀 ~ row:", row)
// push('/admin/division/detail')
push({
path: "/admin/division/detail",
query: {
id: row.id,
time: row.dataTimes,
name: `${row.gdName}>${row.subName}>${row.devName}>${row.lineName}`
}
})
}
},
{
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除吗?'
},
click: row => {
deleteByIds([row.id]).then(() => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => { }
})
tableStore.table.params.searchValue = ''
// 弹框
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
</script>
<style lang="scss"></style>

View File

@@ -23,9 +23,9 @@
<el-tab-pane label="谐波频谱" name="4" lazy v-if="!isReload">
<Xiebopingpu />
</el-tab-pane>
<el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload">
<!-- <el-tab-pane label="告警数据统计" name="5" lazy v-if="!isReload">
<Gaojingshujutongji />
</el-tab-pane>
</el-tab-pane> -->
<el-tab-pane label="监测点运行状态" name="6" lazy v-if="!isReload">
<Yunxingzhuangtai />
</el-tab-pane>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@
<div class="collapse_none" style="color: red;cursor: pointer" @click="showWrap = false">关闭</div>
</div>
<baidu-map class="map" :style="height" @ready="initMap" @zoomend='syncCenterAndZoom' :center="center"
:zoom="zoomMap" :scroll-wheel-zoom='true'>
:zoom="zoomMap" :scroll-wheel-zoom='true' >
<!-- 线-->
<div v-if='zoom > 13'>
<bm-polyline :path='path' v-for='(path, index) in polyline' :key='index'></bm-polyline>
@@ -55,7 +55,7 @@
@click='markerClick(path)'></bm-marker>
</template>
<!-- 点 -->
<BmlMarkerClusterer maxZoom='12' v-if='zoom > 9'>
<div :maxZoom='12' v-if='zoom > 9'>
<bm-marker :position='path' v-for='path in areaLineInfo' :key='path.lineId' :icon='path.icon'
@click='markerClick(path)' :zIndex="1">
@@ -64,7 +64,7 @@
:offset="{ height: 33 }" />
</bm-marker>
</BmlMarkerClusterer>
</div>
<!-- 详情 -->
<bm-marker :position='infoWindowPoint' :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show='infoWindowPoint.show' @close='infoWindowPoint.show = false'>
@@ -98,8 +98,43 @@
</bm-info-window>
</bm-marker>
<!-- 行政区划 -->
<!-- <bm-boundary v-for="item in boundaryList" :name="item.name" :strokeWeight="2" strokeColor="#0e8780"
fillColor="#0e8780" fillOpacity="0.05"></bm-boundary> -->
<div v-if='zoom <= 11'>
<div v-for="item in AreaData">
<bm-polygon v-for="timeK in item.boundary" :path="timeK" :strokeWeight="2" strokeColor="#fff"
:strokeOpacity="1" :fillColor="item.background || ''" :fillOpacity="0.5"></bm-polygon>
</div>
</div>
<!-- 信息弹框 -->
<div v-if='zoom <= 9'>
<bm-overlay v-for="item in AreaData" pane="labelPane" :class="{ sample: true, }"
@draw="draw($event, item.LngLat)">
<div class="my-radiusPop" :style="{ background: item.background }">
<img :src="PopKey == 2 ? imgUrl2 : PopKey == 1 ? imgUrl1 : PopKey == 0 ? imgUrl0 : ''" />
<div class="infoBox">
<div>
总数<br />{{ PopKey == 2 ? item.lineNum : PopKey == 1 ? item.deviceNum : PopKey == 0 ?
item.subNum :
'/' }}
</div>
<div>
{{ PopKey == 2 ? '在线' : PopKey == 1 ? '在运' : '告警' }}<br />{{ PopKey == 2 ?
item.onlineNum :
PopKey
== 1
?
item.alarmSubNum : PopKey == 0 ?
item.onDevice : '/' }}
</div>
<div v-if="PopKey == 2">
告警<br />{{ PopKey == 2 ? item.alarm : PopKey == 1 ? item.xx : PopKey == 0 ? item.xx :
'/' }}
</div>
</div>
</div>
</bm-overlay>
</div>
</baidu-map>
@@ -113,9 +148,11 @@ import { ref, reactive, onMounted } from 'vue'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useDictData } from '@/stores/dictData'
import { Search } from '@element-plus/icons-vue'
import { BaiduMap, BmBoundary, BmPolygon } from 'vue-baidu-map-3x'
import { BaiduMap, BmOverlay } from 'vue-baidu-map-3x'
import { getAssessOverview } from '@/api/device-boot/panorama'
import { getGridDiagramAreaData } from '@/api/device-boot/panorama'
const emit = defineEmits(['changeValue', 'drop', 'show'])
import mapJson from './boundary';
const datePickerRef = ref()
const height = mainHeight(20)
// 页面中直接引入就可以
@@ -123,18 +160,44 @@ const dictData = useDictData()
const inputQuery: any = ref('')
const QueryList: any = ref([])
const activeName: any = ref(0)
const zoomMap = ref(9)
const zoomMap = ref(8.8)
const colorKey = ref('')
const showCollapse: any = ref(true)
const showWrap: any = ref(false)
const deptIndex = ref(dictData.state.area[0].id)
const boundaryList = ref([
{ name: '张家口市' },
{ name: '唐山市' },
{ name: '秦皇岛市' },
{ name: '承德市' },
{ name: '廊坊市' },
const assessList: any = ref([])
const AreaData: any = ref([])
const PopKey: any = ref(2)
const imgUrl0 = new URL('@/assets/img/BDZ-ZS.png', import.meta.url).href
const imgUrl1 = new URL('@/assets/img/ZD-ZS.png', import.meta.url).href
const imgUrl2 = new URL('@/assets/img/JCD-ZS.png', import.meta.url).href
const boundaryList: any = ref([
{
orgName: '唐山',
LngLat: [118.335849137, 39.7513593355],
boundary: mapJson.tsJSON
},
{
orgName: '张家口',
LngLat: [115.032504679, 40.8951549951],
boundary: mapJson.zjkJSON
},
{
orgName: '秦皇岛',
LngLat: [119.185113833, 40.1179119754],
boundary: mapJson.qhdJSON
},
{
orgName: '承德',
LngLat: [117.548498365, 41.3775890632],
boundary: mapJson.cdJSON
},
{
orgName: '廊坊',
LngLat: [116.628004129, 39.0589378611],
boundary: mapJson.lfJSON
}
])
const zoom = ref(13)
@@ -143,7 +206,7 @@ const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const center = ref({
lng: 116.403765, lat: 39.914850
lng: 116.84428600000001, lat: 40.57707185292256
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
@@ -310,18 +373,90 @@ const DeviceQ = () => {
}
// 定位
const flyTo = (e: any) => {
console.log("🚀 ~ flyTo ~ e:", e)
const flyTo = (e: any, zoom?: number) => {
let regex = new RegExp(e.psrName, 'i')
center.value.lng = e.coordinate[0]
center.value.lat = e.coordinate[1]
zoomMap.value = 15
let data = areaLineInfo.value.filter((item: any) => regex.test(item.lineName))[0]
if (data) {
markerClick(data)
if (zoom) { zoomMap.value = zoom }
else {
zoomMap.value = 15
let data = areaLineInfo.value.filter((item: any) => regex.test(item.lineName))[0]
if (data) {
markerClick(data)
}
}
}
// 市级统计数据
const grids = (row: any) => {
let form = {
...row,
id: row.orgNo,
deptIndex: row.orgNo,
orgId: row.orgNo,
ids: [],
statisticalType: dictData.getBasicData('Statistical_Type', ['Report_Type'])[0],
isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
}
AreaData.value=[]
assessList.value=[]
// 综合评估
getAssessOverview(form).then(res => {
assessList.value = res.data?.children
getGridDiagramAreaData({ ...form, deptIndex: deptIndex.value }).then((res: any) => {
AreaData.value = res.data
GridDiagramArea()
})
// if (powerManageGridMap.value) powerLoad()
})
}
const radiusPop = (k: any) => {
console.log("🚀 ~ radiusPop ~ k:", k)
if (k != undefined) PopKey.value = k
}
const GridDiagramArea = () => {
boundaryList.value.forEach((item: any) => {
assessList.value.forEach((y: any) => {
if (item.orgName == y.name) {
if (y.score == 3.14159) {
} else if (y.score > 4.5) {
item.background = '#33996699'
} else if (y.score > 4) {
item.background = '#3399ff99'
} else if (y.score > 3) {
item.background = '#ffcc3399'
} else if (y.score > 2) {
item.background = '#db088799'
} else if (y.score > 0) {
item.background = '#ff000099'
}
}
})
AreaData.value.forEach((k: any, i: any) => {
if (item.orgName == k.orgName) {
for (let kk in item) {
k[kk] = item[kk]
}
}
})
})
AreaData.value = AreaData.value.filter((item: any) => item.orgName != '超高压' && item.orgName != '风光储')
setTimeout(() => {
// radiusPop()
}, 0)
}
// 市级统计
const draw = ({ el, BMap, map }, val) => {
const pixel = map.pointToOverlayPixel(new BMap.Point(val[0], val[1]))
el.style.left = pixel.x - 60 + 'px'
el.style.top = pixel.y - 20 + 'px'
}
// 重置
const reset = () => {
@@ -330,7 +465,7 @@ const reset = () => {
}
onMounted(() => {
})
defineExpose({ addMarkers, locatePositions, reset })
defineExpose({ addMarkers, locatePositions, reset, grids, radiusPop, flyTo })
</script>
<style lang="scss" scoped>
@use '@/views/pqs/qualityInspeection/panorama/components/style/map.scss';
@@ -348,4 +483,38 @@ defineExpose({ addMarkers, locatePositions, reset })
padding-bottom: 0px !important;
}
// @use '@/views/pqs/panorama/components/style/map.scss';</style>
.sample {
position: absolute;
.my-radiusPop {
width: 200px;
height: 50px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.5);
overflow: hidden;
// box-shadow: 0 0 5px #000;
color: #fff;
text-align: center;
padding: 5px 5px !important;
display: flex;
img {
height: 40px;
margin-right: 10px;
}
.infoBox {
flex: 1;
display: flex;
justify-content: space-around;
text-align: center;
div {
cursor: pointer;
}
}
}
}
</style>
./cds.js./boundary

View File

@@ -169,32 +169,7 @@
font-size: 16px;
}
}
:deep(.my-radiusPop) {
.sgmap-popup-tip {
display: none;
}
.sgmap-popup-content {
width: 200px;
height: 50px;
border-radius: 5px;
padding: 5px 5px !important;
background-color: #00000000;
color: #fff;
}
img {
height: 40px;
margin-right: 10px;
}
.infoBox {
flex: 1;
display: flex;
justify-content: space-around;
text-align: center;
div {
cursor: pointer;
}
}
}
#nrDeviceCard {
position: absolute;

View File

@@ -167,7 +167,7 @@ const GridDiagram = (k?: number, num?: number) => {
if (value) VITE_FLAG ? mapRef.value.flyTo({ coordinate: value.LngLat }, value.zoom) : ''
} else {
VITE_FLAG ? mapRef.value.flyTo({ coordinate: [116.84428600000001, 40.57707185292256] }, 6.709267680647425) : ''
VITE_FLAG ? mapRef.value.flyTo({ coordinate: [116.84428600000001, 40.57707185292256] }, 8) : ''
}
}
const info = () => {
@@ -176,9 +176,9 @@ const info = () => {
form.value.endTime = datePickerRef.value.timeValue[1]
form.value.searchEndTime = datePickerRef.value.timeValue[1]
form.value.type = datePickerRef.value.interval
form.value.type = 1//datePickerRef.value.interval
// VITE_FLAG ? mapRef.value.grids(form.value) : ''
VITE_FLAG ? mapRef.value.grids(form.value) : ''
if (control.value == 1) {
mapLRef.value.info(form.value)
mapRRef.value.info(form.value)
@@ -249,14 +249,14 @@ onMounted(() => {
.mapL {
position: absolute;
top: 10px;
top: 5px;
// z-index: 1;
left: 10px;
}
.mapR {
position: absolute;
top: 10px;
top: 5px;
// z-index: 1;
right: 10px;
}

View File

@@ -72,8 +72,8 @@
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="download">下载波形</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
<!-- <el-button icon="el-icon-Download" type="primary" @click="download">下载波形</el-button> -->
<!-- <el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button> -->
</template>
</TableHeader>
<Table ref="tableRef" />
@@ -151,16 +151,16 @@ const tableStore = new TableStore({
{ field: 'ip', title: '网络参数', minWidth: '200' },
{ field: 'lineName', title: '监测点', minWidth: '100' },
{ field: 'scale', title: '电压等级(kV)', minWidth: '120', },
{
field: 'verifyReason', title: '暂降核实原因', minWidth: '120', formatter: function (row) {
return verifyReasonList.filter(item => item.id == row.cellValue)[0]?.name || '/' //row.cellValue ? row.cellValue : '/'
}
},
{
field: 'verifyReasonDetail', title: '暂降核实原因详情', minWidth: '200', formatter: function (row) {
return row.cellValue ? row.cellValue : '/'
}
},
// {
// field: 'verifyReason', title: '暂降核实原因', minWidth: '120', formatter: function (row) {
// return verifyReasonList.filter(item => item.id == row.cellValue)[0]?.name || '/' //row.cellValue ? row.cellValue : '/'
// }
// },
// {
// field: 'verifyReasonDetail', title: '暂降核实原因详情', minWidth: '200', formatter: function (row) {
// return row.cellValue ? row.cellValue : '/'
// }
// },
{
field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)',
@@ -187,7 +187,7 @@ const tableStore = new TableStore({
},
{ field: 'duration', title: '持续时间(s)', minWidth: '100' },
{ field: 'severity', title: '严重度', minWidth: '100', formatter: ({ row }: any) => (row.severity < 0 ? '/' : row.severity) },
// { field: 'severity', title: '严重度', minWidth: '100', formatter: ({ row }: any) => (row.severity < 0 ? '/' : row.severity) },
{
title: '操作',
@@ -195,16 +195,16 @@ const tableStore = new TableStore({
render: 'buttons',
fixed: 'right',
buttons: [
{
name: 'edit',
title: '人工维护',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: async row => {
addFormRef.value.open(row)
}
},
// {
// name: 'edit',
// title: '人工维护',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: async row => {
// addFormRef.value.open(row)
// }
// },
{
name: 'edit',
title: '波形分析',

View File

@@ -3,9 +3,9 @@
<div v-show="view">
<!-- 表头 -->
<TableHeader date-picker showExport>
<template v-slot:operation>
<el-button :icon='Download' type='primary' @click='download'>波形下载</el-button>
</template>
<!-- <template v-slot:operation>
<el-button :icon='Download' type='primary' @click='download'>下载波形</el-button>
</template> -->
</TableHeader>
<!-- 表格 -->
<Table ref='tableRef' :checkboxConfig='checkboxConfig' />
@@ -61,12 +61,13 @@ const tableStore = new TableStore({
}
},
{
title: '暂降(骤升)幅值(%)', field: 'featureAmplitude', minWidth: '80', formatter: (row: any) => {
return (row.cellValue * 100).toFixed(0)
}
title: '暂降(骤升)幅值(%)', field: 'featureAmplitude', minWidth: '120', formatter: (row: any) => {
return (row.cellValue * 100).toFixed(2)
},
},
{ title: '持续时间(s)', field: 'duration', minWidth: '80' },
{ title: '严重度', field: 'severity', minWidth: '80' },
// { title: '严重度', field: 'severity', minWidth: '80' },
{
title: '操作',
width: '180',

View File

@@ -103,7 +103,7 @@ const tableStore = new TableStore({
title: '持续时间(s)',
width: '100'
},
{ field: 'severity', title: '严重度' }
// { field: 'severity', title: '严重度' }
],
})

View File

@@ -35,44 +35,44 @@ const height = mainHeight(80).height
const activeName = ref('1')
const activeName1 = ref('1')
const list = ref([
{
name: '暂态严重度统计',
id: '3',
isGroup: true,
url: '/event-boot/report/getSeverity',
column: [
{
title: '暂态事件严重度(前二十)',
children: [
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (
(tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize +
row.rowIndex +
1
)
}
},
{ field: 'startTime', title: '暂态事件发生时刻', width: '200' },
{ field: 'gdName', title: '供电公司' },
{ field: 'subName', title: '变电站' },
{ field: 'lineName', title: '监测点' },
{ field: 'voltageScale', title: '监测点电压等级' },
{ field: 'loadType', title: '干扰源类型' },
{
field: 'featureAmplitude',
title: '暂降(骤升)幅值(%)',
formatter: ({ row }: any) => (row.featureAmplitude * 100).toFixed(2)
},
{ field: 'duration', title: '持续时间(s)' },
{ field: 'severity', title: '暂态事件严重度' }
]
}
]
},
// {
// name: '暂态严重度统计',
// id: '3',
// isGroup: true,
// url: '/event-boot/report/getSeverity',
// column: [
// {
// title: '暂态事件严重度(前二十)',
// children: [
// {
// field: 'index',
// title: '序号',
// width: '80',
// formatter: (row: any) => {
// return (
// (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize +
// row.rowIndex +
// 1
// )
// }
// },
// { field: 'startTime', title: '暂态事件发生时刻', width: '200' },
// { field: 'gdName', title: '供电公司' },
// { field: 'subName', title: '变电站' },
// { field: 'lineName', title: '监测点' },
// { field: 'voltageScale', title: '监测点电压等级' },
// { field: 'loadType', title: '干扰源类型' },
// {
// field: 'featureAmplitude',
// title: '暂降(骤升)幅值(%)',
// formatter: ({ row }: any) => (row.featureAmplitude * 100).toFixed(2)
// },
// { field: 'duration', title: '持续时间(s)' },
// { field: 'severity', title: '暂态事件严重度' }
// ]
// }
// ]
// },
{
name: '详细事件列表',
id: '4',

View File

@@ -44,7 +44,7 @@ import TableHeader from '@/components/table/header/index.vue'
import taskForm from '@/views/system/scheduledTasks/form.vue'
import { formatDate } from '@/utils/formatTime'
import { ElMessage, ElMessageBox, ElDatePicker } from 'element-plus'
import { timerRun, runTimer, deleteTimer } from '@/api/system-boot/csDictData'
import { timerRun, runTimer, deleteTimer, stop, start } from '@/api/system-boot/csDictData'
defineOptions({
name: 'Distributedphotovoltaic/templateConfiguration'
})
@@ -64,18 +64,43 @@ const tableStore: any = new TableStore({
{ field: 'actionClass', title: '任务执行器' },
{ field: 'cron', title: '定时任务表达式' },
{ field: 'remark', title: '备注' },
// {
// field: 'jobStatus', title: '状态', width: '100',
// render: 'tag',
// custom: {
// 0: 'danger',
// 1: 'success',
// 2: 'danger'
// },
// replaceValue: {
// 0: '未启动',
// 1: '运行中',
// 2: '未启动',
// }
// },
{
field: 'jobStatus', title: '状态', width: '100',
render: 'tag',
custom: {
0: 'danger',
1: 'success',
2: 'danger'
},
replaceValue: {
0: '未启动',
1: '运行中',
2: '未启动',
title: '状态',
render: 'switch',
width: 100,
field: 'jobStatus',
activeText: '运行中',
activeValue: '1',
inactiveText: '未启动',
inactiveValue: '2',
onChangeField: (row: any, value: any) => {
if (row.jobStatus == 1) {
stop({ id: row.id }).then(res => {
ElMessage.success(res.message)
tableStore.index()
})
}else{
start({ id: row.id }).then(res => {
ElMessage.success(res.message)
tableStore.index()
})
}
}
},
{ field: 'sort', title: '排序', width: '80' },
@@ -141,7 +166,7 @@ const tableStore: any = new TableStore({
title: '确定删除?'
},
click: row => {
deleteTimer([row.id ]).then(res => {
deleteTimer([row.id]).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})

View File

@@ -33,7 +33,7 @@
</el-form-item>
<el-form-item label="版本类型">
<el-select v-model.trim="form.versionType" placeholder="please select your zone">
<el-select v-model.trim="form.versionType" placeholder="请选择版本类型">
<el-option label="web" value="WEB" />
<el-option label="app" value="APP" />
</el-select>

2
types/table.d.ts vendored
View File

@@ -66,6 +66,8 @@ declare global {
onChangeField?: (row: TableRow, value: any) => void
activeValue?: string
inactiveValue?: string
activeText?: string
inactiveText?: string
// 自定义组件/函数渲染
customRender?: string | Component
// 使用了 render 属性时,渲染前对字段值的预处理方法,请返回新值

View File

@@ -25,7 +25,7 @@ export default defineConfig({
'/api': {
// target: 'http://10.95.53.49:10215', //海南服务器ip
// target: 'http://10.118.135.128:10215', ///hsw
target: 'http://192.168.1.81:10215', ///hsw
target: 'http://192.168.1.29:10215', ///hsw
// target: 'http://10.119.65.152:10215', //数据中心
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '') //路径重写,把'/api'替换为''