feat(web/user): added back export/import buttons
							parent
							
								
									ded39aeaf5
								
							
						
					
					
						commit
						ef50e55e2e
					
				|  | @ -14,7 +14,7 @@ STATUS_CHOICES = ( | |||
| 
 | ||||
| 
 | ||||
| class Users(AbstractUser, CoreModel): | ||||
|     username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name='用户账号', help_text="用户账号") | ||||
|     username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号") | ||||
|     email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱") | ||||
|     mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话") | ||||
|     avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像") | ||||
|  | @ -24,27 +24,36 @@ class Users(AbstractUser, CoreModel): | |||
|         (1, "男"), | ||||
|         (2, "女"), | ||||
|     ) | ||||
|     gender = models.IntegerField(choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, | ||||
|                                  help_text="性别") | ||||
|     gender = models.IntegerField( | ||||
|         choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, help_text="性别" | ||||
|     ) | ||||
|     USER_TYPE = ( | ||||
|         (0, "后台用户"), | ||||
|         (1, "前台用户"), | ||||
|     ) | ||||
|     user_type = models.IntegerField(choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, | ||||
|                                     help_text="用户类型") | ||||
|     post = models.ManyToManyField(to='Post', verbose_name='关联岗位', db_constraint=False, help_text="关联岗位") | ||||
|     role = models.ManyToManyField(to='Role', verbose_name='关联角色', db_constraint=False, help_text="关联角色") | ||||
|     dept = models.ForeignKey(to='Dept', verbose_name='所属部门', on_delete=models.PROTECT, db_constraint=False, null=True, | ||||
|                              blank=True, help_text="关联部门") | ||||
|     user_type = models.IntegerField( | ||||
|         choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型" | ||||
|     ) | ||||
|     post = models.ManyToManyField(to="Post", verbose_name="关联岗位", db_constraint=False, help_text="关联岗位") | ||||
|     role = models.ManyToManyField(to="Role", verbose_name="关联角色", db_constraint=False, help_text="关联角色") | ||||
|     dept = models.ForeignKey( | ||||
|         to="Dept", | ||||
|         verbose_name="所属部门", | ||||
|         on_delete=models.PROTECT, | ||||
|         db_constraint=False, | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         help_text="关联部门", | ||||
|     ) | ||||
| 
 | ||||
|     def set_password(self, raw_password): | ||||
|         super().set_password(hashlib.md5(raw_password.encode(encoding='UTF-8')).hexdigest()) | ||||
|         super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest()) | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_users" | ||||
|         verbose_name = '用户表' | ||||
|         verbose_name = "用户表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-create_datetime',) | ||||
|         ordering = ("-create_datetime",) | ||||
| 
 | ||||
| 
 | ||||
| class Post(CoreModel): | ||||
|  | @ -59,9 +68,9 @@ class Post(CoreModel): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_post" | ||||
|         verbose_name = '岗位表' | ||||
|         verbose_name = "岗位表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
| 
 | ||||
| 
 | ||||
| class Role(CoreModel): | ||||
|  | @ -79,16 +88,17 @@ class Role(CoreModel): | |||
|     ) | ||||
|     data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name="数据权限范围", help_text="数据权限范围") | ||||
|     remark = models.TextField(verbose_name="备注", help_text="备注", null=True, blank=True) | ||||
|     dept = models.ManyToManyField(to='Dept', verbose_name='数据权限-关联部门', db_constraint=False, help_text="数据权限-关联部门") | ||||
|     menu = models.ManyToManyField(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text="关联菜单") | ||||
|     permission = models.ManyToManyField(to='MenuButton', verbose_name='关联菜单的接口按钮', db_constraint=False, | ||||
|                                         help_text="关联菜单的接口按钮") | ||||
|     dept = models.ManyToManyField(to="Dept", verbose_name="数据权限-关联部门", db_constraint=False, help_text="数据权限-关联部门") | ||||
|     menu = models.ManyToManyField(to="Menu", verbose_name="关联菜单", db_constraint=False, help_text="关联菜单") | ||||
|     permission = models.ManyToManyField( | ||||
|         to="MenuButton", verbose_name="关联菜单的接口按钮", db_constraint=False, help_text="关联菜单的接口按钮" | ||||
|     ) | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + 'system_role' | ||||
|         verbose_name = '角色表' | ||||
|         db_table = table_prefix + "system_role" | ||||
|         verbose_name = "角色表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
| 
 | ||||
| 
 | ||||
| class Dept(CoreModel): | ||||
|  | @ -97,21 +107,35 @@ class Dept(CoreModel): | |||
|     owner = models.CharField(max_length=32, verbose_name="负责人", null=True, blank=True, help_text="负责人") | ||||
|     phone = models.CharField(max_length=32, verbose_name="联系电话", null=True, blank=True, help_text="联系电话") | ||||
|     email = models.EmailField(max_length=32, verbose_name="邮箱", null=True, blank=True, help_text="邮箱") | ||||
|     status = models.BooleanField(default=True, verbose_name="部门状态", null=True, blank=True, | ||||
|                                  help_text="部门状态") | ||||
|     parent = models.ForeignKey(to='Dept', on_delete=models.CASCADE, default=None, verbose_name="上级部门", | ||||
|                                db_constraint=False, null=True, blank=True, help_text="上级部门") | ||||
|     status = models.BooleanField(default=True, verbose_name="部门状态", null=True, blank=True, help_text="部门状态") | ||||
|     parent = models.ForeignKey( | ||||
|         to="Dept", | ||||
|         on_delete=models.CASCADE, | ||||
|         default=None, | ||||
|         verbose_name="上级部门", | ||||
|         db_constraint=False, | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         help_text="上级部门", | ||||
|     ) | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_dept" | ||||
|         verbose_name = '部门表' | ||||
|         verbose_name = "部门表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
| 
 | ||||
| 
 | ||||
| class Menu(CoreModel): | ||||
|     parent = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name="上级菜单", null=True, blank=True, | ||||
|                                db_constraint=False, help_text="上级菜单") | ||||
|     parent = models.ForeignKey( | ||||
|         to="Menu", | ||||
|         on_delete=models.CASCADE, | ||||
|         verbose_name="上级菜单", | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         db_constraint=False, | ||||
|         help_text="上级菜单", | ||||
|     ) | ||||
|     icon = models.CharField(max_length=64, verbose_name="菜单图标", null=True, blank=True, help_text="菜单图标") | ||||
|     name = models.CharField(max_length=64, verbose_name="菜单名称", help_text="菜单名称") | ||||
|     sort = models.IntegerField(default=1, verbose_name="显示排序", null=True, blank=True, help_text="显示排序") | ||||
|  | @ -130,14 +154,20 @@ class Menu(CoreModel): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_menu" | ||||
|         verbose_name = '菜单表' | ||||
|         verbose_name = "菜单表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
| 
 | ||||
| 
 | ||||
| class MenuButton(CoreModel): | ||||
|     menu = models.ForeignKey(to="Menu", db_constraint=False, related_name="menuPermission", on_delete=models.CASCADE, | ||||
|                              verbose_name="关联菜单", help_text='关联菜单') | ||||
|     menu = models.ForeignKey( | ||||
|         to="Menu", | ||||
|         db_constraint=False, | ||||
|         related_name="menuPermission", | ||||
|         on_delete=models.CASCADE, | ||||
|         verbose_name="关联菜单", | ||||
|         help_text="关联菜单", | ||||
|     ) | ||||
|     name = models.CharField(max_length=64, verbose_name="名称", help_text="名称") | ||||
|     value = models.CharField(max_length=64, verbose_name="权限值", help_text="权限值") | ||||
|     api = models.CharField(max_length=200, verbose_name="接口地址", help_text="接口地址") | ||||
|  | @ -151,26 +181,34 @@ class MenuButton(CoreModel): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_menu_button" | ||||
|         verbose_name = '菜单权限表' | ||||
|         verbose_name = "菜单权限表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-name',) | ||||
|         ordering = ("-name",) | ||||
| 
 | ||||
