|
|
@ -2,6 +2,17 @@ |
|
|
|
<template v-if="getShow"> |
|
|
|
<LoginFormTitle class="enter-x" /> |
|
|
|
<Form class="p-4 enter-x" :model="formData" :rules="getFormRules" ref="formRef"> |
|
|
|
<FormItem name="tenantId" class="enter-x" v-if="tenant.tenantEnabled"> |
|
|
|
<Select v-model:value="formData.tenantId" size="large" @change="handleTenantChange"> |
|
|
|
<template #suffixIcon> |
|
|
|
<Icon icon="mdi:company" /> |
|
|
|
</template> |
|
|
|
<SelectOption v-for="item in tenant.voList" :key="item.tenantId" :value="item.tenantId">{{ |
|
|
|
item.companyName |
|
|
|
}}</SelectOption> |
|
|
|
</Select> |
|
|
|
</FormItem> |
|
|
|
|
|
|
|
<FormItem name="account" class="enter-x"> |
|
|
|
<Input |
|
|
|
size="large" |
|
|
@ -18,14 +29,31 @@ |
|
|
|
size="large" |
|
|
|
v-model:value="formData.sms" |
|
|
|
:placeholder="t('sys.login.smsCode')" |
|
|
|
:sendCodeApi="handleSendSmsCode" |
|
|
|
/> |
|
|
|
</FormItem> |
|
|
|
|
|
|
|
<FormItem name="password" class="enter-x"> |
|
|
|
<StrengthMeter |
|
|
|
size="large" |
|
|
|
v-model:value="formData.password" |
|
|
|
:placeholder="t('sys.login.password')" |
|
|
|
/> |
|
|
|
</FormItem> |
|
|
|
<FormItem name="confirmPassword" class="enter-x"> |
|
|
|
<InputPassword |
|
|
|
size="large" |
|
|
|
visibilityToggle |
|
|
|
v-model:value="formData.confirmPassword" |
|
|
|
:placeholder="t('sys.login.confirmPassword')" |
|
|
|
/> |
|
|
|
</FormItem> |
|
|
|
|
|
|
|
<FormItem class="enter-x"> |
|
|
|
<Button type="primary" size="large" block @click="handleReset" :loading="loading"> |
|
|
|
<Button type="primary" size="large" block class="enter-x" @click="handleReset" :loading="loading"> |
|
|
|
{{ t('common.resetText') }} |
|
|
|
</Button> |
|
|
|
<Button size="large" block class="mt-4" @click="handleBackLogin"> |
|
|
|
<Button size="large" block class="mt-4 enter-x" @click="handleBackLogin"> |
|
|
|
{{ t('sys.login.backSignIn') }} |
|
|
|
</Button> |
|
|
|
</FormItem> |
|
|
@ -33,32 +61,136 @@ |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<script lang="ts" setup> |
|
|
|
import { reactive, ref, computed, unref } from 'vue'; |
|
|
|
import { reactive, ref, computed, unref, onMounted } from 'vue'; |
|
|
|
import { message } from 'ant-design-vue'; |
|
|
|
import LoginFormTitle from './LoginFormTitle.vue'; |
|
|
|
import { Form, Input, Button } from 'ant-design-vue'; |
|
|
|
import { Form, Input, Button, Select, SelectOption } from 'ant-design-vue'; |
|
|
|
import { CountdownInput } from '@/components/CountDown'; |
|
|
|
import { StrengthMeter } from '@/components/StrengthMeter'; |
|
|
|
import { useI18n } from '@/hooks/web/useI18n'; |
|
|
|
import { useLoginState, useFormRules, LoginStateEnum } from './useLogin'; |
|
|
|
import { useLoginState, useFormRules, useFormValid, LoginStateEnum } from './useLogin'; |
|
|
|
import { sendSmsCode } from '@/api/auth/captcha'; |
|
|
|
import { resetPasswordApi, tenantList } from '@/api/auth'; |
|
|
|
import { TenantResp } from '@/api/auth/model'; |
|
|
|
import { useLocalStorage } from '@vueuse/core'; |
|
|
|
import { SelectValue } from 'ant-design-vue/es/select'; |
|
|
|
import Icon from '@/components/Icon/Icon.vue'; |
|
|
|
|
|
|
|
const FormItem = Form.Item; |
|
|
|
const InputPassword = Input.Password; |
|
|
|
const { t } = useI18n(); |
|
|
|
const { handleBackLogin, getLoginState } = useLoginState(); |
|
|
|
const { getFormRules } = useFormRules(); |
|
|
|
|
|
|
|
const formRef = ref(); |
|
|
|
const loading = ref(false); |
|
|
|
|
|
|
|
// 默认租户ID |
|
|
|
const defaultTenantId = '000000'; |
|
|
|
const localTenantId = useLocalStorage('tenantId', defaultTenantId); |
|
|
|
|
|
|
|
const formData = reactive({ |
|
|
|
account: '', |
|
|
|
mobile: '', |
|
|
|
sms: '', |
|
|
|
password: '', |
|
|
|
confirmPassword: '', |
|
|
|
tenantId: defaultTenantId, |
|
|
|
}); |
|
|
|
|
|
|
|
// 租户信息 |
|
|
|
const tenant = reactive<TenantResp & { loadSuccess: boolean }>({ |
|
|
|
tenantEnabled: false, |
|
|
|
voList: [], |
|
|
|
loadSuccess: false, |
|
|
|
}); |
|
|
|
|
|
|
|
const { getFormRules } = useFormRules(formData); |
|
|
|
const { validForm } = useFormValid(formRef); |
|
|
|
|
|
|
|
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.RESET_PASSWORD); |
|
|
|
|
|
|
|
// 处理租户变更 |
|
|
|
function handleTenantChange(tenantId: SelectValue) { |
|
|
|
localTenantId.value = tenantId as string; |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化租户选择 |
|
|
|
async function tenantSelectInit() { |
|
|
|
try { |
|
|
|
const ret = await tenantList(); |
|
|
|
const { tenantEnabled, voList } = ret; |
|
|
|
if (tenantEnabled) { |
|
|
|
const currentTenantId = voList.length ? voList[0].tenantId : defaultTenantId; |
|
|
|
formData.tenantId = currentTenantId; |
|
|
|
localTenantId.value = currentTenantId; |
|
|
|
} |
|
|
|
Object.assign(tenant, ret); |
|
|
|
tenant.loadSuccess = true; |
|
|
|
} catch (e) { |
|
|
|
console.error('租户选择异常'); |
|
|
|
tenant.loadSuccess = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 发送短信验证码 |
|
|
|
const handleSendSmsCode = async (): Promise<boolean> => { |
|
|
|
// 验证手机号是否填写 |
|
|
|
if (!formData.mobile) { |
|
|
|
message.error('请先填写手机号码'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 验证手机号格式 |
|
|
|
const mobileRegex = /^1[3-9]\d{9}$/; |
|
|
|
if (!mobileRegex.test(formData.mobile)) { |
|
|
|
message.error('请输入正确的手机号码'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
await sendSmsCode(formData.mobile); |
|
|
|
message.success('验证码发送成功'); |
|
|
|
return true; |
|
|
|
} catch (error) { |
|
|
|
message.error('验证码发送失败,请重试'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
async function handleReset() { |
|
|
|
const form = unref(formRef); |
|
|
|
if (!form) return; |
|
|
|
await form.resetFields(); |
|
|
|
const data = await validForm(); |
|
|
|
if (!data) return; |
|
|
|
|
|
|
|
// 验证密码确认 |
|
|
|
if (formData.password !== formData.confirmPassword) { |
|
|
|
message.error('两次输入的密码不一致'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
loading.value = true; |
|
|
|
try { |
|
|
|
const res = await resetPasswordApi({ |
|
|
|
username: formData.account, |
|
|
|
password: formData.password, |
|
|
|
mobile: formData.mobile, |
|
|
|
code: formData.sms, |
|
|
|
uuid: formData.mobile, // 使用手机号作为uuid,用于短信验证码验证 |
|
|
|
tenantId: formData.tenantId, |
|
|
|
}); |
|
|
|
console.log(res); |
|
|
|
message.success('密码重置成功!'); |
|
|
|
// 重置成功后跳转到登录页面 |
|
|
|
handleBackLogin(); |
|
|
|
} catch (error) { |
|
|
|
console.error('密码重置失败:', error); |
|
|
|
message.error('密码重置失败,请重试'); |
|
|
|
} finally { |
|
|
|
loading.value = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
// 初始化租户选择 |
|
|
|
await tenantSelectInit(); |
|
|
|
}); |
|
|
|
</script> |
|
|
|