feat: 修改密码
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
235e71fba3
commit
a92743dda1
|
|
@ -166,3 +166,4 @@ const answerSheetData = computed(() =>
|
|||
|
||||
适合在 App 中使用,代码更简洁、性能更好、易于维护。
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -91,3 +91,4 @@ answer-sheet-viewer/
|
|||
3. 适用于 H5/小程序/APP 多端
|
||||
4. 图片和批注坐标使用原始像素值,组件内部处理缩放
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -238,3 +238,4 @@ export function useMarkingRenderer() {
|
|||
renderMarking,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ export * from './ai-types'
|
|||
export { default as AnswerSheetWithMarking } from './AnswerSheetWithMarking.vue'
|
||||
export * from './composables/useDataParser'
|
||||
export * from './types'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { myChangePasswordUsingPost } from '@/service/wode'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
show: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:show', value: boolean): void
|
||||
(e: 'success'): void
|
||||
}>()
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
})
|
||||
|
||||
// 是否显示密码
|
||||
const showPassword = ref({
|
||||
old: false,
|
||||
new: false,
|
||||
confirm: false,
|
||||
})
|
||||
|
||||
// 提交中状态
|
||||
const submitting = ref(false)
|
||||
|
||||
// 关闭弹窗
|
||||
function handleClose() {
|
||||
emit('update:show', false)
|
||||
// 延迟清空表单,避免关闭动画时看到数据清空
|
||||
setTimeout(() => {
|
||||
resetForm()
|
||||
}, 300)
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
function resetForm() {
|
||||
formData.value = {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
}
|
||||
showPassword.value = {
|
||||
old: false,
|
||||
new: false,
|
||||
confirm: false,
|
||||
}
|
||||
}
|
||||
|
||||
// 显示提示信息
|
||||
function showToast(title: string) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
mask: true,
|
||||
})
|
||||
}
|
||||
|
||||
// 表单验证
|
||||
function validateForm() {
|
||||
if (!formData.value.oldPassword) {
|
||||
showToast('请输入原密码')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!formData.value.newPassword) {
|
||||
showToast('请输入新密码')
|
||||
return false
|
||||
}
|
||||
|
||||
if (formData.value.newPassword.length < 6) {
|
||||
showToast('新密码长度不能少于6位')
|
||||
return false
|
||||
}
|
||||
|
||||
if (!formData.value.confirmPassword) {
|
||||
showToast('请确认新密码')
|
||||
return false
|
||||
}
|
||||
|
||||
if (formData.value.newPassword !== formData.value.confirmPassword) {
|
||||
showToast('两次输入的密码不一致')
|
||||
return false
|
||||
}
|
||||
|
||||
if (formData.value.oldPassword === formData.value.newPassword) {
|
||||
showToast('新密码不能与原密码相同')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 提交修改
|
||||
async function handleSubmit() {
|
||||
if (!validateForm()) {
|
||||
return
|
||||
}
|
||||
|
||||
submitting.value = true
|
||||
|
||||
try {
|
||||
const res = await myChangePasswordUsingPost({
|
||||
body: {
|
||||
old_password: formData.value.oldPassword,
|
||||
new_password: formData.value.newPassword,
|
||||
confirm_password: formData.value.confirmPassword,
|
||||
},
|
||||
})
|
||||
|
||||
if (res.success) {
|
||||
uni.showToast({
|
||||
title: '密码修改成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
mask: true,
|
||||
})
|
||||
handleClose()
|
||||
emit('success')
|
||||
}
|
||||
else {
|
||||
uni.showToast({
|
||||
title: res.message || '修改失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
mask: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
catch (error: any) {
|
||||
uni.showToast({
|
||||
title: error.data?.message || '修改失败,请稍后重试',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
mask: true,
|
||||
})
|
||||
}
|
||||
finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 切换密码可见性
|
||||
function togglePasswordVisibility(type: 'old' | 'new' | 'confirm') {
|
||||
showPassword.value[type] = !showPassword.value[type]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view v-if="show" class="fixed inset-0 z-999 flex items-center justify-center" @tap.self="handleClose">
|
||||
<!-- 遮罩层 -->
|
||||
<view class="absolute inset-0 bg-black/50" @tap="handleClose" />
|
||||
|
||||
<!-- 弹窗内容 -->
|
||||
<view class="relative mx-6 max-w-400px w-full rounded-2xl bg-white p-6 shadow-xl">
|
||||
<!-- 标题 -->
|
||||
<view class="mb-6 flex items-center justify-between">
|
||||
<text class="text-xl text-slate-800 font-semibold">修改密码</text>
|
||||
<view class="i-carbon:close h-6 w-6 text-slate-400" @tap="handleClose" />
|
||||
</view>
|
||||
|
||||
<!-- 表单 -->
|
||||
<view class="space-y-4">
|
||||
<!-- 原密码 -->
|
||||
<view class="space-y-2">
|
||||
<text class="text-sm text-slate-600">原密码</text>
|
||||
<view class="relative flex items-center border border-slate-200 rounded-xl bg-slate-50 px-4 py-3">
|
||||
<view class="i-carbon:locked mr-2 text-lg text-slate-400" />
|
||||
<input
|
||||
v-model="formData.oldPassword"
|
||||
class="flex-1 bg-transparent text-base text-slate-800"
|
||||
:type="(showPassword.old ? 'text' : 'password') as any"
|
||||
placeholder="请输入原密码"
|
||||
:maxlength="20"
|
||||
>
|
||||
<view
|
||||
:class="showPassword.old ? 'i-carbon:view' : 'i-carbon:view-off'"
|
||||
class="ml-2 text-lg text-slate-400"
|
||||
@tap="togglePasswordVisibility('old')"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 新密码 -->
|
||||
<view class="space-y-2">
|
||||
<text class="text-sm text-slate-600">新密码</text>
|
||||
<view class="relative flex items-center border border-slate-200 rounded-xl bg-slate-50 px-4 py-3">
|
||||
<view class="i-carbon:locked mr-2 text-lg text-slate-400" />
|
||||
<input
|
||||
v-model="formData.newPassword"
|
||||
class="flex-1 bg-transparent text-base text-slate-800"
|
||||
:type="(showPassword.new ? 'text' : 'password') as any"
|
||||
placeholder="请输入新密码(至少6位)"
|
||||
:maxlength="20"
|
||||
>
|
||||
<view
|
||||
:class="showPassword.new ? 'i-carbon:view' : 'i-carbon:view-off'"
|
||||
class="ml-2 text-lg text-slate-400"
|
||||
@tap="togglePasswordVisibility('new')"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认新密码 -->
|
||||
<view class="space-y-2">
|
||||
<text class="text-sm text-slate-600">确认新密码</text>
|
||||
<view class="relative flex items-center border border-slate-200 rounded-xl bg-slate-50 px-4 py-3">
|
||||
<view class="i-carbon:locked mr-2 text-lg text-slate-400" />
|
||||
<input
|
||||
v-model="formData.confirmPassword"
|
||||
class="flex-1 bg-transparent text-base text-slate-800"
|
||||
:type="(showPassword.confirm ? 'text' : 'password') as any"
|
||||
placeholder="请再次输入新密码"
|
||||
:maxlength="20"
|
||||
>
|
||||
<view
|
||||
:class="showPassword.confirm ? 'i-carbon:view' : 'i-carbon:view-off'"
|
||||
class="ml-2 text-lg text-slate-400"
|
||||
@tap="togglePasswordVisibility('confirm')"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 按钮组 -->
|
||||
<view class="mt-6 flex gap-3">
|
||||
<button
|
||||
class="h-44px flex-1 border border-slate-200 rounded-xl bg-white text-slate-600 font-medium !outline-none"
|
||||
@tap="handleClose"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
class="h-44px flex-1 rounded-xl from-blue-500 to-cyan-500 bg-gradient-to-r text-white font-medium !border-none !outline-none"
|
||||
:class="{ 'opacity-50': submitting }"
|
||||
:disabled="submitting"
|
||||
@tap="handleSubmit"
|
||||
>
|
||||
{{ submitting ? '提交中...' : '确认修改' }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import ChangePasswordDialog from '@/components/mine/ChangePasswordDialog.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 修改密码弹窗显示状态
|
||||
const showChangePasswordDialog = ref(false)
|
||||
|
||||
// 获取屏幕边界到安全区域距离
|
||||
let safeAreaInsets
|
||||
let systemInfo
|
||||
|
|
@ -53,10 +57,7 @@ const menuItems = [
|
|||
function handleMenuClick(type: string) {
|
||||
switch (type) {
|
||||
case 'password':
|
||||
uni.showToast({
|
||||
title: '修改密码功能开发中',
|
||||
icon: 'none',
|
||||
})
|
||||
showChangePasswordDialog.value = true
|
||||
break
|
||||
case 'privacy':
|
||||
uni.showToast({
|
||||
|
|
@ -73,6 +74,23 @@ function handleMenuClick(type: string) {
|
|||
}
|
||||
}
|
||||
|
||||
// 修改密码成功回调
|
||||
function handlePasswordChangeSuccess() {
|
||||
// 可以在这里添加额外的逻辑,比如重新登录
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '密码已修改,请重新登录',
|
||||
showCancel: false,
|
||||
confirmColor: '#3B82F6',
|
||||
success: () => {
|
||||
userStore.logOut()
|
||||
uni.reLaunch({
|
||||
url: '/pages/auth/index',
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 退出登录
|
||||
function handleLogout() {
|
||||
uni.showModal({
|
||||
|
|
@ -227,6 +245,12 @@ function getIconColorClass(index: number) {
|
|||
<text class="text-xs text-slate-400">版本号 v1.0.0</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 修改密码弹窗 -->
|
||||
<ChangePasswordDialog
|
||||
v-model:show="showChangePasswordDialog"
|
||||
@success="handlePasswordChangeSuccess"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue