فهرست منبع

init projects

chaooo 2 سال پیش
والد
کامیت
b07fb0294e

+ 1 - 1
.env.development

@@ -3,6 +3,6 @@
 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
 NODE_ENV='development'
 
-VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_TITLE = 'shuimuai-dashboard-h5'
 VITE_APP_PORT = 3000
 VITE_APP_BASE_API = '/dev-api'

+ 1 - 1
.env.production

@@ -1,5 +1,5 @@
 ## 生产环境
 
-VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_TITLE = 'shuimuai-dashboard-h5'
 VITE_APP_PORT = 3000
 VITE_APP_BASE_API = '/prod-api'

+ 1 - 1
.env.staging

@@ -1,6 +1,6 @@
 ## 模拟环境
 NODE_ENV='staging'
 
-VITE_APP_TITLE = 'vue3-element-admin'
+VITE_APP_TITLE = 'shuimuai-dashboard-h5'
 VITE_APP_PORT = 3000
 VITE_APP_BASE_API = '/prod--api'

+ 10 - 13
src/api/auth/index.ts

@@ -1,6 +1,6 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { CaptchaResult, LoginData, LoginResult } from './types';
+import { LoginData, UserInfo, LoginResult } from './types';
 
 /**
  * 登录API
@@ -15,6 +15,15 @@ export function loginApi(data: LoginData): AxiosPromise<LoginResult> {
     params: data
   });
 }
+/**
+ * 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
+ */
+export function getUserInfo(): AxiosPromise<UserInfo> {
+	return request({
+		url: '/api/v1/users/me',
+		method: 'get'
+	});
+}
 
 /**
  * 注销API
@@ -25,15 +34,3 @@ export function logoutApi() {
     method: 'delete'
   });
 }
-
-
-
-/**
- * 获取验证码
- */
-export function getCaptchaApi(): AxiosPromise<CaptchaResult> {
-  return request({
-    url: '/api/v1/auth/captcha',
-    method: 'get'
-  });
-}

+ 11 - 20
src/api/auth/types.ts

@@ -10,16 +10,10 @@ export interface LoginData {
    * 密码
    */
   password?: string;
-
   /**
-   * 验证码缓存key
+   * 是否自动登录
    */
-  verifyCodeKey?: string;
-
-  /**
-   * 验证码
-   */
-  verifyCode?: string;
+  auto?: boolean;
 }
 
 /**
@@ -45,16 +39,13 @@ export interface LoginResult {
 }
 
 /**
- * 验证码响应
+ * 登录用户信息
  */
-export interface CaptchaResult {
-  /**
-   * 验证码缓存key
-   */
-  verifyCodeKey: string;
-  /**
-   * 验证码图片Base64字符串
-   */
-  verifyCodeBase64: string;
-}
-
+export interface UserInfo {
+	userId: number;
+	nickname: string;
+	avatar: string;
+	roles: string[];
+	perms: string[];
+	schoolId: number;
+}

+ 23 - 0
src/api/school/index.ts

@@ -0,0 +1,23 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { SchoolList, ClassList} from './types';
+
+/**
+ * 获取学校列表
+ */
+export function getSchoolList(): AxiosPromise<SchoolList[]> {
+	return request({
+		url: 'http://www.smadmin.com/schools/index',
+		method: 'get'
+	});
+}
+/**
+ * 获取班级列表
+ */
+export function getClassList(id: number): AxiosPromise<ClassList[]> {
+	return request({
+		url: 'http://www.smadmin.com/schools/grade-lists',
+		method: 'get',
+		params: {school_id: id}
+	});
+}

+ 20 - 0
src/api/school/types.ts

@@ -0,0 +1,20 @@
+/**
+ * 学校列表
+ */
+export interface SchoolList {
+  /** 学校id */
+  school_id: number;
+  /** 学校名称 */
+  name: string;
+}
+/**
+ * 班级列表
+ */
+export interface ClassList {
+  /** 班级id */
+  id: number;
+  /** 学校id */
+  school_id: number;
+  /** 学校名称 */
+  name: string;
+}

+ 0 - 154
src/api/user/index.ts

