黎海 1 ヶ月 前
コミット
31aafd2795
共有10 個のファイルを変更した112 個の追加54 個の削除を含む
  1. 1 0
      package.json
  2. 9 1
      src/api/user.js
  3. 21 0
      src/i18n/index.js
  4. 4 0
      src/i18n/locales/en.json
  5. 8 0
      src/i18n/locales/zh.json
  6. 12 9
      src/layout/components/Navbar.vue
  7. 2 1
      src/main.js
  8. 0 24
      src/router/index.js
  9. 2 1
      src/utils/request.js
  10. 53 18
      src/views/login/index.vue

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
22 22
     "nprogress": "0.2.0",
23 23
     "path-to-regexp": "2.4.0",
24 24
     "vue": "2.6.10",
25
+    "vue-i18n": "^8.28.2",
25 26
     "vue-router": "3.0.6",
26 27
     "vuex": "3.1.0"
27 28
   },

+ 9 - 1
src/api/user.js

@@ -2,7 +2,15 @@ import request from '@/utils/request'
2 2
 
3 3
 export function login(data) {
4 4
   return request({
5
-    url: '/vue-admin-template/user/login',
5
+    url: '/login',
6
+    method: 'post',
7
+    data
8
+  })
9
+}
10
+
11
+export function register(data) {
12
+  return request({
13
+    url: '/register',
6 14
     method: 'post',
7 15
     data
8 16
   })

+ 21 - 0
src/i18n/index.js

@@ -0,0 +1,21 @@
1
+// src/i18n/index.js
2
+import Vue from 'vue'
3
+import VueI18n from 'vue-i18n'
4
+
5
+// 导入语言包
6
+import en from './locales/en.json'
7
+import zh from './locales/zh.json'
8
+
9
+Vue.use(VueI18n)
10
+
11
+const messages = {
12
+  en,
13
+  zh
14
+}
15
+
16
+const i18n = new VueI18n({
17
+  locale: 'zh', // 设置默认语言
18
+  messages
19
+})
20
+
21
+export default i18n

+ 4 - 0
src/i18n/locales/en.json

@@ -0,0 +1,4 @@
1
+{
2
+  "mine": "home",
3
+  "logout": "Logout"
4
+}

+ 8 - 0
src/i18n/locales/zh.json

@@ -0,0 +1,8 @@
1
+{
2
+  "mine": "首页",
3
+  "logout": "退出",
4
+  "login": "登录",
5
+  "switchToRegister": "切换到注册",
6
+  "switchToLogin": "切换到登录",
7
+  "register": "注册"
8
+}

+ 12 - 9
src/layout/components/Navbar.vue

@@ -13,17 +13,14 @@
13 13
         <el-dropdown-menu slot="dropdown" class="user-dropdown">
14 14
           <router-link to="/">
15 15
             <el-dropdown-item>
16
-              Home
16
+              {{ $t('mine') }}
17 17
             </el-dropdown-item>
18 18
           </router-link>
19
-          <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
20
-            <el-dropdown-item>Github</el-dropdown-item>
21
-          </a>
22
-          <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
23
-            <el-dropdown-item>Docs</el-dropdown-item>
24
-          </a>
19
+          <el-dropdown-item @click.native="toggleLanguage">
20
+            <span style="display:block;">{{ currentLanguage === 'zh' ? 'Switch to English' : '切换到中文' }}</span>
21
+          </el-dropdown-item>
25 22
           <el-dropdown-item divided @click.native="logout">
26
-            <span style="display:block;">Log Out</span>
23
+            <span style="display:block;">{{ $t('logout') }}</span>
27 24
           </el-dropdown-item>
28 25
         </el-dropdown-menu>
29 26
       </el-dropdown>
@@ -45,7 +42,10 @@ export default {
45 42
     ...mapGetters([
46 43
       'sidebar',
47 44
       'avatar'
48
-    ])
45
+    ]),
46
+    currentLanguage() {
47
+      return this.$i18n.locale
48
+    }
49 49
   },
