|
@@ -86,93 +86,25 @@
|
|
|
<a-modal
|
|
|
v-model:open="exportModalVisible"
|
|
|
title="导出WAF日志"
|
|
|
- :width="800"
|
|
|
+ :width="900"
|
|
|
@ok="handleExport"
|
|
|
@cancel="handleExportCancel"
|
|
|
:confirm-loading="exportLoading"
|
|
|
+ class="export-modal"
|
|
|
>
|
|
|
- <a-form :model="exportForm" layout="vertical">
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="ID">
|
|
|
- <a-input v-model:value="exportForm.id" placeholder="请输入ID" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="用户ID">
|
|
|
- <a-input v-model:value="exportForm.uid" placeholder="请输入用户ID" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="名称">
|
|
|
- <a-input v-model:value="exportForm.name" placeholder="请输入名称" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="请求IP">
|
|
|
- <a-input v-model:value="exportForm.requestIp" placeholder="请输入请求IP" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="规则ID">
|
|
|
- <a-input v-model:value="exportForm.ruleId" placeholder="请输入规则ID" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="User Agent">
|
|
|
- <a-input v-model:value="exportForm.userAgent" placeholder="请输入User Agent" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="24">
|
|
|
- <a-form-item label="实例ID列表">
|
|
|
- <a-select
|
|
|
- v-model:value="exportForm.hostIds"
|
|
|
- mode="tags"
|
|
|
- placeholder="请输入实例ID,支持多个"
|
|
|
- :token-separators="[',']"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="API路径">
|
|
|
- <a-input v-model:value="exportForm.api" placeholder="请输入API路径" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="API类型">
|
|
|
- <a-select v-model:value="exportForm.apiTypes" mode="multiple" placeholder="请选择API类型">
|
|
|
- <a-select-option value="get">get</a-select-option>
|
|
|
- <a-select-option value="add">add</a-select-option>
|
|
|
- <a-select-option value="delete">delete</a-select-option>
|
|
|
- <a-select-option value="edit">edit</a-select-option>
|
|
|
- </a-select>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="24">
|
|
|
- <a-form-item label="API名称">
|
|
|
- <a-checkbox-group v-model:value="exportForm.apiNames" :options="apiNameOptions" />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
-
|
|
|
- <a-row :gutter="16">
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="开始时间">
|
|
|
+ <div class="export-form-container">
|
|
|
+ <!-- 时间范围选择区域 -->
|
|
|
+ <div class="time-range-section">
|
|
|
+ <h4 class="section-title">时间范围</h4>
|
|
|
+ <div class="time-shortcuts">
|
|
|
+ <a-button size="small" @click="setTimeRange('today')">今天</a-button>
|
|
|
+ <a-button size="small" @click="setTimeRange('yesterday')">昨天</a-button>
|
|
|
+ <a-button size="small" @click="setTimeRange('last7days')">最近7天</a-button>
|
|
|
+ <a-button size="small" @click="setTimeRange('last30days')">最近30天</a-button>
|
|
|
+ <a-button size="small" type="text" @click="clearTimeRange">清空</a-button>
|
|
|
+ </div>
|
|
|
+ <a-row :gutter="16" style="margin-top: 12px;">
|
|
|
+ <a-col :span="12">
|
|
|
<a-date-picker
|
|
|
v-model:value="exportForm.startTime"
|
|
|
show-time
|
|
@@ -180,10 +112,8 @@
|
|
|
placeholder="请选择开始时间"
|
|
|
style="width: 100%"
|
|
|
/>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- <a-col :span="12">
|
|
|
- <a-form-item label="结束时间">
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="12">
|
|
|
<a-date-picker
|
|
|
v-model:value="exportForm.endTime"
|
|
|
show-time
|
|
@@ -191,10 +121,110 @@
|
|
|
placeholder="请选择结束时间"
|
|
|
style="width: 100%"
|
|
|
/>
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
- </a-form>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- API名称选择区域 -->
|
|
|
+ <div class="api-names-section">
|
|
|
+ <div class="api-names-header">
|
|
|
+ <h4 class="section-title">API名称选择</h4>
|
|
|
+ <div class="api-names-actions">
|
|
|
+ <span class="selected-count">已选择: {{ exportForm.apiNames.length }} 个</span>
|
|
|
+ <a-button size="small" type="link" @click="selectAllApiNames">全选</a-button>
|
|
|
+ <a-button size="small" type="link" @click="clearAllApiNames">清空</a-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="api-names-grid">
|
|
|
+ <a-checkbox-group v-model:value="exportForm.apiNames" class="custom-checkbox-group">
|
|
|
+ <div class="checkbox-grid">
|
|
|
+ <a-checkbox
|
|
|
+ v-for="option in apiNameOptions"
|
|
|
+ :key="option.value"
|
|
|
+ :value="option.value"
|
|
|
+ class="checkbox-item"
|
|
|
+ >
|
|
|
+ {{ option.label }}
|
|
|
+ </a-checkbox>
|
|
|
+ </div>
|
|
|
+ </a-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 高级筛选条件 -->
|
|
|
+ <a-collapse v-model:activeKey="advancedFilterKey" ghost>
|
|
|
+ <a-collapse-panel key="advanced" header="高级筛选条件">
|
|
|
+ <a-form :model="exportForm" layout="vertical">
|
|
|
+ <a-row :gutter="16">
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="ID">
|
|
|
+ <a-input v-model:value="exportForm.id" placeholder="请输入ID" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="用户ID">
|
|
|
+ <a-input v-model:value="exportForm.uid" placeholder="请输入用户ID" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="名称">
|
|
|
+ <a-input v-model:value="exportForm.name" placeholder="请输入名称" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+
|
|
|
+ <a-row :gutter="16">
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="请求IP">
|
|
|
+ <a-input v-model:value="exportForm.requestIp" placeholder="请输入请求IP" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="规则ID">
|
|
|
+ <a-input v-model:value="exportForm.ruleId" placeholder="请输入规则ID" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="8">
|
|
|
+ <a-form-item label="API路径">
|
|
|
+ <a-input v-model:value="exportForm.api" placeholder="请输入API路径" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+
|
|
|
+ <a-row :gutter="16">
|
|
|
+ <a-col :span="12">
|
|
|
+ <a-form-item label="实例ID列表">
|
|
|
+ <a-select
|
|
|
+ v-model:value="exportForm.hostIds"
|
|
|
+ mode="tags"
|
|
|
+ placeholder="请输入实例ID,支持多个"
|
|
|
+ :token-separators="[',']"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="12">
|
|
|
+ <a-form-item label="API类型">
|
|
|
+ <a-select v-model:value="exportForm.apiTypes" mode="multiple" placeholder="请选择API类型">
|
|
|
+ <a-select-option value="get">get</a-select-option>
|
|
|
+ <a-select-option value="add">add</a-select-option>
|
|
|
+ <a-select-option value="delete">delete</a-select-option>
|
|
|
+ <a-select-option value="edit">edit</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+
|
|
|
+ <a-row :gutter="16">
|
|
|
+ <a-col :span="24">
|
|
|
+ <a-form-item label="User Agent">
|
|
|
+ <a-input v-model:value="exportForm.userAgent" placeholder="请输入User Agent" />
|
|
|
+ </a-form-item>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </a-form>
|
|
|
+ </a-collapse-panel>
|
|
|
+ </a-collapse>
|
|
|
+ </div>
|
|
|
</a-modal>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -322,6 +352,7 @@ const detailModalRef = ref(null);
|
|
|
const exportModalVisible = ref(false);
|
|
|
const exportLoading = ref(false);
|
|
|
const apiNameOptions = ref([]);
|
|
|
+const advancedFilterKey = ref([]);
|
|
|
const exportForm = ref({
|
|
|
id: '',
|
|
|
uid: '',
|
|
@@ -337,6 +368,13 @@ const exportForm = ref({
|
|
|
endTime: null
|
|
|
});
|
|
|
|
|
|
+// 判断是否为TCP、UDP、Web相关的API
|
|
|
+const isTcpUdpWebRelated = (apiName) => {
|
|
|
+ const keywords = ['tcp', 'udp', 'web', '游戏盾', '转发', '网关', '限流', '防护', '规则', '策略'];
|
|
|
+ const lowerApiName = apiName.toLowerCase();
|
|
|
+ return keywords.some(keyword => lowerApiName.includes(keyword.toLowerCase()));
|
|
|
+};
|
|
|
+
|
|
|
const goToInfo = (id) => {
|
|
|
// 打开模态框而不是跳转页面
|
|
|
detailModalRef.value?.open(id);
|
|
@@ -348,10 +386,10 @@ const showExportModal = async () => {
|
|
|
// 获取API描述映射
|
|
|
const response = await getApiDescriptions();
|
|
|
if (response && response.code === 0 && response.data) {
|
|
|
- // 将API描述映射转换为checkbox选项格式
|
|
|
+ // 将API描述映射转换为checkbox选项格式,只显示中文名称
|
|
|
apiNameOptions.value = Object.entries(response.data).map(([key, value]) => ({
|
|
|
- label: `${value} (${key})`,
|
|
|
- value: key
|
|
|
+ label: value, // 只显示中文名称
|
|
|
+ value: value // 传给后端的值也是中文名称
|
|
|
}));
|
|
|
}
|
|
|
|
|
@@ -371,6 +409,17 @@ const showExportModal = async () => {
|
|
|
endTime: null
|
|
|
};
|
|
|
|
|
|
+ // 默认选中TCP、UDP、Web相关的API
|
|
|
+ if (apiNameOptions.value.length > 0) {
|
|
|
+ const defaultSelected = apiNameOptions.value
|
|
|
+ .filter(option => isTcpUdpWebRelated(option.label))
|
|
|
+ .map(option => option.value);
|
|
|
+ exportForm.value.apiNames = defaultSelected;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置高级筛选折叠状态
|
|
|
+ advancedFilterKey.value = [];
|
|
|
+
|
|
|
exportModalVisible.value = true;
|
|
|
} catch (error) {
|
|
|
console.error('获取API描述失败:', error);
|
|
@@ -378,26 +427,77 @@ const showExportModal = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 时间范围快捷选择
|
|
|
+const setTimeRange = (range) => {
|
|
|
+ const now = dayjs();
|
|
|
+
|
|
|
+ switch (range) {
|
|
|
+ case 'today':
|
|
|
+ exportForm.value.startTime = now.startOf('day');
|
|
|
+ exportForm.value.endTime = now.endOf('day');
|
|
|
+ break;
|
|
|
+ case 'yesterday':
|
|
|
+ const yesterday = now.subtract(1, 'day');
|
|
|
+ exportForm.value.startTime = yesterday.startOf('day');
|
|
|
+ exportForm.value.endTime = yesterday.endOf('day');
|
|
|
+ break;
|
|
|
+ case 'last7days':
|
|
|
+ exportForm.value.startTime = now.subtract(7, 'day').startOf('day');
|
|
|
+ exportForm.value.endTime = now.endOf('day');
|
|
|
+ break;
|
|
|
+ case 'last30days':
|
|
|
+ exportForm.value.startTime = now.subtract(30, 'day').startOf('day');
|
|
|
+ exportForm.value.endTime = now.endOf('day');
|
|
|
+ break;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 清空时间范围
|
|
|
+const clearTimeRange = () => {
|
|
|
+ exportForm.value.startTime = null;
|
|
|
+ exportForm.value.endTime = null;
|
|
|
+};
|
|
|
+
|
|
|
+// 全选API名称
|
|
|
+const selectAllApiNames = () => {
|
|
|
+ exportForm.value.apiNames = apiNameOptions.value.map(option => option.value);
|
|
|
+};
|
|
|
+
|
|
|
+// 清空API名称选择
|
|
|
+const clearAllApiNames = () => {
|
|
|
+ exportForm.value.apiNames = [];
|
|
|
+};
|
|
|
+
|
|
|
// 处理导出
|
|
|
const handleExport = async () => {
|
|
|
try {
|
|
|
exportLoading.value = true;
|
|
|
|
|
|
- // 构造导出参数
|
|
|
- const params = {
|
|
|
- id: exportForm.value.id ? parseInt(exportForm.value.id) : 0,
|
|
|
- uid: exportForm.value.uid ? parseInt(exportForm.value.uid) : 0,
|
|
|
- name: exportForm.value.name || '',
|
|
|
- requestIp: exportForm.value.requestIp || '',
|
|
|
- ruleId: exportForm.value.ruleId ? parseInt(exportForm.value.ruleId) : 0,
|
|
|
- hostIds: exportForm.value.hostIds.map(id => parseInt(id)).filter(id => !isNaN(id)),
|
|
|
- userAgent: exportForm.value.userAgent || '',
|
|
|
- api: exportForm.value.api || '',
|
|
|
- apiNames: exportForm.value.apiNames || [],
|
|
|
- apiTypes: exportForm.value.apiTypes || [],
|
|
|
- startTime: exportForm.value.startTime ? dayjs(exportForm.value.startTime).format('YYYY-MM-DD HH:mm:ss') : '',
|
|
|
- endTime: exportForm.value.endTime ? dayjs(exportForm.value.endTime).format('YYYY-MM-DD HH:mm:ss') : ''
|
|
|
- };
|
|
|
+ // 构造导出参数,只传递有值的参数
|
|
|
+ const params = {};
|
|
|
+
|
|
|
+ if (exportForm.value.id) params.id = parseInt(exportForm.value.id);
|
|
|
+ if (exportForm.value.uid) params.uid = parseInt(exportForm.value.uid);
|
|
|
+ if (exportForm.value.name) params.name = exportForm.value.name;
|
|
|
+ if (exportForm.value.requestIp) params.requestIp = exportForm.value.requestIp;
|
|
|
+ if (exportForm.value.ruleId) params.ruleId = parseInt(exportForm.value.ruleId);
|
|
|
+ if (exportForm.value.hostIds && exportForm.value.hostIds.length > 0) {
|
|
|
+ params.hostIds = exportForm.value.hostIds.map(id => parseInt(id)).filter(id => !isNaN(id));
|
|
|
+ }
|
|
|
+ if (exportForm.value.userAgent) params.userAgent = exportForm.value.userAgent;
|
|
|
+ if (exportForm.value.api) params.api = exportForm.value.api;
|
|
|
+ if (exportForm.value.apiNames && exportForm.value.apiNames.length > 0) {
|
|
|
+ params.apiNames = exportForm.value.apiNames;
|
|
|
+ }
|
|
|
+ if (exportForm.value.apiTypes && exportForm.value.apiTypes.length > 0) {
|
|
|
+ params.apiTypes = exportForm.value.apiTypes;
|
|
|
+ }
|
|
|
+ if (exportForm.value.startTime) {
|
|
|
+ params.startTime = dayjs(exportForm.value.startTime).format('YYYY-MM-DD HH:mm:ss');
|
|
|
+ }
|
|
|
+ if (exportForm.value.endTime) {
|
|
|
+ params.endTime = dayjs(exportForm.value.endTime).format('YYYY-MM-DD HH:mm:ss');
|
|
|
+ }
|
|
|
|
|
|
console.log('导出参数:', params);
|
|
|
|
|
@@ -471,4 +571,179 @@ onMounted(() => {
|
|
|
:deep(.ant-table-body::-webkit-scrollbar-thumb:hover) {
|
|
|
background: #a8a8a8;
|
|
|
}
|
|
|
+
|
|
|
+/* 导出弹窗样式 */
|
|
|
+.export-form-container {
|
|
|
+ max-height: 70vh;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.export-form-container::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.export-form-container::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.export-form-container::-webkit-scrollbar-thumb {
|
|
|
+ background: #c1c1c1;
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.export-form-container::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: #a8a8a8;
|
|
|
+}
|
|
|
+
|
|
|
+.section-title {
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #262626;
|
|
|
+}
|
|
|
+
|
|
|
+/* 时间范围选择区域 */
|
|
|
+.time-range-section {
|
|
|
+ background: #fafafa;
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 16px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.time-shortcuts {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.time-shortcuts .ant-btn {
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.time-shortcuts .ant-btn:hover {
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+/* API名称选择区域 */
|
|
|
+.api-names-section {
|
|
|
+ background: #fafafa;
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 16px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-actions {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-count {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-grid {
|
|
|
+ max-height: 200px;
|
|
|
+ overflow-y: auto;
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+ border-radius: 6px;
|
|
|
+ background: white;
|
|
|
+ padding: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-grid::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-grid::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-grid::-webkit-scrollbar-thumb {
|
|
|
+ background: #c1c1c1;
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
+
|
|
|
+.api-names-grid::-webkit-scrollbar-thumb:hover {
|
|
|
+ background: #a8a8a8;
|
|
|
+}
|
|
|
+
|
|
|
+.custom-checkbox-group {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
+ gap: 8px 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 4px 0;
|
|
|
+ transition: background-color 0.2s ease;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding-left: 8px;
|
|
|
+ margin-left: 0 !important;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-item:hover {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+}
|
|
|
+
|
|
|
+/* 高级筛选折叠面板样式 */
|
|
|
+:deep(.ant-collapse-ghost .ant-collapse-item) {
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: #fafafa;
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.ant-collapse-ghost .ant-collapse-header) {
|
|
|
+ padding: 12px 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #262626;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.ant-collapse-ghost .ant-collapse-content) {
|
|
|
+ background: white;
|
|
|
+ border-radius: 0 0 8px 8px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.ant-collapse-ghost .ant-collapse-content-box) {
|
|
|
+ padding: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 导出弹窗整体样式 */
|
|
|
+:deep(.export-modal .ant-modal-body) {
|
|
|
+ padding: 20px 24px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.export-modal .ant-modal-header) {
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
+ padding: 16px 24px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.export-modal .ant-modal-title) {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
</style>
|