feat(用户管理): 添加角色管理和筛选功能
在用户管理模块中新增角色管理和筛选功能,包括: 1. 在用户查询和更新接口中添加 `roleId` 和 `sysRoleId` 字段 2. 在用户详情页添加角色修改功能 3. 在用户列表页添加角色筛选选项卡
This commit is contained in:
parent
53efdc88b7
commit
ba7b027c7b
|
@ -67,6 +67,8 @@ export interface QyUserQuery extends BasePageQuery {
|
|||
mobile?: string;
|
||||
corpid?: string;
|
||||
mainDepartment?: number;
|
||||
roleId?: number;
|
||||
sysRoleId?: number;
|
||||
}
|
||||
|
||||
export interface AddQyUserCommand {
|
||||
|
@ -77,6 +79,7 @@ export interface AddQyUserCommand {
|
|||
/** 用户余额 */
|
||||
balance?: number;
|
||||
roleId?: number;
|
||||
sysRoleId?: number;
|
||||
}
|
||||
|
||||
export interface UpdateQyUserCommand extends AddQyUserCommand {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { type QyUserDTO, getQyUserDetailApi } from "@/api/qy/qyUser";
|
||||
import { type QyUserDTO, getQyUserDetailApi, updateQyUserApi } from "@/api/qy/qyUser";
|
||||
import { getOrderListApi, type OrderDTO } from "@/api/shop/order";
|
||||
import BalanceEditModal from "./BalanceEditModal.vue";
|
||||
import { getRoleListApi, RoleDTO } from "@/api/system/role";
|
||||
|
||||
defineOptions({
|
||||
name: "QyUserDetail"
|
||||
|
@ -15,6 +16,9 @@ const userInfo = ref<QyUserDTO>({});
|
|||
const loading = ref(false);
|
||||
const balanceVisible = ref(false);
|
||||
const currentBalance = ref(0);
|
||||
const roleVisible = ref(false);
|
||||
const roleList = ref<RoleDTO[]>([]);
|
||||
const selectedRoleId = ref<number>();
|
||||
|
||||
// 基础信息
|
||||
const basicInfo = ref({
|
||||
|
@ -56,6 +60,32 @@ watch(activeTab, (newVal) => {
|
|||
}
|
||||
});
|
||||
|
||||
async function handleModifyRole() {
|
||||
try {
|
||||
const { data } = await getRoleListApi({});
|
||||
roleList.value = data.rows;
|
||||
selectedRoleId.value = userInfo.value.roleId;
|
||||
roleVisible.value = true;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRoleConfirm() {
|
||||
try {
|
||||
await updateQyUserApi(userInfo.value.id!, {
|
||||
...userInfo.value,
|
||||
id: userInfo.value.id,
|
||||
roleId: selectedRoleId.value,
|
||||
sysRoleId: selectedRoleId.value
|
||||
});
|
||||
roleVisible.value = false;
|
||||
await fetchUserDetail();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUserDetail() {
|
||||
try {
|
||||
loading.value = true;
|
||||
|
@ -111,6 +141,8 @@ async function handleModifyBalance(row: QyUserDTO) {
|
|||
</div>
|
||||
|
||||
<el-descriptions class="info-details" v-if="activeTab === 'basic'" :column="2" border>
|
||||
<el-descriptions-item label="角色">{{ userInfo.roleName }} <el-button type="primary" size="small"
|
||||
@click="handleModifyRole">修改</el-button></el-descriptions-item>
|
||||
<el-descriptions-item label="用户ID">{{ userInfo.userid }}</el-descriptions-item>
|
||||
<el-descriptions-item label="企业ID">{{ userInfo.corpid }}</el-descriptions-item>
|
||||
<el-descriptions-item label="职务信息">{{ userInfo.position }}</el-descriptions-item>
|
||||
|
@ -143,6 +175,15 @@ async function handleModifyBalance(row: QyUserDTO) {
|
|||
</el-card>
|
||||
</div>
|
||||
<BalanceEditModal v-model:visible="balanceVisible" :row="userInfo" @refresh="fetchUserDetail" />
|
||||
<el-drawer v-model="roleVisible" title="修改角色" direction="rtl" size="30%">
|
||||
<el-select v-model="selectedRoleId" placeholder="请选择角色" style="width: 100%; margin: 20px 0">
|
||||
<el-option v-for="item in roleList" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
|
||||
</el-select>
|
||||
<div style="padding: 20px; text-align: right">
|
||||
<el-button @click="roleVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleRoleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ export function useHook() {
|
|||
mobile: undefined,
|
||||
corpid: wxStore.corpid, // 企业ID
|
||||
mainDepartment: undefined, // 主部门
|
||||
sysRoleId: undefined // 角色ID
|
||||
});
|
||||
|
||||
const timeRange = ref<[string, string]>(); // 时间范围选择
|
||||
|
@ -163,6 +164,7 @@ export function useHook() {
|
|||
handleViewDetail,
|
||||
handleModifyBalance,
|
||||
balanceVisible,
|
||||
selectedUser
|
||||
selectedUser,
|
||||
roleOptions
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,9 +25,15 @@ const {
|
|||
handleViewDetail,
|
||||
handleModifyBalance,
|
||||
balanceVisible,
|
||||
selectedUser
|
||||
selectedUser,
|
||||
roleOptions,
|
||||
} = useHook();
|
||||
|
||||
const handleTabChange = (roleId) => {
|
||||
searchFormParams.sysRoleId = roleId;
|
||||
onSearch();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => searchFormParams.mainDepartment,
|
||||
() => {
|
||||
|
@ -41,6 +47,7 @@ watch(
|
|||
<tree class="w-[17%] float-left" v-model="searchFormParams.mainDepartment" />
|
||||
<div class="float-right w-[82%]">
|
||||
<BalanceEditModal v-model:visible="balanceVisible" :row="selectedUser" @refresh="getList" />
|
||||
<div class="search-form-container">
|
||||
<el-form ref="formRef" :inline="true" :model="searchFormParams"
|
||||
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]">
|
||||
<el-form-item label="姓名:" prop="name">
|
||||
|
@ -56,6 +63,18 @@ watch(
|
|||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="custom-tabs">
|
||||
<button class="tab-btn" :class="{ 'active': searchFormParams.sysRoleId === undefined }"
|
||||
@click="handleTabChange(undefined)">
|
||||
全部
|
||||
</button>
|
||||
<button v-for="role in roleOptions" :key="role.roleId" class="tab-btn"
|
||||
:class="{ 'active': searchFormParams.sysRoleId === role.roleId }" @click="handleTabChange(role.roleId)">
|
||||
{{ role.roleName }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-container">
|
||||
<el-row :gutter="12">
|
||||
<el-col v-for="(item, index) in dataList" :key="index" :xs="24" :sm="12" :md="8" :lg="6">
|
||||
|
@ -101,12 +120,68 @@ watch(
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.search-form-container {
|
||||
.search-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-tabs {
|
||||
padding: 0 20px;
|
||||
background: var(--el-bg-color);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
||||
.tab-btn {
|
||||
padding: 4px 10px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
color: var(--el-text-color-regular);
|
||||
position: relative;
|
||||
border-radius: 4px 4px 0 0;
|
||||
font-size: 14px;
|
||||
transition: color 0.2s ease;
|
||||
|
||||
&.active {
|
||||
color: var(--el-color-primary);
|
||||
background-color: #f0f2f5;
|
||||
border-bottom: none;
|
||||
z-index: 1;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: -18px;
|
||||
border-bottom-right-radius: 18px;
|
||||
box-shadow: 9px 0 0 0 #f0f2f5;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: -18px;
|
||||
border-bottom-left-radius: 18px;
|
||||
box-shadow: -9px 0 0 0 #f0f2f5;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
text-shadow: 0 0 1px rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-card {
|
||||
margin-bottom: 12px;
|
||||
min-height: 210px;
|
||||
|
|
Loading…
Reference in New Issue