| 
 | ||||
| class Dictionary(CoreModel): | ||||
|     TYPE_LIST = ( | ||||
|         (0, 'text'), | ||||
|         (1, 'number'), | ||||
|         (2, 'date'), | ||||
|         (3, 'datetime'), | ||||
|         (4, 'time'), | ||||
|         (5, 'files'), | ||||
|         (6, 'boolean'), | ||||
|         (7, 'images'), | ||||
|         (0, "text"), | ||||
|         (1, "number"), | ||||
|         (2, "date"), | ||||
|         (3, "datetime"), | ||||
|         (4, "time"), | ||||
|         (5, "files"), | ||||
|         (6, "boolean"), | ||||
|         (7, "images"), | ||||
|     ) | ||||
|     label = models.CharField(max_length=100, blank=True, null=True, verbose_name="字典名称", help_text="字典名称") | ||||
|     value = models.CharField(max_length=200, blank=True, null=True, verbose_name="字典编号", help_text="字典编号/实际值") | ||||
|     parent = models.ForeignKey(to='self', related_name='sublist', db_constraint=False, on_delete=models.PROTECT, | ||||
|                                blank=True, null=True, verbose_name="父级", help_text="父级") | ||||
|     parent = models.ForeignKey( | ||||
|         to="self", | ||||
|         related_name="sublist", | ||||
|         db_constraint=False, | ||||
|         on_delete=models.PROTECT, | ||||
|         blank=True, | ||||
|         null=True, | ||||
|         verbose_name="父级", | ||||
|         help_text="父级", | ||||
|     ) | ||||
|     type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name="数据值类型", help_text="数据值类型") | ||||
|     color = models.CharField(max_length=20, blank=True, null=True, verbose_name="颜色", help_text="颜色") | ||||
|     is_value = models.BooleanField(default=False, verbose_name="是否为value值", help_text="是否为value值,用来做具体值存放") | ||||
|  | @ -179,15 +217,15 @@ class Dictionary(CoreModel): | |||
|     remark = models.CharField(max_length=2000, blank=True, null=True, verbose_name="备注", help_text="备注") | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + 'system_dictionary' | ||||
|         db_table = table_prefix + "system_dictionary" | ||||
|         verbose_name = "字典表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
| 
 | ||||
|     def save(self, force_insert=False, force_update=False, using=None, update_fields=None): | ||||
|         super().save(force_insert, force_update, using, update_fields) | ||||
|         dispatch.refresh_dictionary() # 有更新则刷新字典配置 | ||||
|      | ||||
|         dispatch.refresh_dictionary()  # 有更新则刷新字典配置 | ||||
| 
 | ||||
|     def delete(self, using=None, keep_parents=False): | ||||
|         res = super().delete(using, keep_parents) | ||||
|         dispatch.refresh_dictionary() | ||||
|  | @ -208,16 +246,16 @@ class OperationLog(CoreModel): | |||
|     status = models.BooleanField(default=False, verbose_name="响应状态", help_text="响应状态") | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + 'system_operation_log' | ||||
|         verbose_name = '操作日志' | ||||
|         db_table = table_prefix + "system_operation_log" | ||||
|         verbose_name = "操作日志" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-create_datetime',) | ||||
|         ordering = ("-create_datetime",) | ||||
| 
 | ||||
| 
 | ||||
| def media_file_name(instance, filename): | ||||
|     h = instance.md5sum | ||||
|     basename, ext = os.path.splitext(filename) | ||||
|     return os.path.join('files', h[0:1], h[1:2], h + ext.lower()) | ||||
|     return os.path.join("files", h[0:1], h[1:2], h + ext.lower()) | ||||
| 
 | ||||
| 
 | ||||
| class FileList(CoreModel): | ||||
|  | @ -234,10 +272,10 @@ class FileList(CoreModel): | |||
|         super(FileList, self).save(*args, **kwargs) | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + 'system_file_list' | ||||
|         verbose_name = '文件管理' | ||||
|         db_table = table_prefix + "system_file_list" | ||||
|         verbose_name = "文件管理" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-create_datetime',) | ||||
|         ordering = ("-create_datetime",) | ||||
| 
 | ||||
