Browse Source

feat: Add register and login page with TDesign. (#86)

tags/v0.1.0
Asklv GitHub 3 years ago
parent
commit
efb3af925e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 4553 additions and 535 deletions
  1. BIN
      assets/logo/favicon.ico
  2. +0
    -1
      web/.eslintignore
  3. +4
    -0
      web/index.html
  4. +2321
    -520
      web/package-lock.json
  5. +2
    -0
      web/package.json
  6. BIN
      web/public/favicon.ico
  7. +1229
    -0
      web/src/assets/openkf-logo.svg
  8. +4
    -1
      web/src/main.ts
  9. +8
    -2
      web/src/router/index.ts
  10. +3
    -0
      web/src/style/index.less
  11. +69
    -0
      web/src/style/reset.less
  12. +423
    -0
      web/src/style/theme.css
  13. +74
    -0
      web/src/views/login/components/Header.vue
  14. +102
    -0
      web/src/views/login/components/Login.vue
  15. +150
    -0
      web/src/views/login/components/Register.vue
  16. +126
    -0
      web/src/views/login/index.less
  17. +33
    -10
      web/src/views/login/index.vue
  18. +5
    -1
      web/vite.config.ts

BIN
assets/logo/favicon.ico View File

Before After
Width: 300  |  Height: 300  |  Size: 64 kB

+ 0
- 1
web/.eslintignore View File

@@ -1,3 +1,2 @@
// .eslintignore 配置, 防止校验打包的产物
dist
node_modules

+ 4
- 0
web/index.html View File

@@ -26,4 +26,8 @@
<script src="/wasm_exec.js"></script>
<script type="module" src="/src/main.ts"></script>
</body>

<script>
window.global = window;
</script>
</html>

+ 2321
- 520
web/package-lock.json
File diff suppressed because it is too large
View File


+ 2
- 0
web/package.json View File

@@ -12,8 +12,10 @@
"dependencies": {
"axios": "^1.4.0",
"echarts": "^5.4.2",
"less-loader": "^11.1.3",
"open-im-sdk-wasm": "^0.1.1",
"tdesign-vue-next": "^1.3.10",
"vite-svg-loader": "^4.0.0",
"vue": "^3.3.4",
"vue-router": "^4.2.2"
},


BIN
web/public/favicon.ico View File

Before After
Width: 300  |  Height: 300  |  Size: 64 kB

+ 1229
- 0
web/src/assets/openkf-logo.svg
File diff suppressed because it is too large
View File


+ 4
- 1
web/src/main.ts View File

@@ -18,6 +18,9 @@ import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios';
import router from './router';
import TDesign from 'tdesign-vue-next';
import 'tdesign-vue-next/es/style/index.css';
import './style/index.less';

import { getSDK } from '@/utils/open-im-sdk-wasm';

@@ -26,4 +29,4 @@ console.log(OpenIM);

const app = createApp(App);
app.config.globalProperties.$https = axios; // use axios
app.use(router).mount('#app'); // mount the router on the app
app.use(router).use(TDesign).mount('#app'); // mount the router on the app

+ 8
- 2
web/src/router/index.ts View File

@@ -15,9 +15,15 @@
*/

import { createRouter, createWebHistory } from 'vue-router';
import Login from '@/views/login/index.vue';
// router options
const routes = [{ path: '/login', name: 'Login', component: Login }];
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/index.vue')
}
];

