diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 993d360f..7a82a00e 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,19 +1,14 @@
{
"recommendations": [
- "johnsoncodehk.volar",
"octref.vetur",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
- "DavidAnson.vscode-markdownlint",
"esbenp.prettier-vscode",
"mrmlnc.vscode-less",
"antfu.i18n-ally",
- "cpylua.language-postcss",
- "Orta.vscode-jest",
"antfu.iconify",
"mikestead.dotenv",
"bradlc.vscode-tailwindcss",
- "heybourn.headwind",
- "znck.vue-language-features"
+ "heybourn.headwind"
]
}
diff --git a/.vscode/i18n-ally-reviews.yml b/.vscode/i18n-ally-reviews.yml
new file mode 100644
index 00000000..0b288c1c
--- /dev/null
+++ b/.vscode/i18n-ally-reviews.yml
@@ -0,0 +1,5 @@
+# Review comments generated by i18n-ally. Please commit this file.
+
+reviews:
+ sys.login.autoLogin:
+ description: '1'
diff --git a/CHANGELOG.zh_CN.md b/CHANGELOG.zh_CN.md
index f962b89d..4fca970b 100644
--- a/CHANGELOG.zh_CN.md
+++ b/CHANGELOG.zh_CN.md
@@ -1,9 +1,14 @@
## Wip
+### ✨ Refactor
+
+- 登录页重构,新增注册页面/重置密码页面/手机登录/二维码登录
+
### ✨ Features
- 新增 `settingButtonPosition`配置项,用于配置`设置`按钮位置
- `modal`可以通过双击头部切换全屏
+- 新增`CountDownInput`组件
### ⚡ Performance Improvements
diff --git a/build/config/themeConfig.ts b/build/config/themeConfig.ts
index 44683f33..4b004af3 100644
--- a/build/config/themeConfig.ts
+++ b/build/config/themeConfig.ts
@@ -94,7 +94,7 @@ export function generateModifyVars() {
'disabled-color': 'rgba(0, 0, 0, 0.25)', // Failure color
'heading-color': 'rgba(0, 0, 0, 0.85)', // Title color
'text-color': 'rgba(0, 0, 0, 0.85)', // Main text color
- 'text-color-secondary ': 'rgba(0, 0, 0, 0.45)', // Subtext color
+ 'text-color-secondary': 'rgba(0, 0, 0, 0.45)', // Subtext color
'font-size-base': '14px', // Main font size
'box-shadow-base': '0 2px 8px rgba(0, 0, 0, 0.15)', // Floating shadow
'border-color-base': '#d9d9d9', // Border color,
diff --git a/package.json b/package.json
index dc721b14..93510ee9 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"vditor": "^3.8.1",
"vue": "^3.0.5",
"vue-i18n": "9.0.0-rc.2",
- "vue-router": "^4.0.3",
+ "vue-router": "^4.0.4",
"vue-types": "^3.0.2",
"vuex": "^4.0.0",
"vuex-module-decorators": "^1.0.1",
@@ -92,7 +92,7 @@
"pretty-quick": "^3.1.0",
"rimraf": "^3.0.2",
"rollup-plugin-visualizer": "^4.2.0",
- "stylelint": "^13.10.0",
+ "stylelint": "^13.11.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0",
"stylelint-order": "^4.1.0",
@@ -104,10 +104,10 @@
"vite-plugin-imagemin": "^0.2.6",
"vite-plugin-mock": "^2.1.4",
"vite-plugin-purge-icons": "^0.7.0",
- "vite-plugin-pwa": "^0.5.1",
- "vite-plugin-style-import": "^0.7.2",
+ "vite-plugin-pwa": "^0.5.2",
+ "vite-plugin-style-import": "^0.7.3",
"vite-plugin-theme": "^0.4.3",
- "vite-plugin-windicss": "0.3.12",
+ "vite-plugin-windicss": "0.4.3",
"vue-eslint-parser": "^7.5.0",
"yargs": "^16.2.0"
},
diff --git a/src/assets/images/login/login-bg.png b/src/assets/images/login/login-bg.png
deleted file mode 100644
index b773a245..00000000
Binary files a/src/assets/images/login/login-bg.png and /dev/null differ
diff --git a/src/assets/images/login/login-in.png b/src/assets/images/login/login-in.png
deleted file mode 100644
index 3a45b722..00000000
Binary files a/src/assets/images/login/login-in.png and /dev/null differ
diff --git a/src/assets/svg/login-bg.svg b/src/assets/svg/login-bg.svg
new file mode 100644
index 00000000..18cfd2db
--- /dev/null
+++ b/src/assets/svg/login-bg.svg
@@ -0,0 +1,17 @@
+
diff --git a/src/assets/svg/login-box-bg.svg b/src/assets/svg/login-box-bg.svg
new file mode 100644
index 00000000..ee7dbdc2
--- /dev/null
+++ b/src/assets/svg/login-box-bg.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/Application/src/AppLogo.vue b/src/components/Application/src/AppLogo.vue
index ee506e19..522b272d 100644
--- a/src/components/Application/src/AppLogo.vue
+++ b/src/components/Application/src/AppLogo.vue
@@ -10,8 +10,13 @@
>
{{ title }}
@@ -38,6 +43,7 @@
theme: propTypes.oneOf(['light', 'dark']),
// Whether to show title
showTitle: propTypes.bool.def(true),
+ alwaysShowTitle: propTypes.bool.def(false),
},
setup() {
const { prefixCls } = useDesign('app-logo');
diff --git a/src/components/CountDown/index.ts b/src/components/CountDown/index.ts
new file mode 100644
index 00000000..fdcbccf0
--- /dev/null
+++ b/src/components/CountDown/index.ts
@@ -0,0 +1,4 @@
+import CountButton from './src/CountButton.vue';
+import CountdownInput from './src/CountdownInput.vue';
+
+export { CountdownInput, CountButton };
diff --git a/src/components/CountDown/src/CountButton.vue b/src/components/CountDown/src/CountButton.vue
new file mode 100644
index 00000000..59c58393
--- /dev/null
+++ b/src/components/CountDown/src/CountButton.vue
@@ -0,0 +1,57 @@
+
+
+
+
diff --git a/src/components/CountDown/src/CountdownInput.vue b/src/components/CountDown/src/CountdownInput.vue
new file mode 100644
index 00000000..1a0f1167
--- /dev/null
+++ b/src/components/CountDown/src/CountdownInput.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
diff --git a/src/components/CountDown/src/useCountdown.ts b/src/components/CountDown/src/useCountdown.ts
new file mode 100644
index 00000000..f6ed67dc
--- /dev/null
+++ b/src/components/CountDown/src/useCountdown.ts
@@ -0,0 +1,51 @@
+import { ref, unref } from 'vue';
+import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
+
+export function useCountdown(count: number) {
+ const currentCount = ref(count);
+
+ const isStart = ref(false);
+
+ let timerId: ReturnType
| null;
+
+ function clear() {
+ timerId && window.clearInterval(timerId);
+ }
+
+ function stop() {
+ isStart.value = false;
+ timerId = null;
+ clear();
+ }
+
+ function start() {
+ if (unref(isStart) || !!timerId) {
+ return;
+ }
+ isStart.value = true;
+ timerId = setInterval(() => {
+ if (unref(currentCount) === 1) {
+ stop();
+ currentCount.value = count;
+ } else {
+ currentCount.value -= 1;
+ }
+ }, 1000);
+ }
+
+ function reset() {
+ currentCount.value = count;
+ stop();
+ }
+
+ function restart() {
+ reset();
+ start();
+ }
+
+ tryOnUnmounted(() => {
+ reset();
+ });
+
+ return { start, reset, restart, clear, stop, currentCount, isStart };
+}
diff --git a/src/components/StrengthMeter/src/index.vue b/src/components/StrengthMeter/src/index.vue
index 8265b2b1..1f98e372 100644
--- a/src/components/StrengthMeter/src/index.vue
+++ b/src/components/StrengthMeter/src/index.vue
@@ -1,5 +1,5 @@
-
+
{
const { disabled } = props;
- if (disabled) return null;
+ if (disabled) return -1;
const innerValue = unref(innerValueRef);
- const score = innerValue ? zxcvbn(unref(innerValueRef)).score : null;
+ const score = innerValue ? zxcvbn(unref(innerValueRef)).score : -1;
emit('score-change', score);
return score;
});
@@ -57,6 +56,7 @@
watchEffect(() => {
innerValueRef.value = props.value || '';
});
+
watch(
() => unref(innerValueRef),
(val) => {
@@ -77,14 +77,12 @@
@prefix-cls: ~'@{namespace}-strength-meter';
.@{prefix-cls} {
- position: relative;
-
&-bar {
position: relative;
- height: 4px;
+ height: 6px;
margin: 10px auto 6px;
background: @disabled-color;
- border-radius: 3px;
+ border-radius: 6px;
&::before,
&::after {
diff --git a/src/design/ant/index.less b/src/design/ant/index.less
index 6b5a132e..9483cc72 100644
--- a/src/design/ant/index.less
+++ b/src/design/ant/index.less
@@ -13,10 +13,8 @@
}
}
-body {
- .anticon:not(.app-iconify) {
- vertical-align: 0.1em;
- }
+span.anticon:not(.app-iconify) {
+ vertical-align: 0.125em;
}
.ant-back-top {
diff --git a/src/design/var/breakpoint.less b/src/design/var/breakpoint.less
index a38617a7..cc6af9ec 100644
--- a/src/design/var/breakpoint.less
+++ b/src/design/var/breakpoint.less
@@ -2,37 +2,17 @@
// ==============屏幕断点============
// =================================
-// Extra small screen / phone
-@screen-xs: 480px;
-@screen-xs-min: @screen-xs;
-
// Small screen / tablet
-@screen-sm: 576px;
-@screen-sm-min: @screen-sm;
+@screen-sm: 640px;
// Medium screen / desktop
@screen-md: 768px;
-@screen-md-min: @screen-md;
// Large screen / wide desktop
-@screen-lg: 992px;
-@screen-lg-min: @screen-lg;
+@screen-lg: 1024px;
// Extra large screen / full hd
-@screen-xl: 1200px;
-@screen-xl-min: @screen-xl;
+@screen-xl: 1280px;
// Extra extra large screen / large desktop
-@screen-xxl: 1600px;
-@screen-xxl-min: @screen-xxl;
-
-@screen-xxxl: 1900px;
-@screen-xxxl-min: @screen-xxxl;
-
-// provide a maximum
-@screen-xs-max: (@screen-sm-min - 1px);
-@screen-sm-max: (@screen-md-min - 1px);
-@screen-md-max: (@screen-lg-min - 1px);
-@screen-lg-max: (@screen-xl-min - 1px);
-@screen-xl-max: (@screen-xxl-min - 1px);
-@screen-xxl-max: (@screen-xxxl-min - 1px);
+@screen-2xl: 1536px;
diff --git a/src/layouts/default/header/components/user-dropdown/index.vue b/src/layouts/default/header/components/user-dropdown/index.vue
index d00d1ecc..dfa3d0d1 100644
--- a/src/layouts/default/header/components/user-dropdown/index.vue
+++ b/src/layouts/default/header/components/user-dropdown/index.vue
@@ -3,7 +3,7 @@
- {{ getUserInfo.realName }}
+ {{ getUserInfo.realName }}
diff --git a/src/locales/lang/en/component/countdown.ts b/src/locales/lang/en/component/countdown.ts
new file mode 100644
index 00000000..4663ac75
--- /dev/null
+++ b/src/locales/lang/en/component/countdown.ts
@@ -0,0 +1,4 @@
+export default {
+ normalText: 'Get SMS code',
+ sendText: 'Reacquire in {0}s',
+};
diff --git a/src/locales/lang/en/sys/login.ts b/src/locales/lang/en/sys/login.ts
index 2a4e4856..33aaf845 100644
--- a/src/locales/lang/en/sys/login.ts
+++ b/src/locales/lang/en/sys/login.ts
@@ -1,13 +1,38 @@
export default {
- loginButton: 'Login',
- autoLogin: 'AutoLogin',
- forgetPassword: 'Forget Password',
+ backSignIn: 'Back sign in',
+ mobileSignInFormTitle: 'Mobile sign in',
+ qrSignInFormTitle: 'Qr code sign in',
+ signInFormTitle: 'Sign in',
+ signUpFormTitle: 'Sign up',
+ forgetFormTitle: 'Reset password',
+
+ signInTitle: 'Backstage management system',
+ signInDesc: 'Enter your personal details and get started!',
+ policy: 'I agree to the xxx Privacy Policy',
+ scanSign: `scanning the code to complete the login`,
+
+ loginButton: 'Sign in',
+ registerButton: 'Sign up',
+ rememberMe: 'Remember me',
+ forgetPassword: 'Forget Password?',
+ otherSignIn: 'Sign in with',
// notify
loginSuccessTitle: 'Login successful',
loginSuccessDesc: 'Welcome back',
// placeholder
- accountPlaceholder: 'Please input Username',
- passwordPlaceholder: 'Please input Password',
+ accountPlaceholder: 'Please input username',
+ passwordPlaceholder: 'Please input password',
+ smsPlaceholder: 'Please input sms code',
+ mobilePlaceholder: 'Please input mobile',
+ policyPlaceholder: 'Register after checking',
+ diffPwd: 'The two passwords are inconsistent',
+
+ userName: 'Username',
+ password: 'Password',
+ confirmPassword: 'Confirm Password',
+ email: 'Email',
+ smsCode: 'SMS code',
+ mobile: 'Mobile',
};
diff --git a/src/locales/lang/zh_CN/component/countdown.ts b/src/locales/lang/zh_CN/component/countdown.ts
new file mode 100644
index 00000000..c2cfcf87
--- /dev/null
+++ b/src/locales/lang/zh_CN/component/countdown.ts
@@ -0,0 +1,4 @@
+export default {
+ normalText: '获取验证码',
+ sendText: '{0}秒后重新获取',
+};
diff --git a/src/locales/lang/zh_CN/sys/login.ts b/src/locales/lang/zh_CN/sys/login.ts
index 4e24538d..8994109d 100644
--- a/src/locales/lang/zh_CN/sys/login.ts
+++ b/src/locales/lang/zh_CN/sys/login.ts
@@ -1,7 +1,21 @@
export default {
+ backSignIn: '返回',
+ signInFormTitle: '登录',
+ mobileSignInFormTitle: '手机登录',
+ qrSignInFormTitle: '二维码登录',
+ signUpFormTitle: '注册',
+ forgetFormTitle: '重置密码',
+
+ signInTitle: '开箱即用的中后台管理系统',
+ signInDesc: '输入您的个人详细信息开始使用!',
+ policy: '我同意xxx隐私政策',
+ scanSign: `扫码后点击"确认",即可完成登录`,
+
loginButton: '登录',
- autoLogin: '自动登录',
- forgetPassword: '忘记密码',
+ registerButton: '注册',
+ rememberMe: '记住我',
+ forgetPassword: '忘记密码?',
+ otherSignIn: '其他登录方式',
// notify
loginSuccessTitle: '登录成功',
@@ -10,4 +24,15 @@ export default {
// placeholder
accountPlaceholder: '请输入账号',
passwordPlaceholder: '请输入密码',
+ smsPlaceholder: '请输入验证码',
+ mobilePlaceholder: '请输入手机号码',
+ policyPlaceholder: '勾选后才能注册',
+ diffPwd: '两次输入密码不一致',
+
+ userName: '账号',
+ password: '密码',
+ confirmPassword: '确认密码',
+ email: '邮箱',
+ smsCode: '短信验证码',
+ mobile: '手机号码',
};
diff --git a/src/views/sys/lock/LockPage.vue b/src/views/sys/lock/LockPage.vue
index 0ca31e55..489a956d 100644
--- a/src/views/sys/lock/LockPage.vue
+++ b/src/views/sys/lock/LockPage.vue
@@ -1,37 +1,51 @@
-
-
+
+
{{ t('sys.lock.unlock') }}
-
-
- {{ hour }}
-
{{ meridiem }}
+
+
+ {{ hour }}
+
+ {{ meridiem }}
+
-
- {{ minute }}
+
+ {{ minute }}
-
+
{{ realName }}
-
-
+
+
{{ t('sys.lock.alert') }}
-
+
@@ -40,7 +54,7 @@
@@ -54,11 +68,11 @@
-
-
- {{ hour }}:{{ minute }}
{{ meridiem }}
+
+
+ {{ hour }}:{{ minute }} {{ meridiem }}
-
{{ year }}/{{ month }}/{{ day }} {{ week }}
+
{{ year }}/{{ month }}/{{ day }} {{ week }}
@@ -144,125 +158,54 @@
@prefix-cls: ~'@{namespace}-lock-page';
.@{prefix-cls} {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
z-index: @lock-page-z-index;
- display: flex;
- width: 100vw;
- height: 100vh;
- // background: rgba(23, 27, 41);
- background: #000;
- align-items: center;
- justify-content: center;
&__unlock {
- position: absolute;
- top: 0;
- left: 50%;
- display: flex;
- height: 50px;
- padding-top: 20px;
- font-size: 18px;
- color: #fff;
- cursor: pointer;
transform: translate(-50%, 0);
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
- transition: all 0.3s;
- }
-
- &__date {
- display: flex;
- width: 100vw;
- height: 100vh;
- align-items: center;
- justify-content: center;
- }
-
- &__hour {
- position: relative;
- margin-right: 80px;
-
- .meridiem {
- position: absolute;
- top: 20px;
- left: 20px;
- font-size: 26px;
- }
- @media (max-width: @screen-xs) {
- margin-right: 20px;
- }
}
&__hour,
&__minute {
display: flex;
- width: 40%;
- height: 74%;
font-weight: 700;
color: #bababa;
background: #141313;
border-radius: 30px;
justify-content: center;
align-items: center;
- @media (min-width: @screen-xxxl-min) {
- font-size: 46em;
- }
- @media (min-width: @screen-xl-max) and (max-width: @screen-xxl-max) {
- font-size: 38em;
- }
- @media (min-width: @screen-lg-max) and (max-width: @screen-xl-max) {
- font-size: 30em;
- }
- @media (min-width: @screen-md-max) and (max-width: @screen-lg-max) {
- font-size: 23em;
- }
- @media (min-width: @screen-sm-max) and (max-width: @screen-md-max) {
- height: 50%;
- font-size: 12em;
- border-radius: 10px;
-
- .meridiem {
- font-size: 20px;
- }
- }
- @media (min-width: @screen-xs-max) and (max-width: @screen-sm-max) {
- font-size: 13em;
- }
- @media (max-width: @screen-xs) {
- height: 30%;
- font-size: 5em;
- border-radius: 10px;
-
- .meridiem {
- font-size: 14px;
- }
- }
- }
-
- &__footer-date {
- position: absolute;
- bottom: 20px;
- width: 100%;
- font-family: helvetica;
- color: #bababa;
- text-align: center;
-
- .time {
- font-size: 50px;
-
- .meridiem {
- font-size: 32px;
+ @media screen and (max-width: @screen-md) {
+ span:not(.meridiem) {
+ font-size: 160px;
}
}
- .date {
- font-size: 26px;
+ @media screen and (min-width: @screen-md) {
+ span:not(.meridiem) {
+ font-size: 160px;
+ }
+ }
+
+ @media screen and (max-width: @screen-sm) {
+ span:not(.meridiem) {
+ font-size: 90px;
+ }
+ }
+ @media screen and (min-width: @screen-lg) {
+ span:not(.meridiem) {
+ font-size: 220px;
+ }
+ }
+
+ @media screen and (min-width: @screen-xl) {
+ span:not(.meridiem) {
+ font-size: 260px;
+ }
+ }
+ @media screen and (min-width: @screen-2xl) {
+ span:not(.meridiem) {
+ font-size: 320px;
+ }
}
}
diff --git a/src/views/sys/login/ForgetPasswordForm.vue b/src/views/sys/login/ForgetPasswordForm.vue
new file mode 100644
index 00000000..be65f63d
--- /dev/null
+++ b/src/views/sys/login/ForgetPasswordForm.vue
@@ -0,0 +1,90 @@
+
+
+
+
diff --git a/src/views/sys/login/Login.vue b/src/views/sys/login/Login.vue
index c310f09e..5452c859 100644
--- a/src/views/sys/login/Login.vue
+++ b/src/views/sys/login/Login.vue
@@ -1,228 +1,179 @@
-