1.字段权限配置完成;
This commit is contained in:
@@ -184,6 +184,7 @@ class Columns(CoreModel):
|
|||||||
role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False)
|
role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False)
|
||||||
app = models.CharField(max_length=64, verbose_name='应用名')
|
app = models.CharField(max_length=64, verbose_name='应用名')
|
||||||
model = models.CharField(max_length=64, verbose_name='表名')
|
model = models.CharField(max_length=64, verbose_name='表名')
|
||||||
|
menu = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name='菜单', db_constraint=False)
|
||||||
field_name = models.CharField(max_length=64, verbose_name='模型表字段名')
|
field_name = models.CharField(max_length=64, verbose_name='模型表字段名')
|
||||||
title = models.CharField(max_length=64, verbose_name='字段显示名')
|
title = models.CharField(max_length=64, verbose_name='字段显示名')
|
||||||
is_query = models.BooleanField(default=1, verbose_name='是否可查询')
|
is_query = models.BooleanField(default=1, verbose_name='是否可查询')
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ class ColumnViewSet(CustomModelViewSet):
|
|||||||
role_id = request.query_params.get('role')
|
role_id = request.query_params.get('role')
|
||||||
app_name = request.query_params.get('app')
|
app_name = request.query_params.get('app')
|
||||||
model_name = request.query_params.get('model')
|
model_name = request.query_params.get('model')
|
||||||
if not role_id or not model_name or not app_name:
|
menu = request.query_params.get('menu')
|
||||||
|
if not role_id or not model_name or not app_name or not menu:
|
||||||
return SuccessResponse([])
|
return SuccessResponse([])
|
||||||
queryset = self.filter_queryset(self.get_queryset().filter(role_id=role_id, model=model_name, app=app_name))
|
queryset = self.filter_queryset(self.get_queryset().filter(role_id=role_id, model=model_name, app=app_name,menu_id=menu))
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
serializer = self.get_serializer(page, many=True, request=request)
|
serializer = self.get_serializer(page, many=True, request=request)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from rest_framework import serializers
|
|||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission
|
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission, Columns
|
||||||
from dvadmin.system.views.menu import MenuSerializer
|
from dvadmin.system.views.menu import MenuSerializer
|
||||||
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
||||||
from dvadmin.utils.serializers import CustomModelSerializer
|
from dvadmin.utils.serializers import CustomModelSerializer
|
||||||
@@ -71,12 +71,20 @@ class RoleButtonPermissionSerializer(CustomModelSerializer):
|
|||||||
model = MenuButton
|
model = MenuButton
|
||||||
fields = ['id','name','value','isCheck','data_range']
|
fields = ['id','name','value','isCheck','data_range']
|
||||||
|
|
||||||
|
class RoleColumnsSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Columns
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuPermissionSerializer(CustomModelSerializer):
|
class RoleMenuPermissionSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
菜单和按钮权限
|
菜单和按钮权限
|
||||||
"""
|
"""
|
||||||
isCheck = serializers.SerializerMethodField()
|
isCheck = serializers.SerializerMethodField()
|
||||||
btns = serializers.SerializerMethodField()
|
btns = serializers.SerializerMethodField()
|
||||||
|
columns = serializers.SerializerMethodField()
|
||||||
|
|
||||||
def get_isCheck(self, instance):
|
def get_isCheck(self, instance):
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
@@ -90,9 +98,17 @@ class RoleMenuPermissionSerializer(CustomModelSerializer):
|
|||||||
serializer = RoleButtonPermissionSerializer(btn_list,many=True,request=self.request)
|
serializer = RoleButtonPermissionSerializer(btn_list,many=True,request=self.request)
|
||||||
return serializer.data
|
return serializer.data
|
||||||
|
|
||||||
|
def get_columns(self, instance):
|
||||||
|
params = self.request.query_params
|
||||||
|
col_list = Columns.objects.filter(role__id=params.get('role'),menu__id=instance['id'])
|
||||||
|
serializer = RoleColumnsSerializer(col_list,many=True,request=self.request)
|
||||||
|
return serializer.data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Menu
|
model = Menu
|
||||||
fields = ['id','name','isCheck','btns']
|
fields = ['id','name','isCheck','btns','columns']
|
||||||
|
|
||||||
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
@@ -151,6 +167,8 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
|||||||
if btn.get('isCheck'):
|
if btn.get('isCheck'):
|
||||||
instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=btn.get('data_range'))
|
instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=btn.get('data_range'))
|
||||||
instance.dept.set(btn.get('dept',[]))
|
instance.dept.set(btn.get('dept',[]))
|
||||||
|
for col in menu.get('columns'):
|
||||||
|
Columns.objects.filter(id=col.get('id')).update(is_query=col.get('is_query'),is_create=col.get('is_create'),is_update=col.get('is_update'))
|
||||||
return DetailResponse(msg="授权成功")
|
return DetailResponse(msg="授权成功")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -81,12 +81,6 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi
|
|||||||
|
|
||||||
def get_column_permission(self, serializer_class):
|
def get_column_permission(self, serializer_class):
|
||||||
"""获取列权限"""
|
"""获取列权限"""
|
||||||
action_map = {
|
|
||||||
'list': 'is_query',
|
|
||||||
'retrieve': 'is_query',
|
|
||||||
'create': 'is_create',
|
|
||||||
'update': 'is_update'
|
|
||||||
}
|
|
||||||
finded = False
|
finded = False
|
||||||
for app in get_custom_app_models():
|
for app in get_custom_app_models():
|
||||||
for model in app:
|
for model in app:
|
||||||
@@ -97,10 +91,9 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi
|
|||||||
break
|
break
|
||||||
if finded is False:
|
if finded is False:
|
||||||
return []
|
return []
|
||||||
column_permission = Columns.objects.filter(app=model['app'], model=model['model'])
|
return Columns.objects.filter(
|
||||||
if self.action in action_map:
|
app=model['app'], model=model['model']
|
||||||
return [obj.field_name for obj in column_permission if getattr(obj, action_map[self.action])]
|
).values('field_name', 'is_create', 'is_query', 'is_update')
|
||||||
return []
|
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
serializer = self.get_serializer(data=request.data, request=request)
|
serializer = self.get_serializer(data=request.data, request=request)
|
||||||
|
|||||||
@@ -9,9 +9,17 @@ export function getRoleList(query: PageQuery) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMenuList(query: PageQuery) {
|
||||||
|
return request({
|
||||||
|
url: '/api/system/menu/',
|
||||||
|
method: 'get',
|
||||||
|
params: {is_catalog:0,...query},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function getModelList() {
|
export function getModelList() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/system/column/get_models/',
|
url: '/api/system/column/get_models/',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,6 @@
|
|||||||
<el-table :data="state.data" border v-loading="state.loading" class="ctc-table">
|
<el-table :data="state.data" border v-loading="state.loading" class="ctc-table">
|
||||||
<el-table-column prop="field_name" label="字段名" />
|
<el-table-column prop="field_name" label="字段名" />
|
||||||
<el-table-column prop="title" label="列名" />
|
<el-table-column prop="title" label="列名" />
|
||||||
<el-table-column prop="is_create" label="创建显示">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch v-model="scope.row.is_create" @change="handleChange(scope.row)" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="is_update" label="编辑显示">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch v-model="scope.row.is_update" @change="handleChange(scope.row)" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="is_query" label="查询显示">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch v-model="scope.row.is_query" @change="handleChange(scope.row)" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="180" align="center">
|
<el-table-column label="操作" width="180" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="primary" @click="handleUpdateColumn('update', scope.row)">编辑</el-button>
|
<el-button type="primary" @click="handleUpdateColumn('update', scope.row)">编辑</el-button>
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<fs-page class="columns">
|
<fs-page class="columns">
|
||||||
<el-row class="columns-el-row">
|
<el-row class="columns-el-row" :gutter="10">
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<div class="columns-box columns-left">
|
<div class="columns-box columns-left">
|
||||||
<ItemCom title="角色" type="role" showPagination @fetchData="fetchRoleData" @itemClick="handleClick" />
|
<ItemCom title="角色" type="role" showPagination @fetchData="fetchRoleData" @itemClick="handleClick" />
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<div class="columns-box columns-left">
|
||||||
|
<ItemCom title="菜单" type="menu" showPagination @fetchData="fetchMenuData" @itemClick="handleClick" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<div class="columns-box columns-center">
|
<div class="columns-box columns-center">
|
||||||
<ItemCom title="模型表" type="model" label="showText" value="key" @fetchData="fetchModelData" @itemClick="handleClick" />
|
<ItemCom title="模型表" type="model" label="showText" value="key" @fetchData="fetchModelData" @itemClick="handleClick" />
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="14">
|
<el-col :span="10">
|
||||||
<div class="columns-box columns-right">
|
<div class="columns-box columns-right">
|
||||||
<ColumnsTableCom ref="columnsTableRef" :currentInfo="currentInfo" />
|
<ColumnsTableCom ref="columnsTableRef" :currentInfo="currentInfo" />
|
||||||
</div>
|
</div>
|
||||||
@@ -24,7 +29,7 @@
|
|||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive } from 'vue';
|
||||||
import ItemCom from './components/ItemCom/index.vue';
|
import ItemCom from './components/ItemCom/index.vue';
|
||||||
import ColumnsTableCom from './components/ColumnsTableCom/index.vue';
|
import ColumnsTableCom from './components/ColumnsTableCom/index.vue';
|
||||||
import { getRoleList, getModelList } from './api';
|
import { getRoleList, getModelList,getMenuList } from './api';
|
||||||
import { PageQuery, CurrentInfoType, ModelItemType } from './types';
|
import { PageQuery, CurrentInfoType, ModelItemType } from './types';
|
||||||
|
|
||||||
const columnsTableRef = ref<InstanceType<typeof ColumnsTableCom> | null>(null);
|
const columnsTableRef = ref<InstanceType<typeof ColumnsTableCom> | null>(null);
|
||||||
@@ -32,13 +37,29 @@ let currentInfo = reactive<CurrentInfoType>({
|
|||||||
role: '',
|
role: '',
|
||||||
model: '',
|
model: '',
|
||||||
app: '',
|
app: '',
|
||||||
|
menu:''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取角色
|
||||||
|
* @param query
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
const fetchRoleData = async (query: PageQuery, callback: Function) => {
|
const fetchRoleData = async (query: PageQuery, callback: Function) => {
|
||||||
const res = await getRoleList(query);
|
const res = await getRoleList(query);
|
||||||
callback(res);
|
callback(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单
|
||||||
|
* @param query
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
const fetchMenuData= async (query: PageQuery, callback: Function) => {
|
||||||
|
const res = await getMenuList(query);
|
||||||
|
callback(res);
|
||||||
|
};
|
||||||
|
|
||||||
const fetchModelData = async (query: PageQuery, callback: Function) => {
|
const fetchModelData = async (query: PageQuery, callback: Function) => {
|
||||||
const res = await getModelList();
|
const res = await getModelList();
|
||||||
res.data.forEach((item: ModelItemType) => {
|
res.data.forEach((item: ModelItemType) => {
|
||||||
@@ -58,6 +79,11 @@ const handleClick = (type: string, record: any) => {
|
|||||||
if (type === 'role') {
|
if (type === 'role') {
|
||||||
currentInfo.role = record.id;
|
currentInfo.role = record.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(type === 'menu'){
|
||||||
|
currentInfo.menu = record.id;
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'model') {
|
if (type === 'model') {
|
||||||
currentInfo.model = record.key;
|
currentInfo.model = record.key;
|
||||||
currentInfo.app = record.app;
|
currentInfo.app = record.app;
|
||||||
@@ -88,7 +114,6 @@ const handleClick = (type: string, record: any) => {
|
|||||||
border-radius: 0 8px 8px 0;
|
border-radius: 0 8px 8px 0;
|
||||||
}
|
}
|
||||||
.columns-center {
|
.columns-center {
|
||||||
margin: 0 10px;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
.columns-right {
|
.columns-right {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export interface CurrentInfoType {
|
|||||||
role: string;
|
role: string;
|
||||||
model: string;
|
model: string;
|
||||||
app: string;
|
app: string;
|
||||||
|
|
||||||
|
menu: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModelItemType {
|
export interface ModelItemType {
|
||||||
@@ -38,4 +40,4 @@ export interface ColumnsFormDataType {
|
|||||||
is_create: boolean;
|
is_create: boolean;
|
||||||
is_update: boolean;
|
is_update: boolean;
|
||||||
is_query: boolean;
|
is_query: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,29 +49,23 @@
|
|||||||
<div class="pccm-item">
|
<div class="pccm-item">
|
||||||
<p>对这些数据有以下字段权限</p>
|
<p>对这些数据有以下字段权限</p>
|
||||||
|
|
||||||
<el-radio-group v-model="item.radio">
|
<ul class="columns-list">
|
||||||
<el-radio label="1">全部字段可查看可编辑</el-radio>
|
|
||||||
<el-radio label="2">全部字段仅可查看不可编辑</el-radio>
|
|
||||||
<el-radio label="3">自定义字段权限</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
|
|
||||||
<ul v-show="item.radio === '3'" class="columns-list">
|
|
||||||
<li class="columns-head">
|
<li class="columns-head">
|
||||||
<div class="width-txt">
|
<div class="width-txt">
|
||||||
<span>字段</span>
|
<span>字段</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-for="btn in item.btns" :key="btn.value" class="width-check">
|
<div v-for="(head,hIndex) in column.header" :key="hIndex" class="width-check">
|
||||||
<el-checkbox :label="btn.value" @change="handleColumnChange($event, item, btn.value)">
|
<el-checkbox :label="head.value" @change="handleColumnChange($event, item, head.value)">
|
||||||
<span>{{ btn.label }}</span>
|
<span>{{head.label}}</span>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-for="(c_item, c_index) in item.columns" :key="c_index" class="columns-item">
|
<li v-for="(c_item, c_index) in item.columns" :key="c_index" class="columns-item">
|
||||||
<div class="width-txt">{{ c_item.name }}</div>
|
<div class="width-txt">{{ c_item.title }}</div>
|
||||||
<div v-for="btn in item.btns" :key="btn.value" class="width-check">
|
<div v-for="(col,cIndex) in column.header" :key="cIndex" class="width-check">
|
||||||
<el-checkbox v-model="c_item[btn.value]" class="ci-checkout"></el-checkbox>
|
<el-checkbox v-model="c_item[col.value]" class="ci-checkout"></el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -112,7 +106,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted, defineProps, watch,computed} from 'vue';
|
import {ref, onMounted, defineProps, watch, computed, reactive} from 'vue';
|
||||||
import XEUtils from 'xe-utils';
|
import XEUtils from 'xe-utils';
|
||||||
import {errorNotification} from '/@/utils/message';
|
import {errorNotification} from '/@/utils/message';
|
||||||
import {getDataPermissionRange, getDataPermissionDept, getRolePremission, setRolePremission,setBtnDatarange} from './api';
|
import {getDataPermissionRange, getDataPermissionDept, getRolePremission, setRolePremission,setBtnDatarange} from './api';
|
||||||
@@ -257,6 +251,10 @@ const handleSavePermission = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const column = reactive({
|
||||||
|
header:[{value:'is_create',label:'新增可见'},{value:'is_update',label:'编辑可见'},{value:'is_query',label:'列表可见'}]
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -300,7 +298,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.width-check {
|
.width-check {
|
||||||
width: 80px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.width-icon {
|
.width-icon {
|
||||||
|
|||||||
Reference in New Issue
Block a user