修改测试BUG

This commit is contained in:
guanj
2026-06-18 16:35:16 +08:00
parent 13f11596e4
commit 8527939eb1
44 changed files with 1329 additions and 953 deletions

View File

@@ -119,3 +119,11 @@ export function resetFactory(data: any) {
params: data params: data
}) })
} }
//修改mac后接入
export function accessByUpdateMac(data: any) {
return createAxios({
url: '/access-boot/device/accessByUpdateMac',
method: 'post',
params: data
})
}

View File

@@ -1,45 +1,45 @@
import createAxios from '@/utils/request' import createAxios from '@/utils/request'
// 菜单修改 // 菜单修改
export function updateMenu(params: anyObj) { export function updateMenu(params: anyObj) {
return createAxios({ return createAxios({
url: '/user-boot/function/update', url: '/user-boot/function/update',
method: 'PUT', method: 'PUT',
data: params data: params
}) })
} }
export function addMenu(params: anyObj) { export function addMenu(params: anyObj) {
return createAxios({ return createAxios({
url: '/user-boot/function/add', url: '/user-boot/function/add',
method: 'POST', method: 'POST',
data: params data: params
}) })
} }
export function delMenu(id: string) { export function delMenu(id: string) {
return createAxios({ return createAxios({
url: '/user-boot/function/delete?id=' + id, url: '/user-boot/function/delete?id=' + id,
method: 'delete' method: 'delete'
}) })
} }
export function getTheme() { export function getTheme() {
return createAxios({ return createAxios({
url: '/system-boot/theme/getTheme', url: '/system-boot/theme/getTheme',
method: 'get' method: 'get'
}) })
} }
export function addVersion(data:any) { export function addVersion(data:any) {
return createAxios({ return createAxios({
url: '/cs-system-boot/appVersion/add', url: '/cs-system-boot/appVersion/add',
method: 'post', method: 'post',
data data
}) })
} }
export function getLastData(data:any) { export function getLastData(data:any) {
return createAxios({ return createAxios({
url: '/cs-system-boot/appVersion/getLastData', url: '/cs-system-boot/appVersion/getLastData',
method: 'post', method: 'post',
params:data params:data
}) })
} }

View File

@@ -0,0 +1,81 @@
<template>
<ElDialogInner
v-bind="dialogAttrs"
:width="resolvedWidth"
:class="dialogClass"
:draggable="resolvedDraggable"
:close-on-click-modal="closeOnClickModal"
>
<template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData || {}" />
</template>
</ElDialogInner>
</template>
<script setup lang="ts">
import { ElDialog as ElDialogInner } from 'element-plus'
import { computed, useAttrs } from 'vue'
import {
getDialogPreset,
resolveDialogSize,
resolveDialogSizeByClass,
type DialogSize
} from '@/config/dialog'
defineOptions({ inheritAttrs: false })
const props = defineProps<{
/** 显式指定弹框尺寸small | middle | big */
dialogSize?: DialogSize
}>()
const attrs = useAttrs()
const resolvedSize = computed<DialogSize>(() => {
if (props.dialogSize) return props.dialogSize
const width = attrs.width as string | number | undefined
if (width !== undefined && width !== null && width !== '') {
return resolveDialogSize(width)
}
return resolveDialogSizeByClass(attrs.class)
})
const dialogPreset = computed(() => getDialogPreset(resolvedSize.value))
const resolvedWidth = computed(() => dialogPreset.value.width)
const dialogClass = computed(() => [
'cn-dialog',
`cn-dialog--${resolvedSize.value}`,
dialogPreset.value.class,
attrs.class
])
const dialogAttrs = computed(() => {
const {
width: _width,
class: _class,
draggable: _draggable,
closeOnClickModal: _closeOnClickModal,
...rest
} = attrs
const { 'close-on-click-modal': _closeOnClickModalKebab, ...restWithoutKebab } = rest as Record<
string,
unknown
>
return restWithoutKebab
})
const resolvedDraggable = computed(() => {
if (attrs.draggable !== undefined) return attrs.draggable as boolean
return dialogPreset.value.draggable
})
const closeOnClickModal = computed(() => {
if (attrs.closeOnClickModal !== undefined) return attrs.closeOnClickModal as boolean
if (attrs['close-on-click-modal'] !== undefined) return attrs['close-on-click-modal'] as boolean
return dialogPreset.value.closeOnClickModal
})
</script>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<!-- 指标越限详情 --> <!-- 指标越限详情 -->
<el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="70%"> <el-dialog draggable :title="title" v-model="dialogVisible" append-to-body width="1200">
<TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef"> <TableHeader datePicker showExport :showReset="false" ref="tableHeaderRef">
<template v-slot:select> <template v-slot:select>
<!-- <el-form-item label="监测点"> <!-- <el-form-item label="监测点">

View File

