补充前台页面

This commit is contained in:
yumaojun03 2025-01-19 16:32:05 +08:00
parent 0952098885
commit c319804716
7 changed files with 230 additions and 8 deletions

View File

@ -489,3 +489,13 @@
{"level":"info","component":"http","time":"2025-01-19T14:50:39+08:00","caller":"config/http/http.go:152","message":"start graceful shutdown"}
{"level":"error","component":"http","time":"2025-01-19T14:50:39+08:00","caller":"config/http/http.go:146","message":"http: Server closed"}
{"level":"info","component":"server","time":"2025-01-19T14:50:39+08:00","caller":"ioc/server/server.go:115","message":"http service stop complete"}
{"level":"info","component":"gin_webframework","time":"2025-01-19T14:52:20+08:00","caller":"config/gin/framework.go:41","message":"enable gin recovery"}
{"level":"debug","time":"2025-01-19T14:52:20+08:00","caller":"token/impl/impl.go:39","message":"DefaultExpiredTTL: 3600"}
{"level":"info","component":"server","time":"2025-01-19T14:52:20+08:00","caller":"ioc/server/server.go:74","message":"loaded configs: [app.v1 trace.v1 log.v1 validator.v1 gin_webframework.v1 datasource.v1 grpc.v1 http.v1]"}
{"level":"info","component":"server","time":"2025-01-19T14:52:20+08:00","caller":"ioc/server/server.go:75","message":"loaded controllers: [token.v1 user.v1 blog.v1]"}
{"level":"info","component":"server","time":"2025-01-19T14:52:20+08:00","caller":"ioc/server/server.go:76","message":"loaded apis: [blogs.v1 tokens.v1]"}
{"level":"info","component":"server","time":"2025-01-19T14:52:20+08:00","caller":"ioc/server/server.go:77","message":"loaded defaults: []"}
{"level":"info","component":"http","time":"2025-01-19T14:52:20+08:00","caller":"config/http/http.go:144","message":"HTTP服务启动成功, 监听地址: 127.0.0.1:8080"}
{"level":"debug","time":"2025-01-19T15:29:38+08:00","caller":"token/api/api.go:57","message":"cookie domain: localhost"}
{"level":"debug","time":"2025-01-19T15:32:21+08:00","caller":"token/api/api.go:57","message":"cookie domain: localhost"}
{"level":"debug","time":"2025-01-19T15:57:25+08:00","caller":"token/api/api.go:57","message":"cookie domain: localhost"}

View File

@ -0,0 +1,39 @@
<template>
<a-space>
<a-button v-if="isLogin()" @click="logout">
<span style="margin-right: 12px;">
退出
</span>
<icon-export />
</a-button>
<a-button v-else @click="$router.push({ name: 'login' })">
<span>
登录
</span>
</a-button>
</a-space>
</template>
<script setup>
import { isLogin, token } from '@/stores/token'
import { useRouter } from 'vue-router';
const props = defineProps({
redirectToLogin: {
type: Boolean,
value: true,
}
})
const router = useRouter()
const logout = () => {
token.value = undefined
if (props.redirectToLogin) {
router.push({ name: 'login' })
}
}
</script>
<style lang="css" scoped></style>

View File

