导入功能完成

pull/2/head
李强 2021-03-20 15:47:16 +08:00
parent b4c1c871f5
commit d88e03ca89
12 changed files with 232 additions and 43 deletions

View File

@ -0,0 +1,31 @@
from logging import StreamHandler, getLevelName
from logging.handlers import RotatingFileHandler
from typing import Optional, IO
class MyStreamHandler(StreamHandler):
def __init__(self, stream: Optional[IO[str]] = ...) -> None:
print(222)
super().__init__(stream)
def __repr__(self):
level = getLevelName(self.level)
name = getattr(self.stream, 'name', '')
# bpo-36015: name can be an int
name = str(name)
if name:
name += ' '
print(111)
return '<%s %s(%s)>' % (self.__class__.__name__, name, level)
class MyRotatingFileHandler(RotatingFileHandler):
def __init__(self, filename: str, mode: str = ..., maxBytes: int = ..., backupCount: int = ...,
encoding: Optional[str] = ..., delay: bool = ...) -> None:
print(4444)
super().__init__(filename, mode, maxBytes, backupCount, encoding, delay)
def __repr__(self):
level = getLevelName(self.level)
print(22)
return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level)

View File

@ -1,3 +1,4 @@
from django.db import transaction
from rest_framework import mixins from rest_framework import mixins
from rest_framework import serializers from rest_framework import serializers
from rest_framework import status from rest_framework import status
@ -5,6 +6,7 @@ from rest_framework.relations import ManyRelatedField, RelatedField, PrimaryKeyR
from rest_framework.request import Request from rest_framework.request import Request
from .response import SuccessResponse from .response import SuccessResponse
from ..utils.export_excel import excel_to_data, export_excel_save_model
class CreateModelMixin(mixins.CreateModelMixin): class CreateModelMixin(mixins.CreateModelMixin):
@ -271,3 +273,75 @@ class TableSerializerMixin:
info['type'] = 'select' info['type'] = 'select'
column.append(info) column.append(info)
return column return column
class ImportSerializerMixin:
"""
自定义导出模板导入功能
"""
# 导入字段
import_field_data = {}
# 导入序列化器
import_serializer_class = None
@transaction.atomic # Django 事物
def importTemplate(self, request: Request, *args, **kwargs):
"""
用户导人模板
:param request:
:param args:
:param kwargs:
:return:
"""
assert self.import_field_data, (
"'%s' 请配置对应的导出模板字段。"
% self.__class__.__name__
)
# 导出模板
if request.method == 'GET':
# 示例数据
return SuccessResponse(
export_excel_save_model(request, self.import_field_data.values(), [], '导入用户数据模板.xls'))
updateSupport = request.data.get('updateSupport')
# 从excel中组织对应的数据结构然后使用序列化器保存
data = excel_to_data(request.data.get('file_url'), self.import_field_data)
unique_list = [ele.attname for ele in self.get_queryset().model._meta.get_fields() if
hasattr(ele, 'unique') and ele.unique == True]
for ele in data:
# 获取 unique 字段
filter_dic = {i: ele.get(i) for i in list(set(self.import_field_data.keys()) & set(unique_list))}
instance = self.get_queryset().filter(**filter_dic).first()
if instance and not updateSupport:
continue
if not filter_dic:
instance = None
serializer = self.import_serializer_class(instance, data=ele)
serializer.is_valid(raise_exception=True)
serializer.save()
return SuccessResponse(msg=f"导入成功!")
class ExportSerializerMixin:
"""
自定义导出功能
"""
# 导出字段
export_field_data = []
# 导出序列化器
export_serializer_class = None
def export(self, request: Request, *args, **kwargs):
"""
导出功能
:param request:
:param args:
:param kwargs:
:return:
"""
assert self.export_field_data, (
"'%s' 请配置对应的导出模板字段。"
% self.__class__.__name__
)
data = self.export_serializer_class(self.get_queryset(), many=True).data
return SuccessResponse(export_excel_save_model(request, self.export_field_data, data, '导出用户数据.xls'))

View File

