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 中使用,代码更简洁、性能更好、易于维护。
|
适合在 App 中使用,代码更简洁、性能更好、易于维护。
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,3 +91,4 @@ answer-sheet-viewer/
|
||||||
3. 适用于 H5/小程序/APP 多端
|
3. 适用于 H5/小程序/APP 多端
|
||||||
4. 图片和批注坐标使用原始像素值,组件内部处理缩放
|
4. 图片和批注坐标使用原始像素值,组件内部处理缩放
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,3 +238,4 @@ export function useMarkingRenderer() {
|
||||||
renderMarking,
|
renderMarking,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ export * from './ai-types'
|
||||||
export { default as AnswerSheetWithMarking } from './AnswerSheetWithMarking.vue'
|
export { default as AnswerSheetWithMarking } from './AnswerSheetWithMarking.vue'
|
||||||
export * from './composables/useDataParser'
|
export * from './composables/useDataParser'
|
||||||
export * from './types'
|
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">
|
<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'
|
import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
// 修改密码弹窗显示状态
|
||||||
|
const showChangePasswordDialog = ref(false)
|
||||||
|
|
||||||
// 获取屏幕边界到安全区域距离
|
// 获取屏幕边界到安全区域距离
|
||||||
let safeAreaInsets
|
let safeAreaInsets
|
||||||
let systemInfo
|
let systemInfo
|
||||||
|
|
@ -53,10 +57,7 @@ const menuItems = [
|
||||||
function handleMenuClick(type: string) {
|
function handleMenuClick(type: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'password':
|
case 'password':
|
||||||
uni.showToast({
|
showChangePasswordDialog.value = true
|
||||||
title: '修改密码功能开发中',
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
break
|
break
|
||||||
case 'privacy':
|
case 'privacy':
|
||||||
uni.showToast({
|
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() {
|
function handleLogout() {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
|
|
@ -227,6 +245,12 @@ function getIconColorClass(index: number) {
|
||||||
<text class="text-xs text-slate-400">版本号 v1.0.0</text>
|
<text class="text-xs text-slate-400">版本号 v1.0.0</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 修改密码弹窗 -->
|
||||||
|
<ChangePasswordDialog
|
||||||
|
v-model:show="showChangePasswordDialog"
|
||||||
|
@success="handlePasswordChangeSuccess"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue