Compare commits
6 Commits
70111ce18b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f5c10bf892 | |||
| 74aaa8f806 | |||
| e63494061b | |||
| 5df064e80a | |||
| 4d723758df | |||
| cef8121008 |
27
src/Root.vue
27
src/Root.vue
@ -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>
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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("/"),
|
||||||
@ -16,12 +15,17 @@ export default createRouter({
|
|||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
name: "RepositoryList",
|
name: "RepositoryList",
|
||||||
component: RepositoryList
|
component: RepositoryList
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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")
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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
33
src/views/index/About.vue
Normal 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>
|
||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user