亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码

API和狀態(tài)管理配置

API和狀態(tài)管理配置指南

API 配置

1. 請求攔截器配置

編輯 src/utils/request/index.ts 文件:

import axios from 'axios';
import { MessagePlugin } from 'tdesign-vue-next';

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
});

// 請求攔截器
request.interceptors.request.use(
  (config) => {
    // 添加認證token
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 添加其他請求頭
    config.headers['X-Requested-With'] = 'XMLHttpRequest';
    config.headers['Content-Type'] = 'application/json';
    
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

2. 響應攔截器配置

// 響應攔截器
request.interceptors.response.use(
  (response) => {
    const { code, data, message } = response.data;
    
    // 根據您的后端API格式調整
    if (code === 200 || code === 0) {
      return data;
    } else {
      // 錯誤處理
      MessagePlugin.error(message || '請求失敗');
      return Promise.reject(new Error(message));
    }
  },
  (error) => {
    // 網(wǎng)絡(luò )錯誤處理
    if (error.response?.status === 401) {
      // 未授權,跳轉到登錄頁(yè)
      localStorage.removeItem('token');
      window.location.href = '/login';
    } else if (error.response?.status === 403) {
      MessagePlugin.error('無(wú)權限訪(fǎng)問(wèn)');
    } else if (error.response?.status === 500) {
      MessagePlugin.error('服務(wù)器內部錯誤');
    } else {
      MessagePlugin.error(error.message || '網(wǎng)絡(luò )錯誤');
    }
    
    return Promise.reject(error);
  }
);

export default request;

3. API接口定義

src/api/ 目錄下創(chuàng )建API模塊:

// src/api/user.ts
import request from '@/utils/request';

export interface User {
  id: number;
  username: string;
  email: string;
  avatar?: string;
  roles: string[];
}

export interface UserListParams {
  page: number;
  size: number;
  keyword?: string;
}

export interface UserListResponse {
  list: User[];
  total: number;
}

// 獲取用戶(hù)列表
export function getUserList(params: UserListParams) {
  return request.get<UserListResponse>('/api/users', { params });
}

// 獲取用戶(hù)詳情
export function getUserDetail(id: number) {
  return request.get<User>(`/api/users/${id}`);
}

// 創(chuàng  )建用戶(hù)
export function createUser(data: Partial<User>) {
  return request.post<User>('/api/users', data);
}

// 更新用戶(hù)
export function updateUser(id: number, data: Partial<User>) {
  return request.put<User>(`/api/users/${id}`, data);
}

// 刪除用戶(hù)
export function deleteUser(id: number) {
  return request.delete(`/api/users/${id}`);
}

4. 文件上傳API

// src/api/upload.ts
import request from '@/utils/request';

export interface UploadResponse {
  url: string;
  filename: string;
  size: number;
}

export function uploadFile(file: File, onProgress?: (progress: number) => void) {
  const formData = new FormData();
  formData.append('file', file);
  
  return request.post<UploadResponse>('/api/upload', formData, {
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    onUploadProgress: (progressEvent) => {
      if (onProgress && progressEvent.total) {
        const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        onProgress(progress);
      }
    },
  });
}

狀態(tài)管理配置

1. 創(chuàng )建用戶(hù)Store

// src/store/modules/user.ts
import { defineStore } from 'pinia';
import { getUserDetail, type User } from '@/api/user';

export interface UserState {
  userInfo: User | null;
  token: string;
  permissions: string[];
  roles: string[];
}

export const useUserStore = defineStore('user', {
  state: (): UserState => ({
    userInfo: null,
    token: '',
    permissions: [],
    roles: [],
  }),
  
  getters: {
    isLoggedIn: (state) => !!state.token,
    hasRole: (state) => (role: string) => state.roles.includes(role),
    hasPermission: (state) => (permission: string) => state.permissions.includes(permission),
    avatar: (state) => state.userInfo?.avatar || '/default-avatar.png',
    username: (state) => state.userInfo?.username || '',
  },
  
  actions: {
    // 登錄
    async login(credentials: { username: string; password: string }) {
      try {
        const response = await loginApi(credentials);
        this.token = response.token;
        this.userInfo = response.userInfo;
        this.permissions = response.permissions;
        this.roles = response.roles;
        
        // 保存token到localStorage
        localStorage.setItem('token', this.token);
        
        return response;
      } catch (error) {
        throw error;
      }
    },
    
    // 獲取用戶(hù)信息
    async fetchUserInfo() {
      if (!this.token) return;
      
      try {
        const userInfo = await getUserDetail();
        this.userInfo = userInfo;
        this.permissions = userInfo.permissions;
        this.roles = userInfo.roles;
      } catch (error) {
        this.logout();
        throw error;
      }
    },
    
    // 登出
    logout() {
      this.userInfo = null;
      this.token = '';
      this.permissions = [];
      this.roles = [];
      localStorage.removeItem('token');
    },
    
    // 更新用戶(hù)信息
    updateUserInfo(userInfo: Partial<User>) {
      if (this.userInfo) {
        this.userInfo = { ...this.userInfo, ...userInfo };
      }
    },
  },
  
  // 持久化配置
  persist: {
    key: 'user-store',
    storage: localStorage,
    paths: ['token', 'userInfo', 'permissions', 'roles'],
  },
});

2. 創(chuàng )建應用設置Store

// src/store/modules/setting.ts
import { defineStore } from 'pinia';

export interface SettingState {
  theme: 'light' | 'dark';
  language: 'zh_CN' | 'en_US';
  sidebarCollapsed: boolean;
  primaryColor: string;
  layout: 'side' | 'top' | 'mix';
}

export const useSettingStore = defineStore('setting', {
  state: (): SettingState => ({
    theme: 'light',
    language: 'zh_CN',
    sidebarCollapsed: false,
    primaryColor: '#0052d9',
    layout: 'side',
  }),
  
  getters: {
    isDark: (state) => state.theme === 'dark',
    isCollapsed: (state) => state.sidebarCollapsed,
  },
  
  actions: {
    // 切換主題
    toggleTheme() {
      this.theme = this.theme === 'light' ? 'dark' : 'light';
      this.applyTheme();
    },
    
    // 設置主題
    setTheme(theme: 'light' | 'dark') {
      this.theme = theme;
      this.applyTheme();
    },
    
    // 應用主題
    applyTheme() {
      document.documentElement.setAttribute('theme-mode', this.theme);
    },
    
    // 切換側邊欄
    toggleSidebar() {
      this.sidebarCollapsed = !this.sidebarCollapsed;
    },
    
    // 設置語(yǔ)言
    setLanguage(language: 'zh_CN' | 'en_US') {
      this.language = language;
    },
    
    // 設置主色調
    setPrimaryColor(color: string) {
      this.primaryColor = color;
      this.applyPrimaryColor();
    },
    
    // 應用主色調
    applyPrimaryColor() {
      document.documentElement.style.setProperty('--td-brand-color', this.primaryColor);
    },
    
    // 設置布局
    setLayout(layout: 'side' | 'top' | 'mix') {
      this.layout = layout;
    },
  },
  
  persist: {
    key: 'setting-store',
    storage: localStorage,
  },
});

3. 在組件中使用Store

<template>
  <div class="user-profile">
    <t-avatar :image="userStore.avatar" />
    <span>{{ userStore.username }}</span>
    <t-button @click="handleLogout">退出登錄</t-button>
  </div>
</template>

<script setup lang="ts">
import { useUserStore } from '@/store/modules/user';
import { useRouter } from 'vue-router';

const userStore = useUserStore();
const router = useRouter();

const handleLogout = async () => {
  userStore.logout();
  router.push('/login');
};
</script>

4. 數據緩存Store

// src/store/modules/cache.ts
import { defineStore } from 'pinia';

export interface CacheState {
  dictData: Record<string, any[]>;
  userList: any[];
  lastFetchTime: Record<string, number>;
}

export const useCacheStore = defineStore('cache', {
  state: (): CacheState => ({
    dictData: {},
    userList: [],
    lastFetchTime: {},
  }),
  
  getters: {
    // 獲取字典數據
    getDictData: (state) => (key: string) => state.dictData[key] || [],
    
    // 檢查緩存是否過(guò)期
    isCacheExpired: (state) => (key: string, expireTime = 5 * 60 * 1000) => {
      const lastTime = state.lastFetchTime[key];
      return !lastTime || Date.now() - lastTime > expireTime;
    },
  },
  
  actions: {
    // 設置字典數據
    setDictData(key: string, data: any[]) {
      this.dictData[key] = data;
      this.lastFetchTime[key] = Date.now();
    },
    
    // 清除緩存
    clearCache(key?: string) {
      if (key) {
        delete this.dictData[key];
        delete this.lastFetchTime[key];
      } else {
        this.dictData = {};
        this.lastFetchTime = {};
      }
    },
    
    // 獲取或刷新數據
    async getOrFetchData(key: string, fetchFn: () => Promise<any[]>) {
      if (!this.isCacheExpired(key)) {
        return this.getDictData(key);
      }
      
      try {
        const data = await fetchFn();
        this.setDictData(key, data);
        return data;
      } catch (error) {
        console.error(`獲取${key}數據失敗:`, error);
        return this.getDictData(key);
      }
    },
  },
});

5. 組合式API封裝

// src/composables/useApi.ts
import { ref, reactive } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next';

export function useApi<T = any>(apiFn: (...args: any[]) => Promise<T>) {
  const loading = ref(false);
  const error = ref<string>('');
  const data = ref<T | null>(null);
  
  const execute = async (...args: any[]) => {
    loading.value = true;
    error.value = '';
    
    try {
      const result = await apiFn(...args);
      data.value = result;
      return result;
    } catch (err: any) {
      error.value = err.message || '請求失敗';
      MessagePlugin.error(error.value);
      throw err;
    } finally {
      loading.value = false;
    }
  };
  
  return {
    loading,
    error,
    data,
    execute,
  };
}

// 使用示例
const { loading, data, execute } = useApi(getUserList);

// 調用API
await execute({ page: 1, size: 10 });

文章目錄

    亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码