修改键盘输入

This commit is contained in:
jingna 2026-06-12 14:35:11 +08:00
parent 497b9072f8
commit 65c56b8900
12 changed files with 557 additions and 60 deletions

View File

@ -14,6 +14,7 @@
"vue-router": "^5.0.7"
},
"devDependencies": {
"@types/node": "^25.9.3",
"@vitejs/plugin-vue": "^5.2.1",
"sass-embedded": "^1.99.0",
"typescript": "^5.7.3",
@ -1366,6 +1367,16 @@
"@types/lodash": "*"
}
},
"node_modules/@types/node": {
"version": "25.9.3",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-25.9.3.tgz",
"integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
@ -3133,6 +3144,13 @@
"integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
"license": "MIT"
},
"node_modules/undici-types": {
"version": "7.24.6",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
},
"node_modules/unplugin": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-3.0.0.tgz",

View File

@ -15,6 +15,7 @@
"vue-router": "^5.0.7"
},
"devDependencies": {
"@types/node": "^25.9.3",
"@vitejs/plugin-vue": "^5.2.1",
"sass-embedded": "^1.99.0",
"typescript": "^5.7.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

View File

@ -0,0 +1,210 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
const props = defineProps<{
visible: boolean
modelValue: string | number
}>()
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void
(e: 'confirm', value: string): void
}>()
const displayValue = ref(String(props.modelValue))
watch(() => props.visible, (newVal) => {
if (newVal) {
displayValue.value = ''
}
})
const keys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '0', 'del']
const handleKeyPress = (key: string) => {
if (key === 'del') {
displayValue.value = displayValue.value.slice(0, -1)
} else if (key === '.') {
const parts = displayValue.value.split('.')
// 34255
if (parts.length < 4 && parts[parts.length - 1] !== '' && parseInt(parts[parts.length - 1]) <= 255) {
displayValue.value += key
}
} else {
const parts = displayValue.value.split('.')
const currentPart = parts[parts.length - 1]
// 3255
if (currentPart.length < 3 && parseInt(currentPart + key) <= 255) {
displayValue.value += key
}
}
}
const handleConfirm = () => {
emit('confirm', displayValue.value)
emit('update:visible', false)
}
const handleCancel = () => {
emit('update:visible', false)
}
</script>
<template>
<div v-if="visible" class="numeric-keyboard-overlay">
<div class="numeric-keyboard" @click.stop>
<div class="display-area">
<span class="display-value">{{ displayValue }}</span>
</div>
<div class="keyboard-grid">
<button v-for="key in keys" :key="key" class="key-btn" :class="{ 'action-btn': key === 'del' }"
@click="handleKeyPress(key)">
<img v-if="key === 'del'" style="width: 30px; height: 30px;margin-top: 4px;" src="@/assets/images/menuicon/jpdel.png" alt="">
<span v-else>{{ key }}</span>
</button>
</div>
<div class="confirm-area">
<button class="cancel-btn" @click="handleCancel">取消</button>
<button class="confirm-btn" @click="handleConfirm">确定</button>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.numeric-keyboard-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-end;
justify-content: center;
z-index: 9999;
}
.numeric-keyboard {
width: 100%;
max-width: 285px;
background: #fff;
border-radius: 5px 5px 0 0;
padding: 10px;
padding-bottom: calc(20px + env(safe-area-inset-bottom));
position: relative;
}
.display-area {
background: #f5f5f5;
border-radius: 4px;
// padding: 16px;
margin-bottom: 16px;
text-align: right;
height: 40px;
line-height: 40px;
padding-right: 10px;
}
.display-value {
font-size: 20px;
font-weight: 600;
color: #333;
}
.keyboard-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.key-btn {
height: 40px;
font-size: 22px;
font-weight: 500;
border: none;
border-radius: 4px;
background: #f8f8f8;
color: #333;
cursor: pointer;
transition: all 0.2s;
&:active {
background: #e0e0e0;
transform: scale(0.98);
}
&.action-btn {
// background: #ff6b6b;
color: #333;
}
}
.confirm-area {
display: flex;
justify-content: center;
margin-top: 16px;
gap: 10px;
}
.confirm-btn {
width: 60px;
height: 35px;
font-size: 16px;
// font-weight: 600;
border: none;
border-radius: 5px;
background: #0099ff;
color: #fff;
cursor: pointer;
transition: all 0.2s;
margin-right: 10px;
&:active {
background: #0077cc;
transform: scale(0.98);
}
}
.cancel-btn {
width: 60px;
height: 35px;
font-size: 16px;
// font-weight: 600;
border: none;
border-radius: 5px;
border: 1px solid #dcdfe6;
color: #606266;
cursor: pointer;
transition: all 0.2s;
background: transparent;
&:active {
// background: #0077cc;
transform: scale(0.98);
}
}
.close-btn {
position: absolute;
top: -11px;
right: -14px;
width: 30px;
height: 30px;
border: none;
border-radius: 50%;
background: #f0f0f0;
color: #666;
font-size: 30px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
&:active {
background: #e0e0e0;
transform: scale(0.95);
}
}
</style>