| 
 | ||||
| class Area(CoreModel): | ||||
|  | @ -247,14 +285,22 @@ class Area(CoreModel): | |||
|     pinyin = models.CharField(max_length=255, verbose_name="拼音", help_text="拼音") | ||||
|     initials = models.CharField(max_length=20, verbose_name="首字母", help_text="首字母") | ||||
|     enable = models.BooleanField(default=True, verbose_name="是否启用", help_text="是否启用") | ||||
|     pcode = models.ForeignKey(to='self', verbose_name='父地区编码', to_field="code", on_delete=models.CASCADE, | ||||
|                               db_constraint=False, null=True, blank=True, help_text="父地区编码") | ||||
|     pcode = models.ForeignKey( | ||||
|         to="self", | ||||
|         verbose_name="父地区编码", | ||||
|         to_field="code", | ||||
|         on_delete=models.CASCADE, | ||||
|         db_constraint=False, | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         help_text="父地区编码", | ||||
|     ) | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_area" | ||||
|         verbose_name = '地区表' | ||||
|         verbose_name = "地区表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('code',) | ||||
|         ordering = ("code",) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return f"{self.name}" | ||||
|  | @ -273,14 +319,21 @@ class ApiWhiteList(CoreModel): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "api_white_list" | ||||
|         verbose_name = '接口白名单' | ||||
|         verbose_name = "接口白名单" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-create_datetime',) | ||||
|         ordering = ("-create_datetime",) | ||||
| 
 | ||||
| 
 | ||||
| class SystemConfig(CoreModel): | ||||
|     parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE, | ||||
|                                db_constraint=False, null=True, blank=True, help_text="父级") | ||||
|     parent = models.ForeignKey( | ||||
|         to="self", | ||||
|         verbose_name="父级", | ||||
|         on_delete=models.CASCADE, | ||||
|         db_constraint=False, | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         help_text="父级", | ||||
|     ) | ||||
|     title = models.CharField(max_length=50, verbose_name="标题", help_text="标题") | ||||
|     key = models.CharField(max_length=20, verbose_name="键", help_text="键", db_index=True) | ||||
|     value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True) | ||||
|  | @ -288,35 +341,35 @@ class SystemConfig(CoreModel): | |||
|     status = models.BooleanField(default=True, verbose_name="启用状态", help_text="启用状态") | ||||
|     data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True) | ||||
|     FORM_ITEM_TYPE_LIST = ( | ||||
|         (0, 'text'), | ||||
|         (1, 'datetime'), | ||||
|         (2, 'date'), | ||||
|         (3, 'textarea'), | ||||
|         (4, 'select'), | ||||
|         (5, 'checkbox'), | ||||
|         (6, 'radio'), | ||||
|         (7, 'img'), | ||||
|         (8, 'file'), | ||||
|         (9, 'switch'), | ||||
|         (10, 'number'), | ||||
|         (11, 'array'), | ||||
|         (12, 'imgs'), | ||||
|         (13, 'foreignkey'), | ||||
|         (14, 'manytomany'), | ||||
|         (15, 'time'), | ||||
| 
 | ||||
|         (0, "text"), | ||||
|         (1, "datetime"), | ||||
|         (2, "date"), | ||||
|         (3, "textarea"), | ||||
|         (4, "select"), | ||||
|         (5, "checkbox"), | ||||
|         (6, "radio"), | ||||
|         (7, "img"), | ||||
|         (8, "file"), | ||||
|         (9, "switch"), | ||||
|         (10, "number"), | ||||
|         (11, "array"), | ||||
|         (12, "imgs"), | ||||
|         (13, "foreignkey"), | ||||
|         (14, "manytomany"), | ||||
|         (15, "time"), | ||||
|     ) | ||||
|     form_item_type = models.IntegerField( | ||||
|         choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, blank=True | ||||
|     ) | ||||
|     form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0, | ||||
|                                          blank=True) | ||||
|     rule = models.JSONField(null=True, blank=True, verbose_name="校验规则", help_text="校验规则") | ||||
|     placeholder = models.CharField(max_length=50, null=True, blank=True, verbose_name="提示信息", help_text="提示信息") | ||||
|     setting = models.JSONField(null=True, blank=True, verbose_name="配置", help_text="配置") | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + "system_config" | ||||
|         verbose_name = '系统配置表' | ||||
|         verbose_name = "系统配置表" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('sort',) | ||||
|         ordering = ("sort",) | ||||
|         unique_together = (("key", "parent_id"),) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|  | @ -324,8 +377,8 @@ class SystemConfig(CoreModel): | |||
| 
 | ||||
|     def save(self, force_insert=False, force_update=False, using=None, update_fields=None): | ||||
|         super().save(force_insert, force_update, using, update_fields) | ||||
|         dispatch.refresh_system_config() # 有更新则刷新系统配置 | ||||
|      | ||||
|         dispatch.refresh_system_config()  # 有更新则刷新系统配置 | ||||
| 
 | ||||
|     def delete(self, using=None, keep_parents=False): | ||||
|         res = super().delete(using, keep_parents) | ||||
|         dispatch.refresh_system_config() | ||||
|  | @ -333,9 +386,7 @@ class SystemConfig(CoreModel): | |||
| 
 | ||||
| 
 | ||||
| class LoginLog(CoreModel): | ||||
|     LOGIN_TYPE_CHOICES = ( | ||||
|         (1, '普通登录'), | ||||
|     ) | ||||
|     LOGIN_TYPE_CHOICES = ((1, "普通登录"),) | ||||
|     username = models.CharField(max_length=32, verbose_name="登录用户名", null=True, blank=True, help_text="登录用户名") | ||||
|     ip = models.CharField(max_length=32, verbose_name="登录ip", null=True, blank=True, help_text="登录ip") | ||||
|     agent = models.TextField(verbose_name="agent信息", null=True, blank=True, help_text="agent信息") | ||||
|  | @ -355,7 +406,7 @@ class LoginLog(CoreModel): | |||
|     login_type = models.IntegerField(default=1, choices=LOGIN_TYPE_CHOICES, verbose_name="登录类型", help_text="登录类型") | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = table_prefix + 'system_login_log' | ||||
|         verbose_name = '登录日志' | ||||
|         db_table = table_prefix + "system_login_log" | ||||
|         verbose_name = "登录日志" | ||||
|         verbose_name_plural = verbose_name | ||||
|         ordering = ('-create_datetime',) | ||||
|         ordering = ("-create_datetime",) | ||||
|  |  | |||
|  | @ -21,15 +21,17 @@ def import_to_data(file_url, field_data): | |||
|     # 创建一个空列表,存储Excel的数据 | ||||
|     tables = [] | ||||
|     for i, row in enumerate(range(table.max_row)): | ||||
|         if i == 0: continue | ||||
|         if i == 0: | ||||
|             continue | ||||
|         array = {} | ||||
|         for index, ele in enumerate(field_data.keys()): | ||||
|             cell_value = table.cell(row=row + 1, column=index + 2).value | ||||
|             print(cell_value) | ||||
|             # 由于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 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') | ||||
|                 cell_value = cell_value.strip(" \t\n\r") | ||||
|             array[ele] = cell_value | ||||
|         tables.append(array) | ||||
|     return tables | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ class ImportSerializerMixin: | |||
|     """ | ||||
|     自定义导出模板、导入功能 | ||||
|     """ | ||||
| 
 | ||||
