Skip to content

Commit 59a42d1

Browse files
committed
feat: 角色管理功能
1 parent 37fe322 commit 59a42d1

File tree

6 files changed

+341
-563
lines changed

6 files changed

+341
-563
lines changed

src/api/system.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ type ResultTable = {
2020
};
2121

2222
/** 获取系统管理-用户管理列表 */
23-
export const getUserList = (data?: object) => {
24-
return http.request<ResultTable>("get", "/api/users/", { data });
23+
export const getUserList = (params?: object) => {
24+
return http.request<ResultTable>("get", "/api/users/", { params });
2525
};
2626

2727
/** 系统管理-用户管理-获取所有角色列表 */

src/views/system/role/form.vue

Lines changed: 228 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,79 @@
11
<script setup lang="ts">
2-
import { ref } from "vue";
2+
import { ref, onMounted } from "vue";
3+
import { getUserList } from "@/api/system"
4+
import ReCol from "@/components/ReCol";
35
import { formRules } from "./utils/rule";
46
import { FormProps } from "./utils/types";
57
68
const props = withDefaults(defineProps<FormProps>(), {
9+
title: "新增",
710
formInline: () => ({
811
name: "",
912
code: "",
13+
status: 50,
14+
is_super_role: false,
15+
member: [],
1016
remark: ""
1117
})
1218
});
1319
20+
const statusOptions = [
21+
{
22+
value: 50,
23+
label: "生效中"
24+
},
25+
{
26+
value: 100,
27+
label: "已失效"
28+
}
29+
];
30+
const roleOptions = [
31+
{
32+
value: true,
33+
label: ""
34+
},
35+
{
36+
value: false,
37+
label: ""
38+
}
39+
];
1440
const ruleFormRef = ref();
1541
const newFormInline = ref(props.formInline);
1642
1743
function getRef() {
1844
return ruleFormRef.value;
1945
}
2046
47+
const fetchUserLoading = ref(false);
48+
const allUsers = ref([]);
49+
50+
function fetchAllUsers(query?: string, init: boolean = false) {
51+
if (!init && !query) return;
52+
fetchUserLoading.value = true;
53+
allUsers.value.length = 0;
54+
let params = {};
55+
if (query) {params["username"] = query;}
56+
getUserList(params).then((res) => {
57+
// allUsers.value = res.data.list;
58+
const currentUserIds = newFormInline.value.member.map(item => item.id);
59+
const currentUsers = [];
60+
newFormInline.value.member.forEach(user => {
61+
currentUsers.push(user);
62+
})
63+
res.data.list.forEach(user => {
64+
if (!currentUserIds.includes(user.id)) {
65+
currentUsers.push(user);
66+
}
67+
})
68+
allUsers.value = currentUsers;
69+
fetchUserLoading.value = false;
70+
})
71+
}
72+
73+
onMounted(() => {
74+
fetchAllUsers("", true);
75+
})
76+
2177
defineExpose({ getRef });
2278
</script>
2379

@@ -28,28 +84,176 @@ defineExpose({ getRef });
2884
:rules="formRules"
2985
label-width="82px"
3086
>
31-
<el-form-item label="角色名称" prop="name">
32-
<el-input
33-
v-model="newFormInline.name"
34-
clearable
35-
placeholder="请输入角色名称"
36-
/>
37-
</el-form-item>
38-
39-
<el-form-item label="角色标识" prop="code">
40-
<el-input
41-
v-model="newFormInline.code"
42-
clearable
43-
placeholder="请输入角色标识"
44-
/>
45-
</el-form-item>
46-
47-
<el-form-item label="备注">
48-
<el-input
49-
v-model="newFormInline.remark"
50-
placeholder="请输入备注信息"
51-
type="textarea"
52-
/>
53-
</el-form-item>
87+
<el-row :gutter="30">
88+
<re-col :value="12" :xs="24" :sm="24">
89+
<el-form-item label="名称" prop="name">
90+
<el-input
91+
v-model="newFormInline.name"
92+
clearable
93+
placeholder="请输入角色名称"
94+
/>
95+
</el-form-item>
96+
</re-col>
97+
<re-col :value="12" :xs="24" :sm="24">
98+
<el-form-item label="部门编号" prop="code">
99+
<el-input
100+
v-model="newFormInline.code"
101+
clearable
102+
placeholder="请输入角色编号"
103+
/>
104+
</el-form-item>
105+
</re-col>
106+
107+
<re-col :value="12" :xs="24" :sm="24">
108+
<el-form-item label="状态">
109+
<el-select
110+
v-model="newFormInline.status"
111+
placeholder="请选择状态"
112+
class="w-full"
113+
clearable
114+
>
115+
<el-option
116+
v-for="(item, index) in statusOptions"
117+
:key="index"
118+
:label="item.label"
119+
:value="item.value"
120+
/>
121+
</el-select>
122+
</el-form-item>
123+
</re-col>
124+
125+
<re-col :value="12" :xs="24" :sm="24">
126+
<el-form-item label="SuperRole">
127+
<el-select
128+
v-model="newFormInline.is_super_role"
129+
placeholder="请选择"
130+
class="w-full"
131+
clearable
132+
>
133+
<el-option
134+
v-for="(item, index) in roleOptions"
135+
:key="index"
136+
:label="item.label"
137+
:value="item.value"
138+
/>
139+
</el-select>
140+
</el-form-item>
141+
</re-col>
142+
<re-col>
143+
<el-form-item label="成员">
144+
<el-select
145+
v-model="newFormInline.member"
146+
:loading="fetchUserLoading"
147+
value-key="id"
148+
multiple
149+
filterable
150+
remote
151+
reserve-keyword
152+
:remote-method="fetchAllUsers"
153+
placeholder="请输入备注信息"
154+
>
155+
<el-option
156+
v-for="user in allUsers"
157+
:key="user.id"
158+
:label="user.username"
159+
:value="user"
160+
/>
161+
<template #loading>
162+
<el-icon class="is-loading">
163+
<svg class="circular" viewBox="0 0 20 20">
164+
<g
165+
class="path2 loading-path"
166+
stroke-width="0"
167+
style="animation: none; stroke: none"
168+
>
169+
<circle r="3.375" class="dot1" rx="0" ry="0" />
170+
<circle r="3.375" class="dot2" rx="0" ry="0" />
171+
<circle r="3.375" class="dot4" rx="0" ry="0" />
172+
<circle r="3.375" class="dot3" rx="0" ry="0" />
173+
</g>
174+
</svg>
175+
</el-icon>
176+
</template>
177+
</el-select>
178+
</el-form-item>
179+
</re-col>
180+
<re-col>
181+
<el-form-item label="备注">
182+
<el-input
183+
v-model="newFormInline.remark"
184+
placeholder="请输入备注信息"
185+
type="textarea"
186+
/>
187+
</el-form-item>
188+
</re-col>
189+
</el-row>
54190
</el-form>
55191
</template>
192+
193+
<style>
194+
.circular {
195+
display: inline;
196+
height: 30px;
197+
width: 30px;
198+
animation: loading-rotate 2s linear infinite;
199+
}
200+
.path {
201+
animation: loading-dash 1.5s ease-in-out infinite;
202+
stroke-dasharray: 90, 150;
203+
stroke-dashoffset: 0;
204+
stroke-width: 2;
205+
stroke: var(--el-color-primary);
206+
stroke-linecap: round;
207+
}
208+
.loading-path .dot1 {
209+
transform: translate(3.75px, 3.75px);
210+
fill: var(--el-color-primary);
211+
animation: custom-spin-move 1s infinite linear alternate;
212+
opacity: 0.3;
213+
}
214+
.loading-path .dot2 {
215+
transform: translate(calc(100% - 3.75px), 3.75px);
216+
fill: var(--el-color-primary);
217+
animation: custom-spin-move 1s infinite linear alternate;
218+
opacity: 0.3;
219+
animation-delay: 0.4s;
220+
}
221+
.loading-path .dot3 {
222+
transform: translate(3.75px, calc(100% - 3.75px));
223+
fill: var(--el-color-primary);
224+
animation: custom-spin-move 1s infinite linear alternate;
225+
opacity: 0.3;
226+
animation-delay: 1.2s;
227+
}
228+
.loading-path .dot4 {
229+
transform: translate(calc(100% - 3.75px), calc(100% - 3.75px));
230+
fill: var(--el-color-primary);
231+
animation: custom-spin-move 1s infinite linear alternate;
232+
opacity: 0.3;
233+
animation-delay: 0.8s;
234+
}
235+
@keyframes loading-rotate {
236+
to {
237+
transform: rotate(360deg);
238+
}
239+
}
240+
@keyframes loading-dash {
241+
0% {
242+
stroke-dasharray: 1, 200;
243+
stroke-dashoffset: 0;
244+
}
245+
50% {
246+
stroke-dasharray: 90, 150;
247+
stroke-dashoffset: -40px;
248+
}
249+
100% {
250+
stroke-dasharray: 90, 150;
251+
stroke-dashoffset: -120px;
252+
}
253+
}
254+
@keyframes custom-spin-move {
255+
to {
256+
opacity: 1;
257+
}
258+
}
259+
</style>

0 commit comments

Comments
 (0)