@ -201,7 +201,9 @@ class MongoModelViewSet(mixins.CreateModelMixin,
pass pass
class CustomModelViewSet(ModelViewSet, mixins.TableSerializerMixin): class CustomModelViewSet(ModelViewSet, mixins.TableSerializerMixin,
mixins.ImportSerializerMixin,
mixins.ExportSerializerMixin):
""" """
自定义的ModelViewSet: 自定义的ModelViewSet:
(1)默认分页器就为统一分页器op_drf.pagination.Pagination (1)默认分页器就为统一分页器op_drf.pagination.Pagination

View File

@ -1,4 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from rest_framework.fields import empty
from rest_framework.validators import UniqueValidator from rest_framework.validators import UniqueValidator
from ..op_drf.serializers import CustomModelSerializer from ..op_drf.serializers import CustomModelSerializer
@ -285,3 +286,25 @@ class UserProfileCreateUpdateSerializer(CustomModelSerializer):
model = UserProfile model = UserProfile
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined') exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')
read_only_fields = ('dept',) read_only_fields = ('dept',)
class UserProfileImportSerializer(CustomModelSerializer):
def save(self, **kwargs):
data = super().save(**kwargs)
data.set_password(self.initial_data.get('password', None))
data.save()
return data
def run_validation(self, data={}):
# 把excel 数据进行格式转换
if type(data) is dict:
data['role'] = str(data['role']).split(',')
data['post'] = str(data['post']).split(',')
data['gender'] = {'': '0', '': '1', '未知': '2'}.get(data['gender'])
data['is_active'] = {'启用': True, '禁用': False}.get(data['is_active'])
return super().run_validation(data)
class Meta:
model = UserProfile
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')

View File

@ -29,13 +29,16 @@ urlpatterns = [
# 用户自己重置密码 # 用户自己重置密码
re_path('user/profile/updatePwd/', UserProfileModelViewSet.as_view({'put': 'update_pwd'})), re_path('user/profile/updatePwd/', UserProfileModelViewSet.as_view({'put': 'update_pwd'})),
# 获取、更新用户个人信息 # 获取、更新用户个人信息
re_path('user/profile/', UserProfileModelViewSet.as_view({'get': 'profile','put': 'put_profile'})), re_path('user/profile/', UserProfileModelViewSet.as_view({'get': 'profile', 'put': 'put_profile'})),
# 导出用户 # 导出用户
re_path('user/export/', UserProfileModelViewSet.as_view({'get': 'export',})), re_path('user/export/', UserProfileModelViewSet.as_view({'get': 'export', })),
# 导出角色 # 导出角色
re_path('role/export/', RoleModelViewSet.as_view({'get': 'export',})), re_path('role/export/', RoleModelViewSet.as_view({'get': 'export', })),
# 导出岗位 # 导出岗位
re_path('post/export/', PostModelViewSet.as_view({'get': 'export',})), re_path('post/export/', PostModelViewSet.as_view({'get': 'export', })),
# 用户导入模板下载及导入
re_path('user/importTemplate/',
UserProfileModelViewSet.as_view({'get': 'importTemplate', 'post': 'importTemplate'})),
] ]
urlpatterns += router.urls urlpatterns += router.urls

View File

@ -2,16 +2,17 @@ from django.contrib.auth import authenticate
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.views import APIView from rest_framework.views import APIView
from ..op_drf.filters import DataLevelPermissionsFilter
from ..op_drf.viewsets import CustomModelViewSet from ..op_drf.viewsets import CustomModelViewSet
from ..permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter from ..permission.filters import MenuFilter, DeptFilter, PostFilter, RoleFilter, UserProfileFilter
from ..permission.models import Role, Menu, Dept, Post, UserProfile from ..permission.models import Role, Menu, Dept, Post, UserProfile
from ..permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \ from ..permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \
MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \ MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \
RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \ RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \
PostSimpleSerializer, RoleSimpleSerializer, ExportUserProfileSerializer, ExportRoleSerializer, ExportPostSerializer PostSimpleSerializer, RoleSimpleSerializer, ExportUserProfileSerializer, ExportRoleSerializer, ExportPostSerializer, \
from ..op_drf.filters import DataLevelPermissionsFilter UserProfileImportSerializer
from ..system.models import DictDetails from ..system.models import DictDetails
from ..utils.export_excel import export_excel_save_model from ..utils.export_excel import export_excel_save_model, excel_to_data
from ..utils.response import SuccessResponse, ErrorResponse from ..utils.response import SuccessResponse, ErrorResponse
@ -22,7 +23,7 @@ class GetUserProfileView(APIView):
def get(self, request, format=None): def get(self, request, format=None):
user_dict = UserProfileSerializer(request.user).data user_dict = UserProfileSerializer(request.user).data
permissions_list = ["*:*:*"] if user_dict.get('admin') else Menu.objects.filter( permissions_list = ['*:*:*'] if user_dict.get('admin') else Menu.objects.filter(
role__userprofile=request.user).values_list('perms', flat=True) role__userprofile=request.user).values_list('perms', flat=True)
return SuccessResponse({ return SuccessResponse({
'permissions': [ele for ele in permissions_list if ele], 'permissions': [ele for ele in permissions_list if ele],
@ -47,14 +48,14 @@ class GetRouters(APIView):
def get(self, request, format=None): def get(self, request, format=None):
# data = GetUserInfoSerializer(request.user).data # data = GetUserInfoSerializer(request.user).data
menus = Menu.objects.filter(role__userprofile=request.user).exclude(menuType="2").values('id', 'name', menus = Menu.objects.filter(role__userprofile=request.user).exclude(menuType='2').values('id', 'name',
'web_path', 'web_path',
'visible', 'status', 'visible', 'status',
'isFrame', 'isFrame',
'component_path', 'component_path',
'icon', 'parentId', 'icon', 'parentId',
'isCache').distinct() 'isCache').distinct()
# data = '{"msg":"操作成功","code":200,"data":[{"name":"System","path":"/system","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统管理","icon":"system","noCache":false},"children":[{"name":"User","path":"user","hidden":false,"component":"permission/user/index","meta":{"title":"用户管理","icon":"user","noCache":false}},{"name":"Role","path":"role","hidden":false,"component":"permission/role/index","meta":{"title":"角色管理","icon":"peoples","noCache":false}},{"name":"Menu","path":"menu","hidden":false,"component":"permission/menu/index","meta":{"title":"菜单管理","icon":"tree-table","noCache":false}},{"name":"Dept","path":"dept","hidden":false,"component":"permission/dept/index","meta":{"title":"部门管理","icon":"tree","noCache":false}},{"name":"Post","path":"post","hidden":false,"component":"permission/post/index","meta":{"title":"岗位管理","icon":"post","noCache":false}},{"name":"Dict","path":"dict","hidden":false,"component":"system/dict/index","meta":{"title":"字典管理","icon":"dict","noCache":false}},{"name":"Config","path":"config","hidden":false,"component":"system/config/index","meta":{"title":"参数设置","icon":"edit","noCache":false}},{"name":"Notice","path":"notice","hidden":false,"component":"system/notice/index","meta":{"title":"通知公告","icon":"message","noCache":false}},{"name":"Log","path":"log","hidden":false,"redirect":"noRedirect","component":"ParentView","alwaysShow":true,"meta":{"title":"日志管理","icon":"log","noCache":false},"children":[{"name":"Operlog","path":"operlog","hidden":false,"component":"monitor/operlog/index","meta":{"title":"操作日志","icon":"form","noCache":false}},{"name":"Logininfor","path":"logininfor","hidden":false,"component":"monitor/logininfor/index","meta":{"title":"登录日志","icon":"logininfor","noCache":false}}]}]},{"name":"Monitor","path":"/monitor","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统监控","icon":"monitor","noCache":false},"children":[{"name":"Online","path":"online","hidden":false,"component":"monitor/online/index","meta":{"title":"在线用户","icon":"online","noCache":false}},{"name":"Job","path":"job","hidden":false,"component":"monitor/job/index","meta":{"title":"定时任务","icon":"job","noCache":false}},{"name":"Druid","path":"druid","hidden":false,"component":"monitor/druid/index","meta":{"title":"数据监控","icon":"druid","noCache":false}},{"name":"Server","path":"server","hidden":false,"component":"monitor/server/index","meta":{"title":"服务监控","icon":"server","noCache":false}},{"name":"Cache","path":"cache","hidden":false,"component":"monitor/cache/index","meta":{"title":"缓存监控","icon":"redis","noCache":false}}]},{"name":"Tool","path":"/tool","hidden":false,"redirect":"noRedirect","component":"Layout","alwaysShow":true,"meta":{"title":"系统工具","icon":"tool","noCache":false},"children":[{"name":"Build","path":"build","hidden":false,"component":"tool/build/index","meta":{"title":"表单构建","icon":"build","noCache":false}},{"name":"Gen","path":"gen","hidden":false,"component":"tool/gen/index","meta":{"title":"代码生成","icon":"code","noCache":false}},{"name":"Swagger","path":"swagger","hidden":false,"component":"tool/swagger/index","meta":{"title":"系统接口","icon":"swagger","noCache":false}}]},{"name":"Http://ruoyi.vip","path":"http://ruoyi.vip","hidden":false,"component":"Layout","meta":{"title":"若依官网","icon":"guide","noCache":false}}]}' # data = '{'msg':'操作成功','code':200,'data':[{'name':'System','path':'/system','hidden':false,'redirect':'noRedirect','component':'Layout','alwaysShow':true,'meta':{'title':'系统管理','icon':'system','noCache':false},'children':[{'name':'User','path':'user','hidden':false,'component':'permission/user/index','meta':{'title':'用户管理','icon':'user','noCache':false}},{'name':'Role','path':'role','hidden':false,'component':'permission/role/index','meta':{'title':'角色管理','icon':'peoples','noCache':false}},{'name':'Menu','path':'menu','hidden':false,'component':'permission/menu/index','meta':{'title':'菜单管理','icon':'tree-table','noCache':false}},{'name':'Dept','path':'dept','hidden':false,'component':'permission/dept/index','meta':{'title':'部门管理','icon':'tree','noCache':false}},{'name':'Post','path':'post','hidden':false,'component':'permission/post/index','meta':{'title':'岗位管理','icon':'post','noCache':false}},{'name':'Dict','path':'dict','hidden':false,'component':'system/dict/index','meta':{'title':'字典管理','icon':'dict','noCache':false}},{'name':'Config','path':'config','hidden':false,'component':'system/config/index','meta':{'title':'参数设置','icon':'edit','noCache':false}},{'name':'Notice','path':'notice','hidden':false,'component':'system/notice/index','meta':{'title':'通知公告','icon':'message','noCache':false}},{'name':'Log','path':'log','hidden':false,'redirect':'noRedirect','component':'ParentView','alwaysShow':true,'meta':{'title':'日志管理','icon':'log','noCache':false},'children':[{'name':'Operlog','path':'operlog','hidden':false,'component':'monitor/operlog/index','meta':{'title':'操作日志','icon':'form','noCache':false}},{'name':'Logininfor','path':'logininfor','hidden':false,'component':'monitor/logininfor/index','meta':{'title':'登录日志','icon':'logininfor','noCache':false}}]}]},{'name':'Monitor','path':'/monitor','hidden':false,'redirect':'noRedirect','component':'Layout','alwaysShow':true,'meta':{'title':'系统监控','icon':'monitor','noCache':false},'children':[{'name':'Online','path':'online','hidden':false,'component':'monitor/online/index','meta':{'title':'在线用户','icon':'online','noCache':false}},{'name':'Job','path':'job','hidden':false,'component':'monitor/job/index','meta':{'title':'定时任务','icon':'job','noCache':false}},{'name':'Druid','path':'druid','hidden':false,'component':'monitor/druid/index','meta':{'title':'数据监控','icon':'druid','noCache':false}},{'name':'Server','path':'server','hidden':false,'component':'monitor/server/index','meta':{'title':'服务监控','icon':'server','noCache':false}},{'name':'Cache','path':'cache','hidden':false,'component':'monitor/cache/index','meta':{'title':'缓存监控','icon':'redis','noCache':false}}]},{'name':'Tool','path':'/tool','hidden':false,'redirect':'noRedirect','component':'Layout','alwaysShow':true,'meta':{'title':'系统工具','icon':'tool','noCache':false},'children':[{'name':'Build','path':'build','hidden':false,'component':'tool/build/index','meta':{'title':'表单构建','icon':'build','noCache':false}},{'name':'Gen','path':'gen','hidden':false,'component':'tool/gen/index','meta':{'title':'代码生成','icon':'code','noCache':false}},{'name':'Swagger','path':'swagger','hidden':false,'component':'tool/swagger/index','meta':{'title':'系统接口','icon':'swagger','noCache':false}}]},{'name':'Http://ruoyi.vip','path':'http://ruoyi.vip','hidden':false,'component':'Layout','meta':{'title':'若依官网','icon':'guide','noCache':false}}]}'
# data = json.loads(data) # data = json.loads(data)
data = [] data = []
sys_show_hide = DictDetails.get_default_dictValue('sys_show_hide') sys_show_hide = DictDetails.get_default_dictValue('sys_show_hide')
@ -66,7 +67,8 @@ class GetRouters(APIView):
'hidden': True if ele.get('visible') != '1' else False, 'hidden': True if ele.get('visible') != '1' else False,
'redirect': ele.get('web_path') if ele.get('isFrame') == '1' else 'noRedirect', 'redirect': ele.get('web_path') if ele.get('isFrame') == '1' else 'noRedirect',
'component': ele.get('component_path') or 'Layout', 'component': ele.get('component_path') or 'Layout',
'meta': {"title": ele.get('name'), "icon": ele.get('icon'), "noCache": True if ele.get('isCache') == sys_show_hide else False}, 'meta': {'title': ele.get('name'), 'icon': ele.get('icon'),
'noCache': True if ele.get('isCache') == sys_show_hide else False},
'parentId': ele.get('parentId') 'parentId': ele.get('parentId')
}) })
return SuccessResponse(data) return SuccessResponse(data)
@ -254,6 +256,15 @@ class UserProfileModelViewSet(CustomModelViewSet):
update_serializer_class = UserProfileCreateUpdateSerializer update_serializer_class = UserProfileCreateUpdateSerializer
filter_class = UserProfileFilter filter_class = UserProfileFilter
extra_filter_backends = [DataLevelPermissionsFilter] extra_filter_backends = [DataLevelPermissionsFilter]
# 导出
export_serializer_class = ExportUserProfileSerializer
export_field_data = ['用户序号', '登录名称', '用户名称', '用户邮箱', '手机号码', '用户性别', '帐号状态', '最后登录时间', '部门名称', '部门负责人']
# 导入
import_serializer_class = UserProfileImportSerializer
import_field_data = {'username': '登录账号', 'name': '用户名称', 'email': '用户邮箱', 'mobile': '手机号码',
'gender': '用户性别(男/女/未知)',
'is_active': '帐号状态(启用/禁用)', 'password': '登录密码', 'dept': '部门ID', 'role': '角色ID',
'post': '岗位ID'}
# update_extra_permission_classes = (IsManagerPermission,) # update_extra_permission_classes = (IsManagerPermission,)
# destroy_extra_permission_classes = (IsManagerPermission,) # destroy_extra_permission_classes = (IsManagerPermission,)
# create_extra_permission_classes = (IsManagerPermission,) # create_extra_permission_classes = (IsManagerPermission,)
@ -366,15 +377,3 @@ class UserProfileModelViewSet(CustomModelViewSet):
if hasattr(self, 'handle_logging'): if hasattr(self, 'handle_logging'):
self.handle_logging(request, instance=instance, *args, **kwargs) self.handle_logging(request, instance=instance, *args, **kwargs)
return SuccessResponse(serializer.data) return SuccessResponse(serializer.data)
def export(self, request: Request, *args, **kwargs):
"""
导出用户
:param request:
:param args:
:param kwargs:
:return:
"""
field_data = ['用户序号', '登录名称', '用户名称', '用户邮箱', '手机号码', '用户性别', '帐号状态', '最后登录时间', '部门名称', '部门负责人']
data = ExportUserProfileSerializer(UserProfile.objects.all(), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, '导出用户数据.xls'))

