This commit is contained in:
caoqianming 2020-05-11 18:41:05 +08:00
parent 4effaa56a5
commit e266347d47
9 changed files with 549 additions and 6 deletions

57
client/src/api/dict.js Normal file
View File

@ -0,0 +1,57 @@
import request from '@/utils/request'
export function getDictTypeList(query) {
return request({
url: '/system/dicttype/',
method: 'get',
params:query
})
}
export function createDictType(data) {
return request({
url: '/system/dicttype/',
method: 'post',
data
})
}
export function updateDictType(id, data) {
return request({
url: `/system/dicttype/${id}/`,
method: 'put',
data
})
}
export function deleteDictType(id) {
return request({
url: `/system/dicttype/${id}/`,
method: 'delete'
})
}
export function getDictList(query) {
return request({
url: '/system/dict/',
method: 'get',
params:query
})
}
export function createDict(data) {
return request({
url: '/system/dict/',
method: 'post',
data
})
}
export function updateDict(id, data) {
return request({
url: `/system/dict/${id}/`,
method: 'put',
data
})
}
export function deleteDict(id) {
return request({
url: `/system/dict/${id}/`,
method: 'delete'
})
}

View File

@ -91,6 +91,12 @@ export const asyncRoutes = [
name: 'Postion', name: 'Postion',
component: () => import('@/views/system/position'), component: () => import('@/views/system/position'),
meta: { title: '岗位管理', icon: 'position', perms: ['position_manage'] } meta: { title: '岗位管理', icon: 'position', perms: ['position_manage'] }
},
{
path: 'dict',
name: 'Dict',
component: () => import('@/views/system/dict'),
meta: { title: '数据字典', icon: 'example', perms: ['dict_manage'] }
} }
] ]
}, },

View File

@ -0,0 +1,275 @@
<template>
<div class="app-container">
<el-row :gutter="10">
<el-col :md="6">
<div style="margin-top:10px">
<el-button type="primary" icon="el-icon-plus" @click="handleAddDictType">新增</el-button>
</div>
<el-tree
ref="tree"
v-loading="treeLoding"
class="filter-tree"
:data="dictTypeData"
default-expand-all
highlight-current
:expand-on-click-node="false"
:filter-node-method="filterNode"
style="margin-top:10px;"
@node-click="handleDictTypeClick"
/>
</el-col>
<el-col :md="18">
<div style="margin-top:10px">
<el-button type="primary" icon="el-icon-plus" @click="handleAddDict">新增</el-button>
</div>
<el-table
v-loading="listLoading"
:data="dictList.results"
style="width: 100%;margin-top:10px;"
border
fit
stripe
highlight-current-row
max-height="600"
>
<el-table-column type="index" width="50" />
<el-table-column align="center" label="名称">
<template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
<el-table-column align="header-center" label="描述">
<template slot-scope="scope">{{ scope.row.desc }}</template>
</el-table-column>
<el-table-column align="header-center" label="排序">
<template
slot-scope="scope"
>{{ scope.row.sort }}</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button
v-if="!scope.row.is_superuser"
:disabled="!checkPermission(['dict_update'])"
type="primary"
size="small"
icon="el-icon-edit"
@click="handleEdit(scope)"
/>
<el-button
v-if="!scope.row.is_superuser"
:disabled="!checkPermission(['dict_delete'])"
type="danger"
size="small"
icon="el-icon-delete"
@click="handleDelete(scope)"
/>
</template>
</el-table-column>
</el-table>
<pagination
v-show="dictList.count>0"
:total="dictList.count"
:page.sync="listQuery.page"
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</el-col>
</el-row>
<el-dialog :visible.sync="dgV1" :title="dgT1==='edit'?'编辑字典类型':'新建字典类型'">
<el-form ref="Form1" :model="dicttype" label-width="80px" label-position="right" :rules="rule1">
<el-form-item label="名称" prop="name">
<el-input v-model="dicttype.name" placeholder="名称" />
</el-form-item>
<el-form-item label="代号" prop="code">
<el-input v-model="dicttype.code" placeholder="代号" />
</el-form-item>
</el-form>
<div style="text-align:right;">
<el-button type="danger" @click="dgV1=false">取消</el-button>
<el-button type="primary" @click="confirm1('Form1')">确认</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dgV2" :title="dgT2==='edit'?'编辑字典':'新建字典'">
<el-form ref="Form2" :model="dict" label-width="80px" label-position="right" :rules="rule2">
<el-form-item label="名称" prop="name">
<el-input v-model="dict.name" placeholder="名称" />
</el-form-item>
<el-form-item label="描述" prop="desc">
<el-input v-model="dict.desc" placeholder="描述" />
</el-form-item>
</el-form>
<div style="text-align:right;">
<el-button type="danger" @click="dgV2=false">取消</el-button>
<el-button type="primary" @click="confirm2('Form2')">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getDictTypeList, getDictList, createDictType, createDict, updateDictType, updateDict, deleteDictType, deleteDict } from '@/api/dict'
import { genTree } from '@/utils'
import checkPermission from '@/utils/permission'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
const defaultDictType = {
id: '',
name: '',
code: '',
pid: null
}
const defaultDict = {
id: '',
name: '',
desc: '',
sort: 1,
type: null
}
export default {
components: { Pagination },
data() {
return {
dicttype: defaultDictType,
dict: defaultDict,
dictList: {count:0},
listLoading: true,
listQuery: {
page: 1,
page_size: 20,
},
dgV1: false,
dgT1: 'new',
rule1: {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
code: [{ required: true, message: '请输入代号', trigger: 'change' }]
},
dgV2: false,
dgT2: 'new',
rule2: {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
},
filterDictTypeText: '',
treeLoding: false,
dictTypeData: []
}
},
computed: {},
watch: {
filterDictTypeText(val) {
this.$refs.tree.filter(val)
}
},
created() {
this.getList()
this.getDictTypeList()
},
methods: {
checkPermission,
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
handleDictTypeClick(obj, node, vue) {
this.listQuery.page = 1
this.listQuery.type = obj.id
this.getList()
},
getList() {
this.listLoading = true
getDictList(this.listQuery).then(response => {
if (response.code>=200){
if (response.data.results){
this.dictList = response.data
}
this.listLoading = false
}
})
},
getDictTypeList() {
this.treeLoding = true
getDictTypeList().then(response => {
this.dictTypeData = genTree(response.data)
this.treeLoding = false
})
},
handleAddDictType() {
this.dicttype = Object.assign({}, defaultDictType)
this.dgT1 = 'new'
this.dgV1 = true
this.$nextTick(() => {
this.$refs['Form1'].clearValidate()
})
},
handleAddDict() {
this.dict = Object.assign({}, defaultDict)
this.dgT2 = 'new'
this.dgV2 = true
this.$nextTick(() => {
this.$refs['Form2'].clearValidate()
})
},
// handleEdit(scope) {
// this.user = Object.assign({}, scope.row) // copy obj
// this.dialogType = 'edit'
// this.dialogVisible = true
// this.$nextTick(() => {
// this.$refs['Form'].clearValidate()
// })
// },
// handleDelete(scope) {
// this.$confirm('确认删除?', '警告', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'error'
// })
// .then(async() => {
// await deleteUser(scope.row.id)
// this.dictList.splice(scope.row.index, 1)
// this.$message({
// type: 'success',
// message: '成功删除!'
// })
// })
// .catch(err => {
// console.error(err)
// })
// },
async confirm1(form) {
this.$refs[form].validate(valid => {
if (valid) {
const isEdit = this.dialogType === 'edit'
if (isEdit) {
updateDictType(this.dicttype.id, this.dicttype).then(res => {
if (res.code >= 200) {
this.getDictTypeList()
this.dgV1 = false
this.$notify({
title: '成功',
message: '编辑成功',
type: 'success',
duration: 2000
})
}
})
} else {
createDictType(this.dicttype).then(res => {
if (res.code >= 200) {
this.getDictTypeList()
this.dgV1 = false
this.$notify({
title: '成功',
message: '新增成功',
type: 'success',
duration: 2000
})
}
})
}
} else {
return false
}
})
}
}
}
</script>