// create router
const router = createRouter({


+ 3
- 0
web/src/style/index.less View File

@@ -0,0 +1,3 @@
@import './theme.css';

@import './reset.less';

+ 69
- 0
web/src/style/reset.less View File

@@ -0,0 +1,69 @@
body {
color: var(--td-text-color-secondary);
font-family: -apple-system, BlinkMacSystemFont, var(--td-font-family);
font: var(--td-font-body-medium);
-webkit-font-smoothing: antialiased;
padding: 0;
margin: 0;
}

pre {
font-family: var(--td-font-family);
}

ul,
dl,
li,
dd,
dt {
margin: 0;
padding: 0;
list-style: none;
}

figure,
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin: 0;
}

* {
box-sizing: border-box;
}

.t-button-link,
a {
color: var(--td-brand-color);
text-decoration: none;
cursor: pointer;
// transition: color @anim-duration-base @anim-time-fn-easing; // DISABLED: Can not find these variables

&:hover {
color: var(--td-brand-color-hover);
}

&:active {
color: var(--td-brand-color-active);
}

&--active {
color: var(--td-brand-color-active);
}

&:focus {
text-decoration: none;
}
}

.t-button-link {
margin-right: var(--td-comp-margin-xxl);

&:last-child {
margin-right: 0;
}
}

+ 423
- 0
web/src/style/theme.css View File

@@ -0,0 +1,423 @@
:root,:root[theme-mode="light"] {
--brand-main: var(--td-brand-color-5);
--td-brand-color-light: var(--td-brand-color-1);
--td-brand-color-focus: var(--td-brand-color-2);
--td-brand-color-disabled: var(--td-brand-color-3);
--td-brand-color-hover: var(--td-brand-color-4);
--td-brand-color: var(--td-brand-color-5);
--td-brand-color-active: var(--td-brand-color-6);
--td-brand-color-1: #e3f9e9;
--td-brand-color-2: #c6f3d7;
--td-brand-color-3: #92dab2;
--td-brand-color-4: #56c08d;
--td-brand-color-5: #2ba471; /* base */
--td-brand-color-6: #008858;
--td-brand-color-7: #006c45;
--td-brand-color-8: #005334;
--td-brand-color-9: #003b23;
--td-brand-color-10: #002515;
--td-warning-color-1: #fef3e6;
--td-warning-color-2: #f9e0c7;
--td-warning-color-3: #f7c797;
--td-warning-color-4: #f2995f;
--td-warning-color-5: #ed7b2f;
--td-warning-color-6: #d35a21;
--td-warning-color-7: #ba431b;
--td-warning-color-8: #9e3610;
--td-warning-color-9: #842b0b;
--td-warning-color-10: #5a1907;
--td-warning-color: var(--td-warning-color-5);
--td-warning-color-hover: var(--td-warning-color-4);
--td-warning-color-focus: var(--td-warning-color-2);
--td-warning-color-active: var(--td-warning-color-6);
--td-warning-color-disabled: var(--td-warning-color-3);
--td-warning-color-light: var(--td-warning-color-1);
--td-error-color-1: #fdecee;
--td-error-color-2: #f9d7d9;
--td-error-color-3: #f8b9be;
--td-error-color-4: #f78d94;
--td-error-color-5: #f36d78;
--td-error-color-6: #e34d59;
--td-error-color-7: #c9353f;
--td-error-color-8: #b11f26;
--td-error-color-9: #951114;
--td-error-color-10: #680506;
--td-error-color: var(--td-error-color-6);
--td-error-color-hover: var(--td-error-color-5);
--td-error-color-focus: var(--td-error-color-2);
--td-error-color-active: var(--td-error-color-7);
--td-error-color-disabled: var(--td-error-color-3);
--td-error-color-light: var(--td-error-color-1);
--td-success-color-1: #e8f8f2;
--td-success-color-2: #bcebdc;
--td-success-color-3: #85dbbe;
--td-success-color-4: #48c79c;
--td-success-color-5: #00a870;
--td-success-color-6: #078d5c;
--td-success-color-7: #067945;
--td-success-color-8: #056334;
--td-success-color-9: #044f2a;
--td-success-color-10: #033017;
--td-success-color: var(--td-success-color-5);
--td-success-color-hover: var(--td-success-color-4);
--td-success-color-focus: var(--td-success-color-2);
--td-success-color-active: var(--td-success-color-6);
--td-success-color-disabled: var(--td-success-color-3);
--td-success-color-light: var(--td-success-color-1);
--td-gray-color-1: #f3f3f3;
--td-gray-color-2: #eee;
--td-gray-color-3: #e7e7e7;
--td-gray-color-4: #dcdcdc;
--td-gray-color-5: #c5c5c5;
--td-gray-color-6: #a6a6a6;
--td-gray-color-7: #8b8b8b;
--td-gray-color-8: #777;
--td-gray-color-9: #5e5e5e;
--td-gray-color-10: #4b4b4b;
--td-gray-color-11: #383838;
--td-gray-color-12: #2c2c2c;
--td-gray-color-13: #242424;
--td-gray-color-14: #181818;
--td-bg-color-container: #fff;
--td-bg-color-container-select: #fff;
--td-bg-color-page: var(--td-gray-color-2);
--td-bg-color-container-hover: var(--td-gray-color-1);
--td-bg-color-container-active: var(--td-gray-color-3);
--td-bg-color-secondarycontainer: var(--td-gray-color-1);
--td-bg-color-secondarycontainer-hover: var(--td-gray-color-2);
--td-bg-color-secondarycontainer-active: var(--td-gray-color-4);
--td-bg-color-component: var(--td-gray-color-3);
--td-bg-color-component-hover: var(--td-gray-color-4);
--td-bg-color-component-active: var(--td-gray-color-6);
--td-bg-color-component-disabled: var(--td-gray-color-2);
--td-component-stroke: var(--td-gray-color-3);
--td-component-border: var(--td-gray-color-4);
--td-font-white-1: #ffffff;
--td-font-white-2: rgba(255, 255, 255, 0.55);
--td-font-white-3: rgba(255, 255, 255, 0.35);
--td-font-white-4: rgba(255, 255, 255, 0.22);
--td-font-gray-1: rgba(0, 0, 0, 0.9);
--td-font-gray-2: rgba(0, 0, 0, 0.6);
--td-font-gray-3: rgba(0, 0, 0, 0.4);
--td-font-gray-4: rgba(0, 0, 0, 0.26);
--td-font-family: PingFang SC, Microsoft YaHei, Arial Regular;
--td-font-family-medium: PingFang SC, Microsoft YaHei, Arial Medium;
--td-font-size-link-small: 12px;
--td-font-size-link-medium: 14px;
--td-font-size-link-large: 16px;
--td-font-size-mark-small: 12px;
--td-font-size-mark-medium: 14px;
--td-font-size-body-small: 12px;
--td-font-size-body-medium: 14px;
--td-font-size-body-large: 16px;
--td-font-size-title-small: 14px;
--td-font-size-title-medium: 16px;
--td-font-size-title-large: 20px;
--td-font-size-headline-small: 24px;
--td-font-size-headline-medium: 28px;
--td-font-size-headline-large: 36px;
--td-font-size-display-medium: 48px;
--td-font-size-display-large: 64px;
--td-line-height-common: 8px;
--td-line-height-link-small: calc( var(--td-font-size-link-small) + var(--td-line-height-common) );
--td-line-height-link-medium: calc( var(--td-font-size-link-medium) + var(--td-line-height-common) );
--td-line-height-link-large: calc( var(--td-font-size-link-large) + var(--td-line-height-common) );
--td-line-height-mark-small: calc( var(--td-font-size-mark-small) + var(--td-line-height-common) );
--td-line-height-mark-medium: calc( var(--td-font-size-mark-medium) + var(--td-line-height-common) );
--td-line-height-body-small: calc( var(--td-font-size-body-small) + var(--td-line-height-common) );
--td-line-height-body-medium: calc( var(--td-font-size-body-medium) + var(--td-line-height-common) );
--td-line-height-body-large: calc( var(--td-font-size-body-large) + var(--td-line-height-common) );
--td-line-height-title-small: calc( var(--td-font-size-title-small) + var(--td-line-height-common) );
--td-line-height-title-medium: calc( var(--td-font-size-title-medium) + var(--td-line-height-common) );
--td-line-height-title-large: calc( var(--td-font-size-title-medium) + var(--td-line-height-common) );
--td-line-height-headline-small: calc( var(--td-font-size-headline-small) + var(--td-line-height-common) );
--td-line-height-headline-medium: calc( var(--td-font-size-headline-medium) + var(--td-line-height-common) );
--td-line-height-headline-large: calc( var(--td-font-size-headline-large) + var(--td-line-height-common) );
--td-line-height-display-medium: calc( var(--td-font-size-display-medium) + var(--td-line-height-common) );
--td-line-height-display-large: calc( var(--td-font-size-display-large) + var(--td-line-height-common) );
--td-font-link-small: var(--td-font-size-link-small) / var(--td-line-height-link-small) var(--td-font-family);
--td-font-link-medium: var(--td-font-size-link-medium) / var(--td-line-height-link-medium) var(--td-font-family);
--td-font-link-large: var(--td-font-size-link-large) / var(--td-line-height-link-large) var(--td-font-family);
--td-font-mark-small: 600 var(--td-font-size-mark-small) / var(--td-line-height-mark-small) var(--td-font-family);
--td-font-mark-medium: 600 var(--td-font-size-mark-medium) / var(--td-line-height-mark-medium) var(--td-font-family);
--td-font-body-small: var(--td-font-size-body-small) / var(--td-line-height-body-small) var(--td-font-family);
--td-font-body-medium: var(--td-font-size-body-medium) / var(--td-line-height-body-medium) var(--td-font-family);
--td-font-body-large: var(--td-font-size-body-large) / var(--td-line-height-body-large) var(--td-font-family);
--td-font-title-small: var(--td-font-size-title-small) / var(--td-line-height-title-small) var(--td-font-family);
--td-font-title-medium: var(--td-font-size-title-medium) / var(--td-line-height-title-medium) var(--td-font-family);
--td-font-title-large: var(--td-font-size-title-large) / var(--td-line-height-title-large) var(--td-font-family);
--td-font-headline-small: var(--td-font-size-headline-small) / var(--td-line-height-headline-small) var(--td-font-family);
--td-font-headline-medium: var(--td-font-size-headline-medium) / var(--td-line-height-headline-medium) var(--td-font-family);
--td-font-headline-large: var(--td-font-size-headline-large) / var(--td-line-height-headline-large) var(--td-font-family);
--td-font-display-medium: var(--td-font-size-display-medium) / var(--td-line-height-display-medium) var(--td-font-family);
--td-font-display-large: var(--td-font-size-display-large) / var(--td-line-height-display-large) var(--td-font-family);
--td-text-color-primary: var(--td-font-gray-1);
--td-text-color-secondary: var(--td-font-gray-2);
--td-text-color-placeholder: var(--td-font-gray-3);
--td-text-color-disabled: var(--td-font-gray-4);
--td-text-color-anti: #fff;
--td-text-color-brand: var(--td-brand-color);
--td-text-color-link: var(--td-brand-color);
--td-radius-small: 2px;
--td-radius-default: 3px;
--td-radius-medium: 6px;
--td-radius-large: 9px;
--td-radius-extraLarge: 12px;
--td-radius-round: 999px;
--td-radius-circle: 50%;
--td-shadow-1: 0 1px 10px rgba(0, 0, 0, 0.05), 0 4px 5px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.12);
--td-shadow-2: 0 3px 14px 2px rgba(0, 0, 0, 0.05), 0 8px 10px 1px rgba(0, 0, 0, 0.06), 0 5px 5px -3px rgba(0, 0, 0, 0.1);
--td-shadow-3: 0 6px 30px 5px rgba(0, 0, 0, 0.05), 0 16px 24px 2px rgba(0, 0, 0, 0.04), 0 8px 10px -5px rgba(0, 0, 0, 0.08);
--td-size-1: 2px;
--td-size-2: 4px;
--td-size-3: 6px;
--td-size-4: 8px;
--td-size-5: 12px;
--td-size-6: 16px;
--td-size-7: 20px;
--td-size-8: 24px;
--td-size-9: 28px;
--td-size-10: 32px;
--td-size-11: 36px;
--td-size-12: 40px;
--td-size-13: 48px;
--td-size-14: 56px;
--td-size-15: 64px;
--td-size-16: 72px;
--td-comp-size-xxxs: var(--td-size-6);
--td-comp-size-xxs: var(--td-size-7);
--td-comp-size-xs: var(--td-size-8);
--td-comp-size-s: var(--td-size-9);
--td-comp-size-m: var(--td-size-10);
--td-comp-size-l: var(--td-size-11);
--td-comp-size-xl: var(--td-size-12);
--td-comp-size-xxl: var(--td-size-13);
--td-comp-size-xxxl: var(--td-size-14);
--td-comp-size-xxxxl: var(--td-size-15);
--td-comp-size-xxxxxl: var(--td-size-16);
--td-pop-padding-s: var(--td-size-2);
--td-pop-padding-m: var(--td-size-3);
--td-pop-padding-l: var(--td-size-4);
--td-pop-padding-xl: var(--td-size-5);
--td-pop-padding-xxl: var(--td-size-6);
--td-comp-paddingLR-xxs: var(--td-size-1);
--td-comp-paddingLR-xs: var(--td-size-2);
--td-comp-paddingLR-s: var(--td-size-4);
--td-comp-paddingLR-m: var(--td-size-5);
--td-comp-paddingLR-l: var(--td-size-6);
--td-comp-paddingLR-xl: var(--td-size-8);
--td-comp-paddingLR-xxl: var(--td-size-10);
--td-comp-paddingTB-xxs: var(--td-size-1);
--td-comp-paddingTB-xs: var(--td-size-2);
--td-comp-paddingTB-s: var(--td-size-4);
--td-comp-paddingTB-m: var(--td-size-5);
--td-comp-paddingTB-l: var(--td-size-6);
--td-comp-paddingTB-xl: var(--td-size-8);
--td-comp-paddingTB-xxl: var(--td-size-10);
--td-comp-margin-xxs: var(--td-size-1);
--td-comp-margin-xs: var(--td-size-2);
--td-comp-margin-s: var(--td-size-4);
--td-comp-margin-m: var(--td-size-5);
--td-comp-margin-l: var(--td-size-6);
--td-comp-margin-xl: var(--td-size-7);
--td-comp-margin-xxl: var(--td-size-8);
--td-comp-margin-xxxl: var(--td-size-10);
--td-comp-margin-xxxxl: var(--td-size-12);
}

