add scrollbars (#5)

* Delete src/App.vue

* Add files via upload

* Delete src/App.vue

* Add files via upload
This commit is contained in:
zaodonganqi
2025-02-12 11:36:20 +08:00
committed by GitHub
parent 34138fb94d
commit 0844216924

View File

@@ -3,12 +3,7 @@
<a-layout-content :style="{ padding: '20px 50px' }"> <a-layout-content :style="{ padding: '20px 50px' }">
<a-space direction="vertical" size="large" fill> <a-space direction="vertical" size="large" fill>
<a-space> <a-space>
<a-select <a-select v-model="selectedRepo" placeholder="选择脚本仓库" style="width: 320px" @change="fetchRepoData">
v-model="selectedRepo"
placeholder="选择脚本仓库"
style="width: 320px"
@change="fetchRepoData"
>
<a-option v-for="(repo, index) in repoOptions" :key="index" :value="repo.value"> <a-option v-for="(repo, index) in repoOptions" :key="index" :value="repo.value">
{{ repo.label }} {{ repo.label }}
</a-option> </a-option>
@@ -23,84 +18,91 @@
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="6" v-if="showTree(category)"> <a-col :span="6" v-if="showTree(category)">
<!-- 添加搜索框 --> <!-- 添加搜索框 -->
<a-input-search <a-input-search v-model="treeSearchText" placeholder="搜索下方目录" style="margin-bottom: 8px;" allow-clear
v-model="treeSearchText" @input="handleTreeSearch" @clear="handleTreeSearch" />
placeholder="搜索下方目录" <!-- 添加滚动容器 -->
style="margin-bottom: 8px;" <div
allow-clear style="height: calc(100vh - 200px); overflow-y: auto; overflow-x: hidden; border-right: 1px solid #e5e5e5;">
@input="handleTreeSearch" <a-tree :data="filteredTreeData[category.name] || getCategoryTree(category)"
@clear="handleTreeSearch" :defaultExpandedKeys="getExpandedKeys(category)"
/> @select="(selectedKeys, event) => handleTreeSelect(selectedKeys, event, category.name)">
<a-tree <template #extra="nodeData">
:data="filteredTreeData[category.name] || getCategoryTree(category)" <a-button type="text" size="mini"
:defaultExpandedKeys="getExpandedKeys(category)" style="position: absolute; right: 8px; top: 6px; color: #3370ff;"
@select="(selectedKeys, event) => handleTreeSelect(selectedKeys, event, category.name)" @click.stop="() => onTreeIconClick(nodeData)">
> 订阅
<template #extra="nodeData"> </a-button>
<a-button </template>
type="text" </a-tree>
size="mini" </div>
style="position: absolute; right: 8px; top: 6px; color: #3370ff;"
@click.stop="() => onTreeIconClick(nodeData)"
>
订阅
</a-button>
</template>
</a-tree>
</a-col> </a-col>
<a-col :span="showTree(category) ? 18 : 24"> <a-col :span="showTree(category) ? 18 : 24">
<a-space direction="vertical" size="medium" style="width: 100%;"> <a-space direction="vertical" size="medium" style="width: 100%;">
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="8"> <a-col :span="8">
<a-input v-model="searchConditions[category.name].name" placeholder="搜索名称" allow-clear @change="filterData(category.name)" /> <a-input v-model="searchConditions[category.name].name" placeholder="搜索名称" allow-clear
@change="filterData(category.name)" />
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-select v-model="searchConditions[category.name].author" placeholder="选择作者" style="width: 100%;" allow-clear @change="filterData(category.name)"> <a-select v-model="searchConditions[category.name].author" placeholder="选择作者" style="width: 100%;"
<a-option v-for="author in getUniqueAuthors(category)" :key="author" :value="author">{{ author }}</a-option> allow-clear @change="filterData(category.name)">
<a-option v-for="author in getUniqueAuthors(category)" :key="author" :value="author">{{ author
}}</a-option>
</a-select> </a-select>
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-select v-model="searchConditions[category.name].tags" placeholder="选择标签" style="width: 100%;" :filter-option="handleTagFilter" allow-clear @change="handleTagSelect(category.name)" multiple> <a-select v-model="searchConditions[category.name].tags" placeholder="选择标签" style="width: 100%;"
:filter-option="handleTagFilter" allow-clear @change="handleTagSelect(category.name)" multiple>
<a-option v-for="tag in getUniqueTags(category)" :key="tag" :value="tag">{{ tag }}</a-option> <a-option v-for="tag in getUniqueTags(category)" :key="tag" :value="tag">{{ tag }}</a-option>
</a-select> </a-select>
</a-col> </a-col>
</a-row> </a-row>
<a-table :columns="columns" :data="filteredData[category.name]" :pagination="{ pageSize, showPageSize: true }" @page-size-change="handlePageSizeChange"> <!-- 大盒子整体高度 calc(100vh - 200px) -->
<template #name="{ record }"> <div style="height: calc(100vh - 200px); display: flex; flex-direction: column; flex: 1">
<a-popover <!-- 表格内容区域占满剩余空间并启用滚动 -->
position="right" <div class="table-scroll-container" style="flex: 1; overflow-y: auto; overflow-x: hidden; padding-left: 16px;">
v-if="record.description" <!-- 表格内容 -->
:content="record.description" <a-table :columns="columns" :data="filteredData[category.name].slice((currentPage - 1) * pageSize, currentPage*pageSize)" :pagination="false"
:mouseEnterDelay="0.5" @page-size-change="handlePageSizeChange" :stickyHeader="true">
:mouseLeaveDelay="0.2" <template #name="{ record }">
> <a-popover position="right" v-if="record.description" :content="record.description"
<span :ellipsis="{ rows: 1, showTooltip: false }"> :mouseEnterDelay="0.5" :mouseLeaveDelay="0.2">
{{ record.name }} <span :ellipsis="{ rows: 1, showTooltip: false }">
</span> {{ record.name }}
</a-popover> </span>
<span v-else :ellipsis="{ rows: 1, showTooltip: true }"> </a-popover>
{{ record.name }} <span v-else :ellipsis="{ rows: 1, showTooltip: true }">
</span> {{ record.name }}
</template> </span>
<template #tags="{ record }"> </template>
<a-space :style="{ <template #tags="{ record }">
flexWrap: 'wrap', <a-space :style="{ flexWrap: 'wrap', rowGap: '8px' }">
rowGap: '8px' <a-tag v-for="tag in record.tags" :key="tag" :color="getTagColor(tag)"
}"> style="cursor: pointer" @click="handleTagClick(tag, category.name)">{{ tag }}</a-tag>
<a-tag v-for="tag in record.tags" :key="tag" :color="getTagColor(tag)" style="cursor: pointer" @click="handleTagClick(tag, category.name)">{{ tag }}</a-tag> </a-space>
</a-space> </template>
</template> <template #operations="{ record }">
<template #operations="{ record }"> <a-space>
<a-space> <a-button v-if="category.name !== 'pathing'" type="primary" size="mini"
<a-button v-if="category.name !== 'pathing'" type="primary" size="mini" @click="downloadScript(record)"> @click="downloadScript(record)">
订阅 订阅
</a-button> </a-button>
<a-button size="mini" @click="showDetails(record)"> <a-button size="mini" @click="showDetails(record)">
详情 详情
</a-button> </a-button>
</a-space> </a-space>
</template> </template>
</a-table> </a-table>
</div>
<!-- 分页器区域固定在大盒子底部 -->
<div style="margin-top: 10px;">
<a-pagination v-model:current="currentPage" :total="filteredData[category.name]?.length"
:pageSize="pageSize" :show-page-size="true" @change="handlePageChange" @page-size-change="handlePageSizeChange"
style="display: flex; align-items: center; justify-content: flex-end;" />
</div>
</div>
</a-space> </a-space>
</a-col> </a-col>
</a-row> </a-row>
@@ -111,13 +113,7 @@
</a-space> </a-space>
</a-layout-content> </a-layout-content>
<a-drawer <a-drawer :visible="drawerVisible" @cancel="closeDrawer" @ok="closeDrawer" unmountOnClose :width="480">
:visible="drawerVisible"
@cancel="closeDrawer"
@ok="closeDrawer"
unmountOnClose
:width="480"
>
<template #title> <template #title>
脚本详情 脚本详情
</template> </template>
@@ -125,13 +121,7 @@
</a-drawer> </a-drawer>
<!-- 添加加载模态框 --> <!-- 添加加载模态框 -->
<a-modal <a-modal :visible="loading" :footer="false" :closable="false" :mask-closable="false" :unmount-on-close="true">
:visible="loading"
:footer="false"
:closable="false"
:mask-closable="false"
:unmount-on-close="true"
>
<div style="text-align: center;"> <div style="text-align: center;">
<a-spin size="large" /> <a-spin size="large" />
<p style="margin-top: 16px;">正在加载仓库数据...</p> <p style="margin-top: 16px;">正在加载仓库数据...</p>
@@ -202,7 +192,7 @@ const filterTreeNodes = (nodes, searchText) => {
} }
if ( if (
isPinyinMatch(newNode.title, searchText) || isPinyinMatch(newNode.title, searchText) ||
(newNode.children && newNode.children.length > 0) (newNode.children && newNode.children.length > 0)
) { ) {
return newNode; return newNode;
@@ -241,10 +231,26 @@ const loading = ref(false);
// 添加新的响应式量 // 添加新的响应式量
const repoUpdateTime = ref(''); const repoUpdateTime = ref('');
const currentPage = ref(1);
const pageSize = ref(20); const pageSize = ref(20);
const handlePageChange = (newPage) => {
currentPage.value = newPage;
const tableContainer = document.querySelector('.table-scroll-container');
if (tableContainer) {
tableContainer.scrollTop = 0;
}
};
const handlePageSizeChange = (newPageSize) => { const handlePageSizeChange = (newPageSize) => {
pageSize.value = newPageSize; pageSize.value = newPageSize;
currentPage.value = 1;
const tableContainer = document.querySelector('.table-scroll-container');
if (tableContainer) {
tableContainer.scrollTop = 0;
}
}; };
const columns = [ const columns = [
@@ -255,7 +261,7 @@ const columns = [
ellipsis: true, ellipsis: true,
tooltip: false // 关闭默认的 tooltip tooltip: false // 关闭默认的 tooltip
}, },
{ title: '作者', dataIndex: 'author', width: 200 }, { title: '作者', dataIndex: 'author', width: 200 },
{ title: '版本', dataIndex: 'version', width: 100 }, { title: '版本', dataIndex: 'version', width: 100 },
{ title: '标签', dataIndex: 'tags', slotName: 'tags' }, { title: '标签', dataIndex: 'tags', slotName: 'tags' },
{ title: '操作', slotName: 'operations' }, { title: '操作', slotName: 'operations' },
@@ -499,8 +505,8 @@ const getCategoryTree = (category) => {
key: node.path, key: node.path,
children: Array.isArray(node.children) children: Array.isArray(node.children)
? node.children ? node.children
.map(child => buildTree(child, false)) .map(child => buildTree(child, false))
.filter(Boolean) .filter(Boolean)
: undefined, : undefined,
selectable: true selectable: true
}; };
@@ -568,7 +574,7 @@ const getCategoryDisplayName = (name) => {
}; };
const onTreeIconClick = (nodeData) => { const onTreeIconClick = (nodeData) => {
downloadScript({name: nodeData.title, path: nodeData.key}); downloadScript({ name: nodeData.title, path: nodeData.key });
}; };
// 修改日期格式化函数 // 修改日期格式化函数
@@ -653,4 +659,8 @@ onMounted(() => {
overflow: visible; overflow: visible;
text-overflow: clip; text-overflow: clip;
} }
.footer {
position: fixed;
}
</style> </style>