View File

@ -1,7 +1,8 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="6">
<el-col :md="6">
<el-input v-model="filterOrgText" placeholder="输入部门名进行过滤" /> <el-input v-model="filterOrgText" placeholder="输入部门名进行过滤" />
<el-tree <el-tree
@ -17,7 +18,7 @@
@node-click="handleOrgClick" @node-click="handleOrgClick"
/> />
</el-col> </el-col>
<el-col :span="18"> <el-col :md="18">
<div> <div>
<el-select <el-select
v-model="listQuery.is_active" v-model="listQuery.is_active"

View File

@ -0,0 +1,122 @@
# Generated by Django 3.0.5 on 2020-05-11 09:18
from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.CreateModel(
name='Organization',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=60, verbose_name='名称')),
('type', models.CharField(choices=[('公司', '公司'), ('部门', '部门')], default='部门', max_length=20, verbose_name='类型')),
('pid', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.Organization', verbose_name='')),
],
options={
'verbose_name': '组织架构',
'verbose_name_plural': '组织架构',
},
),
migrations.CreateModel(
name='Permission',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=30, verbose_name='名称')),
('type', models.CharField(choices=[('目录', '目录'), ('菜单', '菜单'), ('接口', '接口')], default='接口', max_length=20, verbose_name='类型')),
('is_frame', models.BooleanField(default=False, verbose_name='外部链接')),
('sort', models.IntegerField(default=1, verbose_name='排序标记')),
('method', models.CharField(blank=True, max_length=50, null=True, verbose_name='方法/代号')),
('pid', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.Permission', verbose_name='')),
],
options={
'verbose_name': '功能权限表',
'verbose_name_plural': '功能权限表',
'ordering': ['sort'],
},
),
migrations.CreateModel(
name='Position',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=32, unique=True, verbose_name='名称')),
('desc', models.CharField(blank=True, max_length=50, null=True, verbose_name='描述')),
],
options={
'verbose_name': '职位/岗位',
'verbose_name_plural': '职位/岗位',
},
),
migrations.CreateModel(
name='Role',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=32, unique=True, verbose_name='角色')),
('datas', models.CharField(choices=[('全部', '全部'), ('本级', '本级'), ('本级及以下', '本级及以下'), ('仅本人', '仅本人'), ('自定义', '自定义')], default='本级及以下', max_length=50, verbose_name='数据权限')),
('desc', models.CharField(blank=True, max_length=50, null=True, verbose_name='描述')),
('depts', models.ManyToManyField(blank=True, to='system.Organization', verbose_name='权限范围')),
('perms', models.ManyToManyField(blank=True, to='system.Permission', verbose_name='功能权限')),
],
options={
'verbose_name': '角色',
'verbose_name_plural': '角色',
},
),
migrations.CreateModel(
name='User',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('name', models.CharField(blank=True, max_length=20, null=True, verbose_name='姓名')),
('phone', models.CharField(blank=True, max_length=11, null=True, unique=True, verbose_name='手机号码')),
('avatar', models.CharField(blank=True, default='/media/default/avatar.png', max_length=1000, null=True, verbose_name='头像')),
('dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.Organization', verbose_name='组织')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('position', models.ManyToManyField(blank=True, to='system.Position', verbose_name='岗位')),
('roles', models.ManyToManyField(blank=True, to='system.Role', verbose_name='角色')),
('superior', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='上级主管')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': '用户信息',
'verbose_name_plural': '用户信息',
'ordering': ['id'],
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View File

@ -0,0 +1,47 @@
# Generated by Django 3.0.5 on 2020-05-11 09:19
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('system', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='DictType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=30, verbose_name='名称')),
('code', models.CharField(max_length=30, unique=True, verbose_name='代号')),
('pid', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.DictType', verbose_name='')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Dict',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=30, unique=True, verbose_name='名称')),
('desc', models.TextField(blank=True, null=True, verbose_name='描述')),
('sort', models.IntegerField(default=1, verbose_name='排序')),
('pid', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.Dict', verbose_name='')),
('type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.DictType', verbose_name='类型')),
],
options={
'abstract': False,
},
),
]

