Vue3.5 企業級管理系統實戰(十八):用戶管理

本篇主要探討用戶管理功能,接口部分依然是使用 Apifox mock 模擬。

1 用戶 api

在 src/api/user.ts 中添加用戶相關 CRUD 接口,代碼如下:

//src/api/user.ts 
import request from "@/api/config/request";
// 從 "./type" 模塊中導入 ApiResponse 類型,用于定義接口響應數據的結構
import type { ApiResponse } from "./type";
import type { IRole } from "./role";/*** 定義用戶登錄所需的數據結構* @interface IUserLoginData* @property {string} username - 用戶登錄使用的用戶名* @property {string} password - 用戶登錄使用的密碼*/
export interface IUserLoginData {username: string;password: string;
}/*** 定義登錄接口響應的數據結構* @interface ILoginResponseData* @property {string} token - 登錄成功后返回的令牌,用于后續請求的身份驗證*/
export interface ILoginResponseData {token: string;
}/*** 登錄接口* @param {IUserLoginData} data - 用戶登錄所需的數據,包含用戶名和密碼* @returns {Promise<ApiResponse<ILoginResponseData>>} - 返回一個 Promise 對象,該對象解析為包含登錄響應數據的 ApiResponse 類型*/
export const login = (data: IUserLoginData
): Promise<ApiResponse<ILoginResponseData>> => {return request.post("/4642164-4292760-default/287017559", data);
};
//test
export const logout_error = (): Promise<ApiResponse<ILoginResponseData>> => {return request.post("/4642164-4292760-default/auth/401");
};//個人中心接口
export interface Profile {id: number;username: string;email: string;mobile: string;isSuper: boolean;status: boolean;avatar: string;description: string;roles: IRole[];roleIds?: number[]; // 修改用戶的時候,后端接受只要id
}export interface IUsers {users: Profile[];count: number;
}// 查詢參數
export interface IUserQuery {pageNum?: number;pageSize?: number;mobile?: string;status?: boolean;username?: string;
}// 獲取用戶列表的接口
export const getUsers = (params: IUserQuery): Promise<ApiResponse<IUsers>> => {const {pageNum = 0,pageSize = 10,username = "",status,mobile = ""} = params;return request.get("/user", {params: {pageNum,pageSize,username,status,mobile}});
};// 刪除用戶
export const removeUser = (id: number): Promise<ApiResponse> => {return request.delete(`/user/${id}`);
};// 添加用戶
export const addUser = (data: Profile): Promise<ApiResponse> => {return request.post("/auth/register", data);
};// 編輯用戶
export const updateUser = (id: number, data: Profile): Promise<ApiResponse> => {return request.put(`/user/${id}`, data);
};

2 用戶 Store

在 src/stores/user.ts 中添加用戶相關方法,代碼如下:

//src/stores/user.ts
import type { IUserLoginData, IUserQuery, IUsers, Profile } from "@/api/user";
import {login as loginApi,getUsers as getUsersApi, // 獲取用戶addUser as addUserApi,removeUser as removeUserApi,updateUser as updateUserApi
} from "@/api/user";
import { setToken, removeToken } from "@/utils/auth";
import { useTagsView } from "./tagsView";
import type { IRole } from "@/api/role";
export type IProfileQuery = Profile & {pageNum?: number;pageSize?: number;
};
export const useUserStore = defineStore("user", () => {const state = reactive({token: "",users: [] as IUsers["users"], // 用戶列表count: 0, // 用戶個數roles: [] as IRole[],userInfo: {} as Profile});const tagsViewStore = useTagsView();const login = async (userInfo: IUserLoginData) => {try {const { username, password } = userInfo;const response = await loginApi({ username: username.trim(), password });const { data } = response;state.token = data.token;setToken(data.token);} catch (e) {return Promise.reject(e);}};const logout = () => {state.token = "";removeToken();// 所有的信息都應該情況tagsViewStore.delAllView(); // ...};// 獲取全部用戶const getAllUsers = async (params: IUserQuery) => {const res = await getUsersApi(params);const { data } = res;state.users = data.users;state.count = data.count;};// 添加用戶const addUser = async (data: IProfileQuery) => {const { pageSize, pageNum, ...params } = data;const res = await addUserApi(params);if (res.code === 0) {getAllUsers({pageSize,pageNum});}};// 刪除用戶const removeUser = async (data: IProfileQuery) => {const { pageSize, pageNum, id } = data;const res = await removeUserApi(id);if (res.code === 0) {getAllUsers({pageSize,pageNum});}};//編輯用戶const editUser = async (data: IProfileQuery) => {const { pageSize, pageNum, ...params } = data;const res = await updateUserApi(params.id, params);if (res.code === 0) {getAllUsers({pageSize,pageNum});}};return {login,state,logout,getAllUsers,editUser,removeUser,addUser};
});

3 用戶管理界面實現

3.1 editorUser 組件封裝

在 src/views/system/user/components/editorUser.vue 中,實現用戶新增編輯組件,代碼如下:

//src/views/system/user/components/editorUser.vue
<template><div class="editor-container" p-20px><el-formref="editFormRef":model="editData":rules="menuFormRules"label-width="80px"><el-form-item label="用戶名" prop="username"><el-input v-model="editData.username" placeholder="請輸入用戶名" /></el-form-item><el-form-item label="手機" prop="mobile"><el-inputv-model="editData.mobile"placeholder="請輸入手機"maxlength="11"/></el-form-item><el-form-item label="郵箱" prop="email"><el-input v-model="editData.email" placeholder="請輸入郵箱" /></el-form-item><el-form-item label="狀態" prop="status"><el-switch v-model="editData.status" /></el-form-item><el-form-item label="角色分配" prop="roleIds"><el-select multiple v-model="editData.roleIds" placeholder="請選擇角色"><el-optionv-for="item in editData.roles":key="item.id":label="item.name":value="item.id"></el-option></el-select></el-form-item><el-form-item label="說明" prop="description"><el-inputtype="textarea":rows="3"v-model="editData.description"placeholder="請輸入說明"/></el-form-item><el-form-item><el-button type="primary" @click="submitMenuForm">提交</el-button></el-form-item></el-form></div>
</template><script lang="ts" setup>
import type { Profile } from "@/api/user";
import type { FormInstance, FormItemRule } from "element-plus";
import type { PropType } from "vue";const props = defineProps({type: {// 操作類型 0編輯 1新增type: Number,required: true},data: {type: Object as PropType<Profile>}
});
const emit = defineEmits(["submit"]);const editFormRef = ref<FormInstance | null>(null);
const editData = ref<Partial<Profile>>({username: "",email: "",mobile: "",description: "",status: true
});// 驗證規則
const validateMobile = (rule: unknown,value: string,callback: (arg?: Error) => void
) => {if (!isNaN(Number(value)) && value.length === 11) {callback();}callback(new Error("請輸入正確格式手機號!"));
};const menuFormRules = {username: {required: true,message: "請輸入用戶名",trigger: "blur"},email: [{required: true,message: "請輸入郵箱",trigger: "blur"},{type: "email",message: "請輸入正確的郵箱地址",trigger: ["blur", "change"]}] as FormItemRule[],mobile: [{required: true,message: "請輸入手機",trigger: "blur"},{message: "請輸入正確11位手機號",trigger: "blur",validator: validateMobile}],roleIds: {required: true,message: "請至少選擇一個角色!",trigger: "blur"}
};const defaultProps = {username: "",email: "",mobile: "",description: "",status: true
};watchEffect(() => {if (props.data) {// 移除之前表單效驗結果editFormRef.value?.clearValidate();editData.value = { ...defaultProps, ...props.data };}
});// 提交編輯菜單
const submitMenuForm = () => {(editFormRef.value as FormInstance).validate((valid) => {if (valid) {emit("submit", editData.value);}});
};
</script>

3.2 用戶管理頁面

在 src/views/system/user/index.vue 中,編寫用戶管理靜態頁面,代碼如下:

//src/views/system/user/index.vue
<template><div class="user-container" p-30px><h2>用戶管理</h2><el-button type="primary" plain @click="handleAddUser" class="mb">添加用戶</el-button><el-form :inline="true" :model="formQuery" ref="queryFormRef"><el-form-item label="用戶名" prop="username"><el-inputv-model="formQuery.username"placeholder="請輸入用戶名"></el-input></el-form-item><el-form-item label="手機號" prop="mobile"><el-inputv-model="formQuery.mobile"placeholder="請輸入手機號"></el-input></el-form-item><el-form-item label="狀態" prop="status" w-200px><el-select v-model="formQuery.status" placeholder="狀態"><el-option label="全部" value="all"></el-option><el-option label="禁用" :value="0"></el-option><el-option label="正常" :value="1"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="handleSubmitQuery">查詢</el-button><el-button type="default" @click="handleResetFeilds">重置</el-button></el-form-item></el-form><div class="user-list"><el-table :data="users" max-height="400"><el-table-column prop="username" label="用戶名"> </el-table-column><el-table-column prop="mobile" label="手機"> </el-table-column><el-table-column prop="email" label="郵箱"> </el-table-column><el-table-column prop="status" label="狀態" :formatter="formatter"></el-table-column><el-table-column prop="createdAt" label="創建時間"> </el-table-column><el-table-column label="操作" fixed="right" width="150px"><template #default="scope"><el-buttonsize="small"link@click="handleEditUser(scope.$index, scope.row)">編輯</el-button><el-buttonsize="small"link@click="handleDeleteUser(scope.$index, scope.row)">刪除</el-button></template></el-table-column></el-table><div class="user-container"><div class="user-list"><!--用戶展示--><div class="user-pagination"><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange"background:total="total":page-sizes="[1, 5, 10, 20]":page-size="pageSize"layout="total, prev, pager, next, sizes,jumper"></el-pagination></div></div></div></div><right-panel v-model="panelVisible" :title="panelTitle" :size="330"><editor-user:type="editType":data="editData"@submit="handleSubmitUser"/></right-panel></div>
</template><script lang="ts" setup>
import type { IUserQuery, Profile } from "@/api/user";
import { useRoleStore } from "@/stores/role";
import { type IProfileQuery, useUserStore } from "@/stores/user";
import type { FormInstance } from "element-plus";
const store = useUserStore();
// 用戶列表
const users = computed(() => store.state.users);
// 分頁相關狀態
const pageNum = ref(0);
const pageSize = ref(10);
// 獲取用戶列表 支持分頁
const getUserList = () => {store.getAllUsers({pageNum: pageNum.value,pageSize: pageSize.value,...formQuery// ... 搜索條件} as unknown as IUserQuery);
};
// 格式化status
const formatter = (row: Profile) => {return row.status ? "正常" : "禁用";
};
// 不使用watchEffect
onMounted(() => {getUserList();
});
// 刪除用戶
const { proxy } = getCurrentInstance()!;
const handleDeleteUser = async (index: number, row: Profile) => {try {await proxy?.$confirm(`您確認要刪除用戶${row.username}嗎?`, "刪除確認", {type: "warning"});await store.removeUser({id: row.id,pageNum: pageNum.value,pageSize: pageSize.value} as IProfileQuery);proxy?.$message.success("用戶刪除成功");} catch {proxy?.$message({type: "info",message: "已取消刪除"});}
};
const handleEditUser = (index: number, row: Profile) => {editType.value = 0;editData.value = { ...row };// 獲取當前編輯用戶 現有角色列表editData.value.roleIds = row.roles.map((item) => item.id);editData.value.roles = roles.value!; // 所有角色列表panelVisible.value = true;
};
// 用戶總條數
const total = computed(() => store.state.count);
// 分頁
const handleSizeChange = (val: number) => {pageSize.value = val;getUserList();
};
const handleCurrentChange = (val: number) => {pageNum.value = val - 1; // 頁碼后端是從0開始的getUserList();
};// 查詢參數
const formQuery = reactive({username: "",status: "all",mobile: ""
});
const handleSubmitQuery = () => {getUserList();
};// 重置
const queryFormRef = useTemplateRef<FormInstance | null>("queryFormRef");
const handleResetFeilds = () => {(queryFormRef.value as FormInstance).resetFields();getUserList();
};const editData = ref<Profile | undefined>(undefined);
// 控制面板顯示
const panelVisible = ref(false);
const editType = ref(1);
const panelTitle = computed(() =>editType.value === 1 ? "新增用戶" : "編輯用戶"
);
const storeRole = useRoleStore();
storeRole.getRoles({pageNum: pageNum.value,pageSize: pageSize.value,flag: 0
});
const roles = computed(() => storeRole.state.roles); // 角色const handleAddUser = () => {editType.value = 1;editData.value = {} as Profile;editData.value.roles = roles.value; // 所有角色列表editData.value.roleIds = []; // 所選角色id列表panelVisible.value = true;
};
const editUser = async (data: IProfileQuery) => {store.editUser({...data,pageSize: pageSize.value,pageNum: pageNum.value});(queryFormRef.value as FormInstance).resetFields();proxy?.$message.success("用戶編輯成功");panelVisible.value = false;
};
const handleSubmitUser = (data: Profile) => {if (editType.value === 1) {// 新增addNewUser(data);} else {editUser(data);}
};
const addNewUser = (data: Profile) => {store.addUser({...data,pageSize: pageSize.value,pageNum: pageNum.value});(queryFormRef.value as FormInstance).resetFields();proxy?.$message.success("用戶添加成功");panelVisible.value = false;
};
</script>

npm run dev 啟動后,頁面效果如下:

以上,就是用戶管理的全部內容。

下一篇將繼續探討 菜單管理,敬請期待~?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82295.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C】初階數據結構14 -- 歸并排序

本篇文章主要是講解經典的排序算法 -- 歸并排序 目錄 1 遞歸版本的歸并排序 1&#xff09; 算法思想 2&#xff09; 代碼 3&#xff09; 時間復雜度與空間復雜度分析 &#xff08;1&#xff09; 時間復雜度 &#xff08;2&#xff09; 空間復雜度 2 迭代版本的歸并…

【相機標定】OpenCV 相機標定中的重投影誤差與角點三維坐標計算詳解

摘要&#xff1a; 本文將從以下幾個方面展開&#xff0c;結合典型代碼深入解析 OpenCV 中的相機標定過程&#xff0c;重點闡述重投影誤差的計算方法與實際意義&#xff0c;并通過一個 calcBoardCornerPositions() 函數詳細講解棋盤格角點三維坐標的構建邏輯。 在計算機視覺領域…

RabbitMQ-運維

文章目錄 前言運維-集群介紹多機多節點單機多節點 多機多節點下載配置hosts?件配置Erlang Cookie啟動節點構建集群查看集群狀態 單機多節點安裝啟動兩個節點再啟動兩個節點驗證RabbitMQ啟動成功搭建集群把rabbit2, rabbit3添加到集群 宕機演示仲裁隊列介紹raft算法協議 raft基…

JVM之內存管理(一)

部分內容來源&#xff1a;JavaGuide二哥Java 圖解JVM內存結構 內存管理快速復習 棧幀&#xff1a;局部變量表&#xff0c;動態鏈接&#xff08;符號引用轉為真實引用&#xff09;&#xff0c;操作數棧&#xff08;存儲中間結算結果&#xff09;&#xff0c;方法返回地址 運行時…

無線射頻模塊如何通過CE RED認證?關鍵規范與準備策略詳解

隨著無線通信設備在歐洲市場的廣泛應用&#xff0c;CE RED認證已成為模塊類產品進入歐盟的強制通行證。作為專注于LoRa模塊、對講模塊與FSK射頻模塊研發的技術企業&#xff0c;我們深知從設計、測試到量產&#xff0c;每一個環節都需緊扣合規底線。本文將圍繞CE RED認證核心要求…

Golang中集合相關的庫

一切編程語言的底層結構都是數組&#xff0c;其它復雜數據結構如Map, Stack&#xff0c;Heap和Queue都是基于數組建立起來的。 Go語言主流工具庫推薦&#xff08;含常用數據結構實現&#xff09; 以下是目前Go生態中最主流且活躍的工具庫&#xff0c;包含隊列、棧、優先級隊列…

ABAP 導入Excel形成內表

文章目錄 創建導入模板程序實現代碼代碼解析運行結果 創建導入模板 程序實現 代碼 *&---------------------------------------------------------------------* *& Report Z_EXCEL_UPLOAD_LHY *&--------------------------------------------------------------…

特殊配合力(SCA)作為全基因組關聯分析(GWAS)的表型,其生物學意義和應用價值

生物學意義 解析非加性遺傳效應 特殊配合力(SCA)主要反映特定親本組合的雜交優勢,由非加性遺傳效應(如顯性、超顯性、上位性)驅動。顯性效應涉及等位基因間的顯性互作,上位性效應則涉及不同位點間的基因互作。通過SCA-GWAS,可以定位調控這些非加性效應的關鍵基因組區域…

應急響應基礎模擬靶機-security1

PS:杰克創建在流量包(result.pcap)在根目錄下&#xff0c;請根據已有信息進行分析 1、攻擊者使用的端口掃描工具是? 2、通過流量及日志審計&#xff0c;攻擊者上傳shell的時訪問web使用IP地址是多少? 3、審計流量日志&#xff0c;攻擊者反彈shell的地址及端口? 4、攻擊者…

uniapp-商城-47-后臺 分類數據的生成(通過數據)

在第46章節中&#xff0c;我們為后臺數據創建了分類的數據表結構schema&#xff0c;使得可以通過后臺添加數據并保存&#xff0c;同時使用云函數進行數據庫數據的讀取。文章詳細介紹了如何通過前端代碼實現分類管理功能&#xff0c;包括獲取數據、添加、更新和刪除分類。主要代…

ClickHouse的基本操作說明

說明 文章內容包括數據庫管理、表操作及查詢等核心功能 創建數據庫 -- 默認引擎&#xff08;Atomic&#xff09; CREATE DATABASE IF NOT EXISTS test_db; -- MySQL引擎&#xff08;映射外部MySQL數據庫&#xff09; CREATE DATABASE mysql_db ENGINE MySQL(host:port, m…

Nacos源碼—7.Nacos升級gRPC分析四

大綱 5.服務變動時如何通知訂閱的客戶端 6.微服務實例信息如何同步集群節點 6.微服務實例信息如何同步集群節點 (1)服務端處理服務注冊時會發布一個ClientChangedEvent事件 (2)ClientChangedEvent事件的處理源碼 (3)集群節點處理數據同步請求的源碼 (1)服務端處理服務注冊…

《Overlapping Experiment Infrastructure: More, Better, Faster》論文閱讀筆記

文章目錄 1 背景2 三個核心概念3 Launch層&#xff1a;特性發布的專用機制4 流量分發策略和條件篩選4.1 四種流量分發類型4.2 條件篩選機制 5 工具鏈與監控體系6 實驗設計原則7 培訓參考與推薦 1 背景 谷歌&#xff08;Google&#xff09;以數據驅動著稱&#xff0c;幾乎所有可…

國芯思辰| 醫療AED可使用2通道24位模擬前端SC2946(ADS1292)

生物電信號監測技術在醫療健康行業中發展迅速&#xff0c;成為評估人體生理健康狀況的關鍵手段。心電&#xff08;ECG&#xff09;、腦電&#xff08;EEG&#xff09;和肌電&#xff08;EMG&#xff09;等信號&#xff0c;通過精密模擬前端芯片捕捉和處理&#xff0c;對醫療診斷…

數據結構【二叉搜索樹(BST)】

二叉搜索樹 1. 二叉搜索樹的概念2. 二叉搜索樹的性能分析3.二叉搜索樹的插入4. 二叉搜索樹的查找5. 二叉搜索樹的刪除6.二叉搜索樹的實現代碼7. 二叉搜索樹key和key/value使用場景7.1 key搜索場景&#xff1a;7.2 key/value搜索場景&#xff1a; 1. 二叉搜索樹的概念 二叉搜索…

RDMA高性能網絡通信實踐

RDMA高性能網絡通信實踐 一、背景介紹二、方法設計A.實現方案B.關鍵技術點 三、代碼及注釋四、注意事項 一、背景介紹 遠程直接內存訪問&#xff08;RDMA&#xff09;技術通過繞過操作系統內核和CPU直接訪問遠程內存&#xff0c;實現了超低延遲、高吞吐量的網絡通信。該技術廣…

ndarray數組掩碼操作,True和False獲取數據

#數組掩碼的表示方法 def testht05():a np.arange(1,10)mask [True,False,True,True,False,True,False,True,True]print(a[mask]) 另外的用法&#xff1a; #掩碼操作獲取子集 def testht06():a np.arange(1,100)print(a[a%3 0 & (a%7 0)] )b np.array([A,"B&qu…

索引工具explain

EXPLAIN 是 MySQL 中一個非常有用的工具,用于分析查詢的執行計劃。通過 EXPLAIN,你可以了解 MySQL 是如何執行查詢的,包括它如何使用索引、表的掃描方式等。這有助于優化查詢性能。以下是 EXPLAIN 輸出的各個字段的詳細解釋: 基本用法 EXPLAIN SELECT * FROM table_name …

Git回顧

參考視頻:【GeekHour】一小時Git教程 一句話定義&#xff1a;Git是一個免費開源的分布式版本控制系統。 版本控制系統可以分為兩種&#xff0c;1.集中式&#xff08;SVN&#xff0c;CVS&#xff09;&#xff1b;2.分布式&#xff08;git&#xff09; git的工作區域和文件狀態…

python打卡day20

特征降維------特征組合&#xff08;以SVD為例&#xff09; 知識點回顧&#xff1a; 奇異值的應用&#xff1a; 特征降維&#xff1a;對高維數據減小計算量、可視化數據重構&#xff1a;比如重構信號、重構圖像&#xff08;可以實現有損壓縮&#xff0c;k 越小壓縮率越高&#…