修改键盘输入
This commit is contained in:
parent
497b9072f8
commit
65c56b8900
18
frontend/package-lock.json
generated
18
frontend/package-lock.json
generated
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
BIN
frontend/src/assets/images/menuicon/jpdel.png
Normal file
BIN
frontend/src/assets/images/menuicon/jpdel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 468 B |
210
frontend/src/components/NumericKeyboard.vue
Normal file
210
frontend/src/components/NumericKeyboard.vue
Normal 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('.')
|
||||
// 最多3个点(4段),且前一段不能为空且不能超过255
|
||||
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]
|
||||
// 每段最多3位,且值不能超过255
|
||||
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>
|
||||
@ -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 {
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -483,4 +548,4 @@ const handleSave = () => {
|
||||
:deep(.el-input__inner) {
|
||||
text-align: center !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user