This commit is contained in:
jingna 2026-05-18 18:31:31 +08:00
parent 2bf510dced
commit 26b244cafa
16 changed files with 682 additions and 362 deletions

View File

@ -20,19 +20,25 @@ export async function fetchDeviceStatus(): Promise<DeviceStatus> {
const response = await http.get<ApiResponse<DeviceStatus>>('/device-status')
return response.data.data
}
export async function fetchDeviceConfig(): Promise<DeviceConfigPayload> {
const response = await http.get<ApiResponse<DeviceConfigPayload>>('/config/device')
return response.data.data
}
export async function fetchDeviceNet(nic: string): Promise<DeviceConfigPayload> {
const response = await http.get<ApiResponse<DeviceConfigPayload>>(`/config/device/net?nic=${nic}`)
return response.data.data
}
export async function fetchDevicePort(uart: string): Promise<DeviceConfigPayload> {
const response = await http.get<ApiResponse<DeviceConfigPayload>>(`/config/device/uart?port=${uart}`)
return response.data.data
}
export async function fetchChannelConfig(): Promise<ChannelConfigPayload> {
const response = await http.get<ApiResponse<ChannelConfigPayload>>('/config/channel')
return response.data.data
}
export async function fetchLineAlarmSetting(): Promise<LineAlarmSettingPayload> {
const response = await http.get<ApiResponse<LineAlarmSettingPayload>>('/config/line_alarm_setting')
export async function fetchLineAlarmSetting(lineNo: number): Promise<LineAlarmSettingPayload> {
const response = await http.get<ApiResponse<LineAlarmSettingPayload>>(`/config/line_alarm_setting?line_no=${lineNo}`)
return response.data.data
}
@ -46,14 +52,14 @@ export async function fetchSystemConfig(): Promise<SystemConfigPayload> {
return response.data.data
}
export async function fetchAlarmHistory(page = 1, size = 20): Promise<AlarmEvent[]> {
const response = await http.get<ApiResponse<AlarmEvent[]>>(`/alarm/list?page=${page}&size=${size}`)
export async function fetchAlarmHistory(params: any): Promise<AlarmEvent[]> {
const response = await http.get<ApiResponse<AlarmEvent[]>>('/alarm/list', { params })
return response.data.data
}
export async function verifyAccessPassword(password: string): Promise<boolean> {
export async function verifyAccessPassword(password: string): Promise<ApiResponse<boolean>> {
const response = await http.post<ApiResponse<boolean>>('/auth/verify-password', { password })
return response.data.data
return response.data
}
export async function saveDeviceConfig(payload: DeviceConfigPayload): Promise<ApiResponse<{ save_path: string; send_status: string }>> {
@ -61,6 +67,14 @@ export async function saveDeviceConfig(payload: DeviceConfigPayload): Promise<Ap
return response.data
}
export async function saveDeviceNetConfig(payload: { nic: string; ip: string; mask: string; gateway: string; protocol: string }): Promise<ApiResponse<{ send_status: string }>> {
const response = await http.post<ApiResponse<{ send_status: string }>>('/config/device/net', payload)
return response.data
}
export async function saveDevicePortConfig(payload: { port: string; ip: string; mask: string; gateway: string; protocol: string }): Promise<ApiResponse<{ send_status: string }>> {
const response = await http.post<ApiResponse<{ send_status: string }>>('/config/device/uart', payload)
return response.data
}
export async function saveChannelConfig(
payload: ChannelConfigPayload,
): Promise<ApiResponse<{ save_path: string; send_status: string }>> {

View File

@ -72,7 +72,7 @@ function scheduleRealtimeReconnect() {
}
function startRealtimeSocket() {
if (realtimeSocket && [WebSocket.CONNECTING, WebSocket.OPEN].includes(realtimeSocket.readyState)) {
if (realtimeSocket && [WebSocket.CONNECTING, WebSocket.OPEN].includes(realtimeSocket.readyState as 0 | 1)) {
return
}

View File

@ -5,8 +5,26 @@ export interface ValueGroup {
Ia: number
Ib: number
Ic: number
Pa: number
Pb: number
Pc: number
Pt: number
frq: number
Qa: number
Qb: number
Qc: number
Qt: number
Sa: number
Sb: number
Sc: number
St: number
PFa: number
PFb: number
PFc: number
Uab: number
Ubc: number
Uca: number
PFt: number
}
export interface LineData {

View File

@ -29,7 +29,7 @@ const handleSave = () => {
})
.then(({ value }) => {
verifyAccessPassword(value).then((res: any) => {
if (res.code === 200) {
if (res.data) {
if (isswitch.value) {
return
}
@ -42,7 +42,7 @@ const handleSave = () => {
}
})
}else{
ElMessage.error('密码错误')
ElMessage.error('密码错误,不能修改!')
}
})
})

View File

@ -1,32 +1,75 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const channelList = ref([
{ no: 1, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 2, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 3, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 4, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 5, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 6, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 7, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 8, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 9, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 10, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 11, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 12, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
import { fetchChannelConfig, saveChannelConfig, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
const channelList: any = ref([
{ ch: 1, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 2, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 3, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 4, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 5, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 6, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 7, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 8, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 9, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 10, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 11, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 12, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
])
const lineOptions = ref(['线路一', '线路二'])
const categoryOptions = ref(['UA', 'UB', 'UC'])
const aoChannelList: any = ref([])
const lineOptions = ref([{ label: '线路一', value: 1 }, { label: '线路二', value: 2 }])
const categoryOptions = ref(['UA', 'UB', 'UC'])
const isswitch = ref(false)
const handleSave = () => {
console.log('保存AI通道设置', channelList.value)
ElMessageBox.prompt('请输入密码', '保存', {
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
// inputType: 'password',
})
.then(({ value }) => {
verifyAccessPassword(value).then((res: any) => {
if (res.data) {
if (isswitch.value) {
return
}
isswitch.value = true
const params = {
ai_channel: channelList.value,
ao_channel: aoChannelList.value,
}
saveChannelConfig(params).then(res => {
if (res.data) {
ElMessage.success('保存成功')
isswitch.value = false
}
}).catch(err => {
isswitch.value = false
})
} else {
ElMessage.error('密码错误,不能修改!')
}
})
})
}
function init() {
fetchChannelConfig().then(res => {
aoChannelList.value = res.ao_channel
res.ai_channel.forEach(item => {
channelList.value.forEach((channel: any) => {
if (channel.ch === item.ch) {
channel.singal_type = item.singal_type
channel.line_no = item.line_no
channel.type = item.type
channel.limit_low = item.limit_low
channel.limit_high = item.limit_high
}
})
})
})
}
onMounted(() => {
init()
init()
})
</script>
@ -43,23 +86,24 @@ onMounted(() => {
<div class="cell cell-high">高端值</div>
</div>
<div class="row" v-for="(item, idx) in channelList" :key="idx">
<div class="cell cell-no">{{ item.no }}</div>
<div class="cell cell-type" style="background: #ffffff;">{{ item.type }}</div>
<div class="cell cell-no">{{ item.ch }}</div>
<div class="cell cell-type" style="background: #ffffff;">{{ item.singal_type }}</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-select v-model="item.line">
<el-option v-for="line in lineOptions" :key="line" :value="line" :label="line"></el-option>
<el-select v-model="item.line_no">
<el-option v-for="line in lineOptions" :key="line.value" :value="line.value"
:label="line.label"></el-option>
</el-select>
</div>
<div class="cell cell-category" style="background: #ffffff;">
<el-select v-model="item.category">
<el-select v-model="item.type">
<el-option v-for="cat in categoryOptions" :key="cat" :value="cat" :label="cat"></el-option>
</el-select>
</div>
<div class="cell cell-low" style="background: #ffffff;">
<el-input-number v-model="item.low" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_low" style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-high" style="background: #ffffff;">
<el-input-number v-model="item.high" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_high" style="width: 100%;" :controls="false" />
</div>
</div>
</div>
@ -116,10 +160,12 @@ onMounted(() => {
box-sizing: border-box;
background-color: #f9fafe;
color: #787878;
& + .cell {
&+.cell {
margin-left: 8px;
}
}
.cell-no {
width: 100px;
background: #f9fafe;
@ -173,22 +219,25 @@ onMounted(() => {
cursor: pointer;
}
}
// +
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
background: transparent !important;
text-align: center !important;
}
:deep(.el-select__wrapper.is-hover),
:deep(.el-input__wrapper.is-hover),
:deep(.el-select__wrapper.is-focused),
:deep(.el-input__wrapper.is-focused) {
box-shadow: none !important;
border: none !important;
}
:deep(.el-input__inner){
text-align: center !important;
}
// +
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
background: transparent !important;
text-align: center !important;
}
:deep(.el-select__wrapper.is-hover),
:deep(.el-input__wrapper.is-hover),
:deep(.el-select__wrapper.is-focused),
:deep(.el-input__wrapper.is-focused) {
box-shadow: none !important;
border: none !important;
}
:deep(.el-input__inner) {
text-align: center !important;
}
</style>

View File

@ -1,63 +1,70 @@
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { usePlatformStore } from '../../stores/platform'
import {fetchChannelConfig} from '@/api/platform'
const { state, bootstrap } = usePlatformStore()
const channelConfig = ref<Record<number, { type: string; limit_low: number; limit_high: number; line_no: string }>>({})
const aiData = computed(() => {
if (!state.realtime?.ai_collect) {
return Array.from({ length: 12 }, (_, i) => ({
channel: i + 1,
rawValue: '--',
line: '线路一',
category: '--',
lowValue1: 0,
lowValue2: 0,
}))
}
const aiCollect = state.realtime?.ai_collect || {}
return Array.from({ length: 12 }, (_, i) => {
const channel = i + 1
const key = `ai_${channel}`
const rawValue = state.realtime!.ai_collect[key]
let category = '--'
let rawDisplay = '--'
if (rawValue !== undefined) {
if (channel % 2 === 1) {
const voltage = (rawValue / 1000).toFixed(3)
category = `UA: ${voltage}V`
rawDisplay = `${rawValue}mV`
} else {
const freq = ((rawValue / 1000) * 50).toFixed(4)
category = `f: ${freq}Hz`
rawDisplay = `${rawValue}mA`
}
}
const ch = i + 1
const code = `ai${ch}`
const config = channelConfig.value[ch] || {}
return {
channel,
rawValue: rawDisplay,
line: '线路一',
category,
lowValue1: 1,
lowValue2: 8,
code,
line_no: config.line_no || '',
singal_type: '',
type: config.type || '',
limit_low: config.limit_low || 0,
limit_high: config.limit_high || 0,
rawValue: aiCollect[code] !== undefined ? aiCollect[code] : '',
ch
}
})
})
function formatTime(dateStr: string): string {
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
const tableData = computed(() => {
return state.alarms.slice(0, 10).map((alarm, index) => ({
name: '线路一',
typeName: alarm.type,
content: alarm.content,
time: alarm.time,
ts: '0',
}))
const list = state.alarms[state.alarms.length - 1] || {}
const arr = []
let reslist:any = {}
if(list.alarm_type == 'line_alarm'){
reslist.name = `线路${list?.no || 1}`
}else if(list.alarm_type == 'ai_alarm'){
reslist.name = `通道${list?.no || 1}`
} else if(list.alarm_type == 'operate_alarm'){
reslist.name = ''
}
reslist.typeName = list.type
reslist.content = list.content
reslist.time = list.time ? formatTime(list.time) : ''
reslist.level = list.level || ''
return [reslist]
})
function init(){
fetchChannelConfig().then(res => {
const list = res.ai_channel || []
list.forEach((item: any) => {
channelConfig.value[item.ch] = {
type: item.type,
limit_low: item.limit_low,
limit_high: item.limit_high,
line_no: item.line_no
}
})
})
}
onMounted(() => {
init()
void bootstrap()
})
</script>
@ -74,17 +81,18 @@ onMounted(() => {
<div class="header-cell">所属路线</div>
<div class="header-cell">类别</div>
<div class="header-cell">低值</div>
<div class="header-cell"></div>
<div class="header-cell"></div>
</div>
<!-- 表格内容 -->
<div class="table-body">
<div v-for="(item, index) in aiData" :key="index" class="table-row">
<div class="cell" style="width: 90px;max-width: 90px;min-width: 90px;color: #787878;">{{ item.channel }}</div>
<div class="cell" style="width: 90px;max-width: 90px;min-width: 90px;color: #787878;">{{ item.ch }}
</div>
<div class="cell">{{ item.rawValue }}</div>
<div class="cell">{{ item.line }}</div>
<div class="cell">{{ item.category }}</div>
<div class="cell">{{ item.lowValue1 }}</div>
<div class="cell">{{ item.lowValue2 }}</div>
<div class="cell">线路{{ item.line_no }}</div>
<div class="cell">{{ item.type }}</div>
<div class="cell">{{ item.limit_low }}</div>
<div class="cell">{{ item.limit_high }}</div>
</div>
</div>
</div>
@ -97,9 +105,9 @@ onMounted(() => {
<div style="width: 8%; text-align: center;">{{ index + 1 }}</div>
<div style="width: 23%; text-align: center;">{{ item.name }}</div>
<div style="width: 15%; text-align: center;">{{ item.typeName }}</div>
<div style="width: 10%; text-align: center;">{{ item.level }}</div>
<div style="width: 25%; text-align: center;">{{ item.content }}</div>
<div style="width: 20%; text-align: center;">{{ item.time }}</div>
<div style="width: 10%; text-align: center;">{{ item.ts }}ms</div>
</div>
</div>
</div>
@ -157,6 +165,7 @@ onMounted(() => {
display: flex;
flex-direction: column;
gap: 5px;
.table-row {
display: flex;
width: 100%;

View File

@ -18,7 +18,6 @@ const valList = ref([
const checkedVal = ref('一次值')
const currentLineData = computed(() => {
console.log(state)
if (!state.realtime) return null
const line = lineList.value.find(l => l.name === checkedLine.value)
if (!line) return null
@ -32,12 +31,10 @@ const currentValues = computed<ValueGroup | null>(() => {
})
const frequency = computed(() => {
if (!currentValues.value) return '50.000'
return currentValues.value.frq.toFixed(4)
if (!currentValues.value) return '50'
return currentValues.value.frq
})
const sqrt3 = Math.sqrt(3)
const infoList = computed(() => {
const values = currentValues.value
if (!values) {
@ -53,45 +50,45 @@ const infoList = computed(() => {
return [
{
name: '单项电压V',
a: values.Ua.toFixed(3),
b: values.Ub.toFixed(3),
c: values.Uc.toFixed(3),
total: ((values.Ua + values.Ub + values.Uc) / 3).toFixed(3),
a: values.Ua,
b: values.Ub,
c: values.Uc,
total: '',
},
{
name: '单相电流A',
a: values.Ia.toFixed(3),
b: values.Ib.toFixed(3),
c: values.Ic.toFixed(3),
total: ((values.Ia + values.Ib + values.Ic) / 3).toFixed(3),
a: values.Ia,
b: values.Ib,
c: values.Ic,
total: '',
},
{
name: '有功功率kw',
a: ((values.Ua * values.Ia * 0.9) / 1000).toFixed(3),
b: ((values.Ub * values.Ib * 0.9) / 1000).toFixed(3),
c: ((values.Uc * values.Ic * 0.9) / 1000).toFixed(3),
total: (values.Pt / 1000).toFixed(3),
a: values.Pa,
b: values.Pb,
c: values.Pc,
total: values.Pt
},
{
name: '无功功率kvar',
a: ((values.Ua * values.Ia * Math.sin(Math.acos(0.9))) / 1000).toFixed(3),
b: ((values.Ub * values.Ib * Math.sin(Math.acos(0.9))) / 1000).toFixed(3),
c: ((values.Uc * values.Ic * Math.sin(Math.acos(0.9))) / 1000).toFixed(3),
total: ((sqrt3 * values.Ua * values.Ia * Math.sin(Math.acos(0.9))) / 1000).toFixed(3),
a: values.Qa,
b: values.Qb,
c: values.Qc,
total: values.Qt
},
{
name: '视在功率kVA',
a: ((values.Ua * values.Ia) / 1000).toFixed(3),
b: ((values.Ub * values.Ib) / 1000).toFixed(3),
c: ((values.Uc * values.Ic) / 1000).toFixed(3),
total: ((sqrt3 * values.Ua * values.Ia) / 1000).toFixed(3),
a: values.Sa,
b: values.Sb,
c: values.Sc,
total: values.St
},
{
name: '功率因数cos',
a: '0.900',
b: '0.900',
c: '0.900',
total: '0.900',
a: values.PFa,
b: values.PFb,
c: values.PFc,
total: values.PFt
},
]
})
@ -103,20 +100,46 @@ const infoData = computed(() => {
}
return {
name: '线电压V',
a: (values.Ua * sqrt3).toFixed(3),
b: (values.Ub * sqrt3).toFixed(3),
c: (values.Uc * sqrt3).toFixed(3),
a: values?.Uab,
b: values?.Ubc,
c: values?.Uca,
}
})
function formatTime(dateStr: string): string {
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
const tableData = computed(() => {
return state.alarms.slice(0, 10).map((alarm, index) => ({
name: `线路${currentLineData.value?.line_no || 1}`,
typeName: alarm.type,
content: alarm.content,
time: alarm.time,
ts: '0',
}))
const list = state.alarms[state.alarms.length - 1] || {}
const arr = []
let reslist:any = {}
if(list.alarm_type == 'line_alarm'){
reslist.name = `线路${list?.no || 1}`
}else if(list.alarm_type == 'ai_alarm'){
reslist.name = `通道${list?.no || 1}`
} else if(list.alarm_type == 'operate_alarm'){
reslist.name = ''
}
reslist.typeName = list.type
reslist.content = list.content
reslist.time = list.time ? formatTime(list.time) : ''
reslist.level = list.level || ''
return [reslist]
// return state.alarms.slice(0, 10).map((alarm, index) => ({
// name: `线${currentLineData.value?.line_no || 1}`,
// typeName: alarm.type,
// content: alarm.content,
// time: alarm.time,
// ts: '0',
// }))
})
function handleClick(name: string) {
@ -197,11 +220,11 @@ onMounted(() => {
<div class="container-bottom-box">
<div v-for="(item, index) in tableData" :key="item.name" class="container-bottom-box-line1">
<div style="width: 8%;text-align: center;">{{ index + 1 }}</div>
<div style="width: 23%;text-align: center;">{{ item.name }}</div>
<div style="width: 15%;text-align: center;">{{ item.typeName }}</div>
<div style="width: 25%;text-align: center;">{{ item.content }}</div>
<div style="width: 22%;text-align: center;">{{ item.name }}</div>
<div style="width: 20%;text-align: center;">{{ item.typeName }}</div>
<div style="width: 10%;text-align: center;">{{ item.level }}</div>
<div style="width: 20%;text-align: center;">{{ item.content }}</div>
<div style="width: 20%;text-align: center;">{{ item.time }}</div>
<div style="width: 10%;text-align: center;">{{ item.ts }}ms</div>
</div>
</div>
</div>

View File

@ -1,32 +1,76 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const channelList = ref([
{ no: 1, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 2, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 3, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 4, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 5, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 6, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 7, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 8, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 9, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 10, type: '1~5V', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 11, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
{ no: 12, type: '4~20mA', line: '线路一', category: 'UA', low: 1, high: 8 },
import { fetchChannelConfig, saveChannelConfig, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
const channelList: any = ref([
{ ch: 1, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 2, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 3, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 4, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 5, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 6, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 7, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 8, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 9, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 10, singal_type: '1~5V', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 11, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
{ ch: 12, singal_type: '4~20mA', line_no: 1, type: 'UA', limit_low: 1, limit_high: 8 },
])
const lineOptions = ref([{ label: '线路一', value: 1 }, { label: '线路二', value: 2 }])
const categoryOptions = ref(['UA', 'UB', 'UC'])
const lineOptions = ref(['线路一', '线路二'])
const categoryOptions = ref(['UA', 'UB', 'UC'])
const handleSave = () => {
console.log('保存ao通道设置', channelList.value)
}
const aiChannelList = ref([])
function init() {
fetchChannelConfig().then((res: any) => {
aiChannelList.value = res.ao_channel
res.ao_channel.forEach((item: any) => {
channelList.value.forEach((channel: any) => {
if (channel.ch === item.ch) {
channel.singal_type = item.singal_type
channel.line_no = item.line_no
channel.type = item.type
channel.limit_low = item.limit_low
channel.limit_high = item.limit_high
}
})
})
})
}
const isswitch = ref(false)
const handleSave = () => {
ElMessageBox.prompt('请输入密码', '保存', {
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
// inputType: 'password',
})
.then(({ value }) => {
verifyAccessPassword(value).then((res: any) => {
if (res.data) {
if (isswitch.value) {
return
}
isswitch.value = true
const params = {
ai_channel: aiChannelList.value,
ao_channel: channelList.value,
}
saveChannelConfig(params).then(res => {
if (res.code === 200) {
ElMessage.success('保存成功')
isswitch.value = false
}
}).catch(err => {
isswitch.value = false
})
} else {
ElMessage.error('密码错误,不能修改!')
}
})
})
}
onMounted(() => {
init()
init()
})
</script>
@ -43,23 +87,24 @@ onMounted(() => {
<div class="cell cell-high">高端值</div>
</div>
<div class="row" v-for="(item, idx) in channelList" :key="idx">
<div class="cell cell-no">{{ item.no }}</div>
<div class="cell cell-type" style="background: #ffffff;">{{ item.type }}</div>
<div class="cell cell-no">{{ item.ch }}</div>
<div class="cell cell-type" style="background: #ffffff;">{{ item.singal_type }}</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-select v-model="item.line">
<el-option v-for="line in lineOptions" :key="line" :value="line" :label="line"></el-option>
<el-select v-model="item.line_no">
<el-option v-for="line in lineOptions" :key="line.value" :value="line.value"
:label="line.label"></el-option>
</el-select>
</div>
<div class="cell cell-category" style="background: #ffffff;">
<el-select v-model="item.category">
<el-select v-model="item.type">
<el-option v-for="cat in categoryOptions" :key="cat" :value="cat" :label="cat"></el-option>
</el-select>
</div>
<div class="cell cell-low" style="background: #ffffff;">
<el-input-number v-model="item.low" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_low" style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-high" style="background: #ffffff;">
<el-input-number v-model="item.high" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_high" style="width: 100%;" :controls="false" />
</div>
</div>
</div>
@ -116,10 +161,12 @@ onMounted(() => {
box-sizing: border-box;
background-color: #f9fafe;
color: #787878;
& + .cell {
&+.cell {
margin-left: 8px;
}
}
.cell-no {
width: 100px;
background: #f9fafe;
@ -173,22 +220,25 @@ onMounted(() => {
cursor: pointer;
}
}
// +
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
background: transparent !important;
text-align: center !important;
}
:deep(.el-select__wrapper.is-hover),
:deep(.el-input__wrapper.is-hover),
:deep(.el-select__wrapper.is-focused),
:deep(.el-input__wrapper.is-focused) {
box-shadow: none !important;
border: none !important;
}
:deep(.el-input__inner){
text-align: center !important;
}
// +
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
background: transparent !important;
text-align: center !important;
}
:deep(.el-select__wrapper.is-hover),
:deep(.el-input__wrapper.is-hover),
:deep(.el-select__wrapper.is-focused),
:deep(.el-input__wrapper.is-focused) {
box-shadow: none !important;
border: none !important;
}
:deep(.el-input__inner) {
text-align: center !important;
}
</style>

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { fetchDeviceNet, fetchDevicePort, saveDeviceConfig, verifyAccessPassword, fetchChannelConfig } from '@/api/platform'
import { fetchDeviceNet, fetchDevicePort, saveDeviceNetConfig, saveDevicePortConfig, verifyAccessPassword, fetchChannelConfig } from '@/api/platform'
//
const formData: any = ref({
nic: '',
@ -73,15 +73,9 @@ const handleSave = () => {
})
.then(({ value }) => {
verifyAccessPassword(value).then((res: any) => {
if (res.code == 200) {
const params = {
net: [formData.value],
uart: [formData2.value],
password: config.value.password,
hardware_version: config.value.hardware_version,
software_version: config.value.software_version,
}
saveDeviceConfig(params).then((res: any) => {
if (res.data) {
saveDeviceNetConfig(formData.value).then((res: any) => {
if (res.code == 200) {
ElMessage({
type: 'success',
@ -94,10 +88,24 @@ const handleSave = () => {
})
}
})
saveDevicePortConfig(formData2.value).then((res: any) => {
if (res.code == 200) {
ElMessage({
type: 'success',
message: `保存成功`,
})
} else {
ElMessage({
type: 'info',
message: '保存失败',
})
}
})
} else {
ElMessage({
type: 'info',
message: '密码错误',
message: '密码错误,不能修改!',
})
}
})

View File

@ -1,5 +1,26 @@
<script setup lang="ts">
import { ref } from 'vue'
import { ref,onMounted } from 'vue'
import {fetchDeviceConfig} from '@/api/platform'
const channelConfig = ref({
hardware_version:{
board_version:'B001.001.001',
display_version:'B001.001.001',
other_version:'B001.001.001',
},
software_version:{
communication_program:'001.001.001',
measurement_program:'001.001.001',
display_program:'001.001.001',
}
})
function init(){
fetchDeviceConfig().then(res => {
channelConfig.value = res
})
}
onMounted(() => {
init()
})
</script>
<template>
@ -13,15 +34,15 @@ import { ref } from 'vue'
<div class="box-item-text1">设备硬件信息</div>
<div class="box-item-line">
<div>板卡版本</div>
<div>B001.001.001</div>
<div>{{channelConfig.hardware_version.board_version}}</div>
</div>
<div class="box-item-line">
<div>显示版本</div>
<div>B001.001.001</div>
<div>{{channelConfig.hardware_version.display_version}}</div>
</div>
<div class="box-item-line">
<div>其他版本</div>
<div>B001.001.001</div>
<div>{{channelConfig.hardware_version.other_version}}</div>
</div>
</div>
</div>
@ -33,15 +54,15 @@ import { ref } from 'vue'
<div class="box-item-text1">程序版本信息</div>
<div class="box-item-line">
<div>显示程序版本</div>
<div>001.001.001</div>
<div>{{channelConfig.software_version.display_program}}</div>
</div>
<div class="box-item-line">
<div>通讯程序版本</div>
<div>001.001.001</div>
<div>{{channelConfig.software_version.communication_program}}</div>
</div>
<div class="box-item-line">
<div>测量程序版本</div>
<div>001.001.001</div>
<div>{{channelConfig.software_version.measurement_program}}</div>
</div>
</div>
</div>

View File

@ -1,75 +1,57 @@
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
const formData = reactive({
line: '线路一',
type: '操作事件',
import { fetchAlarmHistory } from '@/api/platform'
const formData = ref({
no: null,
type: '',
timeRange: [],
})
const tableData = ref([
{
id: 1,
belong: '线路一',
type: '操作事件',
detail: '手动修改时间操作',
time: '2026-01-12 12:12:12 886ms',
},
{
id: 2,
belong: '线路一',
type: '操作事件',
detail: '手动修改时间操作',
time: '2026-01-12 12:12:12 886ms',
},
{
id: 3,
belong: '线路一',
type: '操作事件',
detail: '手动修改时间操作',
time: '2026-01-12 12:12:12 886ms',
},
{
id: 4,
belong: '线路一',
type: '操作事件',
detail: '手动修改时间操作',
time: '2026-01-12 12:12:12 886ms',
},
{
id: 5,
belong: '线路一',
type: '操作事件',
detail: '手动修改时间操作',
time: '2026-01-12 12:12:12 886ms',
},
])
const tableData: any = ref([])
const pagination = reactive({
const pagination = ref({
currentPage: 1,
pageSize: 10,
total: 36,
total: 0,
})
const handleQuery = () => {
console.log('查询', formData)
const params: any = {
page: pagination.value.currentPage,
size: pagination.value.pageSize,
// no: formData.value.no,
// type: formData.value.type,
// start_time: formData.value.timeRange[0],
// end_time: formData.value.timeRange[1],
}
fetchAlarmHistory(params).then((res: any) => {
tableData.value = res
})
}
const handleSizeChange = (val: number) => {
pagination.pageSize = val
pagination.currentPage = 1
pagination.value.pageSize = val
pagination.value.currentPage = 1
init()
}
const handleCurrentChange = (val: number) => {
pagination.currentPage = val
pagination.value.currentPage = val
init()
}
function init() {
const params: any = {
page: pagination.value.currentPage,
size: pagination.value.pageSize,
}
fetchAlarmHistory(params).then((res: any) => {
tableData.value = res
})
}
onMounted(() => {
formData.line = ''
formData.type = ''
formData.timeRange = []
formData.value.no = null
formData.value.type = ''
formData.value.timeRange = []
init()
})
</script>
@ -77,7 +59,7 @@ onMounted(() => {
<template>
<div class="event-report-container">
<div class="search-box">
<el-select v-model="formData.line" placeholder="所属线路" style="width: 180px">
<el-select v-model="formData.no" placeholder="所属线路" style="width: 180px">
<el-option label="线路一" value="线路一" />
<el-option label="线路二" value="线路二" />
</el-select>
@ -97,11 +79,18 @@ onMounted(() => {
<div class="table-box">
<el-table :data="tableData" style="width: 100%; height: calc(100vh - 280px)" header-align="center"
align="center">
<el-table-column label="序号" prop="id" width="80" />
<el-table-column label="事件所属" prop="belong" />
<el-table-column label="事件类型" prop="type" />
<el-table-column label="事件详情" prop="detail" />
<el-table-column label="发生时间" prop="time" />
<el-table-column label="序号" type="index" width="80" align="center" />
<el-table-column label="事件所属" prop="belong">
<template #default="scope">
<span v-if="scope.row.alarm_type === 'line_alarm'">线路{{ scope.row.no }}</span>
<span v-else-if="scope.row.alarm_type === 'ai_alarm'">通道{{ scope.row.no }}</span>
<span v-else-if="scope.row.alarm_type === 'operate_alarm'">{{ scope.row.no }}</span>
</template>
</el-table-column>
<el-table-column label="事件类型" prop="type" align="center" />
<el-table-column label="事件等级" prop="level" align="center" />
<el-table-column label="事件详情" prop="content" align="center" />
<el-table-column label="发生时间" prop="time" align="center" />
</el-table>
<div class="pagination">
<el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"

View File

@ -1,24 +1,39 @@
<script setup lang="ts">
import { ref, reactive, watch } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import type { FormInstance } from 'element-plus'
import { fetchSystemConfig, saveSystemConfig } from '@/api/platform'
import { ElMessage } from 'element-plus'
const formRef = ref<FormInstance>()
//
const form = reactive({
sleepTime: 180, //
brightness: 80 //
const form = ref({
screen_saver: 180,
brightness: 80,
time_sync: ''
})
const isswitch = ref(false)
//
const handleSave = async () => {
if (!formRef.value) return
await formRef.value.validate((valid) => {
if (valid) {
console.log('灯光设置数据:', form)
//
alert('灯光设置保存成功!')
if(isswitch.value){
return
}
isswitch.value = true
saveSystemConfig(form.value).then(res => {
if(res.code === 200){
ElMessage.success('保存成功')
}
isswitch.value = false
})
}
onMounted(() => {
init()
})
const init = () => {
fetchSystemConfig().then(res => {
form.value.screen_saver = res.screen_saver
form.value.brightness = res.brightness
form.value.time_sync = res.time_sync
})
}
</script>
@ -31,8 +46,8 @@ const handleSave = async () => {
灯光设置
</div>
<el-form ref="formRef" :model="form" label-width="100px" class="light-form">
<el-form-item label="息屏时间设置" prop="sleepTime">
<el-input v-model.number="form.sleepTime" type="number" min="0">
<el-form-item label="息屏时间设置" prop="screen_saver">
<el-input v-model.number="form.screen_saver" type="number" min="0">
<template #suffix>
<span class="unit"></span>
</template>

View File

@ -1,5 +1,7 @@
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ref, onMounted } from 'vue'
import { fetchLineAlarmSetting, saveLineAlarmSetting, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
const lineTabs = ref([
{
label: '线路一定值',
@ -24,35 +26,115 @@ const lineTabs = ref([
])
const activeTab = ref('1')
const infoList = ref({
category: {a: '180', b: '180', c: '开出1', d: '0'},
voltage: {a: '180', b: '180', c: '开出1', d: '0'},
current: {a: '180', b: '180', c: '开出1', d: '0'},
diffCurrent: {a: '180', b: '180', c: '开出1', d: '0'},
power: {a: '180', b: '180', c: '开出1', d: '0'},
frequency: {a: '180', b: '180', c: '开出1', d: '0'},
ptBreak: {a: '180', b: '180', c: '开出1', d: '1'},
ctBreak: {a: '180', b: '180', c: '开出1', d: '1'},
line_no:1,
fault_alarm:[
{category:'PT断线',delay:0,enabled:false,output_node:'',limit:0},
{category:'CT断线',delay:0,enabled:false,output_node:'',limit:0},
],
over_limit_alarm:[
{category:'电压',delay:0,enabled:false,output_node:'',limit:0},
{category:'电流',delay:0,enabled:false,output_node:'',limit:0},
{category:'差流',delay:0,enabled:false,output_node:'',limit:0},
{category:'功率',delay:0,enabled:false,output_node:'',limit:0},
{category:'频率',delay:0,enabled:false,output_node:'',limit:0},
],
})
const handleSave = () => {
}
const options = ref([
{
label: '开出1',
value: '1'
value: '开出1'
},
{
label: '开出2',
value: '2'
value: '开出2'
},
])
const cleardata = () => {
infoList.value.fault_alarm.forEach(item => {
item.delay = 0
item.enabled = false
item.output_node = ''
item.limit = 0
})
infoList.value.over_limit_alarm.forEach(item => {
item.delay = 0
item.enabled = false
item.output_node = ''
item.limit = 0
})
}
const currentLine = ref(1)
const handleTabClick = (tab:string) => {
activeTab.value = tab
infoList.value.line_no = Number(tab)
currentLine.value = Number(tab)
init()
}
onMounted(() => {
init()
})
const init = () => {
fetchLineAlarmSetting(currentLine.value).then(res => {
infoList.value.line_no = res.line_no
cleardata()
res.fault_alarm.forEach(item => {
infoList.value.fault_alarm.forEach((faultItem, idx) => {
if (faultItem.category === item.category) {
faultItem.delay = item.delay
faultItem.enabled = item.enabled
faultItem.output_node = item.output_node
faultItem.limit = item.limit || 0
}
})
})
res.over_limit_alarm.forEach(item => {
infoList.value.over_limit_alarm.forEach((overLimitItem, idx) => {
if (overLimitItem.category === item.category) {
overLimitItem.delay = item.delay
overLimitItem.enabled = item.enabled
overLimitItem.output_node = item.output_node
overLimitItem.limit = item.limit || 0
}
})
})
})
}
const isswitch = ref(false)
const handleSave = () => {
ElMessageBox.prompt('请输入密码', '保存', {
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
// inputType: 'password',
})
.then(({ value }) => {
verifyAccessPassword(value).then((res: any) => {
if (res.data) {
if (isswitch.value) {
return
}
isswitch.value = true
saveLineAlarmSetting(infoList.value).then(res => {
if (res.code === 200) {
ElMessage.success('保存成功')
init()
isswitch.value = false
}
})
}else{
ElMessage.error('密码错误,不能修改!')
}
})
})
}
</script>
<template>
<div class="line-page">
<div class="line-tabs">
<div class="tab-item" v-for="item in lineTabs" :key="item.value"
:class="{ 'is-active': activeTab === item.value }" @click="activeTab = item.value">
:class="{ 'is-active': activeTab === item.value }" @click="handleTabClick(item.value)">
{{ item.label }}
</div>
</div>
@ -75,19 +157,19 @@ const options = ref([
<div class="tab-content-item">
<div class="tab-content-item-box box-height">限制</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.voltage.a" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[0].limit" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.current.a" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[1].limit" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.diffCurrent.a" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[2].limit" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.power.a" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.fault_alarm[0].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.frequency.a" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.fault_alarm[1].limit" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height" style="border: none;">
<img src="@/assets/images/menuicon/noitem.png" style="width: 100%; height: 100%;" alt="">
@ -99,61 +181,61 @@ const options = ref([
<div class="tab-content-item">
<div class="tab-content-item-box box-height">延时s</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.voltage.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[0].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.current.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[1].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.diffCurrent.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[2].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.power.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[3].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.frequency.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.over_limit_alarm[4].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.ptBreak.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.fault_alarm[0].delay" style="width: 100%;" :controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.ctBreak.b" style="width: 100%;" :controls="false" />
<el-input-number v-model="infoList.fault_alarm[1].delay" style="width: 100%;" :controls="false" />
</div>
</div>
<div class="tab-content-item">
<div class="tab-content-item-box box-height">输出节点</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.voltage.c">
<el-select v-model="infoList.over_limit_alarm[0].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.current.c">
<el-select v-model="infoList.over_limit_alarm[1].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.diffCurrent.c">
<el-select v-model="infoList.over_limit_alarm[2].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.power.c">
<el-select v-model="infoList.over_limit_alarm[3].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.frequency.c">
<el-select v-model="infoList.over_limit_alarm[4].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.ptBreak.c" >
<el-select v-model="infoList.fault_alarm[0].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-select v-model="infoList.ctBreak.c" >
<el-select v-model="infoList.fault_alarm[1].output_node">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</div>
@ -161,25 +243,25 @@ const options = ref([
<div class="tab-content-item">
<div class="tab-content-item-box box-height">是否投入</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.voltage.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.over_limit_alarm[0].enabled"></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.current.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.over_limit_alarm[1].enabled"></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.diffCurrent.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.over_limit_alarm[2].enabled"></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.power.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.over_limit_alarm[3].enabled" ></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.frequency.d" active-value="1" inactive-value="10"></el-switch>
<el-switch v-model="infoList.over_limit_alarm[4].enabled"></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.ptBreak.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.fault_alarm[0].enabled"></el-switch>
</div>
<div class="tab-content-item-box box-color box-height">
<el-switch v-model="infoList.ctBreak.d" active-value="1" inactive-value="0"></el-switch>
<el-switch v-model="infoList.fault_alarm[1].enabled"></el-switch>
</div>
</div>
</div>

View File

@ -6,32 +6,49 @@ const { state, bootstrap } = usePlatformStore()
const inputStates = computed(() => {
if (!state.realtime?.switch) {
return Array(12).fill(false)
return [true, false, true, false, true, false, true, false, true, false, true, false]
}
return Array.from({ length: 12 }, (_, i) => {
const key = `input_${i + 1}`
const key = `di${i + 1}`
return state.realtime!.switch[key] === 1
})
})
const outputStates = computed(() => {
if (!state.realtime?.switch) {
return Array(12).fill(false)
return [false, true, false, true, false, true, false, true, false, true, false, true]
}
return Array.from({ length: 12 }, (_, i) => {
const key = `output_${i + 1}`
const key = `do${i + 1}`
return state.realtime!.switch[key] === 1
})
})
function formatTime(dateStr: string): string {
const date = new Date(dateStr)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
const tableData = computed(() => {
return state.alarms.slice(0, 10).map((alarm, index) => ({
name: '线路一',
typeName: alarm.type,
content: alarm.content,
time: alarm.time,
ts: '0',
}))
const list = state.alarms[state.alarms.length - 1] || {}
const arr = []
let reslist:any = {}
if(list.alarm_type == 'line_alarm'){
reslist.name = `线路${list?.no || 1}`
}else if(list.alarm_type == 'ai_alarm'){
reslist.name = `通道${list?.no || 1}`
} else if(list.alarm_type == 'operate_alarm'){
reslist.name = ''
}
reslist.typeName = list.type
reslist.content = list.content
reslist.time = list.time ? formatTime(list.time) : ''
reslist.level = list.level || ''
return [reslist]
})
onMounted(() => {
@ -51,9 +68,9 @@ onMounted(() => {
</div>
<div class="state-grid">
<div v-for="(state, index) in inputStates" :key="`input-${index}`" class="state-item">
<img v-if="state" src="@/assets/images/menuicon/off.png" style="width: 34px; height: 36px;"
<img v-if="state" src="@/assets/images/menuicon/on.png" style="width: 34px; height: 36px;"
alt="">
<img v-else src="@/assets/images/menuicon/on.png" alt="" style="width: 34px; height: 36px;">
<img v-else src="@/assets/images/menuicon/off.png" alt="" style="width: 34px; height: 36px;">
<div class="label">开入{{ index + 1 }}</div>
</div>
</div>
@ -65,9 +82,9 @@ onMounted(() => {
</div>
<div class="state-grid">
<div v-for="(state, index) in outputStates" :key="`output-${index}`" class="state-item">
<img v-if="state" src="@/assets/images/menuicon/off2.png" style="width: 46px; height: 24px;"
<img v-if="state" src="@/assets/images/menuicon/on2.png" style="width: 46px; height: 24px;"
alt="">
<img v-else src="@/assets/images/menuicon/on2.png" style="width: 46px; height: 24px;"
<img v-else src="@/assets/images/menuicon/off2.png" style="width: 46px; height: 24px;"
alt="">
<div class="label">开出{{ index + 1 }}</div>
</div>
@ -83,9 +100,9 @@ onMounted(() => {
<div style="width: 8%; text-align: center;">{{ index + 1 }}</div>
<div style="width: 23%; text-align: center;">{{ item.name }}</div>
<div style="width: 15%; text-align: center;">{{ item.typeName }}</div>
<div style="width: 10%; text-align: center;">{{ item.level }}</div>
<div style="width: 25%; text-align: center;">{{ item.content }}</div>
<div style="width: 20%; text-align: center;">{{ item.time }}</div>
<div style="width: 10%; text-align: center;">{{ item.ts }}ms</div>
</div>
</div>
</div>
@ -190,7 +207,7 @@ onMounted(() => {
background: #ffffff;
box-shadow: 0px 0px 10px rgba(219, 225, 236, 1);
border-radius: 4px;
overflow: auto;
.container-bottom-box-line1 {
display: flex;
align-items: center;

View File

@ -1,25 +1,49 @@
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ref, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { fetchSystemConfig, saveSystemConfig } from '@/api/platform'
import { ElMessage } from 'element-plus'
const formRef = ref<FormInstance>()
const form = reactive({
targetTime: ''
const form = ref({
time_sync: '',
brightness: 0,
screen_saver: 0,
})
const rules: FormRules = {
}
const isswitch = ref(false)
const handleSubmit = async () => {
if (!formRef.value) return
await formRef.value.validate((valid) => {
if (valid) {
console.log('表单数据:', form)
if (isswitch.value) {
return
}
isswitch.value = true
saveSystemConfig(form.value).then((res: any) => {
if (res.code == 200) {
ElMessage({
type: 'success',
message: `保存成功`,
})
} else {
ElMessage({
type: 'info',
message: '保存失败',
})
}
})
}
function init() {
fetchSystemConfig().then((res: any) => {
form.value = res
})
}
onMounted(() => {
init()
})
</script>
<template>
@ -32,8 +56,8 @@ const handleSubmit = async () => {
</div>
<!-- 表单 -->
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px" class="time-form">
<el-form-item label="选择时间" prop="targetTime">
<el-date-picker v-model="form.targetTime" type="datetime" placeholder="请选择时间"
<el-form-item label="选择时间" prop="time_sync">
<el-date-picker v-model="form.time_sync" type="datetime" placeholder="请选择时间"
format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" style="width: 100%;" />
</el-form-item>
</el-form>
@ -101,6 +125,7 @@ const handleSubmit = async () => {
:deep(.el-form-item__label) {
line-height: 40px !important;
}
:deep(.el-input__wrapper) {
min-height: 40px !important;
}

View File

@ -5,15 +5,15 @@ import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
server: {
host: 0.0.0.0,
host: '0.0.0.0',
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8000',
target: 'http://192.168.1.59:8000',
changeOrigin: true,
},
'/ws': {
target: 'ws://localhost:8000',
target: 'ws://192.168.1.59:8000',
changeOrigin: true,
ws: true,
},