前置管理 新增重置功能

前置交互日志 新增详情查询功能
This commit is contained in:
guanj
2025-09-03 20:57:28 +08:00
parent 0067b63536
commit f251ad3fe6
20 changed files with 3425 additions and 3062 deletions

View File

@@ -1,42 +1,50 @@
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
})
}
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 deleteUserDataByIds(data: any) {
return createAxios({
url: '/advance-boot/responsibility/deleteUserDataByIds',
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

@@ -1,184 +1,192 @@
import createAxios from '@/utils/request'
// 新增菜单接口
export function addNode(data: any) {
return createAxios({
url: '/device-boot/node/addNode',
method: 'post',
data: data
})
}
//修改前置机
export function updateNode(data: any) {
return createAxios({
url: '/device-boot/node/updateNode',
method: 'put',
data: data
})
}
//删除前置机
export function delNode(data: any) {
return createAxios({
url: '/device-boot/node/delNode',
method: 'post',
params: { id: data }
})
}
//终端台账树
export function getTerminalTree() {
return createAxios({
url: '/device-boot/terminalTree/getTerminalTree',
method: 'get'
})
}
/**
* 总计出3层提供给表单选择具体的终端、母线、监测点
* 终端台账树
* 等级0-项目名称1- 用户名称2-单位3-部门4-终端5-母线6-监测点
*/
export function getTerminalSelectTree(level: number) {
return createAxios({
url: '/device-boot/terminalTree/getTerminalSelectTree?level=' + level,
method: 'get'
})
}
//查询节点内容
export function queryTerminal(data: any) {
return createAxios({
url: `/device-boot/device/queryTerminal`,
method: 'get',
params: data
})
}
//删除终端
export function delTerminal(data: any) {
return createAxios({
url: `/device-boot/device/delTerminal`,
method: 'delete',
params: data
})
}
//获取前置机
export function nodeAllList() {
return createAxios({
url: '/device-boot/node/nodeAllList',
method: 'get'
})
}
//修改数据
export function updateTerminal(query: any) {
return createAxios({
url: `/device-boot/device/updateTerminal`,
method: 'put',
data: {
...query
}
})
}
//提交数据
export function addTerminal(query: any) {
return createAxios({
url: '/device-boot/device/addTerminal',
method: 'post',
data: {
...query
}
})
}
//查询终端程序版本升级日志
export function getTerminalUpLog(data: any) {
return createAxios({
url: '/device-boot/version/getTerminalUpLog',
method: 'post',
params: data
})
}
//查询新能源场站
export function selectDown() {
return createAxios({
url: '/device-boot/newStation/selectDown',
method: 'get'
})
}
//获取用户大类小类
export function queryAllByType(params: any) {
return createAxios({
url: '/system-boot/dictTree/queryAllByType',
method: 'get',
params
})
}
//获取用户
export function selectUserList(data: any) {
return createAxios({
url: '/supervision-boot/userReport/selectUserList',
method: 'post',
data
})
}
//查询列表
export function getStatusManageList(data: any) {
return createAxios({
url: '/device-boot/maintain/getStatusManageList',
method: 'post',
data
})
}
//设置终端状态
export function updateRunFlagManage(data: any) {
return createAxios({
url: '/device-boot/maintain/updateRunFlagManage',
method: 'post',
data
})
}
//设置终端日志
export function getList(data: any) {
return createAxios({
url: '/device-boot/pqsTerminalLogs/getList',
method: 'post',
data
})
}
//查询前置-进程-设备-设备树
export function nodeDeviceTree(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/nodeDeviceTree',
method: 'post',
params: data
})
}
//更新设备进程号
export function updateDeviceProcess(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/updateDeviceProcess',
method: 'post',
data
})
}
//导出台账模板
export function downTerminalTemplate() {
return createAxios({
url: '/device-boot/device/downTerminalTemplate',
method: 'get',
responseType: 'blob'
})
}
//导出台账信息
export function exportTerminalBase() {
return createAxios({
url: '/device-boot/device/exportTerminalBase',
method: 'get',
responseType: 'blob'
})
}
import createAxios from '@/utils/request'
// 新增菜单接口
export function addNode(data: any) {
return createAxios({
url: '/device-boot/node/addNode',
method: 'post',
data: data
})
}
//修改前置机
export function updateNode(data: any) {
return createAxios({
url: '/device-boot/node/updateNode',
method: 'put',
data: data
})
}
//删除前置机
export function delNode(data: any) {
return createAxios({
url: '/device-boot/node/delNode',
method: 'post',
params: { id: data }
})
}
//终端台账树
export function getTerminalTree() {
return createAxios({
url: '/device-boot/terminalTree/getTerminalTree',
method: 'get'
})
}
//请求前置重启进程
export function askRestartProcess(data: any) {
return createAxios({
url: '/device-boot/device/askRestartProcess',
method: 'post',
data
})
}
/**
* 总计出3层提供给表单选择具体的终端、母线、监测点
* 终端台账树
* 等级0-项目名称1- 用户名称2-单位3-部门4-终端5-母线6-监测点
*/
export function getTerminalSelectTree(level: number) {
return createAxios({
url: '/device-boot/terminalTree/getTerminalSelectTree?level=' + level,
method: 'get'
})
}
//查询节点内容
export function queryTerminal(data: any) {
return createAxios({
url: `/device-boot/device/queryTerminal`,
method: 'get',
params: data
})
}
//删除终端
export function delTerminal(data: any) {
return createAxios({
url: `/device-boot/device/delTerminal`,
method: 'delete',
params: data
})
}
//获取前置机
export function nodeAllList() {
return createAxios({
url: '/device-boot/node/nodeAllList',
method: 'get'
})
}
//修改数据
export function updateTerminal(query: any) {
return createAxios({
url: `/device-boot/device/updateTerminal`,
method: 'put',
data: {
...query
}
})
}
//提交数据
export function addTerminal(query: any) {
return createAxios({
url: '/device-boot/device/addTerminal',
method: 'post',
data: {
...query
}
})
}
//查询终端程序版本升级日志
export function getTerminalUpLog(data: any) {
return createAxios({
url: '/device-boot/version/getTerminalUpLog',
method: 'post',
params: data
})
}
//查询新能源场站
export function selectDown() {
return createAxios({
url: '/device-boot/newStation/selectDown',
method: 'get'
})
}
//获取用户大类小类
export function queryAllByType(params: any) {
return createAxios({
url: '/system-boot/dictTree/queryAllByType',
method: 'get',
params
})
}
//获取用户
export function selectUserList(data: any) {
return createAxios({
url: '/supervision-boot/userReport/selectUserList',
method: 'post',
data
})
}
//查询列表
export function getStatusManageList(data: any) {
return createAxios({
url: '/device-boot/maintain/getStatusManageList',
method: 'post',
data
})
}
//设置终端状态
export function updateRunFlagManage(data: any) {
return createAxios({
url: '/device-boot/maintain/updateRunFlagManage',
method: 'post',
data
})
}
//设置终端日志
export function getList(data: any) {
return createAxios({
url: '/device-boot/pqsTerminalLogs/getList',
method: 'post',
data
})
}
//查询前置-进程-设备-设备树
export function nodeDeviceTree(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/nodeDeviceTree',
method: 'post',
params: data
})
}
//更新设备进程号
export function updateDeviceProcess(data: any) {
return createAxios({
url: '/device-boot/nodeDevice/updateDeviceProcess',
method: 'post',
data
})
}
//导出台账模板
export function downTerminalTemplate() {
return createAxios({
url: '/device-boot/device/downTerminalTemplate',
method: 'get',
responseType: 'blob'
})
}
//导出台账信息
export function exportTerminalBase() {
return createAxios({
url: '/device-boot/device/exportTerminalBase',
method: 'get',
responseType: 'blob'
})
}

View File

