Compare commits

..

6 Commits

Author SHA1 Message Date
f5c10bf892 fix loss style for async load 2025-07-22 15:25:44 +08:00
74aaa8f806 async import page component 2025-07-22 14:42:40 +08:00
e63494061b add About page 2025-07-22 14:42:08 +08:00
5df064e80a fix RepositoryLog.vue load more 2025-07-22 00:41:00 +08:00
4d723758df bigger layout for FileDetail 2025-07-15 17:16:59 +08:00
cef8121008 fix page list for RepositoryList.vue 2025-07-15 16:53:31 +08:00
7 changed files with 138 additions and 43 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<b-e-flower-fall class="background" /> <b-e-flower-fall class="background" />
<root-layout v-if="ready" class="diselect" icp="粤ICP备2025368555号-1" domain="imyeyu.com" author="夜雨"> <root-layout v-if="ready" class="root-layout diselect" icp="粤ICP备2025368555号-1" domain="imyeyu.com" author="夜雨">
<router-view /> <router-view />
</root-layout> </root-layout>
<popup /> <popup />
@ -10,16 +10,39 @@
<script lang="ts" setup> <script lang="ts" setup>
import { BEFlowerFall, Popup } from "timi-web"; import { BEFlowerFall, Popup } from "timi-web";
import { RootLayout, UserProfilePopup } from "timi-tdesign-pc"; import { RootLayout, UserProfilePopup } from "timi-tdesign-pc";
import { SettingMapper } from "../../timi-web";
const route = useRoute();
const ready = ref(false); const ready = ref(false);
onMounted(async () => { onMounted(async () => {
await SettingMapper.loadSetting({
key: "GIT_ABOUT_ARTICLE"
});
ready.value = true; ready.value = true;
}); });
// ---------- 文件详情页更宽的布局 ----------
const inFileDetail = ref(false);
const largeWidth = computed(() => inFileDetail.value ? "1600px" : "1200px");
const width = computed(() => inFileDetail.value ? "1200px" : "900px");
watch(route, () => inFileDetail.value = route.name === "FileDetail");
</script> </script>
<style lang="less"> <style lang="less">
.background { .background {
background: url("@/assets/img/main.png") fixed right bottom; background: url("@/assets/img/main.png") fixed right bottom;
} }
@media screen and (max-width: 2560px) {
.root-layout {
width: v-bind(largeWidth) !important;
}
}
@media screen and (max-width: 1920px) {
.root-layout {
width: v-bind(width) !important;
}
}
</style> </style>

View File