@@ -1,154 +0,0 @@
-import request from '@/utils/request';
-import { AxiosPromise } from 'axios';
-import { UserForm, UserInfo, UserPageVO, UserQuery } from './types';
-
-/**
- * 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
- */
-export function getUserInfo(): AxiosPromise<UserInfo> {
-  return request({
-    url: '/api/v1/users/me',
-    method: 'get'
-  });
-}
-
-/**
- * 获取用户分页列表
- *
- * @param queryParams
- */
-export function getUserPage(
-  queryParams: UserQuery
-): AxiosPromise<PageResult<UserPageVO[]>> {
-  return request({
-    url: '/api/v1/users/page',
-    method: 'get',
-    params: queryParams
-  });
-}
-
-/**
- * 获取用户表单详情
- *
- * @param userId
- */
-export function getUserForm(userId: number): AxiosPromise<UserForm> {
-  return request({
-    url: '/api/v1/users/' + userId + '/form',
-    method: 'get'
-  });
-}
-
-/**
- * 添加用户
- *
- * @param data
- */
-export function addUser(data: any) {
-  return request({
-    url: '/api/v1/users',
-    method: 'post',
-    data: data
-  });
-}
-
-/**
- * 修改用户
- *
- * @param id
- * @param data
- */
-export function updateUser(id: number, data: UserForm) {
-  return request({
-    url: '/api/v1/users/' + id,
-    method: 'put',
-    data: data
-  });
-}
-
-/**
- * 修改用户状态
- *
- * @param id
- * @param status
- */
-export function updateUserStatus(id: number, status: number) {
-  return request({
-    url: '/api/v1/users/' + id + '/status',
-    method: 'patch',
-    params: { status: status }
-  });
-}
-
-/**
- * 修改用户密码
- *
- * @param id
- * @param password
- */
-export function updateUserPassword(id: number, password: string) {
-  return request({
-    url: '/api/v1/users/' + id + '/password',
-    method: 'patch',
-    params: { password: password }
-  });
-}
-
-/**
- * 删除用户
- *
- * @param ids
- */
-export function deleteUsers(ids: string) {
-  return request({
-    url: '/api/v1/users/' + ids,
-    method: 'delete'
-  });
-}
-
-/**
- * 下载用户导入模板
- *
- * @returns
- */
-export function downloadTemplateApi() {
-  return request({
-    url: '/api/v1/users/template',
-    method: 'get',
-    responseType: 'arraybuffer'
-  });
-}
-
-/**
- * 导出用户
- *
- * @param queryParams
- * @returns
- */
-export function exportUser(queryParams: UserQuery) {
-  return request({
-    url: '/api/v1/users/_export',
-    method: 'get',
-    params: queryParams,
-    responseType: 'arraybuffer'
-  });
-}
-
-/**
- * 导入用户
- *
- * @param file
- */
-export function importUser(deptId: number, file: File) {
-  const formData = new FormData();
-  formData.append('file', file);
-  return request({
-    url: '/api/v1/users/_import',
-    method: 'post',
-    params: { deptId: deptId },
-    data: formData,
-    headers: {
-      'Content-Type': 'multipart/form-data'
-    }
-  });
-}

+ 0 - 112
src/api/user/types.ts

@@ -1,112 +0,0 @@
-/**
- * 登录用户信息
- */
-export interface UserInfo {
-  userId: number;
-  nickname: string;
-  avatar: string;
-  roles: string[];
-  perms: string[];
-}
-
-/**
- * 用户查询对象类型
- */
-export interface UserQuery extends PageQuery {
-  keywords?: string;
-  status?: number;
-  deptId?: number;
-}
-
-/**
- * 用户分页对象
- */
-export interface UserPageVO {
-  /**
-   * 用户头像地址
-   */
-  avatar?: string;
-  /**
-   * 创建时间
-   */
-  createTime?: Date;
-  /**
-   * 部门名称
-   */
-  deptName?: string;
-  /**
-   * 用户邮箱
-   */
-  email?: string;
-  /**
-   * 性别
-   */
-  genderLabel?: string;
-  /**
-   * 用户ID
-   */
-  id?: number;
-  /**
-   * 手机号
-   */
-  mobile?: string;
-  /**
-   * 用户昵称
-   */
-  nickname?: string;
-  /**
-   * 角色名称,多个使用英文逗号(,)分割
-   */
-  roleNames?: string;
-  /**
-   * 用户状态(1:启用;0:禁用)
-   */
-  status?: number;
-  /**
-   * 用户名
-   */
-  username?: string;
-}
-
-/**
- * 用户表单类型
- */
-export interface UserForm {
-  /**
-   * 用户头像
-   */
-  avatar?: string;
-  /**
-   * 部门ID
-   */
-  deptId?: number;
-  /**
-   * 邮箱
-   */
-  email?: string;
-  /**
-   * 性别
-   */
-  gender?: number;
-  /**
-   * 用户ID
-   */
-  id?: number;
-  mobile?: string;
-  /**
-   * 昵称
-   */
-  nickname?: string;
-  /**
-   * 角色ID集合
-   */
-  roleIds?: number[];
-  /**
-   * 用户状态(1:正常;0:禁用)
-   */
-  status?: number;
-  /**
-   * 用户名
-   */
-  username?: string;
-}

+ 43 - 7
src/layout/components/Navbar.vue

@@ -4,6 +4,9 @@ import { useRoute, useRouter } from "vue-router";
 import { useAppStore } from "@/store/modules/app";
 import { useTagsViewStore } from "@/store/modules/tagsView";
 import { useUserStore } from "@/store/modules/user";
+import {SchoolList} from "@/api/school/types";
+import {getSchoolList} from "@/api/school";
+import {watch} from "vue";
 
 const appStore = useAppStore();
 const tagsViewStore = useTagsViewStore();
@@ -45,6 +48,32 @@ function logout() {
       });
   });
 }
+/**
+ * 学校数据
+ */
+const schoolData = ref<SchoolList[]>([{
+	school_id: 1,
+	name: "全部学校",
+},{
+	school_id: 2,
+	name: "全部学校2",
+}]);
+const schoolNumber = ref(0);
+function querySchoolList() {
+	getSchoolList().then(({ data }) => {
+	  schoolData.value.concat(data);
+	}).catch(error => {
+		console.log(error)
+	});
+}
+onMounted(() => {
+	// querySchoolList();
+	// changeSchool();
+});
+watch(() => schoolNumber.value, (newValue, oldValue) => {
+	//console.log("NAV-watch", newValue, oldValue);
+	userStore.changeSchool(schoolNumber.value);
+})
 </script>
 
 <template>
