Selaa lähdekoodia

feat: 登录页完成,登录态相关逻辑的简化版完成

zhusiqing 3 vuotta sitten
vanhempi
commit
e48bc138cb

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
.eslintcache


+ 8 - 0
CHANGELOG.md

@@ -1,3 +1,11 @@
+## 0.6.0(2021-12-22)
+
+### Features
+
+- 更新npm包
+- 登录页完成
+- 登录态相关逻辑的简化版完成
+
 ## 0.5.0(2021-12-21)
 
 ### Features

+ 4 - 0
components.d.ts

@@ -7,6 +7,9 @@ declare module 'vue' {
     AAvatar: typeof import('ant-design-vue/es')['Avatar']
     AButton: typeof import('ant-design-vue/es')['Button']
     ADropdown: typeof import('ant-design-vue/es')['Dropdown']
+    AForm: typeof import('ant-design-vue/es')['Form']
+    AFormItem: typeof import('ant-design-vue/es')['FormItem']
+    AInput: typeof import('ant-design-vue/es')['Input']
     ALayout: typeof import('ant-design-vue/es')['Layout']
     ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
     ALayoutFooter: typeof import('ant-design-vue/es')['LayoutFooter']
@@ -18,6 +21,7 @@ declare module 'vue' {
     ASpin: typeof import('ant-design-vue/es')['Spin']
     HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
     InitLoading: typeof import('./src/components/InitLoading.vue')['default']
+    LockOutlined: typeof import('@ant-design/icons-vue')['LockOutlined']
     UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
   }
 }

+ 2 - 2
log.md

@@ -5,6 +5,6 @@
 - [x] 底部布局组件
 - [x] 边侧栏布局组件
 - [x] 权限路由设计