:root[theme-mode="dark"] {
--brand-main: var(--td-brand-color-6);
--td-brand-color-light: var(--td-brand-color-1);
--td-brand-color-focus: var(--td-brand-color-2);
--td-brand-color-disabled: var(--td-brand-color-3);
--td-brand-color-hover: var(--td-brand-color-5);
--td-brand-color: var(--td-brand-color-6);
--td-brand-color-active: var(--td-brand-color-7);
--td-brand-color-1: #2ba47120;
--td-brand-color-2: #003b23;
--td-brand-color-3: #005334;
--td-brand-color-4: #006c45;
--td-brand-color-5: #008858;
--td-brand-color-6: #2ba471;
--td-brand-color-7: #56c08d;
--td-brand-color-8: #92dab2;
--td-brand-color-9: #c6f3d7;
--td-brand-color-10: #e3f9e9;
--td-warning-color-1: #4f2a1d;
--td-warning-color-2: #582f21;
--td-warning-color-3: #733c23;
--td-warning-color-4: #a75d2b;
--td-warning-color-5: #cf6e2d;
--td-warning-color-6: #dc7633;
--td-warning-color-7: #e8935c;
--td-warning-color-8: #ecbf91;
--td-warning-color-9: #eed7bf;
--td-warning-color-10: #f3e9dc;
--td-error-color-1: #472324;
--td-error-color-2: #5e2a2d;
--td-error-color-3: #703439;
--td-error-color-4: #83383e;
--td-error-color-5: #a03f46;
--td-error-color-6: #c64751;
--td-error-color-7: #de6670;
--td-error-color-8: #ec888e;
--td-error-color-9: #edb1b6;
--td-error-color-10: #eeced0;
--td-success-color-1: #193a2a;
--td-success-color-2: #1a4230;
--td-success-color-3: #17533d;
--td-success-color-4: #0d7a55;
--td-success-color-5: #059465;
--td-success-color-6: #43af8a;
--td-success-color-7: #46bf96;
--td-success-color-8: #80d2b6;
--td-success-color-9: #b4e1d3;
--td-success-color-10: #deede8;
--td-gray-color-1: #f3f3f3;
--td-gray-color-2: #eee;
--td-gray-color-3: #e7e7e7;
--td-gray-color-4: #dcdcdc;
--td-gray-color-5: #c5c5c5;
--td-gray-color-6: #a6a6a6;
--td-gray-color-7: #8b8b8b;
--td-gray-color-8: #777;
--td-gray-color-9: #5e5e5e;
--td-gray-color-10: #4b4b4b;
--td-gray-color-11: #383838;
--td-gray-color-12: #2c2c2c;
--td-gray-color-13: #242424;
--td-gray-color-14: #181818;
--td-bg-color-page: var(--td-gray-color-14);
--td-bg-color-container: var(--td-gray-color-13);
--td-bg-color-container-hover: var(--td-gray-color-12);
--td-bg-color-container-active: var(--td-gray-color-10);
--td-bg-color-container-select: var(--td-gray-color-9);
--td-bg-color-secondarycontainer: var(--td-gray-color-12);
--td-bg-color-secondarycontainer-hover: var(--td-gray-color-11);
--td-bg-color-secondarycontainer-active: var(--td-gray-color-9);
--td-bg-color-component: var(--td-gray-color-11);
--td-bg-color-component-hover: var(--td-gray-color-10);
--td-bg-color-component-active: var(--td-gray-color-9);
--td-bg-color-component-disabled: var(--td-gray-color-12);
--td-component-stroke: var(--td-gray-color-11);
--td-component-border: var(--td-gray-color-9);
--td-font-white-1: rgba(255, 255, 255, 0.9);
--td-font-white-2: rgba(255, 255, 255, 0.55);
--td-font-white-3: rgba(255, 255, 255, 0.35);
--td-font-white-4: rgba(255, 255, 255, 0.22);
--td-font-gray-1: rgba(0, 0, 0, 0.9);
--td-font-gray-2: rgba(0, 0, 0, 0.6);
--td-font-gray-3: rgba(0, 0, 0, 0.4);
--td-font-gray-4: rgba(0, 0, 0, 0.26);
--td-gray-color-1: #f3f3f3;
--td-gray-color-2: #eee;
--td-gray-color-3: #e7e7e7;
--td-gray-color-4: #dcdcdc;
--td-gray-color-5: #c5c5c5;
--td-gray-color-6: #a6a6a6;
--td-gray-color-7: #8b8b8b;
--td-gray-color-8: #777;
--td-gray-color-9: #5e5e5e;
--td-gray-color-10: #4b4b4b;
--td-gray-color-11: #383838;
--td-gray-color-12: #2c2c2c;
--td-gray-color-13: #242424;
--td-gray-color-14: #181818;
--td-bg-color-page: var(--td-gray-color-14);
--td-bg-color-container: var(--td-gray-color-13);
--td-bg-color-container-hover: var(--td-gray-color-12);
--td-bg-color-container-active: var(--td-gray-color-10);
--td-bg-color-container-select: var(--td-gray-color-9);
--td-bg-color-secondarycontainer: var(--td-gray-color-12);
--td-bg-color-secondarycontainer-hover: var(--td-gray-color-11);
--td-bg-color-secondarycontainer-active: var(--td-gray-color-9);
--td-bg-color-component: var(--td-gray-color-11);
--td-bg-color-component-hover: var(--td-gray-color-10);
--td-bg-color-component-active: var(--td-gray-color-9);
--td-bg-color-secondarycomponent: var(--td-gray-color-10);
--td-bg-color-secondarycomponent-hover: var(--td-gray-color-9);
--td-bg-color-secondarycomponent-active: var(--td-gray-color-8);
--td-bg-color-component-disabled: var(--td-gray-color-12);
--td-component-stroke: var(--td-gray-color-11);
--td-component-border: var(--td-gray-color-9);
--td-font-white-1: rgba(255, 255, 255, 0.9);
--td-font-white-2: rgba(255, 255, 255, 0.55);
--td-font-white-3: rgba(255, 255, 255, 0.35);
--td-font-white-4: rgba(255, 255, 255, 0.22);
--td-font-gray-1: rgba(0, 0, 0, 0.9);
--td-font-gray-2: rgba(0, 0, 0, 0.6);
--td-font-gray-3: rgba(0, 0, 0, 0.4);
--td-font-gray-4: rgba(0, 0, 0, 0.26);
--td-text-color-primary: var(--td-font-white-1);
--td-text-color-secondary: var(--td-font-white-2);
--td-text-color-placeholder: var(--td-font-white-3);
--td-text-color-disabled: var(--td-font-white-4);
--td-text-color-anti: #fff;
--td-text-color-brand: var(--td-brand-color);
--td-text-color-link: var(--td-brand-color);
--td-radius-small: 2px;
--td-radius-default: 3px;
--td-radius-medium: 6px;
--td-radius-large: 9px;
--td-radius-extraLarge: 12px;
--td-radius-round: 999px;
--td-radius-circle: 50%;
--td-shadow-1: 0 1px 10px rgba(0, 0, 0, 0.05), 0 4px 5px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.12);
--td-shadow-2: 0 3px 14px 2px rgba(0, 0, 0, 0.05), 0 8px 10px 1px rgba(0, 0, 0, 0.06), 0 5px 5px -3px rgba(0, 0, 0, 0.1);
--td-shadow-3: 0 6px 30px 5px rgba(0, 0, 0, 0.05), 0 16px 24px 2px rgba(0, 0, 0, 0.04), 0 8px 10px -5px rgba(0, 0, 0, 0.08);
--td-size-1: 2px;
--td-size-2: 4px;
--td-size-3: 6px;
--td-size-4: 8px;
--td-size-5: 12px;
--td-size-6: 16px;
--td-size-7: 20px;
--td-size-8: 24px;
--td-size-9: 28px;
--td-size-10: 32px;
--td-size-11: 36px;
--td-size-12: 40px;
--td-size-13: 48px;
--td-size-14: 56px;
--td-size-15: 64px;
--td-size-16: 72px;
--td-comp-size-xxxs: var(--td-size-6);
--td-comp-size-xxs: var(--td-size-7);
--td-comp-size-xs: var(--td-size-8);
--td-comp-size-s: var(--td-size-9);
--td-comp-size-m: var(--td-size-10);
--td-comp-size-l: var(--td-size-11);
--td-comp-size-xl: var(--td-size-12);
--td-comp-size-xxl: var(--td-size-13);
--td-comp-size-xxxl: var(--td-size-14);
--td-comp-size-xxxxl: var(--td-size-15);
--td-comp-size-xxxxxl: var(--td-size-16);
--td-pop-padding-s: var(--td-size-2);
--td-pop-padding-m: var(--td-size-3);
--td-pop-padding-l: var(--td-size-4);
--td-pop-padding-xl: var(--td-size-5);
--td-pop-padding-xxl: var(--td-size-6);
--td-comp-paddingLR-xxs: var(--td-size-1);
--td-comp-paddingLR-xs: var(--td-size-2);
--td-comp-paddingLR-s: var(--td-size-4);
--td-comp-paddingLR-m: var(--td-size-5);
--td-comp-paddingLR-l: var(--td-size-6);
--td-comp-paddingLR-xl: var(--td-size-8);
--td-comp-paddingLR-xxl: var(--td-size-10);
--td-comp-paddingTB-xxs: var(--td-size-1);
--td-comp-paddingTB-xs: var(--td-size-2);
--td-comp-paddingTB-s: var(--td-size-4);
--td-comp-paddingTB-m: var(--td-size-5);
--td-comp-paddingTB-l: var(--td-size-6);
--td-comp-paddingTB-xl: var(--td-size-8);
--td-comp-paddingTB-xxl: var(--td-size-10);
--td-comp-margin-xxs: var(--td-size-1);
--td-comp-margin-xs: var(--td-size-2);
--td-comp-margin-s: var(--td-size-4);
--td-comp-margin-m: var(--td-size-5);
--td-comp-margin-l: var(--td-size-6);
--td-comp-margin-xl: var(--td-size-7);
--td-comp-margin-xxl: var(--td-size-8);
--td-comp-margin-xxxl: var(--td-size-10);
--td-comp-margin-xxxxl: var(--td-size-12);
}

