update:优化样式

This commit is contained in:
hrz
2025-11-06 12:27:45 +08:00
parent ea15ed39f5
commit 987a72a3aa
8 changed files with 756 additions and 735 deletions
@@ -208,4 +208,5 @@ public interface ErrorCode {
int RAG_CONFIG_MISSING_PARAMS = 10167; // RAG配置缺少必要参数 int RAG_CONFIG_MISSING_PARAMS = 10167; // RAG配置缺少必要参数
int UPLOAD_FILE_ERROR = 10168; // 上传文件失败 int UPLOAD_FILE_ERROR = 10168; // 上传文件失败
int NO_PERMISSION = 10169; // 没有权限 int NO_PERMISSION = 10169; // 没有权限
int RAG_API_ERROR = 10170; // RAG API接口错误
} }
@@ -1,22 +1,26 @@
package xiaozhi.modules.knowledge.service.impl; package xiaozhi.modules.knowledge.service.impl;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -396,7 +400,7 @@ public class KnowledgeBaseServiceImpl extends BaseServiceImpl<KnowledgeBaseDao,
if (!response.getStatusCode().is2xxSuccessful()) { if (!response.getStatusCode().is2xxSuccessful()) {
log.error("RAGFlow API调用失败,状态码: {}, 响应内容: {}", response.getStatusCode(), response.getBody()); log.error("RAGFlow API调用失败,状态码: {}, 响应内容: {}", response.getStatusCode(), response.getBody());
throw new RenException(ErrorCode.RAG_CONFIG_MISSING_PARAMS); throw new RenException(ErrorCode.RAG_API_ERROR, response.getStatusCode());
} }
// 解析响应体,提取datasetId // 解析响应体,提取datasetId
@@ -3,34 +3,44 @@ package xiaozhi.modules.knowledge.service.impl;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.AbstractResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.core.io.AbstractResource;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.multipart.MultipartFile;
import xiaozhi.common.constant.Constant; import xiaozhi.common.constant.Constant;
import xiaozhi.common.exception.ErrorCode; import xiaozhi.common.exception.ErrorCode;
import xiaozhi.common.exception.RenException; import xiaozhi.common.exception.RenException;
import xiaozhi.common.page.PageData; import xiaozhi.common.page.PageData;
import xiaozhi.modules.knowledge.dto.KnowledgeFilesDTO; import xiaozhi.modules.knowledge.dto.KnowledgeFilesDTO;
import xiaozhi.modules.knowledge.service.KnowledgeFilesService; import xiaozhi.modules.knowledge.service.KnowledgeFilesService;
import xiaozhi.modules.model.service.ModelConfigService;
import xiaozhi.modules.model.dao.ModelConfigDao; import xiaozhi.modules.model.dao.ModelConfigDao;
import xiaozhi.modules.model.entity.ModelConfigEntity; import xiaozhi.modules.model.entity.ModelConfigEntity;
import xiaozhi.modules.model.service.ModelConfigService;
@Service @Service
@AllArgsConstructor @AllArgsConstructor
@@ -1003,7 +1013,7 @@ public class KnowledgeFilesServiceImpl implements KnowledgeFilesService {
} else { } else {
String message = (String) responseMap.get("message"); String message = (String) responseMap.get("message");
log.error("RAGFlow API调用失败,响应码: {}, 消息: {}, 响应内容: {}", code, message, responseBody); log.error("RAGFlow API调用失败,响应码: {}, 消息: {}, 响应内容: {}", code, message, responseBody);
throw new RenException(ErrorCode.RAG_CONFIG_MISSING_PARAMS, "RAGFlow API调用失败: " + message); throw new RenException(ErrorCode.RAG_API_ERROR, response.getStatusCode().toString());
} }
} catch (IOException e) { } catch (IOException e) {
@@ -169,3 +169,11 @@
10160=\u706B\u5C71\u5F15\u64CE\u97F3\u8272ID\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5S_\u5F00\u5934 10160=\u706B\u5C71\u5F15\u64CE\u97F3\u8272ID\u683C\u5F0F\u9519\u8BEF\uFF0C\u5FC5\u987B\u4EE5S_\u5F00\u5934
10161=Mac\u5730\u5740\u5DF2\u5B58\u5728 10161=Mac\u5730\u5740\u5DF2\u5B58\u5728
10162=\u6A21\u578B\u4F9B\u5E94\u5668\u4E0D\u5B58\u5728 10162=\u6A21\u578B\u4F9B\u5E94\u5668\u4E0D\u5B58\u5728
10163=\u77E5\u8BC6\u5E93\u8BB0\u5F55\u4E0D\u5B58\u5728
10164=RAG\u914D\u7F6E\u672A\u627E\u5230
10165=RAG\u914D\u7F6E\u7C7B\u578B\u9519\u8BEF
10166=\u9ED8\u8BA4RAG\u914D\u7F6E\u672A\u627E\u5230
10167=RAG\u914D\u7F6E\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570
10168=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25
10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55
10170=RAG \u63A5\u53E3\u9519\u8BEF\u63A5\u53E3\u9519\u8BEF:{0}
@@ -176,5 +176,4 @@
10167=RAG configuration missing required parameters 10167=RAG configuration missing required parameters
10168=Upload file failed 10168=Upload file failed
10169=No permission to operate this knowledge base 10169=No permission to operate this knowledge base
10170=RAG API interface error: {0}
@@ -176,3 +176,4 @@
10167=RAG\u914D\u7F6E\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570 10167=RAG\u914D\u7F6E\u7F3A\u5C11\u5FC5\u8981\u53C2\u6570
10168=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25 10168=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25
10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55 10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55
10170=RAG API\u63A5\u53E3\u9519\u8BEF:{0}
@@ -175,6 +175,5 @@
10166=\u9810\u8A2DRAG\u914D\u7F6E\u672A\u627E\u5230 10166=\u9810\u8A2DRAG\u914D\u7F6E\u672A\u627E\u5230
10167=RAG\u914D\u7F6E\u7F3A\u5C11\u5FC5\u8981\u53C3\u6578 10167=RAG\u914D\u7F6E\u7F3A\u5C11\u5FC5\u8981\u53C3\u6578
10168=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557 10168=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557
10169=\u60A8\u6CA1\u6709\u6743\u9650\u64CD\u4F5C\u8BE5\u8BB0\u5F55 10169=\u60A8\u6C92\u6709\u6B0A\u9650\u64CD\u4F5C\u8A72\u8A18\u9304
10170=RAG \u63A5\u53E3\u932F\u8AA4\u63A5\u53E3\u9519\u8BEF:{0}
+164 -165
View File
@@ -7,7 +7,7 @@
<el-button class="btn-back" type="text" @click="$router.back()"> <el-button class="btn-back" type="text" @click="$router.back()">
&lt; &lt;
</el-button> </el-button>
<h2 class="knowledge-base-title">文档管理-{{ knowledgeBaseName }}</h2> <h2 class="knowledge-base-title">{{ knowledgeBaseName }}</h2>
</div> </div>
<div class="right-operations"> <div class="right-operations">
<el-input :placeholder="$t('knowledgeFileUpload.searchPlaceholder')" v-model="searchName" class="search-input" <el-input :placeholder="$t('knowledgeFileUpload.searchPlaceholder')" v-model="searchName" class="search-input"
@@ -23,8 +23,7 @@
<div class="table-wrapper"> <div class="table-wrapper">
<el-table ref="fileTable" :data="fileList" class="transparent-table" v-loading="loading" <el-table ref="fileTable" :data="fileList" class="transparent-table" v-loading="loading"
element-loading-text="Loading" element-loading-spinner="el-icon-loading" element-loading-text="Loading" element-loading-spinner="el-icon-loading"
element-loading-background="rgba(255, 255, 255, 0.7)" element-loading-background="rgba(255, 255, 255, 0.7)" :header-cell-class-name="headerCellClassName"
:header-cell-class-name="headerCellClassName"
@selection-change="handleSelectionChange"> @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column> <el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column :label="$t('knowledgeFileUpload.documentName')" prop="name" align="center"> <el-table-column :label="$t('knowledgeFileUpload.documentName')" prop="name" align="center">
@@ -45,8 +44,7 @@
<el-table-column :label="$t('knowledgeFileUpload.operation')" align="center"> <el-table-column :label="$t('knowledgeFileUpload.operation')" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button size="mini" type="text" @click="handleParse(scope.row)" <el-button size="mini" type="text" @click="handleParse(scope.row)"
:disabled="scope.row.status === 1" :disabled="scope.row.status === 1" v-if="!scope.row.sliceCount || scope.row.sliceCount <= 0">
v-if="!scope.row.sliceCount || scope.row.sliceCount <= 0">
{{ $t('knowledgeFileUpload.parse') }} {{ $t('knowledgeFileUpload.parse') }}
</el-button> </el-button>
<el-button size="mini" type="text" @click="handleViewSlices(scope.row)" <el-button size="mini" type="text" @click="handleViewSlices(scope.row)"
@@ -72,10 +70,7 @@
<el-button type="danger" @click="handleBatchDelete" :disabled="selectedFiles.length === 0"> <el-button type="danger" @click="handleBatchDelete" :disabled="selectedFiles.length === 0">
{{ $t('knowledgeFileUpload.batchDelete') }} {{ $t('knowledgeFileUpload.batchDelete') }}
</el-button> </el-button>
<el-button <el-button type="primary" icon="el-icon-search" @click="showRetrievalTestDialog"
type="primary"
icon="el-icon-search"
@click="showRetrievalTestDialog"
style="background-color: #409EFF; border-color: #409EFF;"> style="background-color: #409EFF; border-color: #409EFF;">
{{ $t('knowledgeFileUpload.retrievalTest') }} {{ $t('knowledgeFileUpload.retrievalTest') }}
</el-button> </el-button>
@@ -109,15 +104,8 @@
<!-- 上传文档对话框 --> <!-- 上传文档对话框 -->
<el-dialog :title="$t('knowledgeFileUpload.uploadDocument')" :visible.sync="uploadDialogVisible" width="800px"> <el-dialog :title="$t('knowledgeFileUpload.uploadDocument')" :visible.sync="uploadDialogVisible" width="800px">
<el-upload <el-upload class="document-uploader" drag :action="uploadUrl" :auto-upload="false" :on-change="handleFileChange"
class="document-uploader" :multiple="true" :show-file-list="false" accept=".doc,.docx,.pdf,.txt,.md,.mdx,.csv,.xls,.xlsx,.ppt,.pptx">
drag
:action="uploadUrl"
:auto-upload="false"
:on-change="handleFileChange"
:multiple="true"
:show-file-list="false"
accept=".doc,.docx,.pdf,.txt,.md,.mdx,.csv,.xls,.xlsx,.ppt,.pptx">
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">{{ $t('knowledgeFileUpload.dragOrClick') }}</div> <div class="el-upload__text">{{ $t('knowledgeFileUpload.dragOrClick') }}</div>
<div class="el-upload__tip">{{ $t('knowledgeFileUpload.uploadTip') }}</div> <div class="el-upload__tip">{{ $t('knowledgeFileUpload.uploadTip') }}</div>
@@ -127,21 +115,13 @@
<div class="selected-files-section" v-if="selectedFilesList.length > 0"> <div class="selected-files-section" v-if="selectedFilesList.length > 0">
<h4>{{ $t('knowledgeFileUpload.selectedFiles') }} ({{ selectedFilesList.length }})</h4> <h4>{{ $t('knowledgeFileUpload.selectedFiles') }} ({{ selectedFilesList.length }})</h4>
<div class="selected-files-list"> <div class="selected-files-list">
<div <div v-for="(file, index) in selectedFilesList" :key="index" class="selected-file-item">
v-for="(file, index) in selectedFilesList"
:key="index"
class="selected-file-item"
>
<div class="file-info"> <div class="file-info">
<i class="el-icon-document"></i> <i class="el-icon-document"></i>
<span class="file-name">{{ file.name }}</span> <span class="file-name">{{ file.name }}</span>
<span class="file-size">{{ formatFileSize(file.size) }}</span> <span class="file-size">{{ formatFileSize(file.size) }}</span>
</div> </div>
<el-button <el-button type="text" class="remove-btn" @click="removeSelectedFile(index)">
type="text"
class="remove-btn"
@click="removeSelectedFile(index)"
>
<i class="el-icon-close"></i> <i class="el-icon-close"></i>
</el-button> </el-button>
</div> </div>
@@ -150,29 +130,27 @@
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="uploadDialogVisible = false">{{ $t('knowledgeFileUpload.cancel') }}</el-button> <el-button @click="uploadDialogVisible = false">{{ $t('knowledgeFileUpload.cancel') }}</el-button>
<el-button type="primary" @click="handleBatchUploadSubmit" :loading="uploading" :disabled="selectedFilesList.length === 0"> <el-button type="primary" @click="handleBatchUploadSubmit" :loading="uploading"
{{ $t('knowledgeFileUpload.confirm') }} {{ selectedFilesList.length > 0 ? `(${selectedFilesList.length}${$t('knowledgeFileUpload.itemsPerPage').replace('条/页', '个文件')})` : '' }} :disabled="selectedFilesList.length === 0">
{{ $t('knowledgeFileUpload.confirm') }} {{ selectedFilesList.length > 0 ?
`(${selectedFilesList.length}${$t('knowledgeFileUpload.itemsPerPage').replace('条/页', '个文件')})` : '' }}
</el-button> </el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 切片管理弹窗 --> <!-- 切片管理弹窗 -->
<el-dialog :title="`${$t('knowledgeFileUpload.viewSlices')} - ${currentDocumentName}`" :visible.sync="sliceDialogVisible" width="1200px" class="slice-dialog"> <el-dialog :title="`${$t('knowledgeFileUpload.viewSlices')} - ${currentDocumentName}`"
:visible.sync="sliceDialogVisible" width="1200px" class="slice-dialog">
<div class="slice-management"> <div class="slice-management">
<!-- 切片列表 --> <!-- 切片列表 -->
<div class="slice-list-section"> <div class="slice-list-section">
<div class="slice-header">
<div class="slice-info">
<h3>{{ $t('knowledgeFileUpload.documentName') }}{{ currentDocumentName }}</h3>
</div>
</div>
<!-- 切片内容卡片式布局 --> <!-- 切片内容卡片式布局 -->
<div v-loading="sliceLoading" class="slice-content-container"> <div v-loading="sliceLoading" class="slice-content-container">
<div v-if="sliceList.length > 0" class="slice-cards-container"> <div v-if="sliceList.length > 0" class="slice-cards-container">
<div v-for="(slice, index) in sliceList" :key="index" class="slice-card"> <div v-for="(slice, index) in sliceList" :key="index" class="slice-card">
<div class="slice-header-info"> <div class="slice-header-info">
<p><strong>{{ $t('knowledgeFileUpload.slice') }} {{ (sliceCurrentPage - 1) * slicePageSize + index + 1 }}</strong></p> <p><strong>{{ $t('knowledgeFileUpload.slice') }} {{ (sliceCurrentPage - 1) * slicePageSize + index + 1
}}</strong></p>
</div> </div>
<div class="slice-card-content"> <div class="slice-card-content">
<div class="content-text">{{ slice.content }}</div> <div class="content-text">{{ slice.content }}</div>
@@ -188,28 +166,20 @@
<div class="slice-pagination" style="margin-top: 20px; text-align: right;"> <div class="slice-pagination" style="margin-top: 20px; text-align: right;">
<div class="custom-pagination"> <div class="custom-pagination">
<!-- /页选择器 --> <!-- /页选择器 -->
<el-select <el-select v-model="slicePageSize" @change="handleSliceSizeChange" class="page-size-select"
v-model="slicePageSize" :popper-append-to-body="false">
@change="handleSliceSizeChange"
class="page-size-select"
:popper-append-to-body="false"
>
<el-option v-for="item in pageSizeOptions" :key="item" <el-option v-for="item in pageSizeOptions" :key="item"
:label="`${item}${$t('knowledgeFileUpload.itemsPerPage')}`" :value="item"> :label="`${item}${$t('knowledgeFileUpload.itemsPerPage')}`" :value="item">
</el-option> </el-option>
</el-select> </el-select>
<!-- 首页按钮 --> <!-- 首页按钮 -->
<button class="pagination-btn" <button class="pagination-btn" :disabled="sliceCurrentPage === 1" @click="goToSliceFirstPage">
:disabled="sliceCurrentPage === 1"
@click="goToSliceFirstPage">
{{ $t('knowledgeFileUpload.firstPage') }} {{ $t('knowledgeFileUpload.firstPage') }}
</button> </button>
<!-- 上一页按钮 --> <!-- 上一页按钮 -->
<button class="pagination-btn" <button class="pagination-btn" :disabled="sliceCurrentPage === 1" @click="goToSlicePrevPage">
:disabled="sliceCurrentPage === 1"
@click="goToSlicePrevPage">
{{ $t('knowledgeFileUpload.prevPage') }} {{ $t('knowledgeFileUpload.prevPage') }}
</button> </button>
@@ -220,9 +190,7 @@
</button> </button>
<!-- 下一页按钮 --> <!-- 下一页按钮 -->
<button class="pagination-btn" <button class="pagination-btn" :disabled="sliceCurrentPage === slicePageCount" @click="goToSliceNextPage">
:disabled="sliceCurrentPage === slicePageCount"
@click="goToSliceNextPage">
{{ $t('knowledgeFileUpload.nextPage') }} {{ $t('knowledgeFileUpload.nextPage') }}
</button> </button>
@@ -235,21 +203,18 @@
</el-dialog> </el-dialog>
<!-- 召回测试弹窗 --> <!-- 召回测试弹窗 -->
<el-dialog :title="$t('knowledgeFileUpload.retrievalTest')" :visible.sync="retrievalTestDialogVisible" width="1200px" class="retrieval-test-dialog"> <el-dialog :title="$t('knowledgeFileUpload.retrievalTest')" :visible.sync="retrievalTestDialogVisible"
width="1200px" class="retrieval-test-dialog">
<div class="retrieval-test-form"> <div class="retrieval-test-form">
<el-form :model="retrievalTestForm" label-width="80px"> <el-form :model="retrievalTestForm" label-width="80px">
<el-form-item :label="$t('knowledgeFileUpload.testQuestion')" required> <el-form-item :label="$t('knowledgeFileUpload.testQuestion')" required>
<el-input <el-input v-model="retrievalTestForm.question"
v-model="retrievalTestForm.question" :placeholder="$t('knowledgeFileUpload.testQuestionPlaceholder')" style="width: 100%; max-height: 80px;">
type="textarea"
:rows="2"
:placeholder="$t('knowledgeFileUpload.testQuestionPlaceholder')"
style="width: 100%; max-height: 80px;">
</el-input> </el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="retrieval-test-actions" style="text-align: center; margin-top: 20px;"> <div class="retrieval-test-actions" style="text-align: center;">
<el-button type="primary" @click="runRetrievalTest" :loading="retrievalTestLoading"> <el-button type="primary" @click="runRetrievalTest" :loading="retrievalTestLoading">
{{ $t('knowledgeFileUpload.runTest') }} {{ $t('knowledgeFileUpload.runTest') }}
</el-button> </el-button>
@@ -289,9 +254,9 @@
<script> <script>
import Api from "@/apis/api"; import Api from "@/apis/api";
import KnowledgeBaseAPI from "@/apis/module/knowledgeBase";
import HeaderBar from "@/components/HeaderBar.vue"; import HeaderBar from "@/components/HeaderBar.vue";
import VersionFooter from "@/components/VersionFooter.vue"; import VersionFooter from "@/components/VersionFooter.vue";
import KnowledgeBaseAPI from "@/apis/module/knowledgeBase";
export default { export default {
components: { HeaderBar, VersionFooter }, components: { HeaderBar, VersionFooter },
@@ -385,12 +350,12 @@ export default {
goBack() { goBack() {
this.$router.push('/knowledge-base-management'); this.$router.push('/knowledge-base-management');
}, },
handlePageSizeChange: function(val) { handlePageSizeChange: function (val) {
this.pageSize = val; this.pageSize = val;
this.currentPage = 1; this.currentPage = 1;
this.fetchFileList(); this.fetchFileList();
}, },
fetchFileList: function() { fetchFileList: function () {
this.loading = true; this.loading = true;
const params = { const params = {
page: this.currentPage, page: this.currentPage,
@@ -399,7 +364,7 @@ export default {
}; };
KnowledgeBaseAPI.getDocumentList(this.datasetId, params, KnowledgeBaseAPI.getDocumentList(this.datasetId, params,
async ({data}) => { async ({ data }) => {
this.loading = false; this.loading = false;
if (data && data.code === 0) { if (data && data.code === 0) {
this.fileList = data.data.list; this.fileList = data.data.list;
@@ -424,7 +389,7 @@ export default {
}, },
// 为文档列表中的每个文档获取切片数量 // 为文档列表中的每个文档获取切片数量
fetchSliceCountsForDocuments: async function() { fetchSliceCountsForDocuments: async function () {
if (!this.fileList || this.fileList.length === 0) { if (!this.fileList || this.fileList.length === 0) {
return; return;
} }
@@ -439,7 +404,7 @@ export default {
return new Promise((resolve) => { return new Promise((resolve) => {
KnowledgeBaseAPI.listChunks(this.datasetId, document.id, params, KnowledgeBaseAPI.listChunks(this.datasetId, document.id, params,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
// 获取切片总数 // 获取切片总数
const sliceCount = data.data.total || 0; const sliceCount = data.data.total || 0;
@@ -482,7 +447,7 @@ export default {
}, },
// 获取单个文档的切片数量 // 获取单个文档的切片数量
fetchSliceCountForSingleDocument: function(documentId) { fetchSliceCountForSingleDocument: function (documentId) {
const document = this.fileList.find(doc => doc.id === documentId); const document = this.fileList.find(doc => doc.id === documentId);
if (!document) { if (!document) {
console.warn('未找到文档:', documentId); console.warn('未找到文档:', documentId);
@@ -495,7 +460,7 @@ export default {
}; };
KnowledgeBaseAPI.listChunks(this.datasetId, documentId, params, KnowledgeBaseAPI.listChunks(this.datasetId, documentId, params,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
const sliceCount = data.data.total || 0; const sliceCount = data.data.total || 0;
// 更新文档的切片数量 // 更新文档的切片数量
@@ -514,7 +479,7 @@ export default {
}, },
// 智能检测切片生成状态并自动刷新 // 智能检测切片生成状态并自动刷新
smartRefreshSliceCount: function(documentId, maxRetries = 10, interval = 2000) { smartRefreshSliceCount: function (documentId, maxRetries = 10, interval = 2000) {
const document = this.fileList.find(doc => doc.id === documentId); const document = this.fileList.find(doc => doc.id === documentId);
if (!document) { if (!document) {
console.warn('未找到文档:', documentId); console.warn('未找到文档:', documentId);
@@ -531,7 +496,7 @@ export default {
}; };
KnowledgeBaseAPI.listChunks(this.datasetId, documentId, params, KnowledgeBaseAPI.listChunks(this.datasetId, documentId, params,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
const currentSliceCount = data.data.total || 0; const currentSliceCount = data.data.total || 0;
@@ -581,17 +546,17 @@ export default {
// 开始检测 // 开始检测
setTimeout(checkSliceStatus, 1000); // 1秒后开始第一次检测 setTimeout(checkSliceStatus, 1000); // 1秒后开始第一次检测
}, },
handleSearch: function() { handleSearch: function () {
this.currentPage = 1; this.currentPage = 1;
this.fetchFileList(); this.fetchFileList();
}, },
headerCellClassName: function({ row, column, rowIndex, columnIndex }) { headerCellClassName: function ({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) { if (columnIndex === 0) {
return 'header-cell-first'; return 'header-cell-first';
} }
return 'header-cell'; return 'header-cell';
}, },
showUploadDialog: function() { showUploadDialog: function () {
this.uploadForm = { this.uploadForm = {
name: '', name: '',
file: null file: null
@@ -599,7 +564,7 @@ export default {
this.selectedFilesList = []; // 清空已选择文件列表 this.selectedFilesList = []; // 清空已选择文件列表
this.uploadDialogVisible = true; this.uploadDialogVisible = true;
}, },
handleFileChange: function(file, fileList) { handleFileChange: function (file, fileList) {
if (!file || !file.raw) return; if (!file || !file.raw) return;
// 文件上传前的验证 // 文件上传前的验证
@@ -616,7 +581,7 @@ export default {
raw: file.raw raw: file.raw
}); });
}, },
beforeUpload: function(file) { beforeUpload: function (file) {
// 文件上传前的验证 // 文件上传前的验证
const isLt10M = file.size / 1024 / 1024 < 10; const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) { if (!isLt10M) {
@@ -628,12 +593,12 @@ export default {
return false; // 阻止自动上传,使用自定义上传逻辑 return false; // 阻止自动上传,使用自定义上传逻辑
}, },
// 移除已选择的文件 // 移除已选择的文件
removeSelectedFile: function(index) { removeSelectedFile: function (index) {
this.selectedFilesList.splice(index, 1); this.selectedFilesList.splice(index, 1);
}, },
// 格式化文件大小 // 格式化文件大小
formatFileSize: function(bytes) { formatFileSize: function (bytes) {
if (bytes === 0) return '0 B'; if (bytes === 0) return '0 B';
const k = 1024; const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB']; const sizes = ['B', 'KB', 'MB', 'GB'];
@@ -642,7 +607,7 @@ export default {
}, },
// 批量上传提交 // 批量上传提交
handleBatchUploadSubmit: function() { handleBatchUploadSubmit: function () {
if (this.selectedFilesList.length === 0) { if (this.selectedFilesList.length === 0) {
this.$message.error('请选择要上传的文件'); this.$message.error('请选择要上传的文件');
return; return;
@@ -657,7 +622,7 @@ export default {
formData.append('file', file.raw); formData.append('file', file.raw);
KnowledgeBaseAPI.uploadDocument(this.datasetId, formData, KnowledgeBaseAPI.uploadDocument(this.datasetId, formData,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
resolve({ success: true, fileName: file.name }); resolve({ success: true, fileName: file.name });
} else { } else {
@@ -702,7 +667,7 @@ export default {
}, },
// 单文件上传(保留原有功能) // 单文件上传(保留原有功能)
handleUploadSubmit: function() { handleUploadSubmit: function () {
if (!this.uploadForm.file) { if (!this.uploadForm.file) {
this.$message.error(this.$t('knowledgeFileUpload.fileRequired')); this.$message.error(this.$t('knowledgeFileUpload.fileRequired'));
return; return;
@@ -714,7 +679,7 @@ export default {
formData.append('file', this.uploadForm.file); formData.append('file', this.uploadForm.file);
KnowledgeBaseAPI.uploadDocument(this.datasetId, formData, KnowledgeBaseAPI.uploadDocument(this.datasetId, formData,
({data}) => { ({ data }) => {
this.uploading = false; this.uploading = false;
if (data && data.code === 0) { if (data && data.code === 0) {
this.$message.success(this.$t('knowledgeFileUpload.uploadSuccess')); this.$message.success(this.$t('knowledgeFileUpload.uploadSuccess'));
@@ -731,14 +696,14 @@ export default {
} }
); );
}, },
handleParse: function(row) { handleParse: function (row) {
this.$confirm(this.$t('knowledgeFileUpload.confirmParse'), this.$t('warning'), { this.$confirm(this.$t('knowledgeFileUpload.confirmParse'), this.$t('warning'), {
confirmButtonText: this.$t('knowledgeFileUpload.confirm'), confirmButtonText: this.$t('knowledgeFileUpload.confirm'),
cancelButtonText: this.$t('knowledgeFileUpload.cancel'), cancelButtonText: this.$t('knowledgeFileUpload.cancel'),
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
KnowledgeBaseAPI.parseDocument(this.datasetId, row.id, KnowledgeBaseAPI.parseDocument(this.datasetId, row.id,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
this.$message.success('请求已提交,解析中'); this.$message.success('请求已提交,解析中');
// 使用智能检测自动刷新切片数量 // 使用智能检测自动刷新切片数量
@@ -756,7 +721,7 @@ export default {
this.$message.info(this.$t('knowledgeFileUpload.parseCancelled')); this.$message.info(this.$t('knowledgeFileUpload.parseCancelled'));
}); });
}, },
handleViewSlices: function(row) { handleViewSlices: function (row) {
// 查看切片 // 查看切片
this.currentDocumentId = row.id; this.currentDocumentId = row.id;
this.currentDocumentName = row.name; this.currentDocumentName = row.name;
@@ -765,14 +730,14 @@ export default {
this.sliceSearchKeyword = ''; this.sliceSearchKeyword = '';
this.fetchSlices(); this.fetchSlices();
}, },
handleDelete: function(row) { handleDelete: function (row) {
this.$confirm(this.$t('knowledgeFileUpload.confirmDelete'), this.$t('warning'), { this.$confirm(this.$t('knowledgeFileUpload.confirmDelete'), this.$t('warning'), {
confirmButtonText: this.$t('knowledgeFileUpload.confirm'), confirmButtonText: this.$t('knowledgeFileUpload.confirm'),
cancelButtonText: this.$t('knowledgeFileUpload.cancel'), cancelButtonText: this.$t('knowledgeFileUpload.cancel'),
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
KnowledgeBaseAPI.deleteDocument(this.datasetId, row.id, KnowledgeBaseAPI.deleteDocument(this.datasetId, row.id,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
this.$message.success(this.$t('knowledgeFileUpload.deleteSuccess')); this.$message.success(this.$t('knowledgeFileUpload.deleteSuccess'));
this.fetchFileList(); this.fetchFileList();
@@ -789,10 +754,10 @@ export default {
this.$message.info(this.$t('knowledgeFileUpload.deleteCancelled')); this.$message.info(this.$t('knowledgeFileUpload.deleteCancelled'));
}); });
}, },
handleSelectionChange: function(selection) { handleSelectionChange: function (selection) {
this.selectedFiles = selection; this.selectedFiles = selection;
}, },
handleSelectAll: function() { handleSelectAll: function () {
if (this.isAllSelected) { if (this.isAllSelected) {
this.$refs.fileTable.clearSelection(); this.$refs.fileTable.clearSelection();
this.isAllSelected = false; this.isAllSelected = false;
@@ -804,7 +769,7 @@ export default {
this.isAllSelected = true; this.isAllSelected = true;
} }
}, },
handleBatchDelete: function() { handleBatchDelete: function () {
if (this.selectedFiles.length === 0) { if (this.selectedFiles.length === 0) {
this.$message.warning(this.$t('knowledgeFileUpload.selectFilesFirst')); this.$message.warning(this.$t('knowledgeFileUpload.selectFilesFirst'));
return; return;
@@ -818,7 +783,7 @@ export default {
const deletePromises = this.selectedFiles.map(file => { const deletePromises = this.selectedFiles.map(file => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
KnowledgeBaseAPI.deleteDocument(this.datasetId, file.id, KnowledgeBaseAPI.deleteDocument(this.datasetId, file.id,
({data}) => { ({ data }) => {
if (data && data.code === 0) { if (data && data.code === 0) {
resolve(); resolve();
} else { } else {
@@ -846,8 +811,8 @@ export default {
this.$message.info(this.$t('knowledgeFileUpload.deleteCancelled')); this.$message.info(this.$t('knowledgeFileUpload.deleteCancelled'));
}); });
}, },
getStatusType: function(status) { getStatusType: function (status) {
switch(status) { switch (status) {
case 0: case 0:
return 'info'; // 灰色 - 待解析 return 'info'; // 灰色 - 待解析
case 1: case 1:
@@ -858,8 +823,8 @@ export default {
return 'danger'; // 红色 - 解析失败 return 'danger'; // 红色 - 解析失败
} }
}, },
getStatusText: function(status) { getStatusText: function (status) {
switch(status) { switch (status) {
case 0: case 0:
return this.$t('knowledgeFileUpload.statusPending'); return this.$t('knowledgeFileUpload.statusPending');
case 1: case 1:
@@ -870,38 +835,38 @@ export default {
return this.$t('knowledgeFileUpload.statusFailed'); return this.$t('knowledgeFileUpload.statusFailed');
} }
}, },
goToPage: function(page) { goToPage: function (page) {
if (page !== this.currentPage) { if (page !== this.currentPage) {
this.currentPage = page; this.currentPage = page;
this.fetchFileList(); this.fetchFileList();
} }
}, },
goFirst: function() { goFirst: function () {
if (this.currentPage !== 1) { if (this.currentPage !== 1) {
this.currentPage = 1; this.currentPage = 1;
this.fetchFileList(); this.fetchFileList();
} }
}, },
goPrev: function() { goPrev: function () {
if (this.currentPage > 1) { if (this.currentPage > 1) {
this.currentPage--; this.currentPage--;
this.fetchFileList(); this.fetchFileList();
} }
}, },
goNext: function() { goNext: function () {
if (this.currentPage < this.pageCount) { if (this.currentPage < this.pageCount) {
this.currentPage++; this.currentPage++;
this.fetchFileList(); this.fetchFileList();
} }
}, },
formatDate: function(dateString) { formatDate: function (dateString) {
if (!dateString) return ''; if (!dateString) return '';
const date = new Date(dateString); const date = new Date(dateString);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`; return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
}, },
// 切片管理相关方法 // 切片管理相关方法
fetchSlices: function() { fetchSlices: function () {
this.sliceLoading = true; this.sliceLoading = true;
const params = { const params = {
@@ -914,7 +879,7 @@ export default {
} }
KnowledgeBaseAPI.listChunks(this.datasetId, this.currentDocumentId, params, KnowledgeBaseAPI.listChunks(this.datasetId, this.currentDocumentId, params,
({data}) => { ({ data }) => {
this.sliceLoading = false; this.sliceLoading = false;
if (data && data.code === 0) { if (data && data.code === 0) {
// 解析切片列表数据 // 解析切片列表数据
@@ -935,7 +900,7 @@ export default {
); );
}, },
parseSliceData: function(data) { parseSliceData: function (data) {
try { try {
if (data && data.list) { if (data && data.list) {
// 后端已经解析过的格式 // 后端已经解析过的格式
@@ -964,19 +929,19 @@ export default {
} }
}, },
handleSliceSizeChange: function(pageSize) { handleSliceSizeChange: function (pageSize) {
this.slicePageSize = pageSize; this.slicePageSize = pageSize;
this.sliceCurrentPage = 1; this.sliceCurrentPage = 1;
this.fetchSlices(); this.fetchSlices();
}, },
handleSlicePageChange: function(page) { handleSlicePageChange: function (page) {
this.sliceCurrentPage = page; this.sliceCurrentPage = page;
this.fetchSlices(); this.fetchSlices();
}, },
// 跳转到切片管理第一页 // 跳转到切片管理第一页
goToSliceFirstPage: function() { goToSliceFirstPage: function () {
if (this.sliceCurrentPage !== 1) { if (this.sliceCurrentPage !== 1) {
this.sliceCurrentPage = 1; this.sliceCurrentPage = 1;
this.fetchSlices(); this.fetchSlices();
@@ -984,7 +949,7 @@ export default {
}, },
// 切片管理上一页 // 切片管理上一页
goToSlicePrevPage: function() { goToSlicePrevPage: function () {
if (this.sliceCurrentPage > 1) { if (this.sliceCurrentPage > 1) {
this.sliceCurrentPage--; this.sliceCurrentPage--;
this.fetchSlices(); this.fetchSlices();
@@ -992,7 +957,7 @@ export default {
}, },
// 切片管理跳转到指定页 // 切片管理跳转到指定页
goToSlicePage: function(page) { goToSlicePage: function (page) {
if (page !== this.sliceCurrentPage) { if (page !== this.sliceCurrentPage) {
this.sliceCurrentPage = page; this.sliceCurrentPage = page;
this.fetchSlices(); this.fetchSlices();
@@ -1000,7 +965,7 @@ export default {
}, },
// 切片管理下一页 // 切片管理下一页
goToSliceNextPage: function() { goToSliceNextPage: function () {
if (this.sliceCurrentPage < this.slicePageCount) { if (this.sliceCurrentPage < this.slicePageCount) {
this.sliceCurrentPage++; this.sliceCurrentPage++;
this.fetchSlices(); this.fetchSlices();
@@ -1008,7 +973,7 @@ export default {
}, },
// 召回测试相关方法 // 召回测试相关方法
showRetrievalTestDialog: function() { showRetrievalTestDialog: function () {
// 初始化召回测试表单 // 初始化召回测试表单
this.retrievalTestForm = { this.retrievalTestForm = {
question: '' question: ''
@@ -1017,7 +982,7 @@ export default {
this.retrievalTestDialogVisible = true; this.retrievalTestDialogVisible = true;
}, },
runRetrievalTest: function() { runRetrievalTest: function () {
if (!this.retrievalTestForm.question.trim()) { if (!this.retrievalTestForm.question.trim()) {
this.$message.error(this.$t('knowledgeFileUpload.testQuestionRequired')); this.$message.error(this.$t('knowledgeFileUpload.testQuestionRequired'));
return; return;
@@ -1033,7 +998,7 @@ export default {
// 调用召回测试API // 调用召回测试API
KnowledgeBaseAPI.retrievalTest(this.datasetId, requestData, KnowledgeBaseAPI.retrievalTest(this.datasetId, requestData,
({data}) => { ({ data }) => {
this.retrievalTestLoading = false; this.retrievalTestLoading = false;
if (data && data.code === 0) { if (data && data.code === 0) {
this.retrievalTestResult = data.data || data; this.retrievalTestResult = data.data || data;
@@ -1050,7 +1015,7 @@ export default {
); );
}, },
handleRetrievalTestDialogClose: function() { handleRetrievalTestDialogClose: function () {
this.retrievalTestDialogVisible = false; this.retrievalTestDialogVisible = false;
this.retrievalTestResult = null; this.retrievalTestResult = null;
} }
@@ -1458,27 +1423,45 @@ export default {
/* 召回测试弹窗样式 */ /* 召回测试弹窗样式 */
.retrieval-test-dialog { .retrieval-test-dialog {
:deep(.el-dialog) { ::v-deep .el-dialog__wrapper {
width: 1000px !important; display: block !important;
max-height: 850px !important;
min-height: 600px !important;
} }
:deep(.el-dialog__body) { ::v-deep .el-dialog {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
margin: 0 !important;
width: 1200px !important;
height: 90vh !important;
max-height: 90vh !important;
min-height: 90vh !important;
}
::v-deep .el-dialog__body {
height: calc(100% - 90px) !important; height: calc(100% - 90px) !important;
max-height: calc(100% - 90px) !important; max-height: calc(100% - 90px) !important;
overflow: hidden; overflow: hidden;
padding: 15px 25px; padding: 15px 25px;
display: flex;
flex-direction: column;
} }
} }
.retrieval-test-form {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.retrieval-test-result { .retrieval-test-result {
margin-top: 20px; margin-top: 20px;
height: 300px; flex: 1;
max-height: 300px;
min-height: 200px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden;
h4 { h4 {
margin: 0 0 12px 0; margin: 0 0 12px 0;
@@ -1704,39 +1687,48 @@ export default {
} }
} }
.slice-dialog-content { .slice-dialog-content {
max-height: 70vh; max-height: 70vh;
overflow-y: auto; overflow-y: auto;
}
/* 切片管理弹窗固定容器大小 */
.slice-dialog {
::v-deep .el-dialog__wrapper {
display: block !important;
} }
/* 切片管理弹窗固定容器大小 */
.slice-dialog {
/* 切片管理弹窗滚动条样式 */ /* 切片管理弹窗滚动条样式 */
:deep(.el-dialog)::-webkit-scrollbar { ::v-deep .el-dialog::-webkit-scrollbar {
width: 8px; width: 8px;
height: 8px; height: 8px;
} }
:deep(.el-dialog)::-webkit-scrollbar-track { ::v-deep .el-dialog::-webkit-scrollbar-track {
background: #f8f9fa; background: #f8f9fa;
border-radius: 4px; border-radius: 4px;
} }
:deep(.el-dialog)::-webkit-scrollbar-thumb { ::v-deep .el-dialog::-webkit-scrollbar-thumb {
background: #f0f0f0; background: #f0f0f0;
border-radius: 4px; border-radius: 4px;
border: 1px solid #e8e8e8; border: 1px solid #e8e8e8;
} }
:deep(.el-dialog)::-webkit-scrollbar-thumb:hover { ::v-deep .el-dialog::-webkit-scrollbar-thumb:hover {
background: #e8e8e8; background: #e8e8e8;
} }
:deep(.el-dialog) { ::v-deep .el-dialog {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
margin: 0 !important;
width: 1200px !important; width: 1200px !important;
height: 800px !important; height: 90vh !important;
max-height: 600px !important; max-height: 90vh !important;
min-height: 600px !important; min-height: 90vh !important;
} }
:deep(.el-dialog__body) { :deep(.el-dialog__body) {
@@ -1875,7 +1867,8 @@ export default {
} }
/* 列表样式 */ /* 列表样式 */
ul, ol { ul,
ol {
margin: 8px 0; margin: 8px 0;
padding-left: 24px; padding-left: 24px;
@@ -1886,19 +1879,38 @@ export default {
} }
/* 标题样式 */ /* 标题样式 */
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
margin: 16px 0 8px 0; margin: 16px 0 8px 0;
font-weight: 600; font-weight: 600;
line-height: 1.4; line-height: 1.4;
} }
h1 { font-size: 18px; } h1 {
h2 { font-size: 16px; } font-size: 18px;
h3 { font-size: 15px; } }
h4, h5, h6 { font-size: 14px; }
h2 {
font-size: 16px;
}
h3 {
font-size: 15px;
}
h4,
h5,
h6 {
font-size: 14px;
}
/* 强调文本 */ /* 强调文本 */
strong, b { strong,
b {
font-weight: 600; font-weight: 600;
color: #1a1a1a; color: #1a1a1a;
} }
@@ -1932,22 +1944,9 @@ export default {
justify-content: center; justify-content: center;
height: 100%; height: 100%;
} }
} }
.slice-header { .slice-count {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 20px;
}
.slice-info {
display: flex;
flex-direction: column;
gap: 8px;
}
.slice-count {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
@@ -1957,30 +1956,30 @@ export default {
padding: 6px 12px; padding: 6px 12px;
border-radius: 4px; border-radius: 4px;
border: 1px solid #e4e7ed; border: 1px solid #e4e7ed;
} }
.count-label { .count-label {
font-weight: 500; font-weight: 500;
color: #303133; color: #303133;
} }
.count-value { .count-value {
font-weight: 600; font-weight: 600;
color: #409eff; color: #409eff;
font-size: 15px; font-size: 15px;
} }
.count-unit { .count-unit {
color: #909399; color: #909399;
} }
.slice-actions { .slice-actions {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
} }
.slice-pagination { .slice-pagination {
text-align: right; text-align: right;
margin-top: 20px; margin-top: 20px;
@@ -1990,7 +1989,7 @@ export default {
justify-content: flex-end; justify-content: flex-end;
gap: 5px; gap: 5px;
} }
} }
@media (min-width: 1144px) { @media (min-width: 1144px) {
.table_bottom { .table_bottom {