Forráskód Böngészése

feat: 登录页面

Gaokun Wang 1 hónapja
szülő
commit
a0b5fe5673

+ 1 - 0
.eslintrc-auto-import.json

@@ -5,6 +5,7 @@
     "ComputedRef": true,
     "DirectiveBinding": true,
     "EffectScope": true,
+    "ElMessage": true,
     "ExtractDefaultPropTypes": true,
     "ExtractPropTypes": true,
     "ExtractPublicPropTypes": true,

+ 3 - 4
plugins/vue-components.ts

@@ -1,12 +1,11 @@
 import Components from 'unplugin-vue-components/vite'
-import { TDesignResolver } from 'unplugin-vue-components/resolvers'
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 import IconsResolver from 'unplugin-icons/resolver'
 export default () => {
   return Components({
     resolvers: [
-      TDesignResolver({
-        library: 'vue-next'
-      }),
+      // 自动导入 Element Plus 组件
+      ElementPlusResolver(),
       // 自动注册图标组件
       IconsResolver({
         // 图标库,其他图标库 https://icon-sets.iconify.design/

+ 3 - 9
src/api/interface/system/user.ts

@@ -12,13 +12,13 @@ export interface UserInfo {
  */
 export interface UserVO extends BaseEntity {
   userId: string | number
-  deptId: number
+  orgId: string
+  account: string
   userName: string
   nickName: string
   userType: string
   email: string
-  phonenumber: string
-  dept: any
+  phoneNumber: string
   gender: string
   avatar: string
   url: string
@@ -27,10 +27,4 @@ export interface UserVO extends BaseEntity {
   loginIp: string
   loginDate: string
   remark: string
-  deptName: string
-  roles: any[]
-  roleIds: any
-  postIds: any
-  roleId: any
-  admin: boolean
 }

BIN
src/assets/images/bg.png


+ 33 - 0
src/assets/images/login_bg.svg

@@ -0,0 +1,33 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" width="100%" height="100%" viewBox="0 0 1400 800">
+
+  <rect x="1300" y="400" rx="40" ry="40" width="150" height="150" stroke="rgb(129, 201, 149)" fill="rgb(129, 201, 149)">
+    <animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 1450 550" to="360 1450 550" repeatCount="indefinite"/>
+  </rect>
+
+  <path d="M 100 350 A 150 150 0 1 1 400 350 Q400 370 380 370 L 250 370 L 120 370 Q100 370 100 350" fill="#a2b3ff">
+    <animateMotion path="M 800 -200 L 800 -300 L 800 -200" dur="20s" begin="0s" repeatCount="indefinite"/>
+    <animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 210 530 ; -30 210 530 ; 0 210 530" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite"/>
+  </path>
+
+  <circle cx="150" cy="150" r="180" stroke="#85FFBD" fill="#85FFBD">
+    <animateMotion path="M 0 0 L 40 20 Z" dur="5s" repeatCount="indefinite"/>
+  </circle>
+
+  <!-- 三角形 -->
+  <path d="M 165 580 L 270 580 Q275 578 270 570 L 223 483 Q220 480 217 483 L 165 570 Q160 578 165 580"  fill="#a2b3ff">
+    <animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 210 530" to="360 210 530" repeatCount="indefinite"/>
+  </path>
+
+<!--  <circle cx="1200" cy="600" r="30" stroke="rgb(241, 243, 244)" fill="rgb(241, 243, 244)">-->
+<!--    <animateMotion path="M 0 0 L -20 40 Z" dur="9s" repeatCount="indefinite"/>-->
+<!--  </circle>-->
+
+  <path d="M 100 350 A 40 40 0 1 1 180 350 L 180 430 A 40 40 0 1 1 100 430 Z" fill="#3054EB">
+    <animateMotion path="M 140 390 L 180 360 L 140 390" dur="20s" begin="0s" repeatCount="indefinite"/>
+    <animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 140 390; -60 140 390; 0 140 390" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite"/>
+  </path>
+
+  <rect x="400" y="600" rx="40" ry="40" width="100" height="100" stroke="rgb(129, 201, 149)" fill="#3054EB">
+    <animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="-30 550 750" to="330 550 750" repeatCount="indefinite"/>
+  </rect>
+</svg>

BIN
src/assets/images/login_left3.png


+ 1 - 0
src/assets/images/logo.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

+ 3 - 2
src/axios/config.ts

@@ -10,13 +10,14 @@ const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => {
 }
 
 const defaultResponseInterceptors = (response: AxiosResponse) => {
-  const { code } = response.data
+  const { code, msg } = response.data
   if (response?.config?.responseType === 'blob') {
     // 如果是文件流,直接过
     return response
   } else if (code === ResultEnum.SUCCESS) {
     return response.data
+  } else {
+    ElMessage.error(msg)
   }
 }
-
 export { defaultResponseInterceptors, defaultRequestInterceptors }

+ 1 - 1
src/router/index.ts

@@ -22,7 +22,7 @@ const routerMode = {
  * @param meta.activeMenu ==> 当前路由为详情页时,需要高亮的菜单
  * @param meta.isLink ==> 路由外链时填写的访问地址
  * @param meta.isHidden ==> 是否在菜单中隐藏 (通常列表详情页需要隐藏)
- * @param meta.isFull ==> 菜单是否全屏 (示例:数据大屏页面)
+ * @param meta.isFull ==> 菜单是否全屏
  * @param meta.isAffix ==> 菜单是否固定在标签页中 (首页通常是固定项)
  * @param meta.isKeepAlive ==> 当前路由是否缓存
  */

+ 6 - 0
src/types/auto-components.d.ts

@@ -10,6 +10,12 @@ declare module 'vue' {
   export interface GlobalComponents {
     AppClassic: typeof import('./../layouts/container/AppClassic/index.vue')['default']
     AppTransverse: typeof import('./../layouts/container/AppTransverse/index.vue')['default']
+    ElButton: typeof import('element-plus/es')['ElButton']
+    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElForm: typeof import('element-plus/es')['ElForm']
+    ElFormItem: typeof import('element-plus/es')['ElFormItem']
+    ElIcon: typeof import('element-plus/es')['ElIcon']
+    ElInput: typeof import('element-plus/es')['ElInput']
     HelloWorld: typeof import('./../components/HelloWorld.vue')['default']
     LoginForm: typeof import('./../views/login/components/LoginForm.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']

+ 2 - 0
src/types/auto-imports.d.ts

@@ -7,6 +7,7 @@
 export {}
 declare global {
   const EffectScope: (typeof import('vue'))['EffectScope']
+  const ElMessage: (typeof import('element-plus/es'))['ElMessage']
   const acceptHMRUpdate: (typeof import('pinia'))['acceptHMRUpdate']
   const asyncComputed: (typeof import('@vueuse/core'))['asyncComputed']
   const autoResetRef: (typeof import('@vueuse/core'))['autoResetRef']
@@ -336,6 +337,7 @@ declare module 'vue' {
   interface GlobalComponents {}
   interface ComponentCustomProperties {
     readonly EffectScope: UnwrapRef<(typeof import('vue'))['EffectScope']>
+    readonly ElMessage: UnwrapRef<(typeof import('element-plus/es'))['ElMessage']>
     readonly acceptHMRUpdate: UnwrapRef<(typeof import('pinia'))['acceptHMRUpdate']>
     readonly asyncComputed: UnwrapRef<(typeof import('@vueuse/core'))['asyncComputed']>
     readonly autoResetRef: UnwrapRef<(typeof import('@vueuse/core'))['autoResetRef']>

+ 59 - 0
src/views/login/index.scss

@@ -0,0 +1,59 @@
+.login-container {
+  height: 100%;
+  min-height: 550px;
+  background-color: #eeeeee;
+  background-image: url('@/assets/images/bg.png');
+  background-size: cover;
+  .login-box {
+    .login-left {
+      width: 800px;
+      margin-right: 10px;
+      .login-left-img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .login-form {
+      width: 420px;
+      padding: 50px 40px 45px;
+      background-color: var(--el-bg-color);
+      border-radius: 10px;
+      box-shadow: rgb(0 0 0 / 10%) 0 2px 10px 2px;
+      .login-logo {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .logo-text {
+          padding: 0 0 0 25px;
+          margin: 0;
+          font-size: 42px;
+          font-weight: bold;
+          color: #34495e;
+          white-space: nowrap;
+        }
+      }
+      .login-btn {
+        display: flex;
+        align-items: center;
+        width: 100%;
+        margin-top: 40px;
+        white-space: nowrap;
+        .el-button {
+          width: 185px;
+        }
+      }
+    }
+  }
+}
+
+@media screen and (width <= 1250px) {
+  .login-left {
+    display: none;
+  }
+}
+
+@media screen and (width <= 600px) {
+  .login-form {
+    width: 97% !important;
+  }
+}

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

@@ -1,40 +1,50 @@
 <template>
-  <div class="login-page">
-    <div class="login-container">
-      <div class="login-card">
-        <h2 class="login-title">卫星轨道仿真演示系统</h2>
-        <el-form ref="ruleFormRef" :model="loginForm">
-          <el-form-item label="账号" prop="account">
-            <el-input v-model="loginForm.account" />
+  <div class="login-container flx-center">
+    <div class="login-box">
+      <div class="login-form">
+        <div class="login-logo">
+          <h2 class="logo-text">ECO-BOOT-WEB</h2>
+        </div>
+        <el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" size="large" label-position="top">
+          <el-form-item prop="account" label="账号">
+            <el-input v-model="loginForm.account" placeholder="账号: superadmin"> </el-input>
           </el-form-item>
-          <el-form-item label="密码" prop="password">
-            <el-input v-model="loginForm.password" type="password" autocomplete="off" />
+          <el-form-item prop="password" style="margin-bottom: 0" label="密码">
+            <el-input v-model="loginForm.password" type="password" placeholder="密码: admin123" autocomplete="new-password"> </el-input>
           </el-form-item>
-          <el-button type="primary" @click="submitForm(ruleFormRef)"> 登录 </el-button>
-          <el-button @click="resetForm(ruleFormRef)">重置</el-button>
         </el-form>
+        <div class="login-btn">
+          <el-button round size="large" @click="resetForm(loginFormRef)"> 重置 </el-button>
+          <el-button round size="large" type="primary" :loading="loading" @click="submitForm(loginFormRef)"> 登录 </el-button>
+        </div>
       </div>
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { type FormInstance } from 'element-plus'
+import { ElMessage, type FormInstance } from 'element-plus'
 import { useUserStore } from '@/stores'
 import router from '@/router'
 import { LocationQuery } from 'vue-router'
 import { initDynamicRouter } from '@/router/modules/dynamicRouter'
-const ruleFormRef = ref<FormInstance>()
+const loginFormRef = ref<FormInstance>()
+const loading = ref(false)
 const route = useRoute()
 const userStore = useUserStore()
 const loginForm = reactive({
-  account: 'superadmin',
-  password: 'admin123',
+  account: '',
+  password: '',
   grantType: 'password',
   clientId: '7daa6e9b-8876-4918-8a12-b68cbfcdc680',
   tenantId: '1'
 })
 
+const loginRules = reactive({
+  account: [{ required: true, message: '请输入账号', trigger: 'blur' }],
+  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
+})
+
 /**
  * 提交表单
  *
@@ -49,7 +59,7 @@ const submitForm = (formEl: FormInstance | undefined) => {
           await initDynamicRouter()
           const { path, queryParams } = parseRedirect()
           router.push({ path: path, query: queryParams })
-          // ElMessage.success('提交成功')
+          ElMessage.success('提交成功')
         }
       })
     } else {
@@ -76,8 +86,9 @@ const parseRedirect = () => {
   url.searchParams.forEach((value, key) => {
     queryParams[key] = value
   })
-
   return { path, queryParams }
 }
 </script>
-<style lang="scss"></style>
+<style lang="scss">
+@use './index';
+</style>

+ 12 - 1
vite.config.ts

@@ -34,7 +34,18 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
       }
     },
     optimizeDeps: {
-      include: ['vue', 'vue-router', 'pinia', 'axios', '@vueuse/core', 'element-plus', '@element-plus/icons-vue']
+      include: [
+        'vue',
+        'vue-router',
+        'pinia',
+        'axios',
+        '@vueuse/core',
+        'element-plus',
+        '@element-plus/icons-vue',
+        'element-plus/es',
+        'element-plus/es/components/base/style/css',
+        'element-plus/es/components/config-provider/style/css'
+      ]
     }
   }
 })