bls-dan 2 years ago
parent
commit
5d2278af3f

+ 6 - 2
src/assets/native-plugin.ts

@@ -11,7 +11,9 @@ import {
   NSelect,
   NCheckboxGroup,
   NCheckbox,
-  NDatePicker
+  NDatePicker,
+  NForm,
+  NFormItem
 } from 'naive-ui'
 
 const naive = create({
@@ -27,7 +29,9 @@ const naive = create({
     NSelect,
     NCheckboxGroup,
     NCheckbox,
-    NDatePicker
+    NDatePicker,
+    NForm,
+    NFormItem
   ]
 })
 

+ 181 - 0
src/pages/login/index.vue

@@ -0,0 +1,181 @@
+<script lang='ts' setup>
+import { nextTick, ref } from 'vue'
+import NetService from '@/services/net.service'
+import useStore from '../store'
+const netService = new NetService()
+
+const store = useStore()
+
+const formRef = ref()
+const model = ref({
+  account: '',
+  password: ''
+})
+const rules = {
+  account: [ {
+    required: true,
+    trigger: [ 'blur', 'input' ],
+    message: '请输入用户名'
+  } ],
+  password: [ {
+    required: true,
+    trigger: [ 'blur', 'input' ],
+    message: '请输入密码'
+  } ]
+}
+const labelStyle = {
+  height: '50px',
+  fontSize: '20px'
+}
+/** 登录 */
+async function login() {
+  formRef.value?.validate(async (errors?: Array<any>) => {
+    if (!errors) {
+      const params = {
+        account: model.value.account.trim(),
+        password: model.value.password.trim()
+      }
+      const { success, data, message } = await netService.post('/sys/login', params)
+      if (!success) throw message
+      store.setUserInfo(data)
+      sessionStorage.setItem('token', data.satoken)
+      await nextTick()
+      // 页面跳转
+      window.location.href = '/'
+    }
+  })
+}
+
+</script>
+<template>
+  <div class="login">
+    <div
+      class="form"
+      @keydown.enter="login"
+    >
+      <div class="title">
+        雅安可视化管控中心
+      </div>
+      <n-form
+        ref="formRef"
+        :model="model"
+        :rules="rules"
+        label-placement="left"
+        label-width="80px"
+        :show-require-mark="false"
+      >
+        <n-form-item
+          label="用户名"
+          path="account"
+          :label-style="labelStyle"
+        >
+          <n-input
+            v-model:value="model.account"
+            placeholder="请输入用户名"
+            size="large"
+            round
+          >
+            <template #prefix>
+              <icon
+                name="user"
+                :size="16"
+              />
+            </template>
+          </n-input>
+        </n-form-item>
+        <n-form-item
+          label="密码"
+          path="password"
+          :label-style="labelStyle"
+        >
+          <n-input
+            v-model:value="model.password"
+            placeholder="请输入密码"
+            size="large"
+            round
+            type="password"
+          >
+            <template #prefix>
+              <icon
+                name="lock"
+                :size="16"
+              />
+            </template>
+          </n-input>
+        </n-form-item>
+        <n-form-item
+          label=" "
+          :label-style="labelStyle"
+        >
+          <n-button
+            v-debounce
+            round
+            :bordered="false"
+            @click="login"
+          >
+            登 录
+          </n-button>
+        </n-form-item>
+      </n-form>
+    </div>
+  </div>
+</template>
+
+<style lang='scss' scoped>
+.login {
+  width: 100vw;
+  height: 100vh;
+  background: #030E25;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 0 160px;
+
+  .form {
+    width: 711px;
+    height: 576px;
+    background: linear-gradient(229deg, #050f25, #535c66);
+    border-radius: 30px;
+    border: 2px solid #FFFFFF;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+
+    .title {
+      display: flex;
+      gap: 30px;
+      margin-top: 81px;
+      font-size: 36px;
+      color: #FFFFFF;
+      line-height: 41px;
+      letter-spacing: 2px;
+    }
+
+    .n-form-item {
+      &:first-child {
+        margin-top: 110px;
+      }
+
+      margin-top: 16px;
+      margin-bottom: 0;
+    }
+
+    :deep(.n-form-item-label__text) {
+      text-align-last: justify;
+    }
+
+    .n-input,
+    .n-button {
+      width: 415px;
+      --n-height: 50px
+    }
+
+    .n-button {
+      background: #030E25;
+      color: #FFFFFF;
+      border-color: #fff;
+      font-size: 20px;
+    }
+  }
+}
+</style>

+ 10 - 0
src/pages/login/route.ts

@@ -0,0 +1,10 @@
+import { RouteRecordRaw } from 'vue-router'
+
+export default {
+  path: '/login',
+  meta: {
+    authorize: true
+  },
+  component: () => import('./index.vue'),
+  children: []
+} as RouteRecordRaw

+ 27 - 0
src/pages/login/services/login.service.ts

@@ -0,0 +1,27 @@
+import { injectable, Service } from '@/services/service'
+import NetService from '@/services/net.service'
+import useStore from '@/pages/store'
+
+@injectable
+export default class UserService extends Service {
+  private netService = new NetService()
+
+  private store = useStore()
+
+  // protected baseUrl = `${import.meta.env.VITE_PROXY_URL}`
+
+  /** 用户登录接口 */
+  async login(account: string, password: string) {
+    const { code, data, msg } = await this.netService.post('/sys/login', { account, password })
+    if (code !== 200) throw msg
+    this.store.setUserInfo(data)
+    sessionStorage.setItem('token', data.satoken)
+    // 页面跳转
+    window.location.href = '/'
+  }
+
+  /** 退出登录 */
+  async loginOut() {
+    sessionStorage.clear()
+  }
+}

+ 14 - 2
src/pages/main.ts

@@ -10,7 +10,10 @@ const store = createPinia()
 
 // 动态路由
 const routes = Object.values(import.meta.glob('./views/*/route.ts', { eager: true, import: 'default' })) as unknown as RouteRecordRaw[]
-routes.push({ path: '/:path(.*)', redirect: '/' })
+routes.push(
+  { path: '/login', component: () => import('./login/index.vue') },
+  { path: '/:path(.*)', redirect: '/login' }
+)
 
 const app = createApp(App)
 const router = createRouter({
@@ -18,6 +21,15 @@ const router = createRouter({
   routes
 })
 
+// 路由守卫
+router.beforeEach((to, from, next) => {
+  const token = sessionStorage.getItem('token')
+  if (to.path !== '/login' && !token) {
+    router.replace('/login')
+  } else {
+    next()
+  }
+})
 app.use(store)
   .use(router)
   .use(naive)
@@ -27,7 +39,7 @@ router.isReady().then(() => {
   const vm = app.mount('#app')
   app.config.errorHandler = (err: any) => {
     if (err.reason === 401) {
-      router.replace('/')
+      router.replace('/login')
     } else {
       console.log(err)
     }

+ 1 - 1
src/pages/store/index.ts

@@ -19,7 +19,7 @@ export interface Weather {
 const useStore = defineStore('index', {
   state: () => ({
     userInfro: {} as UserInfo,
-    token: '9d984fe66da0459bb64f0a408600344e',
+    token: '',
     loading: false,
     weather: {} as Weather,
     weatherIcons: [

+ 1 - 1
src/pages/views/home/index.vue

@@ -479,7 +479,7 @@ getAnalysisLineStatistics()
       <div class="home-content-left" />
       <div class="home-content-right" />
       <div class="home-content-center">
-        <Map :Item="menus[active]" />
+        <Map :Item="(menus[active] as any)" />
       </div>
       <div class="home-content-left-img" />
       <div class="home-content-right-img" />

+ 2 - 2
src/services/net.service.ts

@@ -95,7 +95,7 @@ export default class NetService extends Service {
    * @returns
    */
   private fetch(url: string, opt: RequestInit, timeout = 0): Promise<NetResult> {
-    const satoken = this._store.token
+    const satoken = this._store.token || `${sessionStorage.getItem('token')}`
     return new Promise((resolve) => {
       const controller = new AbortController()
       const { signal } = controller
@@ -113,7 +113,7 @@ export default class NetService extends Service {
         return res.json()
       }).then((res) => {
         const obj = { data: res.data, success: res.data instanceof Object }
-        if (!obj.success && obj.data?.includes('need authrize')) {
+        if (!obj.success && res.message?.includes('Token')) {
           throw 401
         }
         resolve(obj)