51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

完成个人中心、问题详情和问题编辑

当做完了之前的所有步骤之后,后续的内容开发就变得相对来说很简单了,总的逻辑都是差不多的,每个用户肯定会有一个个人中心界面,里面存放自己写的问题和收到的回复等等,今天要做的就是编写这个个人中心功能。展示效果如下:

点击右上角小三角,选择我的提问,可以看到自己发布的所有问题,点击每一个问题进入详情界面

目前仅展示问题名称,作者发布时间,内容,如果检测到用户就是作者,可进行编辑操作

点击编辑,进入编辑界面

# (一)页面的搭建 {#一-页面的搭建}

首先在导航栏中为我的消息加上href标签

<ul class="dropdown-menu">
    <li><a href="/personal/questions">我的提问</a></li>
    <li><a href="#">个人资料</a></li>
    <li><a href="/logout">退出登陆</a></li>
</ul>

对于我的消息的布局,依旧使用bootstrap的栅格系统,页面左右比例3:1,问题的展示逻辑和首页类似,只是这里需要增加用户检测,如果问题的发起者就是当前登陆用户,则分页展示,右侧的列表组依旧来自bootstrap官网的组件:

只需要复制代码然后修改成自己的就行,我在这里加了判断逻辑,目的是让当前选中的高亮

<div class="col-lg-3 col-md-12 col-sm-12 col-ss-12">
    <div class="list-group personal">
        <a href="/personal/questions" th:class="${section=='questions'}?'list-group-item active' : 'list-group-item' ">
            我的问题
        </a>
        <a href="/personal/information" th:class="${section=='information'}?'list-group-item active' : 'list-group-item' ">我的消息</a>
    </div>
</div>

其余的前端代码见文末源码。

# (二)个人中心后端处理逻辑 {#二-个人中心后端处理逻辑}

在controller层建立PersonalController,首先获取当前登陆的用户信息,接着和首页一样在questionService进行处理,返回当前页面需要展示的数据的页码栏情况

//个人中心
@Controller
public class PersonalController {
    @Resource
    private UserMapper userMapper;
    @Resource
    private QuestionService questionService;
    @GetMapping("/personal/{action}")
    public String personal(@PathVariable(name = "action")String action,
                           Model model,
                           HttpServletRequest request,
                           @RequestParam(name = "page",defaultValue = "1")int page,
                           @RequestParam(name = "size",defaultValue = "5")int size){
        //获取当前用户
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return "login";
        }
        User user = null;
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("token")) {
                String token = cookie.getValue();
                user = userMapper.findBytoken(token);
                if (user != null) {
                    request.getSession().setAttribute("user", user);
                }
                break;
            }
        }
        //判断action是什么
        if (action.equals("questions")){
            model.addAttribute("section","questions");
            model.addAttribute("sectionname","我的问题");
        }else if (action.equals("information")){
            model.addAttribute("section","information");
            model.addAttribute("sectionname","我的消息");
        }

        PageDto pagination=questionService.list(user.getId(),page,size);
        model.addAttribute("pagination", pagination);
        return "personal";
    }
}
questionService.list(user.getId(),page,size);的实现方法:找出来每页需要展示的内容,添加到pageDto中,pageDto中同时还储存页面信息
public PageDto list(int userid, int page, int size) {
    PageDto pageDto = new PageDto();
    int totalcount = questionMapper.countbyid(userid);
    pageDto.setPagination(totalcount,page,size);
    //size*{page-1}
    int offset = size * (page - 1);
    //每页只展示5条
    //select * from question where createid=#{userid} limit #{offset},#{size}
    List<Question> questions = questionMapper.listbyid(userid,offset, size);
    List<Questiondto> questiondtoList = new ArrayList<>();

    for (Question question : questions) {
        User user = userMapper.findById(question.getCreateid());
        Questiondto questiondto = new Questiondto();
        //把第一个对象的所有属性拷贝到第二个对象中
        BeanUtils.copyProperties(question, questiondto);
        questiondto.setUser(user);
        questiondtoList.add(questiondto);
    }
    pageDto.setQuestions(questiondtoList);
    return pageDto;
}

最后返回给前端的model包含了所有需要展示的内容,前端只需要根据model布局页面即可。

# (三)为每个问题做问题详情页 {#三-为每个问题做问题详情页}

我们现在做的不管是首页还是我的问题中,都无法点击相关问题,为每个问题增加href标签,地址为:http://localhost:8080/question/问题的id,这样就可以通过id知道是哪篇文章

<h4 class="media-heading">
    <a th:href="@{'/question/'+${question.id}}" th:text="title"></a>
</h4>
<span>
    <a th:text="${question.description}" th:href="@{'/question/'+${question.id}}"></a>
</span>

问题详情页的后端处理逻辑很简单,只需要通过id查询这篇文章和作者即可,我们之前已经创建了问题和用户联立的DTO

@Controller
public class QuestionController {
    @Resource
    private QuestionService questionService;
    @GetMapping("/question/{id}")
    public String question(@PathVariable(name = "id")int id,
                           Model model){
        Questiondto questiondto=questionService.getbyid(id);
        model.addAttribute("questionDto",questiondto);
        return "question";
    }
}

对前端的布局不再做过多解释,大家可以看源码。

# (四)完成问题编辑功能 {#四-完成问题编辑功能}

问题编辑按钮只有在当前用户等于问题作者时才会出现,因此在前端界面做一个逻辑判断处理:

<a th:href="@{'/publish/'+${questionDto.id}}" th:if="${session.user!=null && session.user.id==questionDto.createid}">
    <span class="glyphicon glyphicon-pencil question-menu" aria-hidden="true">编辑
    </span>
</a>

点击编辑过后会跳转到问题发布界面,那如何判断这个时候是要新发布还是编辑更新呢?因此需要设置一个新的属性id来处理这个问题,在publish.html中增加

<input type="hidden" name="id" th:value="${id}">

这条input组件不会出现在页面中,但是传递了id属性,这里的id为问题id,页面编辑控制器代码如下:

@GetMapping("/publish/{id}")
public String edit(@PathVariable(name = "id")int id,
                   Model model){
    Question question=questionMapper.getbyId(id);
    model.addAttribute("title", question.getTitle());
    model.addAttribute("description", question.getDescription());
    model.addAttribute("tag", question.getTag());
    //用来标识问题是修改而不是重新创建
    model.addAttribute("id",question.getId());
    return "publish";
}

修改此前创建的publishController,在参数中获取id的值,如果为空则附上默认值-1,意思就是如果是第一次创建,id=-1,如果是编辑,id就是问题id

@RequestParam(value = "id",defaultValue = "-1")int id,

根据id的值,执行不同的功能

if(id==-1){
    questionMapper.createquestion(question);
}else {
    question.setId(id);
    questionMapper.updatequestion(question);
}

这样问题编辑功能就完成了。

赞(3)
未经允许不得转载:工具盒子 » 完成个人中心、问题详情和问题编辑