@ 跟着视频学习,刚开始就是跟着视频敲代码,然后再改改,不懂的地方语法什么的在网上搜索。不可能自己从头到尾完全独立的开发一个网站,现阶段第一次做项目,不可能自己造轮子。
Controller层调用Service层,Service层调用Dao层
目录
debug:
1.
login.html里面的login不亮,我以为是没成功调用,问群里面的兄弟后,告诉我login(){alert("111)},然后看会不会弹窗,结果有弹窗,但是会显示系统错误,然后没有跳转login的登陆界面。自己查资料查了两天都不会弄。最后在淘宝花了50块找大佬远程解决了。 首先笔记本上报错是因为数据库没连好,yml文件里面不应该是空的。还要在MySQLworkbench里面输入一句话,IDEA里面数据库文件的密码应该换成我自己的。 然后,login的问题并不是前端的问题,是后端错了。少了AdminInfo 和Account初始化,大佬说是打断点看出来的。
2.
安装vue的bug:
环境变量的“;”是中文的,造成cmd里面输入vue 显示vue不是内部命令。
解决方法:把";"换成英文符号。有一个技巧,因为环境变量里面符号很多肉眼一个个找很麻烦,把环境变量复制到记事本中,使用记事本的“全部替换”功能。
MD5加密登录:
1.调用hutool包
2.新增用户时自动赋值的密码通过MD5加密后保存到数据库
3.登录时将输入的密码通过MD5加密后与数据库的值比较
数据库中的数据
spring + vue 如何连接前后端
vue前端增加一个网址后要新建一个路由。
给项目添加权限管理功能
V-if
总结:角色权限控制就一个role 搞定!!
注册页改造
1.注册页跳转到登录
RegisterView.vue
<div style="text-align:center">
已有账号?<a href="javascript:void(0)" style="text-decoration: none "@click="navLogin()">点击登录</a>
</div>
navLogin(){
this.$router.push("/login");
}
2.注册的时候,支持选择角色
<el-form-item>
<el-select v-model="admin.role" placeholder="请选择" style="width: 80%">
<el-option label="教练" value="ROLE_COACH"></el-option>
<el-option label="学员" value="ROLE_STUDENT"></el-option>
</el-select>
</el-form-item>
文件上传和下载功能
@FileController
@RestController
@RequestMapping("/files")
public class FileController {
// 文件上传存储路径
private static final String filePath = System.getProperty("user.dir") + "/file/";
/**
* 文件上传
*/
@PostMapping("/upload")
public Result upload(MultipartFile file) {
synchronized (FileController.class) {
String flag = System.currentTimeMillis() + "";
String fileName = file.getOriginalFilename();
try {
if (!FileUtil.isDirectory(filePath)) {
FileUtil.mkdir(filePath);
}
// 文件存储形式:时间戳-文件名
FileUtil.writeBytes(file.getBytes(), filePath + flag + "-" + fileName);
System.out.println(fileName + "--上传成功");
Thread.sleep(1L);
} catch (Exception e) {
System.err.println(fileName + "--文件上传失败");
}
return Result.success(flag);
}
}
/**
* 获取文件
*/
@GetMapping("/{flag}")
public void avatarPath(@PathVariable String flag, HttpServletResponse response) {
if (!FileUtil.isDirectory(filePath)) {
FileUtil.mkdir(filePath);
}
OutputStream os;
List<String> fileNames = FileUtil.listFileNames(filePath);
String avatar = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");
try {
if (StrUtil.isNotEmpty(avatar)) {
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(avatar, "UTF-8"));
response.setContentType("application/octet-stream");
byte[] bytes = FileUtil.readBytes(filePath + avatar);
os = response.getOutputStream();
os.write(bytes);
os.flush();
os.close();
}
} catch (Exception e) {
System.out.println("文件下载失败");
}
}
}
遇到跨域问题加一个配置文件
@Configuration
public class CORSFilter {
@Bean
public CorsFilter corsFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return new CorsFilter(source);
}
}
下载图片( 加个点击事件@clidk="down(scope.row.image)" )
down(flag) {
location.href = 'http://localhost:8080/api/files/' + flag
}
预约功能优化
实先同一个课程一名用户只能预约一次
点击预约后,后台根据对应的预约人和预约课程查reserve数据库表,若能查到则显示“已经预约过该课程”
Lesson lesson = lessonDao.selectByPrimaryKey(reserve.getLessonId());
Reserve reserve1=reserveDao.selectByUserIdAndLessonId(reserve.getUserId(),reserve.getLessonId());
if (lesson.getNumber() == 0) {
return Result.error("课程已被预定完");
}
// 2.判断该用户是否选过该课程,如果选过了,就提示用户不能重复选课
else if (ObjectUtil.isNotEmpty(reserve1)) {
throw new CustomException("已经预约过此课程。");
}
Dao层
@Select("select * from reserve where userId = #{userId} and lessonId = #{lessonId}")
Reserve selectByUserIdAndLessonId(@Param("userId") Integer userId,@Param("lessonId") Integer lessonId);
个人中心页面
要求进入个人中心页面时,自动加载当时的个人信息(把user的信息传给form,因为调用时使用form.name等form的方法调用)。
export default {
data() {
return {
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {},
tableData: [],
form: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {},
}
},
但是有一个问题,用户点击确定修改后,因为表外调用的是user.name所以表外的名字没有改。所以我让用户修改完信息后需要重新登录。
邮箱发送找回密码功能
<el-form-item>
<el-button style="width: 80%; margin-top: 10px" type="primary" @click="sendemail()">找回密码</el-button>
</el-form-item>
sendemail() {
if(!this.admin.email){
this.$message.warning("请输入邮箱账号");
return;
}
// 判断邮箱格式是否正确
if(!/^\w+((.\w+)|(-\w+))@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/.test(this.admin.email)) {
this.$message.warning("请输入正确邮箱");
return;
}
request.get("/admin/email/" + this.admin.email).then(res => {
if (res.code === '0') {
this.$message.success("发送成功");
} else{
this.$message.error(res.msg);
}
})
},
(有一个bug,要是写成this.request.get来请求就会不成功)
@admincontroller
@GetMapping("/email/{email}")
public Result sendEmail(@PathVariable String email) {
if(StrUtil.isBlank(email)) {
throw new CustomException("请输入邮箱");
}
adminService.sendEmail(email);
return Result.success();
}
@adminservice
@Value("${spring.mail.username}")
private String from;
@Autowired
JavaMailSender javaMailSender;
public void sendEmail(String email) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(email);
message.setSubject("验证一下能不能使用");
message.setText("测试邮箱内容");
javaMailSender.send(message);
}
application.yml
mail:
protocol: smtps
host: smtp.163.com
username: 18020106701@163.com
password: KPTHLJVWPYUFMLYD
port: 465
default-encoding: UTF-8
password是在网易云163邮箱里面获得
点开启服务,发送短信验证码开启后获得Password
评论功能
comment表
createtime 要设置CURRENT_TIMESTAMP,自动生成时间
前端写评论弹框界面
<el-dialog title="评论" :visible.sync="viewFormVisible" width="60%">
<el-input type="textarea" placeholder="请输入评论" v-model="comment.content"></el-input>
<div style="text-align: right; margin: 10px 0 ">
<el-button type="primary" @click="sub()">提交</el-button>
</div>
<div style="margin: 20px 0">
<div style="margin: 10px 0 ;font-size: 20px ;padding: 10px 0; border-bottom: 1px solid #ccc;text-align: left">评论列表</div>
</div>
<div style="margin: 20px 0; text-align: left">
<div style="padding: 10px 0; display: flex" v-for="item in comments" :key="item.id">
<div>
<el-image
style="width: 50px; height: 50px; border-radius: 50%"
:src=" 'http://localhost:8080/api/files/' + item.useravatar "
:preview-src-list="['http://localhost:8080/api/files/' + item.useravatar ]">
</el-image>
</div>
<div style="flex: 1; margin-left: 15px">
<div>{{item.username}}</div>
<div style="margin-top: 10px">{{item.content}}</div>
</div>
</div>
</div>
</el-dialog>
export default {
data() {
return {
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {},
params: {
name:'',
phone:'',
pageNum: 1,
pageSize: 5,
},
tableData: [],
total: 0,
dialogFormVisible: false,
editVisible: false,
viewFormVisible: false,
form: {},
//coments是后台根据该Foreign_id查到的所有评论内容和评论人用户名头像
comments: [],
//comment将内容传到后台
comment: {
content:'',
}
}
},
注意:
this.load(this.comment.foreign_id)这样才能正确传输foreign_id。刚开始写错了,后台会拿不到数据。
view(row) {
this.viewFormVisible = true;
this.comment = {
content: ''
}
this.comment.foreign_id = row.id;
this.load(this.comment.foreign_id);
},
//加载出对应帖子id的评论
load(id) {
request.get("/comment/" + id).then( res =>{
this.comments = res.data;
})
},
//把comment里面的数据传给后台
sub(){
this.comment.user_id = this.user.id
this.comment.username = this.user.name
this.comment.useravatar = this.user.avatar
request.post("/comment",JSON.stringify(this.comment)).then( res => {
if(res.code === '0'){
this.$message.success("成功")
} else{
this.$message.error(res.data)
}
})
},
@comment.entity
@Table(name="comment")
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String content;
private String username;
private Integer user_id;
private Integer foreign_id;
private String target;
private String useravatar;
@JsonFormat(pattern = "yyyy-mm-dd HH:mm:ss")
private LocalDateTime createtime;
}
@CommentController
@RestController
@RequestMapping("/comment")
public class CommentController {
@Resource
CommentService commentService;
@Resource
CommentDao commentDao;
@PostMapping
public Result save(@RequestBody Comment comment) {
if(comment.getId() == null ){
commentService.add(comment);
} else {
commentService.update(comment);
}
return Result.success();
}
//根据帖子的id查找评论
@GetMapping("/{id}")
public Result list(@PathVariable("id") Integer foreign_id){
List<Comment> comments = commentDao.findAllByForeign_Id(foreign_id);
return Result.success(comments) ;
}
}
@CommentService
@Service
public class CommentService {
@Resource
private CommentDao commentDao;
public void add(Comment comment) {
commentDao.insertSelective(comment);
}
public void update(Comment comment) {
commentDao.updateByPrimaryKeySelective(comment);
}
public void delete(Integer id) {
commentDao.deleteByPrimaryKey(id);
}
}
@CommentDao
public interface CommentDao extends Mapper<Comment> {
@Select("select * from comment where foreign_id = #{foreign_id}")
List<Comment> findAllByForeign_Id(@Param("foreign_id") Integer foreignId);
}