@ -73,11 +73,29 @@ const router = createRouter({
},
],
},
{
path: '/frontend',
name: 'frontend',
redirect: '/frontend/blog_list',
component: () => import('../views/frontend/FrontendLayout.vue'),
children: [
{
path: 'blog_list',
name: 'frontend_blog_list',
component: () => import('../views/frontend/blog/ListPage.vue'),
},
{
path: 'blog_detail',
name: 'frontend_blog_detail',
component: () => import('../views/frontend/blog/DetailPage.vue'),
},
],
},
],
})
router.beforeEach((to, from) => {
const whiteList = ['login']
const whiteList = ['login', 'frontend']
if (!whiteList.includes(to.name)) {
// 需要做权限判断
if (isLogin()) {

View File

@ -5,14 +5,14 @@
<div style="font-size: 16px;font-weight: 500;">
博客管理系统
</div>
<div>
<a-button @click="logout">
<span style="margin-right: 12px;">
退出登录
<a-space>
<a-button @click="$router.push({ name: 'frontend' })">
<span>
前台
</span>
<icon-export />
</a-button>
</div>
<LogoutButton></LogoutButton>
</a-space>
</a-layout-header>
<a-layout class="body">
<!-- 侧边栏 -->
@ -51,7 +51,7 @@
import { token } from '@/stores/token';
import { useRouter } from 'vue-router';
import { systemConfig } from '@/stores/system';
import LogoutButton from '@/components/LogoutButton.vue'
const router = useRouter()

View File

@ -0,0 +1,85 @@
<template>
<a-layout class="layout">
<!-- 顶部导航 -->
<a-layout-header class="header">
<div style="font-size: 16px;font-weight: 500;">
博客管理系统
</div>
<div>
<LogoutButton :redirectToLogin="false"></LogoutButton>
</div>
</a-layout-header>
<a-layout-content class="content">
<div class="left">
</div>
<div class="center">
<RouterView></RouterView>
</div>
<div class="right">
</div>
</a-layout-content>
</a-layout>
</template>
<script setup>
import LogoutButton from '@/components/LogoutButton.vue'
</script>
<style lang="css" scoped>
.layout {
height: 100%;
}
.header {
height: 60px;
box-sizing: border-box;
min-height: 60px;
max-height: 60px;
padding: 12px;
display: flex;
justify-content: space-between;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
border-bottom: 1px solid var(--color-border);
background-color: var(--color-bg-2);
align-items: center;
}
.left {
width: 300px;
border-right: 1px solid var(--color-border);
height: calc(100vh - 60xp);
overflow: auto;
}
.right {
width: 300px;
border-left: 1px solid var(--color-border);
height: calc(100vh - 60xp);
overflow: auto;
}
.content {
margin-top: 60px;
height: calc(100vh - 60xp);
display: flex;
justify-content: center;
overflow: auto;
}
.center {
width: 100%;
height: calc(100vh - 60xp);
overflow: auto;
}
.center::-webkit-scrollbar {
display: none;
/* Chrome, Safari 和 Opera */
}
</style>

View File

@ -0,0 +1,11 @@
<template>
<div>
文章详情
</div>
</template>
<script setup>
</script>
<style lang="css" scoped></style>

View File

@ -0,0 +1,59 @@
<template>
<a-list :loading="queryBlogLoadding" class="list-demo-action-layout" :bordered="false" :data="data.items"
:pagination-props="{ pageSize: blogQueryRequest.page_size, total: data.total }">
<template #item="{ item }">
<a-list-item class="list-demo-item" action-layout="vertical">
<template #actions>
<span><icon-heart />83</span>
<span><icon-star />{{ item.id }}</span>
<span><icon-message />Reply</span>
</template>
<template #extra>
<div className="image-area">
<img @click="$router.push({ name: 'frontend_blog_detail', query: { id: item.id } })" alt="arco-design"
width="200" height="120"
src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/1f61854a849a076318ed527c8fca1bbf.png~tplv-uwbnlip3yd-webp.webp" />
</div>
</template>
<a-list-item-meta :title="item.title" :description="item.summary">
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue';
import { QUERY_BLOG } from '@/api/blog'
onMounted(() => {
queryData()
})
// API
const blogQueryRequest = reactive({
keywords: '',
category: '',
page_size: 10,
page_number: 1,
})
// , reactive, ({data...})
// ref data.value = {}
const data = ref({
items: [],
total: 0
})
//
const queryBlogLoadding = ref(false)
const queryData = async () => {
try {
queryBlogLoadding.value = true
data.value = await QUERY_BLOG(blogQueryRequest)
} finally {
queryBlogLoadding.value = false
}
}
</script>
<style lang="css" scoped></style>