触摸屏-直流
Lufaneng 4 months ago
parent de483cecf8
commit b5686ced94

@ -8,6 +8,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
BaseKeyboardInput: typeof import('./components/BaseKeyboardInput.vue')['default']
BasePasswordInput: typeof import('./components/BasePasswordInput.vue')['default']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']

@ -0,0 +1,256 @@
<template>
<div ref="keyboardWrapRef" class="keyboard-wrap" @click="focusInput">
<el-input ref="inputRef" v-model="model" @keyup.enter="handleEnter" :disabled="disabled" v-bind="$attrs" type="text">
<template v-for="(item, index) in $slots" :key="index" #[index]>
<slot :name="index"></slot>
</template>
</el-input>
</div>
<el-popover v-if="visible" :visible="true" :virtual-ref="inputRef" virtual-triggering placement="bottom" :width="width" :show-arrow="false" :hide-after="0" popper-style="padding: 0px;color:#000" popper-class="keyboard-popper" @after-enter="keyboardInit">
<div class="simple-keyboard"></div>
</el-popover>
</template>
<script setup lang="ts">
import Keyboard from 'simple-keyboard'
import 'simple-keyboard/build/css/index.css'
import layout from 'simple-keyboard-layouts/build/layouts/chinese.js'
defineOptions({
inheritAttrs: false
})
const model = defineModel<string>()
const emits = defineEmits(['onChange', 'enter', 'close', 'focus'])
const props = defineProps({
layoutName: {
type: String,
default: 'default'
},
// layoutNamenumber
precision: {
type: Number,
default: 10
},
//
isOpen: {
type: Boolean,
default: true
},
disabled: Boolean
})
const keyboard = ref<any>(null)
const keyboardWrapRef = ref(null)
const visible = ref(false)
const inputRef = ref()
const width = ref(1000)
const inputType = ref('text')
if (props.layoutName == 'number') width.value = 300
const displayDefault = ref({
'{bksp}': 'backspace',
'{lock}': 'caps',
'{enter}': 'enter',
'{tab}': 'tab',
'{shift}': 'shift',
'{change}': 'en',
'{space}': 'space',
'{clear}': 'clear',
'{close}': 'close',
'{arrowleft}': '←',
'{arrowright}': '→'
})
const open = () => {
if (visible.value) return
inputRef.value.focus()
emits('focus')
visible.value = true
}
const focusInput = () => {
if (props.disabled) return
if (visible.value) return
emits('focus')
if (props.isOpen) visible.value = true
}
const lang: any = {
'zh-cn': {
//
default: [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
"{lock} a s d f g h j k l ; ' {enter}",
'{change} z x c v b n m , . / {clear}',
'{arrowleft} {arrowright} {space} {close}'
],
//
shift: [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
'{lock} A S D F G H J K L : " {enter}',
'{change} Z X C V B N M < > ? {clear}',
'{arrowleft} {arrowright} {space} {close}'
]
},
th: {
default: [
'\u005F \u0E45 \u002F \u002D \u0E20 \u0E16 \u0E38 \u0E36 \u0E04 \u0E15 \u0E08 \u0E02 \u0E0A {bksp}',
'{tab} \u0E46 \u0E44 \u0E33 \u0E1E \u0E30 \u0E31 \u0E35 \u0E23 \u0E19 \u0E22 \u0E1A \u0E25 \u0E03',
'{lock} \u0E1F \u0E2B \u0E01 \u0E14 \u0E40 \u0E49 \u0E48 \u0E32 \u0E2A \u0E27 \u0E07 {enter}',
'{shift} \u0E1C \u0E1B \u0E41 \u0E2D \u0E34 \u0E37 \u0E17 \u0E21 \u0E43 \u0E1D {clear}',
'{arrowleft} {arrowright} {space} {close}'
],
shift: [
'% + \u0E51 \u0E52 \u0E53 \u0E54 \u0E39 \u0E3F \u0E55 \u0E56 \u0E57 \u0E58 \u0E59 {bksp}',
'{tab} \u0E50 \u0022 \u0E0E \u0E11 \u0E18 \u0E4D \u0E4A \u0E13 \u0E2F \u0E0D \u0E10 \u002C \u0E05',
'{lock} \u0E24 \u0E06 \u0E0F \u0E42 \u0E0C \u0E47 \u0E4B \u0E29 \u0E28 \u0E0B \u002E {enter}',
'{shift} ( ) \u0E09 \u0E2E \u0E3A \u0E4C \u003F \u0E12 \u0E2C \u0E26 {clear}',
'{arrowleft} {arrowright} {space} {close}'
]
}
}
const keyboardInit = () => {
let keyboardLayout = {
//
number: ['7 8 9', '4 5 6', '1 2 3', '. 0 {bksp}', '{arrowleft} {arrowright} {clear} {close}'],
...lang['zh-cn']
}
// if (lang[useSession('lang').value]) {
// keyboardLayout = { ...lang[useSession('lang').value], ...keyboardLayout }
// }
keyboard.value = new Keyboard('simple-keyboard', {
onChange: onChange,
onKeyPress: onKeyPress,
onInit: onInit,
layout: keyboardLayout,
layoutName: props.layoutName,
display: displayDefault.value
// theme: 'hg-theme-default init-keyboard' // class
})
}
const onInit = (keyboard: any) => {
keyboard.setInput(String(model.value || ''))
keyboard.setCaretPosition(inputRef.value?.ref.selectionEnd)
document.addEventListener('click', handlePopClose)
}
const onChange = (input: any) => {
model.value = input
emits('onChange', input)
}
const onKeyPress = (button: any) => {
if (button === '{lock}') return handleLock()
if (button === '{change}') return handleChange()
if (button === '{clear}') return handleClear()
if (button === '{enter}') return handleEnter()
if (button === '{close}') return close()
if (button === '{arrowleft}') return handleArrow(0)
if (button === '{arrowright}') return handleArrow(1)
}
const handleLock = () => {
let currentLayout = keyboard.value.options.layoutName
let shiftToggle = currentLayout === 'default' ? 'shift' : 'default'
keyboard.value.setOptions({
layoutName: shiftToggle
})
}
const handleChange = () => {
let layoutCandidates = keyboard.value.options.layoutCandidates
//
if (layoutCandidates != null && layoutCandidates != undefined) {
displayDefault.value['{change}'] = 'en'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: null,
display: displayDefault.value
})
} else {
displayDefault.value['{change}'] = 'cn'
keyboard.value.setOptions({
layoutName: 'default',
layoutCandidates: (layout as any)?.layoutCandidates,
display: displayDefault.value
})
}
}
const handleClear = () => {
keyboard.value.clearInput()
model.value = ''
}
const handleEnter = () => {
emits('enter')
}
const close = () => {
if (props.layoutName == 'number') {
//
model.value = model.value?.replace(new RegExp(`(\\d+)\\.(\\d{${props.precision}}).*$`), '$1.$2').replace(/\.$/, '')
}
document.removeEventListener('click', handlePopClose)
visible.value = false
emits('close')
}
const handleArrow = (num: number) => {
//
const index = keyboard.value.getCaretPositionEnd()
if (num == 0 && index - 1 >= 0) {
keyboard.value.setCaretPosition(index - 1)
} else if (num == 1 && index + 1 <= (model.value?.length || 0)) {
keyboard.value.setCaretPosition(index + 1)
}
}
const handlePopClose = (e: any) => {
//
if (
(e.target as Element).closest('.keyboard-popper') ||
(e.target as Element).closest('.keyboard-wrap') == keyboardWrapRef.value ||
/hg-candidate-box/.test(e.target.className)
) {
const index = keyboard.value.getCaretPositionEnd()
inputRef.value.ref.selectionStart = inputRef.value.ref.selectionEnd = index
inputRef.value.focus()
} else {
close()
}
}
onUnmounted(() => {
//
document.removeEventListener('click', handlePopClose)
})
defineExpose({ inputRef, visible, open, close, keyboardInit })
</script>
<style scoped>
.keyboard-wrap {
width: 100%;
}
:deep(.el-input input) {
-webkit-text-security: disc;
}
</style>
<style>
.hg-theme-default .hg-button.hg-button-arrowleft,
.hg-theme-default .hg-button.hg-button-arrowright {
max-width: 70px;
}
.hg-theme-default .hg-button.hg-button-close {
max-width: 100px;
}
.hg-layout-number .hg-button.hg-button-close {
max-width: none;
}
.hg-layout-number .hg-button.hg-button-bksp {
max-width: 92px;
}
</style>