-- [ ] 登录页
-- [ ] 登录态相关处理
+- [x] 登录页
+- [x] 登录态相关处理
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "vite-template",
-  "version": "0.5.0",
+  "version": "0.6.0",
   "scripts": {
     "dev": "vite",
     "build": "vue-tsc --noEmit && vite build",

BIN
public/images/login_bg.jpeg


+ 32 - 18
src/App.vue

@@ -1,32 +1,46 @@
 <script setup lang="ts">
 // This starter template is using Vue 3 <script setup> SFCs
 // Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
+  import { ref, watch, computed, nextTick } from 'vue';
   import { RouterView, useRouter, useRoute } from 'vue-router';
-  import { AppRoute, NotFoundRoute } from '@/router/base';
+  import { AppRoute, NotFoundRoute, EnumPage } from '@/router/base';
   import { authRoutes } from '@/router/auth';
   import { filterAuthHandle } from '@/router/utils'
   import { AppStore } from '@/store/modules/app';
+  import { useLocalStorage } from '@vueuse/core'
+
 
   const router = useRouter()
   const route = useRoute()
   const store = AppStore()
-
-  // TODO: 增加无需权限时的判断
-  // 此处模拟接口请求获取权限列表
-  setTimeout(() => {
-    const authFilterRoutes = filterAuthHandle([1], authRoutes)
-    console.log(authFilterRoutes);
-    const childrenRoutes = [...authFilterRoutes, ...AppRoute.children as []]
-    router.removeRoute(AppRoute.name as string)
-    router.addRoute({
-      ...AppRoute,
-      children: childrenRoutes
-    })
-    router.addRoute(NotFoundRoute)
-    store.updateLoading(false)
-    store.updateAuthRoutes(authFilterRoutes)
-    router.replace(route.fullPath)
-  }, 2e3);
+  const isLogin = computed(() => store.isLogin)
+  watch(isLogin, (val) => {
+    if (![EnumPage.Login as string, EnumPage.Error as string].includes(route.path)) {
+      if (!val) {
+        router.push(EnumPage.Login)
+        store.updateLoading(false)
+      } else {
+        // 此处模拟接口请求获取权限列表
+        store.updateLoading(true)
+        setTimeout(() => {
+          const authFilterRoutes = filterAuthHandle([1], authRoutes)
+          console.log(authFilterRoutes);
+          const childrenRoutes = [...authFilterRoutes, ...AppRoute.children as []]
+          router.removeRoute(AppRoute.name as string)
+          router.addRoute({
+            ...AppRoute,
+            children: childrenRoutes
+          })
+          router.addRoute(NotFoundRoute)
+          store.updateLoading(false)
+          store.updateAuthRoutes(authFilterRoutes)
+          router.replace(route.fullPath)
+        }, 2e3);
+      }
+    }
+  }, {
+    immediate: true
+  })
 </script>
 
 <template>

+ 10 - 1
src/layouts/app/Footer.vue

@@ -1,5 +1,14 @@
 <template>
   <a-layout-footer>
-    Vite+Vue3+Typescript Template &copy;2021 Created by zhusiqing
+    <p class="foot-text">
+      Vite+Vue3+Typescript Template &copy;2021 Created by zhusiqing
+    </p>
   </a-layout-footer>
 </template>
+
+<style scoped>
+.foot-text {
+  margin: 0;
+  text-align: center;
+}
+</style>

+ 8 - 3
src/layouts/app/Header.vue

@@ -37,10 +37,15 @@
 </template>
 <script lang="ts" setup>
 import { ref } from 'vue';
-import { RouterLink } from 'vue-router';
+import { RouterLink, useRouter } from 'vue-router';
 import { message } from 'ant-design-vue';
+import { AppStore } from '@/store/modules/app'
+
 import 'ant-design-vue/es/message/style/index.less';
+import { EnumPage } from '@/router/base';
 
+const store = AppStore()
+const router = useRouter()
 const navs = ref([
   {
     path: '/',
@@ -64,13 +69,13 @@ interface menuClickParams {
 }
 
 const menuClickHandle = ({ key }: menuClickParams) => {
-  console.log(key);
   switch (key) {
     case EnumUserDropdown.center:
       message.info('个人中心')
       break
     case EnumUserDropdown.logout:
-      message.info('退出登录')
+      message.success('退出登录')
+      router.push(EnumPage.Login).then(() => store.updateIsLogin(false))
       break
     default:
       break;

+ 1 - 0
src/layouts/app/index.vue

@@ -29,6 +29,7 @@ import AppFooter from './Footer.vue';
   .layout-content {
     overflow: auto;
     padding: 24px;
+    padding-bottom: 0;
   }
   .content {
     min-height: 100%;

+ 137 - 4
src/pages/Login/index.vue

@@ -1,13 +1,146 @@
 <template>
   <div class="login">
-    login page
+    <div class="form-box">
+      <div class="title">
+        后台管理系统
+      </div>
+      <a-form
+        class="form"
+        :model="loginState"
+        :rules="rules"
+        @finish="finishHandle"
+        @finishFailed="finishFailedHandle"
+      >
+        <a-form-item
+          name="username"
+          class="form-item"
+        >
+          <a-input
+            v-model:value="loginState.username"
+            placeholder="用户名"
+            size="large"
+          >
+            <template #prefix>
+              <user-outlined style="color: rgba(0, 0, 0, 0.25)" />
+            </template>
+          </a-input>
+        </a-form-item>
+        <a-form-item
+          name="password"
+          class="form-item"
+        >
+          <a-input
+            v-model:value="loginState.password"
+            type="password"
+            placeholder="密码"
+            size="large"
+          >
+            <template #prefix>
+              <lock-outlined style="color: rgba(0, 0, 0, 0.25)" />
+            </template>
+          </a-input>
+        </a-form-item>
+        <a-form-item>
+          <a-button
+            class="form-submit"
+            type="primary"
+            html-type="submit"
+            size="large"
+          >
+            登录
+          </a-button>
+        </a-form-item>
+      </a-form>
+    </div>
   </div>
 </template>
-<script setup>
+<script lang="ts" setup>
+import { reactive, ref } from 'vue';
+import { EnumPage } from '@/router/base';
+import { useRouter } from 'vue-router';
+import { message } from 'ant-design-vue'
+import { useLocalStorage } from '@vueuse/core'
+import type { UnwrapRef } from 'vue';
+import type { FormProps } from 'ant-design-vue';
+import { AppStore } from '@/store/modules/app'
 
+const router = useRouter()
+const store = AppStore()
+interface loginState {
+  username: string
+  password: string
+}
+const loginState: UnwrapRef<loginState> = reactive({
+  username: '',
+  password: ''
+})
+const rules = {
+  username: [
+    {
+      required: true,
+      message: '请输入用户名',
+      whitespace: true,
+      trigger: 'blur'
+    }
+  ],
+  password: [
+    {
+      required: true,
+      message: '请输入密码',
+      whitespace: true,
+      trigger: 'blur'
+    }
+  ]
+}
+
+const finishHandle: FormProps['onFinish'] = (values: loginState) => {
+  const { username, password } = values
+  if (username === 'admin' && password === '123') {
+    router.push(EnumPage.App).then(() => store.updateIsLogin(true))
+  } else {
+    message.error('用户名或密码错误')
+  }
+}
+const finishFailedHandle: FormProps['onFinishFailed'] = (errors) => {
+  console.log(errors);
+}
 </script>
-<style scoped>
+<style lang="less" scoped>
 .login {
-  font-size: 46px;
+  height: 100%;
+  background: url('/images/login_bg.jpeg') center/cover no-repeat;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .form-box {
+    background-color: rgba(255, 255, 255, .8);
+    height: 460px;
+    width: 400px;
+    border-radius: 12px;
+    padding: 60px 40px;
+    .title {
+      text-align: center;
+      font-size: 26px;
+      font-weight: 500;
+    }
+    .form {
+      margin-top: 40px;
+      .form-item {
+        margin-bottom: 40px;
+      }
+      .form-submit {
+        width: 180px;
+      }
+      // 修复表单错误提示出现时的显示异常
+      :deep(.ant-form-item-with-help) {
+        margin-bottom: 16px;
+      }
+      // 登录按钮居中
+      :deep(.ant-form-item-control-input-content) {
+        text-align: center;
+      }
+    }
+
+  }
 }
 </style>

+ 6 - 1
src/store/modules/app.ts

@@ -1,10 +1,12 @@
 import { defineStore } from 'pinia';
 import { RouteRecordRaw } from 'vue-router';
+import { useLocalStorage } from '@vueuse/core'
 
 export const AppStore = defineStore('app', {
   state: () => ({
     isLoading: true,
-    authRoutes: [] as RouteRecordRaw[]
+    authRoutes: [] as RouteRecordRaw[],
+    isLogin: useLocalStorage('login', false)
   }),
   actions: {
     updateLoading(isLoading = false) {
@@ -12,6 +14,9 @@ export const AppStore = defineStore('app', {
     },
     updateAuthRoutes(routes: RouteRecordRaw[]) {
       this.authRoutes = routes
+    },
+    updateIsLogin(isLogin = false) {
+      this.isLogin = isLogin
     }
   }
 })

+ 0 - 1
src/style/global.css

@@ -9,6 +9,5 @@ html, body {
   font-family: Avenir, Helvetica, Arial, sans-serif;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-  text-align: center;
   color: #2c3e50;
 }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä