导出功能 完成

pull/1/head
李强 2021-02-28 14:49:09 +08:00
parent 17559ed11b
commit f0961c07a5
19 changed files with 323 additions and 55 deletions

View File

@ -39,7 +39,6 @@ class MenuCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Menu
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
class MenuTreeSerializer(serializers.ModelSerializer):
@ -80,7 +79,6 @@ class DeptCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Dept
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
class DeptTreeSerializer(serializers.ModelSerializer):
@ -109,6 +107,16 @@ class PostSerializer(CustomModelSerializer):
exclude = ('description', 'creator', 'modifier')
class ExportPostSerializer(CustomModelSerializer):
"""
导出 岗位管理 简单序列化器
"""
class Meta:
model = Post
fields = ('id', 'postName', 'postCode', 'postSort', 'status', 'creator', 'modifier', 'remark')
class PostSimpleSerializer(CustomModelSerializer):
"""
岗位管理 极简单序列化器
@ -130,7 +138,6 @@ class PostCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Post
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
# ================================================= #
@ -147,6 +154,21 @@ class RoleSerializer(CustomModelSerializer):
exclude = ('description', 'creator', 'modifier')
class ExportRoleSerializer(CustomModelSerializer):
"""
导出 角色管理 简单序列化器
"""
dataScope = serializers.SerializerMethodField()
def get_dataScope(self, obj):
dataScope = obj.get_dataScope_display()
return dataScope
class Meta:
model = Role
fields = ('id', 'roleName', 'roleKey', 'roleSort', 'dataScope', 'status', 'creator', 'modifier', 'remark')
class RoleSimpleSerializer(CustomModelSerializer):
"""
角色管理 极简单序列化器
@ -176,7 +198,6 @@ class RoleCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Role
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
# ================================================= #
@ -203,6 +224,20 @@ class UserProfileSerializer(CustomModelSerializer):
exclude = ('password', 'secret', 'user_permissions', 'groups', 'is_superuser', 'date_joined')
class ExportUserProfileSerializer(CustomModelSerializer):
"""
用户导出 序列化器
"""
last_login = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False, read_only=True)
dept__deptName = serializers.CharField(source='dept.deptName', default='')
dept__owner = serializers.CharField(source='dept.owner', default='')
class Meta:
model = UserProfile
fields = ('id', 'username', 'name', 'email', 'mobile', 'gender', 'is_active', 'last_login', 'dept__deptName',
'dept__owner')
class UserProfileCreateUpdateSerializer(CustomModelSerializer):
"""
用户管理 创建/更新时的列化器

View File

@ -30,6 +30,12 @@ urlpatterns = [
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/export/', UserProfileModelViewSet.as_view({'get': 'export',})),
# 导出角色
re_path('role/export/', RoleModelViewSet.as_view({'get': 'export',})),
# 导出岗位
re_path('post/export/', PostModelViewSet.as_view({'get': 'export',})),
]
urlpatterns += router.urls

View File

@ -8,7 +8,8 @@ from apps.permission.models import Role, Menu, Dept, Post, UserProfile
from apps.permission.serializers import UserProfileSerializer, MenuSerializer, RoleSerializer, \
MenuCreateUpdateSerializer, DeptSerializer, DeptCreateUpdateSerializer, PostSerializer, PostCreateUpdateSerializer, \
RoleCreateUpdateSerializer, DeptTreeSerializer, MenuTreeSerializer, UserProfileCreateUpdateSerializer, \
PostSimpleSerializer, RoleSimpleSerializer
PostSimpleSerializer, RoleSimpleSerializer, ExportUserProfileSerializer, ExportRoleSerializer, ExportPostSerializer
from utils.export_excel import export_excel_save_model
from utils.response import SuccessResponse, ErrorResponse
@ -44,7 +45,8 @@ class GetRouters(APIView):
def get(self, request, format=None):
# data = GetUserInfoSerializer(request.user).data
menus = Menu.objects.filter(role__userprofile=request.user).exclude(menuType="2").values('id','name', 'web_path',
menus = Menu.objects.filter(role__userprofile=request.user).exclude(menuType="2").values('id', 'name',
'web_path',
'visible', 'status',
'isFrame',
'component_path',
@ -56,7 +58,7 @@ class GetRouters(APIView):
for ele in menus:
data.append({
'id': ele.get('id'),
'name': ''.join([i.capitalize() for i in ele.get('web_path','').split('/')]),
'name': ''.join([i.capitalize() for i in ele.get('web_path', '').split('/')]),
'path': ele.get('web_path'),
'hidden': True if ele.get('visible') != '1' else False,
'redirect': ele.get('web_path') if ele.get('isFrame') == '1' else 'noRedirect',
@ -194,6 +196,18 @@ class PostModelViewSet(CustomModelViewSet):
search_fields = ('postName',)
ordering = ['postSort', 'create_datetime'] # 默认排序
def export(self, request: Request, *args, **kwargs):
"""
导出岗位
:param request:
:param args:
:param kwargs:
:return:
"""
field_data = ['岗位序号', '岗位编码', '岗位名称', '岗位排序', '状态', '创建者', '修改者', '备注']
data = ExportPostSerializer(Post.objects.all(), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, '导出岗位数据.xls'))
class RoleModelViewSet(CustomModelViewSet):
"""
@ -210,6 +224,18 @@ class RoleModelViewSet(CustomModelViewSet):
search_fields = ('roleName',)
ordering = 'create_datetime' # 默认排序
def export(self, request: Request, *args, **kwargs):
"""
导出角色
:param request:
:param args:
:param kwargs:
:return:
"""
field_data = ['角色序号', '角色名称', '角色权限', '角色排序', '数据范围', '角色状态', '创建者', '修改者', '备注']
data = ExportRoleSerializer(Role.objects.all(), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, '导出角色数据.xls'))
class UserProfileModelViewSet(CustomModelViewSet):
"""
@ -304,17 +330,16 @@ class UserProfileModelViewSet(CustomModelViewSet):
:return:
"""
instance = self.queryset.get(id=request.user.id)
instance.name = request.data.get('name',None)
instance.mobile = request.data.get('mobile',None)
instance.email = request.data.get('email',None)
instance.gender = request.data.get('gender',None)
instance.name = request.data.get('name', None)
instance.mobile = request.data.get('mobile', None)
instance.email = request.data.get('email', None)
instance.gender = request.data.get('gender', None)
instance.save()
serializer = self.get_serializer(instance)
if hasattr(self, 'handle_logging'):
self.handle_logging(request, instance=instance, *args, **kwargs)
return SuccessResponse(serializer.data)
def update_pwd(self, request: Request, *args, **kwargs):
"""
个人修改密码
@ -324,8 +349,8 @@ class UserProfileModelViewSet(CustomModelViewSet):
:return:
"""
instance = self.queryset.get(id=request.user.id)
instance.mobile = request.data.get('newPassword',None)
if not authenticate(username=request.user.username, password=request.data.get('oldPassword',None)):
instance.mobile = request.data.get('newPassword', None)
if not authenticate(username=request.user.username, password=request.data.get('oldPassword', None)):
return ErrorResponse(msg='旧密码不正确!')
instance.set_password(request.data.get('newPassword'))
instance.save()
@ -333,3 +358,15 @@ class UserProfileModelViewSet(CustomModelViewSet):
if hasattr(self, 'handle_logging'):
self.handle_logging(request, instance=instance, *args, **kwargs)
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

@ -1,7 +1,7 @@
import os
import uuid
from django.db.models import CharField, FileField
from django.db.models import CharField, FileField,BooleanField
from django.utils import timezone
from apps.op_drf.models import CoreModel
@ -17,6 +17,7 @@ class SaveFile(CoreModel):
size = CharField(max_length=64, verbose_name="文件大小", null=True, blank=True)
address = CharField(max_length=16, verbose_name="存储位置", null=True, blank=True) # 本地、阿里云、腾讯云..
oss_url = CharField(max_length=200, verbose_name="OSS地址", null=True, blank=True)
status = BooleanField(default=True, verbose_name="文件是否存在")
file = FileField(verbose_name="文件URL", upload_to=files_path, )
class Meta:

View File

@ -18,6 +18,16 @@ class DictDataSerializer(CustomModelSerializer):
exclude = ('description', 'creator', 'modifier')
class ExportDictDataSerializer(CustomModelSerializer):
"""
导出 字典管理 简单序列化器
"""
class Meta:
model = DictData
fields = ('id', 'dictName', 'dictType', 'status', 'creator', 'modifier', 'remark',)
class DictDataCreateUpdateSerializer(CustomModelSerializer):
"""
字典管理 创建/更新时的列化器
@ -26,7 +36,6 @@ class DictDataCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = DictData
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
# ================================================= #
@ -44,6 +53,16 @@ class DictDetailsSerializer(CustomModelSerializer):
exclude = ('description', 'creator', 'modifier')
class ExportDictDetailsSerializer(CustomModelSerializer):
"""
导出 字典详情 简单序列化器
"""
class Meta:
model = DictDetails
fields = ('id', 'dictLabel', 'dictValue', 'is_default', 'status', 'sort', 'creator', 'modifier', 'remark',)
class DictDetailsListSerializer(CustomModelSerializer):
"""
字典详情List 简单序列化器
@ -62,7 +81,6 @@ class DictDetailsCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = DictDetails
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
# ================================================= #
@ -71,24 +89,33 @@ class DictDetailsCreateUpdateSerializer(CustomModelSerializer):
class ConfigSettingsSerializer(CustomModelSerializer):
"""
字典详情 简单序列化器
参数设置 简单序列化器
"""
dictType = serializers.CharField(source='dict_data.dictType', default='', read_only=True)
class Meta:
model = ConfigSettings
exclude = ('description', 'creator', 'modifier')
class ExportConfigSettingsSerializer(CustomModelSerializer):
"""
导出 参数设置 简单序列化器
"""
class Meta:
model = ConfigSettings
fields = (
'id', 'configName', 'configKey', 'configValue', 'configType', 'status', 'creator', 'modifier', 'remark')
class ConfigSettingsCreateUpdateSerializer(CustomModelSerializer):
"""
字典详情 创建/更新时的列化器
参数设置 创建/更新时的列化器
"""
class Meta:
model = ConfigSettings
exclude = ('description', 'creator', 'modifier')
read_only_fields = ('update_datetime', 'create_datetime', 'creator', 'modifier')
# ================================================= #