@@ -767,6 +767,9 @@ const initWave = (
// min: rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0, // min: rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0,
max: yRange.max, max: yRange.max,
min: yRange.min, min: yRange.min,
interval: yRange.interval,
minInterval: yRange.interval,
scale: false,
boundaryGap: [0, '100%'], boundaryGap: [0, '100%'],
showLastLabel: true, showLastLabel: true,
opposite: false, opposite: false,
@@ -799,25 +802,26 @@ const initWave = (
grid: { grid: {
left: '60px', left: '60px',
right: '45px', right: '45px',
bottom: '40px', bottom: '45px',
top: '60px' top: '60px'
// containLabel: true // containLabel: true
}, },
dataZoom: [ dataZoom: [
{ {
type: 'inside', type: 'inside',
height: 13, height: 13,
start: 0, start: 0,
bottom: '20px',
bottom: '10px',
end: 100, end: 100,
filterMode: 'filter' filterMode: 'none'
}, },
{ {
start: 0, start: 0,
height: 13, height: 13,
bottom: '20px', bottom: '10px',
end: 100, end: 100,
filterMode: 'filter' filterMode: 'none'
} }
], ],
series: [ series: [
@@ -1101,6 +1105,9 @@ const drawPics = (
showLastLabel: true, showLastLabel: true,
max: yRange.max, max: yRange.max,
min: yRange.min, min: yRange.min,
interval: yRange.interval,
minInterval: yRange.interval,
scale: false,
opposite: false, opposite: false,
// max: Math.floor((rmscm[0]?.[1] * 1.06 || 0) * 1.1 * 10) / 10, // max: Math.floor((rmscm[0]?.[1] * 1.06 || 0) * 1.1 * 10) / 10,
// min: Math.floor((rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0) * 10) / 10, // min: Math.floor((rmscu[0]?.[1] - rmscu[0]?.[1] * 0.2 || 0) * 10) / 10,
@@ -1133,23 +1140,26 @@ const drawPics = (
grid: { grid: {
left: '60px', left: '60px',
right: '45px', right: '45px',
bottom: '40px', bottom: '45px',
top: '60px' top: '60px'
// containLabel: true // containLabel: true
}, },
dataZoom: [ dataZoom: [
{ {
type: 'inside', type: 'inside',
height: 13, height: 13,
start: 0, start: 0,
bottom: '20px',
end: 100 bottom: '10px',
end: 100,
filterMode: 'none'
}, },
{ {
start: 0, start: 0,
height: 13, height: 13,
bottom: '20px', bottom: '10px',
end: 100 end: 100,
filterMode: 'none'
} }
], ],
series: [ series: [

View File

@@ -527,6 +527,9 @@ const initWave = (
showLastLabel: true, showLastLabel: true,
max: yRange.max, max: yRange.max,
min: yRange.min, min: yRange.min,
interval: yRange.interval,
minInterval: yRange.interval,
scale: false,
opposite: false, opposite: false,
nameTextStyle: { nameTextStyle: {
fontSize: '12px', fontSize: '12px',
@@ -557,7 +560,7 @@ const initWave = (
grid: { grid: {
left: '60px', left: '60px',
right: '45px', right: '45px',
bottom: '40px', bottom: '45px',
top: '60px' top: '60px'
}, },
dataZoom: [ dataZoom: [
@@ -565,16 +568,17 @@ const initWave = (
type: 'inside', type: 'inside',
height: 13, height: 13,
start: 0, start: 0,
bottom: '20px',
bottom: '10px',
end: 100, end: 100,
filterMode: 'filter' filterMode: 'none'
}, },
{ {
start: 0, start: 0,
height: 13, height: 13,
bottom: '20px', bottom: '10px',
end: 100, end: 100,
filterMode: 'filter' filterMode: 'none'
} }
], ],
series: [ series: [
@@ -838,6 +842,9 @@ const drawPics = (
showLastLabel: true, showLastLabel: true,
max: yRange.max, max: yRange.max,
min: yRange.min, min: yRange.min,
interval: yRange.interval,
minInterval: yRange.interval,
scale: false,
opposite: false, opposite: false,
nameTextStyle: { nameTextStyle: {
fontSize: '12px', fontSize: '12px',
@@ -868,7 +875,7 @@ const drawPics = (
grid: { grid: {
left: '60px', left: '60px',
right: '45px', right: '45px',
bottom: '40px', bottom: '45px',
top: '60px' top: '60px'
// containLabel: true // containLabel: true
}, },
@@ -877,14 +884,17 @@ const drawPics = (
type: 'inside', type: 'inside',
height: 13, height: 13,
start: 0, start: 0,
bottom: '20px',
end: 100 bottom: '10px',
end: 100,
filterMode: 'none'
}, },
{ {
start: 0, start: 0,
height: 13, height: 13,
bottom: '20px', bottom: '10px',
end: 100 end: 100,
filterMode: 'none'
} }
], ],
series: [ series: [

View File

@@ -1,74 +1,136 @@
<template> <template>
<div style='border: 1px solid #e4e4e4;height: 100%'> <div style="border: 1px solid #e4e4e4; height: 100%">
<Toolbar <Toolbar
style='border-bottom: 1px solid #e4e4e4;border-top: 1px solid #e4e4e4' style="border-bottom: 1px solid #e4e4e4; border-top: 1px solid #e4e4e4"
:editor='editorRef' :editor="editorRef"
:defaultConfig='toolbarConfig' :defaultConfig="toolbarConfig"
mode='default' mode="default"
/> />
<Editor <Editor
v-bind='$attrs' v-model="innerHtml"
:defaultConfig='editorConfig' :defaultConfig="editorConfig"
mode='default' mode="default"
@onCreated='handleCreated' @onCreated="handleCreated"
style='height: calc(100% - 42px); ' @onChange="handleChange"
/> style="height: calc(100% - 42px)"
</div> />
</template> </div>
<script lang='ts' setup> </template>
import '@wangeditor/editor/dist/css/style.css' // 引入 css
<script lang="ts" setup>
import { onBeforeUnmount, ref, shallowRef, onMounted } from 'vue' import '@wangeditor/editor/dist/css/style.css'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
// 编辑器实例,必须用 shallowRef import { nextTick, onBeforeUnmount, ref, shallowRef, watch } from 'vue'
const editorRef = shallowRef() import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
// 内容 HTML const props = withDefaults(defineProps<{ modelValue?: string | null }>(), {
const valueHtml = ref('<p>hello</p>') modelValue: ''
})
// 模拟 ajax 异步获取内容
onMounted(() => { const emit = defineEmits<{
setTimeout(() => { 'update:modelValue': [value: string]
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>' }>()
}, 1500)
}) const editorRef = shallowRef<any>()
const innerHtml = ref('<p><br></p>')
const toolbarConfig = { const isApplyingExternal = ref(false)
excludeKeys: ['fullScreen', 'emotion']
} /** 清理 HTML避免标签间空白文本节点导致 Slate 解析失败 */
let sever = '/cs-harmonic-boot/csconfiguration/uploadImage' function sanitizeEditorHtml(html: string | null | undefined): string {
// 本地加api if (html == null || html === '') return '<p><br></p>'
if (process.env.NODE_ENV === 'development') { const cleaned = html
sever = '/api' + sever .replace(/>\s+</g, '><')
} .replace(/(<\/li>)\s+(<li>)/g, '$1$2')
const editorConfig = { .trim()
placeholder: '请输入内容...', return cleaned || '<p><br></p>'
MENU_CONF: { }
uploadImage: {
server: sever, function toSaveHtml(html: string): string {
fieldName: 'file', return html === '<p><br></p>' ? '' : html
compress: true, }
uploadFileName: 'file',
withCredentials: true, function applyHtmlToEditor(html: string | null | undefined) {
headers: {}, const content = sanitizeEditorHtml(html)
timeout: 0, const editor = editorRef.value
customInsert: (insertImg, result, editor) => { if (!editor || editor.isDestroyed) return
const url = result.data.url
insertImg(url) try {
} const current = editor.getHtml()
} if (current === content) return
} } catch {
} // ignore getHtml error on half-destroyed editor
}
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => { isApplyingExternal.value = true
const editor = editorRef.value try {
if (editor == null) return editor.setHtml(content)
editor.destroy() innerHtml.value = content
}) } catch {
try {
const handleCreated = (editor) => { editor.setHtml('<p><br></p>')
editorRef.value = editor // 记录 editor 实例,重要! innerHtml.value = '<p><br></p>'
} } catch {
// editor may already be destroyed
</script> }
} finally {
nextTick(() => {
isApplyingExternal.value = false
})
}
}
watch(
() => props.modelValue,
val => {
applyHtmlToEditor(val)
}
)
const toolbarConfig = {
excludeKeys: ['fullScreen', 'emotion']
}
let sever = '/cs-harmonic-boot/csconfiguration/uploadImage'
if (process.env.NODE_ENV === 'development') {
sever = '/api' + sever
}
const editorConfig = {
placeholder: '请输入内容...',
MENU_CONF: {
uploadImage: {
server: sever,
fieldName: 'file',
compress: true,
uploadFileName: 'file',
withCredentials: true,
headers: {},
timeout: 0,
customInsert: (insertImg: (url: string) => void, result: { data: { url: string } }) => {
insertImg(result.data.url)
}
}
}
}
onBeforeUnmount(() => {
const editor = editorRef.value
editorRef.value = undefined
if (editor == null || editor.isDestroyed) return
editor.destroy()
})
const handleCreated = (editor: any) => {
editorRef.value = editor
nextTick(() => {
applyHtmlToEditor(props.modelValue)
})
}
const handleChange = (editor: { getHtml: () => string }) => {
if (isApplyingExternal.value) return
const html = editor.getHtml()
innerHtml.value = html
emit('update:modelValue', toSaveHtml(html))
}
</script>

125
src/config/dialog.ts Normal file
View File

@@ -0,0 +1,125 @@
/**
* 系统弹框尺寸配置(大 / 中 / 小)
* 修改此处即可全局统一弹框宽度与默认行为
*/
export interface DialogPreset {
width: string
maxWidth: string
minWidth: string
closeOnClickModal: boolean
draggable: boolean
class: string
}
export const dialogSmall: DialogPreset = {
width: '26vw',
maxWidth: '500px',
minWidth: '300px',
closeOnClickModal: false,
draggable: true,
class: 'dialog-small'
}
export const dialogMiddle: DialogPreset = {
width: '42vw',
maxWidth: '800px',
minWidth: '600px',
closeOnClickModal: false,
draggable: true,
class: 'dialog-middle'
}
export const dialogBig: DialogPreset = {
width: '62vw',
maxWidth: '1200px',
minWidth: '800px',
closeOnClickModal: false,
draggable: true,
class: 'dialog-big'
}
export const DIALOG_PRESETS = {
small: dialogSmall,
middle: dialogMiddle,
big: dialogBig
} as const
export type DialogSize = keyof typeof DIALOG_PRESETS
export function getDialogPreset(size: DialogSize = 'small'): DialogPreset {
return DIALOG_PRESETS[size]
}
export function getDialogWidth(size: DialogSize = 'small'): string {
return DIALOG_PRESETS[size].width
}
/** 将配置同步到 CSS 变量,供全局样式使用 */
export function applyDialogCssVars(): void {
;(Object.keys(DIALOG_PRESETS) as DialogSize[]).forEach(size => {
const preset = DIALOG_PRESETS[size]
document.documentElement.style.setProperty(`--cn-dialog-width-${size}`, preset.width)
document.documentElement.style.setProperty(`--cn-dialog-max-width-${size}`, preset.maxWidth)
document.documentElement.style.setProperty(`--cn-dialog-min-width-${size}`, preset.minWidth)
})
}
/**
* 根据原有 width 推断弹框尺寸(兼容现有 el-dialog 的 width 写法)
*/
export function resolveDialogSize(width: string | number): DialogSize {
const raw = String(width).trim().toLowerCase()
if (raw.endsWith('%')) {
const percent = parseFloat(raw)
if (Number.isNaN(percent)) return 'small'
if (percent >= 60) return 'big'
if (percent >= 40) return 'middle'
return 'small'
}
if (raw.endsWith('vw')) {
const vw = parseFloat(raw)
if (Number.isNaN(vw)) return 'middle'
if (vw >= 55) return 'big'
if (vw >= 35) return 'middle'
return 'small'
}
const numeric = parseFloat(raw.replace(/px/g, ''))
if (Number.isNaN(numeric)) return 'small'
if (numeric >= 850) return 'big'
if (numeric >= 550) return 'middle'
return 'small'
}
/** 无 width 时根据 class 推断尺寸 */
export function resolveDialogSizeByClass(classValue: unknown): DialogSize {
const classStr = normalizeClass(classValue)
if (classStr.includes('dialog-big')) return 'big'
if (classStr.includes('dialog-middle')) return 'middle'
if (classStr.includes('dialog-small')) return 'small'
if (classStr.includes('transient-filter-dialog')) return 'small'
if (classStr.includes('cn-operate-dialog')) return 'small'
if (classStr.includes('device-manage-popup') || classStr.includes('analysisList')) {
return 'big'
}
return 'middle'
}
function normalizeClass(classValue: unknown): string {
if (!classValue) return ''
if (typeof classValue === 'string') return classValue
if (Array.isArray(classValue)) return classValue.filter(Boolean).join(' ')
if (typeof classValue === 'object') {
return Object.entries(classValue as Record<string, boolean>)
.filter(([, active]) => active)
.map(([name]) => name)
.join(' ')
}
return String(classValue)
}

View File

@@ -13,7 +13,8 @@ import 'element-plus/theme-chalk/display.css'
import '@fortawesome/fontawesome-free/css/all.css' import '@fortawesome/fontawesome-free/css/all.css'
import '@/styles/index.scss' import '@/styles/index.scss'
import '@/assets/font/iconfont.css' import '@/assets/font/iconfont.css'
import { ElDialog } from 'element-plus' import CnDialog from '@/components/CnDialog/CnDialog.vue'
import { applyDialogCssVars } from '@/config/dialog'
import ExcelJS from 'exceljs' import ExcelJS from 'exceljs'
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx' import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'
VXETable.use(VXETablePluginExportXLSX, { VXETable.use(VXETablePluginExportXLSX, {
@@ -21,13 +22,14 @@ VXETable.use(VXETablePluginExportXLSX, {
}) })
window.XEUtils = XEUtils window.XEUtils = XEUtils
applyDialogCssVars()
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
app.use(pinia) app.use(pinia)
app.use(ElementPlus); app.use(ElementPlus)
(app._context.components.ElDialog as typeof ElDialog).props.closeOnClickModal.default = false app.component('ElDialog', CnDialog)
app.use(VXETable) app.use(VXETable)
registerIcons(app) // icons registerIcons(app) // icons

View File

@@ -346,12 +346,6 @@ body,
} }
} }
@media screen and (max-width: 1024px) {
.cn-operate-dialog {
width: 96%;
}
}
@media screen and (max-width: 991px) { @media screen and (max-width: 991px) {
.user-views { .user-views {
padding: 0; padding: 0;

53
src/styles/dialog.scss Normal file
View File

@@ -0,0 +1,53 @@
/* 弹框尺寸 - CSS 变量由 config/dialog.ts 在启动时注入 */
:root {
--cn-dialog-width-small: 26vw;
--cn-dialog-max-width-small: 500px;
--cn-dialog-min-width-small: 300px;
--cn-dialog-width-middle: 42vw;
--cn-dialog-max-width-middle: 800px;
--cn-dialog-min-width-middle: 600px;
--cn-dialog-width-big: 62vw;
--cn-dialog-max-width-big: 1200px;
--cn-dialog-min-width-big: 800px;
}
.cn-dialog.el-dialog {
max-width: calc(100vw - 32px);
}
.cn-dialog--small.el-dialog,
.dialog-small.el-dialog {
width: var(--cn-dialog-width-small) !important;
max-width: var(--cn-dialog-max-width-small) !important;
min-width: var(--cn-dialog-min-width-small) !important;
}
.cn-dialog--middle.el-dialog,
.dialog-middle.el-dialog {
width: var(--cn-dialog-width-middle) !important;
max-width: var(--cn-dialog-max-width-middle) !important;
min-width: var(--cn-dialog-min-width-middle) !important;
}
.cn-dialog--big.el-dialog,
.dialog-big.el-dialog {
width: var(--cn-dialog-width-big) !important;
max-width: var(--cn-dialog-max-width-big) !important;
min-width: var(--cn-dialog-min-width-big) !important;
}
@media screen and (max-width: 1024px) {
.cn-dialog--small.el-dialog,
.cn-dialog--middle.el-dialog,
.cn-dialog--big.el-dialog,
.dialog-small.el-dialog,
.dialog-middle.el-dialog,
.dialog-big.el-dialog,
.cn-operate-dialog.el-dialog {
width: 96% !important;
min-width: unset !important;
max-width: calc(100vw - 32px) !important;
}
}

View File

@@ -1,5 +1,6 @@
@use '@/styles/app'; @use '@/styles/app';
@use '@/styles/vxeTable'; @use '@/styles/vxeTable';
@use '@/styles/element'; @use '@/styles/element';
@use '@/styles/var'; @use '@/styles/var';
@use '@/styles/map'; @use '@/styles/map';
@use '@/styles/dialog';

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog width="500px" v-model.trim='dialogVisible' :title='title'> <el-dialog v-model.trim="dialogVisible" width="500px" :title="title" dialog-size="small">
<el-scrollbar> <el-scrollbar>
<el-form :inline='false' :model='form' label-width='auto' class="form-one" :rules='rules' ref='formRef'> <el-form :inline='false' :model='form' label-width='auto' class="form-one" :rules='rules' ref='formRef'>
<el-form-item label='角色名称'> <el-form-item label='角色名称'>

View File

@@ -1,4 +1,12 @@
const AXIS_DECIMALS = 2 const AXIS_DECIMALS = 2
/** 与 formatAxisLabel 小数位一致,刻度步长不得小于此值,避免标签重复 */
const MIN_TICK_STEP = 10 ** -AXIS_DECIMALS
export interface YAxisRange {
min: number
max: number
interval: number
}
export function roundAxisValue(val: number, decimals = AXIS_DECIMALS): number { export function roundAxisValue(val: number, decimals = AXIS_DECIMALS): number {
if (!Number.isFinite(val)) return 0 if (!Number.isFinite(val)) return 0
@@ -12,12 +20,61 @@ export function formatAxisLabel(value: number): string {
return String(Number(roundAxisValue(value).toFixed(AXIS_DECIMALS))) return String(Number(roundAxisValue(value).toFixed(AXIS_DECIMALS)))
} }
/** 根据数据范围计算与显示精度对齐的刻度步长 */
function calcNiceTickInterval(range: number, maxTicks = 6): number {
if (!Number.isFinite(range) || range <= 0) return MIN_TICK_STEP
const raw = range / maxTicks
const magnitude = 10 ** Math.floor(Math.log10(raw))
const normalized = raw / magnitude
let niceFactor: number
if (normalized <= 1) niceFactor = 1
else if (normalized <= 2) niceFactor = 2
else if (normalized <= 5) niceFactor = 5
else niceFactor = 10
let interval = niceFactor * magnitude
if (interval < MIN_TICK_STEP) {
interval = MIN_TICK_STEP
} else {
interval = Math.ceil(interval / MIN_TICK_STEP) * MIN_TICK_STEP
}
return roundAxisValue(interval)
}
/** 将 min/max 对齐到刻度步长边界 */
function alignAxisToInterval(min: number, max: number, interval: number): { min: number; max: number } {
const alignedMin = Math.floor(min / interval) * interval
let alignedMax = Math.ceil(max / interval) * interval
if (alignedMax <= alignedMin) {
alignedMax = alignedMin + interval
}
return {
min: roundAxisValue(alignedMin),
max: roundAxisValue(alignedMax)
}
}
function buildYAxisRange(axisMin: number, axisMax: number): YAxisRange {
const interval = calcNiceTickInterval(axisMax - axisMin)
const aligned = alignAxisToInterval(axisMin, axisMax, interval)
return {
...aligned,
interval
}
}
/** 瞬间波形 Y 轴范围 */ /** 瞬间波形 Y 轴范围 */
export function calcShuYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } { export function calcShuYAxisRange(dataMin: number, dataMax: number): YAxisRange {
const min = Number(dataMin) const min = Number(dataMin)
const max = Number(dataMax) const max = Number(dataMax)
if (!Number.isFinite(min) || !Number.isFinite(max)) { if (!Number.isFinite(min) || !Number.isFinite(max)) {
return { min: 0, max: 1 } return buildYAxisRange(0, 1)
} }
let axisMax = max * 1.1 let axisMax = max * 1.1
@@ -29,18 +86,15 @@ export function calcShuYAxisRange(dataMin: number, dataMax: number): { min: numb
axisMin = min - pad axisMin = min - pad
} }
return { return buildYAxisRange(axisMin, axisMax)
min: roundAxisValue(axisMin),
max: roundAxisValue(axisMax)
}
} }
/** RMS 波形 Y 轴范围 */ /** RMS 波形 Y 轴范围 */
export function calcRmsYAxisRange(dataMin: number, dataMax: number): { min: number; max: number } { export function calcRmsYAxisRange(dataMin: number, dataMax: number): YAxisRange {
const min = Number(dataMin) const min = Number(dataMin)
const max = Number(dataMax) const max = Number(dataMax)
if (!Number.isFinite(min) || !Number.isFinite(max)) { if (!Number.isFinite(min) || !Number.isFinite(max)) {
return { min: 0, max: 1 } return buildYAxisRange(0, 1)
} }
let axisMax = max * 1.06 * 1.1 let axisMax = max * 1.06 * 1.1
@@ -52,8 +106,5 @@ export function calcRmsYAxisRange(dataMin: number, dataMax: number): { min: numb
axisMin = min - pad axisMin = min - pad
} }
return { return buildYAxisRange(axisMin, axisMax)
min: roundAxisValue(axisMin),
max: roundAxisValue(axisMax)
}
} }

View File

@@ -77,10 +77,10 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
config.url == '/cs-harmonic-boot/limitRateDetailD/limitProbabilityData' || config.url == '/cs-harmonic-boot/limitRateDetailD/limitProbabilityData' ||
config.url == '/system-boot/dictTree/queryByCode' || config.url == '/system-boot/dictTree/queryByCode' ||
config.url == '/system-boot/dictTree/queryByid' || config.url == '/system-boot/dictTree/queryByid' ||
config.url == '/system-boot/dictTree/query'|| config.url == '/system-boot/dictTree/query' ||
config.url == '/cs-harmonic-boot/csevent/f47Curve'|| config.url == '/cs-harmonic-boot/csevent/f47Curve' ||
config.url == '/cs-harmonic-boot/sysExcel/querySysExcel'|| config.url == '/cs-harmonic-boot/sysExcel/querySysExcel' ||
config.url == '/cs-device-boot/csLedger/lineTree'|| config.url == '/cs-device-boot/csLedger/lineTree' ||
config.url == '/cs-harmonic-boot/pqSensitiveUser/getUserDevTree' config.url == '/cs-harmonic-boot/pqSensitiveUser/getUserDevTree'
) )
) )
@@ -103,7 +103,10 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw==' config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw=='
} }
} }
if (config.url == '/user-boot/user/generateSm2Key' || config.url == '/pqs-auth/oauth/token') { if (
config.url == '/user-boot/user/generateSm2Key' ||
config.url == '/pqs-auth/oauth/token'
) {
config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw==' config.headers.Authorization = 'Basic bmpjbnRlc3Q6bmpjbnBxcw=='
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog width="700px" v-model.trim="dialogVisible" :title="title"> <el-dialog width="500px" v-model.trim="dialogVisible" :title="title">
<el-scrollbar> <el-scrollbar>
<el-form <el-form
:mode="form" :mode="form"

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog" width="700px" v-model.trim="dialogVisible" :title="title"> <el-dialog class="cn-operate-dialog" width="500px" v-model.trim="dialogVisible" :title="title">
<el-scrollbar> <el-scrollbar>
<el-form :inline="false" :model="form" label-width="auto" ref="formRef" class="form-one" :rules="rules"> <el-form :inline="false" :model="form" label-width="auto" ref="formRef" class="form-one" :rules="rules">
<el-form-item label="上级菜单"> <el-form-item label="上级菜单">

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog" v-model.trim="dialogVisible" :title="title"> <el-dialog class="cn-operate-dialog" v-model.trim="dialogVisible" width="800" :title="title">
<el-form :model="form" ref="formRef" label-width="auto" class="form-two" :rules="rules"> <el-form :model="form" ref="formRef" label-width="auto" class="form-two" :rules="rules">
<el-form-item label="用户名" prop="name"> <el-form-item label="用户名" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入昵称" /> <el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入昵称" />

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog v-model="visible" title="事件筛选" width="450px" append-to-body draggable class="transient-filter-dialog"> <el-dialog v-model="visible" title="事件筛选" width="500px" append-to-body draggable class="transient-filter-dialog">
<el-form label-width="auto" class="filter-form"> <el-form label-width="auto" class="filter-form">
<el-form-item label="暂态幅值(%)"> <el-form-item label="暂态幅值(%)">
<div class="range-inputs"> <div class="range-inputs">

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog" draggable v-model="dialogVisible" :title="title" width="900px" <el-dialog class="cn-operate-dialog" draggable v-model="dialogVisible" :title="title" width="800px"
@closed="handleClosed"> @closed="handleClosed">
<el-scrollbar max-height="60vh"> <el-scrollbar max-height="60vh">
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto" class="form-two"> <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" class="form-two">

View File

@@ -135,13 +135,13 @@
:data="menuTree" :checkStrictly="checkStrictly"></Tree> :data="menuTree" :checkStrictly="checkStrictly"></Tree>
</div> </div>
<!-- 新增/编辑弹框 --> <!-- 新增/编辑弹框 -->
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="400px" :before-close="handleClose"> <el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px" :before-close="handleClose">
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px"> <el-form :model="formData" :rules="formRules" ref="formRef" class="form-one" label-width="100px">
<el-form-item label="方案名称" prop="name"> <el-form-item label="方案名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="formData.name" placeholder="请输入方案名称" clearable /> <el-input maxlength="32" show-word-limit v-model.trim="formData.name" placeholder="请输入方案名称" clearable />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort"> <el-form-item label="排序" prop="sort">
<el-input-number v-model.number="formData.sort" :min="0" /> <el-input-number v-model.number="formData.sort" :min="0" style="width: 100%;" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>

View File

@@ -205,8 +205,9 @@
(nodeLevel >= 2 || pageStatus == 2) && (nodeLevel >= 2 || pageStatus == 2) &&
formData.deviceInfoList.length > 0 formData.deviceInfoList.length > 0
"> ">
<el-tabs v-model="busBarIndex" type="border-card" :addable="false" :closable="pageStatus != 1" <el-tabs v-model="busBarIndex" type="border-card" :addable="false"
@edit="handleBusBarTabsEdit" @tab-click="tabChange('busBarIndex', $event)"> :closable="pageStatus != 1 && connectionMethod != 'MQTT'" @edit="handleBusBarTabsEdit"
@tab-click="tabChange('busBarIndex', $event)">
<el-tab-pane v-for="(busItem, bIndex) in formData.deviceInfoList" :key="bIndex" <el-tab-pane v-for="(busItem, bIndex) in formData.deviceInfoList" :key="bIndex"
:label="busItem.name ? busItem.name : '新建设备' + bIndex" :name="bIndex + ''"> :label="busItem.name ? busItem.name : '新建设备' + bIndex" :name="bIndex + ''">
<div class="flex mt10"> <div class="flex mt10">
@@ -403,7 +404,7 @@
formData.lineInfoList.length > 0 formData.lineInfoList.length > 0
"> ">
<!-- connectionMethod != 'MQTT' --> <!-- connectionMethod != 'MQTT' -->
<el-tabs type="border-card" v-model="lineIndex" :addable="false" :closable="pageStatus != 1" <el-tabs type="border-card" v-model="lineIndex" :addable="false" :closable="pageStatus != 1 && connectionMethod != 'MQTT'"
@edit="handleLineTabsEdit" @tab-click="tabChange('lineIndex', $event)"> @edit="handleLineTabsEdit" @tab-click="tabChange('lineIndex', $event)">
<el-tab-pane v-for="(lineItem, lIndex) in formData.lineInfoList" :key="lIndex" <el-tab-pane v-for="(lineItem, lIndex) in formData.lineInfoList" :key="lIndex"
:label="lineItem.name ? lineItem.name : '新建监测点' + lIndex" :name="lIndex + ''"> :label="lineItem.name ? lineItem.name : '新建监测点' + lIndex" :name="lIndex + ''">
@@ -543,7 +544,7 @@
trigger: 'change' trigger: 'change'
}"> }">
<el-select clearable filterable v-model="lineItem.lineInterval" <el-select clearable filterable v-model="lineItem.lineInterval"
placeholder="请选择统计间隔" :disabled="!( placeholder="请选择统计间隔" :disabled="!(connectionMethod != 'MQTT' &&
(nodeLevel == 4 && pageStatus == 3) || (nodeLevel == 4 && pageStatus == 3) ||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
pageStatus == 2) pageStatus == 2)
@@ -647,7 +648,7 @@
</el-form-item> </el-form-item>
<el-form-item class="form-item" label="监测位置"> <el-form-item class="form-item" label="监测位置">
<el-select clearable filterable v-model="lineItem.position" <el-select clearable filterable v-model="lineItem.position"
placeholder="请选择监测位置" :disabled="!( placeholder="请选择监测位置" :disabled="!(connectionMethod != 'MQTT' &&
(nodeLevel == 4 && pageStatus == 3) || (nodeLevel == 4 && pageStatus == 3) ||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) && ((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
pageStatus == 2) pageStatus == 2)
@@ -919,7 +920,7 @@ const project = ref([
const wiringTypeArr = ref([ const wiringTypeArr = ref([
{ name: '星型接线', value: 0 }, { name: '星型接线', value: 0 },
{ name: '三角型接线', value: 1 }, { name: '三角型接线', value: 1 },
{ name: '开口三角型接线', value: 2 } { name: 'V型接线', value: 2 }
]) ])
/**监测点序号 */ /**监测点序号 */
const pointNumArr = ref([ const pointNumArr = ref([
@@ -1987,247 +1988,247 @@ const submitAllLevelData = async () => {
let submitData: any = {} let submitData: any = {}
// 根据当前节点层级构建相应的数据结构 // 根据当前节点层级构建相应的数据结构
switch (nodeLevel.value) { switch (nodeLevel.value) {
case 0: // 只有工程 case 0: // 只有工程
submitData = { submitData = {
engineering: tempAllLevelData.value.engineering || { ...formData.value.engineeringParam } engineering: tempAllLevelData.value.engineering || { ...formData.value.engineeringParam }
} }
break break
case 1: // 工程 + 项目 case 1: // 工程 + 项目
// 工程信息 // 工程信息
const engineeringData = tempAllLevelData.value.engineering || { ...formData.value.engineeringParam } const engineeringData = tempAllLevelData.value.engineering || { ...formData.value.engineeringParam }
// 项目信息 // 项目信息
const projectData: any = const projectData: any =
tempAllLevelData.value.projects.length > 0 tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects.find(project => project !== undefined) || {} ? tempAllLevelData.value.projects.find(project => project !== undefined) || {}
: formData.value.projectInfoList[0] || {} : formData.value.projectInfoList[0] || {}
// 如果是从根节点开始新增工程和项目 // 如果是从根节点开始新增工程和项目
if (nodeData.value.level === -1) { if (nodeData.value.level === -1) {
submitData = { submitData = {
engineering: engineeringData, engineering: engineeringData,
project: { ...projectData, topoIds: [projectData.topoId] } project: { ...projectData, topoIds: [projectData.topoId] }
}
} else {
// 如果是从工程节点开始新增项目
submitData = {
engineeringIndex: nodeData.value?.id || '',
project: { ...projectData, topoIds: [projectData.topoId] }
}
}
break
case 2: // 工程 + 项目 + 设备
// 工程信息
const engineeringData2 = tempAllLevelData.value.engineering || {
...formData.value.engineeringParam
}
// 项目信息
const projectData2 =
tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects.find(project => project !== undefined) || {}
: formData.value.projectInfoList[0] || {}
// 设备信息
let devices = []
if (tempAllLevelData.value.devices.length > 0) {
devices = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices = formData.value.deviceInfoList.filter((d: any) => d && d.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === -1) {
submitData = {
engineering: engineeringData2,
project: { ...projectData2, topoIds: [projectData2.topoId] },
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
// 如果是从工程节点开始新增
else if (nodeData.value.level === 0) {
submitData = {
engineeringIndex: nodeData.value?.id || '',
project: { ...projectData2, topoIds: [projectData2.topoId] },
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
// 如果是从项目节点开始新增
else if (nodeData.value.level === 1) {
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : ''
submitData = {
projectIndex: nodeData.value?.id || '',
engineeringIndex: engineeringId,
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
}
}
break
// case 3: // 工程 + 项目 + 设备 + 监测点
case 3:
// 工程信息
const engineeringData3 = tempAllLevelData.value.engineering || {
...formData.value.engineeringParam
}
// 项目信息
const projectData3 =
tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects.find(project => project !== undefined) || {}
: formData.value.projectInfoList[0] || {}
// 设备信息
let devices2: any[] = []
if (tempAllLevelData.value.devices.length > 0) {
devices2 = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices2 = formData.value.deviceInfoList.filter((d: any) => d && d.name)
}
// 监测点信息
let lines = []
if (tempAllLevelData.value.lines.length > 0) {
lines = tempAllLevelData.value.lines.filter((l: any) => l && l.name)
} else {
lines = formData.value.lineInfoList.filter((l: any) => l && l.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === -1) {
submitData = {
engineering: engineeringData3,
project: { ...projectData3, topoIds: [projectData3.topoId] },
device: devices2.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
} }
} else {
// 如果是从工程节点开始新增项目 // 获取设备MAC地址
submitData = { let devMac = ''
engineeringIndex: nodeData.value?.id || '', if (devices2.length > 0) {
project: { ...projectData, topoIds: [projectData.topoId] } devMac = devices2[0].mac || ''
} }
}
break
case 2: // 工程 + 项目 + 设备 return {
// 工程信息 ...line,
const engineeringData2 = tempAllLevelData.value.engineering || { volGrade: volGradeValue,
...formData.value.engineeringParam devMac: devMac
}
// 项目信息
const projectData2 =
tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects.find(project => project !== undefined) || {}
: formData.value.projectInfoList[0] || {}
// 设备信息
let devices = []
if (tempAllLevelData.value.devices.length > 0) {
devices = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices = formData.value.deviceInfoList.filter((d: any) => d && d.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === -1) {
submitData = {
engineering: engineeringData2,
project: { ...projectData2, topoIds: [projectData2.topoId] },
device: devices.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
} }
} })
// 如果是从工程节点开始新增 }
else if (nodeData.value.level === 0) { }
submitData = { // 如果是从工程节点开始新增
engineeringIndex: nodeData.value?.id || '', else if (nodeData.value.level === 0) {
project: { ...projectData2, topoIds: [projectData2.topoId] }, submitData = {
device: devices.map((device: any) => ({ engineeringIndex: nodeData.value?.id || '',
...device, project: projectData3,
ndid: device.mac ? device.mac.replace(/:/g, '') : '' device: devices2.map((device: any) => ({
})) ...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
} }
}
// 如果是从项目节点开始新增
else if (nodeData.value.level === 1) {
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : ''
submitData = { // 获取设备MAC地址
projectIndex: nodeData.value?.id || '', let devMac = ''
engineeringIndex: engineeringId, if (devices2.length > 0) {
device: devices.map((device: any) => ({ devMac = devices2[0].mac || ''
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
}))
} }
}
break
// case 3: // 工程 + 项目 + 设备 + 监测点 return {
case 3: ...line,
// 工程信息 volGrade: volGradeValue,
const engineeringData3 = tempAllLevelData.value.engineering || { devMac: devMac
...formData.value.engineeringParam
}
// 项目信息
const projectData3 =
tempAllLevelData.value.projects.length > 0
? tempAllLevelData.value.projects.find(project => project !== undefined) || {}
: formData.value.projectInfoList[0] || {}
// 设备信息
let devices2: any[] = []
if (tempAllLevelData.value.devices.length > 0) {
devices2 = tempAllLevelData.value.devices.filter((d: any) => d && d.name)
} else {
devices2 = formData.value.deviceInfoList.filter((d: any) => d && d.name)
}
// 监测点信息
let lines = []
if (tempAllLevelData.value.lines.length > 0) {
lines = tempAllLevelData.value.lines.filter((l: any) => l && l.name)
} else {
lines = formData.value.lineInfoList.filter((l: any) => l && l.name)
}
// 如果是从根节点开始新增
if (nodeData.value.level === -1) {
submitData = {
engineering: engineeringData3,
project: { ...projectData3, topoIds: [projectData3.topoId] },
device: devices2.map((device: any) => ({
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
} }
} })
// 如果是从工程节点开始新增 }
else if (nodeData.value.level === 0) { }
submitData = { // 如果是从项目节点开始新增
engineeringIndex: nodeData.value?.id || '', else if (nodeData.value.level === 1) {
project: projectData3, const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
device: devices2.map((device: any) => ({ const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : ''
...device,
ndid: device.mac ? device.mac.replace(/:/g, '') : ''
})),
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址 submitData = {
let devMac = '' device: devices2.map((device: any) => ({
if (devices2.length > 0) { ...device,
devMac = devices2[0].mac || '' ndid: device.mac ? device.mac.replace(/:/g, '') : ''
} })),
projectIndex: nodeData.value?.id || '',
return { engineeringIndex: engineeringId,
...line, line: lines.map((line: any) => {
volGrade: volGradeValue, // 处理电压等级,去除"kV"后缀
devMac: devMac let volGradeValue = line.volGrade
} if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
}) volGradeValue = volGradeValue.slice(0, -2)
} }
}
// 如果是从项目节点开始新增
else if (nodeData.value.level === 1) {
const pidsArray = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
const engineeringId = pidsArray.length >= 2 ? pidsArray[1] : ''
submitData = { // 获取设备MAC地址
device: devices2.map((device: any) => ({ let devMac = ''
...device, if (devices2.length > 0) {
ndid: device.mac ? device.mac.replace(/:/g, '') : '' devMac = devices2[0].mac || ''
})),
projectIndex: nodeData.value?.id || '',
engineeringIndex: engineeringId,
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
} }
}
// 如果是从设备节点开始新增
else if (nodeData.value.level === 2) {
const pidsArray2 = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
const engineeringId2 = pidsArray2.length >= 2 ? pidsArray2[1] : ''
const projectId = pidsArray2.length >= 3 ? pidsArray2[2] : ''
submitData = { return {
devIndex: nodeData.value?.id || '', ...line,
projectIndex: projectId, volGrade: volGradeValue,
engineeringIndex: engineeringId2, devMac: devMac
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
} }
} })
break }
}
// 如果是从设备节点开始新增
else if (nodeData.value.level === 2) {
const pidsArray2 = nodeData.value?.pids ? nodeData.value.pids.split(',') : []
const engineeringId2 = pidsArray2.length >= 2 ? pidsArray2[1] : ''
const projectId = pidsArray2.length >= 3 ? pidsArray2[2] : ''
submitData = {
devIndex: nodeData.value?.id || '',
projectIndex: projectId,
engineeringIndex: engineeringId2,
line: lines.map((line: any) => {
// 处理电压等级,去除"kV"后缀
let volGradeValue = line.volGrade
if (typeof volGradeValue === 'string' && volGradeValue.endsWith('kV')) {
volGradeValue = volGradeValue.slice(0, -2)
}
// 获取设备MAC地址
let devMac = ''
if (devices2.length > 0) {
devMac = devices2[0].mac || ''
}
return {
...line,
volGrade: volGradeValue,
devMac: devMac
}
})
}
}
break
} }
// 发送请求 // 发送请求

View File

@@ -193,14 +193,14 @@
</TableHeader> </TableHeader>
<div class="data_time" :style="{ <div class="data_time" :style="{
alignItems: realTimeFlag ? 'flex-end' : 'center' alignItems: realTimeFlag ? 'flex-end' : 'center'
}" v-if="dataSet.includes('_realtimedata') && sonTab != 2 && !realTimeFlag"> }" v-if="dataSet.includes('_realtimedata') && sonTab != 2 && !realTimeFlag">
<p class="mb10 mt10" > <p class="mb10 mt10">
<span>数据时间:{{ trendDataTime || '-' }}</span> <span>数据时间:{{ trendDataTime || '-' }}</span>
</p> </p>
<el-button v-if="!realTimeFlag && dataSet.includes('_realtimedata')" style="float: right !important" <el-button v-if="!realTimeFlag && dataSet.includes('_realtimedata')" style="float: right !important"
:icon="Back" @click="handleReturn" > :icon="Back" @click="handleReturn">
返回 返回
</el-button> </el-button>
</div> </div>
@@ -503,7 +503,7 @@ const activeTrendName: any = ref(0)
const trendTimer: any = ref() const trendTimer: any = ref()
const trendDataTime: any = ref() const trendDataTime: any = ref()
const showButton = ref(false) const showButton = ref(false)
const latestTime=ref('') const latestTime = ref('')
const decodeMqttPayload = (message: any) => { const decodeMqttPayload = (message: any) => {
try { try {
return JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))) return JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
@@ -552,6 +552,7 @@ const handleTrend = async () => {
}) })
.catch(e => { .catch(e => {
realTrendRef.value && realTrendRef.value.setRealTrendData(false) realTrendRef.value && realTrendRef.value.setRealTrendData(false)
harmonicSpectrumRef.value && harmonicSpectrumRef.value.setloading()
tableLoading.value = false tableLoading.value = false
}) })
@@ -559,8 +560,12 @@ const handleTrend = async () => {
if (res.code == 'A0000') { if (res.code == 'A0000') {
realTrendRef.value && realTrendRef.value.setOverLimitData(res.data) realTrendRef.value && realTrendRef.value.setOverLimitData(res.data)
} }
}).catch(e => {
realTrendRef.value && realTrendRef.value.setRealTrendData(false)
harmonicSpectrumRef.value && harmonicSpectrumRef.value.setloading()
tableLoading.value = false
}) })
realTrendRef.value && await realTrendRef.value &&
realTrendRef.value.open({ devId: deviceId.value, lineId: lineId.value, activeTrendName: activeTrendName.value }) realTrendRef.value.open({ devId: deviceId.value, lineId: lineId.value, activeTrendName: activeTrendName.value })
} }
//实时趋势 //实时趋势
@@ -632,7 +637,7 @@ const handleSearch = () => {
if (oddAndEvenFlag.value) { if (oddAndEvenFlag.value) {
list = list.filter((item: any) => { list = list.filter((item: any) => {
let str = item.name.split('次')[0] let str = item.name.split('次')[0]
if (oddAndEven.value == '1') { if (oddAndEven.value == '1') {
// 奇次 // 奇次
@@ -693,24 +698,25 @@ const nodeClick = async (e: anyObj, node?: any) => {
if (e == undefined) { if (e == undefined) {
return (loading.value = false) return (loading.value = false)
} }
if(e.pname?.includes('便携')){ if (e.pname?.includes('便携')) {
deviceType.value = '1' deviceType.value = '1'
}else{ } else {
deviceType.value = '2' deviceType.value = '2'
} }
searchValue.value = ''
deviceId.value = e?.pid
lineId.value = e?.id
TrendList.value = e
if (!e) {
loading.value = false
return
}
//选中设备名称后,点击标签页也能查询数据,要求点击设备名称后,点击标签页默认查询第一个监测点数据 //选中设备名称后,点击标签页也能查询数据,要求点击设备名称后,点击标签页默认查询第一个监测点数据
if (e.level == 3) { if (e.level == 3) {
searchValue.value = ''
deviceId.value = e?.pid
lineId.value = e?.id
TrendList.value = e
if (!e) {
loading.value = false
return
}
engineeringName.value = node?.parent.parent.data.name engineeringName.value = node?.parent.parent.data.name
await queryDictType({ await queryDictType({
@@ -795,7 +801,7 @@ const nodeClick = async (e: anyObj, node?: any) => {
//治理设备和便携式设备切换判断 //治理设备和便携式设备切换判断
const deviceType = ref('0') const deviceType = ref('0')
const pointTypeChange = (val: any, obj: any) => { const pointTypeChange = (val: any, obj: any) => {
nodeClick(obj) nodeClick(obj)
} }
const realTimeRef: any = ref() const realTimeRef: any = ref()
@@ -1209,7 +1215,7 @@ const handleClick = async (tab?: any) => {
} }
//运行趋势 //运行趋势
if (dataSet.value.includes('_devRunTrend')) { if (dataSet.value.includes('_devRunTrend')) {
tableLoading.value=true tableLoading.value = true
setTimeout(async () => { setTimeout(async () => {
if (tab.props != undefined) await (datePickerRef.value && datePickerRef.value?.setInterval(5)) if (tab.props != undefined) await (datePickerRef.value && datePickerRef.value?.setInterval(5))
@@ -1242,13 +1248,13 @@ const handleClick = async (tab?: any) => {
//查询当前指标 //查询当前指标
if (!dataSet.value.includes('_')) { if (!dataSet.value.includes('_')) {
formInline.id = dataSet.value formInline.id = dataSet.value
latestTime.value='' latestTime.value = ''
tableData.value=[] tableData.value = []
// await deviceRtData(formInline) // await deviceRtData(formInline)
await realTimeData(formInline) await realTimeData(formInline)
.then((res: any) => { .then((res: any) => {
tableData.value = res.data[0].children tableData.value = res.data[0].children
latestTime.value=res.data[0].dataTime latestTime.value = res.data[0].dataTime
formInline.total = res.data.total formInline.total = res.data.total
let queryListName = queryList.value.filter((item: any) => item.id == formInline.targetType) let queryListName = queryList.value.filter((item: any) => item.id == formInline.targetType)
let list = tableData.value.filter((item: any) => { let list = tableData.value.filter((item: any) => {

View File

@@ -205,15 +205,17 @@ const buildTMetric = (name: string, items: RawMetricItem[]): DisplayMetric => {
} }
const sharedUnit = getSharedUnit(items) const sharedUnit = getSharedUnit(items)
const unitsDiffer = sharedUnit == null && new Set(items.map(item => item.unit ?? null)).size > 1
return { return {
name, name,
otherName: name, otherName: name,
unit: getSharedUnit(items), unit: sharedUnit,
type: 't-multi', type: 't-multi',
subItems: items.map(item => ({ subItems: items.map(item => ({
subTitle: extractSubTitle(item.otherName || item.name || ''), subTitle: buildTitle(
extractSubTitle(item.otherName || item.name || ''),
item.unit
),
value: item.data, value: item.data,
})), })),
} }

View File

@@ -46,7 +46,7 @@
<Table ref="tableRef"></Table> <Table ref="tableRef"></Table>
<el-dialog :title="dialogTitle" v-model.trim="dialogFormVisible" :close-on-click-modal="false" <el-dialog :title="dialogTitle" v-model.trim="dialogFormVisible" :close-on-click-modal="false"
:before-close="resetForm" draggable width="40%"> :before-close="resetForm" draggable width="500px">
<el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef"> <el-form :model="form" label-width="120px" :rules="rules" ref="ruleFormRef">
<el-form-item label="设备名称:" prop="name"> <el-form-item label="设备名称:" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" autocomplete="off" clearable <el-input maxlength="32" show-word-limit v-model.trim="form.name" autocomplete="off" clearable

View File

@@ -281,6 +281,9 @@ const resetData = (dataLevel: string) => {
allDataList.value = [] allDataList.value = []
xAixsTimeList.value = [] xAixsTimeList.value = []
} }
const setloading=()=>{
loading.value = false
}
resetData('Primary') resetData('Primary')
const mqttMessage: any = ref() const mqttMessage: any = ref()
const setHarmonicSpectrumData = (val: any) => { const setHarmonicSpectrumData = (val: any) => {
@@ -414,7 +417,7 @@ const init = () => {
} }
onMounted(() => { }) onMounted(() => { })
defineExpose({ resetData, setHarmonicSpectrumData }) defineExpose({ resetData, setHarmonicSpectrumData,setloading })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.harmonic { .harmonic {

View File

@@ -277,6 +277,7 @@ const init = () => {
return return
} }
const handleClick = (tab: any, event: any) => { const handleClick = (tab: any, event: any) => {
tableData.value = [] tableData.value = []
echartsData.value = {} echartsData.value = {}
@@ -305,6 +306,7 @@ const shouldIncludeHarmonicData = (numberPart: number) => {
const setRealTrendData = (val: any) => { const setRealTrendData = (val: any) => {
mqttMessage.value = {} mqttMessage.value = {}
if (!val) { if (!val) {
loading.value = false
return return
} }
loading.value = true loading.value = true
@@ -338,24 +340,24 @@ const selectChange = () => {
//获取国标限值 //获取国标限值
const limitData: any = ref() const limitData: any = ref()
const setOverLimitData = (val: any) => { const setOverLimitData = (val: any) => {
limitData.value = {} // limitData.value = {}
for (let key in val) { // for (let key in val) {
if (activeName.value == 0) { // if (activeName.value == 0) {
if (String(key).includes('uharm')) { // if (String(key).includes('uharm')) {
if (key.startsWith('uharm')) { // if (key.startsWith('uharm')) {
limitData.value[key] = val[key] // limitData.value[key] = val[key]
} // }
} // }
} else if (activeName.value == 1) { // } else if (activeName.value == 1) {
if (String(key).includes('iharm')) { // if (String(key).includes('iharm')) {
limitData.value[key] = val[key] // limitData.value[key] = val[key]
} // }
} else { // } else {
if (String(key).includes('inuharm')) { // if (String(key).includes('inuharm')) {
limitData.value[key] = val[key] // limitData.value[key] = val[key]
} // }
} // }
} // }
} }
onMounted(() => {}) onMounted(() => {})
defineExpose({ open, setRealTrendData, setOverLimitData }) defineExpose({ open, setRealTrendData, setOverLimitData })

View File

@@ -1,211 +1,211 @@
<template> <template>
<!-- 测试项日志 --> <!-- 测试项日志 -->
<div :style="{ height: height }"> <div :style="{ height: height }">
<vxe-table height="auto" auto-resize :data="dataList" v-bind="defaultAttribute" :key="key"> <vxe-table height="auto" auto-resize :data="dataList" v-bind="defaultAttribute" :key="key">
<vxe-column v-for="item in column" :field="item.field" :title="item.title" :formatter="formatter" <vxe-column v-for="item in column" :field="item.field" :title="item.title" :formatter="formatter"
:min-width="item.width" :sortable="item.sortable"></vxe-column> :min-width="item.width" :sortable="item.sortable"></vxe-column>
<vxe-column title="操作" fixed="right" width="120" v-if="showButtom"> <vxe-column title="操作" fixed="right" width="120" v-if="showButtom">
<template v-slot:default="scoped"> <template v-slot:default="scoped">
<el-button link type="primary" @click="revise(scoped.row)">修改</el-button> <el-button link type="primary" @click="revise(scoped.row)">修改</el-button>
<el-button link type="danger" @click="remove(scoped.row)">删除</el-button> <el-button link type="danger" @click="remove(scoped.row)">删除</el-button>
</template> </template>
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<el-dialog draggable v-model="dialogVisible" title="修改" width="400" :before-close="handleClose"> <el-dialog draggable v-model="dialogVisible" title="修改" width="500" :before-close="handleClose">
<el-form :model="form" ref="ruleFormRef" label-width="auto" class="form-one" :rules="rules"> <el-form :model="form" ref="ruleFormRef" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="数据起始时间" prop="proStartTime"> <el-form-item label="数据起始时间" prop="proStartTime">
<el-date-picker v-model="form.proStartTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" <el-date-picker v-model="form.proStartTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择数据起始时间" /> value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择数据起始时间" />
</el-form-item> </el-form-item>
<el-form-item label="数据结束时间" prop="proEndTime"> <el-form-item label="数据结束时间" prop="proEndTime">
<el-date-picker v-model="form.proEndTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" <el-date-picker v-model="form.proEndTime" type="datetime" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择数据结束时间" /> value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择数据结束时间" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button @click="handleClose">取消</el-button> <el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm"> <el-button type="primary" @click="handleConfirm">
确定 确定
</el-button> </el-button>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import { betweenDay } from '@/utils/formatTime' import { betweenDay } from '@/utils/formatTime'
import { defaultAttribute } from '@/components/table/defaultAttribute' import { defaultAttribute } from '@/components/table/defaultAttribute'
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user' import { activateUser, deluser, passwordConfirm } from '@/api/user-boot/user'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { updateRecordData } from '@/api/cs-device-boot/EquipmentDelivery' import { updateRecordData } from '@/api/cs-device-boot/EquipmentDelivery'
import { useAdminInfo } from '@/stores/adminInfo' import { useAdminInfo } from '@/stores/adminInfo'
const dictData = useDictData() const dictData = useDictData()
const voltageLevelList: any = dictData.getBasicData('Dev_Voltage_Stand') const voltageLevelList: any = dictData.getBasicData('Dev_Voltage_Stand')
import { deleteItem } from '@/api/cs-device-boot/csGroup' import { deleteItem } from '@/api/cs-device-boot/csGroup'
const volConTypeList = dictData.getBasicData('Dev_Connect') const volConTypeList = dictData.getBasicData('Dev_Connect')
const emit = defineEmits(['onSubmit']) const emit = defineEmits(['onSubmit'])
const height = mainHeight(295).height const height = mainHeight(295).height
const dataList = ref([]) const dataList = ref([])
const key: any = ref(0) const key: any = ref(0)
const ruleFormRef = ref() const ruleFormRef = ref()
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const showButtom = ref(adminInfo.roleCode.includes('operation_manager') || adminInfo.roleCode.includes('root')) const showButtom = ref(adminInfo.roleCode.includes('operation_manager') || adminInfo.roleCode.includes('root'))
const dialogVisible = ref(false) const dialogVisible = ref(false)
const column: any = ref([ const column: any = ref([
{ field: 'startTime', title: '数据起始时间', width: '140px', sortable: true }, { field: 'startTime', title: '数据起始时间', width: '140px', sortable: true },
{ field: 'endTime', title: '数据结束时间', width: '140px', sortable: true }, { field: 'endTime', title: '数据结束时间', width: '140px', sortable: true },
{ field: 'lastTime', title: '持续时间', width: '140px', sortable: true }, { field: 'lastTime', title: '持续时间', width: '140px', sortable: true },
{ field: 'itemName', title: '数据来源', width: '100px' }, { field: 'itemName', title: '数据来源', width: '100px' },
{ field: 'statisticalInterval', title: '时间间隔(分钟)', width: '120px', }, { field: 'statisticalInterval', title: '时间间隔(分钟)', width: '120px', },
{ field: 'voltageLevel', title: '电压等级', width: '100px', sortable: true }, { field: 'voltageLevel', title: '电压等级', width: '100px', sortable: true },
{ field: 'volConType', title: ' 电压接线方式', width: '120px', sortable: true }, { field: 'volConType', title: ' 电压接线方式', width: '120px', sortable: true },
{ {
field: 'pt', title: 'PT', width: '100px', field: 'pt', title: 'PT', width: '100px',
}, },
{ field: 'ct', title: 'CT', width: '100px', }, { field: 'ct', title: 'CT', width: '100px', },
{ field: 'capacitySi', title: '用户协议容量(MVA)', width: '140px', }, { field: 'capacitySi', title: '用户协议容量(MVA)', width: '140px', },
{ field: 'capacitySt', title: '供电设备容量(MVA)', width: '140px', }, { field: 'capacitySt', title: '供电设备容量(MVA)', width: '140px', },
{ field: 'capacitySscb', title: '基准短路容量(MVA)', width: '140px', }, { field: 'capacitySscb', title: '基准短路容量(MVA)', width: '140px', },
{ field: 'capacitySscmin', title: '最小短路容量(MVA)', width: '140px', }, { field: 'capacitySscmin', title: '最小短路容量(MVA)', width: '140px', },
// { field: 'location', title: ' 测试位置', width: '100px', }, // { field: 'location', title: ' 测试位置', width: '100px', },
]) ])
const form = reactive({ const form = reactive({
proStartTime: '', proStartTime: '',
proEndTime: '', proEndTime: '',
id: '' id: ''
}) })
const rules = { const rules = {
proStartTime: [{ required: true, message: '请输入数据起始时间', trigger: 'blur' }], proStartTime: [{ required: true, message: '请输入数据起始时间', trigger: 'blur' }],
proEndTime: [{ required: true, message: '请输入数据结束时间', trigger: 'blur' }], proEndTime: [{ required: true, message: '请输入数据结束时间', trigger: 'blur' }],
} }
const setData = (data: any) => { const setData = (data: any) => {
dataList.value = JSON.parse(JSON.stringify(data)) dataList.value = JSON.parse(JSON.stringify(data))
key.value += 1 key.value += 1
} }
const formatter = (row: any) => { const formatter = (row: any) => {
if (row.column.field == 'voltageLevel') { if (row.column.field == 'voltageLevel') {
return row.cellValue == null ? '/' : voltageLevelList.filter((item: any) => item.id == row.cellValue)[0]?.name return row.cellValue == null ? '/' : voltageLevelList.filter((item: any) => item.id == row.cellValue)[0]?.name
} else if (row.column.field == 'volConType') { } else if (row.column.field == 'volConType') {
return row.cellValue == null ? '/' : volConTypeList.filter((item: any) => item.id == row.cellValue)[0]?.name return row.cellValue == null ? '/' : volConTypeList.filter((item: any) => item.id == row.cellValue)[0]?.name
} else { } else {
return row.cellValue == null ? '/' : row.cellValue return row.cellValue == null ? '/' : row.cellValue
} }
} }
// 取消 // 取消
const handleClose = () => { const handleClose = () => {
dialogVisible.value = false dialogVisible.value = false
} }
// 确定 // 确定
const handleConfirm = () => { const handleConfirm = () => {
ruleFormRef.value.validate((valid: any) => { ruleFormRef.value.validate((valid: any) => {
if (valid) { if (valid) {
let data = betweenDay(new Date(form.proStartTime), new Date(form.proEndTime)) let data = betweenDay(new Date(form.proStartTime), new Date(form.proEndTime))
if (data < 0) { if (data < 0) {
ElMessage.warning('数据结束时间不能小于数据起始时间') ElMessage.warning('数据结束时间不能小于数据起始时间')
} else { } else {
updateRecordData(form).then((res) => { updateRecordData(form).then((res) => {
ElMessage.success(res.message) ElMessage.success(res.message)
dialogVisible.value = false dialogVisible.value = false
emit('onSubmit') emit('onSubmit')
}) })
} }
} }
}) })
// dialogVisible.value = false // dialogVisible.value = false
} }
// 删除 // 删除
const remove = (row: any) => { const remove = (row: any) => {
ElMessageBox.prompt('二次校验密码确认', '', { ElMessageBox.prompt('二次校验密码确认', '', {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
customClass: 'customInput', customClass: 'customInput',
inputType: 'text', inputType: 'text',
beforeClose: (action, instance, done) => { beforeClose: (action, instance, done) => {
if (action === 'confirm') { if (action === 'confirm') {
if (instance.inputValue == null) { if (instance.inputValue == null) {
return ElMessage.warning('请输入密码') return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) { } else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length) return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else { } else {
done(); done();
} }
} else { } else {
done(); done();
} }
} }
}).then(({ value }) => { }).then(({ value }) => {
passwordConfirm(value).then(res => { passwordConfirm(value).then(res => {
console.log('密码正确'); console.log('密码正确');
deleteItem({ id: row.id }).then(() => { deleteItem({ id: row.id }).then(() => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
emit('onSubmit') emit('onSubmit')
}) })
}) })
}) })
} }
// 修改 // 修改
const revise = (row: any) => { const revise = (row: any) => {
ElMessageBox.prompt('二次校验密码确认', '', { ElMessageBox.prompt('二次校验密码确认', '', {
confirmButtonText: '确认', confirmButtonText: '确认',
cancelButtonText: '取消', cancelButtonText: '取消',
customClass: 'customInput', customClass: 'customInput',
inputType: 'text', inputType: 'text',
beforeClose: (action, instance, done) => { beforeClose: (action, instance, done) => {
if (action === 'confirm') { if (action === 'confirm') {
if (instance.inputValue == null) { if (instance.inputValue == null) {
return ElMessage.warning('请输入密码') return ElMessage.warning('请输入密码')
} else if (instance.inputValue?.length > 32) { } else if (instance.inputValue?.length > 32) {
return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length) return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
} else { } else {
done(); done();
} }
} else { } else {
done(); done();
} }
} }
}).then(({ value }) => { }).then(({ value }) => {
passwordConfirm(value).then(res => { passwordConfirm(value).then(res => {
dialogVisible.value = true dialogVisible.value = true
form.proStartTime = row.startTime form.proStartTime = row.startTime
form.proEndTime = row.endTime form.proEndTime = row.endTime
form.id = row.id form.id = row.id
}) })
}) })
} }
defineExpose({ setData }) defineExpose({ setData })
</script> </script>
<style lang="scss"> <style lang="scss">
.customInput { .customInput {
.el-input__inner { .el-input__inner {
-webkit-text-security: disc !important; -webkit-text-security: disc !important;
} }
} }
</style> </style>

View File

@@ -32,6 +32,7 @@
title="绑定工程" title="绑定工程"
class="cn-operate-dialog" class="cn-operate-dialog"
:close-on-click-modal="false" :close-on-click-modal="false"
width="500px"
> >
<el-input maxlength="32" show-word-limit <el-input maxlength="32" show-word-limit

View File

@@ -126,7 +126,7 @@
<!-- <el-empty v-if="dirList.length === 0" /> --> <!-- <el-empty v-if="dirList.length === 0" /> -->
</div> </div>
<popup ref="fileRef"></popup> <popup ref="fileRef"></popup>
<el-dialog v-model.trim="addDeviceDirOpen" :destroy-on-close="true" title="新建文件夹目录" width="500" @closed="close"> <el-dialog v-model.trim="addDeviceDirOpen" draggable :destroy-on-close="true" title="新建文件夹目录" width="500" @closed="close">
<el-form ref="formRef" :model="form" <el-form ref="formRef" :model="form"
:rules="{ path: [{ required: true, message: '请输入文件夹名称', trigger: 'blur' }] }"> :rules="{ path: [{ required: true, message: '请输入文件夹名称', trigger: 'blur' }] }">
<el-form-item label="文件夹名称" prop="path"> <el-form-item label="文件夹名称" prop="path">

View File

@@ -1,7 +1,7 @@
<!-- 设备文件下载 --> <!-- 设备文件下载 -->
<template> <template>
<div :class="downLoading ? 'all_disabled' : ''"> <div :class="downLoading ? 'all_disabled' : ''">
<el-dialog v-model.trim="dialogVisible" title="文件信息" width="50%" @closed="handleClose"> <el-dialog draggable v-model.trim="dialogVisible" title="文件信息" width="800px" @closed="handleClose">
<div v-loading="loading"> <div v-loading="loading">
<div <div

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog device-manage-popup" v-model.trim="dialogVisible" title="设备模版分组"> <el-dialog draggable class="cn-operate-dialog device-manage-popup" v-model.trim="dialogVisible" title="设备模版分组" width="500px">
<el-descriptions class="mb10" :column="3" border> <el-descriptions class="mb10" :column="3" border>
<el-descriptions-item label="名称"> <el-descriptions-item label="名称">
{{ popupData.deviceData.name }} {{ popupData.deviceData.name }}

View File

@@ -55,6 +55,7 @@
draggable draggable
title="绑定工程 / 设备" title="绑定工程 / 设备"
class="cn-operate-dialog" class="cn-operate-dialog"
width="800px"
:close-on-click-modal="false" :close-on-click-modal="false"
> >
<div class="dialog-content"> <div class="dialog-content">

View File

@@ -1,14 +1,15 @@
<template> <template>
<el-dialog v-model.trim="dialogVisible" :title="title" draggable <el-dialog
:style="{ width: popupType == 0 || popupType == 1 ? '500px' : '1100px' }"> :width="(popupType == 0 || popupType == 1) ? '500px' : (popupType == 2 || popupType == 3) ? '800px' : '1100px'"
v-model.trim="dialogVisible" :title="title" draggable>
<!-- 新增方案数据 --> <!-- 新增方案数据 -->
<el-form :model="form" scroll-to-error label-width="140px" :rules="rules1" ref="ruleFormRef1" class="form-one" <el-form :model="form" scroll-to-error label-width="140px" :rules="rules1" ref="ruleFormRef1" class="form-one"
v-if="popupType == 0 || popupType == 1"> v-if="popupType == 0 || popupType == 1">
<el-form-item label="方案名称:" prop="itemName"> <el-form-item label="方案名称:" prop="itemName">
<el-input maxlength="32" show-word-limit v-model.trim="form.itemName" placeholder="请输入方案名称" /> <el-input maxlength="32" show-word-limit v-model.trim="form.itemName" placeholder="请输入方案名称" />
</el-form-item> </el-form-item>
<el-form-item label="方案描述:" prop="describe"> <el-form-item label="方案描述:" prop="describe">
<el-input show-word-limit maxlength="300" type="textarea" v-model.trim="form.describe" <el-input show-word-limit maxlength="300" type="textarea" v-model.trim="form.describe"
placeholder="请输入方案描述" /> placeholder="请输入方案描述" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -18,7 +19,7 @@
<el-form :model="form1" ref="ruleFormRef2" scroll-to-error class="form-two" label-width="140px" <el-form :model="form1" ref="ruleFormRef2" scroll-to-error class="form-two" label-width="140px"
:rules="rules2"> :rules="rules2">
<el-form-item label="测试项名称:" prop="itemName"> <el-form-item label="测试项名称:" prop="itemName">
<el-input maxlength="32" show-word-limit v-model.trim="form1.itemName" placeholder="请输入测试项名称" /> <el-input maxlength="32" show-word-limit v-model.trim="form1.itemName" placeholder="请输入测试项名称" />
</el-form-item> </el-form-item>
<el-form-item label="测量间隔:" prop="statisticalInterval"> <el-form-item label="测量间隔:" prop="statisticalInterval">
<el-select v-model.trim="form1.statisticalInterval" placeholder="请选择测量间隔" clearable <el-select v-model.trim="form1.statisticalInterval" placeholder="请选择测量间隔" clearable
@@ -41,7 +42,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="最小短路容量:" prop="capacitySscmin"> <el-form-item label="最小短路容量:" prop="capacitySscmin">
<el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySscmin" oninput="value=value.replace(/[^\-?\d.]/g,'') <el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySscmin" oninput="value=value.replace(/[^\-?\d.]/g,'')
.replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.') .replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')
.replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" autocomplete="off" placeholder="请选择最小短路容量"> .replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" autocomplete="off" placeholder="请选择最小短路容量">
<template #append>MVA</template> <template #append>MVA</template>
@@ -49,7 +50,7 @@
</el-form-item> </el-form-item>
<el-form-item label="用户协议容量:" prop="capacitySi"> <el-form-item label="用户协议容量:" prop="capacitySi">
<el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySi" autocomplete="off" <el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySi" autocomplete="off"
oninput="value=value.replace(/[^\-?\d.]/g,'') oninput="value=value.replace(/[^\-?\d.]/g,'')
.replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.') .replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')
.replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入用户协议容量"> .replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入用户协议容量">
@@ -58,7 +59,7 @@
</el-form-item> </el-form-item>
<el-form-item label="基准短路容量:" prop="capacitySscb"> <el-form-item label="基准短路容量:" prop="capacitySscb">
<el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySscb" oninput="value=value.replace(/[^\-?\d.]/g,'') <el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySscb" oninput="value=value.replace(/[^\-?\d.]/g,'')
.replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.') .replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')
.replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入基准短路容量"> .replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入基准短路容量">
<template #append>MVA</template> <template #append>MVA</template>
@@ -66,26 +67,26 @@
</el-form-item> </el-form-item>
<el-form-item label="供电设备容量:" prop="capacitySt"> <el-form-item label="供电设备容量:" prop="capacitySt">
<el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySt" oninput="value=value.replace(/[^\-?\d.]/g,'') <el-input maxlength="32" show-word-limit v-model.trim="form1.capacitySt" oninput="value=value.replace(/[^\-?\d.]/g,'')
.replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.') .replace(/^\./g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')
.replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入供电设备容量"> .replace('-','$#$').replace(/\-/g,'').replace('$#$','-')" placeholder="请输入供电设备容量">
<template #append>MVA</template> <template #append>MVA</template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item label="PT变比" prop="pt"> <el-form-item label="PT变比" prop="pt">
<el-input maxlength="32" show-word-limit style="width: 48%" v-model.number.trim="form1.pt" <el-input maxlength="32" show-word-limit style="width: 48%" v-model.number.trim="form1.pt"
autocomplete="off" placeholder="请输入PT变比" oninput="value=value.replace(/[^0-9.]/g,'')" /> autocomplete="off" placeholder="请输入PT变比" oninput="value=value.replace(/[^0-9.]/g,'')" />
<el-input maxlength="32" show-word-limit style="width: 48%" v-model.number.trim="form1.pt1" <el-input maxlength="32" show-word-limit style="width: 48%" v-model.number.trim="form1.pt1"
autocomplete="off" placeholder="请输入PT变比" oninput="value=value.replace(/[^0-9.]/g,'')" /> autocomplete="off" placeholder="请输入PT变比" oninput="value=value.replace(/[^0-9.]/g,'')" />
</el-form-item> </el-form-item>
<el-form-item label="CT变比" prop="ct"> <el-form-item label="CT变比" prop="ct">
<el-input maxlength="32" show-word-limit v-model.number.trim="form1.ct" style="width: 48%" <el-input maxlength="32" show-word-limit v-model.number.trim="form1.ct" style="width: 48%"
autocomplete="off" oninput="value=value.replace(/[^0-9.]/g,'')" placeholder="请输入CT变比" /> autocomplete="off" oninput="value=value.replace(/[^0-9.]/g,'')" placeholder="请输入CT变比" />
<el-input maxlength="32" show-word-limit v-model.number.trim="form1.ct1" style="width: 48%" <el-input maxlength="32" show-word-limit v-model.number.trim="form1.ct1" style="width: 48%"
autocomplete="off" oninput="value=value.replace(/[^0-9.]/g,'')" placeholder="请输入CT变比" /> autocomplete="off" oninput="value=value.replace(/[^0-9.]/g,'')" placeholder="请输入CT变比" />
</el-form-item> </el-form-item>
<el-form-item label="监测位置:" prop="location" style="width: 100%"> <el-form-item label="监测位置:" prop="location" style="width: 100%">
<el-input show-word-limit maxlength="300" type="textarea" v-model.trim="form1.location" <el-input show-word-limit maxlength="300" type="textarea" v-model.trim="form1.location"
placeholder="请输入监测位置" /> placeholder="请输入监测位置" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -485,10 +486,10 @@ const submit = () => {
let subForm = JSON.parse(JSON.stringify(form1.value)) let subForm = JSON.parse(JSON.stringify(form1.value))
subForm.list = checkedIdList.value subForm.list = checkedIdList.value
console.log(title.value.includes('绑定测试项')); console.log(title.value.includes('绑定测试项'));
updateRecord(subForm).then((res: any) => { updateRecord(subForm).then((res: any) => {
if (res.code == 'A0000') { if (res.code == 'A0000') {
ElMessage.success(title.value.includes('绑定测试项')?'绑定测试项成功':'修改测试项成功') ElMessage.success(title.value.includes('绑定测试项') ? '绑定测试项成功' : '修改测试项成功')
initForm() initForm()
emit('onSubmit') emit('onSubmit')
close() close()

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog" draggable v-model.trim="dialogVisible" width="900px" :title="title" @close="emit('close')"> <el-dialog class="cn-operate-dialog" draggable v-model.trim="dialogVisible" width="800px" :title="title" @close="emit('close')">
<el-scrollbar> <el-scrollbar>
<div style="padding-left: 50px"> <div style="padding-left: 50px">
<el-divider content-position="center">基础数据</el-divider> <el-divider content-position="center">基础数据</el-divider>

View File

@@ -1,48 +1,50 @@
<template> <template>
<el-dialog draggable class="cn-operate-dialog" width="540px" v-model.trim="dialogVisible" :title="title"> <el-dialog draggable class="cn-operate-dialog" width="540px" v-model.trim="dialogVisible" :title="title">
<el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules"> <div style="height: 300px;overflow-y: auto;">
<el-form-item label="项目名称" prop="name"> <el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入项目名称" /> <el-form-item label="项目名称" prop="name">
</el-form-item> <el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入项目名称" />
<el-form-item label="所属工程" prop="engineeringId"> </el-form-item>
<el-select v-model="form.engineeringId" filterable placeholder="请选择工程" clearable> <el-form-item label="所属工程" prop="engineeringId">
<el-option <el-select v-model="form.engineeringId" filterable placeholder="请选择工程" clearable>
v-for="item in engineeringList" <el-option v-for="item in engineeringList" :key="item.engineeringId"
:key="item.engineeringId" :label="item.engineeringName" :value="item.engineeringId" />
:label="item.engineeringName" </el-select>
:value="item.engineeringId" </el-form-item>
/> <el-form-item label="区域" prop="area">
</el-select> <el-input maxlength="32" show-word-limit v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item> </el-form-item>
<el-form-item label="区域" prop="area"> <el-form-item label="备注" prop="description">
<el-input maxlength="32" show-word-limit v-model="form.area" clearable placeholder="请输入区域" /> <el-input maxlength="300" show-word-limit v-model="form.description" :rows="2" type="textarea"
</el-form-item> clearable placeholder="请输入备注" />
<el-form-item label="备注" prop="description"> </el-form-item>
<el-input maxlength="300" show-word-limit v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" /> <el-form-item label="排序" prop="sort">
</el-form-item> <el-input-number v-model.number="form.sort" style="width: 100%;" :min="0" />
<el-form-item label="排序" prop="sort"> </el-form-item>
<el-input-number v-model.number="form.sort" style="width: 100%;" :min="0" /> <el-form-item label="拓扑图">
</el-form-item> <div class="image-radio-group">
<el-form-item label="拓扑图"> <div class="image-radio-item" v-for="item in images" :key="item.id"
<div class="image-radio-group"> @click="handleSelect(item.id)">
<div class="image-radio-item" v-for="item in images" :key="item.id" @click="handleSelect(item.id)"> <el-radio :label="item.id" v-model="form.topoIds" class="hidden-radio">
<el-radio :label="item.id" v-model="form.topoIds" class="hidden-radio"> {{ item.name }}
{{ item.name }} </el-radio>
</el-radio> <div class="image-container" :class="{ selected: form.topoIds === item.id }">
<div class="image-container" :class="{ selected: form.topoIds === item.id }"> <img :src="item.url" v-if="item.url" class="image-preview" />
<img :src="item.url" v-if="item.url" class="image-preview" /> <div v-else style="width: 110px; height: 70px; text-align: center; line-height: 70px">
<div v-else style="width: 120px; height: 90px; text-align: center; line-height: 90px"> 暂无图片
暂无图片 </div>
</div> <div class="image-overlay" v-if="form.topoIds === item.id">
<div class="image-overlay" v-if="form.topoIds === item.id"> <el-icon class="check-icon">
<el-icon class="check-icon"><Check /></el-icon> <Check />
</el-icon>
</div>
</div> </div>
<div class="image-name">{{ item.name }}</div>
</div> </div>
<div class="image-name">{{ item.name }}</div>
</div> </div>
</div> </el-form-item>
</el-form-item> </el-form>
</el-form> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@@ -94,7 +96,7 @@ const props = {
// checkStrictly: true // checkStrictly: true
} }
const open = (text: string, List: any, data?: anyObj, id?: string) => { const open = (text: string, List: any, data?: anyObj, id?: string) => {
getImageList().catch(() => {}) getImageList().catch(() => { })
formRef.value?.resetFields() formRef.value?.resetFields()
title.value = text title.value = text
dialogVisible.value = true dialogVisible.value = true
@@ -189,8 +191,8 @@ defineExpose({ open })
} }
.image-preview { .image-preview {
width: 120px; width: 110px;
height: 90px; height: 70px;
} }
.image-overlay { .image-overlay {
@@ -213,9 +215,12 @@ defineExpose({ open })
.image-name { .image-name {
margin-top: 8px; margin-top: 8px;
font-size: 14px; font-size: 14px;
width: 120px; width: 110px;
white-space: nowrap; /* 强制文字单行显示,不换行 */ white-space: nowrap;
overflow: hidden; /* 隐藏超出容器的文字 */ /* 强制文字单行显示,不换行 */
text-overflow: ellipsis; /* 超出部分显示省略号(点点点) */ overflow: hidden;
/* 隐藏超出容器的文字 */
text-overflow: ellipsis;
/* 超出部分显示省略号(点点点) */
} }
</style> </style>

View File

@@ -1,5 +1,5 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<TableHeader> <TableHeader>
<template v-slot:select> <template v-slot:select>
<el-form-item label="关键字筛选"> <el-form-item label="关键字筛选">
@@ -90,8 +90,8 @@
</TableHeader> </TableHeader>
<Table ref="tableRef" :checkbox-config="checkboxConfig" :key="tableKey" @sort-change="handleSortChange"></Table> <Table ref="tableRef" :checkbox-config="checkboxConfig" :key="tableKey" @sort-change="handleSortChange"></Table>
<FactoryForm ref="factoryFormRef" :engineering-list="engineeringList" <FactoryForm ref="factoryFormRef" :engineering-list="engineeringList" :dev-type-options="devTypeOptions"
:dev-type-options="devTypeOptions" :dev-type-options2="devTypeOptions2" :dev-model-options="devModelOptions" :dev-type-options2="devTypeOptions2" :dev-model-options="devModelOptions"
:dev-model-options2="devModelOptions2" @success="onFormSuccess" /> :dev-model-options2="devModelOptions2" @success="onFormSuccess" />
<div class="qrcode-label"> <div class="qrcode-label">
@@ -126,6 +126,7 @@ import {
resetFactory, resetFactory,
portableDeviceRegister, portableDeviceRegister,
portableDeviceAccess, portableDeviceAccess,
accessByUpdateMac
} from '@/api/cs-system-boot/device' } from '@/api/cs-system-boot/device'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import { fullUrl } from '@/utils/common' import { fullUrl } from '@/utils/common'
@@ -364,102 +365,7 @@ const tableStore = new TableStore({
width: 180, width: 180,
render: 'buttons', render: 'buttons',
buttons: [ buttons: [
//直连设备注册
// {
// title: '注册',
// type: 'primary',
// icon: 'el-icon-Grid',
// render: 'basicButton',
// disabled: row => {
// return (
// (row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
// row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
// row.status == '1'
// )
// },
// click: row => {
// // 直连设备注册
// ElMessageBox.confirm('确定注册该设备吗?', '提示', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'warning'
// })
// .then(() => {
// governDeviceRegister({
// nDid: row.ndid,
// type: '4'
// }).then(res => {
// ElMessage.success(res.message)
// tableStore.onTableAction('search', {})
// })
// })
// .catch(e => {})
// }
// },
// //便携式设备注册
// {
// title: '注册',
// type: 'primary',
// icon: 'el-icon-Grid',
// render: 'basicButton',
// disabled: row => {
// // return (
// // (row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
// // row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
// // row.status != '1'
// // )
// return true
// },
// click: row => {
// // 便携式设备注册
// ElMessageBox.confirm('确定注册该设备吗?', '提示', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'warning'
// })
// .then(() => {
// portableDeviceRegister({
// nDid: row.ndid
// }).then(res => {
// ElMessage.success(res.message)
// tableStore.index()
// })
// })
// .catch(e => {})
// }
// },
//直连设备接入
// {
// title: '接入',
// type: 'primary',
// icon: 'el-icon-Grid',
// render: 'basicButton',
// disabled: row => {
// return (
// (row.devType == '8b45cf6b7f5266e777d07c166ad5fa77' &&
// row.devModel == 'a0d4da4b5c17b2172362a3f5a27bf217') ||
// row.status != '2'
// )
// },
// click: row => {
// // 直连设备接入
// ElMessageBox.confirm('确定接入该设备吗?', '提示', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'warning'
// })
// .then(() => {
// governDeviceRegister({
// nDid: row.ndid,
// type: '4'
// }).then(res => {
// ElMessage.success(res.message)
// tableStore.onTableAction('search', {})
// })
// })
// .catch(e => {})
// }
// },
// 在线设备注册 // 在线设备注册
{ {
title: '接入', title: '接入',
@@ -469,9 +375,9 @@ const tableStore = new TableStore({
loading: 'loading1', loading: 'loading1',
disabled: row => { disabled: row => {
return !( return !(
row.devType == '123202e523be2b8defc8d0c2f118f232' && (row.devType == '123202e523be2b8defc8d0c2f118f232' || row.devType != '8b45cf6b7f5266e777d07c166ad5fa77') &&
row.associatedProject != null && row.associatedProject != null &&
row.status != 3 (row.status == 5 || row.isAccess == 0)
) )
}, },
click: row => { click: row => {
@@ -483,57 +389,90 @@ const tableStore = new TableStore({
}).then(() => { }).then(() => {
row.loading1 = true row.loading1 = true
onlineRegister({ if (row.status == 5) {
projectId: row.associatedProject, // 在线设备注册
nDid: row.ndid if (row.devType == '123202e523be2b8defc8d0c2f118f232') {
}) onlineRegister({
.then(res => { projectId: row.associatedProject,
ElMessage.success(res.message) nDid: row.ndid
row.loading1 = false })
tableStore.index() .then(res => {
}) ElMessage.success(res.message)
.catch(() => { row.loading1 = false
row.loading1 = false tableStore.index()
})
.catch(() => {
row.loading1 = false
})
} else {
// //便携式设备手动接入
portableDeviceRegister({
nDid: row.ndid
})
.then(res => {
row.loading1 = false
ElMessage.success(res.message)
tableStore.index()
})
.catch(e => {
row.loading1 = false
})
}
} else {
accessByUpdateMac({
nDid: row.ndid
}) })
.then(res => {
row.loading1 = false
ElMessage.success(res.message)
tableStore.index()
})
.catch(e => {
row.loading1 = false
})
}
}) })
} }
}, },
//便携式设备手动接入 //便携式设备手动接入
{ // {
title: '接入', // title: '接入',
type: 'primary', // type: 'primary',
icon: 'el-icon-Grid', // icon: 'el-icon-Grid',
render: 'basicButton', // render: 'basicButton',
loading: 'loading1', // loading: 'loading1',
disabled: row => { // disabled: row => {
return ( // return (
(row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' && // (row.devType != '8b45cf6b7f5266e777d07c166ad5fa77' &&
row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') || // row.devModel != 'a0d4da4b5c17b2172362a3f5a27bf217') ||
row.status != '6' // row.status != '6'
) // )
}, // },
click: row => { // click: row => {
// 便携式设备手动接入 // // 便携式设备手动接入
ElMessageBox.confirm('确定接入该设备吗?', '提示', { // ElMessageBox.confirm('确定接入该设备吗?', '提示', {
confirmButtonText: '确认', // confirmButtonText: '确认',
cancelButtonText: '取消', // cancelButtonText: '取消',
type: 'warning' // type: 'warning'
}) // })
.then(() => { // .then(() => {
row.loading1 = true // row.loading1 = true
portableDeviceAccess({ // portableDeviceAccess({
nDid: row.ndid // nDid: row.ndid
}).then(res => { // }).then(res => {
ElMessage.success(res.message) // ElMessage.success(res.message)
row.loading1 = false // row.loading1 = false
tableStore.index() // tableStore.index()
}) // })
}) // })
.catch(e => { // .catch(e => {
row.loading1 = false // row.loading1 = false
}) // })
} // }
}, // },
{ {
title: '接入', title: '接入',
type: 'primary', type: 'primary',

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog class="cn-operate-dialog" v-model.trim="dialogVisible" title="编辑拓扑图信息"> <el-dialog draggable class="cn-operate-dialog" v-model.trim="dialogVisible" title="编辑拓扑图信息" width="800px">
<el-form :label-width="140"> <el-form :label-width="140">
<el-form-item label="拓扑图:" style="height: auto !important" class="form-one"> <el-form-item label="拓扑图:" style="height: auto !important" class="form-one">
<div class="gplot-content"> <div class="gplot-content">

View File

@@ -1,60 +1,74 @@
<template> <template>
<div class='default-main'> <div class="default-main">
<el-tabs v-model.trim='activeName' type='border-card' @tab-click='init'> <el-tabs v-model.trim="activeName" type="border-card" @tab-change="loadTabContent">
<el-tab-pane label='用户协议' name='User_Agreement'></el-tab-pane> <el-tab-pane label="用户协议" name="User_Agreement"></el-tab-pane>
<el-tab-pane label='个人信息保护政策' name='Personal_Infor_Protect'></el-tab-pane> <el-tab-pane label="个人信息保护政策" name="Personal_Infor_Protect"></el-tab-pane>
<el-tab-pane label='系统介绍' name='introduction'></el-tab-pane> <el-tab-pane label="系统介绍" name="introduction"></el-tab-pane>
<el-tab-pane label='使用手册' name='User_Manual'></el-tab-pane> <el-tab-pane label="使用手册" name="User_Manual"></el-tab-pane>
<el-tab-pane label='公司介绍' name='Company_Profile'></el-tab-pane> <el-tab-pane label="公司介绍" name="Company_Profile"></el-tab-pane>
<div class='agreement' :style='{ height: height }'> <div class="agreement" :style="{ height: height }">
<div style='margin-top: 5px; right: 10px; position: absolute; z-index: 9999999'> <div style="margin-top: 5px; right: 10px; position: absolute; z-index: 9999999">
<el-button type='primary' @click='submit' icon='el-icon-Checked'>保存</el-button> <el-button type="primary" @click="submit" icon="el-icon-Checked">保存</el-button>
</div> </div>
<WangEditor v-model.trim='html' style='border-top: none' /> <WangEditor v-if="editorVisible" :key="activeName" v-model="html" style="border-top: none" />
</div> </div>
</el-tabs> </el-tabs>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref, nextTick } from 'vue' import { ref, nextTick } from 'vue'
import { mainHeight } from '@/utils/layout' import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData' import { useDictData } from '@/stores/dictData'
import { BasicDictData } from '@/stores/interface' import { BasicDictData } from '@/stores/interface'
import { addAppInfo, queryAppInfo } from '@/api/cs-system-boot/appinfo' import { addAppInfo, queryAppInfo } from '@/api/cs-system-boot/appinfo'
import WangEditor from '@/components/wangEditor/index.vue' import WangEditor from '@/components/wangEditor/index.vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
defineOptions({ defineOptions({
name: 'govern/setting/app' name: 'govern/setting/app'
}) })
const dic = useDictData().getBasicData('appInformationType')
const id = ref('') const dic = useDictData().getBasicData('appInformationType')
const activeName = ref('User_Agreement') const id = ref('')
const html = ref('') const activeName = ref('User_Agreement')
const height = mainHeight(80).height const html = ref('')
const submit = () => { const editorVisible = ref(false)
addAppInfo({ const height = mainHeight(80).height
type: id.value,
content: html.value const submit = () => {
}).then((res) => { addAppInfo({
ElMessage.success('保存成功') type: id.value,
}) content: html.value
} }).then(() => {
const init = () => { ElMessage.success('保存成功')
nextTick(() => { })
dic.forEach((item: BasicDictData) => { }
if (item.code == activeName.value) {
const loadTabContent = async (paneName: string | number) => {
editorVisible.value = false
id.value = item.id await nextTick()
} await nextTick()
})
queryAppInfo(id.value).then((res: any) => { const matched = dic.find((item: BasicDictData) => item.code === String(paneName))
html.value = res.data.content if (!matched) {
}) id.value = ''
}) html.value = ''
} editorVisible.value = true
init() return
}
</script>
id.value = matched.id
try {
const res: any = await queryAppInfo(id.value)
html.value = res.data?.content ?? ''
} catch {
html.value = ''
}
await nextTick()
editorVisible.value = true
}
loadTabContent(activeName.value)
</script>

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog width="500px" v-model.trim="dialogVisible" :title="title"> <el-dialog draggable width="500px" v-model.trim="dialogVisible" :title="title">
<el-form :model="form" ref="formRef" class="form-one" label-width="auto" :rules="rules"> <el-form :model="form" ref="formRef" class="form-one" label-width="auto" :rules="rules">
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入名称" /> <el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入名称" />

View File

@@ -1,6 +1,6 @@
<template> <template>
<el-dialog draggable class="cn-operate-dialog statistical-type-binding" v-model.trim="dialogVisible" title="绑定指标" <el-dialog draggable class="cn-operate-dialog statistical-type-binding" v-model.trim="dialogVisible" title="绑定指标"
style="width: 1200px" @closed="close"> width="1200px" @closed="close">
<el-scrollbar style="padding-right: 0"> <el-scrollbar style="padding-right: 0">
<div class="box"> <div class="box">
<div class="box-left"> <div class="box-left">

View File

@@ -8,7 +8,7 @@
@close="cancel" @close="cancel"
> >
<div style="display: flex"> <div style="display: flex">
<el-form :inline="false" :model="form" label-width="auto" :rules="rules" ref="formRef" style="flex: 1"> <el-form :inline="false" :model="form" label-width="auto" :rules="rules" ref="formRef" style="width: 400px;">
<el-form-item class="top" label="组件名称" prop="name"> <el-form-item class="top" label="组件名称" prop="name">
<el-input maxlength="32" show-word-limit v-model="form.name" placeholder="请输入组件名称"></el-input> <el-input maxlength="32" show-word-limit v-model="form.name" placeholder="请输入组件名称"></el-input>
</el-form-item> </el-form-item>
@@ -48,7 +48,7 @@
<el-input-number v-model.number="form.sort" style="width: 100%;" :min="0" /> <el-input-number v-model.number="form.sort" style="width: 100%;" :min="0" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style="width: 600px; height: 390px; overflow: hidden"> <div style="flex: 1; width: 600px; height: 390px; overflow: hidden">
<div class="ml10" style="font-weight: 600">组件展示</div> <div class="ml10" style="font-weight: 600">组件展示</div>
<component <component
:is="registerComponent(form.path)" :is="registerComponent(form.path)"

View File

@@ -1,5 +1,5 @@
<template> <template>
<el-dialog width='600px' v-model.trim='dialogVisible' :title='title'> <el-dialog width='500px' v-model.trim='dialogVisible' :title='title'>
<el-scrollbar> <el-scrollbar>
<el-form :inline='false' :model='form' label-width='auto' class="form-one" :rules='rules' ref='formRef'> <el-form :inline='false' :model='form' label-width='auto' class="form-one" :rules='rules' ref='formRef'>
<el-form-item label='名称' prop='name'> <el-form-item label='名称' prop='name'>
@@ -9,9 +9,7 @@
<el-input maxlength="32" show-word-limit v-model.trim='form.code' placeholder="请输入字典编码"></el-input> <el-input maxlength="32" show-word-limit v-model.trim='form.code' placeholder="请输入字典编码"></el-input>
</el-form-item> </el-form-item>
<el-form-item label='排序' class='top' prop='sort'>
<el-input-number v-model.trim="form.sort" :min="0" />
</el-form-item>
<el-form-item label='开启等级' class='top'> <el-form-item label='开启等级' class='top'>
<el-select v-model.trim='form.openLevel' placeholder='选择开启等级'> <el-select v-model.trim='form.openLevel' placeholder='选择开启等级'>
<el-option v-for='item in OpenLevel' :key='item.value' :label='item.label' :value='item.value'> <el-option v-for='item in OpenLevel' :key='item.value' :label='item.label' :value='item.value'>
@@ -29,6 +27,9 @@
<el-input show-word-limit maxlength="300" v-model.trim='form.remark' placeholder='请输入字典描述' <el-input show-word-limit maxlength="300" v-model.trim='form.remark' placeholder='请输入字典描述'
type='textarea' :rows='2'></el-input> type='textarea' :rows='2'></el-input>
</el-form-item> </el-form-item>
<el-form-item label='排序' class='top' prop='sort'>
<el-input-number v-model.trim="form.sort" :min="0" style="width: 100%;"/>
</el-form-item>
</el-form> </el-form>
</el-scrollbar> </el-scrollbar>

View File

@@ -41,11 +41,11 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="Android路径:" prop="androidPath" v-if="form.versionType == 'APP'"> <el-form-item label="Android路径:" prop="androidPath" v-if="form.versionType == 'APP'">
<el-input maxlength="32" show-word-limit v-model.trim="form.androidPath" <el-input v-model.trim="form.androidPath"
placeholder="请输入Android路径" /> placeholder="请输入Android路径" />
</el-form-item> </el-form-item>
<el-form-item label="IOS路径:" prop="iosPath" v-if="form.versionType == 'APP'"> <el-form-item label="IOS路径:" prop="iosPath" v-if="form.versionType == 'APP'">
<el-input maxlength="32" show-word-limit v-model.trim="form.iosPath" placeholder="请输入IOS路径" /> <el-input v-model.trim="form.iosPath" placeholder="请输入IOS路径" />
</el-form-item> </el-form-item>
</el-form> </el-form>