@ -21,6 +21,7 @@
</template> </template>
<t-menu-item to="/" :value="Menu.LIST">仓库列表</t-menu-item> <t-menu-item to="/" :value="Menu.LIST">仓库列表</t-menu-item>
<t-menu-item to="/log" :value="Menu.LOG">最近推送</t-menu-item> <t-menu-item to="/log" :value="Menu.LOG">最近推送</t-menu-item>
<t-menu-item to="/about" :value="Menu.ABOUT">关于</t-menu-item>
<template #operations> <template #operations>
<login-menu /> <login-menu />
</template> </template>
@ -44,14 +45,16 @@ onMounted(async () => owner.value = await UserAPI.view(1));
enum Menu { enum Menu {
LIST = "LIST", LIST = "LIST",
LOG = "LOG" LOG = "LOG",
ABOUT = "ABOUT"
} }
const regexMenu: { const regexMenu: {
[key: string]: Menu [key: string]: Menu
} = { } = {
"RepositoryList": Menu.LIST, "RepositoryList": Menu.LIST,
"RepositoryLog": Menu.LOG "RepositoryLog": Menu.LOG,
"About": Menu.ABOUT
}; };
const route = useRoute(); const route = useRoute();
@ -76,7 +79,7 @@ onMounted(() => syncMenuRouter(route.name as string));
.header { .header {
top: 0; top: 0;
z-index: 1; z-index: 3;
position: sticky; position: sticky;
background: rgba(231, 234, 239, .8); background: rgba(231, 234, 239, .8);
border-bottom: var(--tui-border); border-bottom: var(--tui-border);

View File

@ -1,8 +1,7 @@
import { createRouter, createWebHistory } from "vue-router";
import repository from "./repository";
import IndexLayout from "@/layout/IndexLayout.vue"; import IndexLayout from "@/layout/IndexLayout.vue";
import RepositoryList from "@/views/index/RepositoryList.vue"; import RepositoryList from "@/views/index/RepositoryList.vue";
import RepositoryLog from "@/views/index/RepositoryLog.vue";
import {createRouter, createWebHistory} from "vue-router";
import repository from "./repository";
export default createRouter({ export default createRouter({
history: createWebHistory("/"), history: createWebHistory("/"),
@ -21,7 +20,12 @@ export default createRouter({
{ {
path: "/log", path: "/log",
name: "RepositoryLog", name: "RepositoryLog",
component: RepositoryLog component: () => import("@/views/index/RepositoryLog.vue")
},
{
path: "/about",
name: "About",
component: () => import("@/views/index/About.vue")
} }
] ]
}, },

View File

@ -1,13 +1,4 @@
import RepositoryLayout from "@/layout/RepositoryLayout.vue"; import RepositoryLayout from "@/layout/RepositoryLayout.vue";
import CommitLog from "@/views/repository/CommitLog.vue";
import FileDetail from "@/views/repository/FileDetail.vue";
import IssueDetail from "@/views/repository/IssueDetail.vue";
import IssueEdit from "@/views/repository/IssueEdit.vue";
import IssueList from "@/views/repository/IssueList.vue";
import MergeDetail from "@/views/repository/MergeDetail.vue";
import MergeEdit from "@/views/repository/MergeEdit.vue";
import MergeList from "@/views/repository/MergeList.vue";
import ReleaseList from "@/views/repository/ReleaseList.vue";
export default { export default {
path: "/:repository", path: "/:repository",
@ -17,7 +8,7 @@ export default {
{ {
path: ":branch", path: ":branch",
name: "FileDetail", name: "FileDetail",
component: FileDetail, component: () => import("@/views/repository/FileDetail.vue"),
meta: { meta: {
keepAlive: true keepAlive: true
} }
@ -25,47 +16,42 @@ export default {
{ {
path: "commits", path: "commits",
name: "CommitLog", name: "CommitLog",
component: CommitLog component: () => import("@/views/repository/CommitLog.vue")
}, },
{ {
path: "issues", path: "issues",
name: "IssueList", name: "IssueList",
component: IssueList component: () => import("@/views/repository/IssueList.vue")
},
{
path: "issues",
name: "IssueList",
component: IssueList
}, },
{ {
path: "issues/edit/:id?", path: "issues/edit/:id?",
name: "IssueEdit", name: "IssueEdit",
component: IssueEdit component: () => import("@/views/repository/IssueEdit.vue")
}, },
{ {
path: "issues/:id", path: "issues/:id",
name: "IssueDetail", name: "IssueDetail",
component: IssueDetail component: () => import("@/views/repository/IssueDetail.vue")
}, },
{ {
path: "merges", path: "merges",
name: "MergeList", name: "MergeList",
component: MergeList component: () => import("@/views/repository/MergeList.vue")
}, },
{ {
path: "merges/edit/:id?", path: "merges/edit/:id?",
name: "MergeEdit", name: "MergeEdit",
component: MergeEdit component: () => import("@/views/repository/MergeEdit.vue")
}, },
{ {
path: "merges/:id", path: "merges/:id",
name: "MergeDetail", name: "MergeDetail",
component: MergeDetail component: () => import("@/views/repository/MergeDetail.vue")
}, },
{ {
path: "releases", path: "releases",
name: "ReleaseList", name: "ReleaseList",
component: ReleaseList component: () => import("@/views/repository/ReleaseList.vue")
} }
] ]
}; };

33
src/views/index/About.vue Normal file
View File

@ -0,0 +1,33 @@
<template>
<article v-if="article" class="about">
<markdown-view class="content" :content="article.data" />
<comment
v-if="SettingMapper.is(SettingKey.ENABLE_COMMENT) && article.showComment"
:bizType="CommentBizType.ARTICLE"
:bizId="article.id!"
:titleStickyOffset="80"
:canComment="article.canComment"
/>
</article>
</template>
<script lang="ts" setup>
import { ArticleAPI, ArticleView, CommentBizType, MarkdownView, SettingKey, SettingMapper } from "timi-web";
import { Comment } from "timi-tdesign-pc";
const article = ref<ArticleView<any>>();
onMounted(async () => {
article.value = await ArticleAPI.view(SettingMapper.getValue("GIT_ABOUT_ARTICLE") as unknown as number);
});
</script>
<style lang="less" scoped>
.about {
.content {
width: calc(100% - 4rem);
padding: 1rem 2rem;
}
}
</style>

View File

@ -22,13 +22,16 @@
</t-list> </t-list>
<footer class="footer"> <footer class="footer">
<t-pagination <t-pagination
class="pagination" class="pages"
v-if="pageResult"
:total="pageResult.total" :total="pageResult.total"
:pageSize="16" :pageSize="16"
:showPageSize="false" :showPageSize="false"
:current="currentPage"
:onCurrentChange="onPageChangeEvent"
> >
<template #totalContent> <template #totalContent>
<div class="total" v-text="`共 ${pageResult.total} 个项目`"></div> <div style="flex: 1" v-text="`共 ${pageResult.total} 篇文章`"></div>
</template> </template>
</t-pagination> </t-pagination>
</footer> </footer>
@ -37,24 +40,62 @@
<script lang="ts" setup> <script lang="ts" setup>
import RepositoryAPI from "@/api/RepositoryAPI"; import RepositoryAPI from "@/api/RepositoryAPI";
import { Repository } from "@/types/Repository"; import { Repository } from "@/types/Repository";
import { Icon, Loading, Page, PageResult, Time } from "timi-web"; import { Icon, Loading, Page, PageResult, Time, Toolkit } from "timi-web";
const page = ref<Page>({ const router = useRouter();
const route = useRoute();
const isLoading = ref(false);
const currentPage = computed(() => page.index + 1);
const page = reactive<Page>({
index: 0, index: 0,
size: 12 size: 16
}); });
const pageResult = reactive<PageResult<Repository>>({ const pageResult = reactive<PageResult<Repository>>({
total: 0, total: 0,
list: [] list: []
}); });
const isLoading = ref(false); // 获取列表
onMounted(async () => { const fetchList = Toolkit.debounce(async () => {
isLoading.value = true; isLoading.value = true;
const result = await RepositoryAPI.page(page.value); const result = await RepositoryAPI.page(page);
pageResult.total = result.total; pageResult.total = result.total;
pageResult.list = result.list; pageResult.list = result.list;
isLoading.value = false; isLoading.value = false;
}); });
// 监听路由分页
watch(
() => route.query.p,
async (newP) => {
const pNum = Number(newP);
if (Number.isInteger(pNum) && 0 <= pNum) {
page.index = pNum;
await fetchList();
} else {
// 参数无效时重置为第一页
await router.push({
path: route.path,
query: {
...route.query,
p: 0
}
});
}
},
{ immediate: true }
);
function onPageChangeEvent(current: number) {
const newIndex = current - 1;
router.push({
path: route.path,
query: {
...route.query,
p: newIndex
}
});
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -3,7 +3,7 @@
<push-log-timeline :items="list" /> <push-log-timeline :items="list" />
<div class="bottom"> <div class="bottom">
<loading :showOn="isLoading" /> <loading :showOn="isLoading" />
<empty-tips :showOn="isFinished && !isLoading" /> <empty-tips v-if="isFinished && !isLoading" />
<t-button v-show="!isFinished && !isLoading" @click="doFetchEvent">加载更多</t-button> <t-button v-show="!isFinished && !isLoading" @click="doFetchEvent">加载更多</t-button>
</div> </div>
</div> </div>
@ -40,5 +40,10 @@ onMounted(doFetchEvent);
.repository-log { .repository-log {
width: calc(100% - 4rem); width: calc(100% - 4rem);
padding: 1rem 2rem; padding: 1rem 2rem;
.bottom {
display: flex;
justify-content: center;
}
} }
</style> </style>