|
@@ -0,0 +1,322 @@
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
|
|
+import { useUserStore } from '@/stores/modules/user'
|
|
|
|
|
+
|
|
|
|
|
+const router = useRouter()
|
|
|
|
|
+const loginForm = ref({
|
|
|
|
|
+ username: 'ra.admin',
|
|
|
|
|
+ oldPassword: 'abc123456789',
|
|
|
|
|
+ newPassword: '',
|
|
|
|
|
+ confirmPassword: ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const loginError: any = ref({
|
|
|
|
|
+ oldPassword: false,
|
|
|
|
|
+ newPassword: false,
|
|
|
|
|
+ confirmPassword: false
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const userStore = useUserStore()
|
|
|
|
|
+
|
|
|
|
|
+// 点击登录按钮
|
|
|
|
|
+const handleChangePwd = () => {
|
|
|
|
|
+ $api
|
|
|
|
|
+ .login({
|
|
|
|
|
+ uname: loginForm.value.username,
|
|
|
|
|
+ old_password: loginForm.value.oldPassword,
|
|
|
|
|
+ password: loginForm.value.newPassword
|
|
|
|
|
+ })
|
|
|
|
|
+ .then((res: any) => {
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ const { data } = res
|
|
|
|
|
+ if (data.msg === 'today') {
|
|
|
|
|
+ ElMessageBox.alert('Your password will expire today, please reset', 'Prompt', {
|
|
|
|
|
+ confirmButtonText: 'OK',
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ confirmButtonClass: 'el-button--dark'
|
|
|
|
|
+ })
|
|
|
|
|
+ } else if (data.msg === 'last') {
|
|
|
|
|
+ ElMessageBox.alert(
|
|
|
|
|
+ `Your password will expire in${data.data}days, please reset`,
|
|
|
|
|
+ 'Prompt',
|
|
|
|
|
+ {
|
|
|
|
|
+ confirmButtonText: 'OK',
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ confirmButtonClass: 'el-button--dark'
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ userStore.setUsername(res.data.uname || '')
|
|
|
|
|
+ router.push('/')
|
|
|
|
|
+ } else if (res.code === 400) {
|
|
|
|
|
+ // 验证码错误
|
|
|
|
|
+ if (res.data.msg === 'password_error') {
|
|
|
|
|
+ loginError.value.password = true
|
|
|
|
|
+ } else if (res.data.msg === 'verifcation_error') {
|
|
|
|
|
+ loginError.value.code = true
|
|
|
|
|
+ } else if (res.data.msg === 'error_times') {
|
|
|
|
|
+ errorTipsRef.value.openDialog()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const confirmPwd = () => {
|
|
|
|
|
+ console.log('test')
|
|
|
|
|
+ if (loginForm.value.confirmPassword !== loginForm.value.newPassword) {
|
|
|
|
|
+ loginError.value.confirmPassword = true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ loginError.value.confirmPassword = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const isUserNameExit = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const emit = defineEmits<{
|
|
|
|
|
+ changeStatus: [string]
|
|
|
|
|
+}>()
|
|
|
|
|
+const handleForgot = () => {
|
|
|
|
|
+ emit('changeStatus', 'reset')
|
|
|
|
|
+}
|
|
|
|
|
+const handleBackLogin = () => {
|
|
|
|
|
+ emit('changeStatus', 'login')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const errorTipsRef = ref()
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<template>
|
|
|
|
|
+ <el-card class="login-card">
|
|
|
|
|
+ <div class="title">
|
|
|
|
|
+ <span class="welcome">Change Password</span>
|
|
|
|
|
+ <span class="tips">Password expired, please change your password.</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="login-form">
|
|
|
|
|
+ <div class="label">
|
|
|
|
|
+ <span>User Name</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-input :disabled="true" ref="userNameRef" v-model="loginForm.username" class="user-name">
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <span class="font_family icon-icon_username_b"></span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #suffix>
|
|
|
|
|
+ <span v-if="isUserNameExit" class="font_family icon-icon_confirm_b confirm-icon"></span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <div class="label">
|
|
|
|
|
+ <span>Old Password</span>
|
|
|
|
|
+ <span class="forgot-password" @click="handleForgot">Forgot Password?</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ ref="passWordRef"
|
|
|
|
|
+ :class="{ 'is-error': loginError.oldPassword }"
|
|
|
|
|
+ v-model="loginForm.oldPassword"
|
|
|
|
|
+ type="password"
|
|
|
|
|
+ placeholder="Please input password"
|
|
|
|
|
+ show-password
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <span class="font_family icon-icon_password_b"></span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <div class="error" v-if="loginError.oldPassword">Incorrect password. Please try again.</div>
|
|
|
|
|
+ <div class="label">
|
|
|
|
|
+ <span>New Password</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ ref="passWordRef"
|
|
|
|
|
+ :class="{ 'is-error': loginError.newPassword }"
|
|
|
|
|
+ v-model="loginForm.newPassword"
|
|
|
|
|
+ type="password"
|
|
|
|
|
+ placeholder="Please input password"
|
|
|
|
|
+ show-password
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <span class="font_family icon-icon_password_b"></span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <div class="error" v-if="loginError.newPassword">Incorrect password. Please try again.</div>
|
|
|
|
|
+ <div class="label">
|
|
|
|
|
+ <span>Confirm New Password</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ ref="passWordRef"
|
|
|
|
|
+ :class="{ 'is-error': loginError.confirmPassword }"
|
|
|
|
|
+ v-model="loginForm.confirmPassword"
|
|
|
|
|
+ type="password"
|
|
|
|
|
+ placeholder="Please input password"
|
|
|
|
|
+ show-password
|
|
|
|
|
+ @change="confirmPwd"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #prefix>
|
|
|
|
|
+ <span class="font_family icon-icon_password_b"></span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-input>
|
|
|
|
|
+ <div class="error" v-if="loginError.confirmPassword">
|
|
|
|
|
+ The password does not match. Please try again.
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <el-button @click="handleChangePwd" class="el-button--dark login-btn"
|
|
|
|
|
+ >Change Password</el-button
|
|
|
|
|
+ >
|
|
|
|
|
+ <div @click="handleBackLogin" class="back-text">
|
|
|
|
|
+ <span class="font_family icon-icon_back_b"></span>
|
|
|
|
|
+ <span class="text"> Back to login</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <template #footer>
|
|
|
|
|
+ <div class="license">
|
|
|
|
|
+ <span>© 2024 KTreker from <span class="company">Kerry Logistics</span></span>
|
|
|
|
|
+ <span>Version 0.67</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.login-card {
|
|
|
|
|
+ width: 400px;
|
|
|
|
|
+
|
|
|
|
|
+ .title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 24px;
|
|
|
|
|
+
|
|
|
|
|
+ .welcome {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ :deep(.el-card__body) {
|
|
|
|
|
+ padding: 40px;
|
|
|
|
|
+ padding-bottom: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .login-btn {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ margin-top: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.login-form {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+
|
|
|
|
|
+ .el-input {
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ .confirm-icon {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ height: 16px;
|
|
|
|
|
+ width: 16px;
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ background-color: var(--color-success);
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.is-error {
|
|
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
|
|
+ box-shadow: 0 0 0 1px var(--color-danger) inset;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ :deep(.el-input__prefix) {
|
|
|
|
|
+ margin: 0 4px;
|
|
|
|
|
+ background-color: transparent;
|
|
|
|
|
+ }
|
|
|
|
|
+ &.is-disabled {
|
|
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
|
|
+ background-color: #f4f4f4;
|
|
|
|
|
+ }
|
|
|
|
|
+ :deep(.el-input__inner) {
|
|
|
|
|
+ -webkit-text-fill-color: var(--color-neutral-1);
|
|
|
|
|
+ color: var(--color-neutral-1);
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .verification-code {
|
|
|
|
|
+ margin-top: 16px;
|
|
|
|
|
+ .verification-code-img {
|
|
|
|
|
+ width: 130px;
|
|
|
|
|
+ height: 38px;
|
|
|
|
|
+ object-fit: cover;
|
|
|
|
|
+ }
|
|
|
|
|
+ :deep(.el-input-group__append) {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+ padding-right: 1px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ .el-input.user-name {
|
|
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
|
|
+ padding-right: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .label {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ margin-top: 16px;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ line-height: 18px;
|
|
|
|
|
+
|
|
|
|
|
+ span {
|
|
|
|
|
+ color: var(--color-neutral-2);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .forgot-password {
|
|
|
|
|
+ color: var(--color-theme);
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .error {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: var(--color-danger);
|
|
|
|
|
+ line-height: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .back-text {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 20px;
|
|
|
|
|
+ margin-top: 24px;
|
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+
|
|
|
|
|
+ span {
|
|
|
|
|
+ color: var(--color-theme);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .text {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.license {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+
|
|
|
|
|
+ .company {
|
|
|
|
|
+ color: var(--color-theme);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ span {
|
|
|
|
|
+ color: var(--color-neutral-2);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|