@ -1,34 +1,13 @@
<template>
<el-dialog
v-model="visible"
title="请输入操作密码"
width="400px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="closeable"
append-to-body
class="password-dialog"
>
<el-dialog v-model="visible" title="请输入操作密码" width="400px" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="closeable" append-to-body class="password-dialog">
<div class="password-dialog-body">
<p class="password-hint">{{ hint }}</p>
<BaseKeyboardInput
v-model="password"
layout-name="number"
type="password"
placeholder="请输入密码"
clearable
@enter="handleVerify"
/>
<BasePasswordInput v-model="password" layout-name="number" placeholder="请输入密码" clearable @enter="handleVerify" />
</div>
<template #footer>
<div style="display:flex; gap:12px;">
<el-button style="flex:1" @click="handleCancel"></el-button>
<el-button
type="primary"
:loading="loading"
@click="handleVerify"
style="flex:1"
>
<el-button type="primary" :loading="loading" @click="handleVerify" style="flex:1">
确认
</el-button>
</div>
@ -37,7 +16,7 @@
</template>
<script setup>
import BaseKeyboardInput from '@/components/BaseKeyboardInput.vue'
import BasePasswordInput from '@/components/BasePasswordInput.vue'
import RPC from '@/utils/rpc'
import { useRouter } from 'vue-router'