@@ -1,197 +1,199 @@
<template>
<div :style="{ height: tableStore.table.height }">
<vxe-table
ref="tableRef"
height="auto"
:key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
@sort-change="handleSortChange"
>
<!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" />
</template>
<template v-else>
<Column
:attr="item"
:key="key + '-column'"
v-for="(item, key) in tableStore.table.column"
:tree-node="item.treeNode"
>
<!-- tableStore 预设的列 render 方案 -->
<template v-if="item.render" #default="scope">
<FieldRender
:field="item"
:row="scope.row"
:column="scope.column"
:index="scope.rowIndex"
:key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/>
</template>
</Column>
</template>
<slot name="columns"></slot>
</vxe-table>
</div>
<div v-if="tableStore.showPage" class="table-pagination">
<el-pagination
:currentPage="tableStore.table.params!.pageNum"
:page-size="tableStore.table.params!.pageSize"
:page-sizes="pageSizes"
background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total="tableStore.table.total"
@size-change="onTableSizeChange"
@current-change="onTableCurrentChange"
></el-pagination>
</div>
<slot name="footer"></slot>
</template>
<script setup lang="ts">
import { ref, nextTick, inject, computed, onMounted, watch } from 'vue'
import type { ElTable } from 'element-plus'
import { VxeTableEvents, VxeTableInstance } from 'vxe-table'
import FieldRender from '@/components/table/fieldRender/index.vue'
import Column from '@/components/table/column/index.vue'
import GroupColumn from '@/components/table/column/groupColumn.vue'
import { useConfig } from '@/stores/config'
import type TableStoreClass from '@/utils/tableStore'
import { useRouter } from 'vue-router'
import { defaultAttribute } from '@/components/table/defaultAttribute'
const config = useConfig()
const tableRef = ref<VxeTableInstance>()
const tableStore = inject('tableStore') as TableStoreClass
const router = useRouter()
const key = ref(0)
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
isGroup?: boolean
showOverflow?: boolean
}
const props = withDefaults(defineProps<Props>(), {
isGroup: false,
showOverflow: true
})
onMounted(() => {
tableStore.table.ref = tableRef.value as VxeTableInstance
})
// console.log(props)
const onTableSizeChange = (val: number) => {
tableStore.onTableAction('page-size-change', { size: val })
}
const onTableCurrentChange = (val: number) => {
tableStore.onTableAction('current-page-change', { page: val })
}
const pageSizes = computed(() => {
let defaultSizes = [10, 20, 50, 100, 200]
if (tableStore.table.params!.pageSize) {
if (!defaultSizes.includes(tableStore.table.params!.pageSize)) {
defaultSizes.push(tableStore.table.params!.pageSize)
}
}
return defaultSizes
})
/*
* 记录选择的项
*/
const selectChangeEvent: VxeTableEvents.CheckboxChange<any> = ({ checked }) => {
const records = (tableRef.value as VxeTableInstance).getCheckboxRecords()
tableStore.onTableAction('selection-change', records)
}
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()
key.value += 1
// // 在这里可以根据 column 和 order 进行相应的数据排序操作
// if (order === 'asc') {
// } else if (order === 'desc') {
// }
}
watch(
() => tableStore.table.allFlag,
newVal => {
if (tableStore.table.allFlag) {
tableRef.value?.exportData({
filename:
tableStore.table.filename || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: tableStore.table.allData, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
})
tableStore.table.allFlag = false
}
}
)
watch(
() => tableStore.table.data,
newVal => {
tableStore.onTableAction('selection-change', [])
}
)
defineExpose({
getRef
})
</script>
<style scoped lang="scss">
.ba-data-table :deep(.el-button + .el-button) {
margin-left: 6px;
}
.ba-data-table :deep(.table-header-cell) .cell {
color: var(--el-text-color-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
</style>
<!-- @/components/table/column/GroupColumn.vue@/components/table/column/GroupColumn.vue -->
<template>
<div :style="{ height:props.height?props.height: tableStore.table.height }">
<vxe-table
ref="tableRef"
height="auto"
:key="key"
:data="tableStore.table.data"
v-loading="tableStore.table.loading"
v-bind="Object.assign({}, defaultAttribute, $attrs)"
@checkbox-all="selectChangeEvent"
@checkbox-change="selectChangeEvent"
:showOverflow="showOverflow"
@sort-change="handleSortChange"
>
<!-- Column 组件内部是 el-table-column -->
<template v-if="isGroup">
<GroupColumn :column="tableStore.table.column" />
</template>
<template v-else>
<Column
:attr="item"
:key="key + '-column'"
v-for="(item, key) in tableStore.table.column"
:tree-node="item.treeNode"
>
<!-- tableStore 预设的列 render 方案 -->
<template v-if="item.render" #default="scope">
<FieldRender
:field="item"
:row="scope.row"
:column="scope.column"
:index="scope.rowIndex"
:key="
key +
'-' +
item.render +
'-' +
(item.field ? '-' + item.field + '-' + scope.row[item.field] : '')
"
/>
</template>
</Column>
</template>
<slot name="columns"></slot>
</vxe-table>
</div>
<div v-if="tableStore.showPage" class="table-pagination">
<el-pagination
:currentPage="tableStore.table.params!.pageNum"
:page-size="tableStore.table.params!.pageSize"
:page-sizes="pageSizes"
background
:layout="config.layout.shrink ? 'prev, next, jumper' : 'sizes,total, ->, prev, pager, next, jumper'"
:total="tableStore.table.total"
@size-change="onTableSizeChange"
@current-change="onTableCurrentChange"
></el-pagination>
</div>
<slot name="footer"></slot>
</template>
<script setup lang="ts">
import { ref, nextTick, inject, computed, onMounted, watch } from 'vue'
import type { ElTable } from 'element-plus'
import { VxeTableEvents, VxeTableInstance } from 'vxe-table'
import FieldRender from '@/components/table/fieldRender/index.vue'
import Column from '@/components/table/column/index.vue'
import GroupColumn from '@/components/table/column/groupColumn.vue'
import { useConfig } from '@/stores/config'
import type TableStoreClass from '@/utils/tableStore'
import { useRouter } from 'vue-router'
import { defaultAttribute } from '@/components/table/defaultAttribute'
const config = useConfig()
const tableRef = ref<VxeTableInstance>()
const tableStore = inject('tableStore') as TableStoreClass
const router = useRouter()
const key = ref(0)
interface Props extends /* @vue-ignore */ Partial<InstanceType<typeof ElTable>> {
isGroup?: boolean
showOverflow?: boolean
height?: string | boolean
}
const props = withDefaults(defineProps<Props>(), {
isGroup: false,
showOverflow: true,
height: false
})
onMounted(() => {
tableStore.table.ref = tableRef.value as VxeTableInstance
})
// console.log(props)
const onTableSizeChange = (val: number) => {
tableStore.onTableAction('page-size-change', { size: val })
}
const onTableCurrentChange = (val: number) => {
tableStore.onTableAction('current-page-change', { page: val })
}
const pageSizes = computed(() => {
let defaultSizes = [10, 20, 50, 100, 200]
if (tableStore.table.params!.pageSize) {
if (!defaultSizes.includes(tableStore.table.params!.pageSize)) {
defaultSizes.push(tableStore.table.params!.pageSize)
}
}
return defaultSizes
})
/*
* 记录选择的项
*/
const selectChangeEvent: VxeTableEvents.CheckboxChange<any> = ({ checked }) => {
const records = (tableRef.value as VxeTableInstance).getCheckboxRecords()
tableStore.onTableAction('selection-change', records)
}
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()
key.value += 1
// // 在这里可以根据 column 和 order 进行相应的数据排序操作
// if (order === 'asc') {
// } else if (order === 'desc') {
// }
}
watch(
() => tableStore.table.allFlag,
newVal => {
if (tableStore.table.allFlag) {
tableRef.value?.exportData({
filename:
tableStore.table.filename || document.querySelectorAll('.ba-nav-tab.active')[0].textContent || '', // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: tableStore.table.allData, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(
column.column.title === undefined ||
column.column.title === '序号' ||
column.column.title === '操作'
)
}
})
tableStore.table.allFlag = false
}
}
)
watch(
() => tableStore.table.data,
newVal => {
tableStore.onTableAction('selection-change', [])
}
)
defineExpose({
getRef
})
</script>
<style scoped lang="scss">
.ba-data-table :deep(.el-button + .el-button) {
margin-left: 6px;
}
.ba-data-table :deep(.table-header-cell) .cell {
color: var(--el-text-color-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.table-pagination {
height: 58px;
box-sizing: border-box;
width: 100%;
max-width: 100%;
background-color: var(--ba-bg-color-overlay);
padding: 13px 15px;
border-left: 1px solid #e4e7e9;
border-right: 1px solid #e4e7e9;
border-bottom: 1px solid #e4e7e9;
}
</style>
<!-- @/components/table/column/GroupColumn.vue@/components/table/column/GroupColumn.vue -->

View File

@@ -1,120 +1,118 @@
<template>
<div class="nav-bar">
<div v-if="config.layout.shrink && config.layout.menuCollapse" class="unfold">
<Icon
@click="onMenuCollapse"
name="fa fa-indent"
:color="config.getColorVal('menuActiveColor')"
size="18"
/>
</div>
<span class="nav-bar-title">
{{ getTheme.name }}
<span style="font-size: 14px">
({{ Version||'v1.0.0' }})
</span>
<!-- <span style="font-size: 14px;" v-if="Version?.versionName">
({{ Version?.versionName }})
</span> -->
</span>
<NavMenus />
</div>
</template>
<script setup lang="ts">
import { useConfig } from '@/stores/config'
import NavTabs from '@/layouts/admin/components/navBar/tabs.vue'
import NavMenus from '../navMenus.vue'
import { showShade } from '@/utils/pageShade'
import { getLastData } from '@/api/systerm'
const Version: any = ref('')
const config = useConfig()
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string)
const onMenuCollapse = () => {
showShade('ba-aside-menu-shade', () => {
config.setLayout('menuCollapse', true)
})
config.setLayout('menuCollapse', false)
}
onMounted(() => {
getLastData({ versionType: 'WEB' }).then(res => {
Version.value = res.data.versionName
})
document.title = getTheme.name
})
</script>
<style scoped lang="scss">
.nav-bar {
display: flex;
align-items: center;
height: 60px;
width: 100%;
background-color: v-bind('config.getColorVal("headerBarBackground")');
.nav-bar-title {
color: v-bind('config.getColorVal("headerBarTabColor")');
font-size: 24px;
margin-left: 10px;
font-weight: 700;
}
:deep(.nav-tabs) {
display: flex;
height: 100%;
position: relative;
.ba-nav-tab {
display: flex;
align-items: center;
justify-content: center;
padding: 0 20px;
cursor: pointer;
z-index: 1;
height: 100%;
user-select: none;
color: v-bind('config.getColorVal("headerBarTabColor")');
transition: all 0.2s;
-webkit-transition: all 0.2s;
.close-icon {
padding: 2px;
margin: 2px 0 0 4px;
color: v-bind('config.getColorVal("headerBarTabColor")') !important;
}
&.active {
color: v-bind('config.getColorVal("headerBarTabActiveColor")');
.close-icon {
color: v-bind('config.getColorVal("headerBarTabActiveColor")') !important;
}
}
&:hover {
color: v-bind('config.getColorVal("headerBarTabActiveColor")');
background-color: v-bind('config.getColorVal("headerBarHoverBackground")');
.close-icon {
color: v-bind('config.getColorVal("headerBarTabActiveColor")') !important;
}
}
}
.nav-tabs-active-box {
position: absolute;
height: 50px;
background-color: v-bind('config.getColorVal("headerBarTabActiveBackground")');
transition: all 0.2s;
-webkit-transition: all 0.2s;
}
}
}
.unfold {
align-self: center;
padding-left: var(--ba-main-space);
}
</style>
<template>
<div class="nav-bar">
<div v-if="config.layout.shrink && config.layout.menuCollapse" class="unfold">
<Icon
@click="onMenuCollapse"
name="fa fa-indent"
:color="config.getColorVal('menuActiveColor')"
size="18"
/>
</div>
<span class="nav-bar-title">
{{ getTheme.name }}
<span style="font-size: 14px">({{ Version || 'v1.0.0' }})</span>
<!-- <span style="font-size: 14px;" v-if="Version?.versionName">
({{ Version?.versionName }})
</span> -->
</span>
<NavMenus />
</div>
</template>
<script setup lang="ts">
import { useConfig } from '@/stores/config'
import NavTabs from '@/layouts/admin/components/navBar/tabs.vue'
import NavMenus from '../navMenus.vue'
import { showShade } from '@/utils/pageShade'
import { getLastData } from '@/api/systerm'
const Version: any = ref(null)
const config = useConfig()
const getTheme = JSON.parse(window.localStorage.getItem('getTheme') as string)
const onMenuCollapse = () => {
showShade('ba-aside-menu-shade', () => {
config.setLayout('menuCollapse', true)
})
config.setLayout('menuCollapse', false)
}
onMounted(() => {
getLastData({ versionType: 'WEB' }).then(res => {
Version.value = res.data.versionName
})
document.title = getTheme.name
})
</script>
<style scoped lang="scss">
.nav-bar {
display: flex;
align-items: center;
height: 60px;
width: 100%;
background-color: v-bind('config.getColorVal("headerBarBackground")');
.nav-bar-title {
color: v-bind('config.getColorVal("headerBarTabColor")');
font-size: 24px;
margin-left: 10px;
font-weight: 700;
}
:deep(.nav-tabs) {
display: flex;
height: 100%;
position: relative;
.ba-nav-tab {
display: flex;
align-items: center;
justify-content: center;
padding: 0 20px;
cursor: pointer;
z-index: 1;
height: 100%;
user-select: none;
color: v-bind('config.getColorVal("headerBarTabColor")');
transition: all 0.2s;
-webkit-transition: all 0.2s;
.close-icon {
padding: 2px;
margin: 2px 0 0 4px;
color: v-bind('config.getColorVal("headerBarTabColor")') !important;
}
&.active {
color: v-bind('config.getColorVal("headerBarTabActiveColor")');
.close-icon {
color: v-bind('config.getColorVal("headerBarTabActiveColor")') !important;
}
}
&:hover {
color: v-bind('config.getColorVal("headerBarTabActiveColor")');
background-color: v-bind('config.getColorVal("headerBarHoverBackground")');
.close-icon {
color: v-bind('config.getColorVal("headerBarTabActiveColor")') !important;
}
}
}
.nav-tabs-active-box {
position: absolute;
height: 50px;
background-color: v-bind('config.getColorVal("headerBarTabActiveBackground")');
transition: all 0.2s;
-webkit-transition: all 0.2s;
}
}
}
.unfold {
align-self: center;
padding-left: var(--ba-main-space);
}
</style>

View File

@@ -1,344 +1,344 @@
import type { RouteRecordRaw } from 'vue-router'
const pageTitle = (name: string): string => {
return `pagesTitle.${name}`
}
/**
* 后台基础路由路径
*/
export const adminBaseRoutePath = '/admin'
export const adminBaseRoute = {
path: adminBaseRoutePath,
name: 'admin',
component: () => import('@/layouts/admin/index.vue'),
// 直接重定向到 loading 路由
redirect: adminBaseRoutePath + '/loading',
meta: {
title: `pagesTitle.admin`
},
children: [
{
path: 'loading/:to?',
name: 'adminMainLoading',
component: () => import('@/layouts/common/components/loading.vue'),
meta: {
title: `pagesTitle.loading`
}
},
{
path: 'businessUserRouter',
name: '业务管理员页面',
meta: {
title: pageTitle('businessUser'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'eventView',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/event/eventView.vue'),
name: '暂降事件查看页面',
meta: {
title: pageTitle('router.eventView')
}
},
{
path: 'productLine',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/productLine/index.vue'),
name: '生产线查看页面',
meta: {
title: pageTitle('router.eventView')
}
},
{
path: 'machine',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/machine/index.vue'),
name: '终端查看页面',
meta: {
title: pageTitle('router.eventView')
}
}
]
},
{
path: 'sagGovernScheme',
name: '暂降治理评估方案',
meta: {
title: pageTitle('sagGovernScheme'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'schemeCalc',
component: () => import('@/views/pqs/voltageSags/sagGovern/scheme/schemeCalc/index.vue'),
name: '治理评估页面',
meta: {
title: pageTitle('router.schemeCalc')
}
},
{
path: 'schemeHistory',
component: () => import('@/views/pqs/voltageSags/sagGovern/scheme/history/index.vue'),
name: '治理方案结果详情',
meta: {
title: pageTitle('router.schemeHistory')
}
}
]
},
{
path: '/bpm',
name: 'bpm',
meta: {
hidden: true
},
children: [
{
path: 'formEdit',
component: () => import('@/views/system/bpm/form/editor/index.vue'),
name: 'BpmFormEditor',
meta: {
title: pageTitle('router.formEdit')
}
},
{
path: 'modelEdit',
component: () => import('@/views/system/bpm/model/editor/index.vue'),
name: 'BpmModelEditor',
meta: {
title: pageTitle('router.modelEdit')
}
},
{
path: 'instanceDetail',
component: () => import('@/views/system/bpm/processInstance/detail/index.vue'),
name: 'BpmProcessInstanceDetail',
meta: {
title: pageTitle('router.instanceDetail')
}
},
{
path: 'ProgramReviewInter',
component: () =>
import('@/views/pqs/supervise/interfere/components/normalizationManager/programReview.vue'),
name: 'ProgramReview',
meta: {
title: pageTitle('router.programReview')
}
},
{
path: 'effectProblem',
component: () => import('@/views/pqs/supervise/plan/components/effectProblem/index.vue'),
name: 'PlanEffectProblem',
meta: {
title: pageTitle('router.effectProblem')
}
}
// {
// path: 'manager/model/edit',
// component: () => import('@/views/bpm/model/editor/index.vue'),
// name: 'BpmModelEditor',
// meta: {
// noCache: true,
// hidden: true,
// canTo: true,
// title: '设计流程',
// activeMenu: '/bpm/manager/model'
// }
// },
// {
// path: 'manager/definition',
// component: () => import('@/views/bpm/definition/index.vue'),
// name: 'BpmProcessDefinition',
// meta: {
// noCache: true,
// hidden: true,
// canTo: true,
// title: '流程定义',
// activeMenu: '/bpm/manager/model'
// }
// },
]
},
{
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: 'runManage',
name: '谐波责任划分页面',
meta: {
title: pageTitle('runManage'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'addUser',
component: () => import('@/views/pqs/runManage/assessment/components/uese/form.vue'),
name: '新增评估用户',
meta: {
title: pageTitle('router.addUser')
}
}
]
},
{
path: 'cockpit',
name: '项目管理',
meta: {
title: pageTitle('runManage'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'popup',
component: () => import('@/views/pqs/cockpit/setUp/components/popup.vue'),
name: '新增项目',
meta: {
title: pageTitle('router.popup')
}
},
{
path: 'view',
component: () => import('@/views/pqs/cockpit/setUp/components/view.vue'),
name: '预览项目',
meta: {
title: pageTitle('router.view')
}
}
]
},
{
path: '/boX',
name: 'boX',
component: () => import('@/components/echarts/boX.vue'),
meta: {
title: pageTitle('boX')
}
}
/*{
path: '/bpm',
name: 'bpm',
meta: {
hidden: true
},
children: [
{
path: 'programReview',
component: () => import('@/views/pqs/supervise/interfere/components/normalizationManager/programReview.vue'),
name: 'programReview',
meta: {
title: pageTitle('router.programReview')
}
},{
path: 'projectTreat',
component: () => import('@/views/pqs/supervise/interfere/components/normalizationManager/projectTreat.vue'),
name: 'projectTreat',
meta: {
title: pageTitle('router.projectTreat')
}
},
]
},*/
]
}
/*
* 静态路由
* 自动加载 ./static 目录的所有文件,并 push 到以下数组
*/
const staticRoutes: Array<RouteRecordRaw> = [
adminBaseRoute,
{
path: '/',
redirect: to => {
return {
name: 'adminMainLoading'
}
}
},
{
// 管理员登录页 - 不放在 adminBaseRoute.children 因为登录页不需要使用后台的布局
path: '/login',
name: 'login',
component: () => import('@/views/user/login.vue'),
meta: {
title: pageTitle('login')
}
},
{
path: '/:path(.*)*',
redirect: '/404'
},
{
path: '/404',
name: 'notFound',
component: () => import('@/views/common/error/404.vue'),
meta: {
title: pageTitle('notFound') // 页面不存在
}
},
{
path: '/previewFile',
name: 'previewFile',
component: () => import('@/components/PreviewFile/index.vue'),
meta: {
title: pageTitle('previewFile')
}
},
{
// 后台找不到页面了-可能是路由未加载上
path: adminBaseRoutePath + ':path(.*)*',
redirect: to => {
return {
name: 'adminMainLoading',
params: {
to: JSON.stringify({
path: to.path,
query: to.query
})
}
}
}
}
]
export default staticRoutes
import type { RouteRecordRaw } from 'vue-router'
const pageTitle = (name: string): string => {
return `pagesTitle.${name}`
}
/**
* 后台基础路由路径
*/
export const adminBaseRoutePath = '/admin'
export const adminBaseRoute = {
path: adminBaseRoutePath,
name: 'admin',
component: () => import('@/layouts/admin/index.vue'),
// 直接重定向到 loading 路由
redirect: adminBaseRoutePath + '/loading',
meta: {
title: `pagesTitle.admin`
},
children: [
{
path: 'loading/:to?',
name: 'adminMainLoading',
component: () => import('@/layouts/common/components/loading.vue'),
meta: {
title: `pagesTitle.loading`
}
},
{
path: 'businessUserRouter',
name: '业务管理员页面',
meta: {
title: pageTitle('businessUser'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'eventView',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/event/eventView.vue'),
name: '暂降事件查看页面',
meta: {
title: pageTitle('router.eventView')
}
},
{
path: 'productLine',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/productLine/index.vue'),
name: '生产线查看页面',
meta: {
title: pageTitle('router.eventView')
}
},
{
path: 'machine',
component: () => import('@/views/pqs/voltageSags/sagGovern/businessUser/machine/index.vue'),
name: '终端查看页面',
meta: {
title: pageTitle('router.eventView')
}
}
]
},
{
path: 'sagGovernScheme',
name: '暂降治理评估方案',
meta: {
title: pageTitle('sagGovernScheme'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'schemeCalc',
component: () => import('@/views/pqs/voltageSags/sagGovern/scheme/schemeCalc/index.vue'),
name: '治理评估页面',
meta: {
title: pageTitle('router.schemeCalc')
}
},
{
path: 'schemeHistory',
component: () => import('@/views/pqs/voltageSags/sagGovern/scheme/history/index.vue'),
name: '治理方案结果详情',
meta: {
title: pageTitle('router.schemeHistory')
}
}
]
},
{
path: '/bpm',
name: 'bpm',
meta: {
hidden: true
},
children: [
{
path: 'formEdit',
component: () => import('@/views/system/bpm/form/editor/index.vue'),
name: 'BpmFormEditor',
meta: {
title: pageTitle('router.formEdit')
}
},
{
path: 'modelEdit',
component: () => import('@/views/system/bpm/model/editor/index.vue'),
name: 'BpmModelEditor',
meta: {
title: pageTitle('router.modelEdit')
}
},
{
path: 'instanceDetail',
component: () => import('@/views/system/bpm/processInstance/detail/index.vue'),
name: 'BpmProcessInstanceDetail',
meta: {
title: pageTitle('router.instanceDetail')
}
},
{
path: 'ProgramReviewInter',
component: () =>
import('@/views/pqs/supervise/interfere/components/normalizationManager/programReview.vue'),
name: 'ProgramReview',
meta: {
title: pageTitle('router.programReview')
}
},
{
path: 'effectProblem',
component: () => import('@/views/pqs/supervise/plan/components/effectProblem/index.vue'),
name: 'PlanEffectProblem',
meta: {
title: pageTitle('router.effectProblem')
}
}
// {
// path: 'manager/model/edit',
// component: () => import('@/views/bpm/model/editor/index.vue'),
// name: 'BpmModelEditor',
// meta: {
// noCache: true,
// hidden: true,
// canTo: true,
// title: '设计流程',
// activeMenu: '/bpm/manager/model'
// }
// },
// {
// path: 'manager/definition',
// component: () => import('@/views/bpm/definition/index.vue'),
// name: 'BpmProcessDefinition',
// meta: {
// noCache: true,
// hidden: true,
// canTo: true,
// title: '流程定义',
// activeMenu: '/bpm/manager/model'
// }
// },
]
},
{
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: 'runManage',
name: '二级评估',
meta: {
title: pageTitle('runManage'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'addUser',
component: () => import('@/views/pqs/runManage/assessment/components/uese/form.vue'),
name: '新增评估用户',
meta: {
title: pageTitle('router.addUser')
}
}
]
},
{
path: 'cockpit',
name: '项目管理',
meta: {
title: pageTitle('runManage'),
icon: 'ep:management',
alwaysShow: true
},
children: [
{
path: 'popup',
component: () => import('@/views/pqs/cockpit/setUp/components/popup.vue'),
name: '新增项目',
meta: {
title: pageTitle('router.popup')
}
},
{
path: 'view',
component: () => import('@/views/pqs/cockpit/setUp/components/view.vue'),
name: '预览项目',
meta: {
title: pageTitle('router.view')
}
}
]
},
{
path: '/boX',
name: 'boX',
component: () => import('@/components/echarts/boX.vue'),
meta: {
title: pageTitle('boX')
}
}
/*{
path: '/bpm',
name: 'bpm',
meta: {
hidden: true
},
children: [
{
path: 'programReview',
component: () => import('@/views/pqs/supervise/interfere/components/normalizationManager/programReview.vue'),
name: 'programReview',
meta: {
title: pageTitle('router.programReview')
}
},{
path: 'projectTreat',
component: () => import('@/views/pqs/supervise/interfere/components/normalizationManager/projectTreat.vue'),
name: 'projectTreat',
meta: {
title: pageTitle('router.projectTreat')
}
},
]
},*/
]
}
/*
* 静态路由
* 自动加载 ./static 目录的所有文件,并 push 到以下数组
*/
const staticRoutes: Array<RouteRecordRaw> = [
adminBaseRoute,
{
path: '/',
redirect: to => {
return {
name: 'adminMainLoading'
}
}
},
{
// 管理员登录页 - 不放在 adminBaseRoute.children 因为登录页不需要使用后台的布局
path: '/login',
name: 'login',
component: () => import('@/views/user/login.vue'),
meta: {
title: pageTitle('login')
}
},
{
path: '/:path(.*)*',
redirect: '/404'
},
{
path: '/404',
name: 'notFound',
component: () => import('@/views/common/error/404.vue'),
meta: {
title: pageTitle('notFound') // 页面不存在
}
},
{
path: '/previewFile',
name: 'previewFile',
component: () => import('@/components/PreviewFile/index.vue'),
meta: {
title: pageTitle('previewFile')
}
},
{
// 后台找不到页面了-可能是路由未加载上
path: adminBaseRoutePath + ':path(.*)*',
redirect: to => {
return {
name: 'adminMainLoading',
params: {
to: JSON.stringify({
path: to.path,
query: to.query
})
}
}
}
}
]
export default staticRoutes

View File

@@ -1,225 +1,225 @@
import { reactive } from 'vue'
import createAxios from '@/utils/request'
import { requestPayload } from '@/utils/request'
import { Method } from 'axios'
import { mainHeight } from '@/utils/layout'
import { filtration } from './tableMethod'
interface TableStoreParams {
url: string // 请求地址
pk?: string
filename?: any // 导出文件名
column: TableColumn[]
params?: anyObj
method?: Method // 请求方式
isWebPaging?: boolean // 是否前端分页
showPage?: boolean //是否需要分页
timeAll?: boolean //是否需要时间全部显示
paramsPOST?: boolean // post请求 params传参
publicHeight?: number //计算高度
resetCallback?: () => void // 重置
loadCallback?: () => void // 接口调用后的回调
exportProcessingData?:() => void //导出处理数据
beforeSearchFun?: () => void // 接口调用前的回调
}
export default class TableStore {
public url
public pk
public filename: any = null
public method: Method
public initData: any = null
public isWebPaging = false
public paramsPOST = true
public showPage = true
public timeAll = true
public table: CnTable = reactive({
ref: null,
selection: [],
data: [],
allData: [],
allFlag: false,
webPagingData: [],
total: 0,
params: {
pageNum: 1,
pageSize: 20
},
filename:null,
loading: true,
column: [],
loadCallback: null,
exportProcessingData: null,
resetCallback: null,
beforeSearchFun: null,
height: '',
publicHeight: 0
})
constructor(public options: TableStoreParams) {
this.url = options.url
this.pk = options.pk || 'id'
this.paramsPOST = options.paramsPOST || false
this.isWebPaging = options.isWebPaging || false
this.method = options.method || 'GET'
this.table.filename = options.filename || null
this.table.column = options.column
this.showPage = options.showPage !== false
this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null
this.table.exportProcessingData = options.exportProcessingData || null
this.table.beforeSearchFun = options.beforeSearchFun || null
Object.assign(this.table.params, options.params)
this.table.height = mainHeight(20 + (this.showPage ? 58 : 0) + this.table.publicHeight).height as string
}
index() {
this.table.beforeSearchFun && this.table.beforeSearchFun()
this.table.data = []
this.table.loading = true
// 重置用的数据数据
if (!this.initData) {
this.initData = JSON.parse(JSON.stringify(this.table.params))
}
if (!this.timeAll) {
delete this.table.params.startTime;
delete this.table.params.endTime;
delete this.table.params.searchBeginTime;
delete this.table.params.searchEndTime;
delete this.table.params.timeFlag;
}
createAxios(
Object.assign(
{
url: this.url,
method: this.method
},
requestPayload(this.method, this.table.params, this.paramsPOST)
)
)
.then((res: any) => {
if (res.data) {
this.table.data = res.data.records || res.data
this.table.total = res.data?.total || res.data.length || 0
} else {
this.table.data = []
this.table.total = 0
}
if (Array.isArray(res)) {
this.table.data = res
}
if (this.isWebPaging) {
this.table.webPagingData = window.XEUtils.chunk(this.table.data, this.table.params.pageSize)
this.table.data = this.table.webPagingData[this.table.params.pageNum - 1]
}
this.table.loadCallback && this.table.loadCallback()
this.table.loading = false
})
.catch(() => {
this.table.loading = false
})
}
/**
* 表格内的事件统一响应
* @param event 事件:selection-change=选中项改变,page-size-change=每页数量改变,current-page-change=翻页
* @param data 携带数据
*/
onTableAction = (event: string, data: anyObj) => {
const actionFun = new Map([
[
'search',
() => {
this.table.params.pageNum = 1
this.index()
}
],
[
'reset',
() => {
delete this.initData.pageSize
// console.log(this.table.params)
// console.log(this.initData)
Object.assign(this.table.params, this.initData)
this.table.resetCallback && this.table.resetCallback()
this.index()
}
],
[
'selection-change',
() => {
this.table.selection = data as TableRow[]
}
],
[
'page-size-change',
() => {
this.table.params.pageSize = data.size
this.table.params.pageNum = 1
if (this.isWebPaging) {
this.table.webPagingData = window.XEUtils.chunk(
window.XEUtils.flatten(this.table.webPagingData),
this.table.params.pageSize
)
this.table.data = this.table.webPagingData[this.table.params.pageNum - 1]
} else {
this.index()
}
}
],
[
'current-page-change',
() => {
this.table.params.pageNum = data.page
if (this.isWebPaging) {
this.table.data = []
requestAnimationFrame(() => {
this.table.data = this.table.webPagingData[data.page - 1]
})
} else {
this.index()
}
}
],
[
'field-change',
() => {
console.warn('field-change')
}
],
[
'default',
() => {
console.warn('No action defined')
}
],
[
'export',
() => {
// this.index()
let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total }
createAxios(
Object.assign(
{
url: this.url,
method: this.method
},
requestPayload(this.method, params, this.paramsPOST)
)
).then(res => {
this.table.allData = filtration(res.data.records || res.data)
this.table.exportProcessingData && this.table.exportProcessingData()
this.table.allFlag = data.showAllFlag || true
})
}
]
])
const action = actionFun.get(event) || actionFun.get('default')
action!.call(this)
}
}
import { reactive } from 'vue'
import createAxios from '@/utils/request'
import { requestPayload } from '@/utils/request'
import { Method } from 'axios'
import { mainHeight } from '@/utils/layout'
import { filtration } from './tableMethod'
interface TableStoreParams {
url: string // 请求地址
pk?: string
filename?: any // 导出文件名
column: TableColumn[]
params?: anyObj
method?: Method // 请求方式
isWebPaging?: boolean // 是否前端分页
showPage?: boolean //是否需要分页
timeAll?: boolean //是否需要时间全部显示
paramsPOST?: boolean // post请求 params传参
publicHeight?: number //计算高度
resetCallback?: () => void // 重置
loadCallback?: () => void // 接口调用后的回调
exportProcessingData?:() => void //导出处理数据
beforeSearchFun?: () => void // 接口调用前的回调
}
export default class TableStore {
public url
public pk
public filename: any = null
public method: Method
public initData: any = null
public isWebPaging = false
public paramsPOST = true
public showPage = true
public timeAll = true
public table: CnTable = reactive({
ref: null,
selection: [],
data: [],
allData: [],
allFlag: false,
webPagingData: [],
total: 0,
params: {
pageNum: 1,
pageSize: 20
},
filename:null,
loading: true,
column: [],
loadCallback: null,
exportProcessingData: null,
resetCallback: null,
beforeSearchFun: null,
height: '',
publicHeight: 0
})
constructor(public options: TableStoreParams) {
this.url = options.url
this.pk = options.pk || 'id'
this.paramsPOST = options.paramsPOST || false
this.isWebPaging = options.isWebPaging || false
this.method = options.method || 'GET'
this.table.filename = options.filename || null
this.table.column = options.column
this.showPage = options.showPage !== false
this.table.publicHeight = options.publicHeight || 0
this.table.resetCallback = options.resetCallback || null
this.table.loadCallback = options.loadCallback || null
this.table.exportProcessingData = options.exportProcessingData || null
this.table.beforeSearchFun = options.beforeSearchFun || null
Object.assign(this.table.params, options.params)
this.table.height = mainHeight(20 + (this.showPage ? 58 : 0) + this.table.publicHeight).height as string
}
index() {
this.table.beforeSearchFun && this.table.beforeSearchFun()
this.table.data = []
this.table.loading = true
// 重置用的数据数据
if (!this.initData) {
this.initData = JSON.parse(JSON.stringify(this.table.params))
}
if (!this.timeAll) {
delete this.table.params.startTime;
delete this.table.params.endTime;
delete this.table.params.searchBeginTime;
delete this.table.params.searchEndTime;
delete this.table.params.timeFlag;
}
createAxios(
Object.assign(
{
url: this.url,
method: this.method
},
requestPayload(this.method, this.table.params, this.paramsPOST)
)
)
.then((res: any) => {
if (res.data) {
this.table.data = res.data.records || res.data
this.table.total = res.data?.total || res.data.length || 0
} else {
this.table.data = []
this.table.total = 0
}
if (Array.isArray(res)) {
this.table.data = res
}
if (this.isWebPaging) {
this.table.webPagingData = window.XEUtils.chunk(this.table.data, this.table.params.pageSize)
this.table.data = this.table.webPagingData[this.table.params.pageNum - 1]
}
this.table.loadCallback && this.table.loadCallback()
this.table.loading = false
})
.catch(() => {
this.table.loading = false
})
}
/**
* 表格内的事件统一响应
* @param event 事件:selection-change=选中项改变,page-size-change=每页数量改变,current-page-change=翻页
* @param data 携带数据
*/
onTableAction = (event: string, data: anyObj) => {
const actionFun = new Map([
[
'search',
() => {
this.table.params.pageNum = 1
this.index()
}
],
[
'reset',
() => {
delete this.initData.pageSize
// console.log(this.table.params)
// console.log(this.initData)
Object.assign(this.table.params, this.initData)
this.table.resetCallback && this.table.resetCallback()
this.index()
}
],
[
'selection-change',
() => {
this.table.selection = data as TableRow[]
}
],
[
'page-size-change',
() => {
this.table.params.pageSize = data.size
this.table.params.pageNum = 1
if (this.isWebPaging) {
this.table.webPagingData = window.XEUtils.chunk(
window.XEUtils.flatten(this.table.webPagingData),
this.table.params.pageSize
)
this.table.data = this.table.webPagingData[this.table.params.pageNum - 1]
} else {
this.index()
}
}
],
[
'current-page-change',
() => {
this.table.params.pageNum = data.page
if (this.isWebPaging) {
this.table.data = []
requestAnimationFrame(() => {
this.table.data = this.table.webPagingData[data.page - 1]
})
} else {
this.index()
}
}
],
[
'field-change',
() => {
console.warn('field-change')
}
],
[
'default',
() => {
console.warn('No action defined')
}
],
[
'export',
() => {
// this.index()
let params = { ...this.table.params, pageNum: 1, pageSize: this.table.total }
createAxios(
Object.assign(
{
url: this.url,
method: this.method
},
requestPayload(this.method, params, this.paramsPOST)
)
).then(res => {
this.table.allData = filtration(res.data.records || res.data)
this.table.exportProcessingData && this.table.exportProcessingData()
this.table.allFlag = data.showAllFlag || true
})
}
]
])
const action = actionFun.get(event) || actionFun.get('default')
action!.call(this)
}
}

View File

@@ -0,0 +1,82 @@
<template>
<!-- 新增 -->
<el-dialog draggable title="详情" v-model="dialogVisible" width="1200px">
<TableHeader datePicker showExport :showReset="false">
<template v-slot:select>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable />
</el-form-item>
</template>
</TableHeader>
<div :key="key">
<Table ref="tableRef" :height="'49vh'"></Table>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import { ElMessage, ElMessageBox } from 'element-plus'
import { mainHeight } from '@/utils/layout'
defineOptions({
name: 'frontLog'
})
const key = ref(0)
const dialogVisible = ref(false)
const tableStore = new TableStore({
url: '/system-boot/frontLog/queryLogCHild',
method: 'POST',
column: [
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
title: '发生时间',
field: 'updateTime',
width: '150',
sortable: true
},
{
title: '日志等级',
field: 'grade',
width: '100'
},
{
title: '日志详情',
field: 'log',
formatter: (row: any) => {
return row.cellValue || '/'
}
}
]
})
tableStore.table.params.type = ''
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
const open = (row: any) => {
dialogVisible.value = true
tableStore.table.params.mainId = row.id
setTimeout(() => {
tableStore.index()
}, 0)
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -1,88 +1,111 @@
<template>
<div class="default-main">
<TableHeader datePicker showExport>
<template v-slot:select>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable />
</el-form-item>
</template>
</TableHeader>
<Table ref="tableRef"></Table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'frontLog'
})
const pushDisplayRef = ref()
const dictData = useDictData()
const fontdveoption = dictData.getBasicData('Dev_Ops')
const tableStore = new TableStore({
url: '/system-boot/frontLog/query',
method: 'POST',
column: [
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
// { title: '名称', field: 'name', width: '200' },
{
title: '进程号',
field: 'processNo',
width: '80'
},
{
title: '业务名称',
field: 'businessName',
width: '250'
},
{
title: '日志层级',
field: 'level',
width: '100'
},
{
title: '前置业务类型',
field: 'frontType',
width: '120'
},
{
title: '更改时间',
field: 'updateTime',
width: '180',
sortable: true
},
{ title: '日志详情', field: 'log' }
],
beforeSearchFun: () => {}
})
const tableRef = ref()
provide('tableRef', tableRef)
tableStore.table.params.type = ''
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const addMenu = () => {}
</script>
<style lang="scss" scoped></style>
<template>
<div class="default-main">
<TableHeader datePicker showExport>
<template v-slot:select>
<el-form-item label="筛选数据">
<el-input v-model="tableStore.table.params.searchValue" placeholder="请输入筛选数据" clearable />
</el-form-item>
</template>
</TableHeader>
<Table ref="tableRef"></Table>
<!-- 详情 -->
<Detail ref="detailRef"/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import Detail from './detail.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
defineOptions({
name: 'frontLog'
})
const detailRef = ref()
const tableStore = new TableStore({
url: '/system-boot/frontLog/query',
method: 'POST',
column: [
{
field: 'index',
title: '序号',
width: '80',
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
// { title: '名称', field: 'name', width: '200' },
{
title: '进程号',
field: 'processNo',
width: '80'
},
{
title: '业务名称',
field: 'businessName',
minWidth: '250'
},
{
title: '日志层级',
field: 'level',
minWidth: '100'
},
{
title: '前置业务类型',
field: 'frontType',
minWidth: '120'
},
{
title: '更改时间',
field: 'updateTime',
minWidth: '180',
sortable: true
},
{
title: '日志错误码',
field: 'codeName',
minWidth: '180',
formatter: (row: any) => {
return row.cellValue || '/'
}
},
{
title: '操作',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '详情',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
detailRef.value.open(row)
}
}
]
}
],
beforeSearchFun: () => {}
})
tableStore.table.params.type = ''
tableStore.table.params.searchValue = ''
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})
const addMenu = () => {}
</script>
<style lang="scss" scoped></style>

View File

@@ -78,6 +78,30 @@
@click="edit(data)"
link
></el-button>
<el-popconfirm
v-else
class="box-item"
title="确定重启吗?"
placement="bottom"
@confirm="restart(data)"
>
<template #actions="{ confirm, cancel }">
<el-button size="small" @click="cancel">取消</el-button>
<el-button type="warning" size="small" @click="confirm">确认</el-button>
</template>
<template #reference>
<el-button
style="margin-left: 4px"
icon="el-icon-Refresh"
type="warning"
link
@click.stop
></el-button>
<!-- @click.stop="restart(data)" -->
</template>
</el-popconfirm>
</div>
</div>
</template>
@@ -94,7 +118,13 @@
>
<el-form :model="formData" label-width="120px" :rules="rules" ref="ruleFormRef">
<el-form-item label="名称:" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" maxlength="32" show-word-limit @input="handleInput"></el-input>
<el-input
v-model="formData.name"
placeholder="请输入名称"
maxlength="32"
show-word-limit
@input="handleInput"
></el-input>
</el-form-item>
<el-form-item label="IP:" prop="ip" class="top">
<el-input v-model="formData.ip" placeholder="请输入Ip"></el-input>
@@ -173,7 +203,14 @@
</template>
<script setup lang="ts">
import { ref, onMounted, provide, reactive, nextTick } from 'vue'
import { addNode, delNode, updateNode, nodeDeviceTree, updateDeviceProcess } from '@/api/device-boot/Business'
import {
addNode,
delNode,
updateNode,
nodeDeviceTree,
updateDeviceProcess,
askRestartProcess
} from '@/api/device-boot/Business'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
@@ -295,6 +332,29 @@ const tableStore = new TableStore({
formData.value = JSON.parse(JSON.stringify(row))
}
},
{
name: 'edit',
title: '重启',
type: 'warning',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'warning',
title: '确定重启吗?'
},
click: row => {
askRestartProcess({
deviceRebootType: null,
nodeId: row.id,
processNo: 1
}).then(res => {
ElMessage.success('重启成功')
tableStore.index()
})
}
},
{
name: 'del',
@@ -330,35 +390,52 @@ const tableStore = new TableStore({
currentChangeEvent()
}
})
const nodeId = ref('')
// 点击行
const currentChangeEvent = () => {
// 确保 tableRef 和当前记录存在
// 确保 tableRef 和当前记录存在
if (!tableRef.value || !tableRef.value.getRef().getCurrentRecord()) {
loading.value = false;
dataSource.value = [];
return;
loading.value = false
dataSource.value = []
return
}
loading.value = true
dataSource.value = []
nodeDeviceTree({
nodeId: tableRef.value.getRef().getCurrentRecord().id
}).then(res => {
// 检查返回的数据是否存在且不为空
if (res.data && res.data.processDeviceList) {
dataSource.value = res.data.processDeviceList.filter(item => (item.name = item.processNo + ''))
} else {
dataSource.value = []
}
loading.value = false
}).catch(() => {
// 添加错误处理,确保 loading 状态也能关闭
dataSource.value = []
loading.value = false
})
.then(res => {
nodeId.value = tableRef.value.getRef().getCurrentRecord().id
// 检查返回的数据是否存在且不为空
if (res.data && res.data.processDeviceList) {
dataSource.value = res.data.processDeviceList.filter(item => (item.name = item.processNo + ''))
} else {
dataSource.value = []
}
loading.value = false
})
.catch(() => {
// 添加错误处理,确保 loading 状态也能关闭
dataSource.value = []
loading.value = false
})
// const row = tableRef.value.getRef().getCurrentRecord()
}
// 重启进程
const restart = (data: any) => {
console.log('🚀 ~ restart ~ data:', data)
askRestartProcess({
deviceRebootType: data.processNo,
nodeId: nodeId.value,
processNo: 2
}).then(res => {
ElMessage.success('重启成功')
currentChangeEvent()
})
}
const treeRef = ref()
// 树过滤
const change = val => {

View File

@@ -1,234 +1,234 @@
<template>
<el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" :title="title" width="500px">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="auto" class="form-one" :rules="rules" ref="formRef">
<el-form-item label="上级名称" v-if="title == '新增'">
<el-select v-model="form.pid" placeholder="请选择上级名称" clearable>
<el-option v-for="item in dataTree" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="选择修改" v-if="title == '修改'">
<el-cascader v-model="cascaderId" :options="dataTree" placeholder="请选择需要修改的内容" filterable
checkStrictly :props="cascaderProps" @change="change" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="名称" maxlength="20" show-word-limit @input="handleInput"/>
</el-form-item>
<el-form-item label="标准" v-if="title == '新增' && form.pid?.length > 0">
<el-upload v-model:file-list="urlList" ref="upload" action="" :limit="1" :auto-upload="false"
:on-exceed="handleExceed">
<el-button type="primary">上传</el-button>
</el-upload>
</el-form-item>
<el-form-item label="标准" v-if="title == '修改' && cascaderId.length > 1">
<el-upload v-model:file-list="urlList" ref="upload" action="" :limit="1" :auto-upload="false"
:on-exceed="handleExceed">
<el-button type="primary">上传</el-button>
</el-upload>
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit" :loading="loading">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { queryAll, libstandardAdd, updateStandardLibrary } from '@/api/supervision-boot/database/index'
import { uploadFile, getFileNameAndFilePath } from '@/api/system-boot/file'
import { genFileId } from 'element-plus'
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
const upload = ref<UploadInstance>()
const dialogVisible = ref(false)
const title = ref('')
const emit = defineEmits(['getTree', 'onSubmit'])
const formRef = ref()
// 注意不要和表单ref的命名冲突
const form: any = reactive<anyObj>({
name: '',
pid: '',
url: ''
})
const cascaderId = ref([])
const urlList: any = ref([])
const loading = ref(false)
const cascaderProps = {
children: 'children',
label: 'name',
value: 'id',
checkStrictly: true,
}
const rules = {
name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }]
}
const dataTree: any = ref([])
const open = (text: string, data?: anyObj) => {
getTheTree()
cascaderId.value = []
title.value = text
urlList.value = []
dialogVisible.value = true
// if (data) {
// // 表单赋值
// for (let key in form) {
// form[key] = data[key]
// }
// form.id = data.id
// if (form.pid == 0) {
// form.pid = ''
// }
// if (data.url?.length > 0) {
// getFileNameAndFilePath({ filePath: data.url }).then(res => {
// urlList.value.push({
// name: res.data.fileName,
// url: res.data.name
// })
// })
// }
// } else {
// 在此处恢复默认表单
for (let key in form) {
form[key] = ''
}
// }
}
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
upload.value!.handleStart(file)
}
const getTheTree = () => {
queryAll().then(res => {
dataTree.value = res.data
})
}
const change = (val: any) => {
const selectedNode = findNodeById(dataTree.value, val[val.length - 1]);
urlList.value = []
if (val.length > 0) {
form.name = selectedNode.name
form.id = selectedNode.id
form.pid = selectedNode.pid
if (selectedNode.url?.length > 0) {
getFileNameAndFilePath({ filePath: selectedNode.url }).then(res => {
urlList.value.push({
name: res.data.fileName,
url: res.data.name
})
})
}
} else {
form.name = ''
form.id = ''
form.pid = ''
form.url = ''
}
}
const findNodeById = (tree: any[], id: any) => {
for (const node of tree) {
if (node.id === id) {
return node;
}
if (node.children) {
const found: any = findNodeById(node.children, id);
if (found) {
return found;
}
}
}
return null;
};
const submit = async () => {
loading.value = true
formRef.value.validate(async (valid: boolean) => {
if (valid) {
if (urlList.value.length > 0 && form.pid != '') {
const promises = urlList.value.map(async (item: any) => {
if (urlList.value[0].raw) {
return new Promise((resolve, reject) => {
uploadFile(item.raw, '/supervision/')
.then((res: any) => {
resolve(res.data.name)
})
.catch(reject)
})
} else {
return item.url
}
})
try {
const fileNames = await Promise.all(promises)
form.url = fileNames.join(',') + ''
} catch (error) {
console.error('上传文件出错', error)
return
}
} else {
form.url = ''
}
setTimeout(() => {
if (title.value == '新增') {
libstandardAdd({
pid: form.pid == '' ? null : form.pid,
name: form.name,
url: form.url
}).then(res => {
ElMessage.success('新增成功')
handleClose()
dialogVisible.value = false
})
} else {
updateStandardLibrary({
pid: form.pid == '' ? null : form.pid,
name: form.name,
url: form.url,
id: form.id
}).then(res => {
ElMessage.success('修改成功')
handleClose()
dialogVisible.value = false
})
}
}, 100)
}
})
setTimeout(() => {
loading.value = false
}, 1000);
}
const handleClose = () => {
urlList.value = []
emit('onSubmit')
dialogVisible.value = false
}
const handleInput = (value: string) => {
// 过滤空格
const filteredValue = value.replace(/\s/g, '')
if (filteredValue !== value) {
form.name = filteredValue
}
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>
<template>
<el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" :title="title" width="500px">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="auto" class="form-one" :rules="rules" ref="formRef">
<el-form-item label="上级名称" v-if="title == '新增'">
<el-select v-model="form.pid" placeholder="请选择上级名称" clearable>
<el-option v-for="item in dataTree" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="选择修改" v-if="title == '修改'">
<el-cascader v-model="cascaderId" :options="dataTree" placeholder="请选择需要修改的内容" filterable
checkStrictly :props="cascaderProps" @change="change" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="名称" maxlength="40" show-word-limit @input="handleInput"/>
</el-form-item>
<el-form-item label="标准" v-if="title == '新增' && form.pid?.length > 0">
<el-upload v-model:file-list="urlList" ref="upload" action="" :limit="1" :auto-upload="false"
:on-exceed="handleExceed">
<el-button type="primary">上传</el-button>
</el-upload>
</el-form-item>
<el-form-item label="标准" v-if="title == '修改' && cascaderId.length > 1">
<el-upload v-model:file-list="urlList" ref="upload" action="" :limit="1" :auto-upload="false"
:on-exceed="handleExceed">
<el-button type="primary">上传</el-button>
</el-upload>
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit" :loading="loading">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { queryAll, libstandardAdd, updateStandardLibrary } from '@/api/supervision-boot/database/index'
import { uploadFile, getFileNameAndFilePath } from '@/api/system-boot/file'
import { genFileId } from 'element-plus'
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
const upload = ref<UploadInstance>()
const dialogVisible = ref(false)
const title = ref('')
const emit = defineEmits(['getTree', 'onSubmit'])
const formRef = ref()
// 注意不要和表单ref的命名冲突
const form: any = reactive<anyObj>({
name: '',
pid: '',
url: ''
})
const cascaderId = ref([])
const urlList: any = ref([])
const loading = ref(false)
const cascaderProps = {
children: 'children',
label: 'name',
value: 'id',
checkStrictly: true,
}
const rules = {
name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }]
}
const dataTree: any = ref([])
const open = (text: string, data?: anyObj) => {
getTheTree()
cascaderId.value = []
title.value = text
urlList.value = []
dialogVisible.value = true
// if (data) {
// // 表单赋值
// for (let key in form) {
// form[key] = data[key]
// }
// form.id = data.id
// if (form.pid == 0) {
// form.pid = ''
// }
// if (data.url?.length > 0) {
// getFileNameAndFilePath({ filePath: data.url }).then(res => {
// urlList.value.push({
// name: res.data.fileName,
// url: res.data.name
// })
// })
// }
// } else {
// 在此处恢复默认表单
for (let key in form) {
form[key] = ''
}
// }
}
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles()
const file = files[0] as UploadRawFile
file.uid = genFileId()
upload.value!.handleStart(file)
}
const getTheTree = () => {
queryAll().then(res => {
dataTree.value = res.data
})
}
const change = (val: any) => {
const selectedNode = findNodeById(dataTree.value, val[val.length - 1]);
urlList.value = []
if (val.length > 0) {
form.name = selectedNode.name
form.id = selectedNode.id
form.pid = selectedNode.pid
if (selectedNode.url?.length > 0) {
getFileNameAndFilePath({ filePath: selectedNode.url }).then(res => {
urlList.value.push({
name: res.data.fileName,
url: res.data.name
})
})
}
} else {
form.name = ''
form.id = ''
form.pid = ''
form.url = ''
}
}
const findNodeById = (tree: any[], id: any) => {
for (const node of tree) {
if (node.id === id) {
return node;
}
if (node.children) {
const found: any = findNodeById(node.children, id);
if (found) {
return found;
}
}
}
return null;
};
const submit = async () => {
loading.value = true
formRef.value.validate(async (valid: boolean) => {
if (valid) {
if (urlList.value.length > 0 && form.pid != '') {
const promises = urlList.value.map(async (item: any) => {
if (urlList.value[0].raw) {
return new Promise((resolve, reject) => {
uploadFile(item.raw, '/supervision/')
.then((res: any) => {
resolve(res.data.name)
})
.catch(reject)
})
} else {
return item.url
}
})
try {
const fileNames = await Promise.all(promises)
form.url = fileNames.join(',') + ''
} catch (error) {
console.error('上传文件出错', error)
return
}
} else {
form.url = ''
}
setTimeout(() => {
if (title.value == '新增') {
libstandardAdd({
pid: form.pid == '' ? null : form.pid,
name: form.name,
url: form.url
}).then(res => {
ElMessage.success('新增成功')
handleClose()
dialogVisible.value = false
})
} else {
updateStandardLibrary({
pid: form.pid == '' ? null : form.pid,
name: form.name,
url: form.url,
id: form.id
}).then(res => {
ElMessage.success('修改成功')
handleClose()
dialogVisible.value = false
})
}
}, 100)
}
})
setTimeout(() => {
loading.value = false
}, 1000);
}
const handleClose = () => {
urlList.value = []
emit('onSubmit')
dialogVisible.value = false
}
const handleInput = (value: string) => {
// 过滤空格
const filteredValue = value.replace(/\s/g, '')
if (filteredValue !== value) {
form.name = filteredValue
}
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
:deep(.el-upload-list__item) {
width: 400px;
}
</style>

View File

@@ -1,164 +1,169 @@
<!-- 负荷数据列表 -->
<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>
<!-- 用采数据列表 -->
<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" draggable 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" :loading="loading">确认</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 ,deleteUserDataByIds} from '@/api/advance-boot/division'
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
defineOptions({
name: 'division/aListOfLoadData'
})
const loading = ref(false)
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 => {
deleteUserDataByIds([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
}
ElMessage.info('上传中,请稍等...')
const formData = new FormData()
formData.append('file', fileList.value[0].raw)
loading.value = true
uploadUserData(formData)
.then(res => {
ElMessage.success('上传成功')
loading.value = false
handleClose()
tableStore.index()
})
.catch(err => {
loading.value = false
})
}
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

@@ -1,65 +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>
<template>
<el-dialog v-model="dialogVisible" draggable 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

@@ -1,198 +1,232 @@
<!-- 贡献度计算 -->
<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) => {
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]
showTabs.value = true
let list = JSON.parse(JSON.stringify(form.index)).sort((a, b) => a - b)
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>
<!-- 贡献度计算 -->
<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"
:disabled-date="handleDisabledDate"
/>
<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'
defineOptions({
name: 'division/compute'
})
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) => {
if (data.level == 6) {
dotList.value = data
}
}
// 设置时间
// 处理日期禁用逻辑
const handleDisabledDate = date => {
// 定义时间边界
const startLimit = new Date(tabList.value[0].time[0]).getTime()
const endLimit = new Date(tabList.value[0].time[1]).setHours(23, 59, 59, 999)
// 如果日期不存在(选择今天时可能出现),不禁用
if (!date) return false
// 禁用 2025-08-01 之前和 2025-08-31 之后的日期
return date.getTime() < startLimit || date.getTime() > endLimit
}
// 确定
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]
showTabs.value = true
let list = JSON.parse(JSON.stringify(form.index)).sort((a, b) => a - b)
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