|     # 导入字段 | ||||
|     import_field_dict = {} | ||||
|     # 导入序列化器 | ||||
|  | @ -31,37 +32,42 @@ class ImportSerializerMixin: | |||
|         :param kwargs: | ||||
|         :return: | ||||
|         """ | ||||
|         assert self.import_field_dict, ( | ||||
|                 "'%s' 请配置对应的导出模板字段。" | ||||
|                 % self.__class__.__name__ | ||||
|         ) | ||||
|         assert self.import_field_dict, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__ | ||||
|         # 导出模板 | ||||
|         if request.method == 'GET': | ||||
|         if request.method == "GET": | ||||
|             # 示例数据 | ||||
|             queryset = self.filter_queryset(self.get_queryset()) | ||||
|             # 导出excel 表 | ||||
|             response = HttpResponse(content_type='application/msexcel') | ||||
|             response['Access-Control-Expose-Headers'] = f'Content-Disposition' | ||||
|             response['Content-Disposition'] = f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}' | ||||
|             response = HttpResponse(content_type="application/msexcel") | ||||
|             response["Access-Control-Expose-Headers"] = f"Content-Disposition" | ||||
|             response[ | ||||
|                 "Content-Disposition" | ||||
|             ] = f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}' | ||||
|             wb = Workbook() | ||||
|             ws = wb.active | ||||
|             row = get_column_letter(len(self.import_field_dict) + 1) | ||||
|             column = 10 | ||||
|             ws.append(['序号', *self.import_field_dict.values()]) | ||||
|             ws.append(["序号", *self.import_field_dict.values()]) | ||||
|             tab = Table(displayName="Table1", ref=f"A1:{row}{column}")  # 名称管理器 | ||||
|             style = TableStyleInfo(name='TableStyleLight11', showFirstColumn=True, | ||||
|                                    showLastColumn=True, showRowStripes=True, showColumnStripes=True) | ||||
|             style = TableStyleInfo( | ||||
|                 name="TableStyleLight11", | ||||
|                 showFirstColumn=True, | ||||
|                 showLastColumn=True, | ||||
|                 showRowStripes=True, | ||||
|                 showColumnStripes=True, | ||||
|             ) | ||||
|             tab.tableStyleInfo = style | ||||
|             ws.add_table(tab) | ||||
|             wb.save(response) | ||||
|             return response | ||||
| 
 | ||||
|         updateSupport = request.data.get('updateSupport') | ||||
|         updateSupport = request.data.get("updateSupport") | ||||
|         # 从excel中组织对应的数据结构,然后使用序列化器保存 | ||||
|         data = import_to_data(request.data.get('url'), self.import_field_dict) | ||||
|         data = import_to_data(request.data.get("url"), self.import_field_dict) | ||||
|         queryset = self.filter_queryset(self.get_queryset()) | ||||
|         unique_list = [ele.attname for ele in queryset.model._meta.get_fields() if | ||||
|                        hasattr(ele, 'unique') and ele.unique == True] | ||||
|         unique_list = [ | ||||
|             ele.attname for ele in 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_dict.keys()) & set(unique_list))} | ||||
|  | @ -80,6 +86,7 @@ class ExportSerializerMixin: | |||
|     """ | ||||
|     自定义导出功能 | ||||
|     """ | ||||
| 
 | ||||
|     # 导出字段 | ||||
|     export_field_label = [] | ||||
|     # 导出序列化器 | ||||
|  | @ -93,27 +100,29 @@ class ExportSerializerMixin: | |||
|         :param kwargs: | ||||
|         :return: | ||||
|         """ | ||||
|         assert self.export_field_label, ( | ||||
|                 "'%s' 请配置对应的导出模板字段。" | ||||
|                 % self.__class__.__name__ | ||||
|         ) | ||||
|         assert self.export_field_label, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__ | ||||
|         queryset = self.filter_queryset(self.get_queryset()) | ||||
|         data = self.export_serializer_class(queryset, many=True).data | ||||
|         # 导出excel 表 | ||||
|         response = HttpResponse(content_type='application/msexcel') | ||||
|         response['Access-Control-Expose-Headers'] = f'Content-Disposition' | ||||
|         response['Content-Disposition'] = f'attachment;filename={quote(str(f"导出{get_verbose_name(queryset)}.xlsx"))}' | ||||
|         response = HttpResponse(content_type="application/msexcel") | ||||
|         response["Access-Control-Expose-Headers"] = f"Content-Disposition" | ||||
|         response["Content-Disposition"] = f'attachment;filename={quote(str(f"导出{get_verbose_name(queryset)}.xlsx"))}' | ||||
|         wb = Workbook() | ||||
|         ws = wb.active | ||||
|         row = get_column_letter(len(self.export_field_label) + 1) | ||||
|         column = 1 | ||||
|         ws.append(['序号', *self.export_field_label]) | ||||
|         ws.append(["序号", *self.export_field_label]) | ||||
|         for index, results in enumerate(data): | ||||
|             ws.append([index + 1, *list(results.values())]) | ||||
|             column += 1 | ||||
|         tab = Table(displayName="Table2", ref=f"A1:{row}{column}")  # 名称管理器 | ||||
|         style = TableStyleInfo(name='TableStyleLight11', showFirstColumn=True, | ||||
|                                showLastColumn=True, showRowStripes=True, showColumnStripes=True) | ||||
|         style = TableStyleInfo( | ||||
|             name="TableStyleLight11", | ||||
|             showFirstColumn=True, | ||||
|             showLastColumn=True, | ||||
|             showRowStripes=True, | ||||
|             showColumnStripes=True, | ||||
|         ) | ||||
|         tab.tableStyleInfo = style | ||||
|         ws.add_table(tab) | ||||
|         wb.save(response) | ||||
|  |  | |||
|  | @ -1,13 +1,4 @@ | |||
| /* | ||||
|  * @创建文件时间: 2021-06-01 22:41:21 | ||||
|  * @Auther: 猿小天 | ||||
|  * @最后修改人: 猿小天 | ||||
|  * @最后修改时间: 2021-06-06 10:14:14 | ||||
|  * 联系Qq:1638245306 | ||||
|  * @文件介绍: 用户接口 | ||||
|  */ | ||||
| import { request } from '@/api/service' | ||||
| 
 | ||||