+ 74
- 0
web/src/views/login/components/Header.vue View File

@@ -0,0 +1,74 @@
<script setup lang="ts">
import OpenKFLogo from '@/assets/openkf-logo.svg?component';

const navToGitHub = () => {
window.open('https://github.com/OpenIMSDK/OpenKF');
};

const navToDoc = () => {
window.open('https://openkf.github.io/website/');
};
</script>

<template>
<header class="login-header">
<div class="openkf-header">
<open-k-f-logo class="logo" />
<span class="title">OpenKF</span>
</div>
<div class="operations-container">
<t-button theme="default" shape="square" variant="text" @click="navToGitHub">
<t-icon name="logo-github-filled" class="icon" />
</t-button>
<t-button theme="default" shape="square" variant="text" @click="navToDoc">
<t-icon name="help-circle-filled" class="icon" />
</t-button>
<!-- Add theme tabs -->
</div>
</header>
</template>

<style lang="less" scoped>
.login-header {
padding: 0 var(--td-comp-paddingLR-xl);
display: flex;
justify-content: space-between;
align-items: center;
backdrop-filter: blur(20px);
color: var(--td-text-color-primary);
height: var(--td-comp-size-xxxl);

.openkf-header {
display: flex;
align-items: center;
height: var(--td-comp-size-xxxxxl);

.logo {
width: var(--td-comp-size-xxxxxl);
height: var(--td-comp-size-xxxxxl);
}

.title {
font: var(--td-font-title-large);
font-weight: 600;
color: var(--td-text-color-primary);
margin-top: var(--td-comp-margin-xs);
margin-left: var(--td-comp-margin-s);
&.margin-no {
margin-top: 0;
}
}
}


.operations-container {
display: flex;
align-items: center;
.t-button {
margin-left: var(--td-comp-margin-l);
}
}
}
</style>

