Эх сурвалжийг харах

Refactor layout and user store components for improved code consistency and readability. Adjust template formatting in `index.vue`, enhance user information handling in `user.ts`, and update type definitions in `index.ts` for better clarity and maintainability.

yb 3 долоо хоног өмнө
parent
commit
7b734d7a2e
3 өөрчлөгдсөн 180 нэмэгдсэн , 158 устгасан
  1. 45 27
      src/layout/index.vue
  2. 39 33
      src/store/user.ts
  3. 96 98
      src/types/index.ts

+ 45 - 27
src/layout/index.vue

@@ -1,6 +1,9 @@
 <template>
   <el-container class="app-wrapper">
-    <el-aside :width="sidebarOpened ? '210px' : '64px'" class="sidebar-container">
+    <el-aside
+      :width="sidebarOpened ? '210px' : '64px'"
+      class="sidebar-container"
+    >
       <div class="logo">
         <img src="@/assets/logo.svg" alt="logo" />
         <h1 v-show="sidebarOpened">摄像头管理</h1>
@@ -65,8 +68,11 @@
         <div class="header-right">
           <el-dropdown @command="handleCommand">
             <span class="user-info">
-              <el-avatar :size="32" :src="userInfo?.avatar" />
-              <span class="username">{{ userInfo?.nickName || '用户' }}</span>
+              <el-avatar
+                :size="32"
+                :src="'https://cube.elemecdn.com/0/88/03b0d39583f4b3a790e9d12d41f23e23jps.jpg'"
+              />
+              <span class="username">{{ userInfo?.username }}</span>
               <el-icon><ArrowDown /></el-icon>
             </span>
             <template #dropdown>
@@ -90,43 +96,55 @@
 </template>
 
 <script setup lang="ts">
-import { computed, onMounted } from 'vue'
-import { useRoute, useRouter } from 'vue-router'
-import { VideoCamera, Fold, Expand, ArrowDown, Monitor, Film, VideoCameraFilled, Setting, UserFilled } from '@element-plus/icons-vue'
-import { useAppStore } from '@/store/app'
-import { useUserStore } from '@/store/user'
-
-const route = useRoute()
-const router = useRouter()
-const appStore = useAppStore()
-const userStore = useUserStore()
-
-const sidebarOpened = computed(() => appStore.sidebarOpened)
-const userInfo = computed(() => userStore.userInfo)
+import { computed, onMounted } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import {
+  VideoCamera,
+  Fold,
+  Expand,
+  ArrowDown,
+  Monitor,
+  Film,
+  VideoCameraFilled,
+  Setting,
+  UserFilled,
+} from "@element-plus/icons-vue";
+import { useAppStore } from "@/store/app";
+import { useUserStore } from "@/store/user";
+
+const route = useRoute();
+const router = useRouter();
+const appStore = useAppStore();
+const userStore = useUserStore();
+
+const sidebarOpened = computed(() => appStore.sidebarOpened);
+const userInfo = computed(() => userStore.userInfo);
 
 const activeMenu = computed(() => {
-  const { path } = route
-  return path
-})
+  const { path } = route;
+  return path;
+});
 
 const breadcrumbs = computed(() => {
-  return route.matched.filter(item => item.meta && item.meta.title && !item.meta.hidden)
-})
+  return route.matched.filter(
+    (item) => item.meta && item.meta.title && !item.meta.hidden
+  );
+});
 
 function toggleSidebar() {
-  appStore.toggleSidebar()
+  appStore.toggleSidebar();
 }
 
 async function handleCommand(command: string) {
-  if (command === 'logout') {
-    await userStore.logoutAction()
-    router.push('/login')
+  if (command === "logout") {
+    await userStore.logoutAction();
+    router.push("/login");
   }
 }
 
 onMounted(() => {
-  userStore.getUserInfo()
-})
+  userStore.getUserInfo();
+});
 </script>
 
 <style lang="scss" scoped>

+ 39 - 33
src/store/user.ts

