Skip to content

Commit 9a0d7b0

Browse files
committed
feat(permission): permission manage
1 parent ab93be4 commit 9a0d7b0

File tree

12 files changed

+1482
-60
lines changed

12 files changed

+1482
-60
lines changed

frontend/src/api/permissions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { request } from '@/utils/request'
2+
3+
export const getList = () => request.post('/ds_permission/list')
4+
export const savePermissions = (data: any) => request.post('/ds_permission/save', data)
Lines changed: 5 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading

frontend/src/i18n/en.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,29 @@
358358
"edit_row_permission": "Edit row permission",
359359
"add_column_permission": "Add column permission",
360360
"add_row_permission": "Add row permission",
361-
"no_fields_yet": "No fields yet"
361+
"no_fields_yet": "No fields yet",
362+
"filter_eq": "Equal to",
363+
"filter_not_eq": "Not equal to",
364+
"filter_lt": "Less than",
365+
"filter_le": "Less than or equal to",
366+
"filter_gt": "Greater than",
367+
"filter_ge": "Greater than or equal to",
368+
"filter_null": "Empty",
369+
"filter_not_null": "Not empty",
370+
"filter_empty": "Empty string",
371+
"filter_not_empty": "Not empty string",
372+
"filter_include": "Include",
373+
"filter_not_include": "Not included",
374+
"conditional_filtering": "Conditional filtering",
375+
"add_conditions": "Add conditions",
376+
"add_relationships": "Add relationships",
377+
"cannot_be_empty_": "Filter field cannot be empty",
378+
"cannot_be_empty_de_ruler": "Rule condition cannot be empty",
379+
"filter_value_can_null": "Filter value cannot be null",
380+
"filter_like": "Contains",
381+
"filter_not_like": "Does not contain",
382+
"filter_in": "Belongs to",
383+
"filter_not_in": "Does not belong to"
362384
},
363385
"chat": {
364386
"type": "Chart Type",

frontend/src/i18n/zh-CN.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,29 @@
374374
"edit_row_permission": "编辑行权限",
375375
"add_column_permission": "添加列权限",
376376
"add_row_permission": "添加行权限",
377-
"no_fields_yet": "暂无字段"
377+
"no_fields_yet": "暂无字段",
378+
"filter_eq": "等于",
379+
"filter_not_eq": "不等于",
380+
"filter_lt": "小于",
381+
"filter_le": "小于等于",
382+
"filter_gt": "大于",
383+
"filter_ge": "大于等于",
384+
"filter_null": "为空",
385+
"filter_not_null": "不为空",
386+
"filter_empty": "空字符串",
387+
"filter_not_empty": "非空字符串",
388+
"filter_include": "包含",
389+
"filter_not_include": "不包含",
390+
"conditional_filtering": "条件筛选",
391+
"add_conditions": "添加条件",
392+
"add_relationships": "添加关系",
393+
"cannot_be_empty_": "过滤字段不能为空",
394+
"cannot_be_empty_de_ruler": "规则条件不能为空",
395+
"filter_value_can_null": "过滤值不能为空",
396+
"filter_like": "包含",
397+
"filter_not_like": "不包含",
398+
"filter_in": "属于",
399+
"filter_not_in": "不属于"
378400
},
379401
"chat": {
380402
"type": "图表类型",

frontend/src/views/system/permission/Card.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const setUser = () => {
4545
</div>
4646
<div class="type-value">
4747
<span class="type">{{ $t('permission.permission_rule') }}</span>
48-
<span class="value"> {{ $t('permission.2', { msg: type }) }}</span>
48+
<span class="value"> {{ $t('permission.2', { msg: num }) }}</span>
4949
</div>
5050
<div class="type-value">
5151
<span class="type">{{ $t('permission.restricted_user') }}</span>
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<template>
2+
<div class="select-user_permission">
3+
<p class="lighter-bold">{{ $t('permission.select_restricted_user') }}</p>
4+
<div v-loading="loading" class="flex border" style="height: 428px; border-radius: 6px">
5+
<div class="p-16 border-r">
6+
<el-input
7+
v-model="search"
8+
:validate-event="false"
9+
:placeholder="$t('datasource.search')"
10+
style="width: 364px"
11+
clearable
12+
>
13+
<template #prefix>
14+
<el-icon>
15+
<Search></Search>
16+
</el-icon>
17+
</template>
18+
</el-input>
19+
<div class="mt-8 max-height_workspace">
20+
<el-checkbox
21+
v-if="!search"
22+
v-model="checkAll"
23+
class="mb-8"
24+
:indeterminate="isIndeterminate"
25+
@change="handleCheckAllChange"
26+
>
27+
{{ $t('datasource.select_all') }}
28+
</el-checkbox>
29+
<el-checkbox-group
30+
v-model="checkedWorkspace"
31+
class="checkbox-group-block"
32+
@change="handleCheckedWorkspaceChange"
33+
>
34+
<el-checkbox
35+
v-for="space in workspaceWithKeywords"
36+
:key="space.id"
37+
:label="space.name"
38+
:value="space"
39+
>
40+
<div class="flex">
41+
<el-icon size="28">
42+
<avatar_personal></avatar_personal>
43+
</el-icon>
44+
<span class="ml-4"> {{ space.name }}</span>
45+
<span class="account">({{ space.account }})</span>
46+
</div>
47+
</el-checkbox>
48+
</el-checkbox-group>
49+
</div>
50+
</div>
51+
<div class="p-16 w-full">
52+
<div class="flex-between mb-16">
53+
<span class="lighter">
54+
{{ $t('workspace.selected_2_people', { msg: checkedWorkspace.length }) }}
55+
</span>
56+
57+
<el-button text @click="clearWorkspaceAll">
58+
{{ $t('workspace.clear') }}
59+
</el-button>
60+
</div>
61+
<div v-for="ele in checkedWorkspace" :key="ele.name" class="flex-between">
62+
<div class="flex align-center">
63+
<el-icon size="28">
64+
<avatar_personal></avatar_personal>
65+
</el-icon>
66+
<span class="ml-4 lighter">{{ ele.name }}</span>
67+
<span class="account">({{ ele.account }})</span>
68+
</div>
69+
<el-button text>
70+
<el-icon size="16" @click="clearWorkspace(ele)"><Close /></el-icon>
71+
</el-button>
72+
</div>
73+
</div>
74+
</div>
75+
</div>
76+
</template>
77+
78+
<script lang="ts" setup>
79+
import { ref, computed } from 'vue'
80+
import { workspaceUserList } from '@/api/workspace'
81+
import avatar_personal from '@/assets/svg/avatar_personal.svg'
82+
import Close from '@/assets/svg/icon_close_outlined_w.svg'
83+
import Search from '@/assets/svg/icon_search-outline_outlined.svg'
84+
import type { CheckboxValueType } from 'element-plus-secondary'
85+
const checkAll = ref(false)
86+
const isIndeterminate = ref(false)
87+
const checkedWorkspace = ref<any[]>([])
88+
const workspace = ref<any[]>([])
89+
const search = ref('')
90+
const loading = ref(false)
91+
const centerDialogVisible = ref(false)
92+
93+
const workspaceWithKeywords = computed(() => {
94+
return workspace.value.filter((ele: any) => (ele.name as string).includes(search.value))
95+
})
96+
const handleCheckAllChange = (val: CheckboxValueType) => {
97+
checkedWorkspace.value = val ? workspace.value : []
98+
isIndeterminate.value = false
99+
if (!val) {
100+
clearWorkspaceAll()
101+
}
102+
}
103+
const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
104+
const checkedCount = value.length
105+
checkAll.value = checkedCount === workspace.value.length
106+
isIndeterminate.value = checkedCount > 0 && checkedCount < workspace.value.length
107+
}
108+
109+
const open = async () => {
110+
loading.value = true
111+
checkedWorkspace.value = []
112+
checkAll.value = false
113+
isIndeterminate.value = false
114+
const systemWorkspaceList = await workspaceUserList({}, 1, 1000)
115+
workspace.value = systemWorkspaceList.items.filter((ele: any) => ele.weight !== 1) as any
116+
loading.value = false
117+
centerDialogVisible.value = true
118+
}
119+
120+
const clearWorkspace = (val: any) => {
121+
checkedWorkspace.value = checkedWorkspace.value.filter((ele: any) => ele.id !== val.id)
122+
}
123+
124+
const clearWorkspaceAll = () => {
125+
checkedWorkspace.value = []
126+
handleCheckedWorkspaceChange([])
127+
}
128+
129+
defineExpose({
130+
open,
131+
checkedWorkspace,
132+
})
133+
</script>
134+
<style lang="less">
135+
.select-user_permission {
136+
.mb-8 {
137+
margin-bottom: 8px;
138+
}
139+
140+
.mt-16 {
141+
margin-top: 16px;
142+
}
143+
144+
.p-16 {
145+
padding: 16px;
146+
}
147+
148+
.lighter {
149+
font-weight: 400;
150+
font-size: 14px;
151+
line-height: 22px;
152+
}
153+
154+
.lighter-bold {
155+
font-weight: 500;
156+
font-size: 16px;
157+
line-height: 24px;
158+
margin-bottom: 16px;
159+
}
160+
161+
.checkbox-group-block {
162+
.ed-checkbox,
163+
.ed-checkbox__label,
164+
.flex {
165+
width: 100%;
166+
height: 44px;
167+
}
168+
169+
.flex {
170+
align-items: center;
171+
.account {
172+
color: #8f959e;
173+
}
174+
}
175+
}
176+
177+
.border {
178+
border: 1px solid #dee0e3;
179+
}
180+
181+
.w-full {
182+
width: 100%;
183+
overflow-y: auto;
184+
185+
.flex-between {
186+
height: 44px;
187+
}
188+
}
189+
190+
.mt-8 {
191+
margin-top: 8px;
192+
}
193+
194+
.max-height_workspace {
195+
max-height: calc(100% - 24px);
196+
overflow-y: auto;
197+
}
198+
199+
.align-center {
200+
align-items: center;
201+
}
202+
203+
.flex-between {
204+
display: flex;
205+
justify-content: space-between;
206+
}
207+
208+
.ml-4 {
209+
margin-left: 4px;
210+
}
211+
212+
.flex {
213+
display: flex;
214+
}
215+
216+
.border-r {
217+
border-right: 1px solid #dee0e3;
218+
}
219+
}
220+
</style>

0 commit comments

Comments
 (0)