Skip to main content

一、数据库设计

1、数据库

edu_comment

2、数据表

guli_edu.sql

二、创建课程评论接口

1、在service-edu模块,生成课程评论代码

(1)使用mp代码生成器生成

2、在service-ucenter模块,创建接口

(1)

实现用户id获取用户信息,返回用户信息对象

//根据token字符串获取用户信息
@PostMapping("getInfoUc/{id}")
public com.atguigu.commonutils.vo.UcenterMember getInfo(@PathVariable String id) {
//根据用户id获取用户信息
UcenterMember ucenterMember = memberService.getById(id);
com.atguigu.commonutils.vo.UcenterMember memeber = new com.atguigu.commonutils.vo.UcenterMember();
BeanUtils.copyProperties(ucenterMember,memeber);
return memeber;
}

3、创建课程评论controller

(1)在service-edu模块创建client,实现微服务调用

@Component
@FeignClient(name="service-ucenter",fallback = UcenterClientImpl.class)
public interface UcenterClient {

//根据用户id获取用户信息
@GetMapping("/ucenterservice/member/getUcenterPay/{memberId}")
public UcenterMemberPay getUcenterPay(@PathVariable("memberId") String memberId);
}

@Component
public class UcenterClientImpl implements UcenterClient {
@Override
public UcenterMemberPay getUcenterPay(String memberId) {
return null;
}
}

(2)创建评论列表和添加评论接口

@RestController
@RequestMapping("/eduservice/comment")
@CrossOrigin
public class CommentFrontController {

@Autowired
private CommentService commentService;
@Autowired
private UcenterClient ucenterClient;

//根据课程id查询评论列表
@ApiOperation(value = "评论分页列表")
@GetMapping("{page}/{limit}")
public R index(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,

@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit,

@ApiParam(name = "courseQuery", value = "查询对象", required = false)
String courseId) {
Page<Comment> pageParam = new Page<>(page, limit);

QueryWrapper<Comment> wrapper = new QueryWrapper<>();
wrapper.eq("course_id",courseId);

commentService.page(pageParam,wrapper);
List<Comment> commentList = pageParam.getRecords();

Map<String, Object> map = new HashMap<>();
map.put("items", commentList);
map.put("current", pageParam.getCurrent());
map.put("pages", pageParam.getPages());
map.put("size", pageParam.getSize());
map.put("total", pageParam.getTotal());
map.put("hasNext", pageParam.hasNext());
map.put("hasPrevious", pageParam.hasPrevious());
return R.ok().data(map);
}

@ApiOperation(value = "添加评论")
@PostMapping("auth/save")
public R save(@RequestBody Comment comment, HttpServletRequest request) {
String memberId = JwtUtils.getMemberIdByJwtToken(request);
if(StringUtils.isEmpty(memberId)) {
return R.error().code(28004).message("请登录");
}
comment.setMemberId(memberId);

UcenterMemberPay ucenterInfo = ucenterClient.getUcenterPay(memberId);

comment.setNickname(ucenterInfo.getNickname());
comment.setAvatar(ucenterInfo.getAvatar());

commentService.save(comment);
return R.ok();
}
}

三、课程评论前端整合

1、在api创建commonedu.js

import request from '@/utils/request'

export default {

getPageList(page, limit, courseId) {
return request({
url: `/eduservice/comment/${page}/${limit}`,
method: 'get',
params: {courseId}
})
},
addComment(comment) {
return request({
url: `/eduservice/comment/auth/save`,
method: 'post',
data: comment
})
}
}

2、在课程详情页面,调用方法 _id.vue

import comment from '@/api/commonedu'

<script>
import course from '@/api/course'
import comment from '@/api/commonedu'
export default {

//和页面异步开始的
asyncData({ params, error }) {
return {courseId: params.id}

},
data() {
return {
data:{},
page:1,
limit:4,
total:10,
comment:{
content:'',
courseId:''
},
courseInfo:{},
chapterVideoList:[],
isbuyCourse:false
}
},
created() {
this.initCourseInfo()
this.initComment()
},
methods:{
//获取课程详情
initCourseInfo() {
course.getCourseInfo(this.courseId)
.then(response => {
this.courseInfo=response.data.data.courseFrontInfo
this.chapterVideoList=response.data.data.chapterVideoList
this.isbuyCourse=response.data.data.isbuyCourse
})
},

initComment(){
comment.getPageList(this.page, this.limit, this.courseId).then(response => {
this.data = response.data.data
})
},
addComment(){
this.comment.courseId = this.courseId
this.comment.teacherId = this.courseInfo.teacherId
comment.addComment(this.comment).then(response => {
if(response.data.success){
this.comment.content = ''
this.initComment()
}
})
},
gotoPage(page){
comment.getPageList(page, this.limit,this.courseId).then(response => {
this.data = response.data.data
})
}
}

};
</script>

3、在课程详情页面 _id.vue显示评论

<div class="mt50 commentHtml"><div>
<h6 class="c-c-content c-infor-title" id="i-art-comment">
<span class="commentTitle">课程评论</span>
</h6>
<section class="lh-bj-list pr mt20 replyhtml">
<ul>
<li class="unBr">
<aside class="noter-pic">
<img width="50" height="50" class="picImg" src="~/assets/img/avatar-boy.gif">
</aside>
<div class="of">
<section class="n-reply-wrap">
<fieldset>
<textarea name="" v-model="comment.content" placeholder="输入您要评论的文字" id="commentContent"></textarea>
</fieldset>
<p class="of mt5 tar pl10 pr10">
<span class="fl "><tt class="c-red commentContentmeg" style="display: none;"></tt></span>
<input type="button" @click="addComment()" value="回复" class="lh-reply-btn">
</p>
</section>
</div>
</li>
</ul>
</section>
<section class="">
<section class="question-list lh-bj-list pr">
<ul class="pr10">
<li v-for="(comment,index) in data.items" v-bind:key="index">
<aside class="noter-pic">
<img width="50" height="50" class="picImg" :src="comment.avatar">
</aside>
<div class="of">
<span class="fl">
<font class="fsize12 c-blue">
{{comment.nickname}}</font>
<font class="fsize12 c-999 ml5">评论:</font></span>
</div>
<div class="noter-txt mt5">
<p>{{comment.content}}</p>
</div>
<div class="of mt5">
<span class="fr"><font class="fsize12 c-999 ml5">{{comment.gmtCreate}}</font></span>
</div>
</li>

</ul>
</section>
</section>

<!-- 公共分页 开始 -->
<div class="paging">
<!-- undisable这个class是否存在,取决于数据属性hasPrevious -->
<a
:class="{undisable: !data.hasPrevious}"
href="#"
title="首页"
@click.prevent="gotoPage(1)">首</a>
<a
:class="{undisable: !data.hasPrevious}"
href="#"
title="前一页"
@click.prevent="gotoPage(data.current-1)">&lt;</a>
<a
v-for="page in data.pages"
:key="page"
:class="{current: data.current == page, undisable: data.current == page}"
:title="'第'+page+'页'"
href="#"
@click.prevent="gotoPage(page)">{{ page }}</a>
<a
:class="{undisable: !data.hasNext}"
href="#"
title="后一页"
@click.prevent="gotoPage(data.current+1)">&gt;</a>
<a
:class="{undisable: !data.hasNext}"
href="#"
title="末页"
@click.prevent="gotoPage(data.pages)">末</a>
<div class="clear"/>
</div>
<!-- 公共分页 结束 -->
</div>
</div>