SpringBoot学习笔记-创建个人中心页面(下)
笔记内容转载自 AcWing 的 SpringBoot 框架课讲义,课程链接:AcWing SpringBoot 框架课。
CONTENTS
- 1. 实现个人中心页面
- 2. POJO时区修改
- 3. 集成代码编辑器
本节实现个人中心的前端页面,用户能够查看自己的 Bot 信息,并能创建、修改或删除 Bot,此外还集成了 Vue Ace Editor 代码编辑器,方便用户输入 Bot 的代码。
1. 实现个人中心页面
我们要实现用户的个人中心页面,能够展示用户的头像以及自己所有 Bot 的信息,例如 Bot 名字、创建时间等,还需要具有创建/修改/删除 Bot 等功能,在很早之前创建的 MyBotsIndexView
组件中实现:
<template>
<div class="container">
<div class="card text-bg-secondary" style="margin-top: 20px;">
<div class="card-header">
<h3>My Bots</h3>
</div>
<div class="card-body" style="background-color: rgba(255, 255, 255, 0.5);">
<div class="row">
<div class="col-md-3">
<div class="card">
<!-- 用户头像与用户名 -->
<div class="card-body text-center">
<img class="img-fluid" :src="$store.state.user.photo" style="width:50%; border-radius: 50%;">
<div style="font-size: 20px; margin-top: 10px; font-weight: bold;">
{{ $store.state.user.username }}
</div>
</div>
</div>
</div>
<div class="col-md-9">
<div class="card">
<div class="card-header">
<span style="font-size: 25px;">Bot 管理</span>
<!-- 点击创建按钮能够打开模态框 -->
<button class="btn btn-outline-success float-end" type="button" data-bs-toggle="modal" data-bs-target="#add_bot_modal">
创建 Bot
</button>
<!-- 创建 Bot 的模态框 -->
<div class="modal fade" id="add_bot_modal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header" style="background-color: #198754;">
<h1 class="modal-title fs-5" style="color: white;">创建 Bot</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="title" class="form-label">名称</label>
<input v-model="new_bot.title" type="email" class="form-control" id="title" placeholder="请输入 Bot 名称">
</div>
<div class="mb-3">
<label for="description" class="form-label">简介</label>
<textarea v-model="new_bot.description" class="form-control" id="description" rows="3" placeholder="介绍一下你的 Bot 吧~(可以暂时不填)"></textarea>
</div>
<div class="mb-3">
<label for="content" class="form-label">代码</label>
<textarea v-model="new_bot.content" class="form-control" id="content" rows="14" placeholder="在这里编写你的 Bot 代码~"></textarea>
</div>
</div>
<div class="modal-footer">
<div class="error_message" style="color: red;">{{ new_bot.error_message }}</div>
<button type="button" class="btn btn-success" @click="add_bot">创建</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
</div>
</div>
</div>
</div>
</div>
<!-- 用户的 Bot 列表 -->
<div class="card-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>名称</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="bot in bots" :key="bot.id">
<td style="line-height: 32px;">{{ bot.title }}</td>
<td style="line-height: 32px;">{{ bot.createtime }}</td>
<td>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="modal" :data-bs-target="'#update_bot_modal_' + bot.id" style="margin-right: 10px; padding: 3px 10px;">
修改
</button>
<button class="btn btn-outline-danger" type="button" data-bs-toggle="modal" :data-bs-target="'#remove_bot_modal_' + bot.id" style="padding: 3px 10px;">
删除
</button>
<!-- 修改 Bot 的模态框 -->
<div class="modal fade" :id="'update_bot_modal_' + bot.id" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header" style="background-color: #0D6EFD;">
<h1 class="modal-title fs-5" style="color: white;">修改 Bot</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="title" class="form-label">名称</label>
<input v-model="bot.title" type="email" class="form-control" id="title" placeholder="请输入 Bot 名称">
</div>
<div class="mb-3">
<label for="description" class="form-label">简介</label>
<textarea v-model="bot.description" class="form-control" id="description" rows="3" placeholder="介绍一下你的 Bot 吧~(可以暂时不填)"></textarea>
</div>
<div class="mb-3">
<label for="content" class="form-label">代码</label>
<textarea v-model="bot.content" class="form-control" id="content" rows="14" placeholder="在这里编写你的 Bot 代码~"></textarea>
</div>
</div>
<div class="modal-footer">
<div class="error_message" style="color: red;">{{ new_bot.error_message }}</div>
<button type="button" class="btn btn-primary" @click="update_bot(bot)">保存修改</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
</div>
</div>
</div>
</div>
<!-- 删除 Bot 的确认模态框 -->
<div class="modal fade" :id="'remove_bot_modal_' + bot.id" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header" style="background-color: #DC3545;">
<h1 class="modal-title fs-5" style="color: white;">警告</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" style="font-size: 20px;">
确认删除?该操作无法撤销哦~
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" @click="remove_bot(bot)">删除</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive } from "vue"; // reactive用来让组件绑定对象
import { useStore } from "vuex";
import { Modal } from "bootstrap/dist/js/bootstrap";
import $ from "jquery";
export default {
setup() {
const store = useStore();
let bots = ref([]); // bot列表
const new_bot = reactive({ // 要新创建的bot对象
title: "",
description: "",
content: "",
error_message: "",
});
const get_bots = () => {
$.ajax({
url: "http://localhost:3000/user/bot/getlist/",
type: "GET",
headers: {
Authorization: "Bearer " + store.state.user.jwt_token,
},
success(resp) {
bots.value = resp; // 后端返回的就是一个列表
},
});
};
get_bots(); // 定义完后直接执行一遍
const add_bot = () => {
new_bot.error_message = "";
$.ajax({
url: "http://localhost:3000/user/bot/add/",
type: "POST",
data: {
title: new_bot.title,
description: new_bot.description,
content: new_bot.content,
},
headers: {
Authorization: "Bearer " + store.state.user.jwt_token,
},
success(resp) {
if (resp.result === "success") {
// 需要清空信息防止下次打开创建模态框时还留有上次的信息
new_bot.title = "";
new_bot.description = "";
new_bot.content = "";
Modal.getInstance("#add_bot_modal").hide(); // 关闭模态框
get_bots(); // 刷新一下Bot列表
} else {
new_bot.error_message = resp.result;
}
},
});
};
const remove_bot = (bot) => {
$.ajax({
url: "http://localhost:3000/user/bot/remove/",
type: "POST",
data: {
bot_id: bot.id,
},
headers: {
Authorization: "Bearer " + store.state.user.jwt_token,
},
success(resp) {
if (resp.result === "success") {
Modal.getInstance("#remove_bot_modal_" + bot.id).hide();
get_bots();
}
},
});
};
const update_bot = (bot) => {
new_bot.error_message = "";
$.ajax({
url: "http://localhost:3000/user/bot/update/",
type: "POST",
data: {
bot_id: bot.id,
title: bot.title,
description: bot.description,
content: bot.content,
},
headers: {
Authorization: "Bearer " + store.state.user.jwt_token,
},
success(resp) {
if (resp.result === "success") {
Modal.getInstance("#update_bot_modal_" + bot.id).hide();
get_bots();
} else {
new_bot.error_message = resp.result;
}
},
});
};
return {
bots,
new_bot,
add_bot,
remove_bot,
update_bot,
};
},
};
</script>
<style scoped></style>
注意,我们实现了当点击创建 Bot 按钮时弹出一个模态框(Bootstrap 中的 Modal)的效果,然后用户可以在里面编辑 Bot 的信息。但对于每个 Bot 的修改和删除应该都会分别对应一个模态框,而不像创建那样只有一个模态框,因此每个模态框还需要加一个 ID 来对应。
2. POJO时区修改
现在我们会发现前端页面中显示的 Bot 创建时间和后端数据库中的不一致,需要在 pojo
中的 Bot
类中修改:
package com.kob.backend.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Bot {
@TableId(value = "id", type = IdType.AUTO) // 声明id为自增类型
private Integer id;
private Integer userId; // 注意驼峰命名,userId之后会被解析为user_id,别写成userID,因为这样会解析成user_i_d
private String title;
private String description;
private String content;
private Integer rating;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") // 注意日期格式和时区的设置
private Date createtime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date modifytime;
}
3. 集成代码编辑器
由于 Bot 的内容有代码部分,之前我们用的是 <textarea>
让用户编写代码,这样编写体验不好,因此我们需要集成一个代码编辑器,我们使用的是 Vue Ace Editor(Ace GitHub 官网:Ace (Ajax.org Cloud9 Editor),Vue 3 版 Ace GitHub 官网:vue3-ace-editor)。
先在 Vue 的控制台中安装以下依赖:
vue3-ace-editor
ace-builds
然后就可以用 <VAceEditor>
替代之前的 <textarea>
:
<template>
<div class="container">
<div class="card text-bg-secondary" style="margin-top: 20px;">
...
<div class="card-body" style="background-color: rgba(255, 255, 255, 0.5);">
<div class="row">
...
<div class="col-md-9">
<div class="card">
<div class="card-header">
...
<!-- 创建 Bot 的模态框 -->
<div class="modal fade" id="add_bot_modal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
...
<div class="modal-body">
...
<div class="mb-3">
<label for="content" class="form-label">代码</label>
<VAceEditor
v-model:value="new_bot.content"
@init="editorInit"
lang="c_cpp"
theme="textmate"
style="height: 400px"
:options="{
enableBasicAutocompletion: true, //启用基本自动完成
enableSnippets: true, // 启用代码段
enableLiveAutocompletion: true, // 启用实时自动完成
fontSize: 16, //设置字号
tabSize: 4, // 标签大小
showPrintMargin: false, //去除编辑器里的竖线
highlightActiveLine: true, // 选中行高亮显示
}"
/>
</div>
</div>
...
</div>
</div>
</div>
</div>
<!-- 用户的 Bot 列表 -->
<div class="card-body">
<table class="table table-striped table-hover">
...
<tbody>
<tr v-for="bot in bots" :key="bot.id">
<td style="line-height: 32px;">{{ bot.title }}</td>
<td style="line-height: 32px;">{{ bot.createtime }}</td>
<td>
...
<!-- 修改 Bot 的模态框 -->
<div class="modal fade" :id="'update_bot_modal_' + bot.id" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
...
<div class="modal-body">
...
<div class="mb-3">
<label for="content" class="form-label">代码</label>
<VAceEditor
v-model:value="bot.content"
@init="editorInit"
lang="c_cpp"
theme="textmate"
style="height: 400px"
:options="{
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 16,
tabSize: 4,
showPrintMargin: false,
highlightActiveLine: true,
}"
/>
</div>
</div>
...
</div>
</div>
</div>
<!-- 删除 Bot 的确认模态框 -->
...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
...
import { VAceEditor } from "vue3-ace-editor";
import ace from "ace-builds";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-chrome";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/mode-c_cpp";
export default {
components: {
VAceEditor,
},
setup() {
ace.config.set(
"basePath",
"https://cdn.jsdelivr.net/npm/ace-builds@" +
require("ace-builds").version +
"/src-noconflict/");
...
},
};
</script>
<style scoped></style>