+ 102
- 0
web/src/views/login/components/Login.vue View File

@@ -0,0 +1,102 @@
<script setup lang="ts">
import type { FormRule, SubmitContext } from 'tdesign-vue-next';
import { MessagePlugin } from 'tdesign-vue-next';
import { useRoute, useRouter } from 'vue-router';
import { ref } from 'vue';

const USER_INITIAL_DATA = {
email: '',
password: '',
};

const formData = ref({ ...USER_INITIAL_DATA });
const showPsw = ref(false);

const router = useRouter();
const route = useRoute();

const onSubmit = async (ctx: SubmitContext) => {
if (ctx.validateResult === true) {
try {

MessagePlugin.success('Login success...');
const redirect = route.query.redirect as string;
const redirectUrl = redirect ? decodeURIComponent(redirect) : '/dashboard';
router.push(redirectUrl);
} catch (e) {
console.log(e);
MessagePlugin.error(e.message);
}
}
};
</script>

<template>
<t-form
ref="form"
labelAlign="top"
:data="formData"
@submit="onSubmit"
:class="'item-container'"
>
<t-form-item name="admin_email">
<t-input v-model="formData.email" size="large" clearable placeholder="Please input your email" >
<template #prefix-icon>
<t-icon name="mail" />
</template>
</t-input>
</t-form-item>