View File

@ -115,20 +115,24 @@ export interface ChannelConfigPayload {
}
export interface AlarmRule {
category?: string
limit?: number
delay?: number
output_node?: string
enabled?: boolean
category: string
limit: number
delay: number
output_node: string
enabled: boolean
value?: number
[key: string]: any
}
export interface AlarmRules {
category: string
value?: number
[key: string]: any
}
export interface LineAlarmSettingPayload {
line_no: number
over_limit_alarm: AlarmRule[]
fault_alarm: AlarmRule[],
transformer_change: AlarmRule[]
transformer_change: AlarmRules[]
}
export interface AiAlarmSettingItem {

View File

@ -2,8 +2,20 @@
import { ref, onMounted } from 'vue'
import { fetchAiAlarmSetting, saveAiAlarmSetting, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
import NumericKeyboard from '@/components/NumericKeyboard.vue'
const channelList = ref([
interface ChannelItem {
channel_no: number
singal_type: string
output_node: string
limit_low: number
limit_high: number
delay: number
enabled: boolean
[key: string]: any
}
const channelList = ref<ChannelItem[]>([
{ channel_no: 1, singal_type: '4~20mA', output_node: '', limit_low: 0, limit_high: 8, delay: 8, enabled: false },
{ channel_no: 2, singal_type: '1~5V', output_node: '', limit_low: 0, limit_high: 8, delay: 8, enabled: false },
{ channel_no: 3, singal_type: '4~20mA', output_node: '', limit_low: 0, limit_high: 8, delay: 8, enabled: false },
@ -21,6 +33,24 @@ const channelList = ref([
const nodeOptions = ref(['开出一', '开出二', '开出三', '开出四', '开出五', '开出六', '开出七', '开出八', '开出九', '开出十', '开出十一', '开出十二'])
const isswitch = ref(false)
const dialogVisible = ref(false)
const keyboardVisible = ref(false)
const currentInputValue = ref('')
const currentInputIndex = ref(-1)
const currentInputType = ref('')
const openKeyboard = (index: number, value: any, type: string) => {
currentInputType.value = type
currentInputIndex.value = index
currentInputValue.value = value
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: any) => {
if (currentInputIndex.value >= 0) {
channelList.value[currentInputIndex.value][currentInputType.value] = value
}
keyboardVisible.value = false
}
const handleSave = () => {
ElMessageBox.prompt('请输入密码', '保存', {
confirmButtonText: '确定',
@ -54,7 +84,6 @@ const handleSave = () => {
const init = () => {
fetchAiAlarmSetting().then(res => {
console.log(res, 989)
res.forEach(item => {
channelList.value.forEach((channel: any) => {
if (channel.channel_no === item.channel_no) {
@ -89,16 +118,21 @@ onMounted(() => {
<div class="row" v-for="(item, idx) in channelList" :key="idx">
<div class="cell cell-no">{{ item.channel_no }}</div>
<div class="cell cell-type" style="background: #ffffff;">
<el-input v-model="item.singal_type" placeholder="" />
<el-input
v-model="item.singal_type"
placeholder=""
disabled
/>
</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-input-number v-model="item.limit_low" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_low"
@focus="openKeyboard(idx, item.limit_low, 'limit_low')" style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-low" style="background: #ffffff;">
<el-input-number v-model="item.limit_high" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_high" style="width: 100%;" @focus="openKeyboard(idx, item.limit_high, 'limit_high')" :controls="false" />
</div>
<div class="cell cell-high" style="background: #ffffff;">
<el-input-number v-model="item.delay" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.delay" @focus="openKeyboard(idx, item.delay, 'delay')" style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-select v-model="item.output_node">
@ -120,6 +154,12 @@ onMounted(() => {
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
</template>
</el-dialog>
<NumericKeyboard
v-model:visible="keyboardVisible"
:model-value="currentInputValue"
@confirm="handleKeyboardConfirm"
/>
</div>
</template>
@ -249,4 +289,8 @@ onMounted(() => {
:deep(.el-input__inner) {
text-align: center !important;
}
:deep(.el-input.is-disabled .el-input__inner) {
color: #606266;
-webkit-text-fill-color: #606266;
}
</style>

View File

@ -2,7 +2,8 @@
import { ref, onMounted } from 'vue'
import { fetchChannelConfig, saveChannelConfig, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
const channelList: any = ref([
import NumericKeyboard from '@/components/NumericKeyboard.vue'
const channelList = ref<ChannelItem[]>([
{ 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 },
@ -22,6 +23,44 @@ const categoryOptions = ref(['UA', 'UB', 'UC'])
const categoryOptions2 = ref(['IA', 'IB', 'IC'])
const dialogVisible = ref(false)
const isswitch = ref(false)
const keyboardVisible = ref(false)
const currentInputValue = ref(0)
const currentInputIndex = ref(-1)
interface ChannelItem {
ch: number
singal_type: string
line_no: number
type: string
limit_low: number
limit_high: number
}
const currentInputType = ref('')
const openKeyboard = (index: number, value: number, type: string) => {
currentInputType.value = type
currentInputIndex.value = index
currentInputValue.value = value
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
if (currentInputIndex.value >= 0) {
const channel = channelList.value[currentInputIndex.value]
const numValue = Number(value)
switch (currentInputType.value) {
case 'limit_low':
channel.limit_low = numValue
break
case 'limit_high':
channel.limit_high = numValue
break
default:
break
}
}
keyboardVisible.value = false
}
const handleSave = () => {
ElMessageBox.prompt('请输入密码', '保存', {
confirmButtonText: '确定',
@ -91,10 +130,10 @@ onMounted(() => {
<div class="cell cell-low">低端值</div>
<div class="cell cell-high">高端值</div>
</div>
<div class="row" v-for="(item, idx) in channelList" :key="idx">
<div class="row" v-for="(item, idx ) in channelList" :key="idx">
<div class="cell cell-no">{{ item.ch }}</div>
<div class="cell cell-type" style="background: #ffffff;">
<el-input v-model="item.singal_type" placeholder="" />
<el-input disabled v-model="item.singal_type" placeholder="" />
</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-select v-model="item.line_no">
@ -104,31 +143,35 @@ onMounted(() => {
</div>
<div class="cell cell-category" style="background: #ffffff;">
<el-select v-model="item.type">
<el-option v-for="cat in (item.singal_type.includes('mA') ? categoryOptions2 : categoryOptions)" :key="cat" :value="cat" :label="cat"></el-option>
<el-option v-for="cat in (item.singal_type.includes('mA') ? categoryOptions2 : 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.limit_low" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_low" @focus="openKeyboard(idx, item.limit_low, 'limit_low')"
style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-high" style="background: #ffffff;">
<el-input-number v-model="item.limit_high" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_high" @focus="openKeyboard(idx, item.limit_high, 'limit_high')"
style="width: 100%;" :controls="false" />
</div>
</div>
</div>
<div class="btn-wrap">
<button class="save-btn" @click="handleSave">保存</button>
</div>
<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>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">
确定
</el-button>
</div>
</template>
</el-dialog>
<div style="color: #FF4D4F;font-size: 16px;text-align: center;">原密码验证错误</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="dialogVisible = false">
确定
</el-button>
</div>
</template>
</el-dialog>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm" />
</div>
</template>
@ -260,4 +303,8 @@ onMounted(() => {
font-size: 14px !important;
}
:deep(.el-input.is-disabled .el-input__inner) {
color: #606266;
-webkit-text-fill-color: #606266;
}
</style>

View File

@ -2,7 +2,16 @@
import { ref, onMounted } from 'vue'
import { fetchChannelConfig, saveChannelConfig, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
const channelList: any = ref([
import NumericKeyboard from '@/components/NumericKeyboard.vue'
interface ChannelItem {
ch: number
singal_type: string
line_no: number
type: string
limit_low: number
limit_high: number
}
const channelList = ref<ChannelItem[]>([
{ 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 },
@ -21,6 +30,35 @@ const categoryOptions = ref(['UA', 'UB', 'UC'])
const categoryOptions2 = ref(['IA', 'IB', 'IC'])
const dialogVisible = ref(false)
const aiChannelList = ref([])
const currentInputType = ref('')
const currentInputIndex = ref(-1)
const currentInputValue = ref()
const keyboardVisible = ref(false)
const openKeyboard = (index: number, value: number, type: string) => {
currentInputType.value = type
currentInputIndex.value = index
currentInputValue.value = value
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
if (currentInputIndex.value >= 0) {
const channel = channelList.value[currentInputIndex.value]
const numValue = Number(value)
switch (currentInputType.value) {
case 'limit_low':
channel.limit_low = numValue
break
case 'limit_high':
channel.limit_high = numValue
break
default:
break
}
}
keyboardVisible.value = false
}
function init() {
fetchChannelConfig().then((res: any) => {
aiChannelList.value = res.ao_channel
@ -93,7 +131,7 @@ onMounted(() => {
<div class="row" v-for="(item, idx) in channelList" :key="idx">
<div class="cell cell-no">{{ item.ch }}</div>
<div class="cell cell-type" style="background: #ffffff;">
<el-input v-model="item.singal_type" placeholder="" />
<el-input v-model="item.singal_type" disabled placeholder="" />
</div>
<div class="cell cell-line" style="background: #ffffff;">
<el-select v-model="item.line_no">
@ -108,10 +146,10 @@ onMounted(() => {
</el-select>
</div>
<div class="cell cell-low" style="background: #ffffff;">
<el-input-number v-model="item.limit_low" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_low" @focus="openKeyboard(idx, item.limit_low, 'limit_low')" style="width: 100%;" :controls="false" />
</div>
<div class="cell cell-high" style="background: #ffffff;">
<el-input-number v-model="item.limit_high" style="width: 100%;" :controls="false" />
<el-input-number v-model="item.limit_high" @focus="openKeyboard(idx, item.limit_high, 'limit_high')" style="width: 100%;" :controls="false" />
</div>
</div>
</div>
@ -129,6 +167,8 @@ onMounted(() => {
</div>
</template>
</el-dialog>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm" />
</div>
</template>
@ -258,4 +298,8 @@ onMounted(() => {
:deep(.el-input__inner) {
text-align: center !important;
}
:deep(.el-input.is-disabled .el-input__inner) {
color: #606266;
-webkit-text-fill-color: #606266;
}
</style>

View File

@ -2,6 +2,8 @@
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { fetchDeviceNet, fetchDevicePort, saveDeviceNetConfig, saveDevicePortConfig, verifyAccessPassword, fetchChannelConfig } from '@/api/platform'
import NumericKeyboard from '@/components/NumericKeyboard.vue'
//
const formData: any = ref({
nic: '',
@ -65,6 +67,23 @@ const rtuProtocolOptions = [
]
const isswitch = ref(false)
const dialogVisible = ref(false)
const keyboardVisible = ref(false)
const currentInputValue = ref('')
const currentInputKey = ref('')
const currentInputIndex = ref(0)
const currentInputType = ref('')
const infoList = ref<any>({})
const openKeyboard = (value: number, key: string, type: string) => {
currentInputType.value = type
currentInputValue.value = value.toString()
currentInputKey.value = key
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
formData.value[currentInputKey.value] = value
keyboardVisible.value = false
}
//
const handleSave = () => {
ElMessageBox.prompt('请输入密码', '保存', {
@ -161,15 +180,17 @@ onMounted(() => {
</el-select>
</el-form-item>
<el-form-item label="IP地址">
<el-input v-model="formData.ip" />
<el-input v-model="formData.ip" @focus="openKeyboard(formData.ip, 'ip', 'value')"
style="width: 100%;" />
</el-form-item>
</div>
<div class="form-row">
<el-form-item label="子网掩码">
<el-input v-model="formData.mask" />
<el-input v-model="formData.mask" @focus="openKeyboard(formData.mask, 'mask', 'value')" />
</el-form-item>
<el-form-item label="默认网关">
<el-input v-model="formData.gateway" />
<el-input v-model="formData.gateway"
@focus="openKeyboard(formData.gateway, 'gateway', 'value')" />
</el-form-item>
</div>
<div class="form-row">
@ -242,6 +263,9 @@ onMounted(() => {
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
</template>
</el-dialog>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm">
</NumericKeyboard>
</div>
</template>
@ -325,6 +349,7 @@ onMounted(() => {
:deep(.el-select__wrapper) {
min-height: 40px;
}
:deep(.el-form-item__label) {
height: 40px;
line-height: 40px;

View File

@ -3,7 +3,7 @@ import { ref, reactive, onMounted } from 'vue'
import type { FormInstance } from 'element-plus'
import { fetchSystemConfig, saveSystemConfig } from '@/api/platform'
import { ElMessage } from 'element-plus'
import NumericKeyboard from '@/components/NumericKeyboard.vue'
const formRef = ref<FormInstance>()
//
@ -13,6 +13,19 @@ const form = ref({
time_sync: ''
})
const isswitch = ref(false)
const currentInputType = ref('')
const currentInputIndex = ref(-1)
const currentInputValue = ref()
const keyboardVisible = ref(false)
const openKeyboard = (value: number, type: string) => {
currentInputType.value = type
currentInputValue.value = value
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
form.value.screen_saver = Number(value)
}
//
const handleSave = async () => {
if(isswitch.value){
@ -49,7 +62,7 @@ const init = () => {
</div>
<el-form ref="formRef" :model="form" label-width="100px" class="light-form">
<el-form-item label="息屏时间设置" prop="screen_saver">
<el-input v-model.number="form.screen_saver" type="number" min="0">
<el-input v-model.number="form.screen_saver" type="number" min="0" @click="openKeyboard(form.screen_saver, 'screen_saver')">
<template #suffix>
<span class="unit"></span>
</template>
@ -67,6 +80,8 @@ const init = () => {
<el-button type="primary" class="save-btn" @click="handleSave">
保存
</el-button>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm" />
</div>
</template>

View File

@ -2,6 +2,7 @@
import { ref, onMounted } from 'vue'
import { fetchLineAlarmSetting, saveLineAlarmSetting, verifyAccessPassword } from '@/api/platform'
import { ElMessage, ElMessageBox } from 'element-plus'
import NumericKeyboard from '@/components/NumericKeyboard.vue'
const lineTabs = ref([
{
label: '线路一定值',
@ -25,7 +26,40 @@ const lineTabs = ref([
}
])
const activeTab = ref('1')
const infoList = ref({
interface FaultAlarmItem {
category: string
delay: number
enabled: boolean
output_node: string
limit: number
}
interface OverLimitAlarmItem {
category: string
delay: number
enabled: boolean
output_node: string
limit: number
}
interface TransformerItem {
category: string
value: number
}
interface InfoListType {
line_no: number
fault_alarm: FaultAlarmItem[]
over_limit_alarm: OverLimitAlarmItem[]
transformer_change: TransformerItem[]
}
type InfoFirstKey = 'fault_alarm' | 'over_limit_alarm' | 'transformer_change'
type FaultKey = 'delay' | 'limit'
type OverLimitKey = 'delay' | 'limit'
type TransKey = 'value'
const infoList = ref<InfoListType>({
line_no: 1,
fault_alarm: [
{ category: 'PT断线', delay: 0, enabled: false, output_node: '', limit: 0 },
@ -39,11 +73,40 @@ const infoList = ref({
{ category: '频率', delay: 0, enabled: false, output_node: '', limit: 0 },
],
transformer_change: [
{ category: 'PT变比',value: 0,},
{ category: 'CT变比',value: 0,},
{ category: 'PT变比', value: 0 },
{ category: 'CT变比', value: 0 },
]
})
const currentInputType = ref('')
const currentInputIndex = ref(-1)
const currentInputKey = ref<InfoFirstKey>('fault_alarm')
const currentInputValue = ref<number>(0)
const keyboardVisible = ref(false)
const openKeyboard = (index: number, value: number, key: InfoFirstKey, type: string) => {
currentInputType.value = type
currentInputValue.value = value
currentInputIndex.value = index
currentInputKey.value = key
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
const key1 = currentInputKey.value
const idx = currentInputIndex.value
const key2 = currentInputType.value
const val = Number(value)
if (key1 === 'fault_alarm') {
(infoList.value[key1][idx] as FaultAlarmItem)[key2 as FaultKey] = val
} else if (key1 === 'over_limit_alarm') {
(infoList.value[key1][idx] as OverLimitAlarmItem)[key2 as OverLimitKey] = val
} else if (key1 === 'transformer_change') {
(infoList.value[key1][idx] as TransformerItem)[key2 as TransKey] = val
}
keyboardVisible.value = false
}
const options = ref([
{
label: '开出1',
@ -219,23 +282,23 @@ const handleSave = () => {
<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.over_limit_alarm[0].limit" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[0].limit" @click="openKeyboard(0, infoList.over_limit_alarm[0].limit,'over_limit_alarm','limit')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[1].limit" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[1].limit" @click="openKeyboard(1, infoList.over_limit_alarm[1].limit,'over_limit_alarm','limit')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[2].limit" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[2].limit" @click="openKeyboard(2, infoList.over_limit_alarm[2].limit,'over_limit_alarm','limit')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.fault_alarm[0].delay" style="width: 100%;"
<el-input-number v-model="infoList.fault_alarm[0].delay" @click="openKeyboard(0, infoList.fault_alarm[0].delay,'fault_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.fault_alarm[1].limit" style="width: 100%;"
<el-input-number v-model="infoList.fault_alarm[1].limit" @click="openKeyboard(1, infoList.fault_alarm[1].limit,'fault_alarm','limit')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height" style="border: none;">
@ -245,38 +308,38 @@ const handleSave = () => {
<img src="@/assets/images/menuicon/noitem.png" style="width: 100%; height: 100%;" alt="">
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.transformer_change[0].value" style="width: 100%;"
<el-input-number v-model="infoList.transformer_change[0].value" @click="openKeyboard(0, infoList.transformer_change[0].value,'transformer_change','value')" style="width: 100%;"
:controls="false" />
</div>
</div>
<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.over_limit_alarm[0].delay" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[0].delay" @click="openKeyboard(0, infoList.over_limit_alarm[0].delay,'over_limit_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[1].delay" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[1].delay" @click="openKeyboard(1, infoList.over_limit_alarm[1].delay,'over_limit_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[2].delay" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[2].delay" @click="openKeyboard(2, infoList.over_limit_alarm[2].delay,'over_limit_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[3].delay" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[3].delay" @click="openKeyboard(3, infoList.over_limit_alarm[3].delay,'over_limit_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.over_limit_alarm[4].delay" style="width: 100%;"
<el-input-number v-model="infoList.over_limit_alarm[4].delay" @click="openKeyboard(4, infoList.over_limit_alarm[4].delay,'over_limit_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.fault_alarm[0].delay" style="width: 100%;"
<el-input-number v-model="infoList.fault_alarm[0].delay" @click="openKeyboard(0, infoList.fault_alarm[0].delay,'fault_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.fault_alarm[1].delay" style="width: 100%;"
<el-input-number v-model="infoList.fault_alarm[1].delay" @click="openKeyboard(1, infoList.fault_alarm[1].delay,'fault_alarm','delay')" style="width: 100%;"
:controls="false" />
</div>
<div class="tab-content-item-box box-color box-height">
@ -328,7 +391,7 @@ const handleSave = () => {
</el-select>
</div>
<div class="tab-content-item-box box-color box-height">
<el-input-number v-model="infoList.transformer_change[1].value" style="width: 100%;"
<el-input-number v-model="infoList.transformer_change[1].value" @focus="openKeyboard(1, infoList.transformer_change[1].value,'transformer_change','value')" style="width: 100%;"
:controls="false" />
</div>
</div>
@ -368,6 +431,8 @@ const handleSave = () => {
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
</template>
</el-dialog>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm"></NumericKeyboard>
</div>
</template>

View File

@ -3,6 +3,7 @@ import { ref, reactive, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { verifyAccessPassword, saveDeviceConfig, fetchDeviceConfig, saveDevicePassword } from '@/api/platform'
import { ElMessage } from 'element-plus'
import NumericKeyboard from '@/components/NumericKeyboard.vue'
const formRef = ref<FormInstance>()
//
@ -50,6 +51,27 @@ const dialogVisible = ref(false)
const handleClose = () => {
dialogVisible.value = false
}
const currentInputValue = ref()
const keyboardVisible = ref(false)
const currentInputType = ref('')
const openKeyboard = (value: string, type: string) => {
currentInputType.value = type
currentInputValue.value = value
keyboardVisible.value = true
}
const handleKeyboardConfirm = (value: string) => {
if (currentInputType.value === 'oldPassword') {
form.oldPassword = value
} else if (currentInputType.value === 'newPassword') {
form.newPassword = value
} else if (currentInputType.value === 'confirmPassword') {
form.confirmPassword = value
}
keyboardVisible.value = false
formRef.value?.clearValidate()
}
//
const handleSubmit = async () => {
if (!formRef.value) return
@ -102,15 +124,15 @@ onMounted(() => {
<!-- 表单 -->
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="password-form">
<el-form-item label="原密码" prop="oldPassword">
<el-input v-model="form.oldPassword" type="password" placeholder="请输入原密码" show-password />
<el-input v-model="form.oldPassword" @focus="openKeyboard(form.oldPassword, 'oldPassword')" type="password" placeholder="请输入原密码" show-password />
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="form.newPassword" type="password" placeholder="请输入新密码" show-password />
<el-input v-model="form.newPassword" @focus="openKeyboard(form.newPassword, 'newPassword')" type="password" placeholder="请输入新密码" show-password />
</el-form-item>
<el-form-item label="确认新密码" prop="confirmPassword">
<el-input v-model="form.confirmPassword" type="password" placeholder="请再次输入新密码" show-password />
<el-input v-model="form.confirmPassword" @focus="openKeyboard(form.confirmPassword, 'confirmPassword')" type="password" placeholder="请再次输入新密码" show-password />
</el-form-item>
</el-form>
</div>
@ -131,6 +153,8 @@ onMounted(() => {
</div>
</template>
</el-dialog>
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
@confirm="handleKeyboardConfirm" />
</div>
</template>