@@ -1,61 +1,67 @@
-import { defineStore } from 'pinia'
-import { ref } from 'vue'
-import type { UserInfo } from '@/types'
-import { getToken, setToken, removeToken, setRefreshToken, removeRefreshToken } from '@/utils/auth'
-import { login, logout, getInfo } from '@/api/login'
-import type { LoginParams } from '@/types'
+import { defineStore } from "pinia";
+import { ref } from "vue";
+import type { UserInfo } from "@/types";
+import {
+  getToken,
+  setToken,
+  removeToken,
+  setRefreshToken,
+  removeRefreshToken,
+} from "@/utils/auth";
+import { login, logout, getInfo } from "@/api/login";
+import type { LoginParams } from "@/types";
 
-export const useUserStore = defineStore('user', () => {
-  const token = ref<string>(getToken() || '')
-  const userInfo = ref<UserInfo | null>(null)
+export const useUserStore = defineStore("user", () => {
+  const token = ref<string>(getToken() || "");
+  const userInfo = ref<UserInfo | null>(null);
 
   async function loginAction(loginForm: LoginParams) {
-    const res = await login(loginForm)
+    const res = await login(loginForm);
     if (res.code === 200 && res.data) {
       // Hono API 返回 accessToken 和 refreshToken
-      const { accessToken, refreshToken, user } = res.data
-      token.value = accessToken
-      setToken(accessToken)
+      const { accessToken, refreshToken, user } = res.data;
+      token.value = accessToken;
+      setToken(accessToken);
       if (refreshToken) {
-        setRefreshToken(refreshToken)
+        setRefreshToken(refreshToken);
       }
       // 直接设置用户信息
       if (user) {
         userInfo.value = {
-          userId: user.id,
+          userId: parseInt(user.id),
           userName: user.username,
           nickName: user.username,
-          roles: [user.role]
-        } as UserInfo
+          roles: [user.role],
+        };
       }
     }
-    return res
+    return res;
   }
 
   async function getUserInfo() {
-    const res = await getInfo()
+    const res = await getInfo();
     if (res.code === 200 && res.data) {
-      userInfo.value = res.data
+      userInfo.value = res.data;
     }
-    return res
+    return res;
   }
 
   async function logoutAction() {
     try {
-      await logout()
+      await logout();
     } finally {
-      token.value = ''
-      userInfo.value = null
-      removeToken()
-      removeRefreshToken()
+      token.value = "";
+      userInfo.value = null;
+      removeToken();
+      removeRefreshToken();
     }
   }
 
   function resetToken() {
-    token.value = ''
-    userInfo.value = null
-    removeToken()
-    removeRefreshToken()
+    token.value = "";
+    userInfo.value = null;
+    removeToken();
+    removeRefreshToken();
   }
 
   return {
@@ -64,6 +70,6 @@ export const useUserStore = defineStore('user', () => {
     loginAction,
     getUserInfo,
     logoutAction,
-    resetToken
-  }
-})
+    resetToken,
+  };
+});

+ 96 - 98
src/types/index.ts

@@ -1,132 +1,130 @@
-// API 响应类型 - 兼容 RuoYi 后端格式
+// API 响应类型
 export interface ApiResponse<T = any> {
-  code: number
-  msg: string
-  data: T
-  // RuoYi 特殊字段(有时候数据直接在顶层)
-  token?: string
-  user?: any
-  rows?: any[]
-  total?: number
+  code: number;
+  msg: string;
+  data: T;
 }
 
 // 分页参数
 export interface PageParams {
-  pageNum: number
-  pageSize: number
+  pageNum: number;
+  pageSize: number;
 }
 
 // 分页响应
 export interface PageResult<T = any> {
-  total: number
-  rows: T[]
+  total: number;
+  rows: T[];
 }
 
 // 用户信息
 export interface UserInfo {
-  userId: number
-  userName: string
-  nickName: string
-  avatar: string
-  token: string
+  created_at: number;
+  email: string;
+  id: string;
+  last_login: number;
+  role: string;
+  status: string;
+  updated_at: number;
+  username: string;
 }
 
 // 登录参数
 export interface LoginParams {
-  username: string
-  password: string
-  code?: string
-  uuid?: string
+  username: string;
+  password: string;
+  code?: string;
+  uuid?: string;
 }
 
 // 摄像头设备
 export interface CameraDevice {
-  deviceId: string
-  deviceName: string
-  manufacturer?: string
-  model?: string
-  firmware?: string
-  transport?: string
-  streamMode?: string
-  online: boolean
-  registerTime?: string
-  keepaliveTime?: string
-  ip?: string
-  port?: number
-  hostAddress?: string
-  charset?: string
-  subscribeCycleForCatalog?: number
-  subscribeCycleForMobilePosition?: number
-  mobilePositionSubmissionInterval?: number
-  subscribeCycleForAlarm?: number
-  ssrcCheck?: boolean
-  geoCoordSys?: string
-  treeType?: string
-  password?: string
-  asMessageChannel?: boolean
-  broadcastPushAfterAck?: boolean
-  createTime?: string
-  updateTime?: string
-  channelCount?: number
+  deviceId: string;
+  deviceName: string;
+  manufacturer?: string;
+  model?: string;
+  firmware?: string;
+  transport?: string;
+  streamMode?: string;
+  online: boolean;
+  registerTime?: string;
+  keepaliveTime?: string;
+  ip?: string;
+  port?: number;
+  hostAddress?: string;
+  charset?: string;
+  subscribeCycleForCatalog?: number;
+  subscribeCycleForMobilePosition?: number;
+  mobilePositionSubmissionInterval?: number;
+  subscribeCycleForAlarm?: number;
+  ssrcCheck?: boolean;
+  geoCoordSys?: string;
+  treeType?: string;
+  password?: string;
+  asMessageChannel?: boolean;
+  broadcastPushAfterAck?: boolean;
+  createTime?: string;
+  updateTime?: string;
+  channelCount?: number;
 }
 
 // 摄像头通道
 export interface CameraChannel {
-  channelId: string
-  deviceId: string
-  name: string
-  manufacturer?: string
-  model?: string
-  owner?: string
-  civilCode?: string
-  block?: string
-  address?: string
-  parental?: number
-  parentId?: string
-  safetyWay?: number
-  registerWay?: number
-  certNum?: string
-  certifiable?: number
-  errCode?: number
-  endTime?: string
-  secrecy?: number
-  ipAddress?: string
-  port?: number
-  password?: string
-  ptzType?: number
-  status?: boolean
-  longitude?: number
-  latitude?: number
-  longitudeGcj02?: number
-  latitudeGcj02?: number
-  longitudeWgs84?: number
-  latitudeWgs84?: number
-  hasAudio?: boolean
-  createTime?: string
-  updateTime?: string
-  businessGroupId?: string
-  gpsTime?: string
+  channelId: string;
+  deviceId: string;
+  name: string;
+  manufacturer?: string;
+  model?: string;
+  owner?: string;
+  civilCode?: string;
+  block?: string;
+  address?: string;
+  parental?: number;
+  parentId?: string;
+  safetyWay?: number;
+  registerWay?: number;
+  certNum?: string;
+  certifiable?: number;
+  errCode?: number;
+  endTime?: string;
+  secrecy?: number;
+  ipAddress?: string;
+  port?: number;
+  password?: string;
+  ptzType?: number;
+  status?: boolean;
+  longitude?: number;
+  latitude?: number;
+  longitudeGcj02?: number;
+  latitudeGcj02?: number;
+  longitudeWgs84?: number;
+  latitudeWgs84?: number;
+  hasAudio?: boolean;
+  createTime?: string;
+  updateTime?: string;
+  businessGroupId?: string;
+  gpsTime?: string;
 }
 
 // 录像记录
 export interface RecordItem {
-  name?: string
-  start: number
-  end: number
-  secrecy?: number
-  type?: string
+  name?: string;
+  start: number;
+  end: number;
+  secrecy?: number;
+  type?: string;
 }
 
 // 播放响应
 export interface PlayResponse {
-  streamId: string
-  flv: string
-  ws_flv?: string
-  rtsp?: string
-  rtmp?: string
-  hls?: string
-  rtc?: string
-  mediaServerId?: string
-  deviceId?: string
-  channelId?: string
+  streamId: string;
+  flv: string;
+  ws_flv?: string;
+  rtsp?: string;
+  rtmp?: string;
+  hls?: string;
+  rtc?: string;
+  mediaServerId?: string;
+  deviceId?: string;
+  channelId?: string;
 }