layui设置按钮不可点击_(eblog)7、博客发布收藏、用户中心的设置
小Hub領(lǐng)讀:
繼續(xù)我們的eblog,今天來完成博客文章收藏,用戶中心的設(shè)置!
項目名稱:eblog
項目 Git 倉庫:https://github.com/MarkerHub/eblog(給個 star 支持哈)
項目演示地址:https://markerhub.com:8082
前幾篇項目講解文章:
1、(eblog)Github 上最值得學(xué)習(xí)的 Springboot 開源博客項目!
2、(eblog)小 Hub 手把手教你如何從 0 搭建一個開源項目架構(gòu)
3、(eblog)整合Redis,以及項目優(yōu)雅的異常處理與返回結(jié)果封裝
4、(eblog)用Redis的zset有序集合實現(xiàn)一個本周熱議功能
5、(eblog)自定義Freemaker標(biāo)簽實現(xiàn)博客首頁數(shù)據(jù)填充
1、用戶中心-1
上一篇文章中,我們已完成了用戶的登錄與注冊,現(xiàn)在我們來完成以下登錄之后可以操作的事情,比如進(jìn)入用戶中心等
我的主頁
首先我們來看看我的主頁:
這是點擊用戶主頁之后的顯示效果,上面是用戶的基本信息,左邊是最近發(fā)表的文章,右邊是最近的操作等(評論,發(fā)表等),最近操作部分我們暫時就不弄了,課下大家自行完成。
所以這個頁面要完成很簡單,只需要把用戶的基本信息,和最近的文章傳到頁面就行了:
com.example.controller.UserController
@Controller
public class UserController extends BaseController{
@RequestMapping("/user/{id:\\d*}")
public String home(@PathVariable Long id) {
User user = userService.getById(id);
user.setPassword(null);
//30天內(nèi)容的文章
Date date30Before = DateUtil.offsetDay(new Date(), -30).toJdkDate();
List<Post> posts = postService.list(new QueryWrapper<Post>()
.eq("user_id", id)
.ge("created", date30Before)
.orderByDesc("created"));
req.setAttribute("user", user);
req.setAttribute("posts", posts);
return "user/home";
}
}
至于頁面,就是直接展示數(shù)據(jù),就不再多說了!~
用戶中心
點擊用戶中心后,是個tab標(biāo)簽,分為我發(fā)的貼和我收藏的貼
我發(fā)的貼
先來看看我發(fā)的貼,這個直接安裝userId查詢post就完成了
com.example.controller.CenterController
@GetMapping("")
public String index() {
Page page = getPage();
log.info("-------------->進(jìn)入個人中心");
QueryWrapper<Post> wrapper = new QueryWrapper<Post>().eq("user_id", getProfileId())
.orderByDesc("created");
IPage<Post> pageData = postService.page(page, wrapper);
req.setAttribute("pageData", pageData);
return "center/index";
}
好像沒啥知識點說的~
我收藏的貼
我收藏的貼,因為涉及到關(guān)聯(lián)表
UserCollection
Post
所以,需要關(guān)聯(lián)查詢
@GetMapping("/collection")
public String collection() {
Page page = getPage();
QueryWrapper queryWrapper = new QueryWrapper<>().eq("u.user_id", getProfileId()).orderByAsc("u.created");
IPage<Post> pageData = collectionService.paging(page, queryWrapper);
req.setAttribute("pageData", pageData);
return "center/collection";
}
collectionService.paging的最終mapper是這樣的:
<select id="selectPosts" resultType="com.example.entity.Post">
select *
from user_collection u
left join post p on u.post_id = p.id
${ew.customSqlSegment}
select>
所以我們的條件是u.userid。用u.來區(qū)分是哪個表的userid。 然后其他的頁碼的渲染,就直接是個宏搞定:
style="text-align: center">@page>
基本設(shè)置
我的資料
ok,上面的都比較簡單,我們來看看基本設(shè)置,這里涉及到表單提交和頭像修改等。
我的資料和密碼修改都只是簡單的表單提交,上次我們說過,表單提交都已經(jīng)幫我們封裝好的了,我們只需要返回的時候告訴表單提交成功之后的跳轉(zhuǎn)鏈接是啥,所以我的資料提交是這樣的:
com.example.controller.CenterController
@GetMapping("/setting")
public String setting() {
User user = userService.getById(getProfileId());
user.setPassword(null);
req.setAttribute("user", user);
return "center/setting";
}
@ResponseBody
@PostMapping("/setting")
public Result postSetting(User user) {
if(StringUtils.isEmpty(user.getUsername())){
return Result.fail("用戶名不能為空");
}
User tempUser = userService.getById(getProfileId());
// tempUser.setEmail(user.getEmail());
tempUser.setUsername(user.getUsername());
tempUser.setGender(user.getGender());
tempUser.setSign(user.getSign());
boolean isSucc = userService.updateById(tempUser);
if(isSucc) {
//更新shiro的信息
AccountProfile profile = getProfile();
profile.setUsername(user.getUsername());
profile.setGender(user.getGender());
}
return isSucc ? Result.succ("更新成功", null, "/center/setting"): Result.fail("更新失敗");
}
資料提交之后涉及到shiro登錄信息的修改,所以在updateById完成之后,我們獲取到shiro的用戶信息 AccountProfile profile = getProfile();,然后直接重新set搞定。 前端需要注意的是,我在確認(rèn)按鈕那里加了alert=*"true"*
class="layui-btn" key="set-mine" lay-filter="*" lay-submit alert="true">確認(rèn)修改
頭像
頭像設(shè)計到圖片上傳,
com.example.controller.CenterController
@ResponseBody
@PostMapping("/upload")
public Result upload(@RequestParam(value = "file") MultipartFile file,
@RequestParam(name="type", defaultValue = "avatar") String type) {
if(file.isEmpty()) {
return Result.fail("上傳失敗");
}
// 獲取文件名
String fileName = file.getOriginalFilename();
log.info("上傳的文件名為:" + fileName);
// 獲取文件的后綴名
String suffixName = fileName.substring(fileName.lastIndexOf("."));
log.info("上傳的后綴名為:" + suffixName);
// 文件上傳后的路徑
String filePath = constant.getUploadDir();
if ("avatar".equalsIgnoreCase(type)) {
fileName = "/avatar/avatar_" + getProfileId() + suffixName;
} else if ("post".equalsIgnoreCase(type)) {
fileName = "/post/post_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + suffixName;
}
File dest = new File(filePath + fileName);
// 檢測是否存在目錄
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest);
log.info("上傳成功后的文件路徑未:" + filePath + fileName);
String path = filePath + fileName;
String url = constant.getUploadUrl() + fileName;
log.info("url ---> {}", url);
User current = userService.getById(getProfileId());
current.setAvatar(url);
userService.updateById(current);
//更新shiro的信息
AccountProfile profile = getProfile();
profile.setAvatar(url);
return Result.succ(url);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return Result.succ(null);
}
上面的邏輯其實還是很簡單的,首先獲取到圖片,重命名,并保存到指定位置,然后更新user,在更新shiro的頭像信息。 文件復(fù)制就這一行代碼重要
file.transferTo(dest);
其他都比較固定了。 另外,因為我們的圖片位置是存放在根目錄下的:
這涉及到一些靜態(tài)資源的加載問題,所以我們需要在mvc配置中添加這個靜態(tài)資源的位置,
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
Constant constant;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/upload/avatar/**")
.addResourceLocations("file:///" + constant.getUploadDir() + "/avatar/");
}
}
上面的WebMvcConfig重寫了addResourceHandlers方法,把upload的文件夾讀取進(jìn)去了,然后Constant 是個加載的常量,我提取到了配置文件中
com.example.common.lang.Constant
@Data
@Component
public class Constant {
@Value("${file.upload.dir}")
private String uploadDir;
@Value("${file.upload.url}")
private String uploadUrl;
}
然后配置文件是這樣的:
application.yml
file:
upload:
dir: ${user.dir}/upload
url: http://localhost:8080/upload
user.dir表示用戶根路徑,當(dāng)然了,現(xiàn)在圖片我是直接存在了本地硬盤上,同學(xué)們可以自行拓展上傳到七牛云等云盤上。 所以上面的圖片上的avatar5.png,我們的訪問路徑是:http://localhost:8080/upload/avatar/avatar5.png
密碼
密碼修改也只是一個簡單的form表單提交
@ResponseBody
@PostMapping("/repass")
public Result repass(String nowpass, String pass, String repass) {
if(!pass.equals(repass)) {
return Result.fail("兩次密碼不相同");
}
User user = userService.getById(getProfileId());
String nowPassMd5 = SecureUtil.md5(nowpass);
if(!nowPassMd5.equals(user.getPassword())) {
return Result.fail("密碼不正確");
}
user.setPassword(SecureUtil.md5(pass));
userService.updateById(user);
return Result.succ("更新成功", null, "/center/setting");
}
貌似沒啥說的?
我的消息
展示消息
我的消息包括兩種,一個是系統(tǒng)消息,一個是別人評論了我的文章,或者收藏了我的文章等類型。
這里我就搞了兩種,com.example.entity.UserMessage的type設(shè)置了2中類型:
type消息類型,1評論消息,2系統(tǒng)消息
頁面展示的時候我們需要根據(jù)type的類型來選擇要展示的數(shù)據(jù)樣式,我們先來看下實體的結(jié)構(gòu)
CREATE TABLE `user_message` (
? `id` bigint(20) NOT NULL AUTO_INCREMENT,
? `from_user_id` bigint(20) DEFAULT NULL COMMENT '發(fā)送消息的用戶ID',
? `to_user_id` bigint(20) NOT NULL COMMENT '接收消息的用戶ID',
? `post_id` bigint(20) DEFAULT NULL COMMENT '消息可能關(guān)聯(lián)的帖子',
? `comment_id` bigint(20) DEFAULT NULL COMMENT '消息可能關(guān)聯(lián)的評論',
? `content` text,
? `type` tinyint(2) DEFAULT NULL COMMENT '消息類型,1評論消息,2系統(tǒng)消息',
? `created` datetime NOT NULL,
? `modified` datetime DEFAULT NULL,
? PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
這個表里面有很多廣關(guān)聯(lián)的id,那么在頁面展示的時候我們需要展示評論詳情,用戶來源,評論文章標(biāo)題等的時候就需要關(guān)聯(lián)很多表,所以在寫sql的時候我們采用了另一種方式來完成,我們先來看看vo:
@Data
public class MessageVo extends UserMessage {
private String toUserName;
private String fromUserName;
private String postTitle;
private String commentContent;
}
上面就是我們的數(shù)據(jù)需要展示的內(nèi)容,如何才能讓sql都查出來呢,我們來看看sql:
id="selectMessages" resultType="com.example.vo.MessageVo">
SELECT m.*,
( SELECT username FROM `user` WHERE id = m.to_user_id ) AS toUserName,
( SELECT username FROM `user` WHERE id = m.from_user_id ) AS fromUserName,
( SELECT title FROM `post` WHERE id = m.post_id ) AS postTitle,
( SELECT content FROM `comment` WHERE id = m.comment_id ) AS commentContent
FROM `user_message` m
${ew.customSqlSegment}
可以看到上面的內(nèi)容,我在select的內(nèi)容中又select了一遍,比如根據(jù)touserid 查出toUserName等。所以我們寫起來就簡單了。 編碼的時候我們就直接通過這個sql查詢出結(jié)果:
@GetMapping("/message")
public String message() {
Page<UserMessage> page = getPage();
QueryWrapper wrapper = new QueryWrapper<UserMessage>()
.eq("to_user_id", getProfileId())
.orderByDesc("created");
IPage<MessageVo> pageData = userMessageService.paging(page, wrapper);
req.setAttribute("pageData", pageData);
return "center/message";
}
頁面端根據(jù)type來展示數(shù)據(jù)
href="/user/${mess.fromUserId}" target="_blank">${mess.fromUserName}評論了您的文章 target="_blank" href="${base}/post/${mess.postId}">${mess.postTitle}
#if>
系統(tǒng)消息:${mess.content}
#if>
刪除消息
刪除的js原框架已經(jīng)幫我們完成了,所以我們只需要填充數(shù)據(jù),特別是data-id
data-id="${mess.id}">
刪除邏輯如下:
@ResponseBody
@PostMapping("/message/remove")
public Result removeMsg(Long id, boolean all) {
QueryWrapper<UserMessage> warapper = new QueryWrapper<UserMessage>()
.eq("to_user_id", getProfileId())
.eq(!all,"id", id);
//只能刪除自己的消息
boolean res = userMessageService.remove(warapper);
return res ? Result.succ("操作成功", null, "/center/message") : Result.fail("刪除失敗");
}
static/res/mods/user.js
上面的js有些鏈接需要修改下,大家注意一下
2、用戶中心-2
上面的用戶中心,我們完成了一些數(shù)據(jù)的展示,現(xiàn)在我們來床造一些數(shù)據(jù),比如發(fā)表文章,評論等。這就涉及到一些登錄后的權(quán)限問題,未登錄操作報錯提示等問題,我們在碼代碼的過程再作細(xì)節(jié)的調(diào)整。
發(fā)布編輯博客
我們先來看看評論的頁面
發(fā)布博客分為新發(fā)布和編輯發(fā)布,一般來說我們根據(jù)是否有傳博客id過來判斷,如果有id,那么我們就查詢出來,然后回顯數(shù)據(jù)提交更新,因為頁面都是一樣的,所以,新發(fā)布、編輯我們用了一個方法,從這個頁面可以看到,我們需要的數(shù)據(jù)有博客實體,還有分類列表,還有個驗證碼。
@GetMapping("/post/edit")
public String edit() {
String id = req.getParameter("id");
Post post = new Post();
if(!StringUtils.isEmpty(id)) {
post = postService.getById(Long.valueOf(id));
Assert.notNull(post, "文章已被刪除!");
Long profileId = getProfileId();
Assert.isTrue(post.getUserId()==getProfileId(), "無權(quán)限編輯此文章!");
}
List<Category> categories = categoryService.list(new QueryWrapper<Category>()
.orderByDesc("order_num"));
req.setAttribute("post", post);
req.setAttribute("categories", categories);
return "post/edit";
}
這個就是我們跳轉(zhuǎn)到編輯頁面的controller,從里面可以看到,我們通過id是否為空來判斷是否是編輯,如果是編輯,我們還用斷言來判斷一下文章是否已經(jīng)刪除,或者是否是自己發(fā)布的文章等。
延伸:斷言與異常
這里有個細(xì)節(jié),當(dāng)我們是新發(fā)布文章時候,那么我們傳過去的post就是個new Post(),屬性都是空的,所以我們在頁面中使用${post.title}時候freemaker會報錯,這時候我們需要解決這個問題,讓他不報錯,解決方法很簡單,我們只需要在配置文件中配置好freemaker在這種情況下不報錯就行了:
spring:
freemarker:
cache: false
settings:
classic_compatible: true
加上了classic_compatible=true之后,那么我們在剛才屬性為空的情況下我們就不會報錯了。?
好了,那么文章填充好內(nèi)容之后我們提交,<form?*action="/post/submit" *method=**"post">,我們寫一個submit方法,這里面我們需要考慮幾個問題:
Post必填字段是否文章和符合要求
如果是編輯,那么是否是自己的文章
認(rèn)證碼問題
好,接下來我們一一解決,首先來看下驗證碼問題,頁面中的“人類認(rèn)證”,應(yīng)該是是類似于注冊頁面的驗證碼問題來的,不過這里我就直接跳過了,直接寫死了1+1=2的答案,大家回去自行加上驗證碼的驗證,邏輯其實簡單,生成驗證碼放到session中,然后submit時候比較session中的認(rèn)證碼和提交的驗證碼對比即可,和注冊驗證碼一樣的邏輯。
驗證碼我寫死了:
if(!"2".equals(vercode)) {
return Result.fail("人類認(rèn)證錯誤!");
}
接下來看看post字段問題,我們以前講過一個框架hibernate validatior,剛好springboot自帶集成了這個框架,那么我們直接使用,使用方法是找到post實體,然后在字段上添加屬性的認(rèn)證邏輯,比如:
/**
* 標(biāo)題
*/
@Length(min = 4,max = 32, message = "標(biāo)題長度不能超過最少4位,最長32位")
@NotBlank(message = "標(biāo)題不能為空")
private String title;
/**
* 內(nèi)容
*/
@NotBlank(message = "內(nèi)容不能為空")
private String content;
@NotNull(message = "分類不能為空")
private Long categoryId;
然后submit方法中參數(shù)驗證post,需要注入到@Valid注解和BindingResult驗證結(jié)果。所以整體代碼是這樣的:
@ResponseBody
@Transactional
@PostMapping("/post/submit")
public Result submit(@Valid Post post, BindingResult bindingResult, String vercode) throws JsonProcessingException {
if(!"2".equals(vercode)) {
return Result.fail("人類認(rèn)證錯誤!");
}
if(bindingResult.hasErrors()) {
return Result.fail(bindingResult.getFieldError().getDefaultMessage());
}
if(post.getId() == null) {
post.setUserId(getProfileId());
post.setModified(new Date());
post.setCreated(new Date());
post.setCommentCount(0);
post.setEditMode(null);
post.setLevel(0);
post.setRecommend(false);
post.setViewCount(0);
post.setVoteDown(0);
post.setVoteUp(0);
} else {
Post tempPost = postService.getById(post.getId());
Assert.isTrue(tempPost.getUserId()==getProfileId(), "無權(quán)限編輯此文章!");
}
postService.saveOrUpdate(post);
return Result.succ("發(fā)布成功", null, "/post/" + post.getId());
}
可以看到submit(@Valid Post post, BindingResult bindingResult, String vercode)參數(shù)的使用,bindingResult.hasErrors()就是判斷提交的post是否符合驗證邏輯的。 后面說到的是否是自己的文章,只需要比較一下post.userId和當(dāng)前登錄的用戶id即可,直接使用斷言判斷。
那么這里我來延伸一個問題,斷言的用處。我們知道很多地方我們需要做一下校驗和判斷,從而知道數(shù)據(jù)是否符合預(yù)期的期望,如果不符合那么斷言就會拋出異常。
那么我們需要對斷言拋出的錯誤進(jìn)行一番處理,有兩種情況,同步方法或異步方法,當(dāng)同步的controller時候,我們跳轉(zhuǎn)到異常頁面,并把斷言的錯誤提示展示出來。那么異步的話,我們需要返回json數(shù)據(jù),彈窗提示斷言的錯誤提示。
在之前,我們已經(jīng)做過一個全局異常處理,我發(fā)現(xiàn)寫得不是很好,對我們斷言的錯誤處理不夠好,所以這里我調(diào)整了一下,我們通過req的header中是否包含X-Requested-With來判斷是否是異步的方法。然后通過獲取resp.getWriter()來寫入json數(shù)據(jù)。
com.example.common.exception.GlobalExceptionHandler
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) {
log.error("------------------>捕捉到全局異常", e);
if (req.getHeader("accept").contains("application/json") || (req.getHeader("X-Requested-With")!= null
&& req.getHeader("X-Requested-With").contains("XMLHttpRequest") )) {
try {
System.out.println(e.getMessage());
Result result = Result.fail(e.getMessage(), "some error data");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.write(JSONUtil.toJsonStr(result));
writer.flush();
} catch (IOException i) {
i.printStackTrace();
}
return null;
}
if(e instanceof HwException) {
//...
}
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("message", e.getMessage());
mav.addObject("url", req.getRequestURL());
mav.setViewName("error");
return mav;
}
}
刪除博客
上面我們已經(jīng)可以發(fā)布和編輯文章,我們可以在用戶中心的我發(fā)布的帖子中可以看到自己發(fā)布的文章,接下來我們來弄一下刪除博客,同樣道理,需要做一下簡單校驗
帖子是否存在
是否是自己的帖子
刪除與帖子相關(guān)的消息或收藏等
都比較簡單,所以我就直接給出代碼了,收藏功能我們雖然還沒做,但是刪除邏輯簡單,所以我們直接寫上去了。
@ResponseBody
@Transactional
@PostMapping("/post/delete")
public Result delete(Long id) {
Post post = postService.getById(id);
Assert.notNull(post, "該帖子已被刪除");
Assert.isTrue(post.getUserId()==getProfileId(), "無權(quán)限刪除此文章!");
postService.removeById(id);
// 刪除相關(guān)消息、收藏等
userMessageService.removeByMap(MapUtil.of("post_id", id));
userCollectionService.removeByMap(MapUtil.of("post_id", id));
return Result.succ("刪除成功", null, "/center");
}
大家主題調(diào)整一下js的url,原本的url不是/post/delete的,注意改過來~
發(fā)表刪除評論
渲染
接下來我們看下評論的功能,上一次我們已經(jīng)能把文章的評論功能展示出來了,但是有個bug,就是一些表情和圖片不能渲染出來,我們只是把內(nèi)容原原本本展示出來而已,基于layui的這個編輯器,我們還要做下渲染,我們先來完成這部分然后再作評論功能,其實簡單,模板中已經(jīng)給出了提示,如果我們用的是layui自帶的編輯器的話,我們需要加上那段代碼:
然后又因為layui加載模塊的js,我們寫在了layout.ftl模板上了,所以這里我們等頁面加載完成之后我們再渲染,這樣之前的js已經(jīng)渲染完成了。我們就用到了jq的$(function () {});。然后重要的就是othis.html(fly.content(html));渲染代碼了。
我們看到的效果是這樣的:?
好了,上面的div的類是detail-body都已經(jīng)得以渲染,包括文章內(nèi)容等部分。
發(fā)布
評論發(fā)布其實涉及到的東西還是挺多的,我們先來梳理一下
一下簡單邏輯判斷
文章的評論數(shù)量加一
側(cè)邊欄的本周熱議重新排行
通知文章作者有人評論了
通知@的用戶有人回復(fù)了你的評論
1、一下簡單邏輯判斷,其實就是判斷內(nèi)容是否為空等,沒啥說的,直接斷言判斷
@ResponseBody
@Transactional
@PostMapping("/post/reply")
public Result reply(Long pid, Long parentId, String content) {
Assert.notNull(pid, "找不到對應(yīng)文章!");
Assert.hasLength(content, "評論內(nèi)容不能為空!");
Post post = postService.getById(pid);
Assert.isTrue(post != null, "該文章已被刪除");
...
}
2、保存評論并文章評論數(shù)量加一
Comment comment = new Comment();
comment.setPostId(pid);
comment.setContent(content);
comment.setUserId(getProfileId());
comment.setCreated(new Date());
comment.setModified(new Date());
comment.setLevel(0);
comment.setVoteDown(0);
comment.setVoteUp(0);
commentService.save(comment);
// 評論數(shù)量加一
post.setCommentCount(post.getCommentCount() + 1);
postService.saveOrUpdate(post);
3、側(cè)邊欄的本周熱議功能
關(guān)于這個功能我們一開始就做了,但是好像考慮有點不周全,只有評論加一,沒有評論減一,因為后面刪除評論就需要減一了,所以我們調(diào)整一下postService.incrZsetValueAndUnionForLastWeekRank這個方法,加上一個參數(shù)*boolean *isIncr來判斷是增加還是減少。
大家注意一下所以調(diào)用了這個方法的地方都修改一下。
所以側(cè)邊欄的數(shù)量加一很簡單了,我們直接調(diào)用這個方法就搞定了
//更新首頁排版版的評論數(shù)量
postService.incrZsetValueAndUnionForLastWeekRank(comment.getPostId(), true);
4、通知作者
用戶中心的我的消息就是用來查看消息的,我們還要區(qū)分消息類型來展示不同的樣式。我們先把消息保存起來,但只是保存起來其實是不夠的,我們學(xué)過websocket,但有評論的時候我們應(yīng)該實時通知作者,這怎么做到呢,下一次作業(yè)我們會做好調(diào)整。我們先把消息保存起來。
// 通知作者
UserMessage message = new UserMessage();
message.setPostId(pid);
message.setCommentId(comment.getId());
message.setFromUserId(getProfileId());
message.setToUserId(post.getUserId());
message.setType(1);
message.setContent(comment.getContent());
message.setCreated(new Date());
userMessageService.save(message);
5、通知被@的用戶
當(dāng)我們點擊評論的回復(fù)按鈕時候,評論的輸入框中就會出現(xiàn)@當(dāng)前評論的用戶名稱,所以我們發(fā)布的評論需要告知這個用戶,根據(jù)@的特點,我們提取@與空格之間的用戶名稱,然后搜索出來再報錯消息。
// 通知@的人
if(content.startsWith("@")) {
String username = content.substring(1, content.indexOf(" "));
System.out.println(username);
QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", username);
User user = userService.getOne(wrapper);
if(user != null) {
UserMessage message2 = new UserMessage();
message.setPostId(pid);
message2.setCommentId(comment.getId());
message2.setFromUserId(getProfileId());
message2.setToUserId(user.getId());
message2.setType(3);
message2.setContent(comment.getContent());
message2.setCreated(new Date());
userMessageService.save(message2);
}
}
String username = content.substring(1, content.indexOf(" "));就是提取用戶名稱來的,那么這里又涉及到一個問題,就是用戶昵稱的唯一性問題,所以我們需要修改一下注冊的時候,我們也要加上昵稱唯一性的校驗。
com.example.service.impl.UserServiceImpl#register
User po = this.getOne(new QueryWrapper<User>().eq("email", user.getEmail()).or().eq("username", user.getUsername()));
if(po != null) {
return Result.fail("郵箱或昵稱已被注冊");
}
注意同步一下代碼~,其實用戶中心的修改用戶昵稱那里也需要加上唯一性校驗,大家自行完成。另外,我還在數(shù)據(jù)庫中加了唯一索引,保證字段的唯一。?
上面的方法,我們后期還需要調(diào)整,現(xiàn)在展示先這樣做。
刪除
評論的刪除也是差不多的邏輯
簡單校驗
評論刪除
評論數(shù)量減一
本周熱議重新排行
直接給出代碼了,有了添加的代碼邏輯,相信對刪除邏輯也應(yīng)該熟悉才行。
@ResponseBody
@Transactional
@PostMapping("/post/jieda-delete/")
public Result reply(Long id) {
Assert.notNull(id, "評論id不能為空!");
Comment comment = commentService.getById(id);
Assert.notNull(comment, "找不到對應(yīng)評論!");
if(comment.getUserId() != getProfileId()) {
return Result.fail("不是你發(fā)表的評論!");
}
commentService.removeById(id);
// 評論數(shù)量減一
Post post = postService.getById(comment.getPostId());
post.setCommentCount(post.getCommentCount() - 1);
postService.saveOrUpdate(post);
//評論數(shù)量減一
postService.incrZsetValueAndUnionForLastWeekRank(comment.getPostId(), false);
return Result.succ(null);
}
未登錄提示 什么是未登錄提示,之前我們做過未登錄跳轉(zhuǎn)到登錄頁面,其實我們依靠的都是shiro框架。一些涉及到用才能操作的就需要登錄之后才能完成,回顧一下我們學(xué)過的shiro內(nèi)容,有兩種方法:
配置式:在com.example.config.ShiroConfig#shiroFilter配置hashMap.put("/post/edit",?"auth");
或者注解形式在對應(yīng)方法上使用@RequiresAuthentication
auth是過濾器的別名,具體其實是AuthFilter。
所以大家記得,一些需要登錄才能操作的方法記得用這兩種形式標(biāo)記,不然可能用getProfileId()就會報錯。畢竟需要登錄之后才能操作的內(nèi)容!
?給eblog一個star,感謝支持哈
總結(jié)
以上是生活随笔為你收集整理的layui设置按钮不可点击_(eblog)7、博客发布收藏、用户中心的设置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c# 微服务学习_微服务:学习几个容易混
- 下一篇: java 线程 spring_java中