View File

@ -12,7 +12,11 @@ router.register(r'savefile', SaveFileModelViewSet)
urlpatterns = [
re_path('dict/get/type/(?P<pk>.*)/', DictDetailsModelViewSet.as_view({'get': 'dict_details_list'})),
re_path('config/configKey/(?P<pk>.*)/', ConfigSettingsModelViewSet.as_view({'get': 'get_config_key'})),
# 下载文件
re_path('savefile/(?P<pk>.*)/', SaveFileModelViewSet.as_view({'get': 'download_file'})),
# 参数管理导出
re_path('config/export/', ConfigSettingsModelViewSet.as_view({'get': 'export'})),
# 导出字典管理数据
re_path('dict/type/export/', DictDataModelViewSet.as_view({'get': 'export'})),
# 导出字典详情数据
re_path('dict/data/export/', DictDetailsModelViewSet.as_view({'get': 'export'})),
]
urlpatterns += router.urls

View File

@ -1,7 +1,3 @@
import os
from django.conf import settings
from django.http import HttpResponse
from rest_framework.request import Request
from apps.op_drf.viewsets import CustomModelViewSet
@ -9,7 +5,9 @@ from apps.system.filters import DictDetailsFilter, DictDataFilter, ConfigSetting
from apps.system.models import DictData, DictDetails, ConfigSettings, SaveFile
from apps.system.serializers import DictDataSerializer, DictDataCreateUpdateSerializer, DictDetailsSerializer, \
DictDetailsCreateUpdateSerializer, DictDetailsListSerializer, ConfigSettingsSerializer, \
ConfigSettingsCreateUpdateSerializer, SaveFileSerializer, SaveFileCreateUpdateSerializer
ConfigSettingsCreateUpdateSerializer, SaveFileSerializer, SaveFileCreateUpdateSerializer, \
ExportConfigSettingsSerializer, ExportDictDataSerializer, ExportDictDetailsSerializer
from utils.export_excel import export_excel_save_model
from utils.response import SuccessResponse
@ -30,6 +28,18 @@ class DictDataModelViewSet(CustomModelViewSet):
search_fields = ('dictName',)
ordering = 'id' # 默认排序
def export(self, request: Request, *args, **kwargs):
"""
导出字典管理数据
:param request:
:param args:
:param kwargs:
:return:
"""
field_data = ['字典主键', '字典名称', '字典类型', '字典状态', '创建者', '修改者', '备注']
data = ExportDictDataSerializer(DictData.objects.all(), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, '导出参数管理数据.xls'))
class DictDetailsModelViewSet(CustomModelViewSet):
"""
@ -60,6 +70,19 @@ class DictDetailsModelViewSet(CustomModelViewSet):
serializer = DictDetailsListSerializer(queryset, many=True)
return SuccessResponse(serializer.data)
def export(self, request: Request, *args, **kwargs):
"""
导出字典详情数据
:param request:
:param args:
:param kwargs:
:return:
"""
dictType = request.query_params.get('dictType')
field_data = ['字典详情主键', '字典标签', '字典键值', '是否默认', '字典状态', '字典排序', '创建者', '修改者', '备注']
data = ExportDictDetailsSerializer(DictDetails.objects.filter(dict_data__dictType=dictType), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, f'导出字典[{dictType}]详情数据.xls'))
class ConfigSettingsModelViewSet(CustomModelViewSet):
"""
@ -89,6 +112,18 @@ class ConfigSettingsModelViewSet(CustomModelViewSet):
# self.handle_logging(request, *args, **kwargs)
return SuccessResponse(msg=queryset.configValue if queryset else '')
def export(self, request: Request, *args, **kwargs):
"""
导出参数管理数据
:param request:
:param args:
:param kwargs:
:return:
"""
field_data = ['参数主键', '参数名称', '参数键名', '参数键值', '系统内置', '参数状态', '创建者', '修改者', '备注']
data = ExportConfigSettingsSerializer(ConfigSettings.objects.all(), many=True).data
return SuccessResponse(export_excel_save_model(request, field_data, data, '导出参数管理数据.xls'))
class SaveFileModelViewSet(CustomModelViewSet):
"""
@ -101,19 +136,3 @@ class SaveFileModelViewSet(CustomModelViewSet):
# filter_class = ConfigSettingsFilter
search_fields = ('configName',)
ordering = 'id' # 默认排序
def download_file(self, request: Request, *args, **kwargs):
"""
下载文件
:param request:
:param args:
:param kwargs:
:return:
"""
instance = self.get_object()
file_path = os.path.join(settings.MEDIA_ROOT,str(instance.file))
with open(file_path, "rb") as f:
res = HttpResponse(f)
res["Content-Type"] = instance.type # 注意格式
res["Content-Disposition"] = 'filename="{}"'.format(instance.name)
return res

View File

@ -19,3 +19,4 @@ pytz==2021.1
redis==3.5.3
six==1.15.0
sqlparse==0.4.1
xlwt==1.3.0

View File

@ -0,0 +1,138 @@
# 导出excel数据
import hashlib
import os
import time
import xlwt
from django.conf import settings
from apps.system.models import SaveFile
from apps.system.serializers import SaveFileSerializer
def len_byte(value):
# 获取字符串长度一个中文的长度为2
length = len(value)
utf8_length = len(value.encode('utf-8'))
length = (utf8_length - length) / 2 + length
return int(length)
def export_excel(field_data: list, data: list, FileName: str, file_path: str = settings.MEDIA_ROOT):
"""
Excel导出
:param data: 数据源
:param field_data: 首行数据源
:param file_path: 文件保存路径
:param FileName: 文件保存名字
:return:
"""
wbk = xlwt.Workbook(encoding='utf-8')
sheet = wbk.add_sheet('Sheet1', cell_overwrite_ok=True) # 第二参数用于确认同一个cell单元是否可以重设值。
style = xlwt.XFStyle() # 赋值style为XFStyle(),初始化样式
# 设置居中
wbk.set_colour_RGB(0x23, 0, 60, 139)
xlwt.add_palette_colour("custom_colour_35", 0x23)
tab_al = xlwt.Alignment()
tab_al.horz = 0x02 # 设置水平居中
tab_al.vert = 0x01 # 设置垂直居中
# 设置表头单元格背景颜色
tab_pattern = xlwt.Pattern() # 创建一个模式
tab_pattern.pattern = xlwt.Pattern.SOLID_PATTERN # 设置其模式为实型
tab_pattern.pattern_fore_colour = 55
# 设置单元格内字体样式
tab_fnt = xlwt.Font() # 创建一个文本格式,包括字体、字号和颜色样式特性
tab_fnt.height = 200
default_width = 14
tab_fnt.name = u'楷体' # 设置其字体为微软雅黑
tab_fnt.colour_index = 1 # 设置其字体颜色
# 设置单元格下框线样式
tab_borders = xlwt.Borders()
tab_borders.left = xlwt.Borders.THIN
tab_borders.right = xlwt.Borders.THIN
tab_borders.top = xlwt.Borders.THIN
tab_borders.bottom = xlwt.Borders.THIN
tab_borders.left_colour = 23
tab_borders.right_colour = 23
tab_borders.bottom_colour = 23
tab_borders.top_colour = 23
#### 把数据写入excel中
# 所有表格单元格样式
# 先生成表头
style.alignment = tab_al # 设置居中
style.pattern = tab_pattern # 设置表头单元格背景颜色
style.font = tab_fnt # 设置单元格内字体样式
style.borders = tab_borders
for index, ele in enumerate(field_data):
sheet.write_merge(0, 0, index, index, ele, style) # (列开始, 列结束, 行开始, 行结束, '数据内容')
# 确定栏位宽度
col_width = []
for index,ele in enumerate(data):
for inx,values in enumerate(ele.values()):
if index == 0:
col_width.append(len_byte(str(values)))
else:
if col_width[inx] < len_byte(str(values)):
col_width[inx] = len_byte(str(values))
# 设置栏位宽度栏位宽度小于10时候采用默认宽度
for i in range(len(col_width)):
if col_width[i] > 10:
sheet.col(i).width = 256 * (col_width[i] + 6)
else:
sheet.col(i).width = 256 * (default_width)
row = 1
# 内容背景颜色
left_pattern = xlwt.Pattern() # 创建一个模式
left_pattern.pattern = xlwt.Pattern.SOLID_PATTERN # 设置其模式为实型
left_pattern.pattern_fore_colour = 1
# 设置单元格内字体样式
left_fnt = xlwt.Font() # 创建一个文本格式,包括字体、字号和颜色样式特性
left_fnt.height = 200
left_fnt.name = u'楷体' # 设置其字体为微软雅黑
left_fnt.colour_index = 0 # 设置其字体颜色
left_style = style
left_style.pattern = left_pattern
left_style.font = left_fnt
for results in data:
for index, values in enumerate(results.values()):
sheet.write(row, index, label=values, style=left_style)
row += 1
monthTime = time.strftime('%Y-%m-%d', time.localtime(time.time()))
pathRoot = os.path.join(file_path, 'system', monthTime)
if not os.path.exists(pathRoot):
os.makedirs(pathRoot)
path_name = os.path.join(pathRoot, FileName)
wbk.save(path_name)
return os.path.join('system', monthTime, FileName)
def export_excel_save_model(request,field_data,data,FilName):
"""
导出Excel并保存到 SaveFile 文件管理中
:param request:
:param field_data: 首行数据源
:param data: 数据源
:param FilName: 文件名
:return:
"""
# 根据生成的字典MD5
time_stamp = hashlib.md5(str(field_data).encode('utf8')).hexdigest()
# 存入文件数据库中
FilName = str(time_stamp) + FilName
file_rul = export_excel(field_data=field_data, data=data, FileName=FilName)
savefile, _ = SaveFile.objects.get_or_create(file=file_rul)
if _ == True:
savefile.name = FilName
savefile.type = 'application/vnd.ms-excel'
savefile.size = os.path.getsize(os.path.join(settings.MEDIA_ROOT, file_rul))
savefile.address = '本地存储'
savefile.creator = request.user.username
savefile.modifier = request.user.username
savefile.save()
return SaveFileSerializer(savefile).data

View File

@ -480,7 +480,7 @@ export default {
}).then(function() {
return exportJob(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -291,7 +291,7 @@ export default {
}).then(function() {
return exportJobLog(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -224,7 +224,7 @@ export default {
}).then(function() {
return exportLogininfor(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -312,7 +312,7 @@ export default {
}).then(function() {
return exportOperlog(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -318,7 +318,7 @@ export default {
}).then(function() {
return exportPost(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -603,7 +603,7 @@ export default {
}).then(function() {
return exportRole(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -640,7 +640,7 @@ export default {
}).then(function() {
return exportUser(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
},
/** 导入按钮操作 */
@ -651,7 +651,7 @@ export default {
/** 下载模板操作 */
importTemplate() {
importTemplate().then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
});
},
//

View File

@ -353,7 +353,7 @@ export default {
}).then(function() {
return exportConfig(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
},
/** 清理缓存按钮操作 */

View File

@ -372,7 +372,7 @@
}).then(function() {
return exportData(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
}
}

View File

@ -351,7 +351,7 @@ export default {
}).then(function() {
return exportType(queryParams);
}).then(response => {
this.download(response.msg);
this.download(response.data.file_url,response.data.name);
})
},
/** 清理缓存按钮操作 */