@@ -1,115 +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>
<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: 'harmonic-boot/detailedAnalysis/responsibility'
})
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

@@ -3,8 +3,12 @@
<DatePicker ref="datePickerRef" theCurrentTime style="display: none" />
<!-- 搜索框 -->
<div class="query-box-wrap">
<el-input v-model.trim="inputQuery" style="height: 46px; width: 334px" @keyup.enter="DeviceQ"
placeholder="请输入终端名称">
<el-input
v-model.trim="inputQuery"
style="height: 46px; width: 334px"
@keyup.enter="DeviceQ"
placeholder="请输入终端名称"
>
<template #prefix>
<div class="Icon"></div>
</template>
@@ -26,9 +30,12 @@
<span class="ml10" style="color: #0d867f">{{ item.count }}</span>
</template>
<div class="collapseBox">
<div class="group-list__item"
<div
class="group-list__item"
:style="colorKey == k.coordinate ? 'background-color: #009ea81a;' : ''"
v-for="k in item.psrList" @click="flyTo(k)">
v-for="k in item.psrList"
@click="flyTo(k)"
>
<p>{{ k.psrName }}</p>
<p>{{ k.vlevelName }}|{{ k.maintOrgName }}</p>
</div>
@@ -36,112 +43,167 @@
</el-collapse-item>
</el-collapse>
<div v-if="QueryList.length > 0 && !showCollapse" class="collapse_none" style="color: #009ea8"
@click="showCollapse = true">
<div
v-if="QueryList.length > 0 && !showCollapse"
class="collapse_none"
style="color: #009ea8"
@click="showCollapse = true"
>
展开搜索结果
</div>
<div class="collapse_none" style="color: red;cursor: pointer" @click="showWrap = false">关闭</div>
<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' >
<baidu-map
class="map"
:style="height"
@ready="initMap"
@zoomend="syncCenterAndZoom"
:center="center"
: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>
<div v-if="zoom > 13">
<bm-polyline :path="path" v-for="(path, index) in polyline" :key="index"></bm-polyline>
</div>
<!-- 变电站-->
<template v-if='zoom > 13'>
<bm-marker :position='path' v-for='path in siteList' :key='path.subId' :icon='path.icon'
@click='markerClick(path)'></bm-marker>
<template v-if="zoom > 13">
<bm-marker
:position="path"
v-for="path in siteList"
:key="path.subId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</template>
<!-- -->
<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">
<bm-label v-if='zoom > 14' :content="path.lineName"
:labelStyle="{ color: '#fff', border: '0px solid #fff', backgroundColor: 'rgba(0, 0, 0, 0.5)', borderRadius: '10px', padding: '2px 5px', fontSize: '12px', lineHeight: '15px', transform: 'translateX(-30%)' }"
:offset="{ height: 33 }" />
<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"
>
<bm-label
v-if="zoom > 14"
:content="path.lineName"
:labelStyle="{
color: '#fff',
border: '0px solid #fff',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderRadius: '10px',
padding: '2px 5px',
fontSize: '12px',
lineHeight: '15px',
transform: 'translateX(-30%)'
}"
:offset="{ height: 33 }"
/>
</bm-marker>
</div>
<!-- 详情 -->
<bm-marker :position='infoWindowPoint' :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show='infoWindowPoint.show' @close='infoWindowPoint.show = false'>
<el-descriptions :title='infoWindowPoint.lineName' :column='1' v-if='infoWindowPoint.lineId'>
<el-descriptions-item label='供电公司'>{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label='变电站'>{{ infoWindowPoint.subName }}</el-descriptions-item>
<el-descriptions-item label='母线'>{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label='网络参数'>
<bm-marker :position="infoWindowPoint" :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show="infoWindowPoint.show" @close="infoWindowPoint.show = false">
<el-descriptions :title="infoWindowPoint.lineName" :column="1" v-if="infoWindowPoint.lineId">
<el-descriptions-item label="供电公司">{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label="变电站(场站)">{{ infoWindowPoint.subName }}</el-descriptions-item>
<el-descriptions-item label="母线">{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ infoWindowPoint.ip }}
</el-descriptions-item>
<el-descriptions-item label='PT变化'>{{ infoWindowPoint.pt2 }}</el-descriptions-item>
<el-descriptions-item label='CT变化'>{{ infoWindowPoint.ct2 }}</el-descriptions-item>
<el-descriptions-item label='生产厂家'>
<el-descriptions-item label="PT变化">{{ infoWindowPoint.pt2 }}</el-descriptions-item>
<el-descriptions-item label="CT变化">{{ infoWindowPoint.ct2 }}</el-descriptions-item>
<el-descriptions-item label="生产厂家">
{{ infoWindowPoint.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label='终端状态'>
{{
infoWindowPoint.runFlag == 0 ? '投运' : infoWindowPoint.runFlag == 1 ? '热备用' : '停运'
}}
<el-descriptions-item label="终端状态">
{{ infoWindowPoint.runFlag == 0 ? '投运' : infoWindowPoint.runFlag == 1 ? '检修' : '停运' }}
</el-descriptions-item>
<el-descriptions-item label='通讯状态'>
<el-descriptions-item label="通讯状态">
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
</el-descriptions-item>
<el-descriptions-item>
<el-button type='primary' size='small' @click='lookPoint(infoWindowPoint)'>查看详情</el-button>
<el-button type="primary" size="small" @click="lookPoint(infoWindowPoint)">
查看详情
</el-button>
</el-descriptions-item>
</el-descriptions>
<el-descriptions :title='infoWindowPoint.subName' :column='1' v-else-if='infoWindowPoint.subId'
style='padding-top: 10px'></el-descriptions>
<el-descriptions
:title="infoWindowPoint.subName"
:column="1"
v-else-if="infoWindowPoint.subId"
style="padding-top: 10px"
></el-descriptions>
</bm-info-window>
</bm-marker>
<!-- 行政区划 -->
<div v-if='zoom <= 11'>
<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>
<bm-polygon
v-for="timeK in item.boundary"
:path="timeK"
:strokeWeight="2"
strokeColor="#0e8780"
: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 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 :
'/' }}
总数
<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 : '/' }}
{{ 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 :
'/' }}
告警
<br />
{{ PopKey == 2 ? item.alarm : PopKey == 1 ? item.xx : PopKey == 0 ? item.xx : '/' }}
</div>
</div>
</div>
</bm-overlay>
</div>
</baidu-map>
</div>
</template>
<script setup lang='ts'>
<script setup lang="ts">
import { mainHeight } from '@/utils/layout'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import { ref, reactive, onMounted } from 'vue'
@@ -152,7 +214,7 @@ 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';
import mapJson from './boundary'
const datePickerRef = ref()
const height = mainHeight(20)
// 页面中直接引入就可以
@@ -161,7 +223,7 @@ const inputQuery: any = ref('')
const QueryList: any = ref([])
const activeName: any = ref(0)
const zoomMap = ref(8.8)
const zoomMap = ref(8.9)
const colorKey = ref('')
const showCollapse: any = ref(true)
const showWrap: any = ref(false)
@@ -173,30 +235,100 @@ 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
// }
{
orgName: '唐山',
LngLat: [118.335849137, 39.7513593355],
boundary: mapJson.tsJSON
orgName: '大连',
LngLat: [122.060077, 39.635794],
boundary: mapJson['大连']
},
{
orgName: '张家口',
LngLat: [115.032504679, 40.8951549951],
boundary: mapJson.zjkJSON
orgName: '抚顺',
LngLat: [124.354599, 41.88962],
boundary: mapJson['抚顺']
},
{
orgName: '秦皇岛',
LngLat: [119.185113833, 40.1179119754],
boundary: mapJson.qhdJSON
orgName: '沈阳',
LngLat: [123.0389, 41.992993],
boundary: mapJson['沈阳']
},
{
orgName: '承德',
LngLat: [117.548498365, 41.3775890632],
boundary: mapJson.cdJSON
orgName: '丹东',
LngLat: [124.585661, 40.645967],
boundary: mapJson['丹东']
},
{
orgName: '廊坊',
LngLat: [116.628004129, 39.0589378611],
boundary: mapJson.lfJSON
orgName: '营口',
LngLat: [122.225226, 40.433551],
boundary: mapJson['营口']
},
{
orgName: '盘锦',
LngLat: [121.875362, 41.075416],
boundary: mapJson['盘锦']
},
{
orgName: '铁岭',
LngLat: [124.229492, 42.731873],
boundary: mapJson['铁岭']
},
{
orgName: '朝阳',
LngLat: [119.640944, 41.39657],
boundary: mapJson['朝阳']
},
{
orgName: '葫芦岛',
LngLat: [119.850873, 40.728517],
boundary: mapJson['葫芦岛']
},
{
orgName: '锦州',
LngLat: [121.42, 41.58],
boundary: mapJson['锦州']
},
{
orgName: '阜新',
LngLat: [121.658585, 42.350951],
boundary: mapJson['阜新']
},
{
orgName: '本溪',
LngLat: [124.390785, 41.197021],
boundary: mapJson['本溪']
},
{
orgName: '辽阳',
LngLat: [123.090785, 41.297021],
boundary: mapJson['辽阳']
},
{
orgName: '鞍山',
LngLat: [122.808845, 40.840049],
boundary: mapJson['鞍山']
}
])
@@ -206,7 +338,8 @@ const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const center = ref({
lng: 116.84428600000001, lat: 40.57707185292256
lng: 122.42588,
lat: 40.810977
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
@@ -214,11 +347,9 @@ const infoWindowPoint = ref<anyObj>({
show: false
})
// 地图实例
const initMap = async ({ BMap, map }: any) => {
}
const initMap = async ({ BMap, map }: any) => {}
// 加载点
const addMarkers = async (row?: any, key?: any, num?: any) => {
let params = {
deptIndex: deptIndex.value,
monitorFlag: 2,
@@ -309,15 +440,12 @@ const addMarkers = async (row?: any, key?: any, num?: any) => {
siteList.value = list
// center.value.lng = areaLineInfo.value[0].lng
// center.value.lat = areaLineInfo.value[0].lat
}
// 获取zoom
const syncCenterAndZoom = (e: any) => {
zoom.value = e.target.getZoom()
}
const locatePositions = (e: any) => {
deptIndex.value = e.data.id
// 加载点
addMarkers()
@@ -338,20 +466,18 @@ const markerClick = (e: any) => {
const lookPoint = (e: any) => {
emit('drop', e.lineId)
emit('show', true)
}
// 搜索
const DeviceQ = () => {
showCollapse.value = true
if (inputQuery.value.length == 0) return
let list = []
let regex = new RegExp(inputQuery.value, 'i')
let data = areaLineInfo.value.filter((item: any) => regex.test(item.lineName))
let data = areaLineInfo.value
.filter((item: any) => regex.test(item.lineName))
.map((item: any) => {
return {
psrName: item.lineName,
vlevelName: item.voltageScale,
maintOrgName: item.gdName,
@@ -360,7 +486,6 @@ const DeviceQ = () => {
})
// data.replace(//s/g,',')
if (data.length > 0) {
list.push({
count: data.length,
@@ -374,21 +499,18 @@ const DeviceQ = () => {
// 定位
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]
if (zoom) { zoomMap.value = zoom }
else {
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) => {
@@ -402,8 +524,8 @@ const grids = (row: any) => {
isUpToGrid: row.isUpToGrid,
monitorFlag: row.isUpToGrid == 0 ? null : row.isUpToGrid
}
AreaData.value=[]
assessList.value=[]
AreaData.value = []
assessList.value = []
// 综合评估
getAssessOverview(form).then(res => {
assessList.value = res.data?.children
@@ -416,29 +538,28 @@ const grids = (row: any) => {
})
}
const radiusPop = (k: any) => {
console.log("🚀 ~ radiusPop ~ k:", k)
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'
assessList.value &&
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) {
@@ -453,7 +574,7 @@ const GridDiagramArea = () => {
}, 0)
}
// 市级统计
const draw = ({ el, BMap, map }, val) => {
const draw = ({ el, BMap, map }, val = [0, 0]) => {
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'
@@ -463,8 +584,7 @@ const reset = () => {
inputQuery.value = ''
showWrap.value = false
}
onMounted(() => {
})
onMounted(() => {})
defineExpose({ addMarkers, locatePositions, reset, grids, radiusPop, flyTo })
</script>
<style lang="scss" scoped>
@@ -472,7 +592,6 @@ defineExpose({ addMarkers, locatePositions, reset, grids, radiusPop, flyTo })
.map {
width: 100%;
}
.query-box-wrap {
@@ -514,7 +633,8 @@ defineExpose({ addMarkers, locatePositions, reset, grids, radiusPop, flyTo })
}
}
}
}
:deep(.el-descriptions__cell) {
white-space: nowrap;
}
</style>
./cds.js./boundary

View File

@@ -1,329 +1,329 @@
<template>
<div style="position: relative; height: 100%" v-loading="loading">
<div class="iconBox">
<div class="div">
<img src="@/assets/jcd.png" alt="" />
<span>变电站(场站)</span>
</div>
<div class="div">
<img src="@/assets/rby.png" alt="" />
<span>检修</span>
</div>
<div class="div">
<img src="@/assets/ty.png" alt="" />
<span>停运</span>
</div>
<div class="div">投运</div>
<div class="div" style="padding-left: 10px">
<span>通讯正常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcwzj.png" alt="" />
<span>无暂降</span>
</div>
<div class="div" style="padding-left: 10px">
<span>通讯异常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txycyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzdwzj.png" alt="" />
<span>无暂降</span>
</div>
</div>
<!-- v-if="hackReset" -->
<baidu-map
class="bm-view"
:zoom="zoom"
:map-click="false"
:scroll-wheel-zoom="true"
:center="center"
@ready="handler"
@zoomend="syncCenterAndZoom"
:dragging="true"
>
<!-- <bm-map-type
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
anchor="BMAP_ANCHOR_TOP_RIGHT"
></bm-map-type> -->
<!-- 线-->
<div v-if="zoom > 13">
<bm-polyline :path="path" v-for="(path, index) in polyline" :key="index"></bm-polyline>
</div>
<!-- 变电站-->
<template v-if="zoom > 13">
<bm-marker
:position="path"
v-for="path in siteList"
:key="path.subId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</template>
<!-- -->
<BmlMarkerClusterer maxZoom="12">
<bm-marker
:position="path"
v-for="path in areaLineInfo"
:key="path.lineId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</BmlMarkerClusterer>
<bm-marker :position="infoWindowPoint" :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show="infoWindowPoint.show" @close="infoWindowPoint.show = false">
<el-descriptions
:title="infoWindowPoint.lineName"
style="min-width: 240px"
:column="1"
v-if="infoWindowPoint.lineId"
>
<el-descriptions-item label="供电公司">{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label="变电站(场站)">{{ infoWindowPoint.subName }}</el-descriptions-item>
<el-descriptions-item label="母线">{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ infoWindowPoint.ip }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ infoWindowPoint.pt1 }}/{{ infoWindowPoint.pt2 }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ infoWindowPoint.ct1 }}/{{ infoWindowPoint.ct2 }}
</el-descriptions-item>
<el-descriptions-item label="生产厂家">
{{ infoWindowPoint.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="终端状态">
{{ infoWindowPoint.runFlag == 0 ? '投运' : infoWindowPoint.runFlag == 1 ? '检修' : '停运' }}
</el-descriptions-item>
<el-descriptions-item label="通讯状态">
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
</el-descriptions-item>
<el-descriptions-item v-if="props.showBut">
<el-button type="primary" size="small" @click="changeTab('2')">事件统计</el-button>
<el-button type="primary" size="small" @click="changeTab('3')">事件分析</el-button>
<el-button type="primary" size="small" @click="changeTab('4')">运行情况</el-button>
</el-descriptions-item>
</el-descriptions>
<el-descriptions
:title="infoWindowPoint.subName"
:column="1"
v-else-if="infoWindowPoint.subId"
style="padding-top: 10px"
></el-descriptions>
</bm-info-window>
</bm-marker>
</baidu-map>
</div>
</template>
<script setup lang="ts">
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
import { onMounted, ref, watch } from 'vue'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
const emit = defineEmits(['changeTab'])
interface Props {
showBut?: boolean
mapList?: any
}
const props = withDefaults(defineProps<Props>(), {
showBut: true,
mapList: []
})
const monitoringPoint = useMonitoringPoint()
const adminInfo = useAdminInfo()
const datePickerRef = ref()
const zoom = ref(11)
const loading = ref(true)
const hackReset = ref(true)
const center = ref({
lng: 0,
lat: 0
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
lat: 0,
show: false
})
const areaLineInfo = ref<any>([])
const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const handler = async ({ BMap, map }: any) => {
let data = props.mapList
let r = 0.0035
let list = data.filter((item: any) => item.lng != 0)
list.forEach((item: any) => {
// 变电站图标
item.icon = {
url: new URL('@/assets/jcd.png', import.meta.url).href,
size: {
width: 40,
height: 40
}
}
if (item.children.length > 10 && item.children.length < 100) {
r = 0.0055
} else if (item.children.length >= 100) {
r = 0.01055
}
item.children.forEach((val: any, i: number) => {
val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
// 监测点图标
val.icon = {
url: '',
size: {
width: 40,
height: 40
}
}
switch (val.runFlag) {
case 0:
// 投运
if (val.comFlag == 0) {
// 异常
if (val.noDealCount > 0) {
// 异常有暂降
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 异常无暂降
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
}
} else if (val.comFlag == 1) {
// 正常
if (val.noDealCount > 0) {
// 正常有暂降
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 正常无暂降
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
}
}
break
case 1:
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
break
case 2:
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
break
default:
break
}
polyline.value.push([
{
lng: item.lng,
lat: item.lat
},
{
lng: val.lng,
lat: val.lat
}
])
})
areaLineInfo.value.push(...item.children)
})
siteList.value = list
center.value.lng = list[0]?.lng || 0
center.value.lat = list[0]?.lat + 0.01 || 0
watch(
() => monitoringPoint.state.lineId,
(newLineId, oldLineId) => {
let value = areaLineInfo.value.find((item: any) => item.lineId == newLineId)
if (value == undefined) return
center.value.lng = value.lng
center.value.lat = value.lat + 0.01
infoWindowPoint.value = value
infoWindowPoint.value.show = true
monitoringPoint.setValue(
'lineName',
value.manufacturer + '>' + value.gdName + '>' + value.subName + '>' + value.lineName
)
},
{ immediate: true }
)
zoom.value = 15
setTimeout(() => {
loading.value = false
}, 0)
}
const syncCenterAndZoom = (e: any) => {
zoom.value = e.target.getZoom()
}
const markerClick = (e: any) => {
infoWindowPoint.value = e
infoWindowPoint.value.show = true
}
const changeTab = (e: string) => {
emit('changeTab', e)
}
onMounted(() => {
if (siteList.value.length == 0) {
setTimeout(() => {
hackReset.value = false
}, 500)
setTimeout(() => {
hackReset.value = true
}, 1000)
}
})
</script>
<style lang="scss" scoped>
.bm-view {
width: 100%;
height: 100%;
}
.selectBox {
position: absolute;
top: 16px;
left: 165px;
z-index: 2000;
width: 240px;
}
.iconBox {
position: absolute;
bottom: 10px;
right: 10px;
z-index: 2000;
width: 150px;
height: 260px;
padding: 10px;
background: rgba(255, 255, 255, 0.75) !important;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
font-size: 12px;
.div {
display: flex;
margin-bottom: 5px;
img {
height: 20px;
margin-right: 5px;
}
}
}
:deep(.el-descriptions__cell) {
white-space: nowrap;
}
</style>
<template>
<div style="position: relative; height: 100%" v-loading="loading">
<div class="iconBox">
<div class="div">
<img src="@/assets/jcd.png" alt="" />
<span>变电站(场站)</span>
</div>
<div class="div">
<img src="@/assets/rby.png" alt="" />
<span>检修</span>
</div>
<div class="div">
<img src="@/assets/ty.png" alt="" />
<span>停运</span>
</div>
<div class="div">投运</div>
<div class="div" style="padding-left: 10px">
<span>通讯正常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcwzj.png" alt="" />
<span>无暂降</span>
</div>
<div class="div" style="padding-left: 10px">
<span>通讯异常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txycyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzdwzj.png" alt="" />
<span>无暂降</span>
</div>
</div>
<!-- v-if="hackReset" -->
<baidu-map
class="bm-view"
v-if="hackReset"
:zoom="zoom"
:map-click="false"
:scroll-wheel-zoom="true"
:center="center"
@ready="handler"
@zoomend="syncCenterAndZoom"
:dragging="true"
>
<!-- <bm-map-type
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
anchor="BMAP_ANCHOR_TOP_RIGHT"
></bm-map-type> -->
<!-- 线-->
<div v-if="zoom > 13">
<bm-polyline :path="path" v-for="(path, index) in polyline" :key="index"></bm-polyline>
</div>
<!-- 变电站-->
<template v-if="zoom > 13">
<bm-marker
:position="path"
v-for="path in siteList"
:key="path.subId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</template>
<!-- -->
<BmlMarkerClusterer maxZoom="12">
<bm-marker
:position="path"
v-for="path in areaLineInfo"
:key="path.lineId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</BmlMarkerClusterer>
<bm-marker :position="infoWindowPoint" :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show="infoWindowPoint.show" @close="infoWindowPoint.show = false">
<el-descriptions
:title="infoWindowPoint.lineName"
style="min-width: 240px"
:column="1"
v-if="infoWindowPoint.lineId"
>
<el-descriptions-item label="供电公司">{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label="变电站(场站)">{{ infoWindowPoint.subName }}</el-descriptions-item>
<el-descriptions-item label="母线">{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ infoWindowPoint.ip }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ infoWindowPoint.pt1 }}/{{ infoWindowPoint.pt2 }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ infoWindowPoint.ct1 }}/{{ infoWindowPoint.ct2 }}
</el-descriptions-item>
<el-descriptions-item label="生产厂家">
{{ infoWindowPoint.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="终端状态">
{{ infoWindowPoint.runFlag == 0 ? '投运' : infoWindowPoint.runFlag == 1 ? '检修' : '停运' }}
</el-descriptions-item>
<el-descriptions-item label="通讯状态">
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
</el-descriptions-item>
<el-descriptions-item v-if="props.showBut">
<el-button type="primary" size="small" @click="changeTab('2')">事件统计</el-button>
<el-button type="primary" size="small" @click="changeTab('3')">事件分析</el-button>
<el-button type="primary" size="small" @click="changeTab('4')">运行情况</el-button>
</el-descriptions-item>
</el-descriptions>
<el-descriptions
:title="infoWindowPoint.subName"
:column="1"
v-else-if="infoWindowPoint.subId"
style="padding-top: 10px"
></el-descriptions>
</bm-info-window>
</bm-marker>
</baidu-map>
</div>
</template>
<script setup lang="ts">
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
import { onMounted, ref, watch } from 'vue'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import { useMonitoringPoint } from '@/stores/monitoringPoint'
const emit = defineEmits(['changeTab'])
interface Props {
showBut?: boolean
mapList?: any
}
const props = withDefaults(defineProps<Props>(), {
showBut: true,
mapList: []
})
const monitoringPoint = useMonitoringPoint()
const adminInfo = useAdminInfo()
const datePickerRef = ref()
const zoom = ref(11)
const loading = ref(true)
const hackReset = ref(true)
const center = ref({
lng: 0,
lat: 0
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
lat: 0,
show: false
})
const areaLineInfo = ref<any>([])
const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const handler = async ({ BMap, map }: any) => {
let data = props.mapList
let r = 0.0035
let list = data.filter((item: any) => item.lng != 0)
list.forEach((item: any) => {
// 变电站图标
item.icon = {
url: new URL('@/assets/jcd.png', import.meta.url).href,
size: {
width: 40,
height: 40
}
}
if (item.children.length > 10 && item.children.length < 100) {
r = 0.0055
} else if (item.children.length >= 100) {
r = 0.01055
}
item.children.forEach((val: any, i: number) => {
val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
// 监测点图标
val.icon = {
url: '',
size: {
width: 40,
height: 40
}
}
switch (val.runFlag) {
case 0:
// 投运
if (val.comFlag == 0) {
// 异常
if (val.noDealCount > 0) {
// 异常有暂降
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 异常无暂降
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
}
} else if (val.comFlag == 1) {
// 正常
if (val.noDealCount > 0) {
// 正常有暂降
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 正常无暂降
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
}
}
break
case 1:
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
break
case 2:
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
break
default:
break
}
polyline.value.push([
{
lng: item.lng,
lat: item.lat
},
{
lng: val.lng,
lat: val.lat
}
])
})
areaLineInfo.value.push(...item.children)
})
siteList.value = list
center.value.lng = list[0]?.lng || 0
center.value.lat = list[0]?.lat + 0.01 || 0
watch(
() => monitoringPoint.state.lineId,
(newLineId, oldLineId) => {
let value = areaLineInfo.value.find((item: any) => item.lineId == newLineId)
if (value == undefined) return
center.value.lng = value.lng
center.value.lat = value.lat + 0.01
infoWindowPoint.value = value
infoWindowPoint.value.show = true
monitoringPoint.setValue(
'lineName',
value.manufacturer + '>' + value.gdName + '>' + value.subName + '>' + value.lineName
)
},
{ immediate: true }
)
zoom.value = 15
setTimeout(() => {
loading.value = false
}, 0)
}
const syncCenterAndZoom = (e: any) => {
zoom.value = e.target.getZoom()
}
const markerClick = (e: any) => {
infoWindowPoint.value = e
infoWindowPoint.value.show = true
}
const changeTab = (e: string) => {
emit('changeTab', e)
}
onMounted(() => {
if (siteList.value.length == 0) {
setTimeout(() => {
hackReset.value = false
}, 100)
setTimeout(() => {
hackReset.value = true
}, 1000)
}
})
</script>
<style lang="scss" scoped>
.bm-view {
width: 100%;
height: 100%;
}
.selectBox {
position: absolute;
top: 16px;
left: 165px;
z-index: 2000;
width: 240px;
}
.iconBox {
position: absolute;
bottom: 10px;
right: 10px;
z-index: 2000;
width: 150px;
height: 260px;
padding: 10px;
background: rgba(255, 255, 255, 0.75) !important;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
font-size: 12px;
.div {
display: flex;
margin-bottom: 5px;
img {
height: 20px;
margin-right: 5px;
}
}
}
:deep(.el-descriptions__cell) {
white-space: nowrap;
}
</style>

View File

@@ -1,382 +1,382 @@
<template>
<div style="padding: 10px; display: flex; height: 100%" v-loading="loading">
<div style="position: relative; flex: 1">
<div style="display: none">
<DatePicker ref="datePickerRef"></DatePicker>
</div>
<div class="iconBox">
<div class="div">
<img src="@/assets/jcd.png" alt="" />
<span>变电站(场站)</span>
</div>
<div class="div">
<img src="@/assets/rby.png" alt="" />
<span>检修</span>
</div>
<div class="div">
<img src="@/assets/ty.png" alt="" />
<span>停运</span>
</div>
<div class="div">投运</div>
<div class="div" style="padding-left: 10px">
<span>通讯正常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcwzj.png" alt="" />
<span>无暂降</span>
</div>
<div class="div" style="padding-left: 10px">
<span>通讯异常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txycyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzdwzj.png" alt="" />
<span>无暂降</span>
</div>
</div>
<div class="selectBox">
<el-select @change="pointChange" filterable clearable v-model="lineId" placeholder="输入监测点名称查询">
<el-option
v-for="item in areaLineInfo"
:key="item.lineId"
:label="item.lineName"
:value="item.lineId"
></el-option>
</el-select>
</div>
<!-- v-if="hackReset" -->
<baidu-map
class="bm-view"
:zoom="zoom"
:map-click="false"
:scroll-wheel-zoom="true"
:center="center"
@ready="handler"
:dragging="true"
@zoomend="syncCenterAndZoom"
>
<!-- <bm-map-type
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
anchor="BMAP_ANCHOR_TOP_RIGHT"
></bm-map-type> -->
<!-- 线-->
<div v-if="zoom > 13">
<bm-polyline :path="path" v-for="(path, index) in polyline" :key="index"></bm-polyline>
</div>
<!-- 变电站-->
<template v-if="zoom > 13">
<bm-marker
:position="path"
v-for="path in siteList"
:key="path.subId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</template>
<!-- -->
<BmlMarkerClusterer maxZoom="12">
<bm-marker
:position="path"
v-for="path in areaLineInfo"
:key="path.lineId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</BmlMarkerClusterer>
<bm-marker :position="infoWindowPoint" :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show="infoWindowPoint.show" @close="infoWindowPoint.show = false">
<el-descriptions :title="infoWindowPoint.lineName" :column="1" v-if="infoWindowPoint.lineId">
<el-descriptions-item label="供电公司">{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label="变电站(场站)">
{{ infoWindowPoint.subName }}
</el-descriptions-item>
<el-descriptions-item label="母线">{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ infoWindowPoint.ip }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ infoWindowPoint.pt1 }}/{{ infoWindowPoint.pt2 }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ infoWindowPoint.ct1 }}/{{ infoWindowPoint.ct2 }}
</el-descriptions-item>
<el-descriptions-item label="生产厂家">
{{ infoWindowPoint.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="终端状态">
{{
infoWindowPoint.runFlag == 0
? '投运'
: infoWindowPoint.runFlag == 1
? '检修'
: '停运'
}}
</el-descriptions-item>
<el-descriptions-item label="通讯状态">
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
</el-descriptions-item>
<el-descriptions-item>
<!-- <el-button type="primary" size="small" @click="lookPoint">查看监测点</el-button> -->
<el-button type="primary" size="small" @click="lookEvent">
暂态事件({{ infoWindowPoint.noDealCount }})
</el-button>
</el-descriptions-item>
</el-descriptions>
<el-descriptions
:title="infoWindowPoint.subName"
:column="1"
v-else-if="infoWindowPoint.subId"
style="padding-top: 10px"
></el-descriptions>
</bm-info-window>
</bm-marker>
</baidu-map>
</div>
<div style="width: 600px; height: 100%">
<Right :params="params" v-if="params.deptIndex"></Right>
</div>
<PopupEvent ref="popupEvent"></PopupEvent>
</div>
</template>
<script setup lang="ts">
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
import { ref, onMounted } from 'vue'
import { mainHeight } from '@/utils/layout'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import Right from './right.vue'
import PopupEvent from './popupEvent.vue'
import router from '@/router'
defineOptions({
name: 'Descentsystem/overview'
}) // 添加响应式变量
const height = mainHeight(20)
const adminInfo = useAdminInfo()
const datePickerRef = ref()
const hackReset = ref(true)
const zoom = ref(13)
const loading = ref(true)
const popupEvent = ref()
const params = ref({
deptIndex: '',
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot',
statisticalType: {}
})
const center = ref({
lng: 0,
lat: 0
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
lat: 0,
show: false
})
const areaLineInfo = ref<any>([])
const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const handler = async ({ BMap, map }: any) => {
params.value.deptIndex = adminInfo.$state.deptId
params.value.searchBeginTime = datePickerRef.value.timeValue[0]
params.value.searchEndTime = datePickerRef.value.timeValue[1]
let { data } = await getAreaLineInfo(params.value)
let r = 0.0035
let list = data.filter((item: any) => item.lng != 0)
list.forEach((item: any) => {
// 变电站图标
item.icon = {
url: new URL('@/assets/jcd.png', import.meta.url).href,
size: {
width: 40,
height: 40
}
}
if (item.children.length > 10 && item.children.length < 100) {
r = 0.0055
} else if (item.children.length >= 100) {
r = 0.01055
}
item.children.forEach((val: any, i: number) => {
val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
// 监测点图标
val.icon = {
url: '',
size: {
width: 40,
height: 40
}
}
switch (val.runFlag) {
case 0:
// 投运
if (val.comFlag == 0) {
// 异常
if (val.noDealCount > 0) {
// 异常有暂降
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 异常无暂降
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
}
} else if (val.comFlag == 1) {
// 正常
if (val.noDealCount > 0) {
// 正常有暂降
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 正常无暂降
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
}
}
break
case 1:
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
break
case 2:
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
break
default:
break
}
polyline.value.push([
{
lng: item.lng,
lat: item.lat
},
{
lng: val.lng,
lat: val.lat
}
])
})
areaLineInfo.value.push(...item.children)
})
setTimeout(() => {
loading.value = false
}, 0)
siteList.value = list
center.value.lng = areaLineInfo.value[0]?.lng || 0
center.value.lat = areaLineInfo.value[0]?.lat + 0.04 || 0
infoWindowPoint.value = areaLineInfo.value[0] || {}
infoWindowPoint.value.show = true
zoom.value = 13
setTimeout(() => {
loading.value = false
}, 1500)
}
const syncCenterAndZoom = (e: any) => {
zoom.value = e.target.getZoom()
}
const pointChange = (val: string) => {
if (!val) return
let data = areaLineInfo.value.find((item: any) => item.lineId == val)
center.value.lng = data.lng
center.value.lat = data.lat + 0.04
infoWindowPoint.value = data
infoWindowPoint.value.show = true
zoom.value = 13
}
const markerClick = (e: any) => {
infoWindowPoint.value = e
infoWindowPoint.value.show = true
}
const lookEvent = (e: any) => {
popupEvent.value.open({
id: infoWindowPoint.value.lineId,
searchBeginTime: datePickerRef.value.timeValue[0],
searchEndTime: datePickerRef.value.timeValue[1]
})
}
const lookPoint = () => {
console.log(infoWindowPoint.value)
router.replace({
name: 'Descentsystem/monitoringpoint',
query: {
lineId: infoWindowPoint.value.lineId,
lineName:
infoWindowPoint.value.manufacturer +
'>' +
infoWindowPoint.value.gdName +
'>' +
infoWindowPoint.value.subName +
'>' +
infoWindowPoint.value.lineName
}
})
}
onMounted(() => {
if (siteList.value.length == 0) {
setTimeout(() => {
if (window.localStorage.getItem('BMAP_SECKEY') == null) {
hackReset.value = false
}
}, 500)
setTimeout(() => {
hackReset.value = true
}, 1000)
}
})
</script>
<style lang="scss" scoped>
.bm-view {
width: 100%;
height: 100%;
}
.selectBox {
position: absolute;
top: 16px;
left: 165px;
z-index: 2000;
width: 240px;
}
.iconBox {
position: absolute;
top: 10px;
left: 10px;
z-index: 2000;
width: 150px;
height: 260px;
padding: 10px;
background: rgba(255, 255, 255, 0.75) !important;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
font-size: 12px;
.div {
display: flex;
margin-bottom: 5px;
img {
height: 20px;
margin-right: 5px;
}
}
}
:deep(.el-descriptions__cell) {
white-space: nowrap;
}
</style>
<template>
<div style="padding: 10px; display: flex; height: 100%" v-loading="loading">
<div style="position: relative; flex: 1">
<div style="display: none">
<DatePicker ref="datePickerRef"></DatePicker>
</div>
<div class="iconBox">
<div class="div">
<img src="@/assets/jcd.png" alt="" />
<span>变电站(场站)</span>
</div>
<div class="div">
<img src="@/assets/rby.png" alt="" />
<span>检修</span>
</div>
<div class="div">
<img src="@/assets/ty.png" alt="" />
<span>停运</span>
</div>
<div class="div">投运</div>
<div class="div" style="padding-left: 10px">
<span>通讯正常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzcwzj.png" alt="" />
<span>无暂降</span>
</div>
<div class="div" style="padding-left: 10px">
<span>通讯异常</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txycyzj.gif" alt="" />
<span>有暂降</span>
</div>
<div class="div" style="padding-left: 20px">
<img src="@/assets/txzdwzj.png" alt="" />
<span>无暂降</span>
</div>
</div>
<div class="selectBox">
<el-select @change="pointChange" filterable clearable v-model="lineId" placeholder="输入监测点名称查询">
<el-option
v-for="item in areaLineInfo"
:key="item.lineId"
:label="item.lineName"
:value="item.lineId"
></el-option>
</el-select>
</div>
<!-- v-if="hackReset" -->
<baidu-map
class="bm-view"
v-if="hackReset"
:zoom="zoom"
:map-click="false"
:scroll-wheel-zoom="true"
:center="center"
@ready="handler"
:dragging="true"
@zoomend="syncCenterAndZoom"
>
<!-- <bm-map-type
:map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"
anchor="BMAP_ANCHOR_TOP_RIGHT"
></bm-map-type> -->
<!-- 线-->
<div v-if="zoom > 13">
<bm-polyline :path="path" v-for="(path, index) in polyline" :key="index"></bm-polyline>
</div>
<!-- 变电站-->
<template v-if="zoom > 13">
<bm-marker
:position="path"
v-for="path in siteList"
:key="path.subId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</template>
<!-- -->
<BmlMarkerClusterer maxZoom="12">
<bm-marker
:position="path"
v-for="path in areaLineInfo"
:key="path.lineId"
:icon="path.icon"
@click="markerClick(path)"
></bm-marker>
</BmlMarkerClusterer>
<bm-marker :position="infoWindowPoint" :icon="{ url: '1', size: { width: 0, height: 0 } }">
<bm-info-window :show="infoWindowPoint.show" @close="infoWindowPoint.show = false">
<el-descriptions :title="infoWindowPoint.lineName" :column="1" v-if="infoWindowPoint.lineId">
<el-descriptions-item label="供电公司">{{ infoWindowPoint.gdName }}</el-descriptions-item>
<el-descriptions-item label="变电站(场站)">
{{ infoWindowPoint.subName }}
</el-descriptions-item>
<el-descriptions-item label="母线">{{ infoWindowPoint.voltageName }}</el-descriptions-item>
<el-descriptions-item label="网络参数">
{{ infoWindowPoint.ip }}
</el-descriptions-item>
<el-descriptions-item label="PT变比">
{{ infoWindowPoint.pt1 }}/{{ infoWindowPoint.pt2 }}
</el-descriptions-item>
<el-descriptions-item label="CT变比">
{{ infoWindowPoint.ct1 }}/{{ infoWindowPoint.ct2 }}
</el-descriptions-item>
<el-descriptions-item label="生产厂家">
{{ infoWindowPoint.manufacturer }}
</el-descriptions-item>
<el-descriptions-item label="终端状态">
{{
infoWindowPoint.runFlag == 0
? '投运'
: infoWindowPoint.runFlag == 1
? '检修'
: '停运'
}}
</el-descriptions-item>
<el-descriptions-item label="通讯状态">
{{ infoWindowPoint.comFlag == 0 ? '中断' : '正常' }}
</el-descriptions-item>
<el-descriptions-item>
<!-- <el-button type="primary" size="small" @click="lookPoint">查看监测点</el-button> -->
<el-button type="primary" size="small" @click="lookEvent">
暂态事件({{ infoWindowPoint.noDealCount }})
</el-button>
</el-descriptions-item>
</el-descriptions>
<el-descriptions
:title="infoWindowPoint.subName"
:column="1"
v-else-if="infoWindowPoint.subId"
style="padding-top: 10px"
></el-descriptions>
</bm-info-window>
</bm-marker>
</baidu-map>
</div>
<div style="width: 600px; height: 100%">
<Right :params="params" v-if="params.deptIndex"></Right>
</div>
<PopupEvent ref="popupEvent"></PopupEvent>
</div>
</template>
<script setup lang="ts">
import { BmlMarkerClusterer } from 'vue-baidu-map-3x'
import { ref, onMounted } from 'vue'
import { mainHeight } from '@/utils/layout'
import { getAreaLineInfo } from '@/api/event-boot/areaInfo'
import DatePicker from '@/components/form/datePicker/index.vue'
import { useAdminInfo } from '@/stores/adminInfo'
import Right from './right.vue'
import PopupEvent from './popupEvent.vue'
import router from '@/router'
defineOptions({
name: 'Descentsystem/overview'
}) // 添加响应式变量
const height = mainHeight(20)
const adminInfo = useAdminInfo()
const datePickerRef = ref()
const hackReset = ref(true)
const zoom = ref(13)
const loading = ref(true)
const popupEvent = ref()
const params = ref({
deptIndex: '',
monitorFlag: 2,
powerFlag: 2,
searchBeginTime: '',
searchEndTime: '',
serverName: 'event-boot',
statisticalType: {}
})
const center = ref({
lng: 0,
lat: 0
})
const infoWindowPoint = ref<anyObj>({
lng: 0,
lat: 0,
show: false
})
const areaLineInfo = ref<any>([])
const siteList = ref<any>([])
const polyline = ref<any>([])
const lineId = ref('')
const handler = async ({ BMap, map }: any) => {
params.value.deptIndex = adminInfo.$state.deptId
params.value.searchBeginTime = datePickerRef.value.timeValue[0]
params.value.searchEndTime = datePickerRef.value.timeValue[1]
let { data } = await getAreaLineInfo(params.value)
let r = 0.0035
let list = data.filter((item: any) => item.lng != 0)
list.forEach((item: any) => {
// 变电站图标
item.icon = {
url: new URL('@/assets/jcd.png', import.meta.url).href,
size: {
width: 40,
height: 40
}
}
if (item.children.length > 10 && item.children.length < 100) {
r = 0.0055
} else if (item.children.length >= 100) {
r = 0.01055
}
item.children.forEach((val: any, i: number) => {
val.lng = item.lng + r * Math.cos((2 * Math.PI * i) / item.children.length)
val.lat = item.lat + r * Math.sin((2 * Math.PI * i) / item.children.length)
// 监测点图标
val.icon = {
url: '',
size: {
width: 40,
height: 40
}
}
switch (val.runFlag) {
case 0:
// 投运
if (val.comFlag == 0) {
// 异常
if (val.noDealCount > 0) {
// 异常有暂降
val.icon.url = new URL('@/assets/txycyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 异常无暂降
val.icon.url = new URL('@/assets/txzdwzj.png', import.meta.url).href
}
} else if (val.comFlag == 1) {
// 正常
if (val.noDealCount > 0) {
// 正常有暂降
val.icon.url = new URL('@/assets/txzcyzj.gif', import.meta.url).href
} else if (val.noDealCount == 0) {
// 正常无暂降
val.icon.url = new URL('@/assets/txzcwzj.png', import.meta.url).href
}
}
break
case 1:
val.icon.url = new URL('@/assets/rby.png', import.meta.url).href
break
case 2:
val.icon.url = new URL('@/assets/ty.png', import.meta.url).href
break
default:
break
}
polyline.value.push([
{
lng: item.lng,
lat: item.lat
},
{
lng: val.lng,
lat: val.lat
}
])
})
areaLineInfo.value.push(...item.children)
})
setTimeout(() => {
loading.value = false
}, 0)
siteList.value = list
center.value.lng = areaLineInfo.value[0]?.lng || 0
center.value.lat = areaLineInfo.value[0]?.lat + 0.04 || 0
infoWindowPoint.value = areaLineInfo.value[0] || {}
infoWindowPoint.value.show = true
zoom.value = 13
setTimeout(() => {
loading.value = false
}, 1500)
}
const syncCenterAndZoom = (e: any) => {
zoom.value = e.target.getZoom()
}
const pointChange = (val: string) => {
if (!val) return
let data = areaLineInfo.value.find((item: any) => item.lineId == val)
center.value.lng = data.lng
center.value.lat = data.lat + 0.04
infoWindowPoint.value = data
infoWindowPoint.value.show = true
zoom.value = 13
}
const markerClick = (e: any) => {
infoWindowPoint.value = e
infoWindowPoint.value.show = true
}
const lookEvent = (e: any) => {
popupEvent.value.open({
id: infoWindowPoint.value.lineId,
searchBeginTime: datePickerRef.value.timeValue[0],
searchEndTime: datePickerRef.value.timeValue[1]
})
}
const lookPoint = () => {
console.log(infoWindowPoint.value)
router.replace({
name: 'Descentsystem/monitoringpoint',
query: {
lineId: infoWindowPoint.value.lineId,
lineName:
infoWindowPoint.value.manufacturer +
'>' +
infoWindowPoint.value.gdName +
'>' +
infoWindowPoint.value.subName +
'>' +
infoWindowPoint.value.lineName
}
})
}
onMounted(() => {
if (siteList.value.length == 0) {
setTimeout(() => {
if (window.localStorage.getItem('BMAP_SECKEY') == null) {
hackReset.value = false
}
}, 100)
setTimeout(() => {
hackReset.value = true
}, 1000)
}
})
</script>
<style lang="scss" scoped>
.bm-view {
width: 100%;
height: 100%;
}
.selectBox {
position: absolute;
top: 16px;
left: 165px;
z-index: 2000;
width: 240px;
}
.iconBox {
position: absolute;
top: 10px;
left: 10px;
z-index: 2000;
width: 150px;
height: 260px;
padding: 10px;
background: rgba(255, 255, 255, 0.75) !important;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
font-size: 12px;
.div {
display: flex;
margin-bottom: 5px;
img {
height: 20px;
margin-right: 5px;
}
}
}
:deep(.el-descriptions__cell) {
white-space: nowrap;
}
</style>

View File

@@ -1,97 +1,97 @@
<template>
<el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" title="修改密码">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef">
<el-form-item label="新密码" prop="newPwd">
<el-input v-model="form.newPwd" type="password" placeholder="请输入新密码" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="confirmPwd">
<el-input v-model="form.confirmPwd" type="password" placeholder="请输入确认密码" show-password />
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { validatePwd } from '@/utils/common'
import { passwordConfirm, updatePassword } from '@/api/user-boot/user'
import { debug } from 'console'
const formRef = ref()
const tableStore = inject('tableStore') as TableStore
const form = reactive({
id: '',
newPwd: '',
confirmPwd: '',
loginName: ''
})
const rules = {
newPwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 12,
message: '长度在 6 到 12 个字符',
trigger: 'blur'
},
{ validator: validatePwd, trigger: 'blur' }
],
confirmPwd: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{
min: 6,
max: 12,
message: '长度在 6 到 12 个字符',
trigger: 'blur'
},
{
validator: (rule: any, value: string, callback: any) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== form.newPwd) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
},
trigger: 'blur',
required: true
}
]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (id: string, loginName: string) => {
form.id = id
form.loginName = loginName
form.newPwd = ''
form.confirmPwd = ''
dialogVisible.value = true
}
const submit = async () => {
formRef.value.validate((valid: boolean) => {
if (valid) {
updatePassword({
id: form.id,
newPassword: form.newPwd
}).then((res: any) => {
ElMessage.success('密码修改成功')
dialogVisible.value = false
})
}
})
}
defineExpose({ open })
</script>
<template>
<el-dialog draggable width="500px" v-model="dialogVisible" title="修改密码">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef">
<el-form-item label="新密码" prop="newPwd">
<el-input v-model="form.newPwd" type="password" placeholder="请输入新密码" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="confirmPwd">
<el-input v-model="form.confirmPwd" type="password" placeholder="请输入确认密码" show-password />
</el-form-item>
</el-form>
</el-scrollbar>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { validatePwd } from '@/utils/common'
import { passwordConfirm, updatePassword } from '@/api/user-boot/user'
import { debug } from 'console'
const formRef = ref()
const tableStore = inject('tableStore') as TableStore
const form = reactive({
id: '',
newPwd: '',
confirmPwd: '',
loginName: ''
})
const rules = {
newPwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 12,
message: '长度在 6 到 12 个字符',
trigger: 'blur'
},
{ validator: validatePwd, trigger: 'blur' }
],
confirmPwd: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{
min: 6,
max: 12,
message: '长度在 6 到 12 个字符',
trigger: 'blur'
},
{
validator: (rule: any, value: string, callback: any) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== form.newPwd) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
},
trigger: 'blur',
required: true
}
]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (id: string, loginName: string) => {
form.id = id
form.loginName = loginName
form.newPwd = ''
form.confirmPwd = ''
dialogVisible.value = true
}
const submit = async () => {
formRef.value.validate((valid: boolean) => {
if (valid) {
updatePassword({
id: form.id,
newPassword: form.newPwd
}).then((res: any) => {
ElMessage.success('密码修改成功')
dialogVisible.value = false
})
}
})
}
defineExpose({ open })
</script>

View File

@@ -1,133 +1,139 @@
<template>
<div class="default-main">
<div v-show="show && lookShow">
<TableHeader ref="TableHeaderRef">
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
<luckysheet ref="luckysheetRef" v-if="!show" @shutDown="shutDown" />
<!-- 查看 -->
<look ref="lookRef" v-if="!lookShow" @shutDown="shutDown" />
<!-- 绑定 -->
<department ref="departmentRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { delTemplate } from '@/api/harmonic-boot/luckyexcel'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import luckysheet from './luckysheet.vue'
import look from './look.vue'
import department from './department.vue'
defineOptions({
name: 'Distributedphotovoltaic/templateConfiguration'
})
const luckysheetRef = ref()
const lookRef = ref()
const departmentRef = ref()
const show = ref(true)
const lookShow = ref(true)
const tableStore: any = new TableStore({
url: '/harmonic-boot/customReport/getTemplateList',
method: 'POST',
isWebPaging: true,
column: [
{ field: 'name', title: '报表模板名称' },
{ field: 'updateBy', title: '操作用户' },
{ field: 'createTime', title: '创建时间' },
{ field: 'updateTime', title: '更新时间' },
{ field: 'activation', title: '状态' },
{
title: '操作',
width: '220',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '查看 ',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
lookShow.value = false
setTimeout(() => {
lookRef.value.open(row)
}, 10)
}
},
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('编辑报表模板', row)
}, 10)
}
},
// {
// name: 'edit',
// title: '绑定',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: row => {
// departmentRef.value.open(row)
// }
// },
{
name: 'del',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除?'
},
click: row => {
delTemplate({ tempId: row.id, deptId: row.deptId }).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {}
})
tableStore.table.params = {}
tableStore.table.params.pageSize = 20
tableStore.table.params.pageNum = 1
provide('tableStore', tableStore)
// 关闭
const shutDown = () => {
show.value = true
lookShow.value = true
tableStore.index()
}
const add = () => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('新增报表模板')
}, 10)
}
onMounted(() => {
tableStore.index()
})
</script>
<template>
<div class="default-main">
<div v-show="show && lookShow">
<TableHeader ref="TableHeaderRef">
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
<luckysheet ref="luckysheetRef" v-if="!show" @shutDown="shutDown" />
<!-- 查看 -->
<look ref="lookRef" v-if="!lookShow" @shutDown="shutDown" />
<!-- 绑定 -->
<department ref="departmentRef" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { delTemplate } from '@/api/harmonic-boot/luckyexcel'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import luckysheet from './luckysheet.vue'
import look from './look.vue'
import department from './department.vue'
defineOptions({
name: 'Distributedphotovoltaic/templateConfiguration'
})
const luckysheetRef = ref()
const lookRef = ref()
const departmentRef = ref()
const show = ref(true)
const lookShow = ref(true)
const tableStore: any = new TableStore({
url: '/harmonic-boot/customReport/getTemplateList',
method: 'POST',
isWebPaging: true,
column: [
{ field: 'name', title: '报表模板名称' },
{ field: 'updateBy', title: '操作用户' },
{ field: 'createTime', title: '创建时间' },
{ field: 'updateTime', title: '更新时间' },
{
field: 'activation',
title: '状态',
formatter(row) {
return row.cellValue == 1 ? '激活' : '未激活'
}
},
{
title: '操作',
width: '220',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '查看 ',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
lookShow.value = false
setTimeout(() => {
lookRef.value.open(row)
}, 10)
}
},
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('编辑报表模板', row)
}, 10)
}
},
// {
// name: 'edit',
// title: '绑定',
// type: 'primary',
// icon: 'el-icon-Plus',
// render: 'basicButton',
// click: row => {
// departmentRef.value.open(row)
// }
// },
{
name: 'del',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除?'
},
click: row => {
delTemplate({ tempId: row.id, deptId: row.deptId }).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {}
})
tableStore.table.params = {}
tableStore.table.params.pageSize = 20
tableStore.table.params.pageNum = 1
provide('tableStore', tableStore)
// 关闭
const shutDown = () => {
show.value = true
lookShow.value = true
tableStore.index()
}
const add = () => {
show.value = false
setTimeout(() => {
luckysheetRef.value.open('新增报表模板')
}, 10)
}
onMounted(() => {
tableStore.index()
})
</script>