View File

@ -2,6 +2,7 @@ import logging
import traceback import traceback
from rest_framework import serializers, exceptions from rest_framework import serializers, exceptions
from rest_framework.views import set_rollback
from .response import ErrorResponse from .response import ErrorResponse
@ -67,9 +68,10 @@ def op_exception_handler(ex, context):
code = 401 code = 401
msg = ex.detail msg = ex.detail
elif isinstance(ex, DRFAPIException): elif isinstance(ex, DRFAPIException):
# set_rollback() set_rollback()
msg = ex.detail msg = ex.detail
elif isinstance(ex, exceptions.APIException): elif isinstance(ex, exceptions.APIException):
set_rollback()
msg = ex.detail msg = ex.detail
elif isinstance(ex, Exception): elif isinstance(ex, Exception):
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())

View File

@ -3,6 +3,7 @@ import hashlib
import os import os
import time import time
import xlrd
import xlwt import xlwt
from django.conf import settings from django.conf import settings
@ -68,8 +69,8 @@ def export_excel(field_data: list, data: list, FileName: str, file_path: str = s
# 确定栏位宽度 # 确定栏位宽度
col_width = [] col_width = []
for index,ele in enumerate(data): for index, ele in enumerate(data):
for inx,values in enumerate(ele.values()): for inx, values in enumerate(ele.values()):
if index == 0: if index == 0:
col_width.append(len_byte(str(values))) col_width.append(len_byte(str(values)))
else: else:
@ -83,7 +84,6 @@ def export_excel(field_data: list, data: list, FileName: str, file_path: str = s
else: else:
sheet.col(i).width = 256 * (default_width) sheet.col(i).width = 256 * (default_width)
row = 1 row = 1
# 内容背景颜色 # 内容背景颜色
left_pattern = xlwt.Pattern() # 创建一个模式 left_pattern = xlwt.Pattern() # 创建一个模式
@ -113,7 +113,8 @@ def export_excel(field_data: list, data: list, FileName: str, file_path: str = s
wbk.save(path_name) wbk.save(path_name)
return os.path.join('system', monthTime, FileName) return os.path.join('system', monthTime, FileName)
def export_excel_save_model(request,field_data,data,FilName):
def export_excel_save_model(request, field_data, data, FilName):
""" """
导出Excel并保存到 SaveFile 文件管理中 导出Excel并保存到 SaveFile 文件管理中
:param request: :param request:
@ -125,7 +126,7 @@ def export_excel_save_model(request,field_data,data,FilName):
# 根据生成的字典MD5 # 根据生成的字典MD5
time_stamp = hashlib.md5(str(field_data).encode('utf8')).hexdigest() time_stamp = hashlib.md5(str(field_data).encode('utf8')).hexdigest()
# 存入文件数据库中 # 存入文件数据库中
FilName = str(time_stamp) + FilName FilName = '.'.join(FilName.split('.')[:-1]) + str(time_stamp) + '.' + FilName.split('.')[-1]
file_rul = export_excel(field_data=field_data, data=data, FileName=FilName) file_rul = export_excel(field_data=field_data, data=data, FileName=FilName)
savefile, _ = SaveFile.objects.get_or_create(file=file_rul) savefile, _ = SaveFile.objects.get_or_create(file=file_rul)
if _ == True: if _ == True:
@ -137,3 +138,33 @@ def export_excel_save_model(request,field_data,data,FilName):
savefile.modifier = request.user.username savefile.modifier = request.user.username
savefile.save() savefile.save()
return SaveFileSerializer(savefile).data return SaveFileSerializer(savefile).data
def excel_to_data(file_url, field_data):
"""
读取导入的excel文件
:param request:
:param field_data: 首行数据源
:param data: 数据源
:param FilName: 文件名
:return:
"""
# 读取excel 文件
data = xlrd.open_workbook(os.path.join(settings.BASE_DIR, *file_url.split(os.sep)))
table = data.sheets()[0]
# 创建一个空列表存储Excel的数据
tables = []
for i, rown in enumerate(range(table.nrows)):
if i == 0: continue
array = {}
for index, ele in enumerate(field_data.keys()):
cell_value = table.cell_value(rown, index)
# 由于excel导入数字类型后会出现数字加 .0 的,进行处理
if type(cell_value) is float and str(cell_value).split('.')[1] == '0':
cell_value = int(str(cell_value).split('.')[0])
if type(cell_value) is str:
cell_value = cell_value.strip(' \t\n\r')
array[ele] = cell_value
tables.append(array)
return tables

View File

@ -20,6 +20,7 @@ redis==3.5.3
six==1.15.0 six==1.15.0
sqlparse==0.4.1 sqlparse==0.4.1
xlwt==1.3.0 xlwt==1.3.0
xlrd==2.0.1
coreapi==2.3.3 coreapi==2.3.3
user-agents==2.2.0 user-agents==2.2.0
eventlet==0.30.2 eventlet==0.30.2

View File

@ -13,7 +13,7 @@ export function listUser(query) {
// 查询用户详细 // 查询用户详细
export function getUser(userId) { export function getUser(userId) {
return request({ return request({
url: '/admin/permission/user/details/?userId=' + praseStrEmpty(userId) , url: '/admin/permission/user/details/?userId=' + praseStrEmpty(userId),
method: 'get' method: 'get'
}) })
} }
@ -112,7 +112,7 @@ export function updateUserPwd(oldPassword, newPassword) {
// 用户头像上传 // 用户头像上传
export function uploadAvatar(data) { export function uploadAvatar(data) {
return request({ return request({
url: '/admin/permission/user/profile/avatar', url: '/admin/permission/user/profile/avatar/',
method: 'post', method: 'post',
data: data data: data
}) })
@ -121,7 +121,16 @@ export function uploadAvatar(data) {
// 下载用户导入模板 // 下载用户导入模板
export function importTemplate() { export function importTemplate() {
return request({ return request({
url: '/admin/permission/user/importTemplate', url: '/admin/permission/user/importTemplate/',
method: 'get' method: 'get'
}) })
} }
// 用户导入
export function importsUser(data) {
return request({
url: '/admin/permission/user/importTemplate/',
method: 'post',
data: data
})
}

View File

@ -64,7 +64,7 @@ export default {
name:'FileUpload', name:'FileUpload',
data() { data() {
return { return {
uploadFileUrl: process.env.VUE_APP_BASE_API + "/system/savefile/", // uploadFileUrl: process.env.VUE_APP_BASE_API + "/admin/system/savefile/", //
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: "Bearer " + getToken(),
}, },

View File

@ -343,13 +343,24 @@
</template> </template>
<script> <script>
import { listUser, getUser, delUser, addUser, updateUser, exportUser, resetUserPwd, changeUserStatus, importTemplate } from "@/api/vadmin/permission/user"; import {
import { getToken } from "@/utils/auth"; addUser,
import { treeselect } from "@/api/vadmin/permission/dept"; changeUserStatus,
import Treeselect from "@riophae/vue-treeselect"; delUser,
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; exportUser,
getUser,
importsUser,
importTemplate,
listUser,
resetUserPwd,
updateUser
} from "@/api/vadmin/permission/user";
import {getToken} from "@/utils/auth";
import {treeselect} from "@/api/vadmin/permission/dept";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default { export default {
name: "User", name: "User",
components: { Treeselect }, components: { Treeselect },
data() { data() {
@ -407,7 +418,7 @@ export default {
// //
headers: { Authorization: "Bearer " + getToken() }, headers: { Authorization: "Bearer " + getToken() },
// //
url: process.env.VUE_APP_BASE_API + "/system/savefile/" url: process.env.VUE_APP_BASE_API + "/admin/system/savefile/"
}, },
// //
queryParams: { queryParams: {
@ -665,8 +676,11 @@ export default {
this.upload.open = false; this.upload.open = false;
this.upload.isUploading = false; this.upload.isUploading = false;
this.$refs.upload.clearFiles(); this.$refs.upload.clearFiles();
this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true }); //
this.getList(); importsUser({file_url: response.data.file_url,updateSupport:this.upload.updateSupport}).then(response => {
this.$alert('导入成功!', "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
});
}, },
// //
submitFileForm() { submitFileForm() {