50 50
   methods: {
51 51
     toggleSideBar() {
@@ -54,6 +54,9 @@ export default {
54 54
     async logout() {
55 55
       await this.$store.dispatch('user/logout')
56 56
       this.$router.push(`/login?redirect=${this.$route.fullPath}`)
57
+    },
58
+    toggleLanguage() {
59
+      this.$i18n.locale = this.currentLanguage === 'zh' ? 'en' : 'zh'
57 60
     }
58 61
   }
59 62
 }

+ 2 - 1
src/main.js

@@ -11,7 +11,7 @@ import '@/styles/index.scss' // global css
11 11
 import App from './App'
12 12
 import store from './store'
13 13
 import router from './router'
14
-
14
+import i18n from '@/i18n'
15 15
 import '@/icons' // icon
16 16
 import '@/permission' // permission control
17 17
 
@@ -39,5 +39,6 @@ new Vue({
39 39
   el: '#app',
40 40
   router,
41 41
   store,
42
+  i18n,
42 43
   render: h => h(App)
43 44
 })

+ 0 - 24
src/router/index.js

@@ -6,30 +6,6 @@ Vue.use(Router)
6 6
 /* Layout */
7 7
 import Layout from '@/layout'
8 8
 
9
-/**
10
- * Note: sub-menu only appear when route children.length >= 1
11
- * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
12
- *
13
- * hidden: true                   if set true, item will not show in the sidebar(default is false)
14
- * alwaysShow: true               if set true, will always show the root menu
15
- *                                if not set alwaysShow, when item has more than one children route,
16
- *                                it will becomes nested mode, otherwise not show the root menu
17
- * redirect: noRedirect           if set noRedirect will no redirect in the breadcrumb
18
- * name:'router-name'             the name is used by <keep-alive> (must set!!!)
19
- * meta : {
20
-    roles: ['admin','editor']    control the page roles (you can set multiple roles)
21
-    title: 'title'               the name show in sidebar and breadcrumb (recommend set)
22
-    icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
23
-    breadcrumb: false            if set false, the item will hidden in breadcrumb(default is true)
24
-    activeMenu: '/example/list'  if set path, the sidebar will highlight the path you set
25
-  }
26
- */
27
-
28
-/**
29
- * constantRoutes
30
- * a base page that does not have permission requirements
31
- * all roles can be accessed
32
- */
33 9
 export const constantRoutes = [
34 10
   {
35 11
     path: '/login',

+ 2 - 1
src/utils/request.js

@@ -5,7 +5,8 @@ import { getToken } from '@/utils/auth'
5 5
 
6 6
 // create an axios instance
7 7
 const service = axios.create({
8
-  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
8
+  baseURL: 'http://192.168.1.9:8000/docs', // url = base url + request url
9
+  // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
9 10
   // withCredentials: true, // send cookies when cross-domain requests
10 11
   timeout: 5000 // request timeout
11 12
 })

+ 53 - 18
src/views/login/index.vue

@@ -3,9 +3,23 @@
3 3
     <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
4 4
 
5 5
       <div class="title-container">
6
-        <h3 class="title">Login Form</h3>
6
+        <h3 class="title">{{ isLogin ? $t('login') : $t('register') }}</h3>
7 7
       </div>
8 8
 
9
+      <el-form-item v-if="!isLogin" prop="email">
10
+        <span class="svg-container">
11
+          <svg-icon icon-class="email" />
12
+        </span>
13
+        <el-input
14
+          v-model="loginForm.email"
15
+          placeholder="Email"
16
+          name="email"
17
+          type="email"
18
+          tabindex="1"
19
+          auto-complete="on"
20
+        />
21
+      </el-form-item>
22
+
9 23
       <el-form-item prop="username">
10 24
         <span class="svg-container">
11 25
           <svg-icon icon-class="user" />
@@ -16,7 +30,7 @@
16 30
           placeholder="Username"
17 31
           name="username"
18 32
           type="text"
19
-          tabindex="1"
33
+          tabindex="2"
20 34
           auto-complete="on"
21 35
         />
22 36
       </el-form-item>
@@ -32,20 +46,21 @@
32 46
           :type="passwordType"
33 47
           placeholder="Password"
34 48
           name="password"
35
-          tabindex="2"
49
+          tabindex="3"
36 50
           auto-complete="on"
37
-          @keyup.enter.native="handleLogin"
51
+          @keyup.enter.native="handleSubmit"
38 52
         />
39 53
         <span class="show-pwd" @click="showPwd">
40 54
           <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
41 55
         </span>
42 56
       </el-form-item>
43 57
 
44
-      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
58
+      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleSubmit">
59
+        {{ isLogin ? $t('login') : $t('register') }}
60
+      </el-button>
45 61
 
46
-      <div class="tips">
47
-        <span style="margin-right:20px;">username: admin</span>
48
-        <span> password: any</span>
62
+      <div class="switch-mode" @click="toggleMode">
63
+        {{ isLogin ? $t('switchToRegister') : $t('switchToLogin') }}
49 64
       </div>
50 65
 
51 66
     </el-form>
@@ -72,12 +87,23 @@ export default {
72 87
         callback()
73 88
       }
74 89
     }
90
+    const validateEmail = (rule, value, callback) => {
91
+      const emailPattern = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/
92
+      if (!emailPattern.test(value)) {
93
+        callback(new Error('Please enter a valid email address'))
94
+      } else {
95
+        callback()
96
+      }
97
+    }
75 98
     return {
99
+      isLogin: true,
76 100
       loginForm: {
101
+        email: '',
77 102
         username: 'admin',
78 103
         password: '111111'
79 104
       },
80 105
       loginRules: {
106
+        email: [{ required: true, trigger: 'blur', validator: validateEmail }],
81 107
         username: [{ required: true, trigger: 'blur', validator: validateUsername }],
82 108
         password: [{ required: true, trigger: 'blur', validator: validatePassword }]
83 109
       },
@@ -86,15 +112,10 @@ export default {
86 112
       redirect: undefined
87 113
     }
88 114
   },
89
-  watch: {
90
-    $route: {
91
-      handler: function(route) {
92
-        this.redirect = route.query && route.query.redirect
93
-      },
94
-      immediate: true
95
-    }
96
-  },
97 115
   methods: {
116
+    toggleMode() {
117
+      this.isLogin = !this.isLogin
118
+    },
98 119
     showPwd() {
99 120
       if (this.passwordType === 'password') {
100 121
         this.passwordType = ''
@@ -105,11 +126,15 @@ export default {
105 126
         this.$refs.password.focus()
106 127
       })
107 128
     },
108
-    handleLogin() {
129
+    handleSubmit() {
109 130
       this.$refs.loginForm.validate(valid => {
110 131
         if (valid) {
111 132
           this.loading = true
112
-          this.$store.dispatch('user/login', this.loginForm).then(() => {
133
+          const action = this.isLogin ? 'user/login' : 'user/register'
134
+          this.$store.dispatch(action, this.loginForm).then(() => {
135
+            if (!this.isLogin) {
136
+              this.toggleMode()
137
+            }
113 138
             this.$router.push({ path: this.redirect || '/' })
114 139
             this.loading = false
115 140
           }).catch(() => {
@@ -176,6 +201,7 @@ $cursor: #fff;
176 201
 $bg:#2d3a4b;
177 202
 $dark_gray:#889aa4;
178 203
 $light_gray:#eee;
204
+$green: #00ff00;
179 205
 
180 206
 .login-container {
181 207
   min-height: 100%;
@@ -233,5 +259,14 @@ $light_gray:#eee;
233 259
     cursor: pointer;
234 260
     user-select: none;
235 261
   }
262
+
263
+  .switch-mode {
264
+    text-decoration: underline;
265
+    color: $green;
266
+    cursor: pointer;
267
+    user-select: none;
268
+    text-align: center;
269
+    margin-top: 20px;
270
+  }
236 271
 }
237 272
 </style>