1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228 |
- <template>
- <div class="gpu-list">
- <!-- 顶部筛选区域 -->
- <div class="filter-section">
- <el-select
- v-model="selectedBucket"
- placeholder="请选择知识库"
- @change="handleBucketChange"
- >
- <el-option
- v-for="item in buckets"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- <el-select
- v-model="selectedType"
- placeholder="请选择目录"
- :disabled="!selectedBucket"
- class="ml-15"
- >
- <el-option
- v-for="item in types"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- <el-button
- type="primary"
- :loading="isSyncing"
- :disabled="!selectedType"
- class="ml-15"
- @click="handleSyncData"
- >
- {{ isSyncing ? "同步中..." : "同步数据" }}
- </el-button>
- </div>
- <el-tabs v-model="activeName" @tab-click="handleClick">
- <!-- 原有的文献列表 tab -->
- <el-tab-pane label="文献列表" name="first">
- <!-- 添加搜索表单 -->
- <div class="search-form">
- <el-form
- :inline="true"
- :model="searchForm"
- class="demo-form-inline"
- label-width="80px"
- ><el-form-item label="内容:">
- <el-input
- style="width: 260px"
- v-model="searchForm.name"
- clearable
- placeholder="请输入名称\文献编号\ID"
- ></el-input>
- </el-form-item>
- <el-form-item label="创建时间:">
- <el-date-picker
- v-model="searchForm.createTimeRange"
- type="daterange"
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- value-format="yyyy-MM-dd"
- />
- </el-form-item>
- <el-form-item label="更新时间:">
- <el-date-picker
- v-model="searchForm.updateTimeRange"
- type="daterange"
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- value-format="yyyy-MM-dd"
- />
- </el-form-item>
- <!-- <el-form-item label="文档类型:">
- <el-select
- v-model="searchForm.type"
- clearable
- placeholder="请选择文档类型"
- >
- <el-option label="PDF" value="pdf" />
- <el-option label="DOCX" value="docx" />
- <el-option label="DOC" value="doc" />
- <el-option label="TXT" value="txt" />
- </el-select>
- </el-form-item> -->
- <el-form-item label="处理状态:">
- <el-select
- v-model="searchForm.processing_status"
- clearable
- placeholder="请选择处理状态"
- >
- <el-option
- v-for="(value, key) in STATUS_MAP"
- :key="key"
- :label="value.text"
- :value="key"
- />
- </el-select>
- </el-form-item>
- <!-- <el-form-item label="文本时间:">
- <el-date-picker
- v-model="searchForm.textTimeRange"
- type="daterange"
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- value-format="yyyy-MM-dd"
- />
- </el-form-item> -->
- <el-form-item label="标签:">
- <el-select
- v-model="searchForm.id"
- multiple
- filterable
- remote
- reserve-keyword
- :remote-method="searchFormTags"
- :loading="searchTagsLoading"
- placeholder="请输入标签关键词"
- clearable
- >
- <el-option
- v-for="tag in searchTagOptions"
- :key="tag.id"
- :label="tag.name"
- :value="tag.name"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleSearch">搜索</el-button>
- <el-button @click="resetSearch" type="danger">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
- <div class="batch-operations">
- <el-button
- type="primary"
- @click="handleBatchProcess"
- :loading="isProcessing"
- :disabled="selectedRows.length === 0"
- class="ml-15"
- >
- {{ isProcessing ? "处理中..." : "批量处理文献" }}
- </el-button>
- <el-button
- type="primary"
- @click="handleBatchTag"
- :disabled="selectedRows.length == 0"
- >批量绑定标签</el-button
- >
- <el-button
- type="primary"
- @click="handleExport"
- :disabled="selectedRows.length == 0"
- >文件导出</el-button
- >
- </div>
- <!-- 添加选择提示区域 :title="selectionText"-->
- <div class="selection-control" v-if="selectedRows.length > 0">
- <el-alert
- type="info"
- show-icon
- :closable="false"
- style="margin-bottom: 10px"
- >
- <template v-if="!isAllDataSelected">
- <span
- type="text"
- style="cursor: pointer; color: #409eff"
- @click="handleSelectAllData"
- >
- 选择全部{{ total }}条数据
- </span>
- </template>
- <template v-else>
- <span
- type="text"
- style="cursor: pointer; color: #409eff"
- @click="handleCancelAllSelection"
- >
- 取消全选
- </span>
- </template>
- </el-alert>
- </div>
- <!-- 数据表格区域 -->
- <el-table
- v-loading="isLoading"
- :data="gpuList"
- style="width: 100%"
- @selection-change="handleSelectionChange"
- @select-all="handleSelectAll"
- ref="gpuTable"
- :row-key="getRowKey"
- >
- <el-table-column
- type="selection"
- width="55"
- :selectable="checkSelectable"
- :reserve-selection="true"
- />
- <el-table-column prop="id" label="ID" width="80" />
- <el-table-column prop="identifier" label="文献编号"></el-table-column>
- <el-table-column prop="name" label="名称" sortable>
- <!-- <template #default="{ row }">
- <el-link @click="handleNameClick(row)">{{ row.name }}</el-link>
- </template> -->
- </el-table-column>
- <el-table-column prop="tags" label="已绑定标签">
- <template #default="{ row }">
- <el-tag
- v-for="(item, index) in row.tags"
- :key="index"
- type=""
- style="margin-right: 5px;margin-bottom:5px;"
- >
- {{ item.name }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="type" label="文档类型" width="100" />
- <el-table-column
- prop="create_time"
- label="创建时间"
- width="200"
- sortable
- />
- <el-table-column prop="status" label="处理状态" width="100">
- <template #default="{ row }">
- <el-tag :type="getStatusType(row.processing_status)">
- {{ getStatusText(row.processing_status) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="100">
- <template #default="{ row }">
- <el-dropdown trigger="click">
- <el-button
- type="text"
- size="small"
- circle
- class="operation-button"
- style="font-size: 15px; margin-left: 10px"
- icon="el-icon-more"
- ></el-button>
- <template #dropdown>
- <el-dropdown-menu>
- <el-dropdown-item @click.native="handleNameClick(row)">
- <i class="el-icon-view"></i> 查看
- </el-dropdown-item>
- <el-dropdown-item @click.native="handlePreview(row)">
- <i class="el-icon-tickets"></i> 预览
- </el-dropdown-item>
- <el-dropdown-item
- @click.native="handleSingleProcess(row)"
- v-if="row.processing_status !== 2"
- >
- <i class="el-icon-caret-right"></i> 处理文献
- </el-dropdown-item>
- <el-dropdown-item
- @click.native="handleReprocess(row)"
- v-if="row.processing_status === 2"
- >
- <i class="el-icon-refresh"></i> 重新处理
- </el-dropdown-item>
- <!-- <el-dropdown-item
- @click.native="firstHandleUpload(scope.$index, scope.row)"
- >
- <i class="el-icon-refresh"></i> 批量处理
- </el-dropdown-item> -->
- <!-- <el-dropdown-item
- @click.native="firstHandleDelete(scope.$index, scope.row)"
- >
- <i class="el-icon-delete"></i> 删除
- </el-dropdown-item> -->
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页器 -->
- <el-pagination
- class="pagination"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- :current-page="currentPage"
- :page-sizes="[10, 20, 50, 100]"
- :page-size="pageSize"
- layout="total, sizes, prev, pager, next, jumper"
- :total="total"
- />
- </el-tab-pane>
- <!-- 添加 SOTA详情 tab -->
- <el-tab-pane label="SOTA详情" name="second">
- <el-table :data="sotaDetailsList" style="width: 100%">
- <el-table-column label="Identifier" prop="identifier" />
- <el-table-column label="Device" prop="device" />
- <el-table-column label="Outcomes" prop="outcomes" />
- <el-table-column label="Unit for analysis" prop="unit" />
- <el-table-column label="Mean" prop="mean" />
- <!-- 操作列与原有类似 -->
- </el-table>
- </el-tab-pane>
- <!-- 添加 SOTA汇总表 tab -->
- <el-tab-pane label="SOTA汇总表" name="third">
- <el-table :data="sotaSummaryList" style="width: 100%">
- <el-table-column label="Summary" prop="summary" />
- <el-table-column label="EqMD" prop="eqmd" />
- <el-table-column label="Pain:VAS" prop="painVas" />
- <!-- 操作列与原有类似 -->
- </el-table>
- </el-tab-pane>
- </el-tabs>
- <!-- 添加标签对话框 -->
- <el-dialog
- title="批量绑定标签"
- :visible.sync="tagDialogVisible"
- width="800px"
- >
- <el-form :model="tagForm" label-width="150px">
- <el-form-item label="标签分类:">
- <el-select
- v-model="tagForm.category_id"
- placeholder="请选择分类"
- clearable
- style="width: 350px"
- @change="handleCategoryChange"
- >
- <el-option label="全部分类" value="" />
- <el-option
- v-for="item in categoriesList"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="标签:">
- <el-select
- style="width: 350px"
- v-model="tagForm.tags"
- multiple
- filterable
- remote
- reserve-keyword
- :remote-method="handleTagSearch"
- :loading="tagsLoading"
- placeholder="请输入关键词搜索标签"
- >
- <el-option
- v-for="tag in tagOptions"
- :key="tag.id"
- :label="tag.name"
- :value="tag.id"
- />
- </el-select>
- </el-form-item>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="tagDialogVisible = false">取消</el-button>
- <el-button type="primary" @click="submitBatchTag">确定</el-button>
- </span>
- </template>
- </el-dialog>
- </div>
- </template>
- <script>
- import { debounce } from "lodash-es";
- import {
- GET_list,
- GET_sync,
- listBuckets,
- selectTypeList,
- getDetail,
- search_tags,
- edit_tags,
- search,
- process_model_generation,
- process_model_regeneration,
- categories,
- } from "@/api/knowledge";
- import axios from "axios";
- // 状态映射表
- const STATUS_MAP = {
- 0: { text: "未处理", type: "info" },
- 1: { text: "处理中", type: "warning" },
- 2: { text: "处理完成", type: "success" },
- 3: { text: "处理失败", type: "danger" },
- };
- export default {
- name: "GpuList",
- data() {
- return {
- gpuList: [],
- currentPage: 1,
- pageSize: 10,
- total: 0,
- isLoading: false,
- isSyncing: false,
- buckets: [],
- types: [],
- selectedBucket: null,
- selectedType: null,
- activeName: "first", // 当前激活的tab
- sotaDetailsList: [], // SOTA详情列表数据
- sotaSummaryList: [], // SOTA汇总表数据
- searchForm: {
- name: "",
- createTimeRange: [],
- textTimeRange: [],
- id: [],
- type: "", // 新增文档类型
- processing_status: "", // 新增处理状态
- updateTimeRange: [], // 新增更新时间范围
- },
- selectedRows: [], // 选中的行
- tagDialogVisible: false, // 标签对话框显示状态
- categoriesList: [], // 添加分类列表
- tagForm: {
- tags: [], // 选中的标签ID数组
- category_id: null, // 添加分类ID
- },
- tagOptions: [], // 标签选项
- tagsLoading: false, // 标签加载状态
- searchTagOptions: [], // 搜索表单的标签选项
- searchTagsLoading: false, // 搜索表单的标签加载状态
- isProcessing: false, // 批量处理的加载状态
- pollingTimers: {}, // 新增:存储每个文献的轮询定时器
- STATUS_MAP: {
- 0: { text: "未处理", type: "info" },
- 1: { text: "处理中", type: "warning" },
- 2: { text: "处理完成", type: "success" },
- 3: { text: "处理失败", type: "danger" },
- },
- multipleSelection: [], // 存储跨页选中的数据
- selectedRows: [], // 当前页选中的行
- allSelectedRows: new Map(), // 存储所有选中的行
- isAllDataSelected: false, // 是否选中所有数据
- };
- },
- created() {
- // 使用防抖处理数据加载
- this.debouncedFetchGpuList = debounce(this.fetchGpuList, 300);
- },
- mounted() {
- this.initialize();
- },
- computed: {
- // 添加选择提示文本计算属性
- selectionText() {
- const selectedCount = this.isAllDataSelected
- ? this.total
- : this.allSelectedRows.size;
- return `已选择 ${selectedCount} 项`;
- },
- },
- methods: {
- // 添加获取分类列表方法
- async fetchCategories() {
- try {
- const res = await categories();
- if (res.status === 200) {
- this.categoriesList = res.data.data.items;
- }
- } catch (error) {
- console.error("获取分类列表失败:", error);
- this.$message.error("获取分类列表失败");
- }
- },
- // 添加导出处理方法
- async handleExport() {
- try {
- const ids = this.selectedRows.map((row) => row.id);
- // 添加确认对话框
- await this.$confirm("确认要导出选中的文献吗?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- });
- // 调用导出接口
- const response = await axios({
- url: `${process.env.VUE_APP_BASE_API}/literature-data/export/`,
- method: "POST",
- data: { ids },
- responseType: "blob", // 指定响应类型为 blob
- });
- // 创建下载链接
- const blob = new Blob([response.data], {
- type: response.headers["content-type"],
- });
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- // 从响应头获取文件名,如果没有则使用默认名称
- const filename = response.headers["content-disposition"]
- ? decodeURIComponent(
- response.headers["content-disposition"].split("filename=")[1]
- )
- : "文献导出.xlsx";
- link.setAttribute("download", filename);
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- window.URL.revokeObjectURL(url);
- this.$message.success("导出成功");
- } catch (error) {
- if (error === "cancel") return;
- this.$message.error(error.message || "导出失败");
- console.error("导出错误:", error);
- }
- },
- /* 重复处理 */
- async handleReprocess(row) {
- try {
- await this.$confirm("确认要重新处理该文献吗?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- });
- // 调用重新处理的接口
- const res = await process_model_regeneration([row.id]); // 添加第二个参数表示重新处理
- if (res.status === 200) {
- this.$message.success("重新处理任务已提交");
- await this.fetchGpuList(); // 刷新列表
- } else {
- throw new Error(res.message || "重新处理失败");
- }
- } catch (error) {
- if (error === "cancel") {
- return;
- }
- this.$message.error(error.message || "重新处理提交失败");
- console.error("重新处理错误:", error);
- }
- },
- // 在中添加单个处理方法
- async handleSingleProcess(row) {
- try {
- await this.$confirm("确认要处理该文献吗?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- });
- const res = await process_model_generation([row.id]);
- if (res.status === 200) {
- this.$message.success("处��任务已提交");
- await this.fetchGpuList(); // 刷新列表
- } else {
- throw new Error(res.message || "处理失败");
- }
- } catch (error) {
- if (error === "cancel") {
- return;
- }
- this.$message.error(error.message || "处理提交失败");
- console.error("处理错误:", error);
- }
- },
- /* 搜索栏模糊查找 */
- async searchFormTags(query) {
- if (query !== "") {
- this.searchTagsLoading = true;
- try {
- const { data } = await search_tags({ keyword: query });
- this.searchTagOptions = data.data.items;
- } catch (error) {
- this.$message.error("搜索标签失败");
- } finally {
- this.searchTagsLoading = false;
- }
- } else {
- this.searchTagOptions = [];
- }
- },
- // 获取行的唯一键
- getRowKey(row) {
- return row.id;
- },
- // 处理表格选择变化
- handleSelectionChange(selection) {
- this.selectedRows = selection;
- if (!this.isAllDataSelected) {
- // 更新选中数据集合
- selection.forEach((row) => {
- this.allSelectedRows.set(row.id, row);
- });
- // 当前页取消选中的数据从总选中集合中移除
- this.gpuList.forEach((row) => {
- if (!selection.find((item) => item.id === row.id)) {
- this.allSelectedRows.delete(row.id);
- }
- });
- }
- },
- // 处理全选按钮
- handleSelectAll(selection) {
- if (selection.length > 0) {
- this.$message.success(`已全选当前页${selection.length}条数据`);
- } else {
- // 取消当前页所有选择
- this.gpuList.forEach((row) => {
- this.allSelectedRows.delete(row.id);
- });
- this.$message.info("已取消选中当前页全部数据");
- }
- },
- // 选择全部数据
- async handleSelectAllData() {
- try {
- // 获取所有数据的查询参数
- const params = {
- page: 1,
- page_size: this.total,
- keyword: this.searchForm.name,
- tag_names: this.searchForm.id,
- create_time_start: this.searchForm.createTimeRange?.[0] || "",
- create_time_end: this.searchForm.createTimeRange?.[1] || "",
- update_time_start: this.searchForm.updateTimeRange?.[0] || "",
- update_time_end: this.searchForm.updateTimeRange?.[1] || "",
- processing_status: this.searchForm.processing_status || null,
- };
- const response = await axios.post(
- `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
- params
- );
- if (response.status === 200) {
- const allData = response.data.data.list;
- // 清空之前的选择
- this.allSelectedRows.clear();
- // 将所有数据添加到选中集合
- allData.forEach((item) => {
- this.allSelectedRows.set(item.id, item);
- });
- this.isAllDataSelected = true;
- // 选中当前页显示的所有行
- this.$nextTick(() => {
- if (this.$refs.gpuTable) {
- this.gpuList.forEach((row) => {
- this.$refs.gpuTable.toggleRowSelection(row, true);
- });
- }
- });
- this.$message.success(`已选中全部${this.total}条数据`);
- }
- } catch (error) {
- console.error("获取全部数据失败:", error);
- this.$message.error("选择全部数据失败");
- }
- },
- // 取消全选
- handleCancelAllSelection() {
- this.clearSelection();
- this.$message.info("已取消全部选择");
- },
- // 检查行是否可选
- checkSelectable(row) {
- // 可以根据需要添加选择限制条件
- return true;
- },
- // 修改分页方法
- async handleCurrentChange(val) {
- this.currentPage = val;
- await this.fetchGpuList();
- // 恢复选中状态
- this.$nextTick(() => {
- if (this.$refs.gpuTable) {
- this.gpuList.forEach((row) => {
- if (this.allSelectedRows.has(row.id) || this.isAllDataSelected) {
- this.$refs.gpuTable.toggleRowSelection(row, true);
- }
- });
- }
- });
- },
- // 修改每页条数切换方法
- async handleSizeChange(val) {
- this.pageSize = val;
- this.currentPage = 1;
- await this.fetchGpuList();
- // 恢复选中状态
- this.$nextTick(() => {
- if (this.$refs.gpuTable) {
- this.gpuList.forEach((row) => {
- if (this.allSelectedRows.has(row.id) || this.isAllDataSelected) {
- this.$refs.gpuTable.toggleRowSelection(row, true);
- }
- });
- }
- });
- },
- // 清空选择
- clearSelection() {
- if (this.$refs.gpuTable) {
- this.$refs.gpuTable.clearSelection();
- }
- this.selectedRows = [];
- this.allSelectedRows.clear();
- this.isAllDataSelected = false;
- },
- // 打开标签对话框时重置表单
- handleBatchTag() {
- this.tagDialogVisible = true;
- this.tagForm = {
- tags: [],
- category_id: "",
- };
- this.tagOptions = [];
- this.fetchCategories(); // 获取分类列表
- this.handleCategoryChange(""); // 获取所有标签
- },
- // 修改分类变更处理方法
- async handleCategoryChange(categoryId) {
- this.tagForm.tags = []; // 清空已选标签
- this.tagOptions = []; // 清空标签选项
- try {
- this.tagsLoading = true;
- const { data } = await search_tags({
- page: 1,
- pagesize: 999,
- keyword: "",
- category_id: categoryId === "" ? undefined : categoryId, // 修改判断条件
- });
- if (data?.data?.items) {
- this.tagOptions = data.data.items;
- }
- } catch (error) {
- console.error("获取标签列表失败:", error);
- this.$message.error("获取标签列表失败");
- } finally {
- this.tagsLoading = false;
- }
- },
- // 修改标签搜索方法
- async handleTagSearch(query) {
- this.tagsLoading = true;
- try {
- const { data } = await search_tags({
- keyword: query,
- category_id:
- this.tagForm.category_id === ""
- ? undefined
- : this.tagForm.category_id, // 修改判断条件
- });
- if (data?.data?.items) {
- this.tagOptions = data.data.items;
- }
- } catch (error) {
- console.error("搜索标签失败:", error);
- this.$message.error("搜索标签失败");
- } finally {
- this.tagsLoading = false;
- }
- },
- /* 批量处理文献 */
- async handleBatchProcess() {
- const selectedIds = this.isAllDataSelected
- ? await this.getAllDataIds()
- : Array.from(this.allSelectedRows.keys());
- if (selectedIds.length === 0) {
- this.$message.warning("请选择需要处理的文献");
- return;
- }
- try {
- this.isProcessing = true;
- const ids = this.selectedRows.map((row) => row.id);
- // 添加确认对话框
- await this.$confirm("确认要批量处理选中的文献吗?", "提示", {
- confirmButtonText: "确定",
- cancelButtonText: "取消",
- type: "warning",
- });
- const res = await process_model_regeneration(ids);//process_model_regeneration
- if (res.status === 200) {
- this.$message.success("批量处理已提交");
- this.selectedRows = []; // 清空选中
- this.clearSelection()
- this.allSelectedRows.clear();
- await this.fetchGpuList(); // 刷新列表
- } else {
- throw new Error(res.message || "处理失败");
- }
- } catch (error) {
- if (error === "cancel") {
- return;
- }
- this.$message.error(error.message || "批量处理提交失败");
- console.error("批量处理错误:", error);
- } finally {
- this.isProcessing = false;
- }
- },
- // 获取所有数据的ID
- async getAllDataIds() {
- try {
- const params = {
- page: 1,
- page_size: this.total,
- keyword: this.searchForm.name,
- tag_names: this.searchForm.id,
- create_time_start: this.searchForm.createTimeRange?.[0] || "",
- create_time_end: this.searchForm.createTimeRange?.[1] || "",
- update_time_start: this.searchForm.updateTimeRange?.[0] || "",
- update_time_end: this.searchForm.updateTimeRange?.[1] || "",
- processing_status: this.searchForm.processing_status || null,
- };
- const response = await axios.post(
- `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
- params
- );
- if (response.status === 200) {
- return response.data.data.list.map((item) => item.id);
- }
- return [];
- } catch (error) {
- console.error("获取所有数据ID失败:", error);
- return [];
- }
- },
- /* 模糊搜索 */
- async searchTags(query) {
- if (query !== "") {
- this.tagsLoading = true;
- try {
- const { data } = await search_tags({
- keyword: query,
- });
- this.tagOptions = data.data.items;
- } catch (error) {
- this.$message.error("搜索标签失败");
- } finally {
- this.tagsLoading = false;
- }
- } else {
- this.tagOptions = [];
- }
- },
- // 修改提交方法
- async submitBatchTag() {
- try {
- const ids = this.selectedRows.map((row) => row.id);
- // 这里需要添加实际的API调用
- /* await edit_tags({
- ids,
- tagIds: this.tagForm.tags, // 现在传递的是标签ID数组
- }); */
- const idObject = { literature_ids: ids, tag_ids: this.tagForm.tags };
- const response = await axios.post(
- `${process.env.VUE_APP_BASE_API}/literature-tags/relation_tags/`,
- idObject,
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- if (response.status !== 200) return;
- console.log(this.tagForm.tags);
- this.$message.success("标签更新成功");
- this.tagDialogVisible = false;
- this.fetchGpuList(); // 刷新列表
- } catch (error) {
- this.$message.error("标签更新失败");
- }
- },
- // 处理搜索
- handleSearch() {
- this.currentPage = 1; // 重置页码
- this.fetchGpuList();
- },
- // 修改重置搜索方法
- resetSearch() {
- this.searchForm = {
- name: "",
- createTimeRange: [],
- textTimeRange: [],
- id: [],
- type: "",
- processing_status: "",
- };
- this.clearSelection(); // 清空选择
- this.handleSearch();
- },
- // 初始化数据
- async initialize() {
- try {
- await this.fetchBuckets();
- await this.fetchGpuList();
- } catch (error) {
- this.$message.error("初始化数据失败");
- console.error("初始化失败:", error);
- }
- },
- // 获取状态文本
- getStatusText(status) {
- return STATUS_MAP[status]?.text || "未知状态";
- },
- // 获取状态样式类型
- getStatusType(status) {
- return STATUS_MAP[status]?.type || "info";
- },
- // 获取知识库列表
- async fetchBuckets() {
- try {
- const { data } = await listBuckets();
- this.buckets = data;
- } catch (error) {
- this.$message.error("获取知识库列表失败");
- console.error("获取知识库失败:", error);
- }
- },
- // 处理知识库变更
- async handleBucketChange(val) {
- this.selectedType = null;
- this.types = [];
- if (!val) return;
- try {
- const { data } = await selectTypeList({ kb_id: val });
- this.types = data.dataList;
- this.debouncedFetchGpuList();
- } catch (error) {
- this.$message.error("获取目录列表失败");
- }
- },
- // 同步数据处理
- async handleSyncData() {
- if (!this.selectedType) {
- this.$message.warning("请先选择目录");
- return;
- }
- this.isSyncing = true;
- try {
- await GET_sync({ doc_type_id: this.selectedType });
- this.$message.success("同步成功");
- await this.fetchGpuList();
- } catch (error) {
- this.$message.error("同步失败");
- } finally {
- this.isSyncing = false;
- }
- },
- // 修改 fetchGpuList 方法中的分页处理部分
- async fetchGpuList() {
- this.isLoading = true;
- try {
- const params = {
- page: this.currentPage,
- page_size: this.pageSize,
- keyword: this.searchForm.name,
- tag_names: this.searchForm.id,
- create_time_start: this.searchForm.createTimeRange?.[0] || "",
- create_time_end: this.searchForm.createTimeRange?.[1] || "",
- update_time_start: this.searchForm.updateTimeRange?.[0] || "", // 新增
- update_time_end: this.searchForm.updateTimeRange?.[1] || "", // 新增
- processing_status: this.searchForm.processing_status || null,
- };
- const response = await axios.post(
- `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
- params,
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- if (response.status !== 200) return;
- // 更新数据和分页信息
- const { list, total, current_page, page_size } = response.data.data;
- this.gpuList = list.map((item) => {
- const nameParts = item.name.split(".");
- const processedItem = {
- ...item,
- name: nameParts[0],
- type: nameParts.length > 1 ? nameParts.pop() : "未知",
- };
- // 检查处理状态,如果是处理中且没有设置轮询,则开始轮询
- if (
- processedItem.processing_status === 1 &&
- !this.pollingTimers[processedItem.id]
- ) {
- this.startPolling(processedItem.id);
- }
- // 如果状态不是处理中,但存在轮询,则停止轮询
- else if (
- processedItem.processing_status !== 1 &&
- this.pollingTimers[processedItem.id]
- ) {
- this.stopPolling(processedItem.id);
- }
- return processedItem;
- });
- // 确保这些值都是数字类型
- this.total = parseInt(total);
- this.currentPage = parseInt(current_page);
- this.pageSize = parseInt(page_size);
- } catch (error) {
- console.error("获取列表数据失败:", error);
- this.$message.error("获取列表数据失败");
- } finally {
- this.isLoading = false;
- }
- },
- // 新增:开始轮询
- startPolling(id) {
- if (this.pollingTimers[id]) return; // 如果已经在轮询,则不重复设置
- this.pollingTimers[id] = setInterval(async () => {
- try {
- const response = await axios.post(
- `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
- {
- page: this.currentPage,
- page_size: this.pageSize,
- doc_type_id: this.selectedType || 36,
- keyword: this.searchForm.name,
- tag_names: this.searchForm.id,
- }
- );
- if (response.status === 200) {
- const item = response.data.data.list.find((item) => item.id === id);
- if (item && item.processing_status !== 1) {
- // 如果状态不再是"处理中",停止轮询
- this.stopPolling(id);
- await this.fetchGpuList(); // 刷新列表
- }
- }
- } catch (error) {
- console.error("轮询检查状态失败:", error);
- this.stopPolling(id); // 发生错误时停止轮询
- }
- }, 10000); // 每分钟检查一次
- },
- // 新增:停止轮询
- stopPolling(id) {
- if (this.pollingTimers[id]) {
- clearInterval(this.pollingTimers[id]);
- delete this.pollingTimers[id];
- }
- },
- /* // 修改分页处理方法
- handleSizeChange(val) {
- this.pageSize = val;
- this.currentPage = 1; // 切换每页数量时重置为第一页
- this.fetchGpuList(); // 移除防抖,直接调用
- }, */
- /* handleCurrentChange(val) {
- this.currentPage = val;
- this.fetchGpuList(); // 移除防抖,直接调用
- }, */
- /* 预览 */
- handlePreview(row) {
- console.log(row);
- let _this = this;
- let a = document.createElement("a");
- a.href = `#/infoList?id=${row.id}&type=${row.type.toLowerCase()}`; // 使用 hash
- a.target = "_blank";
- a.click();
- },
- // 处理名称点击
- async handleNameClick(row) {
- try {
- /* const res = await getDetail({ id: row.id })
- console.log('详情数据:', res) */
- this.$router.push({
- path: "/knowledge/middPage/index",
- query: {
- id: row.id,
- name: row.name,
- tag: JSON.stringify(row.tags),
- identifier: row.identifier,
- },
- });
- // 这里可以添加详情处理逻辑
- } catch (error) {
- this.$message.error("获取详情失败");
- }
- },
- // Tab切换处理
- handleClick(tab) {
- // 根据tab加载相应数据
- switch (tab.name) {
- case "second":
- this.loadSotaDetails();
- break;
- case "third":
- this.loadSotaSummary();
- break;
- }
- },
- // 加载SOTA详情数据
- async loadSotaDetails() {
- try {
- // 这里调用API获取SOTA详情数据
- const response = await getSotaDetails();
- this.sotaDetailsList = response.data;
- } catch (error) {
- /* this.$message.error("获取SOTA详情失败");
- console.error(error); */
- }
- },
- // 加载SOTA汇总表数据
- async loadSotaSummary() {
- try {
- // 这里调用API获取SOTA汇总数据
- const response = await getSotaSummary();
- this.sotaSummaryList = response.data;
- } catch (error) {
- /* this.$message.error("获取SOTA汇总数据失败");
- console.error(error); */
- }
- },
- },
- // 在组件销毁时清理所有轮询
- beforeDestroy() {
- // 清理轮询
- Object.keys(this.pollingTimers).forEach((id) => {
- this.stopPolling(id);
- });
- // 清空选择
- this.clearSelection();
- },
- };
- </script>
- <style scoped>
- .gpu-list {
- padding: 20px;
- }
- .filter-section {
- margin-bottom: 20px;
- }
- .ml-15 {
- margin-left: 15px;
- }
- .pagination {
- display: flex;
- justify-content: flex-end;
- margin-top: 15px;
- }
- </style>
|