<t-form-item name="admin_password">
<t-input
v-model="formData.password"
size="large"
:type="showPsw ? 'text' : 'password'"
clearable
placeholder="Please input your password" >
<template #prefix-icon>
<t-icon name="lock-on" />
</template>
</t-input>
</t-form-item>

<div class="check-container-login remember-pwd">
<!-- TODO: Add to localstorage -->
<t-checkbox>Remember me</t-checkbox>
<!-- TODO: Redirect to find my password page -->
<span class="tip">Find my password</span>
</div>

<t-row justify="space-between">
<t-col :span="4">
<!-- TODO: Disable unused method -->
<t-space size="1">
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="mail" /></template>
</t-button>
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="logo-github" /></template>
</t-button>
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="logo-wecom" /></template>
</t-button>

<template #separator>
<t-divider layout="vertical" />
</template>
</t-space>
</t-col>

<t-col :span="6">
<t-form-item>
<t-button block size="large" type="submit"> Login </t-button>
</t-form-item>
</t-col>
</t-row>

</t-form>
</template>

<style lang="less" scoped>
@import url('../index.less');
</style>

+ 150
- 0
web/src/views/login/components/Register.vue View File

@@ -0,0 +1,150 @@
<script setup lang="ts">
import type { FormRule, SubmitContext } from 'tdesign-vue-next';
import { MessagePlugin } from 'tdesign-vue-next';
import { ref } from 'vue';

const COMMUNITY_INITIAL_DATA = {
email: '',
name: '',
};

const ADMIN_INITIAL_DATA = {
email: '',
nickname: '',
password: '',
verifyCode: '',
checked: false,
};

const formData = ref({ community: COMMUNITY_INITIAL_DATA, admin: ADMIN_INITIAL_DATA });
const showPsw = ref(false);
const showCommunity = ref(true);
const countDown = ref(0);

const emit = defineEmits(['registerSuccess']);

const onSubmit = (ctx: SubmitContext) => {
if (ctx.validateResult === true) {
if (!formData.value.admin.checked) {
MessagePlugin.error('Please agree to the TDesign Service Agreement and TDesign Privacy Statement');
return;
}
MessagePlugin.success('Register success');
emit('registerSuccess');
}
};
</script>

<template>
<t-form
ref="form"
labelAlign="top"
:data="formData"
@submit="onSubmit"
:class="'item-container'"
>
<t-form-item name="community_email" v-show="showCommunity">
<t-input v-model="formData.community.email" size="large" clearable placeholder="Please input your community email" >
<template #prefix-icon>
<t-icon name="mail" />
</template>
</t-input>
</t-form-item>

<t-form-item name="community_name" v-show="showCommunity">
<t-input v-model="formData.community.name" size="large" clearable placeholder="Please input your community name" >
<template #prefix-icon>
<t-icon name="cloud" />
</template>
</t-input>
</t-form-item>

<t-form-item name="admin_email" v-show="!showCommunity">
<t-input v-model="formData.admin.email" size="large" clearable placeholder="Please input your email" >
<template #prefix-icon>
<t-icon name="mail" />
</template>
</t-input>
</t-form-item>

<t-form-item name="admin_nickname" v-show="!showCommunity">
<t-input v-model="formData.admin.nickname" size="large" clearable placeholder="Please input your nickname" >
<template #prefix-icon>
<t-icon name="user" />
</template>
</t-input>
</t-form-item>

<t-form-item name="admin_password" v-show="!showCommunity">
<t-input
v-model="formData.admin.password"
size="large"
:type="showPsw ? 'text' : 'password'"
clearable
placeholder="Please input your password" >
<template #prefix-icon>
<t-icon name="lock-on" />
</template>
</t-input>
</t-form-item>

<t-form-item class="verification-code" name="admin_verifyCode" v-show="!showCommunity">
<t-input v-model="formData.admin.verifyCode" size="large" clearable placeholder="Please input your verify code" >
<template #prefix-icon>
<t-icon name="discount" />
</template>
</t-input>
<t-button variant="outline" :disabled="countDown > 0">
<!-- TODO: Add count down. -->
{{ countDown == 0 ? 'Send Code' : `Resend in ${countDown}s` }}
</t-button>
</t-form-item>

