forked from gzt/A8000
9 changed files with 536 additions and 25 deletions
-
6components.d.ts
-
1src/pages/Index/Regular/Emergency.vue
-
3src/pages/Index/Regular/Running.vue
-
80src/pages/Index/Settings/Users.vue
-
88src/pages/Index/components/Setting/AddUserModal.vue
-
8src/pages/Index/components/Setting/DelWarn.vue
-
84src/pages/Index/components/Setting/EnterPinModal.vue
-
290src/pages/Index/components/Setting/UpdatePinModal.vue
-
1src/pages/Index/components/Setting/index.ts
@ -0,0 +1,290 @@ |
|||
<template> |
|||
<teleport to="body"> |
|||
<div v-if="visible" class="modal-overlay"> |
|||
<div class="modal-container"> |
|||
<div class="modal-header"></div> |
|||
<div class="modal-title"> |
|||
<span class="title-text">请输入 PIN 码</span> |
|||
</div> |
|||
<div class="modal-body"> |
|||
<div class="input-container"> |
|||
<div> |
|||
<input :type="showoldpasswd?'text':'password'" v-model="oldpasswd" placeholder="输入旧PIN码" @focus="showKeyboard('oldpasswd')" class="pin-input" /> |
|||
<el-icon class="pwd-view" @click="showoldpasswd = !showoldpasswd"><View /></el-icon> |
|||
</div> |
|||
<br/> |
|||
<div> |
|||
<input :type="showPassword?'text':'password'" v-model="password " placeholder="输入新PIN 码" @focus="showKeyboard('password')" class="pin-input" /> |
|||
<el-icon class="pwd-view" @click="showPassword = !showPassword"><View /></el-icon> |
|||
</div> |
|||
<br/> |
|||
<div> |
|||
<input :type="showConfirmPassword?'text':'password'" v-model="confirmPassword " placeholder="输入确认新PIN 码" @focus="showKeyboard('confirmPassword')" class="pin-input" /> |
|||
<el-icon class="pwd-view" @click="showConfirmPassword = !showConfirmPassword"><View /></el-icon> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="modal-footer"> |
|||
<el-button @click="cancel">取消</el-button> |
|||
<el-button type="primary" @click="confirmPin" :loading="loading">确认</el-button> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
<InitWarn |
|||
v-if="showErrorModal" |
|||
:visible="showErrorModal" |
|||
title="错误提示" |
|||
message="两次输入的密码不一致" |
|||
icon="/src/assets/Warn.svg" |
|||
confirmText="确认" |
|||
@confirm="showErrorModal = false" |
|||
/> |
|||
<!-- 键盘 --> |
|||
<transition name="slide-up"> |
|||
<div class="keyboard" v-if="keyboardVisible"> |
|||
<SimpleKeyboard :input="currentInputValue" @onChange="handleKeyboardInput" @onKeyPress="handleKeyPress" /> |
|||
</div> |
|||
</transition> |
|||
</div> |
|||
</teleport> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue' |
|||
import { InitWarn } from '../../components/Consumables' |
|||
import { ElMessage } from 'element-plus'; |
|||
defineProps<{ visible: boolean; loading: boolean }>() |
|||
const emit = defineEmits<{ |
|||
(e: 'confirm', pin: {oldpasswd:string, password:string}): void |
|||
(e: 'cancel'): void |
|||
}>() |
|||
|
|||
const showErrorModal = ref(false) |
|||
const showoldpasswd = ref(false) |
|||
const showPassword = ref(false) |
|||
const showConfirmPassword = ref(false) |
|||
const oldpasswd = ref('') |
|||
const password = ref('') |
|||
const confirmPassword = ref('') |
|||
|
|||
const confirmPin = () => { |
|||
if(!oldpasswd.value){ |
|||
ElMessage.error('请输入旧密码'); |
|||
return; |
|||
} |
|||
if(!password.value){ |
|||
ElMessage.error('请输入新密码'); |
|||
return; |
|||
} |
|||
if(!confirmPassword.value){ |
|||
ElMessage.error('请确认新密码'); |
|||
return; |
|||
} |
|||
|
|||
if(password.value != confirmPassword.value){ |
|||
// showErrorModal.value = true; |
|||
ElMessage.error('两次输入的密码不一致'); |
|||
return; |
|||
} |
|||
const params = { |
|||
oldpasswd: oldpasswd.value, |
|||
password: password.value |
|||
} |
|||
emit('confirm', params) |
|||
} |
|||
|
|||
// 键盘相关状态 |
|||
const keyboardVisible = ref(false) |
|||
const currentInputValue = ref('') |
|||
const currentInputField = ref<'oldpasswd' | 'password' | 'confirmPassword' | ''>('') |
|||
|
|||
// 隐藏键盘 |
|||
const hideKeyboard = () => { |
|||
keyboardVisible.value = false |
|||
currentInputField.value = '' |
|||
currentInputValue.value = '' |
|||
} |
|||
|
|||
// 显示键盘 |
|||
const showKeyboard = (field:any) => { |
|||
// 清空当前输入值,避免累加 |
|||
// currentInputValue.value = '' |
|||
if(field == 'oldpasswd'){ |
|||
currentInputValue.value = oldpasswd.value |
|||
} |
|||
if(field == 'password'){ |
|||
currentInputValue.value = password.value |
|||
} |
|||
if(field == 'confirmPassword'){ |
|||
currentInputValue.value = confirmPassword.value |
|||
} |
|||
currentInputField.value = field |
|||
keyboardVisible.value = true |
|||
} |
|||
|
|||
// 处理键盘输入 |
|||
const handleKeyboardInput = (value: string) => { |
|||
// 更新当前输入值 |
|||
currentInputValue.value = value |
|||
// 更新对应字段的值 |
|||
|
|||
if (currentInputField.value === 'oldpasswd') { |
|||
oldpasswd.value = value |
|||
} else if(currentInputField.value == 'password'){ |
|||
password.value = value |
|||
}else if(currentInputField.value == 'confirmPassword'){ |
|||
confirmPassword.value = value |
|||
} |
|||
} |
|||
|
|||
// 处理键盘按键 |
|||
const handleKeyPress = (button: string) => { |
|||
if (button === '{enter}') { |
|||
hideKeyboard() |
|||
} else if (button === '{bksp}') { |
|||
// 处理退格键 |
|||
const value = currentInputValue.value |
|||
if (value.length > 0) { |
|||
const newValue = value.slice(0, -1) |
|||
handleKeyboardInput(newValue) |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
const cancel = () => { |
|||
emit('cancel') |
|||
} |
|||
</script> |
|||
|
|||
<style scoped lang="less"> |
|||
/* 样式与 AddUserModal 类似 */ |
|||
.modal-overlay { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: rgba(0, 0, 0, 0.5); |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
z-index: 1000; |
|||
} |
|||
|
|||
.modal-overlay { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: rgba(0, 0, 0, 0.5); |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
z-index: 1000; |
|||
} |
|||
|
|||
.modal-container { |
|||
background-color: #fff; |
|||
border-radius: 10px; |
|||
width: 833px; |
|||
height: 633px; |
|||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); |
|||
overflow: hidden; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
position: relative; |
|||
|
|||
.modal-header { |
|||
background-color: #528dfe; |
|||
height: 8px; |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
} |
|||
|
|||
.modal-title { |
|||
text-align: center; |
|||
margin-top: 15px; |
|||
font-size: 32px; |
|||
color: #528dfe; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.modal-body { |
|||
display: flex; |
|||
justify-content: center; |
|||
padding: 20px; |
|||
|
|||
.input-container { |
|||
position: relative; |
|||
width: 100%; |
|||
|
|||
.pin-input { |
|||
box-sizing: border-box; |
|||
width: 100%; |
|||
font-size: 32px; |
|||
padding: 20px 80px; |
|||
color: #b0b0b0; |
|||
border: 1px solid #e0e0e0; |
|||
border-radius: 25px; |
|||
outline: none; |
|||
|
|||
&:focus { |
|||
border-color: #528dfe; |
|||
color: #528dfe; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.modal-footer { |
|||
display: flex; |
|||
justify-content: space-around; |
|||
padding: 20px; |
|||
box-sizing: border-box; |
|||
|
|||
button { |
|||
width: 200px; |
|||
height: 80px; |
|||
font-size: 32px; |
|||
border-radius: 30px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.keyboard { |
|||
position: fixed; |
|||
bottom: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 300px; |
|||
background-color: #f5f7fa; |
|||
border-top-left-radius: 16px; |
|||
border-top-right-radius: 16px; |
|||
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.1); |
|||
z-index: 1000; |
|||
} |
|||
// 键盘动画 |
|||
.slide-up-enter-active, |
|||
.slide-up-leave-active { |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
.slide-up-enter-from, |
|||
.slide-up-leave-to { |
|||
transform: translateY(100%); |
|||
} |
|||
|
|||
.pwd-view{ |
|||
font-size: 30px; |
|||
position: absolute; |
|||
margin-left: -40px; |
|||
margin-top: 16px; |
|||
} |
|||
</style> |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue