十次方专属社交平台前端系统开发 网站前台-吐槽与问答

58 篇文章 1 订阅

学习目标:

完成吐槽列表与详细页
完成发吐槽与评论功能,掌握富文本编辑器的使用
完成问答频道功能
掌握DataURL和阿里云OSS

1.吐槽列表与详细页

1.1吐槽列表页

1.1.1吐槽列表页数据渲染

吐槽列表页已经构建,我们现在来实现数据的渲染

(1)easyMock模拟数据

URL: spit/spit/search/{page}/{size}

Method: GET

{
  "code": 20000,
  "flag": true,
  "message": "@string",
  "data|10": [{
    "id": "@string",
    "content": "我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~我要吐槽~",
    "publishtime": "@datetime",
    "thumbup": "@integer(60, 100)"
  }]

}
(2)api目录下创建spit.js

import request from '@/utils/request'
const api_group = 'spit'
const api_name = 'spit'
export default {
  page(page,size) {   
    return request({
      url: `/${api_group}/${api_name}/search/${page}/${size}`,
      method: 'get'
    })
  }
}

(3)修改pages/spit/index.vue

<template>
      <!--两列布局-->
    <div class="wrapper tag-item">
        <div class="fl left-list">
            <div class="tc-data-list">
    <div class="tc-list">
            <ul class="detail-list">            
                    <li v-for="(item,index) in items" :key="index" class="qa-item">
                        <div class="fl record">
                            <div class="number">
                                <div class="border useful">
                                    <p class="usenum"><a href="#" class="zan"><i class="fa fa-thumbs-up " aria-hidden="true"></i></a></p>
                                    <p class="zannum">
                                        {{item.thumbup}}
                                    </p>
                                </div>
                                <div class="border answer">
                                    <a href="#" class="star"><i class="fa fa-star-o" aria-hidden="true"></i></a>
                                </div>
                            </div>
                        </div>
                        <div class="info">
                            <p class="text">
                                <a href="~/assets/spit-detail.html" target="_blank">
                                    {{item.content}}
                                </a>
                            </p>
                            <div class="other">
                                <div class="fl date">
                                    <span>{{item.publishtime}}</span>
                                </div>
                                <div class="fr remark">
                                    <a href="#" data-toggle="modal" data-target="#shareModal" class="share"><i class="fa fa-share-alt" aria-hidden="true"></i> 分享</a>
                                    <a href="#" data-toggle="modal" data-target="#remarkModal" class="comment"><i class="fa fa-commenting" aria-hidden="true"></i> 回复</a>
                                </div>
                            </div>
                        </div>
                        <div class="clearfix"></div>
                    </li>
            </ul>
</div>
        </div>
        <div class="fl right-tag">
            <div class="block-btn">
                <p>来个匿名吐槽,发泄一下你心中的怒火吧!</p>
                <a class="sui-btn btn-block btn-share" href="~/assets/spit-submit.html" target="_blank">发吐槽</a>
            </div>
        </div>
        <div class="clearfix"></div>
    </div>
</template>
<script>
import '~/assets/css/page-sj-spit-index.css'
import spitApi from '@/api/spit'
export default {
  asyncData({params, error}) {
    return spitApi.page(1, 10).then(res => {
        let tmp = res.data.data.map(item => {        
        return {
          ...item,
          zan: ''
        }
      })
      return {items: tmp}
    })
  }
}
</script>

1.1.2吐槽列表瀑布流

修改页面pages/spit/index.vue

 <div class="tc-list" v-infinite-scroll="loadMore" >

修改pages/spit/index.vue ,添加pageNo用于记录页码增加方法

  data() {
      return {
        pageNo: 1
      }
  },

 

loadMore: function() {
    this.pageNo ++
    spitApi.page(this.pageNo, 10).then(res => {
        let tmp = res.data.data.map(item => {
            return {
                ...item,
                zan: ''
            }
        })
        this.items = this.items.concat(tmp )
    })
}

1.2吐槽详情页

1.2.1构建吐槽详情页
(1)根据spit-detail.html创建pages/spit/_id.vue ,内容略
(2)修改pages/spit/index.vue 页面链接

<router‐link :to="'/spit/'+item.id"> {{item.content}} </router‐link>

1.2.2吐槽详情页数据渲染
(1)easyMock模拟数据URL: spit/spit/{id} Methos: GET

{
"code": 20000,
"flag": true, "message": "@string", "data": {
"id": "@string",
"nikename": " 小 雅 ", "content": "@cword(100,300)", "publishtime": "@datetime",
"thumbup": "@integer(60, 100)",
"share": "@integer(60, 100)",
"comment": "@integer(60, 100)"
}
}

URL: spit/spit/commentlist/{id} Method: GET

{
"code": 20000,
"flag": true, "message": "@string", "data|10": [{
"id": "@string",
"content": "我要评论我要评论我要评论我要评论我要评论我要评论", "nikename": "小雅",
"publishtime": "@datetime", "thumbup": "@integer(60, 100)"
}]
}

(2)修改api/spit.js

findById(id){ return request({
url: `/${api_group}/${api_name}/${id}`, method: 'get'
})
},
commentlist(id){ return request({
url: `/${api_group}/${api_name}/commentlist/${id}`, method: 'get'
})
}

(3)修改pages/spit/_id.vue

<template>
<div class="wrapper tc‐detail">
<div class="fl left‐list">
<div class="tc‐detail">
<!‐‐ 标题区 ‐‐>
<div class="detail‐tit">
<div class="detail‐author">
<a href="javascript:;">{{pojo.nickname}}</a> 发布
</div>
<div class="detail‐content">
<p>{{pojo.content}}</p>

</div>
<div class="detail‐tool">
<ul>
<li><span class="star"><i class="fa fa‐thumbs‐o‐up" aria‐ hidden="true"></i> {{pojo.thumbup}}</span></li>
<li><a href="#" data‐toggle="modal" data‐target="#shareModal"><i class="fa fa‐share‐alt" aria‐hidden="true"></i> {{pojo.share}}</a></li>
<li><a data‐toggle="modal" data‐target="#remarkModal"><i class="fa fa‐commenting" aria‐hidden="true"></i> {{pojo.comment}}</a>
</li>
</ul>
</div>
</div>
<!‐‐ 评论区 ‐‐>
<div class="comment‐area">
<div class="comment‐tit">
<span>评论</span>
</div>
<ul class="comment‐list">
<li v‐for="(item,index) in commentlist" :key="index">
<div class="item‐photo">
<img src="~/assets/img/widget‐widget‐photo.png" alt="" />
</div>
<div class="item‐content">
<p class="author"><a href="javascript:;">{{item.nickname}}</a>

发布</p>


<p class="content">{{item.content}}</p>

</div>

<div class="item‐thumb">
<div>
<i class="fa fa‐thumbs‐o‐up" aria‐hidden="true"></i>
{{item.thumbup}}
</div>
</div> </li>

</ul>
</div>
</div>
</div>
<div class="fl right‐tag">
<div class="block‐btn">
<p>来个匿名吐槽,发泄一下你心中的怒火吧!</p>
<a class="sui‐btn btn‐block btn‐share" href="~/assets/spit‐ submit.html" target="_blank">发吐槽</a>
</div>
</div>
<div class="clearfix"></div>
</div>
</template>
<script>
import '~/assets/css/page‐sj‐spit‐detail.css' import spitApi from '@/api/spit'
import axios from 'axios' export default {
asyncData({params}){ return axios.all( [
spitApi.findById(params.id),spitApi.commentlist(params.id)	] ).then( axios.spread( function( pojo,commentlist ){
return {
pojo: pojo.data.data,
commentlist: commentlist.data.data
}
})
)
}
}
</script>

1.3吐槽点赞

1.3.1基本功能
(1)easyMock模拟数据URL: spit/spit/thumbup/{id} Method: put

{
"code": 20000,
"flag": true,
"message": "执行成功"
}

(2)api/spit.js 增加方法