<t-form-item class="check-container" name="admin_checked">
<t-checkbox v-model="formData.admin.checked"></t-checkbox>
<p>
I have read and agree to OpenKF <span>Service Agreement </span> and <span> Privacy Policy. </span>
</p>
</t-form-item>

<t-form-item v-show="!showCommunity">
<t-button block size="large" type="submit"> Register </t-button>
</t-form-item>

<t-row justify="space-between">
<t-col :span="4">
<!-- TODO: Disable unused method -->
<t-space size="1">
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="mail" /></template>
</t-button>
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="logo-github" /></template>
</t-button>
<t-button ghost shape="circle" theme="primary">
<template #icon><t-icon name="logo-wecom" /></template>
</t-button>

<template #separator>
<t-divider layout="vertical" />
</template>
</t-space>
</t-col>

<t-col :span="2">
<t-button ghost>
<!-- <t-button block size="large" type="submit"> -->
<template #default>
<span v-show="showCommunity" @click="showCommunity = false">Next</span>
<span v-show="!showCommunity" @click="showCommunity = true">Back</span>
</template>
</t-button>
</t-col>
</t-row>

</t-form>
</template>

<style lang="less" scoped>
@import url('../index.less');
</style>

+ 126
- 0
web/src/views/login/index.less View File

@@ -0,0 +1,126 @@
// TODO: Add style change.
.light {
&.login-wrapper {
background-color: white;
}
}

.dark {
&.login-wrapper {
background-color: var(--td-bg-color-page);
}
}

.title-container {
.title {
font: var(--td-font-headline-large);
color: var(--td-text-color-primary);
margin-top: var(--td-comp-margin-xs);

&.margin-no {
margin-top: 0;
}
}

.sub-title {
margin-top: var(--td-comp-margin-xxl);

.tip {
display: inline-block;
margin-right: var(--td-comp-margin-s);
font: var(--td-font-body-medium);
cursor: pointer;
}
}
}

.login-wrapper {
height: 100vh;
display: flex;
flex-direction: column;
background-size: cover;
background-position: 100%;
position: relative;
background-image: linear-gradient(to right, white 0%, white 10%, transparent 80%, transparent 100%), url('');
}

.login-container {
position: absolute;
top: 15%;
left: 5%;
min-height: 500px;
padding: var(--td-pop-padding-xxl);
border-radius: var(--td-radius-default);
}

.item-container {
width: 400px;
margin-top: var(--td-comp-margin-xxxxl);


.check-container-login {
display: flex;
align-items: center;
justify-content: space-between;

&.remember-pwd {
margin-bottom: var(--td-comp-margin-l);
justify-content: space-between;
}

span {
color: var(--td-brand-color);

&:hover {
cursor: pointer;
}
}
}
.check-container {
// display: flex;
align-items: center;

span {
color: var(--td-brand-color);

&:hover {
cursor: pointer;
}
}
}

.verification-code {
// display: flex;
align-items: center;

:deep(.t-form__controls) {
width: 100%;

button {
height: var(--td-size-12);
flex-shrink: 0;
margin-left: var(--td-comp-margin-l);
}
}
}
}

.check-container {
font: var(--td-font-body-medium);
color: var(--td-text-color-secondary);
}

.copyright {
font: var(--td-font-body-medium);
position: absolute;
left: 5%;
bottom: 64px;
color: var(--td-text-color-secondary);
}

@media screen and (max-height: 700px) {
.copyright {
display: none;
}
}

+ 33
- 10
web/src/views/login/index.vue View File

@@ -1,15 +1,38 @@
<script setup lang="ts">
import LoginHeader from './components/Header.vue'
import Login from './components/Login.vue'
import Register from './components/Register.vue'
import { ref } from 'vue';

const type = ref('login');
const switchType = (val: string) => {
type.value = val;
};
</script>

<template>
<div class="father">
<div class="son">123456</div>
<div class="login-wrapper">
<login-header/>
<div class="login-container">
<div class="title-container">
<h1 class="title margin-no">Welcome!</h1>
<h1 class="title">{{ type == 'register' ? 'Register' : 'Login' }} to OpenKF</h1>
<div class="sub-title">
<p class="tip" @click="switchType(type == 'register' ? 'login' : 'register')">
{{ type == 'register' ? 'Jump to login' : 'Jump to Register' }}
</p>
</div>
</div>

<login v-if="type === 'login'"/>
<register v-else />
</div>

<footer class="copyright"> Copyright © 2023 OpenIMSDK open source community. All rights reserved.</footer>
</div>
</template>

<script setup lang="ts"></script>

<style lang="less" scoped>
.father {
.son {
font-size: 80px;
}
}
</style>
@import url('./index.less');
</style>

+ 5
- 1
web/vite.config.ts View File

@@ -18,10 +18,14 @@ import { fileURLToPath, URL } from 'node:url';

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
plugins: [
vue(),
svgLoader(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),


Loading…
Cancel
Save