通讯设置
This commit is contained in:
parent
978d5c5378
commit
6937c5bfdd
@ -9,6 +9,7 @@ import type {
|
|||||||
LineAlarmSettingPayload,
|
LineAlarmSettingPayload,
|
||||||
RealtimeData,
|
RealtimeData,
|
||||||
SystemConfigPayload,
|
SystemConfigPayload,
|
||||||
|
FullDeviceConfig,
|
||||||
} from '../types/platform'
|
} from '../types/platform'
|
||||||
|
|
||||||
export async function fetchRealtimeData(): Promise<RealtimeData> {
|
export async function fetchRealtimeData(): Promise<RealtimeData> {
|
||||||
@ -77,10 +78,20 @@ export async function saveDeviceNetConfig(payload: { nic: string; ip: string; ma
|
|||||||
const response = await http.post<ApiResponse<{ send_status: string }>>('/config/device/net', payload)
|
const response = await http.post<ApiResponse<{ send_status: string }>>('/config/device/net', payload)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
export async function saveDevicePortConfig(payload: { port: string; ip: string; mask: string; gateway: string; protocol: string }): Promise<ApiResponse<{ send_status: string }>> {
|
export async function saveDevicePortConfig(
|
||||||
const response = await http.post<ApiResponse<{ send_status: string }>>('/config/device/uart', payload)
|
payload: FullDeviceConfig
|
||||||
|
): Promise<ApiResponse<{ send_status: string }>> {
|
||||||
|
const response = await http.post<ApiResponse<{ send_status: string }>>(
|
||||||
|
'/config/device',
|
||||||
|
payload
|
||||||
|
)
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
export async function getDeviceNetConfig(): Promise<DeviceConfigPayload[]> {
|
||||||
|
const response = await http.get<ApiResponse<DeviceConfigPayload[]>>(`/config/device`)
|
||||||
|
return response.data.data
|
||||||
|
}
|
||||||
|
|
||||||
export async function saveChannelConfig(
|
export async function saveChannelConfig(
|
||||||
payload: ChannelConfigPayload,
|
payload: ChannelConfigPayload,
|
||||||
): Promise<ApiResponse<{ save_path: string; send_status: string }>> {
|
): Promise<ApiResponse<{ save_path: string; send_status: string }>> {
|
||||||
|
|||||||
@ -1,25 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted } from 'vue'
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
import { fetchDeviceStatus } from '@/api/platform'
|
import { fetchDeviceStatus } from '@/api/platform'
|
||||||
|
import { connectTimeSync } from '@/websocket/client'
|
||||||
const time = ref('')
|
const time = ref('')
|
||||||
const date = ref('')
|
const date = ref('')
|
||||||
const day = ref('')
|
const day = ref('')
|
||||||
const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
const weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||||
const updateTime = () => {
|
|
||||||
const now = new Date()
|
|
||||||
const hours = now.getHours().toString().padStart(2, '0')
|
|
||||||
const minutes = now.getMinutes().toString().padStart(2, '0')
|
|
||||||
const seconds = now.getSeconds().toString().padStart(2, '0')
|
|
||||||
const year = now.getFullYear()
|
|
||||||
const month = (now.getMonth() + 1).toString().padStart(2, '0')
|
|
||||||
const dayOfMonth = now.getDate().toString().padStart(2, '0')
|
|
||||||
|
|
||||||
time.value = `${hours}:${minutes}:${seconds}`
|
|
||||||
date.value = `${year}-${month}-${dayOfMonth}`
|
|
||||||
day.value = weekDays[now.getDay()]
|
|
||||||
}
|
|
||||||
|
|
||||||
let timer: ReturnType<typeof setInterval>
|
|
||||||
const centerItems = ref([
|
const centerItems = ref([
|
||||||
{
|
{
|
||||||
label: '装置自检状态',
|
label: '装置自检状态',
|
||||||
@ -47,6 +33,8 @@ const centerItems = ref([
|
|||||||
code: 'serial2'
|
code: 'serial2'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
// WebSocket 连接
|
||||||
|
let ws: WebSocket | null = null
|
||||||
async function refreshStatus() {
|
async function refreshStatus() {
|
||||||
try {
|
try {
|
||||||
const status:any = await fetchDeviceStatus()
|
const status:any = await fetchDeviceStatus()
|
||||||
@ -56,15 +44,69 @@ async function refreshStatus() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 从服务器时间同步更新显示
|
||||||
|
const updateTimeFromServer = (serverTime: string) => {
|
||||||
|
const [dateStr, timeStr] = serverTime.split(' ')
|
||||||
|
const [year, month, dayOfMonth] = dateStr.split('-').map(Number)
|
||||||
|
const [hours, minutes, seconds] = timeStr.split(':').map(Number)
|
||||||
|
time.value = timeStr
|
||||||
|
date.value = dateStr
|
||||||
|
day.value = weekDays[new Date(year, month - 1, dayOfMonth).getDay()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本地计时器(作为备用/平滑过渡)
|
||||||
|
let localTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
let lastServerTime: Date | null = null
|
||||||
|
|
||||||
|
const startLocalTimer = () => {
|
||||||
|
if (localTimer) clearInterval(localTimer)
|
||||||
|
localTimer = setInterval(() => {
|
||||||
|
if (lastServerTime) {
|
||||||
|
lastServerTime.setSeconds(lastServerTime.getSeconds() + 1)
|
||||||
|
const now = lastServerTime
|
||||||
|
const hours = now.getHours().toString().padStart(2, '0')
|
||||||
|
const minutes = now.getMinutes().toString().padStart(2, '0')
|
||||||
|
const seconds = now.getSeconds().toString().padStart(2, '0')
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = (now.getMonth() + 1).toString().padStart(2, '0')
|
||||||
|
const dayOfMonth = now.getDate().toString().padStart(2, '0')
|
||||||
|
|
||||||
|
time.value = `${hours}:${minutes}:${seconds}`
|
||||||
|
date.value = `${year}-${month}-${dayOfMonth}`
|
||||||
|
day.value = weekDays[now.getDay()]
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
updateTime()
|
const now = new Date()
|
||||||
timer = setInterval(updateTime, 1000)
|
const hours = now.getHours().toString().padStart(2, '0')
|
||||||
|
const minutes = now.getMinutes().toString().padStart(2, '0')
|
||||||
|
const seconds = now.getSeconds().toString().padStart(2, '0')
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = (now.getMonth() + 1).toString().padStart(2, '0')
|
||||||
|
const dayOfMonth = now.getDate().toString().padStart(2, '0')
|
||||||
|
|
||||||
|
time.value = `${hours}:${minutes}:${seconds}`
|
||||||
|
date.value = `${year}-${month}-${dayOfMonth}`
|
||||||
|
day.value = weekDays[now.getDay()]
|
||||||
|
|
||||||
|
// 连接时间同步 WebSocket
|
||||||
|
ws = connectTimeSync((event) => {
|
||||||
|
const serverTimeStr = event.data.time_sync
|
||||||
|
lastServerTime = new Date(serverTimeStr.replace(' ', 'T'))
|
||||||
|
updateTimeFromServer(serverTimeStr)
|
||||||
|
// 收到服务器时间后,启动本地平滑计时
|
||||||
|
startLocalTimer()
|
||||||
|
})
|
||||||
refreshStatus()
|
refreshStatus()
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
clearInterval(timer)
|
if (localTimer) clearInterval(localTimer)
|
||||||
|
if (ws) {
|
||||||
|
ws.close()
|
||||||
|
ws = null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -113,7 +113,13 @@ export interface ChannelConfigPayload {
|
|||||||
ai_channel: ChannelItem[]
|
ai_channel: ChannelItem[]
|
||||||
ao_channel: ChannelItem[]
|
ao_channel: ChannelItem[]
|
||||||
}
|
}
|
||||||
|
export type FullDeviceConfig = {
|
||||||
|
password: string
|
||||||
|
hardware_version: HardwareVersion
|
||||||
|
software_version: SoftwareVersion
|
||||||
|
net: [NetConfigItem, NetConfigItem]
|
||||||
|
uart: [UartConfigItem, UartConfigItem]
|
||||||
|
}
|
||||||
export interface AlarmRule {
|
export interface AlarmRule {
|
||||||
category: string
|
category: string
|
||||||
limit: number
|
limit: number
|
||||||
|
|||||||
@ -1,26 +1,46 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { fetchDeviceNet, fetchDevicePort, saveDeviceNetConfig, saveDevicePortConfig, verifyAccessPassword, fetchChannelConfig } from '@/api/platform'
|
import { fetchDeviceNet, fetchDevicePort, getDeviceNetConfig, saveDevicePortConfig, fetchChannelConfig } from '@/api/platform'
|
||||||
import NumericKeyboard from '@/components/NumericKeyboard.vue'
|
import NumericKeyboard from '@/components/NumericKeyboard.vue'
|
||||||
import PasswordDialog from '@/components/passwordValie.vue'
|
import PasswordDialog from '@/components/passwordValie.vue'
|
||||||
|
|
||||||
// 表单数据
|
// 左侧网卡一 表单
|
||||||
const formData: any = ref({
|
const formData: any = ref({
|
||||||
nic: '',
|
nic: '网卡一',
|
||||||
ip: '',
|
ip: '',
|
||||||
mask: '',
|
mask: '',
|
||||||
gateway: '',
|
gateway: '',
|
||||||
protocol: '',
|
protocol: '',
|
||||||
})
|
})
|
||||||
|
// 右侧网卡二 表单
|
||||||
|
const formDataRight: any = ref({
|
||||||
|
nic: '网卡二',
|
||||||
|
ip: '',
|
||||||
|
mask: '',
|
||||||
|
gateway: '',
|
||||||
|
protocol: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 左侧COM1串口
|
||||||
const formData2: any = ref({
|
const formData2: any = ref({
|
||||||
port: '',
|
port: 'COM1',
|
||||||
baud: null,
|
baud: null,
|
||||||
parity: '',
|
parity: '',
|
||||||
data_bits: null,
|
data_bits: null,
|
||||||
stop_bits: null,
|
stop_bits: null,
|
||||||
protocol: ''
|
protocol: ''
|
||||||
})
|
})
|
||||||
|
// 右侧COM2串口
|
||||||
|
const formData2Right: any = ref({
|
||||||
|
port: 'COM2',
|
||||||
|
baud: null,
|
||||||
|
parity: '',
|
||||||
|
data_bits: null,
|
||||||
|
stop_bits: null,
|
||||||
|
protocol: ''
|
||||||
|
})
|
||||||
|
const netConfig: any = ref({})
|
||||||
const networkCardOptions: any = ref([
|
const networkCardOptions: any = ref([
|
||||||
{ label: '网卡一', value: '网卡一' },
|
{ label: '网卡一', value: '网卡一' },
|
||||||
{ label: '网卡二', value: '网卡二' },
|
{ label: '网卡二', value: '网卡二' },
|
||||||
@ -72,120 +92,118 @@ const keyboardVisible = ref(false)
|
|||||||
const passwordDialogVisible = ref(false)
|
const passwordDialogVisible = ref(false)
|
||||||
const currentInputValue = ref('')
|
const currentInputValue = ref('')
|
||||||
const currentInputKey = ref('')
|
const currentInputKey = ref('')
|
||||||
const currentInputIndex = ref(0)
|
// 标记当前操作左/右表单:left / right
|
||||||
const currentInputType = ref('')
|
const currentInputSide = ref('left')
|
||||||
const infoList = ref<any>({})
|
|
||||||
const openKeyboard = (value: number, key: string, type: string) => {
|
const openKeyboard = (value: string, key: string, side: 'left' | 'right') => {
|
||||||
currentInputType.value = type
|
currentInputSide.value = side
|
||||||
currentInputValue.value = value.toString()
|
currentInputValue.value = value
|
||||||
currentInputKey.value = key
|
currentInputKey.value = key
|
||||||
keyboardVisible.value = true
|
keyboardVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyboardConfirm = (value: string) => {
|
const handleKeyboardConfirm = (value: string) => {
|
||||||
|
if (currentInputSide.value === 'left') {
|
||||||
formData.value[currentInputKey.value] = value
|
formData.value[currentInputKey.value] = value
|
||||||
|
} else {
|
||||||
|
formDataRight.value[currentInputKey.value] = value
|
||||||
|
}
|
||||||
keyboardVisible.value = false
|
keyboardVisible.value = false
|
||||||
}
|
}
|
||||||
// 保存
|
|
||||||
|
// 保存按钮打开密码弹窗
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
passwordDialogVisible.value = true
|
passwordDialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码弹框确认回调(密码已在校验组件内验证通过)
|
const handlePasswordConfirm = async () => {
|
||||||
const handlePasswordConfirm = () => {
|
passwordDialogVisible.value = false
|
||||||
saveDeviceNetConfig(formData.value).then((res: any) => {
|
if (isswitch.value) return
|
||||||
if (isswitch.value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isswitch.value = true
|
isswitch.value = true
|
||||||
if (res.code == 200) {
|
try {
|
||||||
saveDevicePortConfig(formData2.value).then((res: any) => {
|
const submitData: any = {
|
||||||
if (res.code == 200) {
|
hardware_version: netConfig.value.hardware_version,
|
||||||
|
software_version: netConfig.value.software_version,
|
||||||
|
password: netConfig.value.password,
|
||||||
|
net: [formData.value, formDataRight.value],
|
||||||
|
uart: [formData2.value, formData2Right.value]
|
||||||
|
}
|
||||||
|
const res = await saveDevicePortConfig(submitData)
|
||||||
|
if (res.code === 200) {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: `保存成功`,
|
message: '全部配置保存成功',
|
||||||
})
|
|
||||||
isswitch.value = false
|
|
||||||
} else {
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
message: '串口设置保存失败',
|
|
||||||
})
|
|
||||||
isswitch.value = false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: '常规配置保存失败',
|
message: '全部配置保存失败',
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
ElMessage({
|
||||||
|
type: 'error',
|
||||||
|
message: err.message || '保存失败',
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
isswitch.value = false
|
isswitch.value = false
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码弹框取消回调
|
|
||||||
const handlePasswordCancel = () => {
|
const handlePasswordCancel = () => {
|
||||||
// 取消操作,不做处理
|
// 取消不处理
|
||||||
}
|
|
||||||
const config: any = ref({})
|
|
||||||
const handleChange = (val: any) => {
|
|
||||||
fetchDeviceNet(val).then((res: any) => {
|
|
||||||
formData.value = res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const handleChangePort = (val: any) => {
|
|
||||||
fetchDevicePort(val).then((res: any) => {
|
|
||||||
formData2.value = res
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化加载左右两套数据
|
||||||
function init() {
|
function init() {
|
||||||
fetchDeviceNet('网卡一').then((res: any) => {
|
fetchDeviceNet('网卡一').then((res: any) => {
|
||||||
formData.value = res
|
formData.value = res
|
||||||
})
|
})
|
||||||
|
fetchDeviceNet('网卡二').then((res: any) => {
|
||||||
|
formDataRight.value = res
|
||||||
|
})
|
||||||
|
|
||||||
fetchDevicePort('COM1').then((res: any) => {
|
fetchDevicePort('COM1').then((res: any) => {
|
||||||
formData2.value = res
|
formData2.value = res
|
||||||
})
|
})
|
||||||
fetchChannelConfig().then((res: any) => {
|
fetchDevicePort('COM2').then((res: any) => {
|
||||||
config.value = res
|
formData2Right.value = res
|
||||||
|
})
|
||||||
|
getDeviceNetConfig().then((res: any) => {
|
||||||
|
netConfig.value = res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init()
|
init()
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="communication-container">
|
<div class="communication-container">
|
||||||
<el-form :model="formData" label-width="100px" class="form-wrapper">
|
<el-form label-width="100px" class="form-wrapper">
|
||||||
|
<!-- 常规配置:左右两栏 网卡一 / 网卡二 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
<div class="icon"></div>
|
<div class="icon"></div>
|
||||||
<div>常规配置</div>
|
<div>常规配置</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<el-row :gutter="40">
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="网卡号">
|
<el-form-item label="网卡号">
|
||||||
<el-select v-model="formData.nic" placeholder="请选择" @change="handleChange">
|
<el-input v-model="formData.nic" disabled placeholder="请输入" />
|
||||||
<el-option v-for="item in networkCardOptions" :key="item.value" :label="item.label"
|
|
||||||
:value="item.label" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="IP地址">
|
<el-form-item label="IP地址">
|
||||||
<el-input v-model="formData.ip" @focus="openKeyboard(formData.ip, 'ip', 'value')"
|
<el-input v-model="formData.ip" @focus="openKeyboard(formData.ip, 'ip', 'left')" />
|
||||||
style="width: 100%;" />
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<el-form-item label="子网掩码">
|
<el-form-item label="子网掩码">
|
||||||
<el-input v-model="formData.mask" @focus="openKeyboard(formData.mask, 'mask', 'value')" />
|
<el-input v-model="formData.mask" @focus="openKeyboard(formData.mask, 'mask', 'left')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="默认网关">
|
<el-form-item label="默认网关">
|
||||||
<el-input v-model="formData.gateway"
|
<el-input v-model="formData.gateway"
|
||||||
@focus="openKeyboard(formData.gateway, 'gateway', 'value')" />
|
@focus="openKeyboard(formData.gateway, 'gateway', 'left')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<el-form-item label="通讯协议">
|
<el-form-item label="通讯协议">
|
||||||
<el-select v-model="formData.protocol" placeholder="请选择">
|
<el-select v-model="formData.protocol" placeholder="请选择">
|
||||||
<el-option v-for="item in tcpProtocolOptions" :key="item.value" :label="item.label"
|
<el-option v-for="item in tcpProtocolOptions" :key="item.value" :label="item.label"
|
||||||
@ -193,19 +211,44 @@ onMounted(() => {
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item />
|
<el-form-item />
|
||||||
</div>
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="网卡号">
|
||||||
|
<el-input v-model="formDataRight.nic" disabled placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="IP地址">
|
||||||
|
<el-input v-model="formDataRight.ip"
|
||||||
|
@focus="openKeyboard(formDataRight.ip, 'ip', 'right')" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="子网掩码">
|
||||||
|
<el-input v-model="formDataRight.mask"
|
||||||
|
@focus="openKeyboard(formDataRight.mask, 'mask', 'right')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="默认网关">
|
||||||
|
<el-input v-model="formDataRight.gateway"
|
||||||
|
@focus="openKeyboard(formDataRight.gateway, 'gateway', 'right')" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="通讯协议">
|
||||||
|
<el-select v-model="formDataRight.protocol" placeholder="请选择">
|
||||||
|
<el-option v-for="item in tcpProtocolOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.label" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
<div class="icon"></div>
|
<div class="icon"></div>
|
||||||
<div>串口设置</div>
|
<div>串口设置</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<el-row :gutter="40">
|
||||||
|
<el-col :span="12">
|
||||||
<el-form-item label="串口号">
|
<el-form-item label="串口号">
|
||||||
<el-select v-model="formData2.port" placeholder="请选择" @change="handleChangePort">
|
<el-input v-model="formData2.port" disabled placeholder="请输入" />
|
||||||
<el-option v-for="item in comPortOptions" :key="item.label" :label="item.label"
|
|
||||||
:value="item.label" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="波特率">
|
<el-form-item label="波特率">
|
||||||
<el-select v-model="formData2.baud" placeholder="请选择">
|
<el-select v-model="formData2.baud" placeholder="请选择">
|
||||||
@ -213,8 +256,7 @@ onMounted(() => {
|
|||||||
:value="item.value" />
|
:value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<el-form-item label="校验位">
|
<el-form-item label="校验位">
|
||||||
<el-select v-model="formData2.parity" placeholder="请选择">
|
<el-select v-model="formData2.parity" placeholder="请选择">
|
||||||
<el-option v-for="item in parityOptions" :key="item.value" :label="item.label"
|
<el-option v-for="item in parityOptions" :key="item.value" :label="item.label"
|
||||||
@ -227,8 +269,6 @@ onMounted(() => {
|
|||||||
:value="item.value" />
|
:value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
|
||||||
<div class="form-row">
|
|
||||||
<el-form-item label="停止位">
|
<el-form-item label="停止位">
|
||||||
<el-select v-model="formData2.stop_bits" placeholder="请选择">
|
<el-select v-model="formData2.stop_bits" placeholder="请选择">
|
||||||
<el-option v-for="item in stopBitsOptions" :key="item.value" :label="item.label"
|
<el-option v-for="item in stopBitsOptions" :key="item.value" :label="item.label"
|
||||||
@ -241,29 +281,65 @@ onMounted(() => {
|
|||||||
:value="item.value" />
|
:value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</el-col>
|
||||||
</div>
|
<el-col :span="12">
|
||||||
|
<el-form-item label="串口号">
|
||||||
|
<el-input v-model="formData2Right.port" disabled placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="波特率">
|
||||||
|
<el-select v-model="formData2Right.baud" placeholder="请选择">
|
||||||
|
<el-option v-for="item in baudRateOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="校验位">
|
||||||
|
<el-select v-model="formData2Right.parity" placeholder="请选择">
|
||||||
|
<el-option v-for="item in parityOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据位">
|
||||||
|
<el-select v-model="formData2Right.data_bits" placeholder="请选择">
|
||||||
|
<el-option v-for="item in dataBitsOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="停止位">
|
||||||
|
<el-select v-model="formData2Right.stop_bits" placeholder="请选择">
|
||||||
|
<el-option v-for="item in stopBitsOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="通讯协议">
|
||||||
|
<el-select v-model="formData2Right.protocol" placeholder="请选择">
|
||||||
|
<el-option v-for="item in rtuProtocolOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div class="btn-wrapper">
|
<div class="btn-wrapper">
|
||||||
<el-button type="primary" style="background-color: #0099ff;width: 150px;height: 40px;"
|
<el-button type="primary" style="background-color: #0099ff;width: 150px;height: 40px;"
|
||||||
@click="handleSave">保存</el-button>
|
@click="handleSave">保存</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog v-model="dialogVisible" :close-on-click-modal="false" :show-close="false" title="错误提示" width="300">
|
<el-dialog v-model="dialogVisible" :close-on-click-modal="false" :show-close="false" title="错误提示" width="300">
|
||||||
<div style="color: #FF4D4F;font-size: 16px;text-align: center;">原密码验证错误!</div>
|
<div style="color: #FF4D4F;font-size: 16px;text-align: center;">原密码验证错误!</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
|
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<PasswordDialog
|
|
||||||
v-model:visible="passwordDialogVisible"
|
<PasswordDialog v-model:visible="passwordDialogVisible" title="密码验证" @confirm="handlePasswordConfirm"
|
||||||
title="密码验证"
|
@cancel="handlePasswordCancel" />
|
||||||
@confirm="handlePasswordConfirm"
|
|
||||||
@cancel="handlePasswordCancel"
|
|
||||||
/>
|
|
||||||
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
|
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
|
||||||
@confirm="handleKeyboardConfirm">
|
@confirm="handleKeyboardConfirm" />
|
||||||
</NumericKeyboard>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -275,14 +351,13 @@ onMounted(() => {
|
|||||||
|
|
||||||
.form-wrapper {
|
.form-wrapper {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 15px 50px;
|
padding: 15px 20px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0px 0px 10px rgba(219, 225, 236, 1);
|
box-shadow: 0px 0px 10px rgba(219, 225, 236, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding-bottom: 10px;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
@ -294,7 +369,7 @@ onMounted(() => {
|
|||||||
.section-title {
|
.section-title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin: 0 0 10px 0;
|
margin: 0 0 12px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@ -311,9 +386,20 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-row {
|
// 分栏小标题(网卡一/网卡二 COM1/COM2)
|
||||||
|
.sub-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #0099ff;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-left: 4px;
|
||||||
|
border-left: 3px solid #0099ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 每栏内部一行两个表单项
|
||||||
|
.form-col-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 40px;
|
gap: 20px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
@ -325,14 +411,12 @@ onMounted(() => {
|
|||||||
.btn-wrapper {
|
.btn-wrapper {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-form-item--label-right .el-form-item__label) {
|
:deep(.el-form-item--label-right .el-form-item__label) {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
color: #787878;
|
color: #787878;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-select__placeholder) {
|
:deep(.el-select__placeholder) {
|
||||||
@ -341,15 +425,19 @@ onMounted(() => {
|
|||||||
|
|
||||||
:deep(.el-input__inner) {
|
:deep(.el-input__inner) {
|
||||||
color: #363636;
|
color: #363636;
|
||||||
min-height: 40px;
|
min-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-select__wrapper) {
|
:deep(.el-select__wrapper) {
|
||||||
min-height: 40px;
|
min-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-form-item__label) {
|
:deep(.el-form-item__label) {
|
||||||
height: 40px;
|
height: 28px;
|
||||||
line-height: 40px;
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -1,11 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import { fetchSystemConfig, saveSystemConfig } from '@/api/platform'
|
import { fetchSystemConfig, saveSystemConfig } from '@/api/platform'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { connectTimeSync } from '@/websocket/client'
|
||||||
|
|
||||||
const formRef = ref<FormInstance>()
|
const formRef = ref<FormInstance>()
|
||||||
|
const isUserEdited = ref(false)
|
||||||
const form = ref({
|
const form = ref({
|
||||||
time_sync: '',
|
time_sync: '',
|
||||||
brightness: 0,
|
brightness: 0,
|
||||||
@ -38,6 +39,7 @@ const handleSubmit = async () => {
|
|||||||
isswitch.value = false
|
isswitch.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
let ws: WebSocket | null = null
|
||||||
function init() {
|
function init() {
|
||||||
fetchSystemConfig().then((res: any) => {
|
fetchSystemConfig().then((res: any) => {
|
||||||
form.value = res
|
form.value = res
|
||||||
@ -45,6 +47,17 @@ function init() {
|
|||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init()
|
init()
|
||||||
|
ws = connectTimeSync((event) => {
|
||||||
|
if (!isUserEdited.value) {
|
||||||
|
form.value.time_sync = event.data.time_sync
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (ws) {
|
||||||
|
ws.close()
|
||||||
|
ws = null
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -60,7 +73,8 @@ onMounted(() => {
|
|||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px" class="time-form">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="90px" class="time-form">
|
||||||
<el-form-item label="选择时间" prop="time_sync">
|
<el-form-item label="选择时间" prop="time_sync">
|
||||||
<el-date-picker v-model="form.time_sync" type="datetime" placeholder="请选择时间"
|
<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%;" />
|
@focus="isUserEdited = true" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%;" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user