山东大学项目实训-地图圈系统-web开发(7)
一、动态页面——页面设计
作为一个具有交际圈功能的系统,用户是可以在其中发布自己的动态的。动态的内容包括文字、图片等等,具体发布是在移动端上进行发布。对于web端来说,虽然用户无法在上面发布动态,但是可以查看动态、发布评论以及查看评论、点赞和取消点赞等操作。
首先上成果图:
在这里可以查看内容区、图片、点赞区和评论区。
这里目前来说已经点赞,根据逻辑,再次点击点赞按钮会取消点赞。接下来我们试一试:
点击后,可以看到点赞按钮已经变成了灰色,点赞区也没有了该用户的名字。
添加评论测试:
点击评论按钮,会弹出输入框。在输入框里输入内容,点击发送,就可以添加评论了。
代码部分:
<div class="block" v-for="(item,index) in upload_list" v-bind:key="index">
<div class="img_name">
<el-col style="flex: 1">
<div class="demo_basic_circle">
<div>
<img :src="item.imageUrlRespense" class="head_img" :preview="index"/>
</div>
</div>
</el-col>
<div class="upload_main_info">
<div style="font-size: 25px;">{{item.username}}</div>
<div>{{item.time}}</div>
</div>
<div class="delete" v-if="item.username === username">
<img src="../../assets/delete.png" style="width: 25px; height: 25px;"
@click="show_delete_upload_dialog(item.id)"/>
</div>
</div>
<div class="content">{{item.content}}</div>
<div v-if="item.image !== ''" style="margin-bottom: 10px">
<div class="upload_images" v-for="(image_list, row) in item.image" v-bind:key="row">
<el-row :gutter="15">
<el-col v-for="(imageUrl, index) in image_list" v-bind:key="index"
:span="image_list.length === 3 ? 8 : image_list.length === 2 ? 12 : 24">
<img class="content_images" :preview="image_list"
:src="'http://8.140.117.15:8800/user/getimage/' + imageUrl" />
</el-col>
</el-row>
</div>
</div>
<div class="location_like_comment">
<div class="location">
<i class="el-icon-location-outline"></i>
{{item.location}}
</div>
<div class="like">
<img v-if="item.likeList.indexOf(username) === -1" src="../../assets/no_like.png"
class="like_img" @mouseover="image_color_change(item.number)"
@mouseleave="image_color_return(item.number)" v-on:click="like(item.id, item.number)" />
<img v-else src="../../assets/already_like.png" class="like_img"
v-on:click="like(item.id, item.number)" />
</div>
<div class="comment">
<img src="../../assets/comment.png" style="width: 25px; height: 25px;"
v-on:click="comment(item.number)">
</div>
</div>
<div class="others_like_comment" v-show="item.likeList.length > 0 || item.commentList.length > 0">
<div class="others_like" v-show="item.likeList.length > 0">
<img src="../../assets/already_like.png" style="width: 25px; height: 25px;"/>
<div v-for="(ilike, index) in item.likeList" v-bind:key="index">
<span v-if="index !== item.likeList.length-1">{{ilike + ','}}</span>
<span v-else>{{ilike}}</span>
</div>
</div>
<div class="comment_input" style="display: none">
<el-row :gutter="30" style="margin: 15px -10px 10px -5px">
<el-col :span="20">
<el-input placeholder="快来添加你的评论吧~" v-model="my_comment" @input="change()"></el-input>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="add_comment(item.id, item.number)">发送</el-button>
</el-col>
</el-row>
</div>
<div class="others_comments" v-show="item.commentList.length > 0">
<div class="others_comment" v-for="(comment, index) in item.commentList" v-bind:key="index"
@click="username === comment.username && show_delete_comment_dialog(comment.id, item.number)"
:style="username === comment.username ? 'cursor: pointer': ''">
<div style="display: flex">
<div style="flex: 1; width: 100%">
<span style="color: #389bff">{{comment.username}}:</span>
<span style="word-break: break-all;white-space:pre-wrap;">{{comment.content}}</span>
</div>
<span style="text-align: right; font-size: 12px; color: #8c939d">{{comment.time}}</span>
</div>
<div v-for="(sub_comment, index) in comment.commentList" v-bind:key="index"
style="display: flex; margin: 5px 0 5px 25px">
<div style="flex: 1; width: 100%">
<span style="color: #389bff">{{sub_comment.username}}</span>
<span style="color: #8c939d; font-size: 14px"> 回复 </span>
<span style="color: #389bff">{{comment.username}}:</span>
<span style="word-break: break-all;white-space:pre-wrap;">{{sub_comment.content}}</span>
</div>
<span style="text-align: right; font-size: 12px; color: #8c939d">{{sub_comment.time}}</span>
</div>
</div>
</div>
</div>
</div>
like (id, number) {
if (document.getElementsByClassName('like_img')[number].src ===
"http://localhost:8080/img/like_image_hover.d8be070b.png" ||
document.getElementsByClassName('like_img')[number].src ===
"http://localhost:8080/img/no_like.026de745.png"){
this.$http
.post('/dongtai/good/' , {
dongtai_id: id,
username: this.username
})
.then(successResponse => {
console.log(successResponse.data)
if (successResponse.data.status === 200){
this.upload_list[number].likeList.push(this.username)
}
})
document.getElementsByClassName('like_img')[number].src = require('../../assets/already_like.png')
} else {
if (document.getElementsByClassName('like_img')[number].src ===
"http://localhost:8080/img/already_like.09b4e91e.png"){
console.log("666")
this.$http
.post('/dongtai/cancelgood/' , {
dongtai_id: id,
username: this.username
})
.then(successResponse => {
console.log(successResponse.data)
if (successResponse.data.status === 200){
let index = this.upload_list[number].likeList.indexOf(this.username)
this.upload_list[number].likeList.splice(index, 1)
}
})
}
document.getElementsByClassName('like_img')[number].src = require('../../assets/no_like.png')
}
},
image_color_change (number) {
if (document.getElementsByClassName('like_img')[number].src ===
"http://localhost:8080/img/no_like.026de745.png"){
document.getElementsByClassName('like_img')[number].src = require('../../assets/like_image_hover.png')
}
},
image_color_return (number) {
if(document.getElementsByClassName('like_img')[number].src ===
"http://localhost:8080/img/like_image_hover.d8be070b.png"){
document.getElementsByClassName('like_img')[number].src = require('../../assets/no_like.png')
}
},
comment (number) {
if (document.getElementsByClassName("comment_input")[number].style.display === 'none') {
document.getElementsByClassName("comment_input")[number].style.display = 'inline'
} else {
document.getElementsByClassName("comment_input")[number].style.display = 'none'
}
},
add_comment(id, number) {
this.$http
.post('/comment/save', {
username: this.username,
dongtai_id: id,
content: this.my_comment
})
.then(successResponse => {
console.log(successResponse.data)
if (successResponse.data.status === 200) {
this.$message.success('添加评论成功!')
this.upload_list[number].commentList.push(successResponse.data.comment)
this.my_comment = ""
} else {
this.$message.error('请稍后再试……')
}
})
},
==
二、动态页面——删除动态/评论设计
删除这一个层次来说呢,我只设计了如何删除自己的动态和评论,毕竟这也符合逻辑。
使用SDUer~登录该系统。
同样回到动态页面,发现右上角多了个删除图片。
点击该图片,就可以进行动态的删除操作。
点击:
再次点击动态,就可以删除该动态了。
在其他人发表的动态里,是没有这个删除图标的。
删除评论演示:
点击自己发表的评论:
会弹出该提示框,点击确定即可删除。
代码部分:
<div class="delete" v-if="item.username === username">
<img src="../../assets/delete.png" style="width: 25px; height: 25px;"
@click="show_delete_upload_dialog(item.id)"/>
</div>
<div class="others_comment" v-for="(comment, index) in item.commentList" v-bind:key="index"
@click="username === comment.username && show_delete_comment_dialog(comment.id, item.number)"
:style="username === comment.username ? 'cursor: pointer': ''">
<!-- 删除动态对话框 -->
<el-dialog
title="提示"
:visible.sync="deleteUploadDialogVisible"
width="30%">
<span>你确定要删除该动态吗?此操作无法撤销</span>
<span slot="footer" class="dialog-footer">
<el-button @click="deleteUploadDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="delete_upload">确 定</el-button>
</span>
</el-dialog>
<!-- 删除评论对话框 -->
<el-dialog
title="提示"
:visible.sync="deleteCommentDialogVisible"
width="30%">
<span>你确定要删除该评论吗?此操作无法撤销</span>
<span slot="footer" class="dialog-footer">
<el-button @click="deleteCommentDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="delete_comment()">确 定</el-button>
</span>
</el-dialog>
delete_upload() {
this.$http
.delete('/dongtai/deletebyid/' + this.id)
.then(successResponse => {
if (successResponse.data.status === 200) {
this.$message.success('删除动态成功!')
this.deleteUploadDialogVisible = false
let index = 0
for (let i = 0; i < this.upload_list.length; i++) {
if (this.upload_list[i].id === this.id) {
index = i
}
}
this.upload_list.splice(index, 1)
} else {
this.$message.error('请稍后再试……')
}
})
},
show_delete_upload_dialog(id) {
this.deleteUploadDialogVisible = true
this.id = id
},
show_delete_comment_dialog(comment_id, number) {
this.deleteCommentDialogVisible = true
this.comment_id = comment_id
this.number = number
},
delete_comment(){
this.$http
.delete('/comment/deletebyid/' + this.comment_id)
.then(successResponse => {
if (successResponse.data.status === 200) {
this.$message.success('删除评论成功!')
this.deleteCommentDialogVisible = false
let index = 0
for (let i = 0; i < this.upload_list[this.number].commentList.length; i++) {
if (this.upload_list[this.number].commentList[i].id === this.comment_id) {
index = i
}
}
this.upload_list[this.number].commentList.splice(index, 1)
} else {
this.$message.error('请稍后再试……')
}
})
},
三、动态页面——九宫格图片设计
九宫格图片的设计,我是运用了el-col的span参数调整的。首先获取el-row的每一行的图片数,为从0-3的整数。因为从数据库里取出最多九张图,故首先判断需要几行,再判断最后一行的张数即可。span参数,每一个el-row对应24。意思是,如果有一张图需要占一行,则span为24,两张图就12,三张图就为8。根据这个思想,获取最后一行的图片张数,再在标签里使用三目运算符即可正确调整span的参数大小。
代码如下:
<div class="upload_images" v-for="(image_list, row) in item.image" v-bind:key="row">
<el-row :gutter="15">
<el-col v-for="(imageUrl, index) in image_list" v-bind:key="index"
:span="image_list.length === 3 ? 8 : image_list.length === 2 ? 12 : 24">
<img class="content_images" :preview="image_list"
:src="'http://8.140.117.15:8800/user/getimage/' + imageUrl" />
</el-col>
</el-row>
</div>
async getAllUpload(page, size) {
await this.$http
.get('/dongtai/findall/' + page + '/' + size)
.then(successResponse => {
if (successResponse.data.status === 200) {
this.upload_list = successResponse.data.dongtaiPageList
for (let i = 0; i < this.upload_list.length; i++) {
if (this.upload_list[i].head_img) {
if (this.upload_list[i].if_wx === 0) {
let imageUrlResponse = 'http://8.140.117.15:8800/user/getimage/'
+ this.upload_list[i].head_img
this.upload_list[i].imageUrlRespense = imageUrlResponse
} else {
this.upload_list[i].imageUrlRespense = this.upload_list[i].head_img
}
}
if (this.upload_list[i].image) {
let content_image_list = this.upload_list[i].image.split(",")
if (content_image_list.length > 6) {
let content_image_row1 = []
let content_image_row2 = []
let content_image_row3 = []
for (let i = 0; i < 3; i++) {
content_image_row1.push(content_image_list[i])
}
for (let i = 3; i < 6; i++) {
content_image_row2.push(content_image_list[i])
}
for (let i = 6; i < content_image_list.length; i++) {
content_image_row3.push(content_image_list[i])
}
content_image_list = []
content_image_list.push(content_image_row1)
content_image_list.push(content_image_row2)
content_image_list.push(content_image_row3)
} else if (content_image_list.length > 3 && content_image_list.length <= 6) {
let content_image_row1 = []
let content_image_row2 = []
for (let i = 0; i < 3; i++) {
content_image_row1.push(content_image_list[i])
}
for (let i = 3; i < content_image_list.length; i++) {
content_image_row2.push(content_image_list[i])
}
content_image_list = []
content_image_list.push(content_image_row1)
content_image_list.push(content_image_row2)
} else {
let content_image_row1 = []
for (let i = 0; i < content_image_list.length; i++) {
content_image_row1.push(content_image_list[i])
}
content_image_list = []
content_image_list.push(content_image_row1)
}
this.upload_list[i].image = content_image_list
}
for (let i = 0; i < this.upload_list.length; i++) {
this.upload_list[i].number = i
}
}
console.log(this.upload_list)
} else if (successResponse.data.status === 401) {
this.$message.info("还没有人发表动态,快去移动端发布你的动态吧!")
} else {
this.$message.error("服务器出错,请稍后再试……")
}
})
.catch(failResponse => {
console.log(failResponse.data)
})
}
实现效果:
这样就实现了九宫格的效果。
四、动态页面——动态加载以及返回顶部
作为一个动态页面,每一个动态的数据量都不小,如果动态数据过大,那么浏览器的缓存就会过大,从而造成卡顿,甚至瘫痪。其次,用户不一定能把所有的动态一次性看完,过多的加载会造成缓存浪费,因此,页面需要实现动态加载。
表现效果:
用户在首次登录时:
此时只能加载三条数据,当页面滚动到底部:
就会自动加载新的动态。
要设置这个,就需要用到v-infinite-scroll标签,它可以保证无限滚动。要使用这个标签,就需要让产生滑轮的组件(el-main)的scroll-y属性设置为auto。
代码:
<!-- 主体部分 -->
<el-main class="wrap" style="overflow: auto;">
<div id="main" v-infinite-scroll="upload_more" infinite-scroll-delay="500">
返回顶部:
当用户向下滑动过多时,想要返回最上面,就需要使用该组件。在产生滑轮的组件设置一下el-backtop即可。
<!-- 主体部分 -->
<el-main class="wrap" style="overflow: auto;">
<!-- 路由占位符 -->
<el-backtop target=".wrap" :visibility-height="100"></el-backtop>
<!-- 头部 -->
<router-view></router-view>
</el-main>
至此,动态页面已经告一段落。