功能变化:

优化导出功能
pull/71/MERGE
猿小天 2022-09-20 20:25:10 +08:00
parent 8919307945
commit 7f503e27b7
5 changed files with 79 additions and 30 deletions

View File

@ -91,6 +91,16 @@ class LoginSerializer(TokenObtainPairSerializer):
data["name"] = self.user.name data["name"] = self.user.name
data["userId"] = self.user.id data["userId"] = self.user.id
data["avatar"] = self.user.avatar data["avatar"] = self.user.avatar
dept = getattr(self.user, 'dept', None)
if dept:
data['dept_info'] = {
'dept_id': dept.id,
'dept_name': dept.name,
'dept_key': dept.key
}
role = getattr(self.user, 'role', None)
if role:
data['role_info'] = role.values('id', 'name', 'key')
request = self.context.get("request") request = self.context.get("request")
request.user = self.user request.user = self.user
# 记录登录日志 # 记录登录日志

View File

@ -223,17 +223,17 @@ class UserViewSet(CustomModelViewSet):
} }
search_fields = ["username", "name", "gender", "dept__name", "role__name"] search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出 # 导出
export_field_label = [ export_field_label = {
"用户账号", "username":"用户账号",
"用户名称", "name":"用户名称",
"用户邮箱", "email":"用户邮箱",
"手机号码", "mobile":"手机号码",
"用户性别", "gender":"用户性别",
"帐号状态", "is_active":"帐号状态",
"最后登录时间", "last_login":"最后登录时间",
"部门名称", "dept_name":"部门名称",
"部门负责人", "dept_owner":"部门负责人",
] }
export_serializer_class = ExportUserProfileSerializer export_serializer_class = ExportUserProfileSerializer
# 导入 # 导入
import_serializer_class = UserProfileImportSerializer import_serializer_class = UserProfileImportSerializer

View File

@ -26,6 +26,21 @@ class ImportSerializerMixin:
# 表格表头最大宽度默认50个字符 # 表格表头最大宽度默认50个字符
export_column_width = 50 export_column_width = 50
def is_number(self,num):
try:
float(num)
return True
except ValueError:
pass
try:
import unicodedata
unicodedata.numeric(num)
return True
except (TypeError, ValueError):
pass
return False
def get_string_len(self, string): def get_string_len(self, string):
""" """
获取字符串最大长度 获取字符串最大长度
@ -35,6 +50,8 @@ class ImportSerializerMixin:
length = 4 length = 4
if string is None: if string is None:
return length return length
if self.is_number(string):
return length
for char in string: for char in string:
length += 2.1 if ord(char) > 256 else 1 length += 2.1 if ord(char) > 256 else 1
return round(length, 1) if length <= self.export_column_width else self.export_column_width return round(length, 1) if length <= self.export_column_width else self.export_column_width
@ -155,6 +172,21 @@ class ExportSerializerMixin:
# 表格表头最大宽度默认50个字符 # 表格表头最大宽度默认50个字符
export_column_width = 50 export_column_width = 50
def is_number(self,num):
try:
float(num)
return True
except ValueError:
pass
try:
import unicodedata
unicodedata.numeric(num)
return True
except (TypeError, ValueError):
pass
return False
def get_string_len(self, string): def get_string_len(self, string):
""" """
获取字符串最大长度 获取字符串最大长度
@ -164,6 +196,8 @@ class ExportSerializerMixin:
length = 4 length = 4
if string is None: if string is None:
return length return length
if self.is_number(string):
return length
for char in string: for char in string:
length += 2.1 if ord(char) > 256 else 1 length += 2.1 if ord(char) > 256 else 1
return round(length, 1) if length <= self.export_column_width else self.export_column_width return round(length, 1) if length <= self.export_column_width else self.export_column_width
@ -176,36 +210,35 @@ class ExportSerializerMixin:
:param kwargs: :param kwargs:
:return: :return:
""" """
assert self.export_field_label, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__
queryset = self.filter_queryset(self.get_queryset()) queryset = self.filter_queryset(self.get_queryset())
assert self.export_field_label, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__
assert self.export_serializer_class, "'%s' 请配置对应的导出序列化器。" % self.__class__.__name__
data = self.export_serializer_class(queryset, many=True).data data = self.export_serializer_class(queryset, many=True).data
# 导出excel 表 # 导出excel 表
response = HttpResponse(content_type="application/msexcel") response = HttpResponse(content_type="application/msexcel")
response["Access-Control-Expose-Headers"] = f"Content-Disposition" response["Access-Control-Expose-Headers"] = f"Content-Disposition"
response["Content-Disposition"] = f'attachment;filename={quote(str(f"导出{get_verbose_name(queryset)}.xlsx"))}' response["content-disposition"] = f'attachment;filename={quote(str(f"导出{get_verbose_name(queryset)}.xlsx"))}'
wb = Workbook() wb = Workbook()
ws = wb.active ws = wb.active
header_data = ["序号", *self.export_field_label] header_data = ["序号", *self.export_field_label.values()]
hidden_header = ["#", *self.export_field_label.keys()]
df_len_max = [self.get_string_len(ele) for ele in header_data] df_len_max = [self.get_string_len(ele) for ele in header_data]
row = get_column_letter(len(self.export_field_label) + 1) row = get_column_letter(len(self.export_field_label) + 1)
column = 1 column = 1
ws.append(header_data) ws.append(header_data)
for index, results in enumerate(data): for index, results in enumerate(data):
results_list = [] results_list = []
for inx, result in enumerate(results.values()): for h_index, h_item in enumerate(hidden_header):
# 布尔值进行更新 for key,val in results.items():
if result is True: if key == h_item:
result = "" if val is None or val=="":
elif result is False: results_list.append("")
result = "" else:
if isinstance(result, int): results_list.append(val)
result = str(result) # 计算最大列宽度
# 计算最大列宽度 result_column_width = self.get_string_len(val)
result_column_width = self.get_string_len(result) if h_index !=0 and result_column_width > df_len_max[h_index]:
if result_column_width > df_len_max[inx + 1]: df_len_max[h_index] = result_column_width
df_len_max[inx + 1] = result_column_width
results_list.append(result)
ws.append([index + 1, *results_list]) ws.append([index + 1, *results_list])
column += 1 column += 1
#  更新列宽 #  更新列宽

View File

@ -38,7 +38,7 @@ class CustomModelViewSet(ModelViewSet,ImportSerializerMixin,ExportSerializerMixi
extra_filter_backends = [DataLevelPermissionsFilter] extra_filter_backends = [DataLevelPermissionsFilter]
permission_classes = [CustomPermission] permission_classes = [CustomPermission]
import_field_dict = {} import_field_dict = {}
export_field_label = [] export_field_label = {}
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])): for backend in set(set(self.filter_backends) | set(self.extra_filter_backends or [])):

View File

@ -44,7 +44,13 @@ export default {
util.cookies.set('token', res.access) util.cookies.set('token', res.access)
util.cookies.set('refresh', res.refresh) util.cookies.set('refresh', res.refresh)
// 设置 vuex 用户信息 // 设置 vuex 用户信息
await dispatch('d2admin/user/set', { name: res.name, user_id: res.userId, avatar: res.avatar }, { root: true }) await dispatch('d2admin/user/set', {
name: res.name,
user_id: res.userId,
avatar: res.avatar,
role_info: res.role_info,
dept_info: res.dept_info
}, { root: true })
// 用户登录后从持久化数据加载一系列的设置 // 用户登录后从持久化数据加载一系列的设置
await dispatch('load') await dispatch('load')
}, },