diff --git a/.gitignore b/.gitignore index 9c28553..31f33a0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ **/.idea/** **/target/** +**/node_modules/** + +**/*.iml + *.iml # Package Files # diff --git a/vueblog-java/pom.xml b/vueblog-java/pom.xml index 16e8245..15bb90b 100644 --- a/vueblog-java/pom.xml +++ b/vueblog-java/pom.xml @@ -55,6 +55,12 @@ 3.2.0 + + + org.springframework.boot + spring-boot-starter-freemarker + + org.crazycake @@ -76,12 +82,6 @@ 0.9.1 - - - org.springframework.boot - spring-boot-starter-freemarker - - org.springframework.boot spring-boot-starter-test diff --git a/vueblog-java/src/main/java/com/markerhub/config/ShiroConfig.java b/vueblog-java/src/main/java/com/markerhub/config/ShiroConfig.java index 46d2ddd..5bb6e48 100644 --- a/vueblog-java/src/main/java/com/markerhub/config/ShiroConfig.java +++ b/vueblog-java/src/main/java/com/markerhub/config/ShiroConfig.java @@ -97,7 +97,7 @@ public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityMan } - // 注解代理 + // 开启注解代理 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); diff --git a/vueblog-java/src/main/java/com/markerhub/controller/AccountController.java b/vueblog-java/src/main/java/com/markerhub/controller/AccountController.java index 51c8916..23bb127 100644 --- a/vueblog-java/src/main/java/com/markerhub/controller/AccountController.java +++ b/vueblog-java/src/main/java/com/markerhub/controller/AccountController.java @@ -9,12 +9,12 @@ import com.markerhub.entity.User; import com.markerhub.service.UserService; import com.markerhub.util.JwtUtils; +import com.markerhub.util.ShiroUtil; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; @@ -31,7 +31,6 @@ public class AccountController { * 默认账号密码:markerhub / 111111 * */ - @CrossOrigin @PostMapping("/login") public Result login(@Validated @RequestBody LoginDto loginDto, HttpServletResponse response) { @@ -57,4 +56,11 @@ public Result login(@Validated @RequestBody LoginDto loginDto, HttpServletRespon ); } + @GetMapping("/logout") + @RequiresAuthentication + public Result logout() { + SecurityUtils.getSubject().logout(); + return Result.succ(null); + } + } diff --git a/vueblog-java/src/main/java/com/markerhub/controller/BlogController.java b/vueblog-java/src/main/java/com/markerhub/controller/BlogController.java index 85045f1..516b504 100644 --- a/vueblog-java/src/main/java/com/markerhub/controller/BlogController.java +++ b/vueblog-java/src/main/java/com/markerhub/controller/BlogController.java @@ -1,16 +1,20 @@ package com.markerhub.controller; +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.markerhub.common.lang.Result; import com.markerhub.entity.Blog; import com.markerhub.service.BlogService; +import com.markerhub.util.ShiroUtil; import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.Assert; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; @RestController public class BlogController { @@ -19,19 +23,17 @@ public class BlogController { BlogService blogService; @GetMapping("/blogs") - @RequiresAuthentication public Result blogs(Integer currentPage) { if(currentPage == null || currentPage < 1) currentPage = 1; Page page = new Page(currentPage, 10); - IPage pageData = blogService.page(page); + IPage pageData = blogService.page(page, new QueryWrapper().orderByDesc("created")); return Result.succ(pageData); } @GetMapping("/blog/{id}") - @RequiresAuthentication public Result detail(@PathVariable(name = "id") Long id) { Blog blog = blogService.getById(id); @@ -39,4 +41,28 @@ public Result detail(@PathVariable(name = "id") Long id) { return Result.succ(blog); } + + @RequiresAuthentication + @PostMapping("/blog/edit") + public Result edit(@Validated @RequestBody Blog blog) { + + System.out.println(blog.toString()); + + Blog temp = null; + if(blog.getId() != null) { + temp = blogService.getById(blog.getId()); + Assert.isTrue(temp.getUserId() == ShiroUtil.getProfile().getId(), "没有权限编辑"); + } else { + temp = new Blog(); + temp.setUserId(ShiroUtil.getProfile().getId()); + temp.setCreated(LocalDateTime.now()); + temp.setStatus(0); + } + + BeanUtil.copyProperties(blog, temp, "id", "userId", "created", "status"); + + blogService.saveOrUpdate(temp); + + return Result.succ("操作成功", null); + } } diff --git a/vueblog-java/src/main/java/com/markerhub/controller/UserController.java b/vueblog-java/src/main/java/com/markerhub/controller/UserController.java new file mode 100644 index 0000000..e1c0e3a --- /dev/null +++ b/vueblog-java/src/main/java/com/markerhub/controller/UserController.java @@ -0,0 +1,32 @@ +package com.markerhub.controller; + +import com.markerhub.entity.User; +import com.markerhub.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/user") +public class UserController { + + @Autowired + UserService userService; + + @GetMapping("/{id}") + public Object test(@PathVariable("id") Long id) { + return userService.getById(id); + } + + + /** + * 测试实体校验 + * @param user + * @return + */ + @PostMapping("/save") + public Object testUser(@Validated @RequestBody User user) { + return user.toString(); + } + +} diff --git a/vueblog-java/src/main/java/com/markerhub/entity/Blog.java b/vueblog-java/src/main/java/com/markerhub/entity/Blog.java index 8154dee..b1a27bd 100644 --- a/vueblog-java/src/main/java/com/markerhub/entity/Blog.java +++ b/vueblog-java/src/main/java/com/markerhub/entity/Blog.java @@ -5,10 +5,14 @@ import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import javax.validation.constraints.NotBlank; + /** *

