2026-05-18 12:39:57 +08:00
|
|
|
|
<script setup lang="ts">
|
2026-05-19 10:46:30 +08:00
|
|
|
|
import { ref, reactive, onMounted } from 'vue'
|
2026-05-18 12:39:57 +08:00
|
|
|
|
import type { FormInstance, FormRules } from 'element-plus'
|
2026-05-19 10:46:30 +08:00
|
|
|
|
import { verifyAccessPassword, saveDeviceConfig, fetchDeviceConfig, saveDevicePassword } from '@/api/platform'
|
2026-05-18 18:41:32 +08:00
|
|
|
|
import { ElMessage } from 'element-plus'
|
2026-06-12 14:35:11 +08:00
|
|
|
|
import NumericKeyboard from '@/components/NumericKeyboard.vue'
|
2026-05-18 12:39:57 +08:00
|
|
|
|
const formRef = ref<FormInstance>()
|
|
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
|
const form = reactive({
|
|
|
|
|
|
oldPassword: '',
|
|
|
|
|
|
newPassword: '',
|
|
|
|
|
|
confirmPassword: ''
|
|
|
|
|
|
})
|
2026-05-19 09:14:37 +08:00
|
|
|
|
const deviceConfig: any = ref({})
|
2026-05-18 12:39:57 +08:00
|
|
|
|
// 校验规则
|
|
|
|
|
|
const rules: FormRules = {
|
|
|
|
|
|
oldPassword: [
|
|
|
|
|
|
{ required: true, message: '请输入原密码', trigger: 'blur' }
|
|
|
|
|
|
],
|
|
|
|
|
|
newPassword: [
|
|
|
|
|
|
{ required: true, message: '请输入新密码', trigger: 'blur' },
|
2026-05-19 10:46:30 +08:00
|
|
|
|
{ min: 6, max: 6, message: '密码长度需 6位', trigger: 'blur' },
|
|
|
|
|
|
{
|
|
|
|
|
|
validator: (rule, value, callback) => {
|
|
|
|
|
|
if (!/^\d{6}$/.test(value)) {
|
|
|
|
|
|
callback(new Error('密码必须为6位数字'))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
callback()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
trigger: 'blur'
|
|
|
|
|
|
}
|
2026-05-18 12:39:57 +08:00
|
|
|
|
],
|
|
|
|
|
|
confirmPassword: [
|
|
|
|
|
|
{ required: true, message: '请再次输入新密码', trigger: 'blur' },
|
|
|
|
|
|
{
|
|
|
|
|
|
validator: (rule, value, callback) => {
|
|
|
|
|
|
if (value !== form.newPassword) {
|
|
|
|
|
|
callback(new Error('两次输入的密码不一致'))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
callback()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
trigger: 'blur'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
2026-05-18 18:41:32 +08:00
|
|
|
|
const isSubmit = ref(false)
|
2026-05-19 10:46:30 +08:00
|
|
|
|
const dialogVisible = ref(false)
|
|
|
|
|
|
const handleClose = () => {
|
|
|
|
|
|
dialogVisible.value = false
|
|
|
|
|
|
}
|
2026-06-12 14:35:11 +08:00
|
|
|
|
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()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-18 12:39:57 +08:00
|
|
|
|
// 提交保存
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
|
|
if (!formRef.value) return
|
|
|
|
|
|
await formRef.value.validate((valid) => {
|
|
|
|
|
|
if (valid) {
|
2026-05-18 18:41:32 +08:00
|
|
|
|
if (isSubmit.value) return
|
|
|
|
|
|
isSubmit.value = true
|
|
|
|
|
|
verifyAccessPassword(form.oldPassword).then(res => {
|
|
|
|
|
|
if (res.data) {
|
2026-05-19 10:46:30 +08:00
|
|
|
|
saveDevicePassword({
|
2026-05-19 09:14:37 +08:00
|
|
|
|
password: form.newPassword,
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res.data) {
|
|
|
|
|
|
ElMessage({
|
|
|
|
|
|
type: 'success',
|
|
|
|
|
|
message: '密码设置成功',
|
|
|
|
|
|
})
|
|
|
|
|
|
isSubmit.value = false
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ElMessage({
|
2026-05-19 10:46:30 +08:00
|
|
|
|
type: 'error',
|
2026-05-19 09:14:37 +08:00
|
|
|
|
message: '密码设置失败',
|
|
|
|
|
|
})
|
|
|
|
|
|
isSubmit.value = false
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2026-05-18 18:41:32 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
isSubmit.value = false
|
2026-05-19 10:46:30 +08:00
|
|
|
|
dialogVisible.value = true
|
2026-05-18 18:41:32 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2026-05-18 12:39:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-05-18 18:41:32 +08:00
|
|
|
|
onMounted(() => {
|
2026-05-19 10:46:30 +08:00
|
|
|
|
|
2026-05-18 18:41:32 +08:00
|
|
|
|
})
|
2026-05-18 12:39:57 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="password-container">
|
|
|
|
|
|
<!-- 标题 -->
|
|
|
|
|
|
<div class="password-container-content">
|
|
|
|
|
|
<div class="title">
|
|
|
|
|
|
<span class="title-line"></span>
|
|
|
|
|
|
密码设置
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 表单 -->
|
2026-05-19 09:14:37 +08:00
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="password-form">
|
2026-05-18 18:41:32 +08:00
|
|
|
|
<el-form-item label="原密码" prop="oldPassword">
|
2026-06-12 14:35:11 +08:00
|
|
|
|
<el-input v-model="form.oldPassword" @focus="openKeyboard(form.oldPassword, 'oldPassword')" type="password" placeholder="请输入原密码" show-password />
|
2026-05-18 12:39:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
2026-05-18 18:41:32 +08:00
|
|
|
|
<el-form-item label="新密码" prop="newPassword">
|
2026-06-12 14:35:11 +08:00
|
|
|
|
<el-input v-model="form.newPassword" @focus="openKeyboard(form.newPassword, 'newPassword')" type="password" placeholder="请输入新密码" show-password />
|
2026-05-18 12:39:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
2026-05-18 18:41:32 +08:00
|
|
|
|
<el-form-item label="确认新密码" prop="confirmPassword">
|
2026-06-12 14:35:11 +08:00
|
|
|
|
<el-input v-model="form.confirmPassword" @focus="openKeyboard(form.confirmPassword, 'confirmPassword')" type="password" placeholder="请再次输入新密码" show-password />
|
2026-05-18 12:39:57 +08:00
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 保存按钮 -->
|
2026-05-19 10:46:30 +08:00
|
|
|
|
<el-button type="primary" style="background-color: #0099ff;width: 150px;height: 40px;" class="save-btn"
|
|
|
|
|
|
@click="handleSubmit">
|
2026-05-18 12:39:57 +08:00
|
|
|
|
保存
|
|
|
|
|
|
</el-button>
|
2026-05-19 10:46:30 +08:00
|
|
|
|
<el-dialog v-model="dialogVisible" :close-on-click-modal="false" :show-close="false" title="错误提示" width="500" :before-close="handleClose">
|
|
|
|
|
|
<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>
|
2026-06-12 14:35:11 +08:00
|
|
|
|
<NumericKeyboard v-model:visible="keyboardVisible" :model-value="currentInputValue"
|
|
|
|
|
|
@confirm="handleKeyboardConfirm" />
|
2026-05-18 12:39:57 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.password-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2026-05-19 09:14:37 +08:00
|
|
|
|
padding: 15px;
|
2026-05-18 12:39:57 +08:00
|
|
|
|
|
|
|
|
|
|
.password-container-content {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: calc(100vh - 230px);
|
|
|
|
|
|
background-color: #ffffff;
|
|
|
|
|
|
padding: 20px 50px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
box-shadow: 0px 0px 10px rgba(219, 225, 236, 1);
|
|
|
|
|
|
}
|
2026-05-19 10:46:30 +08:00
|
|
|
|
|
2026-05-18 12:39:57 +08:00
|
|
|
|
.title {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
|
|
.title-line {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
width: 4px;
|
|
|
|
|
|
height: 14px;
|
|
|
|
|
|
background-color: #409eff;
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.password-form {
|
|
|
|
|
|
width: 60%;
|
|
|
|
|
|
}
|
2026-05-19 10:46:30 +08:00
|
|
|
|
|
2026-05-18 12:39:57 +08:00
|
|
|
|
.save-btn {
|
|
|
|
|
|
margin-top: 30px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-form-item--label-right .el-form-item__label) {
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
color: #787878;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.el-input__inner) {
|
|
|
|
|
|
color: #363636;
|
|
|
|
|
|
min-height: 40px;
|
|
|
|
|
|
}
|
2026-05-19 10:46:30 +08:00
|
|
|
|
|
2026-05-18 12:39:57 +08:00
|
|
|
|
:deep(.el-form-item__label) {
|
2026-05-19 10:46:30 +08:00
|
|
|
|
line-height: 40px !important;
|
2026-05-18 12:39:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|