发表帖子页面
新建文件site/pages/topic/create.vue,完整代码如下:
<template>
<section>
<my-nav />
<section class="section">
<div class="container">
<div class="field">
<label class="label">标题</label>
<div class="control">
<input
v-model="form.title"
class="input"
type="text"
placeholder="请输入帖子标题"
/>
</div>
</div>
<div class="field">
<label class="label">内容</label>
<div class="control">
<textarea
v-model="form.content"
class="textarea has-fixed-size"
rows="10"
placeholder="请输入帖子内容"
></textarea>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link" @click="createTopic">发表</button>
</div>
</div>
</div>
</section>
<my-footer />
</section>
</template>
<script>
import MyNav from '~/components/MyNav';
import MyFooter from '~/components/MyFooter';
export default {
components: {
MyNav,
MyFooter,
},
data() {
return {
form: {
title: '',
content: '',
},
};
},
methods: {
async createTopic() {
try {
const resp = await this.$axios.post('/api/topic/add', this.form);
console.log('发表成功', resp);
this.$router.push('/topic/' + resp.id); // 发表成功后跳转到帖子详情页
} catch (err) {
alert(err.message || err);
}
},
},
};
</script>
帖子详情页面
新建文件site/pages/topic/_id.vue,完整代码如下:
<template>
<section>
<my-nav />
<section class="section">
<div class="container">
<article>
<div class="title">
{{ topic.title }}
<span class="meta"
>By {{topic.user.nickname}} @ {{topic.createTime}}</span
>
</div>
<pre class="content">{{ topic.content }}</pre>
</article>
</div>
</section>
<my-footer />
</section>
</template>
<script>
import MyNav from '~/components/MyNav';
import MyFooter from '~/components/MyFooter';
export default {
components: {
MyNav,
MyFooter,
},
async asyncData({ params, $axios }) {
try {
const topicId = params.id; // 从动态路由参数中获取帖子id
const topic = await $axios.get('/api/topic/' + topicId);
return {
topic: topic,
};
} catch (err) {
console.log(err);
}
},
};
</script>
<style scoped>
article .title {
font-weight: bold;
font-size: 15px;
border-bottom: 2px #f7f8fb dashed;
padding-bottom: 10px;
}
article .title .meta {
font-weight: normal;
font-size: 12px;
color: #3b8070;
}
article .content {
margin-top: 10px;
}
</style>
启动前端页面服务之后,访问路径/topic/1就可以看到页面效果(路径中的1是你刚刚发表的帖子编号,请按实际情况填写)
帖子列表页面
新建文件site/pages/topics/_page.vue,完整代码如下:
<template>
<section>
<my-nav />
<section class="section">
<div class="container">
<ul class="topics">
<li class="topic" v-for="topic in topics" :key="topic.id">
<a :href="'/topic/' + topic.id"
>{{topic.title}}<span class="meta">@{{topic.createTime}}</span></a
>
</li>
</ul>
<nav class="pagination" role="navigation" aria-label="pagination">
<a
class="pagination-previous"
:href="page > 1 ? '/topics/' + (page - 1) : 'javascript:void(0)'"
>上一页</a
>
<a
class="pagination-next"
:href="page < maxPage ? '/topics/' + (page + 1) : 'javascript:void(0)'"
>下一页</a
>
</nav>
</div>
</section>
<my-footer />
</section>
</template>
<script>
import MyNav from '~/components/MyNav';
import MyFooter from '~/components/MyFooter';
export default {
components: {
MyNav,
MyFooter,
},
async asyncData({ params, $axios }) {
try {
const page = params.page || 1; // 从动态路由参数中获取页码,如果没获取到默认认为是第一页
const resp = await $axios.get('/api/topic/list/' + page);
// 计算帖子的最大页码
const maxPage =
resp.totalCount % 20 > 0
? parseInt(resp.totalCount / 20) + 1
: resp.totalCount / 20;
return {
topics: resp.topics,
page: parseInt(page), // 当前页码
maxPage: maxPage, // 最大页码
};
} catch (err) {
console.log(err);
}
},
};
</script>
<style scoped>
.topics .topic {
padding: 10px 0px;
border-bottom: 1px solid #f7f8fb;
}
.topics .topic .meta {
font-weight: normal;
font-size: 12px;
color: #3b8070;
float: right;
}
.pagination {
margin-top: 20px;
}
</style>
启动前端页面服务之后,访问路径/topics/1就可以看到页面效果
本实例中我们完成了整个帖子模块的功能。下面我们看下本实例完整源码的目录结构:
.
├── server
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ ├── topic_controller.go
│ ├── topic_model.go
│ ├── topic_service.go
│ ├── user_controller.go
│ ├── user_model.go
│ └── user_service.go
└── site
├── README.md
├── assets
│ └── README.md
├── components
│ ├── Logo.vue
│ ├── MyFooter.vue
│ ├── MyNav.vue
│ └── README.md
├── jsconfig.json
├── layouts
│ ├── README.md
│ └── default.vue
├── middleware
│ └── README.md
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
│ ├── README.md
│ ├── index.vue
│ ├── topic
│ │ ├── _id.vue
│ │ └── create.vue
│ ├── topics
│ │ └── _page.vue
│ └── user
│ ├── login.vue
│ └── reg.vue
├── plugins
│ ├── README.md
│ └── axios.js
├── static
│ ├── README.md
│ └── favicon.ico
└── store
└── README.md