View File

@ -1,5 +1,5 @@
from django.urls import path, include from django.urls import path, include
from .views import UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView from .views import UserViewSet, OrganizationViewSet, PermissionViewSet, RoleViewSet, PositionViewSet, TestView, DictTypeViewSet, DictViewSet
from rest_framework import routers from rest_framework import routers
@ -9,7 +9,8 @@ router.register('organization', OrganizationViewSet, basename="organization")
router.register('permission', PermissionViewSet, basename="permission") router.register('permission', PermissionViewSet, basename="permission")
router.register('role', RoleViewSet, basename="role") router.register('role', RoleViewSet, basename="role")
router.register('position', PositionViewSet, basename="position") router.register('position', PositionViewSet, basename="position")
router.register('dicttype', DictTypeViewSet, basename="dicttype")
router.register('dict', DictViewSet, basename="dict")
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),
path('test/', TestView.as_view()) path('test/', TestView.as_view())

View File

@ -16,12 +16,12 @@ from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from utils.queryset import get_child_queryset from utils.queryset import get_child_queryset
from .models import Organization, Permission, Position, Role, User from .models import Organization, Permission, Position, Role, User, Dict, DictType
from .permission import RbacPermission, get_permission_list from .permission import RbacPermission, get_permission_list
from .serializers import (OrganizationSerializer, PermissionSerializer, from .serializers import (OrganizationSerializer, PermissionSerializer,
PositionSerializer, RoleSerializer, PositionSerializer, RoleSerializer,
UserCreateSerializer, UserListSerializer, UserCreateSerializer, UserListSerializer,
UserModifySerializer) UserModifySerializer, DictSerializer, DictTypeSerializer)
from .filters import UserFilter from .filters import UserFilter
import logging import logging
@ -37,6 +37,40 @@ class LogoutView(APIView):
return Response(status=status.HTTP_200_OK) return Response(status=status.HTTP_200_OK)
class DictTypeViewSet(ModelViewSet):
"""
数据字典类型增删改查
"""
perms_map = [{'post': 'dicttype_create'},
{'put': 'dicttype_update'},
{'delete': 'dicttype_delete'},
{'get': 'dicttype_view'},
]
queryset = DictType.objects.all()
serializer_class = DictTypeSerializer
pagination_class = None
search_fields = ['^name']
ordering_fields = ['id']
ordering = 'id'
class DictViewSet(ModelViewSet):
"""
数据字典增删改查
"""
perms_map = [{'post': 'dict_create'},
{'put': 'dict_update'},
{'delete': 'dict_delete'},
{'get': 'dict_view'},
]
queryset = Dict.objects.all()
serializer_class = DictSerializer
pagination_class = None
search_fields = ['^name']
ordering_fields = ['id']
ordering = 'id'
class PositionViewSet(ModelViewSet): class PositionViewSet(ModelViewSet):
""" """
岗位增删改查 岗位增删改查