diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py
index 396296f..6dec1b1 100644
--- a/backend/dvadmin/system/models.py
+++ b/backend/dvadmin/system/models.py
@@ -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",)
diff --git a/backend/dvadmin/utils/import_export.py b/backend/dvadmin/utils/import_export.py
index 2f3db9c..5a01968 100644
--- a/backend/dvadmin/utils/import_export.py
+++ b/backend/dvadmin/utils/import_export.py
@@ -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
diff --git a/backend/dvadmin/utils/import_export_mixin.py b/backend/dvadmin/utils/import_export_mixin.py
index ee8cfdb..5a5c9f2 100644
--- a/backend/dvadmin/utils/import_export_mixin.py
+++ b/backend/dvadmin/utils/import_export_mixin.py
@@ -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)
diff --git a/web/src/views/system/user/api.js b/web/src/views/system/user/api.js
index d8f7d18..5743af2 100644
--- a/web/src/views/system/user/api.js
+++ b/web/src/views/system/user/api.js
@@ -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'
+ })
+}
diff --git a/web/src/views/system/user/index.vue b/web/src/views/system/user/index.vue
index 087e2bf..6be1535 100644
--- a/web/src/views/system/user/index.vue
+++ b/web/src/views/system/user/index.vue
@@ -21,6 +21,18 @@
>
新增
+ 导出
+
+ 导入
+