|
@@ -1,61 +1,1040 @@
|
|
<template>
|
|
<template>
|
|
- <div class="project-search">
|
|
|
|
|
|
+ <div class="project-search">
|
|
|
|
+ <div class="file-categories">
|
|
|
|
+ <el-button type="primary" @click="createNewFolder">
|
|
|
|
+ <i class="el-icon-plus"></i> 新建目录
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-tree
|
|
|
|
+ :data="folders"
|
|
|
|
+ :props="defaultProps"
|
|
|
|
+ @node-click="handleNodeClick"
|
|
|
|
+ ref="folderTree"
|
|
|
|
+ :default-expanded-keys="['0']"
|
|
|
|
+ node-key="id"
|
|
|
|
+ highlight-current
|
|
|
|
+ >
|
|
|
|
+ <span class="custom-tree-node" slot-scope="{ node, data }">
|
|
|
|
+ <span>
|
|
|
|
+ <i class="el-icon-folder"></i>
|
|
|
|
+ {{ node.label }}
|
|
|
|
+ </span>
|
|
|
|
+ <span class="file-count">{{ data.document_count }} files</span>
|
|
|
|
+ <span class="folder-actions" v-if="data.id !== '0'">
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="编辑"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <i class="el-icon-edit" @click.stop="editFolder(data)"></i>
|
|
|
|
+ </el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="删除"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <i class="el-icon-delete" @click.stop="deleteFolder(data.id)"></i>
|
|
|
|
+ </el-tooltip>
|
|
|
|
+ </span>
|
|
|
|
+ </span>
|
|
|
|
+ </el-tree>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="right">
|
|
<dataSearch @bindSetQuery="setQuery"></dataSearch>
|
|
<dataSearch @bindSetQuery="setQuery"></dataSearch>
|
|
- <dataList
|
|
|
|
|
|
+ <!-- <dataList
|
|
:queryForm="queryForm"
|
|
:queryForm="queryForm"
|
|
:allowEdit="checkAuth('/document/update')"
|
|
:allowEdit="checkAuth('/document/update')"
|
|
:allowDelete="checkAuth('/document/delete')"
|
|
:allowDelete="checkAuth('/document/delete')"
|
|
- ></dataList>
|
|
|
|
|
|
+ ></dataList> -->
|
|
|
|
+ <div
|
|
|
|
+ class="data-list"
|
|
|
|
+ v-loading="loading"
|
|
|
|
+ element-loading-text="加载中..."
|
|
|
|
+ >
|
|
|
|
+ <div class="batch-actions" style="margin: 10px 0">
|
|
|
|
+ <el-button
|
|
|
|
+ type="primary"
|
|
|
|
+ @click="batchAnalysis"
|
|
|
|
+ :disabled="!selectedRows.length"
|
|
|
|
+ >批量解析</el-button
|
|
|
|
+ >
|
|
|
|
+ </div>
|
|
|
|
+ <el-table
|
|
|
|
+ ref="dataTable"
|
|
|
|
+ :data="dataList"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ header-row-class-name="headerBg"
|
|
|
|
+ empty-text="没有模板信息"
|
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
|
+ @sort-change="handleSortChange"
|
|
|
|
+ >
|
|
|
|
+ <el-table-column type="selection" width="55"></el-table-column>
|
|
|
|
+ <el-table-column prop="id" label="ID" align="center" width="80" />
|
|
|
|
+ <el-table-column
|
|
|
|
+ prop="name"
|
|
|
|
+ label="文件名称"
|
|
|
|
+ align="center"
|
|
|
|
+ sortable="custom"
|
|
|
|
+ >
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <span>{{ scope.row.name }}</span>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column prop="type" label="文件类型" align="center" />
|
|
|
|
+ <el-table-column prop="chunk_num" label="分块数" align="center" />
|
|
|
|
+ <el-table-column
|
|
|
|
+ prop="create_time"
|
|
|
|
+ label="上传时间"
|
|
|
|
+ align="center"
|
|
|
|
+ sortable="custom"
|
|
|
|
+ />
|
|
|
|
+ <el-table-column prop="run" label="解析状态" align="center">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <div v-if="scope.row.run == 0">未解析</div>
|
|
|
|
+ <div v-if="scope.row.run == 1">解析中</div>
|
|
|
|
+ <div v-if="scope.row.run == 3">成功</div>
|
|
|
|
+ <div v-if="scope.row.run == 4">失败</div>
|
|
|
|
+ <div v-if="scope.row.run == 5">待处理</div>
|
|
|
|
+ <div v-if="scope.row.run == 6">文件异常</div>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="操作" align="center" width="330">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <div class="btns">
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="预览"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ type="text"
|
|
|
|
+ size="small"
|
|
|
|
+ circle
|
|
|
|
+ icon="el-icon-view"
|
|
|
|
+ v-if="checkAuth('/document/update')"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ @click="getName(scope.row)"
|
|
|
|
+ ></el-button
|
|
|
|
+ ></el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ :content="
|
|
|
|
+ scope.row.run === 1 || scope.row.run === 5
|
|
|
|
+ ? '解析中'
|
|
|
|
+ : '解析'
|
|
|
|
+ "
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ v-if="scope.row.run !== 1 && scope.row.run !== 5"
|
|
|
|
+ type="text"
|
|
|
|
+ icon="el-icon-caret-right"
|
|
|
|
+ circle
|
|
|
|
+ @click="analysis(scope.row)"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ >
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ v-else
|
|
|
|
+ type="text"
|
|
|
|
+ icon="el-icon-loading"
|
|
|
|
+ circle
|
|
|
|
+ :disabled="true"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ >
|
|
|
|
+ </el-button>
|
|
|
|
+ </el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="解析方法"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ type="text"
|
|
|
|
+ size="small"
|
|
|
|
+ circle
|
|
|
|
+ icon="el-icon-tickets"
|
|
|
|
+ v-if="checkAuth('/document/update')"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ @click="Analytical(scope.row)"
|
|
|
|
+ ></el-button
|
|
|
|
+ ></el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="修改文件名"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ type="text"
|
|
|
|
+ size="small"
|
|
|
|
+ circle
|
|
|
|
+ icon="el-icon-edit"
|
|
|
|
+ v-if="checkAuth('/document/update')"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ @click="btnEdit(scope.row)"
|
|
|
|
+ ></el-button
|
|
|
|
+ ></el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="下载"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ type="text"
|
|
|
|
+ size="small"
|
|
|
|
+ circle
|
|
|
|
+ icon="el-icon-download"
|
|
|
|
+ @click="btnDown(scope.row)"
|
|
|
|
+ :loading="scope.row.downloading"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ ></el-button
|
|
|
|
+ ></el-tooltip>
|
|
|
|
+ <el-tooltip
|
|
|
|
+ class="item"
|
|
|
|
+ effect="dark"
|
|
|
|
+ content="删除"
|
|
|
|
+ placement="top"
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ type="text"
|
|
|
|
+ size="small"
|
|
|
|
+ circle
|
|
|
|
+ icon="el-icon-delete"
|
|
|
|
+ v-if="checkAuth('/document/delete')"
|
|
|
|
+ @click="btnDelete(scope.row.id)"
|
|
|
|
+ style="font-size: 20px"
|
|
|
|
+ ></el-button
|
|
|
|
+ ></el-tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+
|
|
|
|
+ <div class="page-info">
|
|
|
|
+ <el-pagination
|
|
|
|
+ :currentPage="queryForm.page"
|
|
|
|
+ :page-size="queryForm.pageSize"
|
|
|
|
+ :total="recordCount"
|
|
|
|
+ :page-count="pageTotal"
|
|
|
|
+ :page-sizes="[10, 20, 50, 100]"
|
|
|
|
+ background
|
|
|
|
+ layout="sizes, prev, pager, next"
|
|
|
|
+ @current-change="ChangePage"
|
|
|
|
+ @size-change="handleSizeChange"
|
|
|
|
+ >
|
|
|
|
+ </el-pagination>
|
|
|
|
+ </div>
|
|
|
|
+ <el-dialog
|
|
|
|
+ title="修改名称"
|
|
|
|
+ :visible.sync="dialogVisible"
|
|
|
|
+ width="30%"
|
|
|
|
+ :before-close="handleClose"
|
|
|
|
+ >
|
|
|
|
+ <el-form :model="wordForm" ref="wordRef" :rules="wordRules">
|
|
|
|
+ <el-form-item label="文件名称:" prop="new_name">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model="wordForm.new_name"
|
|
|
|
+ placeholder="请输入文件名称"
|
|
|
|
+ ></el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
|
+ <el-button @click="handleClose">取 消</el-button>
|
|
|
|
+ <el-button type="primary" @click="submitBuck">确 定</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ </el-dialog>
|
|
|
|
+
|
|
|
|
+ <!-- 解析方法 -->
|
|
|
|
+ <el-dialog
|
|
|
|
+ title="解析方法"
|
|
|
|
+ :visible.sync="anaDialogVisible"
|
|
|
|
+ width="30%"
|
|
|
|
+ :before-close="handleAnalClose"
|
|
|
|
+ >
|
|
|
|
+ <el-form
|
|
|
|
+ :model="analForm"
|
|
|
|
+ ref="analRef"
|
|
|
|
+ label-position="top"
|
|
|
|
+ :rules="analRules"
|
|
|
|
+ >
|
|
|
|
+ <el-form-item label="页码范围:" prop="new_name">
|
|
|
|
+ <el-input-number
|
|
|
|
+ v-model="analForm.start_page"
|
|
|
|
+ controls-position="right"
|
|
|
|
+ :min="1"
|
|
|
|
+ ></el-input-number>
|
|
|
|
+ <el-input-number
|
|
|
|
+ v-model="analForm.end_page"
|
|
|
|
+ controls-position="right"
|
|
|
|
+ :min="1"
|
|
|
|
+ style="margin-left: 10px"
|
|
|
|
+ ></el-input-number>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item label="块token数">
|
|
|
|
+ <div class="block">
|
|
|
|
+ <el-slider v-model="analForm.token_num" :max="2048" show-input>
|
|
|
|
+ </el-slider>
|
|
|
|
+ </div>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
|
+ <el-button @click="handleAnalClose">取 消</el-button>
|
|
|
|
+ <el-button type="primary" @click="submitAnal">确 定</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ <el-dialog
|
|
|
|
+ title="新建目录"
|
|
|
|
+ :visible.sync="newFolderDialogVisible"
|
|
|
|
+ width="30%"
|
|
|
|
+ >
|
|
|
|
+ <el-form
|
|
|
|
+ :model="newFolderForm"
|
|
|
|
+ :rules="newFolderRules"
|
|
|
|
+ ref="newFolderFormRef"
|
|
|
|
+ >
|
|
|
|
+ <el-form-item label="文件夹名称" prop="name">
|
|
|
|
+ <el-input v-model="newFolderForm.name"></el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
|
+ <el-button @click="newFolderDialogVisible = false">取 消</el-button>
|
|
|
|
+ <el-button type="primary" @click="submitNewFolder">确 定</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
- </template>
|
|
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
- import { mapGetters } from "vuex";
|
|
|
|
- import { dataSearch, dataList } from "./components";
|
|
|
|
- export default {
|
|
|
|
- components: {
|
|
|
|
- dataSearch,
|
|
|
|
- dataList,
|
|
|
|
- },
|
|
|
|
- computed: {
|
|
|
|
- ...mapGetters(["roleInfo", "authList"]),
|
|
|
|
- },
|
|
|
|
-
|
|
|
|
- data() {
|
|
|
|
- return {
|
|
|
|
- queryForm: {
|
|
|
|
- page: 1,
|
|
|
|
- pageSize: 10,
|
|
|
|
- bucket_id:''
|
|
|
|
|
|
+import { mapGetters } from "vuex";
|
|
|
|
+import { dataSearch, dataList } from "./components";
|
|
|
|
+import {
|
|
|
|
+ getBucketContents,
|
|
|
|
+ deleteFile,
|
|
|
|
+ nameGetUrl,
|
|
|
|
+ renameFile,
|
|
|
|
+ analysis,
|
|
|
|
+ batchAnalysis,
|
|
|
|
+ getRunStatus,
|
|
|
|
+ insertType,
|
|
|
|
+ updateType,
|
|
|
|
+ selectTypeList,
|
|
|
|
+ deleteType,
|
|
|
|
+ Info,
|
|
|
|
+} from "@/api/knowledge";
|
|
|
|
+export default {
|
|
|
|
+ components: {
|
|
|
|
+ dataSearch,
|
|
|
|
+ dataList,
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ ...mapGetters(["roleInfo", "authList"]),
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ queryForm: {
|
|
|
|
+ page: 1,
|
|
|
|
+ pageSize: 10,
|
|
|
|
+ bucket_id: "",
|
|
|
|
+ folder: "0",
|
|
|
|
+ },
|
|
|
|
+ typeForm: {
|
|
|
|
+ page: 1,
|
|
|
|
+ pageSize: 10,
|
|
|
|
+ kb_id: "",
|
|
|
|
+ },
|
|
|
|
+ folders: [{ id: "0", name: "All", document_count: 0 }],
|
|
|
|
+ defaultProps: {
|
|
|
|
+ children: "children",
|
|
|
|
+ label: "name",
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // dataList 组件的数据
|
|
|
|
+ loading: false,
|
|
|
|
+ dialogVisible: false,
|
|
|
|
+ currentDataId: 0,
|
|
|
|
+ recordCount: 0,
|
|
|
|
+ pageTotal: 1,
|
|
|
|
+ dataList: [],
|
|
|
|
+ currentData: {},
|
|
|
|
+ wordForm: {
|
|
|
|
+ document_id: "",
|
|
|
|
+ new_name: "",
|
|
|
|
+ },
|
|
|
|
+ wordRules: {
|
|
|
|
+ new_name: [
|
|
|
|
+ { required: true, message: "请输入文件名称", trigger: "blur" },
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ anaDialogVisible: false,
|
|
|
|
+ analForm: {
|
|
|
|
+ start_page: 1,
|
|
|
|
+ end_page: 10000,
|
|
|
|
+ token_num: 0,
|
|
|
|
+ },
|
|
|
|
+ analRules: {},
|
|
|
|
+ selectedRows: [],
|
|
|
|
+ sortColumn: "",
|
|
|
|
+ sortOrder: "",
|
|
|
|
+ analysisStatusCheckers: {},
|
|
|
|
+ newFolderDialogVisible: false,
|
|
|
|
+ newFolderForm: {
|
|
|
|
+ name: "",
|
|
|
|
+ kb_id: "",
|
|
|
|
+ status: 5,
|
|
|
|
+ },
|
|
|
|
+ newFolderRules: {
|
|
|
|
+ name: [
|
|
|
|
+ { required: true, message: "请输入文件夹名称", trigger: "blur" },
|
|
|
|
+ ],
|
|
|
|
+ },
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ this.queryForm.bucket_id = this.$route.query.id;
|
|
|
|
+ this.typeForm.kb_id = this.$route.query.id;
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ this.initializeTree();
|
|
|
|
+ });
|
|
|
|
+ this.typeList();
|
|
|
|
+ this.search();
|
|
|
|
+ },
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ Object.values(this.analysisStatusCheckers).forEach(clearTimeout);
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ editFolder(folder) {
|
|
|
|
+ this.$prompt("请输入新的文件夹名称", "编辑文件夹", {
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ inputValue: folder.name,
|
|
|
|
+ inputValidator: (value) => {
|
|
|
|
+ if (!value) {
|
|
|
|
+ return "文件夹名称不能为空";
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
},
|
|
},
|
|
- };
|
|
|
|
|
|
+ })
|
|
|
|
+ .then(({ value }) => {
|
|
|
|
+ if (value !== folder.name) {
|
|
|
|
+ const updatedFolder = { ...folder, name: value };
|
|
|
|
+ updateType(updatedFolder)
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ this.$message.success("更新文件夹成功");
|
|
|
|
+ this.typeList(); // 刷新文件夹列表
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("更新文件夹失败");
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("更新文件夹时出错:", error);
|
|
|
|
+ this.$message.error("更新文件夹时出错");
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch(() => {
|
|
|
|
+ // 用户取消操作,不做任何处理
|
|
|
|
+ });
|
|
},
|
|
},
|
|
- mounted(){
|
|
|
|
- this.queryForm.bucket_id=this.$route.query.id
|
|
|
|
|
|
+
|
|
|
|
+ deleteFolder(folderId) {
|
|
|
|
+ this.$confirm("确定要删除该文件夹吗?删除后无法恢复。", "警告", {
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ type: "warning",
|
|
|
|
+ })
|
|
|
|
+ .then(() => {
|
|
|
|
+ deleteType({ id: folderId })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ this.$message.success("删除文件夹成功");
|
|
|
|
+ this.typeList(); // 刷新文件夹列表
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("删除文件夹失败");
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("删除文件夹时出错:", error);
|
|
|
|
+ this.$message.error("删除文件夹时出错");
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+ .catch(() => {
|
|
|
|
+ // 用户取消删除操作,不做任何处理
|
|
|
|
+ });
|
|
},
|
|
},
|
|
- methods: {
|
|
|
|
- checkAuth(path) {
|
|
|
|
- if (this.roleInfo.is_admin == 1) {
|
|
|
|
- return true;
|
|
|
|
|
|
+
|
|
|
|
+ typeList() {
|
|
|
|
+ this.loading = true;
|
|
|
|
+ selectTypeList(this.typeForm)
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ const folderList = res.data.dataList.map((folder) => ({
|
|
|
|
+ ...folder,
|
|
|
|
+ document_count: folder.file_count || 0, // 确保 document_count 存在
|
|
|
|
+ }));
|
|
|
|
+
|
|
|
|
+ this.folders = [
|
|
|
|
+ {
|
|
|
|
+ id: "0",
|
|
|
|
+ name: "All",
|
|
|
|
+ document_count: folderList.reduce(
|
|
|
|
+ (sum, folder) => sum + folder.document_count,
|
|
|
|
+ 0
|
|
|
|
+ ),
|
|
|
|
+ },
|
|
|
|
+ ...folderList.filter((folder) => folder.id !== "0"),
|
|
|
|
+ ];
|
|
|
|
+ this.initializeTree();
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("获取文件夹列表失败");
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("获取文件夹列表时出错:", error);
|
|
|
|
+ this.$message.error("获取文件夹列表时出错");
|
|
|
|
+ })
|
|
|
|
+ .finally(() => {
|
|
|
|
+ this.loading = false;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ initializeTree() {
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ if (this.$refs.folderTree) {
|
|
|
|
+ this.$refs.folderTree.setCurrentKey("0");
|
|
|
|
+ this.handleNodeClick(this.folders[0]);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ createNewFolder() {
|
|
|
|
+ this.newFolderDialogVisible = true;
|
|
|
|
+ },
|
|
|
|
+ /* 新增 */
|
|
|
|
+ submitNewFolder() {
|
|
|
|
+ this.$refs.newFolderFormRef.validate((valid) => {
|
|
|
|
+ if (valid) {
|
|
|
|
+ this.newFolderForm.kb_id = this.$route.query.id;
|
|
|
|
+ insertType(this.newFolderForm).then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ this.$message.success("创建文件夹成功");
|
|
|
|
+ this.newFolderDialogVisible = false;
|
|
|
|
+ this.$refs.newFolderFormRef.resetFields();
|
|
|
|
+ this.typeList(); // Refresh folder list
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("创建文件夹失败");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
}
|
|
}
|
|
- /* let auth=this.authList.filter(o=>o.type==999 && o.path==path);
|
|
|
|
- if(auth.length>0){
|
|
|
|
- return true;
|
|
|
|
- } */
|
|
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ initializeTree() {
|
|
|
|
+ this.$refs.folderTree.setCurrentKey("0");
|
|
|
|
+ this.handleNodeClick(this.folders[0]); // Trigger initial search for "All"
|
|
|
|
+ },
|
|
|
|
+ checkAuth(path) {
|
|
|
|
+ if (this.roleInfo.is_admin === 1) {
|
|
return true;
|
|
return true;
|
|
- },
|
|
|
|
-
|
|
|
|
- setQuery(e) {
|
|
|
|
- this.queryForm = e;
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
+ return this.authList.some(
|
|
|
|
+ (auth) => auth.type === 999 && auth.path === path
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ setQuery(e) {
|
|
|
|
+ this.queryForm = e;
|
|
|
|
+ },
|
|
|
|
+ handleNodeClick(data) {
|
|
|
|
+ this.queryForm.folder = data.id;
|
|
|
|
+ this.queryForm.page = 1; // Reset to first page when changing folder
|
|
|
|
+ this.search();
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ /*列表事件 */
|
|
|
|
+ /* 排序 */
|
|
|
|
+ handleSortChange({ prop, order }) {
|
|
|
|
+ this.sortColumn = prop;
|
|
|
|
+ this.sortOrder = order;
|
|
|
|
+ this.sortData();
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ sortData() {
|
|
|
|
+ const { sortColumn, sortOrder } = this;
|
|
|
|
+ if (!sortColumn || !sortOrder) {
|
|
|
|
+ this.search(); // Reset to original order
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.dataList.sort((a, b) => {
|
|
|
|
+ let comparison = 0;
|
|
|
|
+ if (sortColumn === "name") {
|
|
|
|
+ comparison = a.name.localeCompare(b.name, "zh-CN");
|
|
|
|
+ } else if (sortColumn === "create_time") {
|
|
|
|
+ comparison = new Date(a.create_time) - new Date(b.create_time);
|
|
|
|
+ }
|
|
|
|
+ return sortOrder === "ascending" ? comparison : -comparison;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ /* 批量解析 */
|
|
|
|
+ handleSelectionChange(val) {
|
|
|
|
+ this.selectedRows = val;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ batchAnalysis() {
|
|
|
|
+ const selectedIds = this.selectedRows.map((row) => row.id);
|
|
|
|
+ if (selectedIds.length === 0) {
|
|
|
|
+ this.$message.warning("请选择要解析的文件");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.$confirm("确定要批量解析选中的文件吗?", "提示", {
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ type: "warning",
|
|
|
|
+ })
|
|
|
|
+ .then(() => {
|
|
|
|
+ this.loading = true;
|
|
|
|
+ batchAnalysis({ ids: JSON.stringify(selectedIds) })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ this.$message.success("批量解析任务已提交");
|
|
|
|
+ this.updateAnalysisStatus(selectedIds);
|
|
|
|
+ this.clearSelection();
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("批量解析请求失败");
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("批量解析错误:", error);
|
|
|
|
+ this.$message.error("批量解析过程中出现错误");
|
|
|
|
+ })
|
|
|
|
+ .finally(() => {
|
|
|
|
+ this.loading = false;
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+ .catch(() => {
|
|
|
|
+ // 取消操作
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ updateAnalysisStatus(ids) {
|
|
|
|
+ this.dataList.forEach((row) => {
|
|
|
|
+ if (ids.includes(row.id)) {
|
|
|
|
+ row.run = 1; // 设置状态为"解析中"
|
|
|
|
+ this.startAnalysisStatusChecker(row);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ clearSelection() {
|
|
|
|
+ this.$refs.dataTable.clearSelection();
|
|
|
|
+ this.selectedRows = [];
|
|
},
|
|
},
|
|
- };
|
|
|
|
- </script>
|
|
|
|
|
|
+
|
|
|
|
+ /* 跳转页面 */
|
|
|
|
+ getName(e) {
|
|
|
|
+ /* this.$router.push({
|
|
|
|
+ path: "/knowledge/category/infoList",
|
|
|
|
+ query: { id: e.id, type: e.type },
|
|
|
|
+ }); */
|
|
|
|
+ let _this = this;
|
|
|
|
+ let a = document.createElement("a");
|
|
|
|
+ a.href = `#/infoList?id=${e.id}&type=${e.type}`; // 使用 hash
|
|
|
|
+ a.target = "_blank";
|
|
|
|
+ a.click();
|
|
|
|
+ },
|
|
|
|
+ /* 解析 */
|
|
|
|
+ analysis(row) {
|
|
|
|
+ if (row.run === 1 || row.run === 5) return;
|
|
|
|
+
|
|
|
|
+ this.$set(row, "run", 1);
|
|
|
|
+
|
|
|
|
+ analysis({
|
|
|
|
+ document_id: row.id,
|
|
|
|
+ start_page: row.start_page || 0,
|
|
|
|
+ end_page: row.end_page || 1000,
|
|
|
|
+ max_tokens: row.token_num,
|
|
|
|
+ })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ this.startAnalysisStatusChecker(row);
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("解析请求失败");
|
|
|
|
+ this.$set(row, "run", 0);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("解析错误:", error);
|
|
|
|
+ this.$message.error("解析过程中出现错误");
|
|
|
|
+ this.$set(row, "run", 0);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ startAnalysisStatusChecker(row) {
|
|
|
|
+ // 如果已经有一个检查器在运行,先停止它
|
|
|
|
+ if (this.analysisStatusCheckers[row.id]) {
|
|
|
|
+ clearTimeout(this.analysisStatusCheckers[row.id]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const checkStatus = () => {
|
|
|
|
+ getRunStatus({ document_id: row.id })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ const newStatus = Number(res.data.run);
|
|
|
|
+ this.$set(row, "run", newStatus);
|
|
|
|
+
|
|
|
|
+ if (newStatus === 3) {
|
|
|
|
+ this.$message.success("解析成功");
|
|
|
|
+ delete this.analysisStatusCheckers[row.id];
|
|
|
|
+ } else if (newStatus === 4) {
|
|
|
|
+ this.$message.error("解析失败");
|
|
|
|
+ delete this.analysisStatusCheckers[row.id];
|
|
|
|
+ } else if (newStatus === 1 || newStatus === 5) {
|
|
|
|
+ // 继续检查
|
|
|
|
+ this.analysisStatusCheckers[row.id] = setTimeout(
|
|
|
|
+ checkStatus,
|
|
|
|
+ 5000 + Math.random() * 5000
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("获取解析状态失败");
|
|
|
|
+ this.$set(row, "run", 0);
|
|
|
|
+ delete this.analysisStatusCheckers[row.id];
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("获取解析状态错误:", error);
|
|
|
|
+ this.$message.error("获取解析状态时出现错误");
|
|
|
|
+ this.$set(row, "run", 0);
|
|
|
|
+ delete this.analysisStatusCheckers[row.id];
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // 立即开始第一次检查
|
|
|
|
+ checkStatus();
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ handleAnalClose() {
|
|
|
|
+ this.anaDialogVisible = false;
|
|
|
|
+ },
|
|
|
|
+ /* 确认 */
|
|
|
|
+ submitAnal() {
|
|
|
|
+ this.dataList.map((el) => {
|
|
|
|
+ if (this.analForm.id == el.id) {
|
|
|
|
+ el.start_page = this.analForm.start_page;
|
|
|
|
+ el.end_page = this.analForm.end_page;
|
|
|
|
+ el.token_num = this.analForm.token_num;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ this.anaDialogVisible = false;
|
|
|
|
+ },
|
|
|
|
+ /* 解析方法 */
|
|
|
|
+ Analytical(e) {
|
|
|
|
+ this.analForm.id = e.id;
|
|
|
|
+ this.analForm.token_num = e.token_num;
|
|
|
|
+ this.anaDialogVisible = true;
|
|
|
|
+ },
|
|
|
|
+ editWidth() {
|
|
|
|
+ if (this.allowDelete && this.allowEdit) {
|
|
|
|
+ return 200;
|
|
|
|
+ }
|
|
|
|
+ if (this.allowDelete || this.allowEdit) {
|
|
|
|
+ return 120;
|
|
|
|
+ }
|
|
|
|
+ return 100;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ onFocusVal(e) {
|
|
|
|
+ let _this = this;
|
|
|
|
+ _this.currentDataId = e.target.dataset.id;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ onChangeVal(e) {
|
|
|
|
+ let _this = this;
|
|
|
|
+ let par = {
|
|
|
|
+ id: _this.currentDataId,
|
|
|
|
+ val: e,
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ btnDelete(e) {
|
|
|
|
+ let _this = this;
|
|
|
|
+ let par = {
|
|
|
|
+ document_id: e,
|
|
|
|
+ };
|
|
|
|
+ _this
|
|
|
|
+ .$confirm("您是否确认删除该记录?", "提示", {
|
|
|
|
+ confirmButtonText: "确认",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ type: "warning",
|
|
|
|
+ })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ deleteFile(par).then((res) => {
|
|
|
|
+ if (res.status !== 200) return;
|
|
|
|
+ _this.$message.success(res.data);
|
|
|
|
+ _this.search();
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+ .catch(() => {});
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ searchData() {
|
|
|
|
+ let _this = this;
|
|
|
|
+ _this.dialogVisible = false;
|
|
|
|
+ _this.search();
|
|
|
|
+ },
|
|
|
|
+ /* 关闭 */
|
|
|
|
+ handleClose(done) {
|
|
|
|
+ done();
|
|
|
|
+ },
|
|
|
|
+ /* 修改文件名 */
|
|
|
|
+ btnEdit(e) {
|
|
|
|
+ this.wordForm.new_name = e.name;
|
|
|
|
+ this.wordForm.document_id = e.id;
|
|
|
|
+ this.dialogVisible = true;
|
|
|
|
+ },
|
|
|
|
+ /* 提交 */
|
|
|
|
+ submitBuck() {
|
|
|
|
+ this.$refs.wordRef.validate((valid) => {
|
|
|
|
+ if (valid) {
|
|
|
|
+ renameFile(this.wordForm).then((res) => {
|
|
|
|
+ if (res.status !== 200) return;
|
|
|
|
+ this.search();
|
|
|
|
+ this.dialogVisible = false;
|
|
|
|
+ this.wordForm = {
|
|
|
|
+ new_name: "",
|
|
|
|
+ document_id: "",
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error("请填写文档名称");
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ //下载
|
|
|
|
+ btnDown(e) {
|
|
|
|
+ // Set downloading flag for this specific row
|
|
|
|
+ this.$set(e, "downloading", true);
|
|
|
|
+
|
|
|
|
+ nameGetUrl({
|
|
|
|
+ document_id: e.id,
|
|
|
|
+ })
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status !== 200) {
|
|
|
|
+ this.$message.error("获取下载链接失败");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return fetch(res.data.url);
|
|
|
|
+ })
|
|
|
|
+ .then((response) => response.blob())
|
|
|
|
+ .then((blob) => {
|
|
|
|
+ const url = window.URL.createObjectURL(blob);
|
|
|
|
+ const link = document.createElement("a");
|
|
|
|
+ link.href = url;
|
|
|
|
+ link.download = e.name;
|
|
|
|
+ document.body.appendChild(link);
|
|
|
|
+ link.click();
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ document.body.removeChild(link);
|
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
|
+ }, 100);
|
|
|
|
+ })
|
|
|
|
+ .catch((error) => {
|
|
|
|
+ console.error("下载出错:", error);
|
|
|
|
+ this.$message.error("下载失败,请稍后重试");
|
|
|
|
+ })
|
|
|
|
+ .finally(() => {
|
|
|
|
+ // Reset downloading flag when done
|
|
|
|
+ this.$set(e, "downloading", false);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ handleClose() {
|
|
|
|
+ let _this = this;
|
|
|
|
+ _this.currentData = {};
|
|
|
|
+ _this.dialogVisible = false;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ //搜索
|
|
|
|
+ search() {
|
|
|
|
+ let _this = this;
|
|
|
|
+ _this.loading = true;
|
|
|
|
+ getBucketContents(_this.queryForm)
|
|
|
|
+ .then((res) => {
|
|
|
|
+ if (res.status !== 200) return;
|
|
|
|
+ _this.dataList = res.data.documents.map((el) => ({
|
|
|
|
+ ...el,
|
|
|
|
+ token_num: 256,
|
|
|
|
+ start_page: _this.analForm.start_page,
|
|
|
|
+ end_page: _this.analForm.end_page,
|
|
|
|
+ }));
|
|
|
|
+ _this.pageTotal = res.data.pagination.total_count;
|
|
|
|
+ _this.recordCount = res.data.pagination.total_count;
|
|
|
|
+ _this.queryForm.pageSize = res.data.pagination.total_size;
|
|
|
|
+ _this.loading = false;
|
|
|
|
+
|
|
|
|
+ // Update file count for the selected folder
|
|
|
|
+ if (_this.queryForm.folder === "0") {
|
|
|
|
+ // If "All" is selected, update its document_count
|
|
|
|
+ _this.folders[0].document_count = _this.recordCount;
|
|
|
|
+ } else {
|
|
|
|
+ const selectedFolder = _this.folders.find(
|
|
|
|
+ (f) => f.id === _this.queryForm.folder
|
|
|
|
+ );
|
|
|
|
+ if (selectedFolder) {
|
|
|
|
+ selectedFolder.document_count = _this.recordCount;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Initialize the analysis status for each row
|
|
|
|
+ _this.dataList.forEach((row) => {
|
|
|
|
+ if (row.run === 1) {
|
|
|
|
+ _this.startAnalysisStatusChecker(row);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ })
|
|
|
|
+ .catch(() => {
|
|
|
|
+ _this.loading = false;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ //修改分页
|
|
|
|
+ ChangePage(e) {
|
|
|
|
+ let _this = this;
|
|
|
|
+ _this.queryForm.page = e;
|
|
|
|
+ _this.search();
|
|
|
|
+ },
|
|
|
|
+ handleSizeChange(val) {
|
|
|
|
+ this.queryForm.pageSize = val;
|
|
|
|
+ this.queryForm.page = 1; // Reset to first page when changing page size
|
|
|
|
+ this.search();
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+</script>
|
|
|
|
|
|
- <style lang="scss">
|
|
|
|
- .project-search {
|
|
|
|
- padding: 30px;
|
|
|
|
- font-size: 12px;
|
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
+.project-search {
|
|
|
|
+ display: flex;
|
|
|
|
+ height: calc(100vh - 100px); // 假设顶部导航栏高度为60px
|
|
|
|
+ background-color: #f9fafb;
|
|
|
|
+ .custom-tree-node {
|
|
|
|
+ width: 100%;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ padding: 8px 0;
|
|
|
|
+ position: relative;
|
|
|
|
+
|
|
|
|
+ .el-icon-folder {
|
|
|
|
+ color: #409eff;
|
|
|
|
+ margin-right: 8px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .file-count {
|
|
|
|
+ color: #909399;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+
|
|
|
|
+ padding: 2px 6px;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ transition: opacity 0.3s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .folder-actions {
|
|
|
|
+ position: absolute;
|
|
|
|
+ right: 0;
|
|
|
|
+ top: 50%;
|
|
|
|
+ transform: translateY(-50%);
|
|
|
|
+ display: none;
|
|
|
|
+
|
|
|
|
+ padding-left: 10px;
|
|
|
|
+
|
|
|
|
+ i {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ margin-left: 8px;
|
|
|
|
+ color: #606266;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ color: #409eff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ &:hover {
|
|
|
|
+ .file-count {
|
|
|
|
+ opacity: 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .folder-actions {
|
|
|
|
+ display: inline-block;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .el-tree-node__content:hover {
|
|
|
|
+ background-color: #f5f7fa;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .el-tree-node__content:hover {
|
|
|
|
+ background-color: #f5f7fa;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .file-categories {
|
|
|
|
+ flex: 0 0 280px;
|
|
|
|
+ padding: 20px;
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
+ box-shadow: 2px 0 10px rgba(0, 0, 0, 0.05);
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+
|
|
|
|
+ .el-button {
|
|
|
|
+ width: 100%;
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .el-tree {
|
|
|
|
+ background-color: transparent;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .right {
|
|
|
|
+ flex: 1;
|
|
|
|
+ padding: 20px;
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .custom-tree-node {
|
|
|
|
+ width: 100%;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ padding: 8px 0;
|
|
|
|
+
|
|
|
|
+ .el-icon-folder {
|
|
|
|
+ color: #409eff;
|
|
|
|
+ margin-right: 8px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .file-count {
|
|
|
|
+ color: #909399;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ background-color: #f0f2f5;
|
|
|
|
+ padding: 2px 6px;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- </style>
|
|
|
|
|
|
+}
|
|
|
|
+@import "./components/dataList.scss";
|
|
|
|
+</style>
|
|
|
|
|