thumbup(id) { return request({
url: `/${api_group}/${api_name}/thumbup/${id}`, method: 'put'
})
}

(3)修改pages/spit/index.vue

methods: {
thumbup(index){ spitApi.thumbup(this.items[index].id).then( res=>{
if(res.data.flag){ this.items[index].thumbup++
}
})
}
}

(4)点赞调用

<p class="usenum" @click="thumbup(index)"><a href="#" class="zan"><i class="fa fa‐thumbs‐up " aria‐hidden="true"></i></a></p>

1.3.2样式处理
实现点赞后,大拇指图标变色。样式表已经写好,在li 的样式上加上color 即可
(1)修改pages/spit/index.vue 的代码部分

import '~/assets/css/page‐sj‐spit‐index.css' import spitApi from '@/api/spit'
export default { asyncData(){
return spitApi.search(1,10, {state:'1'} ).then( res=> { let tmp= res.data.data.rows.map( item=>{
return {
...item,
zan: ''
}
})
return {items:tmp}
})
},
data(){
return {
pageNo: 1
}
},
methods:{
loadMore(){ this.pageNo++
spitApi.search( this.pageNo,10,{state:'1'} ).then( res=>{ let tmp= res.data.data.rows.map( item=>{
return {
...item,
zan: ''
}
})
this.items=this.items.concat( tmp	)
})
},
thumbup(index){ this.items[index].zan='color'
spitApi.thumbup(this.items[index].id).then( res=>{ if(res.data.flag){
this.items[index].thumbup++
}
})
}
}
}

(2)修改pages/spit/index.vue的html部分

<a href="#" class="zan">
<i :class="'fa fa‐thumbs‐up '+item.zan" aria‐hidden="true"></i>
</a>

1.3.3判断是否登陆
要求:点赞必须要在用户登陆的情况下执行,非登陆状态下不能点赞。并且不可重复点 赞
导入getUser

import {getUser} from '@/utils/auth'

修改thumbup(点赞)方法

thumbup(index){
if(getUser().name===undefined){ this.$message({
message:'必须登陆才可以点赞哦~',
type:"warning"
})
return
}
if( this.items[index].zan==='color'){ this.$message({
message:'不可以重复点赞哦~',
type:"warning"
})
return
}
this.items[index].zan='color' spitApi.thumbup(this.items[index].id).then( res=>{
if(res.data.flag){ this.items[index].thumbup++
}
})
}

1.3.4提交token
修改utils/request.js ,每次请求将token添加到header里

import axios from 'axios'
import {getUser} from '@/utils/auth'
// 创建axios实例
const service = axios.create({
baseURL: 'http://192.168.184.133:7300/mock/5af314a4c612520d0d7650c7',
// api的base_url
timeout: 30000, // 请求超时时间
headers: { 'Authorization': 'Bearer '+getUser().token	}
})
export default service

2发吐槽与吐槽评论

2.1发吐槽

2.1.1构建页面
我们这里用到VUE常用的富文本编辑器vue-quill-editor
详见文档: https://www.npmjs.com/package/vue-quill-editor
(1)安装vue-quill-editor

cnpm install vue‐quill‐editor ‐‐save

(2)plugins下创建nuxt-quill-plugin.js

import Vue from 'vue'
import VueQuillEditor from 'vue‐quill‐editor/dist/ssr' Vue.use(VueQuillEditor)

(3)修改nuxt.config.js ,配置插件和样式

plugins: [
{ src: '~plugins/nuxt‐quill‐plugin.js', ssr: false }
],
// some nuxt config... css: [
'quill/dist/quill.snow.css', 'quill/dist/quill.bubble.css', 'quill/dist/quill.core.css'
],

(4)pages/spit/submit.vue

<template>
<div class="wrapper release‐tc">
<div class="release‐box">
<h3>发布吐槽</h3>
<div class="editor">
<div class="quill‐editor"
:content="content" @change="onEditorChange($event)" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @ready="onEditorReady($event)" v‐quill:myQuillEditor="editorOption">
</div>

<div class="btns">
<button class="sui‐btn btn‐danger btn‐release">发布</button>
</div>
<div class="clearfix"></div>
</div>
</div>
<div class="clearfix"></div>
</div>

</template>
<script>
import '~/assets/css/page‐sj‐spit‐submit.css' export default {
data () { return {
content: '', editorOption: {
// some quill options modules: {
toolbar: [
[{ 'size': ['small', false, 'large'] }], ['bold', 'italic'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }], ['link', 'image']
]

}

}
}
},
mounted() {
console.log('app init, my quill insrance object is:', this.myQuillEditor)
/*setTimeout(() => { this.content = 'i am changed'
}, 3000)*/
},
methods: { onEditorBlur(editor) {
console.log('editor blur!', editor)
},
onEditorFocus(editor) { console.log('editor focus!', editor)
},
onEditorReady(editor) { console.log('editor ready!', editor)
},
onEditorChange({ editor, html, text }) { console.log('editor change!', editor, html, text) this.content = html
}
}
}
</script>
<style>
.quill‐editor {
min‐height: 200px; max‐height: 400px; overflow‐y: auto;
}

</style>

(5)修改pages/spit/index.vue 链接到此页面

<router‐link class="sui‐btn btn‐block btn‐share" to="/spit/submit">发吐槽
</router‐link>

2.1.2提交吐槽
(1)easyMock模拟数据
URL:spit/spit Method: post

{
"code": 20000,
"flag": true,
"message": "执行成功"
}

(2)修改api/spit.js ,增加提交吐槽的方法

save(pojo) {
return request({
url: `/${group_name}/${api_name}`, method: 'post',
data: pojo
})
}

(2)修改pages/spit/submit.vue 引入API

import spitApi from '@/api/spit'

在methods增加方法

save(){
spitApi.save({ content:this.content }	).then(res=>{ this.$message({
message: res.data.message,
type: (res.data.flag?'success':'error')
})
if(res.data.flag){ this.$router.push('/spit')
}
})
}

$router.push()的作用是路由跳转。
(3)发布按钮调用方法

<button class="sui‐btn btn‐danger btn‐release" @click="save">发布</button>

2.2吐槽评论

2.2.1评论弹出框
我们这里的评论弹出框使用elementUI的弹出框来实现
(1)修改pages/spit/_id.vue ,添加弹出框, 弹出框中放置富文本编辑器

<el‐dialog
title="评论"
:visible.sync="dialogVisible" width="40%" >
<div class="quill‐editor"
:content="content" @change="onEditorChange($event)" v‐quill:myQuillEditor="editorOption">
</div>
<span slot="footer" class="dialog‐footer">
<el‐button @click="dialogVisible = false">取 消</el‐button>
<el‐button type="primary" @click="dialogVisible = false">确 定
</el‐button>
</span>
</el‐dialog>

为富文本编辑框添加样式:

<style>
.quill‐editor {
min‐height: 200px; max‐height: 400px; overflow‐y: auto;
}
</style>

(2)修改pages/spit/index.vue代码部分

data(){
return {
dialogVisible: false, content: '', editorOption: {
// some quill options modules: {
toolbar: [
[{ 'size': ['small', false, 'large'] }], ['bold', 'italic'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }], ['link', 'image']
]
}
}
}
},
methods:{
onEditorChange({ editor, html, text }) { console.log('editor change!', editor, html, text) this.content = html
}
}

(3)修改pages/spit/_id.vue 中的回复链接

<a @click="dialogVisible=true;content=''"><i	class="fa fa‐commenting" aria‐hidden="true"></i> {{pojo.comment}}</a>

2.2.2提交评论
修改pages/spit/_id.vue ,增加提交回复的方法

save(){
spitApi.save({ content:this.content,parentid: this.pojo.id }
).then(res=>{
this.$message({
message: res.data.message,
type: (res.data.flag?'success':'error')
})
if(res.data.flag){ this.dialogVisible=false
spitApi.commentlist(this.pojo.id).then(res=>{ this.commentlist=res.data.data
})
}
})
}

编辑提交按钮

<el‐button type="primary" @click="save">提交</el‐button>

3问答频道

3.1嵌套布局与标签导航

3.1.1嵌套布局
(1)创建pages/qa.vue

<template>
<div>
<div class="tab‐nav ">
<div class="wrapper">
<ul class="fl sui‐nav nav‐tabs navbar‐dark">
<li class="active"><a href="#index" data‐toggle="tab">首页</a>
</li>
<li><a href="#php" data‐toggle="tab">Php</a></li>
<li><a href="#js" data‐toggle="tab">Javascript </a></li>
<li><a href="#python" data‐toggle="tab">Python</a></li>
<li><a href="#java" data‐toggle="tab">Java</a></li>
</ul>
<span class="fr more"><a href="./qa‐allTag.html" target="_blank">更多</a></span>
<div class="clearfix"></div>
</div>
</div>
<nuxt‐child/>
</div>
</template>
<script>
import '~/assets/css/page‐sj‐qa‐logined.css' export default {
}
</script>

(2)创建pages/qa/label/_label.vue

<template>
<div class="wrapper qa‐content">
<div class="fl left‐list">
<div class="tab‐content">
<div id="index" class="tab‐pane active">
<div class="tab‐bottom‐line">
<ul class="sui‐nav nav‐tabs">
<li class="active"><a href="#new" data‐toggle="tab">最新回答</a>

</li>


<li><a href="#hot" data‐toggle="tab">热门回答</a></li>
<li><a href="#wait" data‐toggle="tab">等待回答</a></li>
</ul>
<div class="qa‐list">
<div class="tab‐content">
<div id="new" class="tab‐pane active">
<ul class="detail‐list">
<li class="qa‐item">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">12</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">luckness</span>

<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">有关PHP初级进阶的问题?</a></p>
</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>

<li>Javascript</li>





</p>

</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</div>
</div>
</div>
<div class="clearfix"></div> </li>
<li class="qa‐item">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">12</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">牛奶糖</span>

<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">springMVC的controller接收json数据失败</a></p>
</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>
<li>Javascript</li>
</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</p>


</div>
</div>
</div>
<div class="clearfix"></div> </li>

<li class="qa‐item">

<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">12</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">大白兔</span>
<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">监听器中timer查询数据库</a></p>
</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>
<li>Javascript</li>
</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</p>


</div>
</div>
</div>
<div class="clearfix"></div> </li>
<li class="qa‐item">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">34</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>

</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">luckness</span>
<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">服务器上安装了一个考试系统ASP.NET,安装完成后访问不了,求助</a>
</p>












</p>

</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>
<li>Javascript</li>
</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</div>
</div>
</div>
<div class="clearfix"></div> </li>
<li class="qa‐item">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">12</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">牛奶糖</span>

<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html"

target="_blank">springMVC的controller接收json数据失败</a></p>
</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>
<li>Javascript</li>
</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</p>


</div>
</div>
</div>
<div class="clearfix"></div> </li>
<li class="qa‐item">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">12</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">9</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">大白兔</span>

<span>3</span>分钟前回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">监听器中timer查询数据库</a></p>
</div>
<div class="other">
<ul class="fl sui‐tag">
<li>Php</li>
<li>Javascript</li>
</ul>
<div class="fr brower">
<p>浏览量 50 | 2017‐07‐05 15:09 来自 <a href="#">毕鹏 </a>

</p>


</div>
</div>
</div>
<div class="clearfix"></div> </li>
</ul>
</div>
<div id="hot" class="tab‐pane">
<p>热门回答</p>
</div>
<div id="wait" class="tab‐pane">
<p>等待回答</p>
</div>
</div>
</div>
</div>
</div>
<div id="php" class="tab‐pane"> php
</div>
<div id="js" class="tab‐pane"> Javascript
</div>
<div id="python" class="tab‐pane"> python
</div>
<div id="java" class="tab‐pane"> java
</div>

</div>
</div>
<div class="fl right‐tag">
<div class="block‐btn">
<p>今天,有什么好东西要和大家分享么?</p>
<a class="sui‐btn btn‐block btn‐share" href="./qa‐submit.html" target="_blank">发布问题</a>
</div>
<div class="hot‐tags">
<div class="head">
<h3 class="title">热门标签</h3>
</div>
<div class="tags">
<ul class="sui‐tag">
<li>Php</li>
<li>Javascript</li>
<li>Gif</li>
<li>Java</li>
<li>C#</li>
<li>iOS</li>
<li>C++</li>
</ul>
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
</template>

(3)创建pages/qa/index.vue

<template>
<div></div>
</template>
<script>
export default { created(){
this.$router.push('/qa/label/0')
}
}
</script>

3.1.2标签导航
(1)easyMock模拟数据URL: base/label/toplist Method: GET

{
"flag": true,
"code": 20000,
"data": [{
"id": "1",
"labelname": "JAVA"
},
{
"id": "2",
"labelname": "PHP"
},
{
"id": "3",
"labelname": "前端"
},
{
"id": "4",
"labelname": "Python"
}
]
}

(2)编写标签API 创建api/label.js

import request from '@/utils/request' import {getUser} from '@/utils/auth' const api_group = 'base'
const api_name = 'label' export default {
toplist()  { return request({
url: `/${api_group}/${api_name}/toplist`, method: 'get'
})
}
}

(3)修改pages/qa.vue

<template>
<div>
<div class="tab‐nav ">
<div class="wrapper">
<ul class="fl sui‐nav nav‐tabs navbar‐dark">
<router‐link tag="li" to="/qa" active‐class="active" exact	>
<a> 首页</a></router‐link>
<router‐link tag="li" :to="'/qa/label/'+item.id" active‐ class="active" v‐for="(item,index) in labelList" :key="index"	>

<a>{{item.labelname}} </a>
</router‐link>
</ul>
<span class="fr more"><a href="./qa‐allTag.html" target="_blank">更多</a></span>
<div class="clearfix"></div>
</div>
</div>
<nuxt‐child/>
</div>
</template>
<script>
import labelApi from '@/api/label' export default {
asyncData ({ params, error}) {
return labelApi.toplist().then((res) => { return {labelList: res.data.data	}
})
}
}
</script>

(4)创建pages/qa/index.vue

<template>
<div>
这里是问答列表
</div>
</template>

3.2问答列表

3.2.1最新问答列表
(1)easy-mock模拟数据URL:/qa/problem/newlist/{label}/{page}/{size} Method:GET

{
"code": "@integer(60, 100)",
"flag": "@boolean", "message": "@string", "data": {
"total": "@integer(60, 100)", "rows|10": [{
"id": "@integer(1, 1000)",
"title": "@cword(20,30)", "content": "@string", "createtime": "@datetime", "updatetime": "@datetime", "userid": "@integer(1, 1000)", "nickname": "小马",
"visits": "@integer(60, 100)",
"thumbup": "@integer(60, 100)",
"reply": "@integer(60, 100)", "solve": "@string",
"replyname": "小牛",
"replytime": "@datetime"
}]
}
}

(2)API编写 创建api/problem.js

import request from '@/utils/request'
const group_name = 'qa' const api_name = 'problem' export default {
list(type,label,page,size){
return request({
url:`/${group_name}/${api_name}/${type}/${label}/${page}/${size}`,
method: 'get'
})
}
}

(3)修改pages/qa/label/_label.vue 脚本部分

import problemApi from '@/api/problem' import axios from 'axios'
export default { asyncData({params}){
return axios.all([problemApi.list('newlist',params.label,1,10), problemApi.list('hotlist',params.label,1,10),
problemApi.list('waitlist',params.label,1,10)	] ).then( axios.spread(function(newlist,hotlist,waitlist ){
return { newlist:newlist.data.data.rows, hotlist:hotlist.data.data.rows, waitlist:waitlist.data.data.rows
}
}))
}
}

(4)修改pages/qa/label/_label.vue 模板部分

<ul class="detail‐list">
<li class="qa‐item" v‐for="(item,index) in newlist"
:key="index">
<div class="fl record">
<div class="number">
<div class="border useful">
<p class="usenum">{{item.thumbup}}</p>
<p>有用</p>
</div>
<div class="border answer">
<p class="ansnum">{{item.reply}}</p>
<p>回答</p>
</div>
</div>
</div>
<div class="fl info">
<div class="question">
<p class="author"><span class="name">{{item.replyname}}
</span><span>{{item.replytime}}</span>回答</p>
<p class="title"><a href="./qa‐detail.html" target="_blank">{{item.title}}</a></p>
</div>
<div class="other">
<div class="fr brower">
<p>浏览量 {{item.visits}} | {{item.createtime}} 来自 <a href="#">{{item.nickname}} </a></p>
</div>
</div>
</div>
<div class="clearfix"></div> </li>
</ul>

3.2.2热门回答和等待回答列表
(1)定义属性type ,默认值为new

data(){ return {
type:'new'
}
}

(2)修改选项卡

<ul class="sui‐nav nav‐tabs">
<li :class="type=='new'?'active':''"><a @click="type='new'">最新回答</a></li>
<li :class="type=='hot'?'active':''"><a @click="type='hot'">热门回答</a></li>
<li :class="type=='wait'?'active':''"><a @click="type='wait'">等待回答</a></li>
</ul>

(3)修改div的样式为动态获取最新回答列表

<div id="new" :class="'tab‐pane '+(type=='new'?'active':'')">
.....
</div>

热门回答列表

<div id="hot" :class="'tab‐pane '+(type=='hot'?'active':'')">

等待回答列表

<div id="wait" :class="'tab‐pane '+(type=='wait'?'active':'')">

(4)参照最新问答列表编写热门回答列表与等待回答列表内容

<li class="qa‐item" v‐for="(item,index) in hotlist" :key="index">
.....
<li class="qa‐item" v‐for="(item,index) in waitlist" :key="index">

3.2.3问答列表瀑布流
(1)修改pages/qa/label/_label.vue模板部分

<div class="qa‐list"	v‐infinite‐scroll="loadMore">
....

(2)修改pages/qa/label/_label.vue脚本部分

import problemApi from '@/api/problem' import axios from 'axios'
export default { asyncData({params}){
return axios.all([problemApi.list('newlist',params.label,1,10), problemApi.list('hotlist',params.label,1,10),
problemApi.list('waitlist',params.label,1,10)	] ).then( axios.spread(function(newlist,hotlist,waitlist ){
return { newlist:newlist.data.data.rows, hotlist:hotlist.data.data.rows, waitlist:waitlist.data.data.rows,
label:params.label //标签ID,我们需要记录下来
}
}))
},
data(){ return {
type:'new',
page_new: 1,//记录最新问题列表的页码page_hot: 1,//记录热门问题列表的页码page_wait: 1//记录等待回答列表的页码
}
},
methods:{ loadMore(){
if(this.type==='new'){ this.page_new++
problemApi.list('newlist',this.label,this.page_new,10).then(

res=>{
}

this.newlist=this.newlist.concat( res.data.data.rows )
})

if(this.type==='hot'){ this.page_hot++
problemApi.list('hotlist',this.label,this.page_hot,10).then(

res=>{


this.hotlist=this.hotlist.concat( res.data.data.rows )
})


}




if(this.type==='wait'){ this.page_wait++
problemApi.list('waitlist',this.label,this.page_wait,10).then(
res=>{
this.waitlist=this.waitlist.concat( res.data.data.rows )
})
}
}
}
}

3.3问答详细页

学员实现

3.4发布问题页

学员实现。使用富文本编辑器(参见吐槽模块的实现)

3.5标签列表与关注标签

学员实现

4图片上传

4.1Data URL

Data URL给了我们一种很巧妙的将图片“嵌入”到HTML中的方法。跟传统的用

标记将

服务器上的图片引用到页面中的方式不一样,在Data URL协议中,图片被转换成base64
编码的字符串形式,并存储在URL中,冠以mime-type。传统方式:

<img src="images/myimg.gif ">

这种方式中,img标记的src属性指定了一个远程服务器上的资源。当网页加载到浏览器中 时,浏览器会针对每个外部资源都向服务器发送一次拉取资源请求,占用网络资源。大多数的浏览器都有一个并发请求数不能超过4个的限制。这意味着,如果一个 网页里嵌入了过多的外部资源,这些请求会导致整个页面的加载延迟。而使用Data URL技术,图片数据以base64字符串格式嵌入到了页面中,与HTML成为一体,它的形式如下
vue-quill-editor的图片上传默认采用Data URL方式。

4.2辅助插件vue-quill-editor-upload

如果你不想使用Data URL方式存储图片,我们可以通过一个辅助插件vue-quill-editor- upload 来让vue-quill-editor实现传统方式的上传。
(1)安装:

cnpm install vue‐quill‐editor‐upload ‐‐save

(2)修改submit.vue 引入插件

import {quillRedefine} from 'vue‐quill‐editor‐upload'

(3)将editorOption的值改为{}

data () { return {
content: '', editorOption:{}//修改此处!
}
}

(4)新增created 钩子函数

created () {
this.editorOption = quillRedefine(
{
// 图片上传的设置
uploadConfig: {
action: 'http://localhost:3000/upload',	// 必填参数 图片上传地
// 你必须把返回的数据中所包含的图片地址 return 回去
res: (respnse) => { return respnse.info
},
name: 'img'	// 图片上传参数名
}
}
}
}

4.3Multer(了解)

课程中提供了上传图片的服务端代码 upload-server ,我们可以先测试运行后,对照在线文档阅读并理解代码(课程不要求学员独立编写此段代码)

cnpm install npm run start

这段代码主要应用两项技术:
(1)Express --node.js的web框架 在线文档:
http://www.expressjs.com.cn/4x/api.html
(2)Multer --Express官方推出的,用于multipart/form-data请求数据处理的中间件在 线 文 档 : https://github.com/expressjs/multer/blob/master/doc/README-zh- cn.md

4.4云存储解决方案-阿里云OSS

为了能够解决海量数据存储与弹性扩容,我们在十次方项目中采用云存储的解决方案- 阿里云OSS。
4.4.1准备工作
(1)申请阿里云账号并完成实名认证: 可以使用我们之前发短信用的阿里云账号。
(2)开通OSS: 登录阿里云官网。将鼠标移至产品找到并单击对象存储OSS打开OSS产品详情页面。在OSS产品详情页中的单击立即开通。开通服务后,在OSS产品详情页面单击管理控制台直接进入OSS管理控制台界面。您也可以单击位于官网首页右上方菜单栏的控制台,进入阿里云管理控制台首页,然后单击左侧的对象存储OSS菜单进入OSS管理控制台界面。
在这里插入图片描述
(3)创建存储空间
新建Bucket,命名为tensquare ,读写权限为公共读
在这里插入图片描述
4.4.2代码编写
(1)安装ali-oss

cnpm install ali‐oss ‐‐save cnpm install co ‐‐save

(2)修改file-upload-demo-master的server.js

var co = require('co');
var OSS = require('ali‐oss'); var client = new OSS({
accessKeyId: 'LTAIWaEERTRWSD2',
accessKeySecret: 'PznrHXxYvTcADAFFDDDJnoAokJ0NSWEWF', endpoint: 'oss‐cn‐beijing.aliyuncs.com',
bucket: 'tensquare'
});
app.post('/upload', upload.single('img'), (req, res) => {
// 没有附带文件
if (!req.file) {
res.json({ ok: false }); return;
}
co(function* () {
var stream = fs.createReadStream(req.file.path);
var result = yield client.putStream(req.file.originalname, stream); console.log("result:"+result);
res.json({ ok: true , info: result.url})
}).catch(function (err) { console.log(err);
});
});

co :已同步的方式调用异步的代码 配合yield关键字使用,将异步结果直接返回。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值