@@ -52,13 +81,19 @@ function logout() {
   <div class="navbar">
     <!-- 左侧面包屑 -->
     <div class="flex">
-      <hamburger
-        :is-active="appStore.sidebar.opened"
-        @toggle-click="toggleSideBar"
-      />
+      <hamburger :is-active="appStore.sidebar.opened" @toggle-click="toggleSideBar" />
       <breadcrumb />
     </div>
-
+		<div class="flex">
+		  <el-select v-model="schoolNumber" class="m-2" placeholder="全部学校">
+			  <el-option
+					  v-for="item in schoolData"
+					  :key="item.school_id"
+					  :label="item.name"
+					  :value="item.school_id"
+			  />
+		  </el-select>
+		</div>
     <!-- 右侧导航设置 -->
     <div class="flex">
       <!-- 导航栏设置(窄屏隐藏)-->
@@ -73,13 +108,14 @@ function logout() {
         <el-tooltip content="布局大小" effect="dark" placement="bottom">
           <size-select class="setting-item" />
         </el-tooltip>
-        <!--语言选择-->
-        <lang-select class="setting-item" />
       </div>
 
       <!-- 用户头像 -->
       <el-dropdown trigger="click">
         <div class="avatar-container">
+					<span class="ml-[10px] text-[16px]">
+						{{ userStore.nickname }}
+					</span>
           <img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" />
           <i-ep-caret-bottom class="w-3 h-3" />
         </div>

+ 11 - 5
src/store/modules/user.ts

@@ -1,12 +1,10 @@
 import { defineStore } from "pinia";
 
-import { loginApi, logoutApi } from "@/api/auth";
-import { getUserInfo } from "@/api/user";
+import { loginApi, logoutApi, getUserInfo } from "@/api/auth";
 import { resetRouter } from "@/router";
 import { store } from "@/store";
 
-import { LoginData } from "@/api/auth/types";
-import { UserInfo } from "@/api/user/types";
+import { LoginData, UserInfo } from "@/api/auth/types";
 
 import { useStorage } from "@vueuse/core";
 
@@ -18,7 +16,7 @@ export const useUserStore = defineStore("user", () => {
   const avatar = ref("");
   const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
   const perms = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
-
+  const schoolId = ref(0);
   /**
    * 登录调用
    *
@@ -87,6 +85,11 @@ export const useUserStore = defineStore("user", () => {
     roles.value = [];
     perms.value = [];
   }
+  // 切换学校
+  function changeSchool(id: number){
+	  schoolId.value = id;
+  }
+
   return {
     token,
     nickname,
@@ -97,10 +100,13 @@ export const useUserStore = defineStore("user", () => {
     getInfo,
     logout,
     resetToken,
+    changeSchool,
     /**
      * 当前登录用户ID
      */
     userId,
+	schoolId,
+
   };
 });
 

+ 19 - 3
src/views/class/index.vue

@@ -1,17 +1,33 @@
 <!-- setup 无法设置组件名称,组件名称keepAlive必须 -->
 <script lang="ts">
-export default {
-	name: "",
-};
+
+// export default {
+// 	name: "",
+// 	data() {
+// 		return {
+//
+// 		}
+// 	},
+// 	mounted() {
+//
+// 	}
+// };
 </script>
 
 <script setup lang="ts">
+//import { watch } from 'vue';
+import {useUserStore} from "@/store/modules/user";
+const userStore = useUserStore();
 
+// watch(() => userStore.schoolId, (newValue, oldValue) => {
+// 	console.log(newValue, oldValue);
+// })
 </script>
 
 <template>
 	<div class="container">
 		<h1>班级管理</h1>
+<div>{{userStore.schoolId}}</div>
 	</div>
 </template>
 

+ 104 - 105
src/views/dashboard/index.vue

@@ -1,115 +1,113 @@
 <script setup lang="ts">
-defineOptions({
-  // eslint-disable-next-line vue/no-reserved-component-names
-  name: "Dashboard",
-  inheritAttrs: false,
-});
-
-import { useUserStore } from "@/store/modules/user";
-import { useTransition, TransitionPresets } from "@vueuse/core";
-
-import GithubCorner from "@/components/GithubCorner/index.vue";
+// defineOptions({
+//   // eslint-disable-next-line vue/no-reserved-component-names
+//   name: "Dashboard",
+//   inheritAttrs: false,
+// });
 import SvgIcon from "@/components/SvgIcon/index.vue";
 import BarChart from "./components/BarChart.vue";
 import PieChart from "./components/PieChart.vue";
 import RadarChart from "./components/RadarChart.vue";
-
-const userStore = useUserStore();
-
-const date: Date = new Date();
-
-const greetings = computed(() => {
-  if (date.getHours() >= 6 && date.getHours() < 8) {
-    return "晨起披衣出草堂,轩窗已自喜微凉🌅!";
-  } else if (date.getHours() >= 8 && date.getHours() < 12) {
-    return "上午好🌞!";
-  } else if (date.getHours() >= 12 && date.getHours() < 18) {
-    return "下午好☕!";
-  } else if (date.getHours() >= 18 && date.getHours() < 24) {
-    return "晚上好🌃!";
-  } else if (date.getHours() >= 0 && date.getHours() < 6) {
-    return "偷偷向银河要了一把碎星,只等你闭上眼睛撒入你的梦中,晚安🌛!";
-  }
-});
+import { useTransition, TransitionPresets } from "@vueuse/core";
+import {getClassList, getSchoolList} from "@/api/school";
+import {ClassList} from "@/api/school/types";
 
 const duration = 5000;
-
-// 收入金额
-const amount = ref(0);
-const amountOutput = useTransition(amount, {
+/**
+ * 数据卡片
+ */
+// 全部班级
+const classCount = ref(0);
+const classCountOutput = useTransition(classCount, {
   duration: duration,
   transition: TransitionPresets.easeOutExpo,
 });
-amount.value = 2000;
+classCount.value = 2000;
 
-// 访问数
-const visitCount = ref(0);
-const visitCountOutput = useTransition(visitCount, {
+// 全部教师
+const teacherCount = ref(0);
+const teacherCountOutput = useTransition(teacherCount, {
   duration: duration,
   transition: TransitionPresets.easeOutExpo,
 });
-visitCount.value = 2000;
+teacherCount.value = 2000;
 
-//消息数
-const messageCount = ref(0);
-const messageCountOutput = useTransition(messageCount, {
+// 全部学生
+const studentCount = ref(0);
+const studentCountOutput = useTransition(studentCount, {
   duration: duration,
   transition: TransitionPresets.easeOutExpo,
 });
-messageCount.value = 2000;
+studentCount.value = 2000;
 
-// 订单
-const orderCount = ref(0);
-const orderCountOutput = useTransition(orderCount, {
+// 设备套
+const equipmentCount = ref(0);
+const equipmentCountOutput = useTransition(equipmentCount, {
   duration: duration,
   transition: TransitionPresets.easeOutExpo,
 });
-orderCount.value = 2000;
+equipmentCount.value = 2000;
+
+// 累计训练次数
+const trainingCount = ref(0);
+const trainingCountOutput = useTransition(trainingCount, {
+	duration: duration,
+	transition: TransitionPresets.easeOutExpo,
+});
+trainingCount.value = 2000;
+/**
+ * 班级数据
+ */
+let classNumber = ref(0);
+const classData = ref<ClassList[]>([]);
+// function queryClassList() {
+// 	getClassList().then(({ data }) => {
+// 		classData.value = data;
+// 	});
+// }
+onMounted(() => {
+	//queryClassList();
+});
 </script>
 
 <template>
   <div class="dashboard-container">
-    <!-- 用户信息 -->
-    <el-row class="mb-8">
-      <el-card class="w-full">
-        <div class="flex justify-between flex-wrap">
-          <div class="flex items-center">
-            <img
-              class="user-avatar"
-              :src="userStore.avatar + '?imageView2/1/w/80/h/80'"
-            />
-            <span class="ml-[10px] text-[16px]">
-              {{ userStore.nickname }}
-            </span>
-          </div>
-
-          <div class="leading-[40px]">
-            {{ greetings }}
-          </div>
-        </div>
-      </el-card>
-    </el-row>
-
     <!-- 数据卡片 -->
     <el-row :gutter="40" class="mb-4">
-      <el-col :xs="24" :sm="12" :lg="6" class="mb-4">
+      <el-col :xs="24" :sm="8" :lg="5" class="mb-4">
         <div class="data-box">
-          <div
-            class="text-[#40c9c6] hover:!text-white hover:bg-[#40c9c6] p-3 rounded"
-          >
+          <div class="text-[#40c9c6] hover:!text-white hover:bg-[#40c9c6] p-3 rounded">
             <svg-icon icon-class="uv" size="3em" />
           </div>
           <div class="flex flex-col space-y-3">
-            <div class="text-[var(--el-text-color-secondary)]">访问数</div>
-            <div class="text-lg">
-              {{ Math.round(visitCountOutput) }}
-            </div>
+            <div class="text-[var(--el-text-color-secondary)]">全部班级</div>
+            <div class="text-lg">{{ Math.round(classCountOutput) }}</div>
           </div>
         </div>
       </el-col>
-
-      <!--消息数-->
-      <el-col :xs="24" :sm="12" :lg="6" class="mb-4">
+			<el-col :xs="24" :sm="8" :lg="5" class="mb-4">
+				<div class="data-box">
+					<div class="text-[#40c9c6] hover:!text-white hover:bg-[#40c9c6] p-3 rounded">
+						<svg-icon icon-class="uv" size="3em" />
+					</div>
+					<div class="flex flex-col space-y-3">
+						<div class="text-[var(--el-text-color-secondary)]">全部教师</div>
+						<div class="text-lg">{{ Math.round(teacherCountOutput) }}</div>
+					</div>
+				</div>
+			</el-col>
+			<el-col :xs="24" :sm="8" :lg="5" class="mb-4">
+				<div class="data-box">
+					<div class="text-[#40c9c6] hover:!text-white hover:bg-[#40c9c6] p-3 rounded">
+						<svg-icon icon-class="uv" size="3em" />
+					</div>
+					<div class="flex flex-col space-y-3">
+						<div class="text-[var(--el-text-color-secondary)]">全部学生</div>
+						<div class="text-lg">{{ Math.round(studentCountOutput) }}</div>
+					</div>
+				</div>
+			</el-col>
+      <el-col :xs="24" :sm="8" :lg="5" class="mb-4">
         <div class="data-box">
           <div
             class="text-[#36a3f7] hover:!text-white hover:bg-[#36a3f7] p-3 rounded"
@@ -117,15 +115,14 @@ orderCount.value = 2000;
             <svg-icon icon-class="message" size="3em" />
           </div>
           <div class="flex flex-col space-y-3">
-            <div class="text-[var(--el-text-color-secondary)]">消息数</div>
+            <div class="text-[var(--el-text-color-secondary)]">设备套数</div>
             <div class="text-lg">
-              {{ Math.round(messageCountOutput) }}
+              {{ Math.round(equipmentCountOutput) }}
             </div>
           </div>
         </div>
       </el-col>
-
-      <el-col :xs="24" :sm="12" :lg="6" class="mb-4">
+      <el-col :xs="24" :sm="8" :lg="5" class="mb-4">
         <div class="data-box">
           <div
             class="text-[#f4516c] hover:!text-white hover:bg-[#f4516c] p-3 rounded"
@@ -133,29 +130,31 @@ orderCount.value = 2000;
             <svg-icon icon-class="money" size="3em" />
           </div>
           <div class="flex flex-col space-y-3">
-            <div class="text-[var(--el-text-color-secondary)]">收入金额</div>
+            <div class="text-[var(--el-text-color-secondary)]">累计训练次数</div>
             <div class="text-lg">
-              {{ Math.round(amountOutput) }}
-            </div>
-          </div>
-        </div>
-      </el-col>
-      <el-col :xs="24" :sm="12" :lg="6" class="mb-2">
-        <div class="data-box">
-          <div
-            class="text-[#34bfa3] hover:!text-white hover:bg-[#34bfa3] p-3 rounded"
-          >
-            <svg-icon icon-class="shopping" size="3em" />
-          </div>
-          <div class="flex flex-col space-y-3">
-            <div class="text-[var(--el-text-color-secondary)]">订单数</div>
-            <div class="text-lg">
-              {{ Math.round(orderCountOutput) }}
+              {{ Math.round(trainingCountOutput) }}
             </div>
           </div>
         </div>
       </el-col>
     </el-row>
+	  <!-- 班级选择 及 案例展示 -->
+	  <el-row class="row-bg" justify="space-between">
+		  <el-col :span="12">
+				<el-select v-model="classNumber" class="m-2" placeholder="全部班级">
+					<el-option
+							v-for="item in classData"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id"
+					/>
+				</el-select>
+			</el-col>
+		  <el-col :span="12">
+		  	<el-link href="#" type="primary">优秀教学效果示例</el-link>
+			</el-col>
+	  </el-row>
+
 
     <!-- Echarts 图表 -->
     <el-row :gutter="40">
@@ -200,13 +199,13 @@ orderCount.value = 2000;
     border-radius: 50%;
   }
 
-  .github-corner {
-    position: absolute;
-    top: 0;
-    right: 0;
-    z-index: 99;
-    border: 0;
-  }
+  @media only screen and (min-width: 1200px){
+		.el-col-lg-5 {
+			display: block;
+			max-width: 20%;
+			flex: 0 0 20%;
+		}
+	}
 
   .data-box {
     display: flex;

+ 6 - 10
src/views/login/index.vue

@@ -45,13 +45,15 @@
           />
           <span class="mr-2" @click="passwordVisible = !passwordVisible">
             <svg-icon
-              :icon-class="passwordVisible === false ? 'eye' : 'eye-open'"
+              :icon-class="!passwordVisible ? 'eye' : 'eye-open'"
               class="text-white cursor-pointer"
             />
           </span>
         </el-form-item>
       </el-tooltip>
 
+		<el-checkbox v-model="loginData.auto" label="自动登录" size="large" />
+
       <el-button
         size="default"
         :loading="loading"
@@ -80,7 +82,6 @@ import { useUserStore } from "@/store/modules/user";
 
 // API依赖
 import { LocationQuery, LocationQueryValue, useRoute } from "vue-router";
-import { getCaptchaApi } from "@/api/auth";
 import { LoginData } from "@/api/auth/types";
 
 const userStore = useUserStore();
@@ -98,10 +99,6 @@ const isCapslock = ref(false);
  * 密码是否可见
  */
 const passwordVisible = ref(false);
-/**
- * 验证码图片Base64字符串
- */
-const captchaBase64 = ref();
 
 /**
  * 登录表单引用
@@ -111,10 +108,11 @@ const loginFormRef = ref(ElForm);
 const loginData = ref<LoginData>({
   username: "admin",
   password: "123456",
+	auto: true,
 });
 
 const loginRules = {
-  username: [{ required: true, trigger: "blur" }],
+  username: [{ required: true, trigger: "blur"}],
   password: [{ required: true, trigger: "blur", validator: passwordValidator }],
 };
 
@@ -144,9 +142,7 @@ function handleLogin() {
   loginFormRef.value.validate((valid: boolean) => {
     if (valid) {
       loading.value = true;
-      userStore
-        .login(loginData.value)
-        .then(() => {
+      userStore.login(loginData.value).then(() => {
           const query: LocationQuery = route.query;
           const redirect = (query.redirect as LocationQueryValue) ?? "/";
           const otherQueryParams = Object.keys(query).reduce(