昨天,已经完成了项目搭建已经完成首页轮播图。详情
今天,将完成首页博客内容展示,以及添加博客。
效果如下:
安装MongoDB
MongoDB安装比较简单,一步next即可。
安装方法:
https://www.runoob.com/mongodb/mongodb-window-install.html
运行服务端
- 项目进行之前,需要运行服务端,获取数据。
- 打开项目,直接npm run start:dev启动项目。
链接:https://pan.baidu.com/s/1b5s7er5hA6Z3OR6G8Cr-Xw?pwd=hb39
提取码:hb39
请求接口,获取博客
components/list.vue
<template>
<view>
<view v-if="blogList">
<u-swipe-action @click="del(item._id)" :options="options" v-for="item in blogList" :key="item._id">
<u-card :title="item.blogTitle" :sub-title="subTitle" :full="true" :border="false" :padding="20"
margin="10rpx" :footBorderTop="false" :footStyle="footStyle" @click="toDetail(item._id)">
<view class="" slot="body">
<view class="u-body-item u-flex u-border-bottom u-col-between u-p-t-0">
<view class="u-body-item-title u-font-sm u-line-3" style="width: 550rpx;">{{item.blogContext}}</view>
<image
src="https://img11.360buyimg.com/n7/jfs/t1/94448/29/2734/524808/5dd4cc16E990dfb6b/59c256f85a8c3757.jpg"
mode="aspectFill"></image>
</view>
</view>
<view class="" slot="foot">
<u-icon name="thumb-up-fill" size="32" color="#2BC3C8" label="30 点赞" labelSize="24"
class="u-m-r-30"></u-icon>
<u-icon name="eye-fill" size="32" color="#2BC3C8" label="30 浏览" labelSize="24"></u-icon>
</view>
</u-card>
</u-swipe-action>
</view>
<u-gap bgColor="#ededed" height="20"></u-gap>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
export default {
data() {
return {
footStyle: {
'paddingTop': '0rpx'
},
title: '素胚勾勒出青花,笔锋浓转淡,笔锋浓转淡',
subTitle: '2020-05-15',
content: '瓶身描绘的牡丹一如你初妆,冉冉檀香透过窗心事我了然,宣纸上走笔至此搁一半瓶身描绘的牡丹一如你初妆,冉冉檀香透过窗心事我了然,宣纸上走笔至此搁一半',
options: [
{
text: '删除',
style: {
backgroundColor: '#39c9c6'
}
}
]
}
},
computed: {
...mapState(['blogList'])
},
onLoad() {
},
methods: {
toDetail(_id) {
console.log(_id);
this.$router.push(`/pages/index/detail?_id=` + _id)
},
//删除博客
async del(_id){
const {data:res}=await this.$API.delBlog(_id)
if(res.code!==200) return this.$common.errorToShow('删除失败')
this.$common.successToShow('删除成功')
this.$store.dispatch('getBlogs')
}
},
}
</script>
<style lang="scss" scoped>
.u-card-wrap {
background-color: $u-bg-color;
padding: 1px;
}
.u-body-item {
font-size: 32rpx;
color: #333;
padding: 20rpx 10rpx;
}
.u-body-item image {
width: 120rpx;
flex: 0 0 120rpx;
height: 120rpx;
border-radius: 8rpx;
margin-left: 12rpx;
}
</style>
添加博客
pages目录下新建addblog文件夹
pages/addblog/addblog.vue
<template>
<view class="container">
<!-- 消息提示框 -->
<u-toast ref="uToast" />
<h1 class="text-center title">新增博客</h1>
<view class="context">
<u-form>
<u-form-item label="标题">
<u-input placeholder="请输入标题" v-model="blogForm.blogTitle"></u-input>
</u-form-item>
<u-form-item label="类型">
<view @click="show()">
<text v-if="blogForm.blogType" class="lighter" style="width: 550rpx;display: inline-block;">{{blogForm.blogType}}</text>
<text v-else class="lighter" style="width: 550rpx;display: inline-block;">请选择所属类型</text>
<u-icon name="arrow-right"></u-icon>
</view>
</u-form-item>
<u-form-item label="内容">
<textarea v-model="blogForm.blogContext" placeholder="请输入内容" focus />
</u-form-item>
<!-- <u-form-item label="上传图片">
<u-upload :action="action" :before-upload="beforeUpload"></u-upload>
</u-form-item> -->
</u-form>
<button class="getCaptcha" @click="addBlogs">提交</button>
</view>
<u-select v-model="showPop" mode="single-column" value-name="id" label-name="name" :list="blogCategory"
@confirm="confirmSelect"></u-select>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
export default {
data() {
return {
// action: 'http://localhost:3001/file',
// fileList: [{
// url: 'http://pics.sc.chinaz.com/files/pic/pic9/201912/hpic1886.jpg'
// }],
blogForm: {
blogTitle: '',
blogContext: '',
blogType: '',
typeId:'',
flag: false,
img: ''
},
showPop: false,
blogCategory: [{
id: 1,
name: '前端'
},
{
id: 2,
name: '后端'
},
{
id: 3,
name: '移动开发'
},
{
id: 4,
name: 'Python'
}
]
}
},
computed: {
...mapState(['id'])
},
methods: {
showToast() {
this.$refs.uToast.show({
title: '添加成功',
type: 'success',
url: '/pages/index/index'
})
},
addBlogs() {
this.$store.commit('setID')
const {
blogTitle,
blogContext,
blogType,
typeId
} = this.blogForm
try {
this.$store.dispatch('addBlogs', {
_id: this.id,
blogTitle,
blogContext,
blogType,
typeId
})
this.$router.replace('/pages/index/index')
} catch (e) {
console.log(e.message)
//TODO handle the exception
}
},
// 图片上传
// getImage(e) {
// console.log('lx', e);
// },
// async beforeUpload(index, list) {
// console.log('lx', list);
// },
confirmSelect(e) {
const {
value,
label
} = e[0]
this.blogForm.typeId = value
this.blogForm.blogType = label
console.log(this.blogForm.typeId);
},
show(){
this.showPop=true
}
}
}
</script>
<style lang="scss" scoped>
.container {
padding: 20rpx;
}
.getCaptcha {
background-color: #39cccc;
color: #ffffff;
border: none;
font-size: 30rpx;
margin: 60rpx 0;
&::after {
border: none;
}
}
</style>
修改pages/index/index.vue
<template>
<view class="">
<u-navbar :backTextStyle="backTextColor" backIconColor="#39CCCC" :background="background" :is-back="false">
<view class="u-nav-slot" slot="right" @click="toAddBlog">
<u-icon color="#fff" name="plus" size="50"></u-icon>
</view>
<!-- <view class="u-nav-slot" slot="left" @click="toAddBlog"><u-icon name="plus" size="50"></u-icon></view> -->
<view class="flex row-center" style="width: 100rpx;">
<u-icon name="scan" class="icon-md" color="#fff" size="50" @click="scanCode"></u-icon>
</view>
<view class="search-wrap" @click="toSearch">
<!-- 如果使用u-search组件,必须要给v-model绑定一个变量 -->
<u-search height="56" :showAction="false"></u-search>
</view>
</u-navbar>
<view class="">
<view class="toptem">
<u-swiper :list="swiper" border-radius="0" :effect3d="true"></u-swiper>
</view>
<u-gap bgColor="#ededed" height="20"></u-gap>
<!-- list -->
<list v-if="blogList.length>0"></list>
<view v-else class="flex-col col-center" style="margin-top: 200rpx;">
<text>没有博客哦,亲~</text>
<router-link to="/pages/addblog/addblog">去添加</router-link>
</view>
</view>
<u-back-top :scrollTop="scrollTop" :mode="modeTop" :bottom="bottomTop" :right="rightTop" :top="top"
:icon="iconTop" :custom-style="customStyle" :icon-style="iconStyleTop" :tips="tips"></u-back-top>
</view>
</template>
<script>
import list from '@/components/list';
import {
mapState
} from 'vuex'
export default {
components: {
list
},
data() {
return {
swiper: [],
background: {
'background-image': 'linear-gradient(45deg, #2BC3C8, #84E7B9)'
},
backTextColor: {
color: '#ffffff'
},
// top
scrollTop: 0,
modeTop: 'circle',
bottomTop: 200,
rightTop: 40,
top: 600,
iconTop: 'arrow-up',
iconStyleTop: {
color: '#ffffff',
fontSize: '30rpx'
},
customStyle: {
backgroundColor: '#39CCCC',
color: '#ffffff'
},
tips: '顶部',
token:null
};
},
onLoad() {
this.getSwiper();
this.$store.dispatch('getBlogs')
},
onShow() {
this.$store.dispatch('getBlogs')
},
computed: {
...mapState(['blogList'])
},
methods: {
resetToken(){
this.token=uni.getStorageSync('token')
},
toSearch() {
this.$common.navigateTo('/pages/index/search');
},
back() {
// 首页
uni.navigateBack({
delta: 2
});
},
toDetail() {
this.$common.navigateTo('/pages/index/detail');
},
// 回到顶部
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
toAddBlog() {
this.$router.push('/pages/addblog/addblog');
},
async getSwiper() {
const {
data: res
} = await this.$API.getSwiper();
console.log(res);
if (res.code !== 200) return;
this.swiper = res.data;
},
scanCode() {
// 允许从相机和相册扫码
uni.scanCode({
scanType: ["qrCode"],
success: (res) => {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
if (res.result) {
const val = res.result;
console.log(val)
// uni.navigateTo({
// url: val
// })
void plus.runtime.openWeb(val);
} else {
console.log('请重新扫描');
return false;
}
},
fail: (res) => {
console.log('未识别到二维码');
}
})
},
},
};
</script>
<style lang="scss">
.u-nav-slot {
margin-right: 20rpx;
}
.search-wrap {
margin: 0 30rpx 0 10rpx;
flex: 1;
}
.u-body-item {
font-size: 32rpx;
color: #333;
padding: 20rpx;
}
.u-body-item image {
width: 180rpx;
flex: 0 0 180rpx;
height: 150rpx;
border-radius: 6rpx;
margin-right: 12rpx;
}
.height {
height: 88rpx;
}
.toptem {
padding: 20rpx 0;
}
</style>