修改测试bug 优化页面

This commit is contained in:
guanj
2026-01-04 14:55:31 +08:00
parent cc0f8bc8b6
commit a765cdf9ee
68 changed files with 5396 additions and 3096 deletions

View File

@@ -5,7 +5,7 @@
<div class="title">角色列表</div>
<el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增</el-button>
</div>
<Table ref="tableRef" @currentChange="currentChange" />
<Table ref="tableRef" :row-config="{ isCurrent: true, isHover: true }" @currentChange="currentChange" />
</div>
<Tree
v-if="menuListId"
@@ -13,8 +13,8 @@
show-checkbox
width="350px"
:data="menuTree"
:checkStrictly="checkStrictly"
@check-change="checkChange"
:checkStrictly="false"
@checkChange="checkChange"
></Tree>
<el-empty style="width: 350px; padding-top: 300px; box-sizing: border-box" description="请选择角色" v-else />
<PopupForm ref="popupRef"></PopupForm>
@@ -26,7 +26,7 @@ import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import Tree from '@/components/tree/index.vue'
import Tree from '@/components/tree/allocation.vue'
import { functionTree } from '@/api/user-boot/function'
import { getFunctionsByRoleIndex, updateRoleMenu } from '@/api/user-boot/roleFuction'
import { mainHeight } from '@/utils/layout'
@@ -43,6 +43,7 @@ const height = mainHeight(20).height
const treeRef = ref()
const menuTree = ref<treeData[]>([])
const popupRef = ref()
const tableRef = ref()
const checkStrictly = ref(true)
const menuListId = ref('')
const tableStore = new TableStore({
@@ -104,7 +105,13 @@ const tableStore = new TableStore({
}
]
}
]
],
loadCallback: () => {
tableRef.value.getRef().setCurrentRow(tableStore.table.data[0])
currentChange({
row: tableStore.table.data[0]
})
}
})
tableStore.table.params.searchValue = ''
@@ -139,21 +146,22 @@ const currentChange = (data: any) => {
const timeout = ref<NodeJS.Timeout>()
const checkChange = (data: any) => {
if (checkStrictly.value) {
checkStrictly.value = false
return
}
if (timeout.value) {
clearTimeout(timeout.value)
}
timeout.value = setTimeout(() => {
updateRoleMenu({
id: menuListId.value,
idList: treeRef.value.treeRef.getCheckedNodes(false, true).map((node: any) => node.id)
}).then(() => {
// if (checkStrictly.value) {
// checkStrictly.value = false
// return
// }
updateRoleMenu({
id: menuListId.value,
idList: treeRef.value.treeRef.getCheckedNodes(false, true).map((node: any) => node.id)
})
.then(() => {
ElMessage.success('操作成功!')
treeRef.value.loading = false
})
.catch(() => {
treeRef.value.loading = false
})
}, 1000)
}
onMounted(() => {
tableStore.index()

View File

@@ -83,14 +83,14 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center' },
{ title: '工程名称', field: 'engineeringName', align: 'center' },
{ title: '项目名称', field: 'projectName', align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', width: 180, sortable: true },
{ title: '设备名称', field: 'equipmentName', align: 'center',minWidth: 100 },
{ title: '工程名称', field: 'engineeringName', align: 'center',minWidth: 100 },
{ title: '项目名称', field: 'projectName', align: 'center',minWidth: 100 },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{
title: '模块信息',
field: 'moduleNo',
align: 'center',
align: 'center',minWidth: 100 ,
formatter: (row: any) => {
return row.cellValue ? row.cellValue : '/'
}
@@ -107,7 +107,7 @@ const tableStore = new TableStore({
},
{
title: '事件描述',
minWidth: 220,
minWidth: 250,
field: 'showName'
},
{

View File

@@ -35,10 +35,10 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '前置服务器名称', field: 'lineId', align: 'center' },
{ title: '前置服务器ip', field: 'wavePath', align: 'center' },
{ title: '进程号', field: 'clDid', align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 80, sortable: true },
{ title: '前置服务器名称', field: 'lineId', align: 'center' ,minWidth: 120 },
{ title: '前置服务器ip', field: 'wavePath', align: 'center' ,minWidth: 100 },
{ title: '进程号', field: 'clDid', align: 'center',minWidth: 60 },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180, sortable: true },
{
title: '事件描述',
@@ -48,7 +48,8 @@ const tableStore = new TableStore({
{
title: '告警代码',
field: 'code',
align: 'center',
align: 'center',minWidth: 100 ,
formatter: (row: any) => {
return row.cellValue ? '\u200B' + row.cellValue : '/'

View File

@@ -128,15 +128,15 @@ const tableStore = new TableStore({
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '设备名称', field: 'equipmentName', align: 'center' },
{ title: '工程名称', field: 'engineeringName', align: 'center' },
{ title: '项目名称', field: 'projectName', align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', width: '240',sortable: true },
{ title: '监测点名称', field: 'lineName', align: 'center' },
{ title: '事件描述', field: 'showName', align: 'center' },
{ title: '事件发生位置', field: 'evtParamPosition', align: 'center' },
{ title: '相别', field: 'evtParamPhase', align: 'center' },
{ title: '持续时间(s)', field: 'evtParamTm', align: 'center',sortable: true },
{ title: '设备名称', field: 'equipmentName', minWidth: 120,align: 'center' },
{ title: '工程名称', field: 'engineeringName', minWidth: 120,align: 'center' },
{ title: '项目名称', field: 'projectName', minWidth: 120,align: 'center' },
{ title: '发生时刻', field: 'startTime', align: 'center', minWidth: 180,sortable: true },
{ title: '监测点名称', field: 'lineName', minWidth: 120,align: 'center' },
{ title: '事件描述', field: 'showName', minWidth: 120,align: 'center' },
{ title: '事件发生位置', field: 'evtParamPosition',minWidth: 150, align: 'center' },
{ title: '相别', field: 'evtParamPhase',minWidth: 80, align: 'center' },
{ title: '持续时间(s)', field: 'evtParamTm',minWidth: 80, align: 'center',sortable: true },
{ title: '暂降(聚升)幅值(%)', minWidth: 100, field: 'evtParamVVaDepth', align: 'center',sortable: true },
{
@@ -166,7 +166,7 @@ const tableStore = new TableStore({
boxoList.value = row
boxoList.value.featureAmplitude =
row.evtParamVVaDepth != '-' ? row.evtParamVVaDepth - 0 : null
boxoList.value.systemType = 'WX'
boxoList.value.systemType = 'ZL'
wp.value = res.data
}
loading.value = false

View File

@@ -77,7 +77,6 @@
</el-descriptions-item> -->
</el-descriptions>
<el-tabs v-model.trim="dataSet" type="border-card" class="device-control-box-card" @tab-click="handleClick">
<el-tab-pane
lazy
:label="item.name"
@@ -87,7 +86,7 @@
>
<template #label>
<span class="custom-tabs-label">
<el-icon>
<!-- <el-icon>
<TrendCharts v-if="item.name == 'APF模块数据'" />
<DataLine v-if="item.name == '历史APF模块数据'" />
<DataAnalysis v-if="item.name.includes('趋势数据')" />
@@ -113,7 +112,7 @@
!item.name.includes('暂态事件')
"
/>
</el-icon>
</el-icon> -->
<span>{{ item.name }}</span>
</span>
</template>
@@ -157,7 +156,7 @@
</el-select> -->
<el-radio-group
v-model.trim="formInline.dataLevel"
v-if="!dataSet.includes('_moduleData')"
v-if="!dataSet.includes('_moduleData') && TrendList?.lineType == 1"
:disabled="TrendList?.lineType != 1"
@change="handleClick"
>
@@ -733,14 +732,14 @@ const handleHarmonicSpectrum = async () => {
// getRealDataMqttMsg()
await getBasicRealData(lineId.value).then((res: any) => {
if (res.code == 'A0000') {
ElMessage.success('装置应答成功')
ElMessage.success('装置应答成功')
// mqttMessage.value = {}
realDataTimer.value = window.setInterval(() => {
if (!dataSet.value.includes('_realtimedata')) return
getBasicRealData(lineId.value).then((res: any) => {
console.log(res, '获取基础实时数据')
console.log(res, '获取基础实时数据')
})
}, 30000)
}
@@ -838,8 +837,8 @@ const devData: any = ref({})
const lineId: any = ref('')
const dataLevel: any = ref('')
const dataSource = ref([])
const nodeClick = async (e: anyObj) => {
console.log("🚀 ~ nodeClick ~ e:", e)
const engineeringName = ref('')
const nodeClick = async (e: anyObj, node: any) => {
if (e == undefined || e.level == 2) {
return (loading.value = false)
}
@@ -855,6 +854,8 @@ const nodeClick = async (e: anyObj) => {
//选中设备名称后,点击标签页也能查询数据,要求点击设备名称后,点击标签页默认查询第一个监测点数据
if (e.level == 3 || e.level == 2) {
engineeringName.value = node?.parent.parent.data.name
await queryDictType({
lineId: e?.id,
conType: e.conType
@@ -985,44 +986,42 @@ const getRealDataMqttMsg = async () => {
JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
)
let obj = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
if (lineId.value != obj.lineId || adminInfo.userIndex != obj.userId) return
//处理mqtt数据 1转2除 2转1乘
//如果消息返回值是二次值,下拉框是二次值只需要单位换算 除以1000
//如果消息返回值是一次值,下拉框是一次值只需要单位换算 除以1000
if (obj.dataLevel == formInline.dataLevel) {
obj = {
...obj,
// 电压有效值
vRmsA: obj.vRmsA ,
vRmsB: obj.vRmsB ,
vRmsC: obj.vRmsC ,
vRmsA: obj.vRmsA,
vRmsB: obj.vRmsB,
vRmsC: obj.vRmsC,
//基波电压幅值
v1A: obj.v1A ,
v1B: obj.v1B ,
v1C: obj.v1C ,
v1A: obj.v1A,
v1B: obj.v1B,
v1C: obj.v1C,
//有功功率
pA: obj.pA ,
pB: obj.pB ,
pC: obj.pC ,
pTot: obj.pTot ,
pA: obj.pA,
pB: obj.pB,
pC: obj.pC,
pTot: obj.pTot,
//无功功率
qA: obj.qA ,
qB: obj.qB ,
qC: obj.qC ,
qTot: obj.qTot ,
qA: obj.qA,
qB: obj.qB,
qC: obj.qC,
qTot: obj.qTot,
//视在功率
sA: obj.sA ,
sB: obj.sB ,
sC: obj.sC ,
sTot: obj.sTot
sA: obj.sA,
sB: obj.sB,
sC: obj.sC,
sTot: obj.sTot
}
}
//如果消息返回值是二次值,下拉框是一次值需要单位换算 除以1000 并且乘以pt ct
if (obj.dataLevel == 'Secondary' && formInline.dataLevel == 'Primary') {
obj = {
...obj,
// 电压有效值
@@ -1103,9 +1102,11 @@ const getRealDataMqttMsg = async () => {
}
if (obj.hasOwnProperty('pA') && obj.hasOwnProperty('pB')) {
mqttMessage.value = obj
//更新实时数据主页面值
realTimeFlag.value && realTimeRef.value && realTimeRef.value.setRealData(mqttMessage.value,formInline.dataLevel)
realTimeFlag.value &&
realTimeRef.value &&
realTimeRef.value.setRealData(mqttMessage.value, formInline.dataLevel)
tableLoading.value = false
//更新实时趋势折线图数据
if (sonTab.value == 2) {
@@ -1229,6 +1230,7 @@ const handleClick = async (tab?: any) => {
let obj = {
devId: deviceId.value, //e.id
lineId: lineId.value, //e.pid
engineeringName: engineeringName.value, //e.name
type: 3,
list: [
{
@@ -1423,9 +1425,7 @@ const echoName = (value: any, arr: any[]) => {
return value ? arr.find(item => item.value == value)?.label : '/'
}
onMounted(() => {
})
onMounted(() => {})
onBeforeUnmount(() => {
clearInterval(realDataTimer.value)
clearInterval(trendTimer.value)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,13 @@
<div class="view">
<TableHeader datePicker ref="headerRef" v-if="!isWaveCharts" :showReset="false"></TableHeader>
<Table ref="tableRef" v-if="!isWaveCharts" />
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
<waveFormAnalysis
v-loading="loading"
v-if="isWaveCharts"
ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false"
:wp="wp"
/>
</div>
</template>
<script lang="ts" setup>
@@ -15,7 +20,7 @@ import TableHeader from '@/components/table/header/index.vue'
import waveFormAnalysis from './components/waveFormAnalysis.vue'
import { ArrowLeft, Message } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { analyseWave,getFileByEventId } from '@/api/common'
import { analyseWave, getFileByEventId } from '@/api/common'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
const tableParams: any = ref({})
const refheader = ref()
@@ -31,12 +36,11 @@ const waveFormAnalysisRef = ref()
const headerRef = ref()
const props = defineProps({
deviceType: {
type: String,
default: '0'
}
});
deviceType: {
type: String,
default: '0'
}
})
const tableStore: any = new TableStore({
url: '/cs-device-boot/csGroup/deviceDataByType',
@@ -45,7 +49,9 @@ const tableStore: any = new TableStore({
column: [
// { width: '60', type: 'checkbox', fixed: 'left' },
{
title: '序号', width: 80, formatter: (row: any) => {
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
@@ -65,10 +71,11 @@ const tableStore: any = new TableStore({
title: '持续时间(s)',
minWidth: 100,
formatter: (row: any) => {
console.log('row.cellValue', row.cellValue)
console.log('row.cellValue', row.cellValue)
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue
}, sortable: true
},
sortable: true
},
{
field: 'featureAmplitude',
@@ -109,7 +116,9 @@ const tableStore: any = new TableStore({
row.loading1 = false
if (res != undefined) {
boxoList.value = row
boxoList.value.systemType = 'WX'
boxoList.value.systemType = 'YPT'
boxoList.value.engineeringName = tableParams.value.engineeringName
console.log("🚀 ~ tableParams.value.engineeringName:", tableParams.value.engineeringName)
wp.value = res.data
view.value = false
view2.value = true
@@ -134,7 +143,7 @@ const tableStore: any = new TableStore({
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.showName != '未知';
return row.showName != '未知'
}
},
{
@@ -158,25 +167,24 @@ const tableStore: any = new TableStore({
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
})
}
},
{
name: 'edit',
title: '波形补召',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
return props.deviceType === '2' && row.wavePath || row.showName === '未知';
},
click: row => {
getFileByEventId(row.id).then(res => {
name: 'edit',
title: '波形补召',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
return (props.deviceType === '2' && row.wavePath) || row.showName === '未知'
},
click: row => {
getFileByEventId(row.id).then(res => {
ElMessage.success(res.message)
tableStore.index()
})
}
}
}
]
}
@@ -186,9 +194,10 @@ const tableStore: any = new TableStore({
tableStore.table.params.devId = tableParams.value.devId
tableStore.table.params.lineId = tableParams.value.lineId
tableStore.table.params.list = tableParams.value.list
console.log('🚀 ~ ableParams.value:', tableParams.value)
tableStore.table.params.type = 3
},
loadCallback: () => { }
loadCallback: () => {}
})
provide('tableStore', tableStore)
const isWaveCharts = ref(false)

View File

@@ -232,6 +232,7 @@ const init = async () => {
loading.value = true
// 选择指标的时候切换legend内容和data数据
let list: any = []
echartsData.value={}
legendDictList.value?.selectedList?.map((item: any) => {
searchForm.value.index.map((vv: any) => {
if (item.dataType == vv) {

View File

@@ -1,5 +1,5 @@
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<div class=" device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<GetMarketList @node-click="selectUser" @selectUser="selectUser"></GetMarketList>
<div class="device-manage-right" :style="{ height: pageHeight.height }">
<el-descriptions title="用户基本信息" class="mb10" :column="2" border>
@@ -65,10 +65,10 @@ import { queryByUseId, add, removeMarketData, queryEnginnerByUseId } from '@/api
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const pageHeight = mainHeight(20)
const pageHeight = mainHeight(60)
const loading = ref(true)
const tableHeight = mainHeight(135)
const tableHeight = mainHeight(173)
const user: any = ref({})
const tableData = ref([])
const tableData2 = ref([])

View File

@@ -1,5 +1,5 @@
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<div class=" device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<OfficialUserTree @node-click="selectUser" @selectUser="selectUser"></OfficialUserTree>
<div class="device-manage-right" :style="{ height: pageHeight.height }">
<div class="el-descriptions__header">
@@ -134,7 +134,7 @@ import { add, removeUserDev, queryDevByUseId } from '@/api/cs-system-boot/offici
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const pageHeight = mainHeight(20)
const pageHeight = mainHeight(60)
const loading = ref(true)
const user: any = ref({})

View File

@@ -0,0 +1,22 @@
<template>
<div class="default-main">
<el-tabs type="border-card" v-model="activeName">
<el-tab-pane label="营销用户" name="1"><Disposition v-if="activeName == '1'" /></el-tab-pane>
<el-tab-pane label="正式用户" name="2"><OfficialUser v-if="activeName == '2'" /></el-tab-pane>
<el-tab-pane label="游客" name="3"><Tourist v-if="activeName == '3'" /></el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import Disposition from '@/views/govern/device/disposition/index.vue'
import OfficialUser from '@/views/govern/device/officialUser/index.vue'
import Tourist from '@/views/govern/device/tourist/index.vue'
const activeName = ref('1')
</script>
<style lang="scss" scoped>
:deep(.el-tabs--border-card > .el-tabs__content) {
padding: 0px;
}
</style>

View File

@@ -1,191 +1,191 @@
<template>
<div>
<Table ref="tableRef" v-if="!isWaveCharts" />
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</div>
<!-- <TableHeader :showReset="false">
</TableHeader> -->
</template>
<script setup lang='ts'>
import { ref, provide, onMounted, nextTick } from 'vue'
import { getEventByItem } from '@/api/cs-device-boot/planData'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { ElMessage } from 'element-plus'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue';
import { analyseWave } from '@/api/common'
import { mainHeight } from '@/utils/layout'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
const props = defineProps({
activeName: String,
activeColName: [Object, String]
})
const loading = ref(false)
const waveFormAnalysisRef = ref()
const isWaveCharts = ref(false)
const boxoList: any = ref([])
const wp = ref({})
const tableStore = new TableStore({
url: '/cs-harmonic-boot/data/getEventByItem',
method: 'POST',
paramsPOST: true,
showPage: false,
publicHeight: 355,
column: [
// { width: '60', type: 'checkbox', fixed: 'left' },
{
title: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 170 },
{
field: 'phaseType',
title: '相别',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue : '/'
return row.cellValue
}
},
{
field: 'persistTime',
title: '持续时间(s)',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue
}, sortable: true
},
{
field: 'featureAmplitude',
title: '暂降(聚升)幅值(%)',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
if (String(row.cellValue).split('.')[1] == '00') {
row.cellValue = String(row.cellValue).split('.')[0]
}
return row.cellValue
}, sortable: true
},
{
title: '操作',
width: 180,
render: 'buttons',
fixed: 'right',
buttons: [
{
name: 'edit',
title: '波形分析',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
loading: 'loading1',
disabled: row => {
// && row.evtParamTm < 20
return !row.wavePath
},
click: async row => {
row.loading1 = true
loading.value = true
isWaveCharts.value = true
await analyseWave(row.id)
.then(res => {
row.loading1 = false
if (res != undefined) {
boxoList.value = row
boxoList.value.systemType = 'WX'
wp.value = res.data
}
loading.value = false
})
.catch(() => {
row.loading1 = false
loading.value = false
})
nextTick(() => {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
setHeight()
})
}
},
{
name: 'edit',
text: '暂无波形',
type: 'info',
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.wavePath
}
},
{
name: 'edit',
title: '波形下载',
type: 'primary',
loading: 'loading2',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
// && row.evtParamTm < 20
return !row.wavePath
},
click: row => {
getFileZip({ eventId: row.id }).then(res => {
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = row.wavePath.split('/')[2] || '波形文件' // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
})
}
}
]
}
],
loadCallback: () => {
}
})
const setHeight = () => {
if (props.activeColName == '0') {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(350, 485)
tableStore.table.height = mainHeight(380).height
} else {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(350, 350)
tableStore.table.height = mainHeight(240).height
}
}
provide('tableStore', tableStore)
const init = () => {
tableStore.table.params.id = props.activeName
// getEventByItem({ id: props.activeName }).then(res => {
// })
tableStore.index()
}
onMounted(() => {
})
defineExpose({ init, setHeight })
</script>
<style lang="scss" scoped></style>
<template>
<div>
<Table ref="tableRef" v-if="!isWaveCharts" />
<waveFormAnalysis v-loading="loading" v-if="isWaveCharts" ref="waveFormAnalysisRef"
@handleHideCharts="isWaveCharts = false" :wp="wp" />
</div>
<!-- <TableHeader :showReset="false">
</TableHeader> -->
</template>
<script setup lang='ts'>
import { ref, provide, onMounted, nextTick } from 'vue'
import { getEventByItem } from '@/api/cs-device-boot/planData'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { ElMessage } from 'element-plus'
import waveFormAnalysis from '@/views/govern/device/control/tabs/components/waveFormAnalysis.vue';
import { analyseWave } from '@/api/common'
import { mainHeight } from '@/utils/layout'
import { getFileZip } from '@/api/cs-harmonic-boot/datatrend'
const props = defineProps({
activeName: String,
activeColName: [Object, String]
})
const loading = ref(false)
const waveFormAnalysisRef = ref()
const isWaveCharts = ref(false)
const boxoList: any = ref([])
const wp = ref({})
const tableStore = new TableStore({
url: '/cs-harmonic-boot/data/getEventByItem',
method: 'POST',
paramsPOST: true,
showPage: false,
publicHeight: 355,
column: [
// { width: '60', type: 'checkbox', fixed: 'left' },
{
title: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ field: 'startTime', title: '发生时刻', minWidth: 170, sortable: true },
{ field: 'showName', title: '事件描述', minWidth: 170 },
{
field: 'phaseType',
title: '相别',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue : '/'
return row.cellValue
}
},
{
field: 'persistTime',
title: '持续时间(s)',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue ? row.cellValue.toFixed(2) : '/'
return row.cellValue
}, sortable: true
},
{
field: 'featureAmplitude',
title: '暂降(聚升)幅值(%)',
minWidth: 100,
formatter: (row: any) => {
row.cellValue = row.cellValue + '' ? row.cellValue.toFixed(2) : '/'
if (String(row.cellValue).split('.')[1] == '00') {
row.cellValue = String(row.cellValue).split('.')[0]
}
return row.cellValue
}, sortable: true
},
{
title: '操作',
width: 180,
render: 'buttons',
fixed: 'right',
buttons: [
{
name: 'edit',
title: '波形分析',
type: 'primary',
icon: 'el-icon-Check',
render: 'basicButton',
loading: 'loading1',
disabled: row => {
// && row.evtParamTm < 20
return !row.wavePath
},
click: async row => {
row.loading1 = true
loading.value = true
isWaveCharts.value = true
await analyseWave(row.id)
.then(res => {
row.loading1 = false
if (res != undefined) {
boxoList.value = row
boxoList.value.systemType = 'YPT'
wp.value = res.data
}
loading.value = false
})
.catch(() => {
row.loading1 = false
loading.value = false
})
nextTick(() => {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.getWpData(wp.value, boxoList.value, true)
setHeight()
})
}
},
{
name: 'edit',
text: '暂无波形',
type: 'info',
icon: 'el-icon-DataLine',
render: 'basicButton',
disabled: row => {
return row.wavePath
}
},
{
name: 'edit',
title: '波形下载',
type: 'primary',
loading: 'loading2',
icon: 'el-icon-Check',
render: 'basicButton',
disabled: row => {
// && row.evtParamTm < 20
return !row.wavePath
},
click: row => {
getFileZip({ eventId: row.id }).then(res => {
let blob = new Blob([res], { type: 'application/zip' }) // console.log(blob) // var href = window.URL.createObjectURL(blob); //创建下载的链接
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = row.wavePath.split('/')[2] || '波形文件' // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link) //释放标签
})
}
}
]
}
],
loadCallback: () => {
}
})
const setHeight = () => {
if (props.activeColName == '0') {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(350, 485)
tableStore.table.height = mainHeight(380).height
} else {
waveFormAnalysisRef.value && waveFormAnalysisRef.value.setHeight(350, 350)
tableStore.table.height = mainHeight(240).height
}
}
provide('tableStore', tableStore)
const init = () => {
tableStore.table.params.id = props.activeName
// getEventByItem({ id: props.activeName }).then(res => {
// })
tableStore.index()
}
onMounted(() => {
})
defineExpose({ init, setHeight })
</script>
<style lang="scss" scoped></style>

View File

@@ -1,95 +1,96 @@
<template>
<div class="default-main device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree
:showCheckbox="true"
:default-checked-keys="defaultCheckedKeys"
@checkChange="checkChange"
></DeviceTree>
<div class="device-manage-right" :style="{ height: pageHeight.height }">
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
<vxe-column field="enginerName" title="工程名称"></vxe-column>
<vxe-column field="projectName" title="项目名称"></vxe-column>
<vxe-column field="deviceName" title="装置名称"></vxe-column>
</vxe-table>
</div>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: 'govern/tourist/index'
})
import { defaultAttribute } from '@/components/table/defaultAttribute'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { mainHeight } from '@/utils/layout'
import { getVisitorConfig, updateVisitorConfig } from '@/api/cs-device-boot/user'
import { ref, onMounted } from 'vue'
const pageHeight = mainHeight(20)
const loading = ref(true)
const defaultCheckedKeys: any = ref([])
const tableData = ref([])
const checkChange = (data: any) => {
if (data.data.level === 2) {
if (data.checked) {
defaultCheckedKeys.value.push(data.data.id)
} else {
defaultCheckedKeys.value.splice(defaultCheckedKeys.value.indexOf(data.data.id), 1)
}
loading.value = true
updateVisitorConfigs()
}
}
const updateVisitorConfigs = () => {
const result = Array.from(new Set(defaultCheckedKeys.value))
updateVisitorConfig(
result.map(item => {
return {
deviceId: item
}
})
).then((res: any) => {
if (res.code === 'A0000') {
getVisitorConfigs()
}
})
}
const getVisitorConfigs = () => {
getVisitorConfig().then((res:any) => {
if (res.code === 'A0000') {
tableData.value = res.data
loading.value = false
if (defaultCheckedKeys.value.length > 0) return
defaultCheckedKeys.value = [] // 清空
res.data.forEach((item:any) => {
defaultCheckedKeys.value.push(item.deviceId)
})
}
})
}
onMounted(() => {
// if (!adminInfo.token) return router.push({ name: 'login' })
getVisitorConfigs()
})
</script>
<style lang="scss">
.device-manage {
display: flex;
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
}
}
</style>
<template>
<div class=" device-manage" :style="{ height: pageHeight.height }" v-loading="loading">
<DeviceTree
:showCheckbox="true"
:default-checked-keys="defaultCheckedKeys"
@checkChange="checkChange"
:height="35"
></DeviceTree>
<div class="device-manage-right" :style="{ height: pageHeight.height }">
<vxe-table v-bind="defaultAttribute" :data="tableData" height="auto" style="width: 100%">
<vxe-column field="enginerName" title="工程名称"></vxe-column>
<vxe-column field="projectName" title="项目名称"></vxe-column>
<vxe-column field="deviceName" title="装置名称"></vxe-column>
</vxe-table>
</div>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: 'govern/tourist/index'
})
import { defaultAttribute } from '@/components/table/defaultAttribute'
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { mainHeight } from '@/utils/layout'
import { getVisitorConfig, updateVisitorConfig } from '@/api/cs-device-boot/user'
import { ref, onMounted } from 'vue'
const pageHeight = mainHeight(60)
const loading = ref(true)
const defaultCheckedKeys: any = ref([])
const tableData = ref([])
const checkChange = (data: any) => {
if (data.data.level === 2) {
if (data.checked) {
defaultCheckedKeys.value.push(data.data.id)
} else {
defaultCheckedKeys.value.splice(defaultCheckedKeys.value.indexOf(data.data.id), 1)
}
loading.value = true
updateVisitorConfigs()
}
}
const updateVisitorConfigs = () => {
const result = Array.from(new Set(defaultCheckedKeys.value))
updateVisitorConfig(
result.map(item => {
return {
deviceId: item
}
})
).then((res: any) => {
if (res.code === 'A0000') {
getVisitorConfigs()
}
})
}
const getVisitorConfigs = () => {
getVisitorConfig().then((res:any) => {
if (res.code === 'A0000') {
tableData.value = res.data
loading.value = false
if (defaultCheckedKeys.value.length > 0) return
defaultCheckedKeys.value = [] // 清空
res.data.forEach((item:any) => {
defaultCheckedKeys.value.push(item.deviceId)
})
}
})
}
onMounted(() => {
// if (!adminInfo.token) return router.push({ name: 'login' })
getVisitorConfigs()
})
</script>
<style lang="scss">
.device-manage {
display: flex;
&-right {
overflow: hidden;
flex: 1;
padding: 10px 10px 10px 0;
.el-descriptions__header {
height: 36px;
margin-bottom: 7px;
display: flex;
align-items: center;
}
}
}
</style>

View File

@@ -1,165 +1,165 @@
<template>
<div class="default-main">
<TableHeader ref="tableHeaderRef">
<template #select>
<el-form-item label="装置型号:">
<el-select v-model.trim="tableStore.table.params.devType" placeholder="请选择装置型号" clearable>
<el-option v-for="item in DevTypeOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button :icon="Plus" type="primary" @click="addMenu" class="ml10">新增版本</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<PopupVersion ref="popupVersionRef" v-if="showPopup"></PopupVersion>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { delCsDictData } from '@/api/system-boot/csDictData'
import { ElMessage } from 'element-plus'
import { queryByCode, queryByid } from '@/api/system-boot/dictTree'
import { useDictData } from '@/stores/dictData'
import PopupVersion from '@/views/govern/manage/basic/popupVersion.vue'
import { Plus } from '@element-plus/icons-vue'
import { auditEdData } from '@/api/cs-device-boot/edData'
defineOptions({
name: 'govern/manage/basic/version'
})
const popupVersionRef = ref()
const dictData = useDictData()
const showPopup = ref(false)
const DevTypeOptions = ref()
const tableHeaderRef = ref()
const tableStore = new TableStore({
url: '/cs-device-boot/edData/queryEdDataPage',
method: 'POST',
column: [
{ title: '装置型号', field: 'devTypeName' },
{ title: '版本号', field: 'versionNo' },
{ title: '版本协议', field: 'versionAgreement' },
{ title: '版本日期', field: 'versionDate' },
{ title: '归档日期', field: 'updateTime' },
{ title: '描述', field: 'description' },
{
title: '状态', field: 'status', render: 'tag',
custom: {
1: 'error',
0: 'success',
},
replaceValue: {
1: '禁用',
0: '启用',
}
},
{
title: '操作',
align: 'center',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
popupVersionRef.value.open('编辑版本', row)
}
},
{
name: 'edit',
title: '启用',
type: 'primary',
icon: 'el-icon-Open',
render: 'basicButton',
disabled: row => {
return row.status == 1
},
click: row => {
auditEdData({
id: row.id,
status: 1
}).then((res: any) => {
ElMessage.success('启用成功')
tableStore.index()
})
}
},
{
name: 'del',
title: '禁用',
type: 'danger',
icon: 'el-icon-SwitchButton',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定禁用吗?'
},
disabled: row => {
return row.status == 0
},
click: row => {
auditEdData({
id: row.id,
status: 0
}).then((res: any) => {
ElMessage.success('禁用成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {
tableStore.table.data.forEach((item: any) => {
item.statusName = item.status == 1 ? '禁用' : '启用'
for (let key in item) {
if (typeof item[key] !== 'number') {
item[key] = item[key] || '/'
}
}
})
}
})
queryByCode('Device_Type').then(res => {
const id = res.data.id
queryByid(id).then(res1 => {
res1.data.map((item: any, index: any) => {
if (item.pid == id) {
res1.data.splice(index, 1)
}
})
console.log("🚀 ~ res1.data.map ~ res1.data:", res1.data)
DevTypeOptions.value = res1.data
})
})
tableStore.table.params.devType = ''
provide('tableStore', tableStore)
onMounted(() => {
tableHeaderRef.value.onComSearch()
})
const addMenu = () => {
showPopup.value = true
setTimeout(() => {
popupVersionRef.value.open('新增版本')
}, 100)
}
</script>
<template>
<div class="default-main">
<TableHeader ref="tableHeaderRef">
<template #select>
<el-form-item label="装置型号:">
<el-select v-model.trim="tableStore.table.params.devType" placeholder="请选择装置型号" clearable>
<el-option v-for="item in DevTypeOptions" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button :icon="Plus" type="primary" @click="addMenu" class="ml10">新增版本</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<PopupVersion ref="popupVersionRef" v-if="showPopup"></PopupVersion>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { delCsDictData } from '@/api/system-boot/csDictData'
import { ElMessage } from 'element-plus'
import { queryByCode, queryByid } from '@/api/system-boot/dictTree'
import { useDictData } from '@/stores/dictData'
import PopupVersion from '@/views/govern/manage/basic/popupVersion.vue'
import { Plus } from '@element-plus/icons-vue'
import { auditEdData } from '@/api/cs-device-boot/edData'
defineOptions({
name: 'govern/manage/basic/version'
})
const popupVersionRef = ref()
const dictData = useDictData()
const showPopup = ref(false)
const DevTypeOptions = ref()
const tableHeaderRef = ref()
const tableStore = new TableStore({
url: '/cs-device-boot/edData/queryEdDataPage',
method: 'POST',
column: [
{ title: '装置型号', field: 'devTypeName' },
{ title: '版本号', field: 'versionNo' },
{ title: '版本协议', field: 'versionAgreement' },
{ title: '版本日期', field: 'versionDate' },
{ title: '归档日期', field: 'updateTime' },
{ title: '描述', field: 'description' },
{
title: '状态', field: 'status', render: 'tag',
custom: {
0: 'error',
1: 'success',
},
replaceValue: {
0: '禁用',
1: '启用',
}
},
{
title: '操作',
align: 'center',
width: '180',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
popupVersionRef.value.open('编辑版本', row)
}
},
{
name: 'edit',
title: '启用',
type: 'primary',
icon: 'el-icon-Open',
render: 'basicButton',
disabled: row => {
return row.status == 1
},
click: row => {
auditEdData({
id: row.id,
status: 1
}).then((res: any) => {
ElMessage.success('启用成功')
tableStore.index()
})
}
},
{
name: 'del',
title: '禁用',
type: 'danger',
icon: 'el-icon-SwitchButton',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定禁用吗?'
},
disabled: row => {
return row.status == 0
},
click: row => {
auditEdData({
id: row.id,
status: 0
}).then((res: any) => {
ElMessage.success('禁用成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {
tableStore.table.data.forEach((item: any) => {
item.statusName = item.status == 1 ? '禁用' : '启用'
for (let key in item) {
if (typeof item[key] !== 'number') {
item[key] = item[key] || '/'
}
}
})
}
})
queryByCode('Device_Type').then(res => {
const id = res.data.id
queryByid(id).then(res1 => {
res1.data.map((item: any, index: any) => {
if (item.pid == id) {
res1.data.splice(index, 1)
}
})
console.log("🚀 ~ res1.data.map ~ res1.data:", res1.data)
DevTypeOptions.value = res1.data
})
})
tableStore.table.params.devType = ''
provide('tableStore', tableStore)
onMounted(() => {
tableHeaderRef.value.onComSearch()
})
const addMenu = () => {
showPopup.value = true
setTimeout(() => {
popupVersionRef.value.open('新增版本')
}, 100)
}
</script>

View File

@@ -6,7 +6,7 @@
<el-button type="primary" :icon="Setting" @click="recall2">波形补召</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<Table ref="tableRef" />
</div>
</template>
@@ -16,17 +16,16 @@ import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { Setting } from '@element-plus/icons-vue'
import {eventRecall,fileRecall,logRecall} from '@/api/cs-device-boot/recall'
import { eventRecall, fileRecall, logRecall } from '@/api/cs-device-boot/recall'
import { ElMessage } from 'element-plus'
import { el } from 'element-plus/es/locale'
const props = defineProps({
checkedNodes: {
type: Array,
default: () => []
}
});
})
const tableStore: any = new TableStore({
url: '/cs-device-boot/csTerminalReply/bzLogs',
@@ -34,14 +33,16 @@ const tableStore: any = new TableStore({
method: 'POST',
column: [
{
title: '序号', width: 80, formatter: (row: any) => {
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{
{
field: 'engineeringName',
title: '项目名称',
width: 120,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
@@ -49,23 +50,23 @@ const tableStore: any = new TableStore({
{
field: 'projectName',
title: '工程名称',
width: 120,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{
{
field: 'deviceName',
title: '设备名称',
width: 120,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{
{
field: 'lineName',
title: '监测点名称',
width: 120,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
@@ -73,23 +74,23 @@ const tableStore: any = new TableStore({
{
field: 'logTime',
title: '补召时间',
width: 160,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{
{
field: 'log',
title: '类型',
width: 80,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
{
{
field: 'status',
title: '状态',
width: 80,
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
@@ -97,25 +98,22 @@ const tableStore: any = new TableStore({
{
field: 'result',
title: '结果',
formatter: row => {
return row.cellValue ? row.cellValue : '/'
}
},
}
],
beforeSearchFun: () => {
if (!nodeClick.value || nodeClick.value.level !== 3) {
ElMessage.warning('请先选中监测点')
return // 阻止查询
return // 阻止查询
}
if (nodeClick.value) {
tableStore.table.params.searchValue = nodeClick.value.id
}
},
loadCallback: () => {
}
loadCallback: () => {}
})
provide('tableStore', tableStore)
@@ -127,19 +125,18 @@ const handleTreeNodeClick = (node: any) => {
if (tableStore && tableStore.index) {
// 判断当前节点是否为监测点层级
if (node) {
if (node.level !== 3) {
if (node.level !== 3) {
ElMessage.warning('请先选中监测点')
return
}
}else {
ElMessage.warning('请先选中监测点')
return
} else {
ElMessage.warning('请先选中监测点')
return
}
tableStore.index()
}
}
const recall1 = async () => {
if (!props.checkedNodes || props.checkedNodes.length === 0) {
ElMessage.warning('请先勾选监测点')
@@ -163,13 +160,12 @@ const recall2 = async () => {
await fileRecall({
startTime: tableStore.table.params.startTime,
endTime: tableStore.table.params.endTime,
lineList: props.checkedNodes.map((node: any) => node.id)
lineList: props.checkedNodes.map((node: any) => node.id)
}).then((res: any) => {
ElMessage.success('补召波形成功')
})
}
// 暴露方法给父组件调用
defineExpose({
handleTreeNodeClick
@@ -194,4 +190,4 @@ defineExpose({
.view :deep(.el-table) {
height: calc(100% - 56px);
}
</style>
</style>

View File

@@ -1,214 +1,229 @@
<template>
<el-dialog
draggable
:title="title"
v-model.trim="dialogVisible"
width="500px"
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form ref="formRef" :rules="rules" :model="form" label-width="90px" class="form">
<el-form-item label="项目名称:" prop="name">
<el-input
maxlength="32"
show-word-limit
v-model.trim="form.name"
placeholder="请输入项目名称"
></el-input>
</el-form-item>
<el-form-item label="工程项目:" class="top" prop="projectIds">
<el-tree-select
v-model.trim="form.projectIds"
default-expand-all
show-checkbox
node-key="id"
:props="defaultProps"
multiple
:data="Engineering"
collapse-tags
style="width: 100%"
/>
<!-- <el-cascader v-model.trim="form.projectIds" :options="Engineering" :props="defaultProps"
:show-all-levels="false" collapse-tags collapse-tags-tooltip clearable style="width: 100%;"/> -->
</el-form-item>
<el-form-item label="项目排序:" prop="orderBy">
<el-input
maxlength="32"
show-word-limit-number
v-model.trim="form.orderBy"
:min="0"
:step="1"
step-strictly
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注:" class="top">
<el-input
maxlength="300"
show-word-limit
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addFn">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { deviceTree, add, audit, getztProjectTree } from '@/api/cs-harmonic-boot/mxgraph'
import { ElMessage, ElMessageBox } from 'element-plus'
const title = ref('')
const formRef = ref()
const Engineering = ref([])
const dialogVisible = ref(false)
const emit = defineEmits(['submit'])
const defaultProps = {
children: 'children',
value: 'id',
label: 'name',
multiple: true,
expandTrigger: 'hover' as const
}
const form: any = reactive({
name: '',
projectIds: [],
orderBy: '100',
remark: ''
})
const rules = {
name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
projectIds: [{ required: true, message: '请选择工程项目', trigger: 'change' }],
orderBy: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const addFn = () => {
console.log('🚀 ~ add ~ form:', form)
formRef.value.validate((valid: boolean) => {
if (valid) {
if (title.value == '新增项目') {
add(form).then((res: any) => {
ElMessage.success('新增项目成功!')
dialogVisible.value = false
emit('submit')
})
} else {
audit(form).then((res: any) => {
ElMessage.success('修改项目成功!')
dialogVisible.value = false
emit('submit')
})
}
}
})
}
const handleTree = (data: any) => {
if (data && data.length != 0) {
data.map((item: any) => {
if (item.level != 2) {
item.disabled = true
} else {
item.disabled = false
}
})
}
}
const open = ref((row: any) => {
formRef.value?.resetFields()
// deviceTree({}).then((res: any) => {
// res.data.forEach((item: any) => {
// item.children.forEach((child: any) => {
// child.children = []
// })
// })
// Engineering.value = res.data
// })
getztProjectTree().then((res: any) => {
res.data.forEach((item: any, index: any) => {
if (!item.children || item.children.length == 0) {
res.data.splice(index, 1)
return
}
item.newList = []
item.children.forEach((vv: any, vvs: any) => {
vv.children.forEach((ss: any, ssIndex: any) => {
if (ss.level == 1) {
item.newList.push(ss)
}
})
})
item.disabled = true
if (item.children && item.children.length != 0) {
item.children.forEach((vv: any, vvs: any) => {
vv.disabled = true
if (item.name.includes('治理')) {
if (vv.level === 0) {
vv.disabled = true
} else {
vv.disabled = false
}
// item.children = item.newList
}
if (item.name.includes('便携式')) {
if (vv.level === 1) {
vv.disabled = false
} else {
vv.disabled = true
}
}
if (vv.children && vv.children.length != 0) {
vv.children.forEach((kk: any, kks: any) => {
if (item.name.includes('便携式') && kk.level === 2) {
kk.disabled = true
vv.children.splice(kks, 1)
}
// else {
// kk.disabled = true
// }
})
}
})
}
})
Engineering.value = removeData(res.data)
})
title.value = row.title
dialogVisible.value = true
if (row.title == '新增项目') {
form.name = ''
form.projectIds = []
form.orderBy = '100'
form.remark = ''
} else {
for (let key in form) {
form[key] = row.row[key] || ''
}
form.id = row.row.id
}
})
const removeData = arr => {
return arr
.map(item => {
if (item.children) {
item.children = removeData(item.children)
}
return item.level <= 1 ? item : {}
})
.filter(item => Object.keys(item).length > 0)
}
const handleClose = () => {
dialogVisible.value = false
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>
<template>
<el-dialog
draggable
:title="title"
v-model.trim="dialogVisible"
width="500px"
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form ref="formRef" :rules="rules" :model="form" label-width="90px" class="form-one">
<el-form-item label="项目名称:" prop="name">
<el-input
maxlength="32"
show-word-limit
v-model.trim="form.name"
placeholder="请输入项目名称"
></el-input>
</el-form-item>
<el-form-item label="是否全局:" class="top" v-if="hasAdmin">
<el-switch
v-model="form.scope"
inline-prompt
width="60px"
:active-value="1"
:inactive-value="0"
active-text=" "
inactive-text=" "
/>
</el-form-item>
<el-form-item label="工程项目:" class="top" prop="projectIds" v-if="!hasAdmin || form.scope == 0">
<el-tree-select
v-model.trim="form.projectIds"
default-expand-all
show-checkbox
node-key="id"
:props="defaultProps"
multiple
:data="Engineering"
collapse-tags
style="width: 100%"
/>
</el-form-item>
<el-form-item label="项目排序:" prop="orderBy">
<el-input
maxlength="32"
show-word-limit-number
v-model.trim="form.orderBy"
:min="0"
:step="1"
step-strictly
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注:" class="top">
<el-input
maxlength="300"
show-word-limit
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="addFn">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { deviceTree, add, audit, getztProjectTree } from '@/api/cs-harmonic-boot/mxgraph'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useAdminInfo } from '@/stores/adminInfo'
const adminInfo = useAdminInfo()
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager')|| item.includes('root'))
const title = ref('')
const formRef = ref()
const Engineering = ref([])
const dialogVisible = ref(false)
const emit = defineEmits(['submit'])
const defaultProps = {
children: 'children',
value: 'id',
label: 'name',
multiple: true,
expandTrigger: 'hover' as const
}
const form: any = reactive({
name: '',
projectIds: [],
scope: 1,
orderBy: '100',
remark: ''
})
const rules = {
name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
projectIds: [{ required: true, message: '请选择工程项目', trigger: 'change' }],
orderBy: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const addFn = () => {
console.log('🚀 ~ add ~ form:', form)
formRef.value.validate((valid: boolean) => {
if (valid) {
if (title.value == '新增项目') {
add({ ...form, projectIds: form.scope == 1 ? ['WIRELESS_PROJECT_ID'] : form.projectIds }).then(
(res: any) => {
ElMessage.success('新增项目成功!')
dialogVisible.value = false
emit('submit')
}
)
} else {
audit({ ...form, projectIds: form.scope == 1 ? ['WIRELESS_PROJECT_ID'] : form.projectIds }).then((res: any) => {
ElMessage.success('修改项目成功!')
dialogVisible.value = false
emit('submit')
})
}
}
})
}
const handleTree = (data: any) => {
if (data && data.length != 0) {
data.map((item: any) => {
if (item.level != 2) {
item.disabled = true
} else {
item.disabled = false
}
})
}
}
const open = ref((row: any) => {
formRef.value?.resetFields()
// deviceTree({}).then((res: any) => {
// res.data.forEach((item: any) => {
// item.children.forEach((child: any) => {
// child.children = []
// })
// })
// Engineering.value = res.data
// })
getztProjectTree().then((res: any) => {
res.data.forEach((item: any, index: any) => {
if (!item.children || item.children.length == 0) {
res.data.splice(index, 1)
return
}
item.newList = []
item.children.forEach((vv: any, vvs: any) => {
vv.children.forEach((ss: any, ssIndex: any) => {
if (ss.level == 1) {
item.newList.push(ss)
}
})
})
item.disabled = true
if (item.children && item.children.length != 0) {
item.children.forEach((vv: any, vvs: any) => {
vv.disabled = true
if (item.name.includes('治理')) {
if (vv.level === 0) {
vv.disabled = true
} else {
vv.disabled = false
}
// item.children = item.newList
}
if (item.name.includes('便携式')) {
if (vv.level === 1) {
vv.disabled = false
} else {
vv.disabled = true
}
}
if (vv.children && vv.children.length != 0) {
vv.children.forEach((kk: any, kks: any) => {
if (item.name.includes('便携式') && kk.level === 2) {
kk.disabled = true
vv.children.splice(kks, 1)
}
// else {
// kk.disabled = true
// }
})
}
})
}
})
Engineering.value = removeData(res.data)
})
title.value = row.title
dialogVisible.value = true
if (row.title == '新增项目') {
form.name = ''
form.projectIds = []
form.orderBy = '100'
form.remark = ''
} else {
for (let key in form) {
form[key] = row.row[key] || ''
}
form.id = row.row.id
}
})
const removeData = arr => {
return arr
.map(item => {
if (item.children) {
item.children = removeData(item.children)
}
return item.level <= 1 ? item : {}
})
.filter(item => Object.keys(item).length > 0)
}
const handleClose = () => {
dialogVisible.value = false
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -28,7 +28,7 @@
<span style="display: flex; align-items: center">
{{ item.name }}
<el-tooltip class="item" effect="dark" content="修改项目" placement="top">
<el-tooltip class="item" effect="dark" content="修改项目" placement="top" v-if="hasAdmin || item.createBy == adminInfo.id">
<Edit
style="margin-left: 5px; width: 16px"
class="xiaoshou color"
@@ -36,28 +36,43 @@
/>
</el-tooltip>
</span>
<div style="display: flex; justify-content: end">
<el-button
class="color"
icon="el-icon-Share"
style="padding: 3px 0"
type="text"
@click="Aclick(item)"
<div style="height: 32px">
<div
style="display: flex; justify-content: end"
v-if="hasAdmin || item.createBy == adminInfo.id"
>
设计
</el-button>
<!-- <el-button icon="el-icon-share" style="padding: 3px 0; color: green"
<!-- <el-button
class="color"
icon="el-icon-Promotion"
style="padding: 3px 0"
type="text"
v-if="bindId != item.id"
@click="activate(item)"
>
绑定
</el-button> -->
<el-button
class="color"
icon="el-icon-Share"
style="padding: 3px 0"
type="text"
@click="Aclick(item)"
>
设计
</el-button>
<!-- <el-button icon="el-icon-share" style="padding: 3px 0; color: green"
type="text" @click="shejid(item)">设计</el-button> -->
<!-- <el-button icon="el-icon-edit" style="padding: 3px 0; color: blue" type="text"
<!-- <el-button icon="el-icon-edit" style="padding: 3px 0; color: blue" type="text"
@click="shejid(item)">编辑</el-button> -->
<el-button
icon="el-icon-Delete"
style="padding: 3px 0; color: red"
type="text"
@click="deleted(item)"
>
删除
</el-button>
<el-button
icon="el-icon-Delete"
style="padding: 3px 0; color: red"
type="text"
@click="deleted(item)"
>
删除
</el-button>
</div>
</div>
</div>
<img
@@ -95,15 +110,18 @@ import TableStore from '@/utils/tableStore'
import TableHeader from '@/components/table/header/index.vue'
import { deleteTopoTemplate, uploadTopo } from '@/api/cs-device-boot/topologyTemplate'
import { ElMessage, ElMessageBox } from 'element-plus'
import { audit, add } from '@/api/cs-harmonic-boot/mxgraph'
import { audit, add, savePageIdWithUser, getByUserId } from '@/api/cs-harmonic-boot/mxgraph'
import { Edit } from '@element-plus/icons-vue'
import popup from './components/popup.vue'
import { useAdminInfo } from '@/stores/adminInfo'
const VITE_FLAG = import.meta.env.VITE_NAME == 'ypt'
defineOptions({
name: 'mxgraph/graph-list'
})
const adminInfo = useAdminInfo()
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager')|| item.includes('root'))
const tableRef = ref()
const popupRef = ref()
let DOMIN = window.location.origin
@@ -120,8 +138,12 @@ const tableStore = new TableStore({
})
provide('tableStore', tableStore)
tableStore.table.params.searchValue = ''
tableStore.table.params.currentUserId = adminInfo.id
// let aa=['operation_manager',]
tableStore.table.params.roleCode = adminInfo.roleCode.join(',')
onMounted(() => {
tableStore.table.ref = tableRef.value
getBindId()
tableStore.index()
tableStore.table.loading = false
})
@@ -131,6 +153,31 @@ const onSubmitadd = () => {
title: '新增项目'
})
}
const bindId = ref('')
const activate = (e: any) => {
ElMessageBox.confirm('是否绑定?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
savePageIdWithUser({ pageId: e.id, userId: adminInfo.id }).then(res => {
if (res.code == 'A0000') {
ElMessage({
type: 'success',
message: '操作成功'
})
bindId.value = e.id
}
})
})
.catch(() => {})
}
const getBindId = () => {
getByUserId({ userId: adminInfo.id }).then(res => {
bindId.value = res.data.pageId
})
}
const querdata = (e: any) => {}
const editd = (e: any) => {
popupRef.value.open({
@@ -142,7 +189,7 @@ const editd = (e: any) => {
const Aclick = (e: any) => {
//window.open(window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=zl`)
window.open(
window.location.origin +
window.location.origin +
`/zutai/?id=${e.id}&&name=${e.name}&&preview=false&&graphicDisplay=${VITE_FLAG ? 'ypt' : 'zl'}`
)
}
@@ -179,7 +226,10 @@ const deleted = (e: any) => {
const imgData = (e: any) => {
window.open(
window.location.origin + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=${VITE_FLAG ? 'ypt' : 'zl'}#/preview_ZL`
window.location.origin +
`/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=${VITE_FLAG ? 'ypt' : 'zl'}#/preview_${
VITE_FLAG ? 'YPT' : 'ZL'
}`
)
// window.open('http://192.168.1.128:4001' + `/zutai/?id=${e.id}&&name=${e.name}&&preview=true&&graphicDisplay=zl#/preview_ZL`)
}

View File

@@ -219,6 +219,13 @@ const exportEvent = () => {
formd.value.searchEndTime = TableHeaderRef.value.datePickerRef.timeValue[1]
formd.value.flag = TableHeaderRef.value.datePickerRef.interval
ElMessage('生成报告中,请稍等!')
const now = new Date()
const year = now.getFullYear() // 4位年份
const month = now.getMonth() + 1 // 月份0-11需+1
const day = now.getDate() // 日期1-31
// 格式化YYYY - MM - DD补零
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
getLineExport(formd.value).then((res: any) => {
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
@@ -227,7 +234,7 @@ const exportEvent = () => {
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = '监测点报告' // 设置下载的文件名
link.download = dotList.value.name+formattedDate // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link)

View File

@@ -1,8 +1,7 @@
<template>
<div class="default-main" :style="height">
<splitpanes style="height: 100%" id="navigation-splitpanes">
<splitpanes style="height: 100%" id="navigation-splitpanes">
<pane :size="size">
<CloudDeviceEntryTree
ref="TerminalRef"
@node-click="handleNodeClick"
@@ -78,6 +77,7 @@ import { exportModel } from '@/api/cs-harmonic-boot/datatrend'
defineOptions({
name: 'harmonic-boot/report/word'
})
const height = mainHeight(20)
const size = ref(0)
const dictData = useDictData()
@@ -121,7 +121,7 @@ const choose = (files: any) => {
}
// 生成
const exportEvent = () => {
console.log("🚀 ~ exportEvent ~ dotList.value:", dotList.value)
console.log('🚀 ~ exportEvent ~ dotList.value:', dotList.value)
if (dotList.value?.level != 4) {
return ElMessage.warning('请选择监测点进行报告生成!')
}
@@ -148,6 +148,13 @@ const exportEvent = () => {
})
} else {
ElMessage('生成报告中...')
const now = new Date()
const year = now.getFullYear() // 4位年份
const month = now.getMonth() + 1 // 月份0-11需+1
const day = now.getDate() // 日期1-31
// 格式化YYYY - MM - DD补零
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
exportModel(form).then((res: any) => {
let blob = new Blob([res], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8'
@@ -156,7 +163,7 @@ const exportEvent = () => {
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a') // 创建a标签
link.href = url
link.download = dotList.value.name // 设置下载的文件名
link.download = dotList.value.name + formattedDate // 设置下载的文件名
document.body.appendChild(link)
link.click() //执行下载
document.body.removeChild(link)

View File

@@ -1,147 +1,147 @@
<template>
<div class="default-main" :style="height">
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
<PointTree :default-expand-all="false" template @node-click="handleNodeClick" @init="handleNodeClick"
@Policy="stencil">
</PointTree>
</pane>
<pane :size="(100 - size)" style="background: #fff" :style="height">
<TableHeader ref="TableHeaderRef" datePicker>
<template v-slot:select>
<el-form-item label="模板策略">
<el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id">
<el-option v-for="item in templatePolicy" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出excel</el-button>
</template>
</TableHeader>
<div class="box">
<div id="luckysheet" v-loading="tableStore.table.loading"
:style="`height: calc(${tableStore.table.height} + 45px)`"></div>
</div>
</pane>
</splitpanes>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import PointTree from '@/components/tree/govern/pointTree.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel'
import { exportExcel } from '@/views/system/reportForms/export.js'
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes'
// import data from './123.json'
defineOptions({
name: 'govern/reportCore/statistics/index'
})
const height = mainHeight(20)
const size = ref(0)
const dictData = useDictData()
const TableHeaderRef = ref()
const dotList: any = ref({})
const Template: any = ref({})
const reportForm: any = ref('')
const templatePolicy: any = ref([])
const reportFormList: any = ref([
{
value: '1',
label: '分析报表'
},
{
value: '2',
label: '统计报表'
},
{
value: '3',
label: '自定义报表'
}
])
const tableStore = new TableStore({
url: '/harmonic-boot/customReport/getCustomReport',
method: 'POST',
column: [],
beforeSearchFun: () => {
tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id
},
loadCallback: () => {
tableStore.table.data.forEach((item: any) => {
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
item.celldata.forEach((k: any) => {
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
})
})
setTimeout(() => {
luckysheet.create({
container: 'luckysheet',
title: '', // 表 头名
lang: 'zh', // 中文
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
data: tableStore.table.data
// tableStore.table.data
})
}, 10)
}
})
provide('tableStore', tableStore)
tableStore.table.params.resourceType = 1
const flag = ref(true)
onMounted(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = ((280 / (dom.offsetWidth - 7)) * 100)
}
})
// getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => {
// templatePolicy.value = res.data
// })
const stencil = (val: any) => {
templatePolicy.value = val
Template.value = val[0]
reportForm.value = val[0]?.reportForm
}
const changetype = (val: any) => {
reportForm.value = val.reportForm
}
const handleNodeClick = (data: any, node: any) => {
if (data?.type == "line") {
dotList.value = data
setTimeout(() => {
tableStore.index()
}, 500)
}
}
const exportEvent = () => {
exportExcel(luckysheet.getAllSheets(), '统计报表下载')
}
</script>
<style lang="scss">
.splitpanes.default-theme .splitpanes__pane {
background: #fff;
}
.box {
padding: 10px;
}
</style>
<template>
<div class="default-main" :style="height">
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
<PointTree :default-expand-all="false" template @node-click="handleNodeClick" @init="handleNodeClick"
@Policy="stencil">
</PointTree>
</pane>
<pane :size="(100 - size)" style="background: #fff" :style="height">
<TableHeader ref="TableHeaderRef" datePicker>
<template v-slot:select>
<el-form-item label="模板策略">
<el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id">
<el-option v-for="item in templatePolicy" :key="item.id" :label="item.name"
:value="item"></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</template>
</TableHeader>
<div class="box">
<div id="luckysheet" v-loading="tableStore.table.loading"
:style="`height: calc(${tableStore.table.height} + 45px)`"></div>
</div>
</pane>
</splitpanes>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import PointTree from '@/components/tree/govern/pointTree.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel'
import { exportExcel } from '@/views/system/reportForms/export.js'
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes'
// import data from './123.json'
defineOptions({
name: 'govern/reportCore/statistics/index'
})
const height = mainHeight(20)
const size = ref(0)
const dictData = useDictData()
const TableHeaderRef = ref()
const dotList: any = ref({})
const Template: any = ref({})
const reportForm: any = ref('')
const templatePolicy: any = ref([])
const reportFormList: any = ref([
{
value: '1',
label: '分析报表'
},
{
value: '2',
label: '统计报表'
},
{
value: '3',
label: '自定义报表'
}
])
const tableStore = new TableStore({
url: '/harmonic-boot/customReport/getCustomReport',
method: 'POST',
column: [],
beforeSearchFun: () => {
tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id
},
loadCallback: () => {
tableStore.table.data.forEach((item: any) => {
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
item.celldata.forEach((k: any) => {
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
})
})
setTimeout(() => {
luckysheet.create({
container: 'luckysheet',
title: '', // 表 头名
lang: 'zh', // 中文
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
data: tableStore.table.data
// tableStore.table.data
})
}, 10)
}
})
provide('tableStore', tableStore)
tableStore.table.params.resourceType = 1
const flag = ref(true)
onMounted(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom) {
size.value = ((280 / (dom.offsetWidth - 7)) * 100)
}
})
// getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => {
// templatePolicy.value = res.data
// })
const stencil = (val: any) => {
templatePolicy.value = val
Template.value = val[0]
reportForm.value = val[0]?.reportForm
}
const changetype = (val: any) => {
reportForm.value = val.reportForm
}
const handleNodeClick = (data: any, node: any) => {
if (data?.type == "line") {
dotList.value = data
setTimeout(() => {
tableStore.index()
}, 500)
}
}
const exportEvent = () => {
exportExcel(luckysheet.getAllSheets(), '统计报表下载')
}
</script>
<style lang="scss">
.splitpanes.default-theme .splitpanes__pane {
background: #fff;
}
.box {
padding: 10px;
}
</style>

View File

@@ -20,7 +20,7 @@
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出excel</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</template>
</TableHeader>
<div class="box" v-loading="tableStore.table.loading">
@@ -45,6 +45,7 @@ import { exportExcel } from '@/views/system/reportForms/export.js'
import 'splitpanes/dist/splitpanes.css'
import DatePicker from '@/components/form/datePicker/time.vue'
import { Splitpanes, Pane } from 'splitpanes'
const name = ref('')
// import data from './123.json'
defineOptions({
name: 'govern/reportCore/statisticsWx/index'
@@ -73,6 +74,7 @@ const tableStore = new TableStore({
delete tableStore.table.params.timeFlag
},
loadCallback: () => {
name.value = dotList.value.name
tableStore.table.data.forEach((item: any) => {
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
item.celldata.forEach((k: any) => {
@@ -140,7 +142,14 @@ const handleNodeClick = (data: any, node: any) => {
}
const exportEvent = () => {
exportExcel(luckysheet.getAllSheets(), '统计报表下载')
const now = new Date()
const year = now.getFullYear() // 4位年份
const month = now.getMonth() + 1 // 月份0-11需+1
const day = now.getDate() // 日期1-31
// 格式化YYYY - MM - DD补零
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
}
</script>
<style lang="scss">

View File

@@ -5,36 +5,51 @@
<!-- <pointTreeWx :default-expand-all="false" template @node-click="handleNodeClick" @init="handleNodeClick"
@Policy="stencil">
</pointTreeWx> -->
<CloudDeviceEntryTree
<CloudDeviceEntryTree
ref="TerminalRef"
template
@Policy="stencil"
@Policy="stencil"
@node-click="handleNodeClick"
@init="handleNodeClick"
></CloudDeviceEntryTree>
</pane>
<pane :size="(100 - size)" style="background: #fff" :style="height">
<TableHeader ref="TableHeaderRef" :showReset="false">
<pane :size="100 - size" style="background: #fff" :style="height">
<TableHeader datePicker ref="TableHeaderRef" :showReset="false">
<template v-slot:select>
<el-form-item label="时间:">
<!-- <el-form-item label="时间:">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item>
</el-form-item> -->
<el-form-item label="模板策略">
<el-select v-model.trim="Template" @change="changetype" placeholder="请选择模版" value-key="id">
<el-option v-for="item in templatePolicy" :key="item.id" :label="item.name"
:value="item"></el-option>
<el-select
v-model.trim="Template"
@change="changetype"
placeholder="请选择模版"
value-key="id"
>
<el-option
v-for="item in templatePolicy"
:key="item.id"
:label="item.name"
:value="item"
></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出excel</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</template>
</TableHeader>
<div class="box" v-loading="tableStore.table.loading">
<div id="luckysheet"
<div
id="luckysheet"
:style="`height: calc(${tableStore.table.height} + 45px)`"
v-if="tableStore.table.data.length > 0"></div>
<el-empty :style="`height: calc(${tableStore.table.height} + 45px)`" v-else description="暂无数据" />
v-if="tableStore.table.data.length > 0"
></div>
<el-empty
:style="`height: calc(${tableStore.table.height} + 45px)`"
v-else
description="暂无数据"
/>
</div>
</pane>
</splitpanes>
@@ -66,23 +81,23 @@ const Template: any = ref({})
const reportForm: any = ref('')
const datePickerRef = ref()
const templatePolicy: any = ref([])
const name = ref('')
const tableStore = new TableStore({
url: '/cs-harmonic-boot/customReport/getSensitiveUserReport',
url: '/cs-harmonic-boot/customReport/getCustomReport',
method: 'POST',
column: [],
beforeSearchFun: () => {
tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id
tableStore.table.params.startTime = datePickerRef.value.timeValue[0],
tableStore.table.params.endTime = datePickerRef.value.timeValue[1],
// tableStore.table.params.startTime = datePickerRef.value.timeValue[0],
// tableStore.table.params.endTime = datePickerRef.value.timeValue[1],
delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime
delete tableStore.table.params.timeFlag
},
loadCallback: () => {
console.log("🚀 ~ tableStore.table:", tableStore.table)
console.log('🚀 ~ tableStore.table:', tableStore.table)
name.value = dotList.value.name
// tableStore.table.data.forEach((item: any) => {
// item.data1 ? (item.data = JSON.parse(item.data1)) : ''
// item.celldata.forEach((k: any) => {
@@ -90,7 +105,13 @@ const tableStore = new TableStore({
// item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
// })
// })
console.log("🚀 ~ tableStore.table:", tableStore.table)
tableStore.table.data.forEach((item: any) => {
item.data1 ? (item.data = JSON.parse(item.data1)) : ''
item.celldata.forEach((k: any) => {
item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
})
})
console.log('🚀 ~ tableStore.table:', tableStore.table)
setTimeout(() => {
luckysheet.create({
@@ -100,7 +121,7 @@ const tableStore = new TableStore({
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
allowEdit: false, // 禁止所有编辑操作(必填)
allowEdit: false, // 禁止所有编辑操作(必填)
data: tableStore.table.data
// tableStore.table.data
})
@@ -109,13 +130,13 @@ const tableStore = new TableStore({
})
provide('tableStore', tableStore)
tableStore.table.params.resourceType = 1
tableStore.table.params.customType = 1
tableStore.table.params.customType = null
const flag = ref(true)
onMounted(() => {
nextTick(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom && dom.offsetHeight > 0) {
size.value = ((280 / (dom.offsetWidth - 7)) * 100)
size.value = (280 / (dom.offsetWidth - 7)) * 100
} else {
// 设置默认值
size.value = 20
@@ -126,14 +147,12 @@ onMounted(() => {
// getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => {
// templatePolicy.value = res.data
// })
const stencil = (val: any) => {
templatePolicy.value = val.filter((item: any) => item.name != '稳态治理报表')
Template.value = templatePolicy.value[0]
reportForm.value = templatePolicy.value[0]?.reportForm
Template.value = templatePolicy.value[0]
reportForm.value = templatePolicy.value[0]?.reportForm
}
const changetype = (val: any) => {
@@ -141,8 +160,7 @@ const changetype = (val: any) => {
}
const handleNodeClick = (data: any, node: any) => {
if (data?.level==4) {
if (data?.level == 4) {
dotList.value = data
setTimeout(() => {
tableStore.index()
@@ -153,7 +171,14 @@ const handleNodeClick = (data: any, node: any) => {
}
const exportEvent = () => {
exportExcel(luckysheet.getAllSheets(), '稳态报表')
const now = new Date()
const year = now.getFullYear() // 4位年份
const month = now.getMonth() + 1 // 月份0-11需+1
const day = now.getDate() // 日期1-31
// 格式化YYYY - MM - DD补零
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
}
</script>
<style lang="scss">

View File

@@ -0,0 +1,212 @@
<template>
<div class="default-main" :style="height">
<splitpanes style="height: 100%" class="default-theme" id="navigation-splitpanes">
<pane :size="size">
<!-- <pointTreeWx :default-expand-all="false" template @node-click="handleNodeClick" @init="handleNodeClick"
@Policy="stencil">
</pointTreeWx> -->
<CloudDeviceEntryTree
ref="TerminalRef"
template
@Policy="stencil"
@node-click="handleNodeClick"
@init="handleNodeClick"
></CloudDeviceEntryTree>
</pane>
<pane :size="100 - size" style="background: #fff" :style="height">
<TableHeader datePicker ref="TableHeaderRef" :showReset="false">
<template v-slot:select>
<!-- <el-form-item label="时间:">
<DatePicker ref="datePickerRef"></DatePicker>
</el-form-item> -->
<el-form-item label="模板策略">
<el-select
v-model.trim="Template"
@change="changetype"
placeholder="请选择模版"
value-key="id"
>
<el-option
v-for="item in templatePolicy"
:key="item.id"
:label="item.name"
:value="item"
></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="监测对象">
<el-select
filterable
v-model="tableStore.table.params.sensitiveUserId"
placeholder="请选择监测对象"
clearable
>
<el-option v-for="item in idList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item> -->
</template>
<template #operation>
<el-button icon="el-icon-Download" type="primary" @click="exportEvent">导出</el-button>
</template>
</TableHeader>
<div class="box" v-loading="tableStore.table.loading">
<div
id="luckysheet"
:style="`height: calc(${tableStore.table.height} + 45px)`"
v-if="tableStore.table.data.length > 0"
></div>
<el-empty
:style="`height: calc(${tableStore.table.height} + 45px)`"
v-else
description="暂无数据"
/>
</div>
</pane>
</splitpanes>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import pointTreeWx from '@/components/tree/govern/pointTreeWx.vue'
import TableHeader from '@/components/table/header/index.vue'
import { useDictData } from '@/stores/dictData'
import { mainHeight } from '@/utils/layout'
import { getTemplateByDept } from '@/api/harmonic-boot/luckyexcel'
import { exportExcel } from '@/views/system/reportForms/export.js'
import 'splitpanes/dist/splitpanes.css'
import DatePicker from '@/components/form/datePicker/time.vue'
import { Splitpanes, Pane } from 'splitpanes'
import CloudDeviceEntryTree from '@/components/tree/govern/cloudDeviceEntryTreeZL.vue'
import { getListByIds } from '@/api/harmonic-boot/cockpit/cockpit'
// import data from './123.json'
defineOptions({
name: 'govern/reportCore/statisticsWx/indexZL'
})
const height = mainHeight(20)
const size = ref(0)
const dictData = useDictData()
const TableHeaderRef = ref()
const dotList: any = ref({})
const Template: any = ref({})
const reportForm: any = ref('')
const datePickerRef = ref()
const templatePolicy: any = ref([])
const name = ref('')
const tableStore = new TableStore({
url: '/cs-harmonic-boot/customReport/getSensitiveUserReport',
method: 'POST',
column: [],
beforeSearchFun: () => {
tableStore.table.params.tempId = Template.value.id
tableStore.table.params.lineId = dotList.value.id
tableStore.table.params.sensitiveUserId = dotList.value.id
// ;(tableStore.table.params.startTime = datePickerRef.value.timeValue[0]),
// (tableStore.table.params.endTime = datePickerRef.value.timeValue[1]),
delete tableStore.table.params.searchBeginTime
delete tableStore.table.params.searchEndTime
delete tableStore.table.params.timeFlag
},
loadCallback: () => {
console.log('🚀 ~ tableStore.table:', tableStore.table.data)
name.value = dotList.value.name
// tableStore.table.data.forEach((item: any) => {
// item.data1 ? (item.data = JSON.parse(item.data1)) : ''
// item.celldata.forEach((k: any) => {
// item.data[k.r][k.c].v ? (item.data[k.r][k.c] = k.v) : ''
// })
// })
setTimeout(() => {
luckysheet.create({
container: 'luckysheet',
title: '', // 表 头名
lang: 'zh', // 中文
showtoolbar: false, // 是否显示工具栏
showinfobar: false, // 是否显示顶部信息栏
showsheetbar: true, // 是否显示底部sheet按钮
allowEdit: false, // 禁止所有编辑操作(必填)
data: tableStore.table.data
// tableStore.table.data
})
}, 10)
}
})
provide('tableStore', tableStore)
tableStore.table.params.resourceType = 1
tableStore.table.params.customType = 1
const flag = ref(true)
onMounted(() => {
initListByIds()
nextTick(() => {
const dom = document.getElementById('navigation-splitpanes')
if (dom && dom.offsetHeight > 0) {
size.value = (280 / (dom.offsetWidth - 7)) * 100
} else {
// 设置默认值
size.value = 20
}
})
})
// getTemplateByDept({ id: dictData.state.area[0].id }).then((res: any) => {
// templatePolicy.value = res.data
// })
const idList = ref([])
// 监测对象
const initListByIds = () => {
getListByIds({}).then((res: any) => {
if (res.data.length > 0) {
idList.value = res.data
if (!tableStore.table.params.sensitiveUserId && idList.value?.length > 0) {
tableStore.table.params.sensitiveUserId = idList.value[0].id
}
// templateListData()
}
})
}
const stencil = (val: any) => {
console.log('🚀 ~ stencil ~ val:', val)
templatePolicy.value = val.filter((item: any) => item.name == '稳态治理报表')
Template.value = templatePolicy.value[0]
reportForm.value = templatePolicy.value[0]?.reportForm
}
const changetype = (val: any) => {
reportForm.value = val.reportForm
}
const handleNodeClick = (data: any, node: any) => {
if (data?.level == 3) {
dotList.value = data
setTimeout(() => {
tableStore.index()
}, 500)
} else {
tableStore.table.loading = false
}
}
const exportEvent = () => {
const now = new Date()
const year = now.getFullYear() // 4位年份
const month = now.getMonth() + 1 // 月份0-11需+1
const day = now.getDate() // 日期1-31
// 格式化YYYY - MM - DD补零
const formattedDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`
exportExcel(luckysheet.getAllSheets(), name.value + formattedDate)
}
</script>
<style lang="scss">
.splitpanes.default-theme .splitpanes__pane {
background: #fff;
}
.box {
padding: 10px;
}
</style>

View File

@@ -11,7 +11,7 @@
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出</el-button>
<el-button icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
</div>

View File

@@ -11,7 +11,7 @@
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出</el-button>
<el-button type="primary" icon="el-icon-Check" @click="preservation">保存</el-button>
<el-button icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
</div>

View File

@@ -48,7 +48,7 @@ import { useDictData } from '@/stores/dictData'
const TypeOptions = ref()
const dictData = useDictData()
const DataTypeSelect = dictData.getBasicData('Sensitive_User_Type')
const DataTypeSelect = dictData.getBasicData('Interference_Source')
const tableStore = inject('tableStore') as TableStore

View File

@@ -26,7 +26,7 @@ defineOptions({
const detail = ref()
const dictData = useDictData()
const interferenceType = dictData.getBasicData('Sensitive_User_Type')
const interferenceType = dictData.getBasicData('Interference_Source')
const tableStore: any = new TableStore({
url: '/cs-harmonic-boot/pqSensitiveUser/getList',

View File

@@ -1,107 +1,108 @@
<template>
<el-dialog width="500px" v-model.trim="dialogVisible" :title="title">
<el-form :model="form" class="form-one" label-width="auto">
<el-form-item label="名称">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="编码">
<el-input maxlength="32" show-word-limit v-model.trim="form.code" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="类型" v-if="title == '新增'|| title == '编辑'">
<el-select v-model.trim="form.type" placeholder="请选择类型">
<el-option v-for="item in options" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input maxlength="32" show-word-limit v-model.trim="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序">
<el-input maxlength="32" show-word-limit-number v-model.trim="form.sort" :min="0" />
</el-form-item>
</el-form>
<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 { addDictTree, updateStatistical } from '@/api/system-boot/dictTree'
import { ElMessage } from 'element-plus'
const emits = defineEmits<{
(e: 'over'): void
}>()
defineOptions({
name: 'govern/setting/statisticalType/add'
})
const tableStore = inject('tableStore') as TableStore
const form = reactive({
name: '',
code: '',
remark: '',
// type: 2,
sort: 100,
pid: '',
id: ''
})
const options = ref([
{ name: '通用指标', value: 2 },
{ name: 'APF模块', value: 3 },
{ name: '星型接线', value: 4 },
{ name: '角型接线', value: 5 },
{ name: 'V型接线', value: 6 },
])
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (text: string, data?: anyObj) => {
title.value = text
for (let key in form) {
form[key] = data ? data[key] : ''
if (key == 'sort') {
form[key] = data?.sort ? data[key] : 100
// console.log("🚀 ~ open ~ form[key]:", form[key])
}
}
dialogVisible.value = true
}
const submit = async () => {
// 非空校验
for (let key in form) {
if (key != 'pid' && key != 'id' && key != 'sort') {
if (!form[key]) {
ElMessage.warning('请填写完整信息')
return
}
}
}
if (form.id) {
await updateStatistical(form).then(res => {
ElMessage.success('编辑成功')
})
} else {
if (!form.pid) {
form.pid = tableStore.table.params.pid
}
await addDictTree(form).then(res => {
ElMessage.success('新增成功')
})
}
emits('over')
dialogVisible.value = false
}
defineExpose({ open })
</script>
<template>
<el-dialog width="500px" v-model.trim="dialogVisible" :title="title">
<el-form :model="form" class="form-one" label-width="auto">
<el-form-item label="名称">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="编码">
<el-input maxlength="32" show-word-limit v-model.trim="form.code" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="类型" v-if="title == '新增'|| title == '编辑'">
<el-select v-model.trim="form.type" placeholder="请选择类型">
<el-option v-for="item in options" :key="item.value" :label="item.name" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input maxlength="32" show-word-limit v-model.trim="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序">
<el-input maxlength="32" show-word-limit-number v-model.trim="form.sort" :min="0" />
</el-form-item>
</el-form>
<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 { addDictTree, updateStatistical } from '@/api/system-boot/dictTree'
import { ElMessage } from 'element-plus'
const emits = defineEmits<{
(e: 'over'): void
}>()
defineOptions({
name: 'govern/setting/statisticalType/add'
})
const tableStore = inject('tableStore') as TableStore
const form = reactive({
name: '',
code: '',
remark: '',
// type: 2,
sort: 100,
pid: '',
id: ''
})
const options = ref([
{ name: '通用指标', value: 2 },
{ name: 'APF模块', value: 3 },
{ name: '星型接线', value: 4 },
{ name: '角型接线', value: 5 },
{ name: 'V型接线', value: 6 },
{ name: '驾驶舱指标', value: 7 },
])
const dialogVisible = ref(false)
const title = ref('新增菜单')
const open = (text: string, data?: anyObj) => {
title.value = text
for (let key in form) {
form[key] = data ? data[key] : ''
if (key == 'sort') {
form[key] = data?.sort ? data[key] : 100
// console.log("🚀 ~ open ~ form[key]:", form[key])
}
}
dialogVisible.value = true
}
const submit = async () => {
// 非空校验
for (let key in form) {
if (key != 'pid' && key != 'id' && key != 'sort') {
if (!form[key]) {
ElMessage.warning('请填写完整信息')
return
}
}
}
if (form.id) {
await updateStatistical(form).then(res => {
ElMessage.success('编辑成功')
})
} else {
if (!form.pid) {
form.pid = tableStore.table.params.pid
}
await addDictTree(form).then(res => {
ElMessage.success('新增成功')
})
}
emits('over')
dialogVisible.value = false
}
defineExpose({ open })
</script>

View File

@@ -1,154 +1,155 @@
<template>
<div class='default-main'>
<TableHeader :showReset='false'>
<template v-slot:operation>
<el-button :icon='Plus' type='primary' @click='addMenu'>新增</el-button>
</template>
</TableHeader>
<Table ref='tableRef' />
<!-- <el-tabs type="border-card">
<el-tab-pane v-for="item in tabPane" :label="item.name">
</el-tab-pane>
</el-tabs> -->
<PopupBinding ref='bindingRef'></PopupBinding>
<PopupAdd ref='addRef' @over='init'></PopupAdd>
</div>
</template>
<script setup lang='ts'>
import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import PopupBinding from './binding.vue'
import PopupAdd from './add.vue'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { dicDelete } from '@/api/system-boot/dic'
defineOptions({
name: 'govern/setting/statisticalType'
})
const tabPane = [{ name: '在线监测' }, { name: '治理' }, { name: '测试' }]
const tableRef = ref()
const bindingRef = ref()
const addRef = ref()
const options = ref([
{ name: '通用指标', value: 2 },
{ name: 'APF模块', value: 3 },
{ name: '星型接线', value: 4 },
{ name: '角型接线', value: 5 },
{ name: 'V型接线', value: 6 },
])
const tableStore = new TableStore({
showPage: false,
url: '/system-boot/dictTree/query',
method: 'POST',
paramsPOST: true,
// publicHeight: 60,
column: [
{
title: '序号', width: 80, formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '统计类型', field: 'name' },
{
title: '类型', field: 'type',
width: 200,
formatter: row => {
return options.value.filter((item: any) => item.value == row.cellValue)[0]?.name
},
},
{
title: '操作',
align: 'center',
width: '200',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '绑定指标',
type: 'primary',
icon: 'el-icon-Connection',
render: 'basicButton',
click: row => {
bindingRef.value.open(row.id)
}
},
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
addRef.value.open('编辑', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除该菜单吗?'
},
click: row => {
dicDelete(row.id).then(() => {
init()
})
}
}
]
}
],
loadCallback: () => {
// // 过滤数组中type等于1的数据children下钻
// const filterData = (arr: any[]) => {
// return arr.filter((item: any) => {
// if (item.children.length) {
// item.children = filterData(item.children)
// }
// return item.type != 1
// })
// }
// tableStore.table.data = filterData(tableStore.table.data)
}
})
provide('tableStore', tableStore)
const init = () => {
tableStore.table.loading = true
queryByCode('Statistical_Type').then(res => {
tableStore.table.params.pid = res.data.id
queryCsDictTree(res.data.id).then(res => {
tableStore.table.data = res.data
tableStore.table.loading = false
})
})
}
onMounted(() => {
tableStore.table.ref = tableRef.value
init()
})
const addMenu = () => {
// console.log(bindingRef)
addRef.value.open('新增', {
sort: tableStore.table.data.length ? tableStore.table.data[tableStore.table.data.length - 1].sort + 1 : 1,
code: '',
pid: '',
id: '',
remark: '',
name: ''
})
}
</script>
<template>
<div class="default-main">
<TableHeader :showReset="false">
<template v-slot:operation>
<el-button :icon="Plus" type="primary" @click="addMenu">新增</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
<!-- <el-tabs type="border-card">
<el-tab-pane v-for="item in tabPane" :label="item.name">
</el-tab-pane>
</el-tabs> -->
<PopupBinding ref="bindingRef"></PopupBinding>
<PopupAdd ref="addRef" @over="init"></PopupAdd>
</div>
</template>
<script setup lang="ts">
import { Plus } from '@element-plus/icons-vue'
import { ref, onMounted, provide } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import PopupBinding from './binding.vue'
import PopupAdd from './add.vue'
import { queryByCode, queryCsDictTree } from '@/api/system-boot/dictTree'
import { dicDelete } from '@/api/system-boot/dic'
defineOptions({
name: 'govern/setting/statisticalType'
})
const tabPane = [{ name: '在线监测' }, { name: '治理' }, { name: '测试' }]
const tableRef = ref()
const bindingRef = ref()
const addRef = ref()
const options = ref([
{ name: '通用指标', value: 2 },
{ name: 'APF模块', value: 3 },
{ name: '星型接线', value: 4 },
{ name: '角型接线', value: 5 },
{ name: 'V型接线', value: 6 },
{ name: '驾驶舱指标', value: 7 }
])
const tableStore = new TableStore({
showPage: false,
url: '/system-boot/dictTree/query',
method: 'POST',
paramsPOST: true,
// publicHeight: 60,
column: [
{
title: '序号',
width: 80,
formatter: (row: any) => {
return (tableStore.table.params.pageNum - 1) * tableStore.table.params.pageSize + row.rowIndex + 1
}
},
{ title: '统计类型', field: 'name' },
{
title: '类型',
field: 'type',
width: 200,
formatter: row => {
return options.value.filter((item: any) => item.value == row.cellValue)[0]?.name
}
},
{
title: '操作',
align: 'center',
width: '200',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '绑定指标',
type: 'primary',
icon: 'el-icon-Connection',
render: 'basicButton',
click: row => {
bindingRef.value.open(row.id)
}
},
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-EditPen',
render: 'basicButton',
click: row => {
addRef.value.open('编辑', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除该菜单吗?'
},
click: row => {
dicDelete(row.id).then(() => {
init()
})
}
}
]
}
],
loadCallback: () => {
// // 过滤数组中type等于1的数据children下钻
// const filterData = (arr: any[]) => {
// return arr.filter((item: any) => {
// if (item.children.length) {
// item.children = filterData(item.children)
// }
// return item.type != 1
// })
// }
// tableStore.table.data = filterData(tableStore.table.data)
}
})
provide('tableStore', tableStore)
const init = () => {
tableStore.table.loading = true
queryByCode('Statistical_Type').then(res => {
tableStore.table.params.pid = res.data.id
queryCsDictTree(res.data.id).then(res => {
tableStore.table.data = res.data
tableStore.table.loading = false
})
})
}
onMounted(() => {
tableStore.table.ref = tableRef.value
init()
})
const addMenu = () => {
// console.log(bindingRef)
addRef.value.open('新增', {
sort: tableStore.table.data.length ? tableStore.table.data[tableStore.table.data.length - 1].sort + 1 : 1,
code: '',
pid: '',
id: '',
remark: '',
name: ''
})
}
</script>

View File

@@ -1,10 +1,10 @@
<template>
<div>
<el-dialog v-model="dialogVisible" title="自定义功能管理" width="600">
<el-dialog v-model="dialogVisible" title="自定义功能管理" width="650">
<div style="display: flex; justify-content: end" class="mb10">
<el-button icon="el-icon-Plus" type="primary" @click="add">新增</el-button>
</div>
<div style="height: calc(100vh / 2); max-height: 400px">
<div style="height: 300px; max-height: 400px">
<vxe-table
border
ref="tableRef"
@@ -25,6 +25,7 @@
<el-switch
v-model="row.state"
inline-prompt
:disabled="!hasAdmin && row.scope"
:active-value="1"
:inactive-value="0"
active-text="已激活"
@@ -33,11 +34,29 @@
/>
</template>
</vxe-column>
<vxe-column field="startTime" title="是否全局" v-if="hasAdmin">
<template #default="{ row }">
<el-switch
v-model="row.scope"
inline-prompt
:active-value="1"
width="50px"
:inactive-value="0"
active-text=""
inactive-text=""
:before-change="() => beforeChange1(row)"
/>
</template>
</vxe-column>
<vxe-column field="startTime" title="操作">
<template #default="{ row }">
<el-button type="primary" link @click="edit(row)">编辑</el-button>
<el-button type="primary" link @click="edit(row)" v-if="!(!hasAdmin && row.scope)">
编辑
</el-button>
<el-button type="danger" link @click="deletes(row)">删除</el-button>
<el-button type="danger" link @click="deletes(row)" v-if="!(!hasAdmin && row.scope)">
删除
</el-button>
</template>
</vxe-column>
</vxe-table>
@@ -49,18 +68,20 @@
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { getDashboardPageByUserId, deleteDashboard, activatePage } from '@/api/system-boot/csstatisticalset'
import { getDashboardPageByUserId, deleteDashboard, activatePage, scopePage } from '@/api/system-boot/csstatisticalset'
import { useAdminInfo } from '@/stores/adminInfo'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useNavTabs } from '@/stores/navTabs'
import { getMenu } from '@/utils/router'
const { push } = useRouter()
const dialogVisible = ref(false)
const route = useRouter()
const navTabs = useNavTabs()
const adminInfo = useAdminInfo()
const pageList: any = ref([])
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager') || item.includes('root'))
const open = () => {
dialogVisible.value = true
@@ -68,7 +89,10 @@ const open = () => {
}
const init = () => {
getDashboardPageByUserId({ id: adminInfo.id, state: false }).then(res => {
pageList.value = res.data
pageList.value = res.data.filter(item => {
item.scope = item.userId == '0' ? 1 : 0
return item
})
})
}
// 新增
@@ -93,7 +117,7 @@ const beforeChange = (row: any): Promise<boolean> => {
type: 'warning'
})
.then(() => {
activatePage({ id: row.id, state: row.state == 0 ? 1 : 0 }).then( async(res: any) => {
activatePage({ id: row.id, state: row.state == 0 ? 1 : 0 }).then(async (res: any) => {
if (res.code == 'A0000') {
ElMessage({
type: 'success',
@@ -102,19 +126,45 @@ const beforeChange = (row: any): Promise<boolean> => {
}
init()
resolve(true)
await getMenu()
await setTimeout(() => {
navTabs.refresh()
await getMenu()
await setTimeout(() => {
navTabs.refresh()
}, 1000)
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除'
.catch(() => {})
})
}
// 全局
const beforeChange1 = (row: any): Promise<boolean> => {
return new Promise(resolve => {
// setTimeout(() => {
// loading1.value = false
// ElMessage.success('Switch success')
// return resolve(true)
// }, 1000)
ElMessageBox.confirm('此操作将页面配置成全局, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
scopePage({ id: row.id, userId: row.scope == 0 ? '0' : adminInfo.id }).then(async (res: any) => {
if (res.code == 'A0000') {
ElMessage({
type: 'success',
message: '操作成功!'
})
}
init()
resolve(true)
await getMenu()
await setTimeout(() => {
navTabs.refresh()
}, 1000)
})
})
.catch(() => {})
})
}
// 删除

View File

@@ -12,7 +12,9 @@
</el-form-item>
</template>
<template v-slot:operation>
<el-button type="primary" icon="el-icon-Edit" @click="editd">编辑</el-button>
<el-button type="primary" icon="el-icon-Edit" v-if="hasAdmin || adminInfo.id == userId" @click="editd">
编辑
</el-button>
<el-button
type="primary"
icon="el-icon-Tools"
@@ -46,7 +48,13 @@
{{ (item as LayoutItem).name }}
</div>
<!-- <FullScreen class="HelpFilled" style="cursor: pointer" @click="setZoom(item)" /> -->
<img :src="flag ? img : img1" style="cursor: pointer; height: 16px" @click="setZoom(item)" />
<span style="display: flex; align-items: center">
<img
:src="flag ? img : img1"
style="cursor: pointer; height: 16px"
@click="setZoom(item)"
/>
</span>
</div>
<div>
<component
@@ -82,12 +90,15 @@ import { queryActivatePage, queryByPagePath } from '@/api/system-boot/csstatisti
import RoutingConfig from '@/views/pqs/cockpit/homePage/components/routingConfig.vue'
import { useRouter, useRoute } from 'vue-router'
import { useTimeCacheStore } from '@/stores/timeCache'
import { Sort } from '@element-plus/icons-vue'
const { push } = useRouter()
const datePickerRef = ref()
const router = useRouter()
const route = useRoute()
const timeCacheStore = useTimeCacheStore()
import { useAdminInfo } from '@/stores/adminInfo'
const adminInfo = useAdminInfo()
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager') || item.includes('root'))
defineOptions({
// name: 'dashboard/index'
})
@@ -109,6 +120,7 @@ interface LayoutItem {
}
const zoom = ref(1)
const RoutingConfigRef = ref()
const userId = ref('')
const key = ref(0)
const img = new URL(`@/assets/img/amplify.png`, import.meta.url).href
const img1 = new URL(`@/assets/img/reduce.png`, import.meta.url).href
@@ -219,6 +231,7 @@ const seRowHeight = (value: any) => {
const fetchLayoutData = async () => {
try {
const { data } = await queryByPagePath({ pagePath: router.currentRoute.value.name })
userId.value = data.userId
dataList.value = data
const parsedLayout = JSON.parse(data.containerConfig || '[]') as LayoutItem[]
// 处理布局数据

View File

@@ -0,0 +1,146 @@
<template>
<el-dialog
class="cn-operate-dialog"
width="1200px"
append-to-body
v-model.trim="dialogVisible"
title="绑定"
>
<el-form ref="formRef" label-width="80px" class="form">
<el-form-item label="项目名称">
<el-input
maxlength="32"
show-word-limit
clearable
style="width: 240px"
v-model.trim="searchValue"
placeholder="请输入项目名称"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="info" icon="el-icon-Search">查询</el-button>
</el-form-item>
</el-form>
<div style="height: calc(60vh - 120px); overflow-y: auto" v-loading="loading">
<el-row :gutter="10" style="width: 100%; margin: auto">
<el-col :span="6" v-for="item in list" :key="item.id" class="mt10">
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix mb10">
<span style="display: flex; align-items: center;justify-content: space-between;">
{{ item.name }}
<!-- <el-tooltip
class="item"
effect="dark"
content="绑定实时数据"
placement="top"
v-if="bindId != item.id"
>
<Sort
style="margin-left: 5px; width: 16px"
class="xiaoshou color"
@click="activate(item)"
/>
</el-tooltip> -->
<el-button type="primary" v-if="bindId != item.id" @click="activate(item)" icon="el-icon-Sort" link>绑定</el-button>
</span>
</div>
<img v-if="item.fileContent" :src="item.fileContent" class="image" />
<el-empty v-else description="暂无设计" style="height: 220px" />
</el-card>
</el-col>
</el-row>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import { coFqueryPage, getByUserId, savePageIdWithUser } from '@/api/cs-harmonic-boot/mxgraph'
import { useAdminInfo } from '@/stores/adminInfo'
import { Sort } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const adminInfo = useAdminInfo()
const emit = defineEmits(['bindClick'])
const dialogVisible = ref(false)
const searchValue = ref('')
const bindId = ref('')
const list = ref([])
const loading = ref(false)
const open = (text: string, data: anyObj) => {
searchValue.value = ''
list.value = []
info()
dialogVisible.value = true
}
const info = () => {
loading.value = true
getBindId()
coFqueryPage({
currentUserId: adminInfo.id,
roleCode: adminInfo.roleCode.join(','),
searchValue: searchValue.value,
pageNum: 1,
pageSize: 1000
})
.then(res => {
list.value = res.data.records
loading.value = false
})
.catch(err => {
loading.value = false
})
}
const getBindId = () => {
getByUserId({ userId: adminInfo.id }).then(res => {
bindId.value = res.data.pageId
})
}
const activate = (e: any) => {
ElMessageBox.confirm('是否绑定页面?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
savePageIdWithUser({ pageId: e.id, userId: adminInfo.id }).then(res => {
if (res.code == 'A0000') {
ElMessage({
type: 'success',
message: '操作成功'
})
bindId.value = e.id
emit('bindClick', bindId.value)
}
})
})
.catch(() => {})
}
defineExpose({ open })
</script>
<style lang="scss" scoped>
.form {
display: flex;
justify-content: space-between;
height: 35px;
}
.image {
display: block;
width: 100%;
height: 220px;
}
.xiaoshou {
cursor: pointer;
}
.color {
color: var(--el-color-primary);
}
.box-card {
width: 100%;
// border: 1px solid #000;
box-shadow: var(--el-box-shadow-light);
}
:deep(.el-card__body) {
padding: 10px;
}
</style>

View File

@@ -12,6 +12,8 @@
style="position: relative"
>
<iframe
v-if="bindId"
:key="bindId"
:src="iframeSrc"
width="100%"
height="100%"
@@ -20,6 +22,7 @@
id="iframeLeft"
@load="onIframeLoad"
></iframe>
<el-empty v-else description="暂无绑定页面" style="height: 100%" />
</div>
</div>
<div class="bottom-container">
@@ -28,13 +31,15 @@
:icon="show ? 'el-icon-ArrowDownBold' : 'el-icon-ArrowUpBold'"
@click="show = !show"
style="width: 100%"
v-if="bindId"
>
事件列表
</el-button>
<el-button class="bindBut" type="primary" icon="el-icon-Sort" @click="bindClick">绑定</el-button>
<!-- <div class="buttonBox">
<el-button type="primary" icon="el-icon-Aim" @click="reset">复位</el-button>
</div> -->
<transition name="table-fade">
<div class="tableBox" v-if="show">
<vxe-table border auto-resize height="230px" :data="tableData" ref="tableRef">
@@ -46,6 +51,8 @@
</div>
</transition>
</div>
<!--绑定实时数据 -->
<Bind ref="bindRef" @bindClick="info" />
</div>
</template>
<script setup lang="ts">
@@ -53,11 +60,16 @@ import { ref, watch, onMounted, onUnmounted, provide } from 'vue'
import Table from '@/components/table/index.vue'
import TableStore from '@/utils/tableStore'
import { mainHeight } from '@/utils/layout'
import { useAdminInfo } from '@/stores/adminInfo'
import { audit, add, coFqueryPage, getByUserId } from '@/api/cs-harmonic-boot/mxgraph'
import Bind from './bind.vue'
// import { getActive } from "@/api/manage_wx/index";
// const props = defineProps<{
// project: { id: string; name: string } | null
// }>()
const adminInfo = useAdminInfo()
const show = ref(false)
const prop = defineProps({
width: { type: [String, Number] },
@@ -65,10 +77,9 @@ const prop = defineProps({
timeKey: { type: Array as () => string[] },
timeValue: { type: Object }
})
const tableData = ref([
])
const bindRef = ref()
const tableData = ref([])
const bindId = ref('')
// 在父页面中添加事件监听器
window.addEventListener('message', function (event) {
@@ -83,6 +94,9 @@ window.addEventListener('message', function (event) {
const tableRef = ref()
const pageHeight = mainHeight(40)
const bindClick = () => {
bindRef.value.open()
}
const reset = () => {
// 向 iframe 发送复位事件
@@ -128,15 +142,10 @@ const iframeSrc = ref('')
// { immediate: true, deep: true }
// )
onMounted(() => {
iframeSrc.value =
window.location.origin + `/zutai/?id=4b4f7f4260198776594f5f9d93a532e8&&name=stt&&preview=true#/preview_YPT`
onMounted(async () => {
info()
// tableStore.index()
// 监听来自 eventStatistics 组件的消息
window.addEventListener('message', handleMessage)
// getActive({}).then((res: any) => {
// if (res.code == "A0000") {
// // window.location.origin
@@ -148,7 +157,31 @@ onMounted(() => {
// }
// });
})
const info = async () => {
iframeSrc.value = ''
await getByUserId({ userId: adminInfo.id })
.then(res => {
bindId.value = res.data.pageId
})
.catch(async err => {
// bindId.value = '4b4f7f4260198776594f5f9d93a532e8'
await coFqueryPage({
currentUserId: adminInfo.id,
roleCode: adminInfo.roleCode.join(','),
searchValue: '',
pageNum: 1,
pageSize: 1000
}).then(res => {
bindId.value = res.data.records.filter(item => item.scope == 1)[0]?.id || null
})
})
await setTimeout(() => {
iframeSrc.value = window.location.origin + `/zutai/?id=${bindId.value}&&name=stt&&preview=true#/preview_YPT`
// iframeSrc.value = `http://192.168.2.128:4001/zutai/?id=${bindId.value}&&name=stt&&preview=true#/preview_YPT`
window.addEventListener('message', handleMessage)
}, 0)
}
onUnmounted(() => {
// 清理事件监听器
window.removeEventListener('message', handleMessage)
@@ -258,4 +291,9 @@ const sendKeysToIframe = (keyList: string[]) => {
.table-fade-enter-active {
transition-delay: 0.05s;
}
.bindBut {
position: absolute;
right: 0px;
top: -35px;
}
</style>

View File

@@ -1,136 +1,195 @@
<template>
<div class="pd10">
<el-card>
<el-form ref="formRef" inline :rules="rules" :model="form" label-width="auto" class="form-four">
<el-form-item label="页面名称" prop="pageName">
<el-input
style="width: 100%"
maxlength="32"
show-word-limit
v-model.trim="form.pageName"
placeholder="请输入页面名称"
></el-input>
</el-form-item>
<el-form-item label="图标">
<IconSelector v-model.trim="form.icon" style="width: 80%" placeholder="请选择图标" />
</el-form-item>
<el-form-item label="页面排序" prop="sort">
<el-input-number style="width: 100%" v-model.trim="form.sort" :min="0" :max="10000" :step="1" />
</el-form-item>
<el-form-item label="是否激活">
<el-switch
v-model="form.state"
inline-prompt
:disabled="form.pagePath == 'dashboard/index'"
:active-value="1"
:inactive-value="0"
active-text=""
inactive-text=""
/>
</el-form-item>
<el-form-item label="备注" class="top">
<el-input
maxlength="300"
show-word-limit
type="textarea"
:rows="1"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
<el-form-item>
<div style="width: 100%; display: flex; justify-content: end">
<el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
<back-component />
</div>
</el-form-item>
</el-form>
</el-card>
<el-card class="mt10" :style="height">
<div style="display: flex">
<div style="width: 605px; overflow: auto" :style="indicatorHeight" class="mr10">
<el-collapse v-model="activeNames" :expand-icon-position="position">
<el-collapse-item
v-for="item in treeComponents"
:key="item.id"
:title="item.name"
:name="item.id"
>
<el-collapse v-model="activeNames1" class="ml20">
<el-collapse-item v-for="k in item.children" :key="k.id" :title="k.name" :name="k.id">
<div class="Box">
<div
v-for="(s, index) in k.children"
:key="index"
class="mr10 mb10 imgBox"
draggable="true"
unselectable="on"
@drag="drag(s)"
@dragend="dragEnd(s)"
>
<div class="textName">{{ s.name }}</div>
<img :src="s.image" style="width: 180px" />
<div class="default-main pd10">
<div style="width: 100%; display: flex; justify-content: end">
<el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
<back-component />
</div>
<div style="display: flex" class="mt10">
<!-- <el-tabs type="border-card">
<el-tab-pane label="组件">
<div style="width: 520px; overflow: auto" :style="indicatorHeight" class="mr10">
<el-collapse v-model="activeNames" :expand-icon-position="position">
<el-collapse-item
v-for="item in treeComponents"
:key="item.id"
:title="item.name"
:name="item.id"
>
<el-collapse v-model="activeNames1" class="ml20">
<el-collapse-item
v-for="k in item.children"
:key="k.id"
:title="k.name"
:name="k.id"
>
<div class="Box">
<div
v-for="(s, index) in k.children"
:key="index"
class="mr10 mb10 imgBox"
draggable="true"
unselectable="on"
@drag="drag(s)"
@dragend="dragEnd(s)"
>
<div class="textName">{{ s.name }}</div>
<img :src="s.image" style="width: 150px" />
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</div>
<div style="flex: 1" ref="wrapper">
<GridLayout
class="GridLayout"
ref="gridLayout"
v-model:layout="layout"
style="width: 100%"
:style="{ height: GridHeight + 'px' }"
:row-height="rowHeight"
:col-num="12"
prevent-collision
:vertical-compact="false"
>
<template #item="{ item }">
<div class="imgBox">
<div class="textName">{{ item.name }}</div>
<img
:src="getImg(item.path)"
:style="{
height:
item.h * rowHeight -
(item.h == 1
? 30
: item.h == 2
? 20
: item.h == 3
? 10
: item.h == 4
? -0
: item.h == 5
? -10
: -20) +
'px'
}"
/>
<CloseBold class="remove" @click="removeItem(item.i)" />
</el-collapse-item>
</el-collapse>
</el-collapse-item>
</el-collapse>
</div>
</el-tab-pane>
</el-tabs> -->
<el-tabs v-model="tableName" type="border-card" @tab-change="changeTab">
<el-tab-pane v-for="item in treeComponents" :key="item.name" :label="item.name" :name="item.name">
<el-tabs v-model="tableName1" tab-position="top">
<el-tab-pane v-for="k in item?.children" :key="k.name" :label="k.name" :name="k.name">
<div :style="indicatorHeight" style="overflow-y: auto; overflow-x: hidden">
<el-row :gutter="10" class="pl5 pr5 pt5" style="width: 520px">
<el-col :span="8" v-for="component in k.children" :key="component.id" class="mb10">
<el-card
class="box-card"
shadow="hover"
@drag="drag(component)"
@dragend="dragEnd(component)"
>
<div slot="header" class="clearfix">
<span style="display: flex; align-items: center">
{{ component.name }}
</span>
</div>
<img v-if="component.image" :src="component.image" class="image xiaoshou" />
</el-card>
</el-col>
</el-row>
</div>
<!-- <span class="text">{{ `${item?.name}` }}</span>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
</el-tabs>
<div style="flex: 1" ref="wrapper" class="ml10">
<el-tabs type="border-card" class="mb10">
<el-tab-pane label="基础信息">
<el-form ref="formRef" inline :rules="rules" :model="form" label-width="auto" class="form-four">
<el-form-item label="页面名称" prop="pageName">
<el-input
style="width: 100%"
maxlength="32"
show-word-limit
v-model.trim="form.pageName"
placeholder="请输入页面名称"
></el-input>
</el-form-item>
<el-form-item label="图标">
<IconSelector v-model.trim="form.icon" placeholder="请选择图标" />
</el-form-item>
<el-form-item label="页面排序" prop="sort">
<el-input-number
style="width: 100%"
v-model.trim="form.sort"
:min="0"
:max="10000"
:step="1"
/>
</el-form-item>
<el-form-item label="是否激活">
<el-switch
v-model="form.state"
inline-prompt
width="60px"
:disabled="form.pagePath == 'dashboard/index'"
:active-value="1"
:inactive-value="0"
active-text=" "
inactive-text=" "
/>
</el-form-item>
<el-form-item label="是否全局" v-if="hasAdmin">
<el-switch
v-model="form.scope"
inline-prompt
width="60px"
:active-value="1"
:inactive-value="0"
:disabled="form.pagePath == 'dashboard/index'"
active-text=" "
inactive-text=" "
/>
</el-form-item>
<el-form-item label="备注" class="top">
<el-input
maxlength="300"
show-word-limit
style="width: 100%"
type="textarea"
:rows="1"
placeholder="请输入内容"
v-model.trim="form.remark"
></el-input>
</el-form-item>
<el-form-item></el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<div ref="PaneRef">
<el-tabs type="border-card">
<el-tab-pane label="画布" :style="height">
<GridLayout
class="GridLayout"
ref="gridLayout"
v-model:layout="layout"
style="width: 100%"
:style="{ height: GridHeight + 'px' }"
:row-height="rowHeight"
:col-num="12"
prevent-collision
:is-bounded="true"
:vertical-compact="false"
>
<template #item="{ item }">
<div class="imgBox">
<div class="textName">{{ item.name }}</div>
<img
:src="getImg(item.path)"
:style="{
height:
item.h * rowHeight -
(item.h == 1
? 30
: item.h == 2
? 20
: item.h == 3
? 10
: item.h == 4
? -0
: item.h == 5
? -10
: -20) +
'px'
}"
/>
<CloseBold class="remove" @click="removeItem(item.i)" />
</div>
<!-- <span class="text">{{ `${item?.name}` }}</span>
-->
</template>
</GridLayout>
</template>
</GridLayout>
</el-tab-pane>
</el-tabs>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import BackComponent from '@/components/icon/back/index.vue'
import { mainHeight } from '@/utils/layout'
@@ -145,17 +204,22 @@ import { addDashboard, updateDashboard, queryById } from '@/api/system-boot/csst
import html2canvas from 'html2canvas'
import { useRoute } from 'vue-router'
import { getMenu } from '@/utils/router'
import { useAdminInfo } from '@/stores/adminInfo'
const tableName = ref('')
const tableName1 = ref('')
import { useNavTabs } from '@/stores/navTabs'
// defineOptions({
// name: 'cockpit/popup'
// })
const adminInfo = useAdminInfo()
const hasAdmin = adminInfo.roleCode.some(item => item.includes('operation_manager') || item.includes('root'))
const { go } = useRouter()
const navTabs = useNavTabs()
const { query } = useRoute()
const router = useRouter()
const height = mainHeight(148)
const indicatorHeight = mainHeight(168)
const height = mainHeight(295)
const indicatorHeight = mainHeight(180)
const rowHeight = ref(0)
const pageList: any = ref([])
const GridHeight = ref(0)
@@ -167,6 +231,7 @@ const form: any = reactive({
sort: '100',
id: '',
state: 1,
scope: 0,
icon: '',
pagePath: '',
remark: '',
@@ -205,6 +270,8 @@ const info = () => {
activeNames1.value = []
componentTree().then(res => {
treeComponents.value = res.data
tableName.value = tableName.value == '' ? treeComponents.value[0].name : tableName.value
tableName1.value = tableName1.value == '' ? treeComponents.value[0].children[0].name : tableName1.value
activeNames.value = treeComponents.value.map(item => item.id)
res.data.forEach(item => {
item.children.forEach(k => {
@@ -223,6 +290,7 @@ const info = () => {
form.remark = res.data.remark
form.id = res.data.id
form.state = res.data.state
form.scope = res.data.userId == 0 ? 1 : 0
form.icon = res.data.icon
})
} else {
@@ -251,6 +319,10 @@ const tree2List = (list: any, id: any) => {
// 返回结果数组
return arr
}
const changeTab = (e: any) => {
console.log('🚀 ~ changeTab ~ e:', e)
tableName1.value = treeComponents.filter(item => item.name == e)[0].children[0].name
}
// 删除拖拽
const removeItem = (id: string) => {
const index = layout.value.findIndex(item => item.i === id)
@@ -260,6 +332,7 @@ const removeItem = (id: string) => {
}
}
const wrapper = ref<HTMLElement>()
const PaneRef = ref<HTMLElement>()
const gridLayout = ref<InstanceType<typeof GridLayout>>()
const mouseAt = { x: -1, y: -1 }
@@ -365,6 +438,12 @@ const onSubmit = () => {
if (layout.value.length == 0) {
return ElMessage.warning('页面设计不能为空!')
}
console.log(123, findDuplicateNames(layout.value))
let repeat = findDuplicateNames(layout.value) || []
if (repeat.length > 0) {
return ElMessage.warning(repeat.join('、')+' 组件重复,请删除重复组件!')
}
// const maxValue = Math.max(...layout.value.map(item => item.y + item.h))
// if (maxValue > 6) {
// return ElMessage.warning('组件不能超出当前容器!')
@@ -381,21 +460,27 @@ const onSubmit = () => {
if (valid) {
if (form.id == '') {
await addDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
async (res: any) => {
ElMessage.success('新增页面成功!')
// go(-1)
await getMenu()
}
)
await addDashboard({
...form,
containerConfig: JSON.stringify(layout.value),
thumbnail: url,
userId: form.scope == 1 ? '0' : adminInfo.id
}).then(async (res: any) => {
ElMessage.success('新增页面成功!')
// go(-1)
await getMenu()
})
} else {
await updateDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
async (res: any) => {
ElMessage.success('修改页面成功!')
// go(-1)
await getMenu()
}
)
await updateDashboard({
...form,
containerConfig: JSON.stringify(layout.value),
thumbnail: url,
userId: form.scope == 1 ? '0' : adminInfo.id
}).then(async (res: any) => {
ElMessage.success('修改页面成功!')
// go(-1)
await getMenu()
})
}
await setTimeout(() => {
router.push({
@@ -406,17 +491,47 @@ const onSubmit = () => {
}
})
}
// 查找重复的name
const findDuplicateNames = (arr: any) => {
// 用于记录每个name出现的次数
const nameCount = {}
// 用于存储重复的name
const duplicates = []
// 遍历数组统计每个name的出现次数
arr.forEach(item => {
const name = item.name
if (nameCount[name]) {
nameCount[name]++
} else {
nameCount[name] = 1
}
})
// 筛选出出现次数大于1的name
for (const name in nameCount) {
if (nameCount[name] > 1) {
duplicates.push(name)
}
}
return duplicates
}
const getImg = throttle((path: string) => {
if (path != undefined) return treeComponentsCopy.value.filter(item => item.path == path)[0]?.image
})
onMounted(() => {
info()
GridHeight.value = wrapper.value?.offsetWidth / 1.77777
rowHeight.value = GridHeight.value / 6 - 11.5
document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
document.addEventListener('dragover', syncMousePosition)
nextTick(() => {
GridHeight.value = PaneRef.value?.offsetHeight - 60 //wrapper.value?.offsetWidth / 1.77777
setTimeout(() => {
console.log('🚀 ~ wrapper.value?.offsetWidth:', PaneRef.value?.offsetWidth)
}, 500)
rowHeight.value = GridHeight.value / 6 - 11.5
document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
document.addEventListener('dragover', syncMousePosition)
})
})
onBeforeUnmount(() => {
@@ -436,7 +551,7 @@ onBeforeUnmount(() => {
display: flex;
// flex: 1;
// align-items: center;
width: 24%;
width: 32%;
.el-form-item__content {
width: 100%;
flex: 1;
@@ -516,4 +631,24 @@ onBeforeUnmount(() => {
:deep(.el-form--inline .el-form-item) {
margin-right: 0px;
}
:deep(.el-card__header) {
padding: 13px 20px;
height: 44px;
}
:deep(.el-card__body) {
padding: 10px;
}
.xiaoshou {
cursor: pointer;
}
.image {
display: block;
width: 100%;
height: 100px;
}
.box-card {
width: 100%;
// border: 1px solid #000;
box-shadow: var(--el-box-shadow-light);
}
</style>

View File

@@ -47,7 +47,7 @@
</el-checkbox-group>
</el-form-item>
<el-form-item class="top" label="组件排序" prop="sort">
<el-input v-model="form.sort" placeholder="请输入组件排序"></el-input>
<el-input v-model.number="form.sort" placeholder="请输入组件排序"></el-input>
</el-form-item>
</el-form>
<div style="width: 600px; height: 390px; overflow: hidden">
@@ -70,7 +70,7 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
<el-button type="primary" @click="submit">保存</el-button>
</span>
</template>
</el-dialog>
@@ -112,7 +112,7 @@ onMounted(() => {
customDeptOption.value = dictData.getBasicData('System_Type')
customDeptOption.value.forEach((item: any) => {
getFatherComponent({ systemType: item.id }).then(res => {
item.children = res.data
item.children = res.data.filter(item => item.name != '无')
})
})
})
@@ -133,36 +133,47 @@ const submit = () => {
formRef.value.validate(async (valid: boolean) => {
if (valid) {
let url = ''
await html2canvas(document.querySelector('.GridLayout'), {
scale: 2
}).then(canvas => {
url = canvas.toDataURL('image/png')
})
if (title.value == '新增组件') {
await componentAdd({
...form.value,
systemType: form.value.system[0],
pid: form.value.system[1],
image: url
}).then(res => {
ElMessage.success('新增成功!')
emit('submit')
cancel()
ElMessage.info('正在保存请稍等!')
setTimeout(async () => {
await html2canvas(document.querySelector('.GridLayout'), {
// scale: 2
scale: 1, // 降低缩放比例2倍会让像素量翻倍优先降到1
useCORS: false, // 非跨域图片关闭CORS检测减少网络请求
logging: false, // 关闭日志输出(减少控制台开销)
letterRendering: true, // 优化文字渲染性能
allowTaint: true, // 允许跨域图片污染画布(避免额外校验)
removeContainer: true, // 自动清理生成的临时容器
ignoreElements: el => {
// 忽略不可见/非关键元素(比如隐藏的弹窗、装饰性元素)
return el.style.display === 'none' || el.classList.contains('ignore-screenshot')
}
}).then(canvas => {
url = canvas.toDataURL('image/png')
})
} else {
await componentEdit({
...form.value,
systemType: form.value.system[0],
pid: form.value.system[1],
image: url
}).then(res => {
ElMessage.success('修改成功!')
emit('submit')
cancel()
})
}
if (title.value == '新增组件') {
await componentAdd({
...form.value,
systemType: form.value.system[0],
pid: form.value.system[1],
image: url
}).then(res => {
ElMessage.success('新增成功!')
emit('submit')
cancel()
})
} else {
await componentEdit({
...form.value,
systemType: form.value.system[0],
pid: form.value.system[1],
image: url
}).then(res => {
ElMessage.success('修改成功!')
emit('submit')
cancel()
})
}
}, 500)
}
})
}

View File

@@ -2,8 +2,8 @@
<el-dialog draggable class="cn-operate-dialog" v-model="dialogVisible" width="500px" :title="title" @close="cancel">
<div style="display: flex">
<el-form :inline="false" :model="form" label-width="auto" :rules="rules" ref="formRef" style="flex: 1">
<el-form-item class="top" label="上级树">
<el-cascader
<el-form-item class="top" label="上级树" prop="system">
<!-- <el-cascader
v-model="form.system"
:options="customDeptOption"
:props="props"
@@ -11,14 +11,22 @@
filterable
placeholder="请选择上级树"
style="width: 100%"
/>
/> -->
<el-select v-model="form.system" placeholder="请选择上级树" style="width: 100%">
<el-option
v-for="item in customDeptOption"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item class="top" label="树名称" prop="name">
<el-input v-model="form.name" placeholder="请输入组件名称"></el-input>
</el-form-item>
<el-form-item class="top" label="树排序" prop="sort">
<el-input v-model="form.sort" placeholder="请输入组件排序"></el-input>
<el-input v-model.number="form.sort" placeholder="请输入排序"></el-input>
</el-form-item>
</el-form>
</div>
@@ -48,10 +56,9 @@ const formRef = ref()
const form = ref<anyObj>({
name: '',
sort: 100,
system: [],
system: '',
timeKey: '3',
code: 'base',
code: 'base'
})
const props = { label: 'name', value: 'id', checkStrictly: true }
const rules = {
@@ -69,9 +76,10 @@ const open = (text: string, data?: anyObj) => {
dialogVisible.value = true
if (data) {
let Data = JSON.parse(JSON.stringify(data))
form.value.system = Data.systemType
form.value.system = Data.systemType//[]
form.value.name = Data.name
form.value.sort = Data.sort
form.value.id = Data.id
}
}
// 查询父节点
@@ -113,8 +121,8 @@ const submit = () => {
if (title.value == '新增树') {
await componentAdd({
...form.value,
systemType: form.value.system[0],
pid: form.value.system?.at(-1)
systemType: form.value.system,
pid: '0' //form.value.system.length == 1 ? '0' : form.value.system
}).then(res => {
ElMessage.success('新增成功!')
emit('submit')
@@ -123,8 +131,8 @@ const submit = () => {
} else {
await componentEdit({
...form.value,
systemType: form.value.system[0],
pid: form.value.system[1]
systemType: form.value.system,
pid: '0'//form.value.system.length == 1 ? '0' : form.value.system
}).then(res => {
ElMessage.success('修改成功!')
emit('submit')

View File

@@ -6,11 +6,81 @@
<el-button type="primary" @click="add" icon="el-icon-Plus">新增组件</el-button>
</template>
</TableHeader>
<Table
<!-- <Table
ref="tableRef"
:tree-config="{ transform: true, parentField: 'uPid', rowField: 'uId' }"
:scroll-y="{ enabled: true }"
/>
/> -->
<el-tabs v-model="tableName" type="border-card" @tab-change="changeTab">
<el-tab-pane v-for="item in tableStore.table.data" :key="item.name" :label="item.name" :name="item.name">
<el-tabs v-model="tableName1" tab-position="left">
<el-tab-pane v-for="k in item?.children" :key="k.name" :label="k.name" :name="k.name">
<template #label>
<span class="custom-tabs-label">
<span>{{ k.name }}</span>
<!-- <el-icon><Edit /></el-icon> -->
<el-button
type="primary"
icon="el-icon-Edit"
link
class="ml10"
@click="editTree(k, 0)"
></el-button>
<el-button
type="danger"
icon="el-icon-Delete"
link
class="ml0"
@click="del(k)"
></el-button>
</span>
</template>
<div :style="height" style="overflow-y: auto; overflow-x: hidden">
<el-row :gutter="10" class="pl5 pr5 pt5">
<el-col :span="6" v-for="component in k.children" :key="component.id" class="mb10">
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span style="display: flex; align-items: center">
{{ component.name }}
</span>
<div style="height: 32px">
<div style="display: flex; justify-content: end">
<el-button
icon="el-icon-Edit"
style="padding: 3px 0; color: blue"
type="text"
@click="editTree(component, 1)"
>
编辑
</el-button>
<el-button
icon="el-icon-Delete"
style="padding: 3px 0; color: red"
type="text"
@click="del(component)"
>
删除
</el-button>
</div>
</div>
</div>
<!-- <img v-if="component.image" :src="component.image" class="image xiaoshou" /> -->
<el-image
style="width: 100%; height: 180px"
:src="component.image"
:preview-src-list="[component.image]"
show-progress
:initial-index="4"
/>
</el-card>
</el-col>
</el-row>
</div>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
</el-tabs>
<Add ref="addRef" v-if="addFlag" @cancel="cancel" @submit="tableStore.index()" />
<!-- 新增树 -->
<Tree ref="treeRef" v-if="addFlag" @cancel="cancel" @submit="tableStore.index()" />
@@ -21,18 +91,23 @@ import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import TableHeader from '@/components/table/header/index.vue'
import Add from './add.vue'
import Tree from './addTree.vue'
import { deleteSubassembly } from '@/api/user-boot/dept'
import { Edit, Delete } from '@element-plus/icons-vue'
import { mainHeight } from '@/utils/layout'
defineOptions({
name: 'component'
})
const addRef = ref()
const addFlag = ref(false)
const tableRef = ref()
const height = ref(mainHeight(140))
const treeRef = ref()
const tableName = ref('')
const tableName1 = ref('')
const treeData: any = ref([])
const tableStore = new TableStore({
url: '/user-boot/component/componentTree',
@@ -61,7 +136,7 @@ const tableStore = new TableStore({
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
disabled: row => row.systemType == null,
click: row => {
addFlag.value = true
setTimeout(() => {
@@ -82,7 +157,7 @@ const tableStore = new TableStore({
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
disabled: row => row.systemType == null,
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
@@ -90,11 +165,10 @@ const tableStore = new TableStore({
title: '确定删除?'
},
click: row => {
deleteSubassembly({ id: row.id }).then(() => {
ElMessage.success('删除成功!')
tableStore.index()
})
deleteSubassembly({ id: row.id }).then(() => {
ElMessage.success('删除成功!')
tableStore.index()
})
}
}
]
@@ -102,16 +176,22 @@ const tableStore = new TableStore({
],
loadCallback: () => {
addFlag.value = false
setTimeout(() => {
tableRef.value?.getRef()?.setAllTreeExpand(true)
}, 0)
tableStore.table.data.forEach((item: any) => {
item.state = 0
})
treeData.value = tree2List(tableStore.table.data, Math.random() * 1000)
tableStore.table.data = treeData.value
tableName.value = tableName.value == '' ? tableStore.table.data[0].name : tableName.value
tableName1.value = tableName1.value == '' ? tableStore.table.data[0].children[0].name : tableName1.value
// setTimeout(() => {
// tableRef.value?.getRef()?.setAllTreeExpand(true)
// }, 0)
// tableStore.table.data.forEach((item: any) => {
// item.state = 0
// })
// treeData.value = tree2List(tableStore.table.data, Math.random() * 1000)
// tableStore.table.data = treeData.value
}
})
const changeTab = (e: any) => {
console.log('🚀 ~ changeTab ~ e:', e)
tableName1.value = tableStore.table.data.filter(item => item.name == e)[0].children[0].name
}
const tree2List = (list: any, id: any) => {
//存储结果的数组
let arr: any = []
@@ -132,6 +212,32 @@ const tree2List = (list: any, id: any) => {
// 返回结果数组
return arr
}
// 修改
const editTree = (row: any, num: number) => {
addFlag.value = true
setTimeout(() => {
if (num == 0) {
treeRef.value?.open('修改树', row)
} else {
addRef.value?.open('修改组件', row)
}
}, 100)
}
// 删除
const del = (row: any) => {
ElMessageBox.confirm('确定删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
deleteSubassembly({ id: row.id }).then(() => {
ElMessage.success('删除成功!')
tableStore.index()
})
})
.catch(() => {})
}
// 新增
const add = () => {
addFlag.value = true
@@ -154,3 +260,100 @@ onMounted(() => {
tableStore.index()
})
</script>
<style lang="scss" scoped>
.text {
font-size: 14px;
}
span {
font-size: 16px;
}
.item {
margin-bottom: 18px;
}
.image {
display: block;
width: 100%;
height: 180px;
}
.clearfix::before,
.clearfix::after {
display: table;
content: '';
}
.clearfix::after {
clear: both;
}
.box-card {
width: 100%;
// border: 1px solid #000;
box-shadow: var(--el-box-shadow-light);
}
.xiaoshou {
cursor: pointer;
}
.setstyle {
min-height: 200px;
padding: 0 !important;
margin: 0;
overflow: auto;
cursor: default !important;
}
.color {
color: var(--el-color-primary);
}
:deep(.el-select-dropdown__wrap) {
max-height: 300px;
}
:deep(.el-tree) {
padding-top: 15px;
padding-left: 10px;
// 不可全选样式
.el-tree-node {
.is-leaf + .el-checkbox .el-checkbox__inner {
display: inline-block;
}
.el-checkbox .el-checkbox__inner {
display: none;
}
}
}
:deep(.el-card__header) {
padding: 13px 20px;
height: 44px;
}
:deep(.el-card__body) {
padding: 10px;
}
.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;
}
:deep(.el-pagination__sizes) {
.el-select {
min-width: 128px;
}
}
</style>

View File

@@ -11,7 +11,7 @@
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出</el-button>
<el-button icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
</div>

View File

@@ -11,7 +11,7 @@
>
<el-button icon="el-icon-Upload" type="primary" class="mr10">导入excel</el-button>
</el-upload>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出excel</el-button>
<el-button @click="downloadExcel" class="" type="primary" icon="el-icon-Download">导出</el-button>
<el-button type="primary" icon="el-icon-Check" @click="preservation">保存</el-button>
<el-button icon="el-icon-Back" @click="emit('shutDown')">返回</el-button>
</div>

View File

@@ -12,8 +12,14 @@
</div>
<el-form :rules="rules" ref="formRef" size="large" class="login-form form-one" :model="form">
<el-form-item prop="username">
<el-input ref="usernameRef" v-model.trim="form.username" type="text" clearable placeholder="用户名"
autocomplete="off">
<el-input
ref="usernameRef"
v-model.trim="form.username"
type="text"
clearable
placeholder="用户名"
autocomplete="off"
>
<template #prefix>
<span class="iconfont icon-yonghu" style="color: var(--el-color-primary)"></span>
<!-- <Icon name="fa fa-user" style="color: var(--el-color-primary); font-size: 16px" /> -->
@@ -21,8 +27,14 @@
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input ref="passwordRef" v-model.trim="form.password" type="password" clearable placeholder="密码"
autocomplete="off">
<el-input
ref="passwordRef"
v-model.trim="form.password"
type="password"
clearable
placeholder="密码"
autocomplete="off"
>
<template #prefix>
<!-- <Icon name="local-password" style="color: var(--el-color-primary); font-size: 16px" /> -->
<span class="iconfont icon-mima" style="color: var(--el-color-primary)"></span>
@@ -30,8 +42,13 @@
</el-input>
</el-form-item>
<el-form-item>
<el-button :loading="state.submitLoading" class="submit-btn" round type="info"
@click="onSubmit(formRef)">
<el-button
:loading="state.submitLoading"
class="submit-btn"
round
type="info"
@click="onSubmit(formRef)"
>
登录
</el-button>
</el-form-item>
@@ -105,7 +122,17 @@ onMounted(() => {
timer = window.setTimeout(() => {
pageBubble.init()
}, 0)
fetchMqttUrl()
})
let buildUrl = 'ws://192.168.1.103:8083/mqtt' //27
const fetchMqttUrl = async () => {
const response = await fetch('/')
const mqttUrl = response.headers.get('X-Mqtt-Url')
const zutai = response.headers.get('X-Mqttzutai-Url')
window.localStorage.setItem('MQTTURL', mqttUrl || buildUrl)
window.localStorage.setItem('MQTTZUTAI', zutai || '')
}
onBeforeUnmount(() => {
clearTimeout(timer)

View File

@@ -1,93 +1,93 @@
<template>
<el-dialog class="cn-operate-dialog" v-model.trim="dialogVisible" :title="title">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef">
<el-form-item label="新密码:" prop="newPwd" style="margin-top: 20px">
<el-input v-model.trim="form.newPwd" type="password" placeholder="请输入新密码" show-password />
</el-form-item>
<el-form-item label="确认密码:" prop="confirmPwd" style="margin-top: 20px">
<el-input v-model.trim="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 { ElMessage } from 'element-plus'
import { updateFirstPassword } from '@/api/user-boot/user'
import { validatePwd } from '@/utils/common'
import { useAdminInfo } from '@/stores/adminInfo'
import { useRouter } from 'vue-router'
const dialogVisible = ref(false)
const title = ref('修改默认密码')
const formRef = ref()
// 注意不要和表单ref的命名冲突
const form = reactive({
newPwd: '',
confirmPwd: '',
loginName: ''
})
const rules = {
newPwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 16,
message: '长度在 6 到 16 个字符',
trigger: 'blur'
},
{ validator: validatePwd, trigger: 'blur' }
],
confirmPwd: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{
min: 6,
max: 16,
message: '长度在 6 到 16 个字符',
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 open = (loginName: string) => {
form.loginName = loginName
dialogVisible.value = true
}
const submit = () => {
formRef.value.validate(async (valid: boolean) => {
if (valid) {
updateFirstPassword({
name: form.loginName,
password: form.confirmPwd
}).then((res: any) => {
dialogVisible.value = false
ElMessage.success('密码修改成功, 请重新登录')
})
}
})
}
defineExpose({ open })
</script>
<template>
<el-dialog class="cn-operate-dialog" width="500px" v-model.trim="dialogVisible" :title="title">
<el-scrollbar>
<el-form :inline="false" :model="form" label-width="120px" :rules="rules" ref="formRef">
<el-form-item label="新密码:" prop="newPwd" style="margin-top: 20px">
<el-input v-model.trim="form.newPwd" type="password" placeholder="请输入新密码" show-password />
</el-form-item>
<el-form-item label="确认密码:" prop="confirmPwd" style="margin-top: 20px">
<el-input v-model.trim="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 { ElMessage } from 'element-plus'
import { updateFirstPassword } from '@/api/user-boot/user'
import { validatePwd } from '@/utils/common'
import { useAdminInfo } from '@/stores/adminInfo'
import { useRouter } from 'vue-router'
const dialogVisible = ref(false)
const title = ref('修改默认密码')
const formRef = ref()
// 注意不要和表单ref的命名冲突
const form = reactive({
newPwd: '',
confirmPwd: '',
loginName: ''
})
const rules = {
newPwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 16,
message: '长度在 6 到 16 个字符',
trigger: 'blur'
},
{ validator: validatePwd, trigger: 'blur' }
],
confirmPwd: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{
min: 6,
max: 16,
message: '长度在 6 到 16 个字符',
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 open = (loginName: string) => {
form.loginName = loginName
dialogVisible.value = true
}
const submit = () => {
formRef.value.validate(async (valid: boolean) => {
if (valid) {
updateFirstPassword({
name: form.loginName,
password: form.confirmPwd
}).then((res: any) => {
dialogVisible.value = false
ElMessage.success('密码修改成功, 请重新登录')
})
}
})
}
defineExpose({ open })
</script>