support resize for FileDetail.vue

This commit is contained in:
Timi
2025-07-11 00:27:59 +08:00
parent 4e0a32701e
commit 54b2d27b81
3 changed files with 219 additions and 29 deletions

View File

@ -1,6 +1,10 @@
<template>
<div class="file-detail" v-if="repositoryStore.value && repositoryStore.value.branchList">
<div class="left">
<split-pane
class="file-detail"
v-if="repositoryStore.value && repositoryStore.value.branchList"
split="vertical"
>
<pane class="left" initialSize="25%" minSize="10%">
<t-select class="branch" v-model="branch" label="分支:" :borderless="true">
<t-option
v-for="item in repositoryStore.value.branchList"
@ -16,6 +20,7 @@
:data="treeItems"
:keys="treeMap"
:line="true"
:label="treeLabel"
:activable="true"
:transition="false"
:active-multiple="false"
@ -32,9 +37,9 @@
</template>
</t-tree>
</div>
</div>
<div class="right">
<div class="header">
</pane>
<pane class="right" minSize="50%">
<div class="header bg-white">
<div class="clone-label">克隆地址</div>
<t-select class="clone-type" v-model="cloneType" borderless>
<t-option
@ -98,8 +103,8 @@
<div v-else class="viewer not-support">
<div class="content">不支持预览</div>
</div>
</div>
</div>
</pane>
</split-pane>
</template>
<script lang="ts" setup>
import { Icon, MarkdownView, Prismjs, PrismjsType, PrismjsViewer, Toolkit } from "timi-web";
@ -108,6 +113,7 @@ import RepositoryAPI from "@/api/RepositoryAPI";
import { File, FileType } from "@/types/Repository";
import { useRepositoryStore } from "@/store/repository.ts";
import useClipboard from "vue-clipboard3";
import SplitPane, { Pane } from "@marsio/vue-split-pane";
const router = useRouter();
const { toClipboard } = useClipboard();
@ -147,20 +153,22 @@ watch(branch, async () => {
}
}
});
const treeLoad: TreeProps["load"] = node => {
return new Promise((resolve) => {
Toolkit.async(async () => {
const file = node.data;
const result = await RepositoryAPI.listFile(
repositoryStore.value!.name,
branch.value,
`/${file.path}`
);
result.forEach((item) => item.children = item.type === FileType.DIRECTORY);
resolve(result);
});
});
const treeLabel: TreeProps["label"] = (_h, node) => node.data.name;
const treeLoad: TreeProps["load"] = async (node) => {
const file = node.data;
const result = await RepositoryAPI.listFile(
repositoryStore.value!.name,
branch.value,
`/${file.path}`
);
if (result.length === 1 && result[0].type === FileType.DIRECTORY) {
const deep = result[0];
file.name = `${file.name}/${deep.name}`;
file.path = `${file.path}/${deep.name}`;
return await treeLoad!(node);
}
result.forEach((item) => item.children = item.type === FileType.DIRECTORY);
return result;
};
// ---------- 克隆地址 ----------
@ -302,17 +310,26 @@ const onClickViewer = async () => {
<style lang="less" scoped>
.file-detail {
// 100% 可视高度 - 上下外边距 - 边框 - 顶部 - 菜单 - 底部
height: calc(100vh - 128px * 2 - 2px - 50px - 50px - 94px);
display: flex;
overflow: unset;
min-height: 520px;
:deep(.vue-splitpane-resizer) {
opacity: 1;
background: var(--tui-light-gray) padding-box;
}
.left {
width: 16rem;
z-index: 4;
width: 100%;
height: 100% !important;
display: flex;
position: relative;
flex-direction: column;
.branch {
top: calc(50px + 49px);
z-index: 1;
position: sticky;
border-bottom: var(--tui-border);
:deep(.t-select-input--borderless) {
@ -336,8 +353,8 @@ const onClickViewer = async () => {
}
.tree-container {
height: 100%;
overflow: auto;
top: calc(50px + 49px + 30px);
position: sticky;
.tree {
@ -360,7 +377,7 @@ const onClickViewer = async () => {
.right {
width: calc(100% - 16rem);
display: flex;
border-left: var(--tui-border);
max-height: 100% !important;
flex-direction: column;
.header {
@ -397,7 +414,11 @@ const onClickViewer = async () => {
}
.tabs {
top: calc(50px + 49px + 30px);
position: sticky;
z-index: 9;
border-top: var(--tui-border);
border-bottom: var(--tui-border);
:deep(.t-tabs__nav-container.t-tabs__nav--card::after) {
background: var(--tui-light-gray);