@ -30,23 +30,21 @@
<div class="line">
<div class="item">
<div class="key">设置时间</div>
<el-date-picker
v-model="targetDatetime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择目标时间"
style="flex: 1;"
/>
<el-date-picker v-model="targetDatetime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择目标时间" style="flex: 1;" />
</div>
</div>
<div class="buttonBox">
<div class="button refresh" @click="getSystemTime">
<el-icon><Refresh /></el-icon>
<el-icon>
<Refresh />
</el-icon>
刷新时间
</div>
<div class="button save" @click="setSystemTime">
<el-icon><Check /></el-icon>
<el-icon>
<Check />
</el-icon>
设置时间
</div>
</div>
@ -72,42 +70,29 @@
<div class="line">
<div class="item full-width">
<div class="key">原密码</div>
<el-input
v-model="pwdForm.oldPassword"
type="password"
placeholder="请输入原密码"
show-password
style="flex:1"
/>
<!-- <el-input v-model="pwdForm.oldPassword" type="password" placeholder="请输入原密码" show-password style="flex:1" /> -->
<BasePasswordInput v-model="pwdForm.oldPassword" layout-name="number" placeholder="请输入原密码" clearable />
</div>
</div>
<div class="line">
<div class="item full-width">
<div class="key">新密码</div>
<el-input
v-model="pwdForm.newPassword"
type="password"
placeholder="至少 6 位"
show-password
style="flex:1"
/>
<!-- <el-input v-model="pwdForm.newPassword" type="password" placeholder="至少 6 位" show-password style="flex:1" /> -->
<BasePasswordInput v-model="pwdForm.newPassword" layout-name="number" placeholder="请输入新密码" clearable />
</div>
</div>
<div class="line">
<div class="item full-width">
<div class="key">确认新密码</div>
<el-input
v-model="pwdForm.confirmPassword"
type="password"
placeholder="再次输入新密码"
show-password
style="flex:1"
/>
<!-- <el-input v-model="pwdForm.confirmPassword" type="password" placeholder="再次输入新密码" show-password style="flex:1" /> -->
<BasePasswordInput v-model="pwdForm.confirmPassword" layout-name="number" placeholder="再次输入新密码" clearable />
</div>
</div>
<div class="buttonBox">
<div class="button save" @click="changePassword">
<el-icon><Check /></el-icon>
<el-icon>
<Check />
</el-icon>
确认修改
</div>
</div>
@ -124,7 +109,9 @@
<div class="bottom_item"></div>
<div class="bottom_item">
<el-button class="back-button" @click="goBack">
<el-icon><HomeFilled /></el-icon>
<el-icon>
<HomeFilled />
</el-icon>
返回主界面
</el-button>
</div>
@ -136,6 +123,7 @@
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import RPC from '@/utils/rpc'
import BasePasswordInput from '@/components/BasePasswordInput.vue'
const router = useRouter()
const commit_uid = sessionStorage.getItem('central_control_comm_uid')
@ -369,12 +357,18 @@ onUnmounted(() => {
&.save {
background-color: #188549;
&:hover { background-color: #1fa85d; }
&:hover {
background-color: #1fa85d;
}
}
&.refresh {
background-color: #1565a8;
&:hover { background-color: #1a7fd4; }
&:hover {
background-color: #1a7fd4;
}
}
}
}
@ -396,7 +390,9 @@ onUnmounted(() => {
color: rgba(255, 255, 255, 0.85);
font-size: 13px;
&:last-child { margin-bottom: 0; }
&:last-child {
margin-bottom: 0;
}
}
.result-key {
@ -418,6 +414,7 @@ onUnmounted(() => {
bottom: 0;
left: 0;
width: 100vw;
z-index: 999
}
.back-button {

Loading…
Cancel
Save