* @@ -28,12 +32,18 @@ public class Blog implements Serializable { @TableId(value = "id", type = IdType.AUTO) private Long id; + private Long userId; + + @NotBlank(message = "标题不能为空") private String title; + @NotBlank(message = "摘要不能为空") private String description; + @NotBlank(message = "内容不能为空") private String content; + @JsonFormat(pattern = "yyyy-MM-dd") private LocalDateTime created; private Integer status; diff --git a/vueblog-java/src/main/java/com/markerhub/shiro/AccountProfile.java b/vueblog-java/src/main/java/com/markerhub/shiro/AccountProfile.java index 6cbde84..01753c1 100644 --- a/vueblog-java/src/main/java/com/markerhub/shiro/AccountProfile.java +++ b/vueblog-java/src/main/java/com/markerhub/shiro/AccountProfile.java @@ -9,5 +9,6 @@ public class AccountProfile implements Serializable { private Long id; private String username; + private String avatar; } diff --git a/vueblog-java/src/main/java/com/markerhub/shiro/JwtFilter.java b/vueblog-java/src/main/java/com/markerhub/shiro/JwtFilter.java index 7915fa1..cc0ce0e 100644 --- a/vueblog-java/src/main/java/com/markerhub/shiro/JwtFilter.java +++ b/vueblog-java/src/main/java/com/markerhub/shiro/JwtFilter.java @@ -1,8 +1,6 @@ package com.markerhub.shiro; -import cn.hutool.http.HttpStatus; import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.extension.api.R; import com.markerhub.common.lang.Result; import com.markerhub.util.JwtUtils; import io.jsonwebtoken.Claims; diff --git a/vueblog-java/src/main/java/com/markerhub/util/ShiroUtil.java b/vueblog-java/src/main/java/com/markerhub/util/ShiroUtil.java new file mode 100644 index 0000000..30122d7 --- /dev/null +++ b/vueblog-java/src/main/java/com/markerhub/util/ShiroUtil.java @@ -0,0 +1,12 @@ +package com.markerhub.util; + +import com.markerhub.shiro.AccountProfile; +import org.apache.shiro.SecurityUtils; + +public class ShiroUtil { + + public static AccountProfile getProfile() { + return (AccountProfile)SecurityUtils.getSubject().getPrincipal(); + } + +} diff --git a/vueblog-java/src/main/resources/application.yml b/vueblog-java/src/main/resources/application.yml index aa30f71..9fd9614 100644 --- a/vueblog-java/src/main/resources/application.yml +++ b/vueblog-java/src/main/resources/application.yml @@ -4,7 +4,7 @@ server: spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/vueblog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC + url: jdbc:mysql://localhost:3306/vueblog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: admin mybatis-plus: diff --git a/vueblog-vue/package.json b/vueblog-vue/package.json index 3567b8c..a1af810 100644 --- a/vueblog-vue/package.json +++ b/vueblog-vue/package.json @@ -10,6 +10,8 @@ "axios": "^0.19.2", "core-js": "^3.6.4", "element-ui": "^2.13.1", + "markdown-it": "^11.0.0", + "mavon-editor": "^2.9.0", "vue": "^2.6.11", "vue-router": "^3.1.6", "vuex": "^3.1.3" diff --git a/vueblog-vue/src/components/Header.vue b/vueblog-vue/src/components/Header.vue new file mode 100644 index 0000000..9b578b6 --- /dev/null +++ b/vueblog-vue/src/components/Header.vue @@ -0,0 +1,80 @@ + + + + + \ No newline at end of file diff --git a/vueblog-vue/src/components/HelloWorld.vue b/vueblog-vue/src/components/HelloWorld.vue deleted file mode 100644 index b9f3c7d..0000000 --- a/vueblog-vue/src/components/HelloWorld.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - diff --git a/vueblog-vue/src/main.js b/vueblog-vue/src/main.js index 7db3079..0c67e91 100644 --- a/vueblog-vue/src/main.js +++ b/vueblog-vue/src/main.js @@ -4,9 +4,15 @@ import router from './router' import axios from 'axios' import store from './store' import Element from 'element-ui' +import editor from "mavon-editor"; + import "element-ui/lib/theme-chalk/index.css" +import 'mavon-editor/dist/css/index.css' + +import './permission.js' Vue.use(Element) +Vue.use(editor) Vue.config.productionTip = false Vue.prototype.$axios = axios // diff --git a/vueblog-vue/src/permission.js b/vueblog-vue/src/permission.js new file mode 100644 index 0000000..d67c669 --- /dev/null +++ b/vueblog-vue/src/permission.js @@ -0,0 +1,26 @@ +import router from "./router"; + +// 路由判断登录 根据路由配置文件的参数 +router.beforeEach((to, from, next) => { + + if (to.matched.some(record => record.meta.requireAuth)) { // 判断该路由是否需要登录权限 + + const token = localStorage.getItem("token") + console.log("------------" + token) + + if (token) { // 判断当前的token是否存在 ; 登录存入的token + if (to.path === '/login') { + + } else { + next() + } + } else { + next({ + path: '/login', + // query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由 + }) + } + } else { + next() + } +}) \ No newline at end of file diff --git a/vueblog-vue/src/router/index.js b/vueblog-vue/src/router/index.js index 9f5191e..c857b62 100644 --- a/vueblog-vue/src/router/index.js +++ b/vueblog-vue/src/router/index.js @@ -1,15 +1,16 @@ import Vue from 'vue' import VueRouter from 'vue-router' -import Home from '../views/Home.vue' import Login from '../views/Login.vue' +import BlogDetail from '../views/BlogDetail.vue' +import BlogEdit from '../views/BlogEdit.vue' Vue.use(VueRouter) const routes = [ { path: '/', - name: 'Login', - component: Login + name: 'Index', + redirect: { name: 'Blogs' } }, { path: '/login', @@ -23,10 +24,25 @@ const routes = [ component: () => import('../views/Blogs.vue') }, { - path: '/about', - name: 'About', - // 懒加载 - component: () => import('../views/About.vue') + path: '/blog/:blogId', + name: 'BlogDetail', + component: BlogDetail + }, + { + path: '/blog/add', + name: 'BlogEdit', + meta: { + requireAuth: true + }, + component: BlogEdit + }, + { + path: '/blog/:blogId/edit', + name: 'BlogEdit', + meta: { + requireAuth: true + }, + component: BlogEdit } ]; diff --git a/vueblog-vue/src/store/index.js b/vueblog-vue/src/store/index.js index 0eb7207..00ea83f 100644 --- a/vueblog-vue/src/store/index.js +++ b/vueblog-vue/src/store/index.js @@ -16,6 +16,11 @@ export default new Vuex.Store({ SET_USERINFO: (state, userInfo) => { state.userInfo = userInfo sessionStorage.setItem("userInfo", JSON.stringify(userInfo)) + }, + REMOVE_INFO: (state) => { + localStorage.setItem("token", '') + sessionStorage.setItem("userInfo", JSON.stringify('')) + state.userInfo = {} } }, getters: { diff --git a/vueblog-vue/src/views/About.vue b/vueblog-vue/src/views/About.vue deleted file mode 100644 index 3fa2807..0000000 --- a/vueblog-vue/src/views/About.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/vueblog-vue/src/views/BlogDetail.vue b/vueblog-vue/src/views/BlogDetail.vue new file mode 100644 index 0000000..49bc831 --- /dev/null +++ b/vueblog-vue/src/views/BlogDetail.vue @@ -0,0 +1,82 @@ + + + + + \ No newline at end of file diff --git a/vueblog-vue/src/views/BlogEdit.vue b/vueblog-vue/src/views/BlogEdit.vue new file mode 100644 index 0000000..9ba572d --- /dev/null +++ b/vueblog-vue/src/views/BlogEdit.vue @@ -0,0 +1,113 @@ + + + + + \ No newline at end of file diff --git a/vueblog-vue/src/views/Blogs.vue b/vueblog-vue/src/views/Blogs.vue index 9726199..d82f51b 100644 --- a/vueblog-vue/src/views/Blogs.vue +++ b/vueblog-vue/src/views/Blogs.vue @@ -1,21 +1,14 @@ @@ -75,7 +58,12 @@ width: 960px; margin: 0 auto; } + .m-content { text-align: center; } + + .maction { + margin: 10px 0; + } \ No newline at end of file diff --git a/vueblog-vue/src/views/Home.vue b/vueblog-vue/src/views/Home.vue deleted file mode 100644 index 1ba0c2e..0000000 --- a/vueblog-vue/src/views/Home.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/vueblog-vue/src/views/Login.vue b/vueblog-vue/src/views/Login.vue index 64fffc5..2a9f4a8 100644 --- a/vueblog-vue/src/views/Login.vue +++ b/vueblog-vue/src/views/Login.vue @@ -2,8 +2,10 @@

+ +