| import { request, downloadFile } from '@/api/service' | ||||
| export const urlPrefix = '/api/system/user/' | ||||
| 
 | ||||
| export function GetList (query) { | ||||
|  | @ -55,3 +46,15 @@ export function ResetPwd (obj) { | |||
|     data: obj | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * 导出 | ||||
|  * @param params | ||||
|  */ | ||||
| export function exportData (params) { | ||||
|   return downloadFile({ | ||||
|     url: urlPrefix + 'export/', | ||||
|     params: params, | ||||
|     method: 'post' | ||||
|   }) | ||||
| } | ||||
|  |  | |||
|  | @ -21,6 +21,18 @@ | |||
|           > | ||||
|             <i class="el-icon-plus" /> 新增 | ||||
|           </el-button> | ||||
|           <el-button | ||||
|             size="small" | ||||
|             type="danger" | ||||
|             @click="onExport" | ||||
|             v-permission="'Export'" | ||||
|             ><i class="el-icon-download" /> 导出 | ||||
|           </el-button> | ||||
|           <importExcel | ||||
|             importApi="api/system/user/import/" | ||||
|             v-permission="'Import'" | ||||
|             >导入 | ||||
|           </importExcel> | ||||
|         </el-button-group> | ||||
|         <crud-toolbar | ||||
|           :search.sync="crud.searchOptions.show" | ||||
|  | @ -132,6 +144,15 @@ export default { | |||
|     delRequest (row) { | ||||
|       return api.DelObj(row.id) | ||||
|     }, | ||||
|     onExport () { | ||||
|       this.$confirm('是否确认导出所有数据项?', '警告', { | ||||
|         confirmButtonText: '确定', | ||||
|         cancelButtonText: '取消', | ||||
|         type: 'warning' | ||||
|       }).then(function () { | ||||
|         return api.exportData() | ||||
|       }) | ||||
|     }, | ||||
|     // 重置密码弹框 | ||||
|     resetPassword ({ row }) { | ||||
|       this.dialogFormVisible = true | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Angelo
						Angelo