提交 0e5f0a6c 编写于 作者: 喷火的神灵's avatar 喷火的神灵 🎱

新增模块说明

上级 333f2b13
{
"description":"",
"directory":"~.fastRequest~collections~Root~Default Group",
"filePath":"~.fastRequest~collections~Root~Default Group~",
"groupId":"1",
"id":"1",
"name":"Default Group",
"type":1
}
\ No newline at end of file
{
"description":"",
"directory":"~.fastRequest~collections~Root",
"filePath":"~.fastRequest~collections~Root~",
"groupId":"-1",
"id":"0",
"name":"Root",
"type":1
}
\ No newline at end of file
{
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~AccountController",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~AccountController~",
"name":"AccountController",
"type":3
}
\ No newline at end of file
{
"activeGroup":"Default",
"apiParamGroup":{},
"childList":[],
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~AccountController",
"domain":"http://localhost:8089",
"enableEnv":"local",
"enableProject":"youbili-project-backend",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~AccountController~login.rapi",
"headerList":[
{
"enabled":true,
"type":"Authorization",
"value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpdGllc0pzb25TdHJpbmciOiJbXSIsInVzZXJJRCI6MywidXNlcm5hbWUiOiJ3YW5nd3UiLCJleHAiOjE2OTMzMDk0MDV9.iSl-LP7jHCbeBSABtzJJ2oH_Zj3qId3r-B7v-s8A9NI"
}
],
"id":"api_cn.tedu.youbiliprojectbackend.modules.user.account.controller.AccountController.login",
"name":"登录",
"paramGroup":{
"bodyKeyValueListJson":"",
"className":"cn.tedu.youbiliprojectbackend.modules.user.account.controller.AccountController",
"jsonDocument":"",
"method":"login",
"methodDescription":"登录",
"methodType":"POST",
"multipartKeyValueListJson":"[]",
"originUrl":"/api/auth/login",
"pathParamsKeyValueListJson":"[]",
"postScript":"",
"postType":"json",
"preScript":"",
"returnDocument":"{\"status\":\"No comment,Type =Number\",\"success\":\"No comment,Type =Boolean\",\"message\":\"No comment,Type =String\",\"data\":{\"userID\":\"用户ID\",\"username\":\"用户名\",\"imgUrl\":\"头像\",\"enable\":\"状态\",\"token\":\"Token(JWT)\"}}",
"tempId":"",
"url":"/api/auth/login",
"urlEncodedKeyValueListJson":"[{\"comment\":\"用户名\",\"customFlag\":2,\"enabled\":true,\"key\":\"username\",\"type\":\"String\",\"value\":\"wangwu\"},{\"comment\":\"密码(原文)\",\"customFlag\":2,\"enabled\":true,\"key\":\"password\",\"type\":\"String\",\"value\":\"123456\"}]",
"urlEncodedKeyValueListText":"username=wangwu\n&password=123456",
"urlParamsKeyValueListJson":"[]",
"urlParamsKeyValueListText":""
},
"tempId":"api_cn.tedu.youbiliprojectbackend.modules.user.account.controller.AccountController.login",
"type":2
}
\ No newline at end of file
{
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController~",
"name":"AuthorizeController",
"type":3
}
\ No newline at end of file
{
"activeGroup":"Default",
"apiParamGroup":{},
"childList":[],
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController",
"domain":"http://localhost:8089",
"enableEnv":"local",
"enableProject":"youbili-project-backend",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController~registerUser.rapi",
"headerList":[
{
"enabled":true,
"type":"Authorization",
"value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpdGllc0pzb25TdHJpbmciOiJbXSIsInVzZXJJRCI6MywidXNlcm5hbWUiOiJ3YW5nd3UiLCJleHAiOjE2OTMzMDk0MDV9.iSl-LP7jHCbeBSABtzJJ2oH_Zj3qId3r-B7v-s8A9NI"
}
],
"id":"api_cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController.registerUser",
"name":"注册验证",
"paramGroup":{
"bodyKeyValueListJson":"",
"className":"cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController",
"jsonDocument":"",
"method":"registerUser",
"methodDescription":"注册验证",
"methodType":"POST",
"multipartKeyValueListJson":"[]",
"originUrl":"/api/auth/register",
"pathParamsKeyValueListJson":"[]",
"postScript":"",
"postType":"json",
"preScript":"",
"returnDocument":"{\"status\":\"No comment,Type =Number\",\"success\":\"No comment,Type =Boolean\",\"message\":\"No comment,Type =String\",\"data\":{\"java.lang.String\":\"No comment,Type =String\"}}",
"tempId":"",
"url":"/api/auth/register",
"urlEncodedKeyValueListJson":"[{\"comment\":\"用户名 长度 4 - 14 只能包含字母、数字、下划线或短横线,并且长度为 4 到 14 位\",\"customFlag\":2,\"enabled\":true,\"key\":\"username\",\"type\":\"String\",\"value\":\"zhaoliu\"},{\"comment\":\"密码: 长度6-18\",\"customFlag\":2,\"enabled\":true,\"key\":\"password\",\"type\":\"String\",\"value\":\"123456\"},{\"comment\":\"邮箱: 格式为邮箱\",\"customFlag\":2,\"enabled\":true,\"key\":\"email\",\"type\":\"String\",\"value\":\"123456@qq.com\"},{\"comment\":\"昵称: 长度1-10\",\"customFlag\":2,\"enabled\":true,\"key\":\"nickname\",\"type\":\"String\",\"value\":\"赵六\"},{\"comment\":\"验证码\",\"customFlag\":2,\"enabled\":true,\"key\":\"code\",\"type\":\"String\",\"value\":\"123456\"}]",
"urlEncodedKeyValueListText":"username=zhaoliu\n&password=123456\n&email=123456@qq.com\n&nickname=赵六\n&code=123456",
"urlParamsKeyValueListJson":"[]",
"urlParamsKeyValueListText":""
},
"tempId":"api_cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController.registerUser",
"type":2
}
\ No newline at end of file
{
"activeGroup":"Default",
"apiParamGroup":{},
"childList":[],
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController",
"domain":"http://localhost:8089",
"enableEnv":"local",
"enableProject":"youbili-project-backend",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~AuthorizeController~vaildateEmail.rapi",
"headerList":[
{
"enabled":true,
"type":"Authorization",
"value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpdGllc0pzb25TdHJpbmciOiJbXSIsInVzZXJJRCI6MywidXNlcm5hbWUiOiJ3YW5nd3UiLCJleHAiOjE2OTMzMDk0MDV9.iSl-LP7jHCbeBSABtzJJ2oH_Zj3qId3r-B7v-s8A9NI"
}
],
"id":"api_cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController.vaildateEmail",
"name":"发送验证邮件",
"paramGroup":{
"bodyKeyValueListJson":"",
"className":"cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController",
"jsonDocument":"",
"method":"vaildateEmail",
"methodDescription":"发送验证邮件",
"methodType":"POST",
"multipartKeyValueListJson":"[]",
"originUrl":"/api/auth/vaild-email",
"pathParamsKeyValueListJson":"[]",
"postScript":"",
"postType":"json",
"preScript":"",
"returnDocument":"{\"status\":\"No comment,Type =Number\",\"success\":\"No comment,Type =Boolean\",\"message\":\"No comment,Type =String\",\"data\":{}}",
"tempId":"",
"url":"/api/auth/vaild-email",
"urlEncodedKeyValueListJson":"[{\"comment\":\" 邮箱\",\"customFlag\":2,\"enabled\":true,\"key\":\"email\",\"type\":\"String\",\"value\":\"123456@qq.com\"}]",
"urlEncodedKeyValueListText":"email=123456@qq.com",
"urlParamsKeyValueListJson":"[]",
"urlParamsKeyValueListText":""
},
"tempId":"api_cn.tedu.youbiliprojectbackend.modules.user.register.controller.AuthorizeController.vaildateEmail",
"type":2
}
\ No newline at end of file
{
"activeGroup":"Default",
"apiParamGroup":{},
"childList":[],
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~TestController",
"domain":"http://localhost:8089",
"enableEnv":"local",
"enableProject":"youbili-project-backend",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~TestController~Test.rapi",
"headerList":[],
"id":"api_cn.tedu.youbiliprojectbackend.modules.user.account.controller.TestController.Test",
"name":"测试JwtAuthorizationFilter过滤器是否有效!",
"paramGroup":{
"bodyKeyValueListJson":"",
"className":"cn.tedu.youbiliprojectbackend.modules.user.account.controller.TestController",
"jsonDocument":"",
"method":"Test",
"methodDescription":"测试JwtAuthorizationFilter过滤器是否有效!",
"methodType":"POST",
"multipartKeyValueListJson":"[]",
"originUrl":"/test/auth/abc",
"pathParamsKeyValueListJson":"[]",
"postScript":"",
"postType":"json",
"preScript":"",
"returnDocument":"{\"status\":\"No comment,Type =Number\",\"success\":\"No comment,Type =Boolean\",\"message\":\"No comment,Type =String\",\"data\":{\"userID\":\"当事人ID\",\"username\":\"当事人用户名\"}}",
"tempId":"",
"url":"/test/auth/abc",
"urlEncodedKeyValueListJson":"[{\"comment\":\"当事人ID\",\"customFlag\":2,\"enabled\":false,\"key\":\"userID\",\"type\":\"Number\",\"value\":1},{\"comment\":\"当事人用户名\",\"customFlag\":2,\"enabled\":false,\"key\":\"username\",\"type\":\"String\",\"value\":\"username_fr9ak\"}]",
"urlEncodedKeyValueListText":"userID=\n&username=",
"urlParamsKeyValueListJson":"[]",
"urlParamsKeyValueListText":""
},
"tempId":"api_cn.tedu.youbiliprojectbackend.modules.user.account.controller.TestController.Test",
"type":2
}
\ No newline at end of file
{
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend~TestController",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~TestController~",
"name":"TestController",
"type":3
}
\ No newline at end of file
{
"description":"",
"directory":"/.fastRequest/collections/ROOT~youbili-project-backend",
"filePath":"/.fastRequest/collections/ROOT~youbili-project-backend~",
"name":"youbili-project-backend",
"type":4
}
\ No newline at end of file
{
"dataList":[
{
"hostGroup":[
{
"env":"local",
"url":"http://localhost:8089"
}
],
"name":"youbili-project-backend"
}
],
"envList":[
"local"
],
"headerList":[
{
"enabled":true,
"type":"Authorization",
"value":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpdGllc0pzb25TdHJpbmciOiJbXSIsInVzZXJJRCI6MywidXNlcm5hbWUiOiJ3YW5nd3UiLCJleHAiOjE2OTM1NTk3NTB9.BnLKTqWvleTJf-bUYbBs8qFR3_JXyqgWmbMEok6fHWQ"
}
],
"postScript":"",
"preScript":"",
"projectList":[
"youbili-project-backend"
],
"syncModel":{
"branch":"master",
"domain":"https://github.com",
"enabled":false,
"namingPolicy":"byDoc",
"owner":"",
"repo":"",
"repoUrl":"",
"syncAfterRun":false,
"token":"",
"type":"github"
},
"urlEncodedKeyValueList":[],
"urlParamsKeyValueList":[],
"urlSuffix":""
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="fastRequestCollection">
<option name="detail">
<CollectionDetail>
<option name="childList">
<list>
<CollectionDetail>
<option name="groupId" value="1" />
<option name="id" value="1" />
<option name="name" value="Default Group" />
<option name="type" value="1" />
</CollectionDetail>
</list>
</option>
<option name="groupId" value="-1" />
<option name="id" value="0" />
<option name="name" value="Root" />
<option name="type" value="1" />
</CollectionDetail>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="fastRequestCurrentParamGroup">
<option name="className" value="cn.tedu.youbiliprojectbackend.modules.user.account.controller.TestController" />
<option name="filePath" value="/.fastRequest/collections/ROOT~youbili-project-backend~TestController~Test.rapi" />
<option name="method" value="Test" />
<option name="methodDescription" value="测试JwtAuthorizationFilter过滤器是否有效!" />
<option name="methodType" value="POST" />
<option name="module" value="youbili-project-backend" />
<option name="originUrl" value="/test/auth/abc" />
<option name="requestParamMap">
<map>
<entry key="currentPrincipal">
<value>
<Object />
</value>
</entry>
</map>
</option>
<option name="returnDocument" value="{&quot;status&quot;:&quot;No comment,Type =Number&quot;,&quot;success&quot;:&quot;No comment,Type =Boolean&quot;,&quot;message&quot;:&quot;No comment,Type =String&quot;,&quot;data&quot;:{&quot;userID&quot;:&quot;当事人ID&quot;,&quot;username&quot;:&quot;当事人用户名&quot;}}" />
<option name="tempId" value="api_cn.tedu.youbiliprojectbackend.modules.user.account.controller.TestController.Test" />
<option name="url" value="/api/auth/register" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="fastRequestCurrentProjectConfig">
<option name="cookieList">
<list>
<DataMapping>
<option name="type" value="http://localhost:8089" />
<option name="value" value="JSESSIONID=F62879E83E4DC4B960C590D470927EBC; Path" />
</DataMapping>
</list>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="fastRequestCurrentProjectLocalConfig">
<option name="cookieList">
<list>
<DataMapping>
<option name="type" value="http://localhost:8089" />
<option name="value" value="JSESSIONID=F62879E83E4DC4B960C590D470927EBC; Path" />
</DataMapping>
</list>
</option>
<option name="domain" value="http://localhost:8089" />
<option name="enableEnv" value="local" />
<option name="enableProject" value="youbili-project-backend" />
<option name="initFlag" value="1" />
</component>
</project>
\ No newline at end of file
此差异已折叠。
......@@ -170,7 +170,7 @@ import login from "./login"
},
data() {
return {
userId: null, // 当前登录用户的id
userID: null, // 当前登录用户的id
isLogin: false,
dialogVisible: false, // 登录注册弹窗
src: "blLogo.png", // 图片路径
......@@ -297,18 +297,18 @@ import login from "./login"
},
created() {
// // 根据用户id获取收藏记录
// getHeaderCollect({userId: this.userId}).then(res => {
// if (res.data.success) {
// this.scList = res.data.data;
// }
// })
// // 根据用户id获取历史记录
// getHeaderHistory({userId: this.userId}).then(res => {
// if (res.data.success) {
// this.lsList = res.data.data;
// }
// })
// 根据用户id获取收藏记录
// getHeaderCollect({userID: this.userID}).then(res => {
// if (res.data.success) {
// this.scList = res.data.data;
// }
// })
// // 根据用户id获取历史记录
// getHeaderHistory({userID: this.userID}).then(res => {
// if (res.data.success) {
// this.lsList = res.data.data;
// }
// })
},
mounted() {
this.restaurants = this.loadAll();
......
......@@ -75,7 +75,7 @@ export function getHeaderHistory(params) {
// 主页视频列表
// 主页视频列表(未对接)
export function getIndexVideoList(params) {
return request({
method: "get",
......@@ -95,6 +95,7 @@ export function getPersonalCenterInfo (params) {
// 分类标题(未对接)
export function getClassification (params) {
return request({
method: 'get',
......@@ -104,8 +105,23 @@ export function getClassification (params) {
}
// 收藏列表
export function getCollection (params) {
return request({
method: 'get',
url: '/user/collection/all-list',
data: params
})
}
// 删除当前收藏
export function deleteCollection(params) {
return request({
method: 'post',
url: '/user/collection/delete',
data: params
})
}
......
<!--收藏-->
<template>
<div>
<el-container>
<el-header>
<h1 style="padding-left: 60px;padding-bottom: 0;margin-top: 20px">收藏记录</h1>
<el-divider></el-divider>
</el-header>
<div >
<el-row style="margin-left: 120px;margin-top: 30px;" v-for="card in 3" >
<el-card style="width: 800px;height: 150px">
<el-col span="22">
<el-card style="width: 700px;height:150px;" class="zoom">
<el-row :gutter="10" style="margin: 0">
<el-col :span="10" >
<img src="../../assets/a.jpg" width=350 height="234">
</el-col>
<el-col :span="14">
<el-row>
<el-button round style="margin-left: 150px;width: 150px"><h1>标题</h1></el-button>
<el-row style="margin-top: 15px">
<el-button style="margin-left: 80px;width: 100px" size="small" round>小型按钮</el-button>
<el-button style="margin-left: 110px" size="small" >按钮</el-button>
</el-row>
<el-row style="margin-top: 15px">
<el-button style="margin-left: 100px" size="mini" round>按钮</el-button>
<el-button style="margin-left: 40px" size="mini" round>按钮</el-button>
<el-button style="margin-left: 40px" size="mini" round>按钮</el-button>
</el-row>
</el-row>
</el-col>
</el-row>
</el-card>
</el-col>
<el-col span="2">
<el-button style="margin-top: 58px" type="danger" size="mini" >删除</el-button>
</el-col>
</el-card>
</el-row>
</div>
<div>
<div style="width: auto">
<div style="margin-left: 600px">
<h1>收藏记录</h1>
</div>
<div style="width: auto">
<el-divider></el-divider>
</div>
</div>
<div>
<el-row :gutter="20">
<el-col :span="6">
<div class="grid-content bg-purple"></div>
</el-col>
<el-col :span="12">
<div class="grid-content bg-purple">
<div style="margin-left: 250px;margin-top: 30px;width: auto" v-for="(v,i) of favorite" :key="1">
<el-card style="width: 900px;height: 250px">
<div style="display: flex">
<div style="height: 200px;width: 350px;margin-left: 15px;margin-top: 10px">
<img :src="v.videoImgUrl" style="width: 350px;height: 200px">
</div>
<div style="margin-top: 5px;margin-left: 50px">
<h1>
{{ v.title }}
</h1>
<div class="block" style="display: flex;margin-top: 5px">
<div>
<el-avatar :size="50"
:src="v.imgUrl"></el-avatar>
</div>
<div style="margin-left: 5px;margin-top: 10px;font-size: 18px">{{ v.nickname }}</div>
</div>
<div style="margin-top: 60px;display: flex">
<div>收藏日期:<span> {{ v.favoriteDate }} </span></div>
<div style="margin-left: 300px">
<el-button type="danger" icon="el-icon-delete" circle
v-on:click="deleted(v.favoriteID)"></el-button>
</div>
</div>
</div>
</div>
</el-card>
</div>
</div>
</el-col>
</el-container>
</div>
<el-col :span="6">
<div class="grid-content bg-purple"></div>
</el-col>
</el-row>
</div>
</div>
</div>
</template>
<style>
.el-card__body, .el-main {
padding: 2px;
}
/*.el-card:hover{*/
/* !*margin: 10px 0 0 10px;*!*/
/* !*设置为相对定位*!*/
/* position: relative;*/
/* !*通过left/right/top/bottom相对于元素自身位置偏移*!*/
/* top: 3px;*/
/* overflow: hidden;*/
/*}*/
</style>
<script>
import {deleteCollection, getCollection} from "@/utils/option";
export default {
name: "collection",
computed: {},
data() {
return {
date: [
favorite: [
{
favoriteID: '1',
videoID: '1',
nickname: '1',
favoriteDate: '2023-2-23',
title: '视频标题:这是个视频!',
imgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
videoImgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
},
{
favoriteID: '2',
videoID: '1',
nickname: '1',
favoriteDate: '2023-2-23',
title: '视频标题:这是个视频!',
imgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
videoImgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
},
{
favoriteID: '3',
videoID: '1',
nickname: '1',
favoriteDate: '2023-2-23',
title: '视频标题:这是个视频!',
imgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
videoImgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
},
{
favoriteID: '4',
videoID: '1',
nickname: '1',
favoriteDate: '2023-2-23',
title: '视频标题:这是个视频!',
imgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
videoImgUrl: 'https://img2.baidu.com/it/u=1857362695,948924529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
},
],
]
}
},
methods: {},
created() {
methods: {
deleted(favoriteID) {
this.$confirm('此收藏记录要被永久删除,是否确定此操作?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
console.log("被删除的ID是:", favoriteID);
// 写axios; 删除方法!;
deleteCollection(favoriteID).then(res => {
if (res.success) {
this.$notify({
title: '删除成功!',
message: res.data,
position: 'bottom-right',
type: 'success'
});
} else {
this.$notify({
title: '出现问题',
message: res.message,
position: 'bottom-right',
type: 'error'
})
}
})
}).catch(() => {
this.$notify({
title: '取消删除',
message: '',
position: 'bottom-right',
});
});
}
},
created() {
// 获取收藏列表;
getCollection().then(res => {
if (res.success) {
this.favorite = res.data
console.log("收藏列表加载完毕")
} else {
this.$notify({
title: '出现问题',
message: res.message,
position: 'bottom-right',
type: 'error'
})
}
})
}
}
</script>
<style scoped>
/*@media screen and (min-width: 1970px) {*/
/* .idxs {*/
/* margin: 60px auto;*/
/* width: calc(100% - 290px);*/
/* max-width: 1570px;*/
/* min-width: 1200px;*/
/* }*/
/*}*/
/*@media screen and (max-width: 1969px) {*/
/* .idxs {*/
/* !*width: 1270px;*!*/
/* !*min-width: 1000px;*!*/
/* !*margin-top: 60px;*!*/
/* !*margin-left: 270px;*!*/
/* !*padding: 40px;*!*/
/* width: calc(100% - 290px);*/
/* max-width: 1570px;*/
/* min-width: 1200px;*/
/* margin: 60px auto;*/
/* }*/
/*}*/
.zoom:hover {
transform: scale(1.1); /* (150% zoom - Note: if the zoom is too large, it will go outside of the viewport) */
}
.zoom {
transition: transform 0.3s; /* Animation */
}
......
<!--动态-->
<template>
<div>
<el-card>
<div style="display: flex">
{{me}}
</div>
</el-card>
</div>
<div>
<div>
<div>
<div style="margin-left: 600px">
<h1>收藏记录</h1>
</div>
<div style="width: auto">
<el-divider></el-divider>
</div>
</div>
<div>
<div>
</div>
</div>
</div>
</div>
</template>
<script>
import {postTest} from "@/utils/option";
export default {
name: "dynamic",
data() {
return {
me: ''
}
return {}
},
methods: {},
created() {
postTest(respon => {
if (respon.data.success){
alert("成功!!!")
}
})
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
......@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"core-js": "^3.8.3",
"echarts": "^5.4.2",
"element-ui": "^2.15.13",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
......@@ -4726,6 +4727,20 @@
"node": ">=6.0.0"
}
},
"node_modules/echarts": {
"version": "5.4.2",
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.2.tgz",
"integrity": "sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==",
"dependencies": {
"tslib": "2.3.0",
"zrender": "5.4.3"
}
},
"node_modules/echarts/node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
......@@ -9839,6 +9854,19 @@
"engines": {
"node": ">=10"
}
},
"node_modules/zrender": {
"version": "5.4.3",
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.3.tgz",
"integrity": "sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==",
"dependencies": {
"tslib": "2.3.0"
}
},
"node_modules/zrender/node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
}
}
}
......@@ -8,6 +8,7 @@
},
"dependencies": {
"core-js": "^3.8.3",
"echarts": "^5.4.2",
"element-ui": "^2.15.13",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
......
@font-face {
font-family: "AlimamaDaoLiTi";
src: url('./AlimamaDaoLiTi.ttf');
font-weight: normal;
font-style: normal;
}
\ No newline at end of file
......@@ -4,7 +4,10 @@ import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import * as echarts from 'echarts';
Vue.prototype.$echarts = echarts;
Vue.config.productionTip = false
Vue.use(ElementUI);
......
......@@ -2,64 +2,586 @@
<div>
<el-row :gutter="20">
<el-col :span="6">
<div>
<el-statistic group-separator="," :precision="2" :value="value2" :title="title"></el-statistic>
</div>
<h2 style="margin-left: 30%; margin-top: 30px; font-size: 35px">用户总人数</h2>
<div style="font-family: AlimamaDaoLiTi; font-size: 50px; margin-left: 30px; margin-top: 30%">63542876546098</div>
</el-col>
<el-col :span="6">
<div>
<el-statistic title="男女比">
<template slot="formatter"> 456/2 </template>
</el-statistic>
</div>
<h2 style="margin-left: 30%; margin-top: 30px; font-size: 35px">每日新增人数</h2>
<div style="font-family: AlimamaDaoLiTi; font-size: 120px; margin-left: 25%; margin-top: 20%">4536</div>
</el-col>
<el-col :span="6">
<div>
<el-statistic group-separator="," :precision="2" decimal-separator="." :value="value1" :title="title">
<template slot="prefix">
<i class="el-icon-s-flag" style="color: red"></i>
</template>
<template slot="suffix">
<i class="el-icon-s-flag" style="color: blue"></i>
</template>
</el-statistic>
</div>
<h2 style="margin-left: 23%; margin-top: 30px; font-size: 35px">用户等级占比</h2>
<div id="level" style="width: 500px;height:350px;margin-left: -50px"></div>
</el-col>
<el-col :span="6">
<div>
<el-statistic :value="like ? 521 : 520" title="Feedback">
<template slot="suffix">
<span @click="like = !like" class="like">
<i class="el-icon-star-on" style="color:red" v-show="!!like"></i>
<i class="el-icon-star-off" v-show="!like"></i>
</span>
</template>
</el-statistic>
</div>
<h2 style="margin-left: 23%; margin-top: 30px; font-size: 35px">用户年龄占比</h2>
<div id="personAge" style="width: 500px;height:350px; margin-left: -50px"></div>
</el-col>
</el-row>
<el-tabs type="border-card">
<el-tab-pane label="电 影">
<div id="film" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
<el-tab-pane label="电视剧">
<div id="tvPlay" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
<el-tab-pane label="综 艺">
<div id="variety" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
<el-tab-pane label="动 漫">
<div id="anime" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
<el-tab-pane label="自 制">
<div id="selfControl" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
<el-tab-pane label="搬 运">
<div id="transport" style="width: 900px;height:430px; margin: 0 auto"></div>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: "adminData",
data(){
return{
like: true,
value1: 4154.564,
value2: 2222,
title: '今日的增长',
data() {
return {
activeName: 'first'
}
},
mounted() {
this.film()
this.tvPlay()
this.variety()
this.anime()
this.selfControl()
this.transport()
this.level()
this.personAge()
},
methods: {
handleClick(tab, event) {
console.log(tab, event);
},
film() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("film")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
tvPlay() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("tvPlay")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [600, 400, 11, 14, 143, 53, 246]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
variety() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("variety")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
anime() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("anime")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
selfControl() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("selfControl")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
transport() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("transport")
);
// 配置option选项
var option = {
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['观看数', '点赞数', '收藏数', '评论数', '弹幕数']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
name: '观看数',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '点赞数',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '收藏数',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '评论数',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '弹幕数',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
level() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("level")
);
// 配置option选项
let option = {
tooltip: {
trigger: 'item'
},
itemStyle: {
borderRadius: 5,
borderColor: '#fff',
borderWidth: 30
},
series: [
{
name: '用户等级占比',
type: 'pie',
radius: '50%',
data: [
{value: 1048, name: '0-10级'},
{value: 735, name: '11-20级'},
{value: 580, name: '21-30级'},
{value: 484, name: '31-40级'},
{value: 300, name: '41-50级'}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
personAge() {
// 基于准备好的dom,初始化echarts实例
var myChart = this.$echarts.init(
document.getElementById("personAge")
);
// 配置option选项
let option = {
tooltip: {
trigger: 'item'
},
itemStyle: {
borderRadius: 5,
borderColor: '#fff',
borderWidth: 30
},
series: [
{
name: '用户年龄占比',
type: 'pie',
radius: '50%',
data: [
{value: 1048, name: '0-18岁'},
{value: 735, name: '19-225岁'},
{value: 580, name: '25-35岁'},
{value: 484, name: '35-45岁'},
{value: 300, name: '45岁以上'}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
// 把配置option选项用js放进dom节点
myChart.setOption(option);
},
}
}
</script>
<style scoped>
.like {
cursor: pointer;
font-size: 25px;
display: inline-block;
}
</style>
\ No newline at end of file
......@@ -8,5 +8,5 @@ package cn.tedu.youbiliprojectbackend.common.consts;
* @author ASUS
*/
public interface RegisterConsts {
String REGISTER_EMAIL_SEND = "register:email";
String REGISTER_EMAIL_SEND = "user:Register:sendEmail";
}
package cn.tedu.youbiliprojectbackend.common.consts;
/**
* JWT缓存相关常量
*
* @author java@tedu.cn
* @version 1.0
*/
public interface UserCacheConsts {
/**
* 缓存的JWT前缀
*/
String USER_JWT_PREFIX = "user:Login:jwt:";
/**
* 用户启用状态的KEY的前缀
*/
String USER_ENABLE_PREFIX = "user:Login:enable:";
}
package cn.tedu.youbiliprojectbackend.common.pojo.po;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 用户登录信息的PO,此类数据将存入到Redis中
*
* @author java@tedu.cn
* @version 1.0
*/
@Data
@Accessors(chain = true)
public class UserLoginInfoPO implements Serializable {
/**
* 用户登录时使用的浏览器的信息
*/
private String userAgent;
/**
* 用户登录时的IP地址
*/
private String ip;
}
package cn.tedu.youbiliprojectbackend.common.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 分页数据类
*
* @author java@tedu.cn
* @version 1.0
*/
@Data
@Accessors(chain = true)
public class PageData<T> implements Serializable {
/**
* 每页记录数
*/
private Integer pageSize;
/**
* 记录总数
*/
private Long total;
/**
* 当前页码
*/
private Integer currentPage;
/**
* 最大页码
*/
private Integer maxPage;
/**
* 数据列表
*/
private List<T> list;
}
\ No newline at end of file
......@@ -38,11 +38,11 @@ public class JwtUtils {
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
log.debug("从认证结果中的当事人中获取权限列表:{}", authorities);
// log.debug("从认证结果中的当事人中获取权限列表:{}", authorities);
String authoritiesJsonString = JSON.toJSONString(authorities);
log.debug("将权限列表对象转换为JSON格式的字符串:{}", authoritiesJsonString);
// log.debug("将权限列表对象转换为JSON格式的字符串:{}", authoritiesJsonString);
Date date = new Date(System.currentTimeMillis() + 60 * 1000 * durationInMinute);
// ↑ 注意加L,避免int溢出为负数
......@@ -64,7 +64,7 @@ public class JwtUtils {
}
public static Claims parseToken(String Token) throws JwtException {
log.debug("开始解析JWT");
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(Token)
......
......@@ -7,8 +7,8 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(
{
"cn.tedu.youbiliprojectbackend.modules.user.register.mapper",
"cn.tedu.youbiliprojectbackend.modules.user.account.mapper"
"cn.tedu.youbiliprojectbackend.modules.user.register.dao.mapper",
"cn.tedu.youbiliprojectbackend.modules.user.account.dao.mapper"
})
public class MybatisConfig {
}
......@@ -12,8 +12,6 @@ import java.io.Serializable;
/**
* Redis的配置类
*
* @author java@tedu.cn
* @version 1.0
*/
@Slf4j
@Configuration
......
......@@ -49,13 +49,12 @@ public class SecurityConfiguration {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
/*配置HTTP请求的授权规则。它指定了/api/auth/**路径下的请求不需要认证,其他的请求都需要认证*/
http
.authorizeHttpRequests()
http.authorizeHttpRequests()
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/error/**").permitAll()
.requestMatchers("/user/collection/**").permitAll()
.anyRequest().authenticated();
// http.authorizeHttpRequests().requestMatchers("/api/auth1/**").permitAll().anyRequest().authenticated();
/*来禁用跨站请求伪造防御*/
http.csrf().disable();//跨域攻击防御
......@@ -143,7 +142,7 @@ public class SecurityConfiguration {
/**
*
* Cors过滤配置
*/
private CorsConfigurationSource configurationSource() {
CorsConfiguration cors = new CorsConfiguration();
......
......@@ -7,6 +7,9 @@ import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author ASUS
*/
@Configuration
@Slf4j
@Component
......
package cn.tedu.youbiliprojectbackend.core.filter;
import cn.tedu.youbiliprojectbackend.common.consts.HttpConsts;
import cn.tedu.youbiliprojectbackend.common.pojo.po.UserLoginInfoPO;
import cn.tedu.youbiliprojectbackend.common.security.CurrentPrincipal;
import cn.tedu.youbiliprojectbackend.common.utils.jwt.JwtUtils;
import cn.tedu.youbiliprojectbackend.common.web.response.RestBean;
import cn.tedu.youbiliprojectbackend.common.web.response.ServiceCode;
import cn.tedu.youbiliprojectbackend.modules.user.account.dao.cache.IUserCacheRepository;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
......@@ -15,6 +18,7 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
......@@ -28,16 +32,21 @@ import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.List;
import static cn.tedu.youbiliprojectbackend.common.consts.HttpConsts.HEADER_AUTHORIZATION;
/**
* @author ASUS
*/
@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {
public class JwtAuthorizationFilter extends OncePerRequestFilter implements HttpConsts {
public static final int JWT_MIN_LENGTH = 80;
@Autowired
IUserCacheRepository userCacheRepository;
public JwtAuthorizationFilter() {
log.info("创建过滤器对象:JwtAuthorizationFilter");
}
......@@ -63,6 +72,27 @@ public class JwtAuthorizationFilter extends OncePerRequestFilter {
return;
}
UserLoginInfoPO userLoginInfoPO = userCacheRepository.getLoginStatus(jwt);
if (userLoginInfoPO == null) {
log.debug("未携带用户信息");
filterChain.doFilter(request,response);
return;
}
String userAgent = userLoginInfoPO.getUserAgent();
String ip = userLoginInfoPO.getIp();
if (!userAgent.equals(request.getHeader(HEADER_USER_AGENT))
&& !ip.equals(request.getRemoteAddr())) {
// 本次请求的信息与当初登录时完全不同,则视为无效的JWT
log.warn("本次请求的信息与当初登录时完全不同,将直接放行,交由后续的组件进行处理");
filterChain.doFilter(request, response);
return;
}
response.setContentType("application/json; charset=utf-8");
Claims claims = null;
......@@ -99,6 +129,13 @@ public class JwtAuthorizationFilter extends OncePerRequestFilter {
CurrentPrincipal principal = new CurrentPrincipal();
principal.setUserID(userID);
principal.setUsername(username);
List<SimpleGrantedAuthority> authorities
= JSON.parseArray(authoritiesJsonString, SimpleGrantedAuthority.class);
Object credentials = null; // 凭证:无需凭证
......@@ -107,6 +144,8 @@ public class JwtAuthorizationFilter extends OncePerRequestFilter {
principal, credentials, authorities
);
log.debug("{}",request.getRequestURI());
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
filterChain.doFilter(request, response);
......
package cn.tedu.youbiliprojectbackend.modules.user.account.controller;
import cn.tedu.youbiliprojectbackend.common.consts.HttpConsts;
import cn.tedu.youbiliprojectbackend.common.consts.UserCacheConsts;
import cn.tedu.youbiliprojectbackend.common.web.response.RestBean;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.param.UserLoginInfoParam;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.vo.UserLoginVO;
import cn.tedu.youbiliprojectbackend.modules.user.account.service.IUserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
......@@ -18,7 +21,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/auth")
@Validated
public class AccountController {
public class AccountController implements HttpConsts {
@Autowired
private IUserService userService;
......@@ -29,8 +32,12 @@ public class AccountController {
}
@PostMapping("/login")
public RestBean<UserLoginVO> login(@Validated UserLoginInfoParam userLoginInfoParam){
UserLoginVO userLoginResultVO = userService.login(userLoginInfoParam);
public RestBean<UserLoginVO> login(@Validated UserLoginInfoParam userLoginInfoParam,
HttpServletRequest request){
String remoteAddr = request.getRemoteAddr();
String userAgent = request.getHeader(HEADER_USER_AGENT);
log.error(userAgent);
UserLoginVO userLoginResultVO = userService.login(userLoginInfoParam,remoteAddr,userAgent);
return RestBean.success(userLoginResultVO);
}
......
package cn.tedu.youbiliprojectbackend.modules.user.account.dao.cache;
import cn.tedu.youbiliprojectbackend.common.consts.UserCacheConsts;
import cn.tedu.youbiliprojectbackend.common.pojo.po.UserLoginInfoPO;
public interface IUserCacheRepository extends UserCacheConsts {
/**\
* 保存用户登录信息到Redis中;
*
* @param Token JWT工具类生成的Token令牌
* @param userLoginInfoPO 用户登录信息;包括IP,浏览器信息
*/
void saveLoginInfo(String Token, UserLoginInfoPO userLoginInfoPO);
/**
* 根据JWT从redis之中取出用户的登录信息
*
* @param Token JWT
* @return 返回用户登录的信息
*/
UserLoginInfoPO getLoginStatus(String Token);
/**
* 保存用户的账号状态进redis中
* @param userID 用户ID
* @param enable 账号状态: 1表示启用,0表示禁用
*/
void saveEnableByUserID(Long userID, int enable);
/**
* 通过用户ID取出用户状态
*
* @param userID 用户ID
* @return 返回值为true时,账号被封禁;为false时,账号开启;
*/
boolean getEnableByUserID(Long userID);
}
package cn.tedu.youbiliprojectbackend.modules.user.account.dao.cache.impl;
import cn.tedu.youbiliprojectbackend.common.pojo.po.UserLoginInfoPO;
import cn.tedu.youbiliprojectbackend.modules.user.account.dao.cache.IUserCacheRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
@Slf4j
@Repository
public class UserCacheRepository implements IUserCacheRepository {
@Autowired
RedisTemplate<String,Serializable> redisTemplate;
/**
* 保存用户登录信息到Redis中,其中KEY为"user:jwt: 'Token:'",value为userLoginInfoPO;
*
* @param Token JWT工具类生成的Token令牌
* @param userLoginInfoPO 用户登录信息;包括IP,浏览器信息
*/
@Override
public void saveLoginInfo(String Token, UserLoginInfoPO userLoginInfoPO) {
String key = USER_JWT_PREFIX + Token;
log.debug("Token :{}",Token);
log.debug("key值为:{}",key);
ValueOperations<String, Serializable> opsForValue = redisTemplate.opsForValue();
opsForValue.set(key,userLoginInfoPO,10,TimeUnit.DAYS);
}
/**
* 根据JWT从redis之中取出用户的登录信息
*
* @param Token JWT
* @return 返回用户登录的信息
*/
@Override
public UserLoginInfoPO getLoginStatus(String Token) {
log.debug("开始从Redis中取出用户信息");
String key = USER_JWT_PREFIX + Token;
log.debug("key值为:{}",key);
ValueOperations<String,Serializable> operations = redisTemplate.opsForValue();
Serializable serializable = operations.get(key);
UserLoginInfoPO userLoginInfoPO = (UserLoginInfoPO) serializable;
log.debug("取出的用户信息是:{}",userLoginInfoPO);
return userLoginInfoPO;
}
/**
* 保存用户的账号状态进redis中
*
* @param userID 用户ID
* @param enable 账号状态: 1表示启用,0表示禁用
*/
@Override
public void saveEnableByUserID(Long userID, int enable) {
String key =USER_ENABLE_PREFIX + userID;
ValueOperations<String,Serializable> operations = redisTemplate.opsForValue();
operations.set(key,enable,10,TimeUnit.DAYS);
}
/**
* 通过用户ID取出用户状态
*
* @param userID 用户ID
* @return 返回值为true时, 账号被封禁;为false时,账号开启;
*/
@Override
public boolean getEnableByUserID(Long userID) {
String key = USER_ENABLE_PREFIX + userID;
ValueOperations<String,Serializable> operations = redisTemplate.opsForValue();
operations.get(key);
return false;
}
}
package cn.tedu.youbiliprojectbackend.modules.user.account.security;
import cn.tedu.youbiliprojectbackend.modules.user.account.mapper.AccountMapper;
import cn.tedu.youbiliprojectbackend.modules.user.account.dao.mapper.AccountMapper;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.entity.Account;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......
......@@ -3,7 +3,17 @@ package cn.tedu.youbiliprojectbackend.modules.user.account.service;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.param.UserLoginInfoParam;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.vo.UserLoginVO;
import jakarta.servlet.http.HttpServletRequest;
public interface IUserService {
UserLoginVO login(UserLoginInfoParam userLoginInfoParam);
/**
* 登录实习
*
* @param userLoginInfoParam 用户名密码表单
* @param remoteAddr IP地址
* @param userAgent 客户端的浏览器信息
* @return 登录成功后将返回用户名,用户ID等
*/
UserLoginVO login(UserLoginInfoParam userLoginInfoParam, String remoteAddr,String userAgent);
}
package cn.tedu.youbiliprojectbackend.modules.user.account.service.impl;
import cn.tedu.youbiliprojectbackend.common.pojo.po.UserLoginInfoPO;
import cn.tedu.youbiliprojectbackend.common.utils.jwt.JwtUtils;
import cn.tedu.youbiliprojectbackend.modules.user.account.dao.cache.impl.UserCacheRepository;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.param.UserLoginInfoParam;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.vo.UserLoginVO;
import cn.tedu.youbiliprojectbackend.modules.user.account.security.CustomUserDetails;
......@@ -20,9 +22,11 @@ public class UserServiceImpl implements IUserService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
UserCacheRepository userCacheRepository;
@Override
public UserLoginVO login(UserLoginInfoParam userLoginInfoParam) {
public UserLoginVO login(UserLoginInfoParam userLoginInfoParam,String remoteAddr,String userAgent ) {
log.debug("开始处理【用户登录】的业务,参数:{}", userLoginInfoParam);
// 验证 !
......@@ -38,10 +42,20 @@ public class UserServiceImpl implements IUserService {
String Token = JwtUtils.CreateJWT(userDetails); //JWT工具类
UserLoginVO userLoginVO = new UserLoginVO().setToken(Token);
UserLoginInfoPO loginInfoPO = new UserLoginInfoPO()
.setUserAgent(userAgent).setIp(remoteAddr);
//将登录JWT,IP和浏览器信息存储到Redis之中;
userCacheRepository.saveLoginInfo(Token,loginInfoPO);
log.debug("生成的jwt{}",Token);
//将用户状态存入Redis之中;
userCacheRepository.saveEnableByUserID(userDetails.getUserID(), 1);
UserLoginVO userLoginVO = new UserLoginVO().setToken(Token);
return userLoginVO;
}
}
package cn.tedu.youbiliprojectbackend.modules.user.collection.controller;
import cn.tedu.youbiliprojectbackend.common.security.CurrentPrincipal;
import cn.tedu.youbiliprojectbackend.common.web.response.RestBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ASUS
*/
@RestController
@RequestMapping("/user/collection")
@Slf4j
public class CollectionController {
@PostMapping("delete")
public RestBean<Object> delete(@AuthenticationPrincipal CurrentPrincipal currentPrincipal,
Long favoriteID){
log.debug("开始处理请求: delete");
return RestBean.success(favoriteID);
}
@GetMapping("/all-list")
public RestBean<Object> allList(){
log.debug("开始处理请求 all-list");
String data = "请求成功";
return RestBean.success(data);
}
}
package cn.tedu.youbiliprojectbackend.modules.user.collection.pojo.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class collectionVO implements Serializable {
}
package cn.tedu.youbiliprojectbackend.modules.user.register.dao.cache;
import cn.tedu.youbiliprojectbackend.common.consts.RegisterConsts;
public interface RegisteCacheRepository extends RegisterConsts {
/**
* 发送验证码功能;
* 将验证码的内容存储到redis之中,其中key为SessionID+email,value为code验证码
* @param key sessionID+email组合拼接
* @param code 验证码
*/
void AddSendToEmail(String key,String code);
/**
* 查询key是否已存在与Redis之中;
* 存在返回true,不存在返回false
* @param key Redis之中存储的key
* @return key存在返回true 不存在返回false
*/
boolean keyByKey(String key);
/**
* 通过key查询这个key的剩余时间
* @param key Redis之中存储的Key
* @return key存在返回true 不存在返回false
*/
Long timeOrdata(String key);
/**
* 通过key取出value的值;
*
* @param key 存储到Redis之中的key
* @return 将value返回;
*/
String valueByKey(String key);
}
package cn.tedu.youbiliprojectbackend.modules.user.register.dao.cache.impl;
import cn.tedu.youbiliprojectbackend.modules.user.register.dao.cache.RegisteCacheRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@Slf4j
@Repository
public class RegisteCacheRepositoryImpl implements RegisteCacheRepository {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
/**
* 发送验证码功能;
* 将验证码的内容存储到redis之中,其中key为SessionID+email,value为code验证码
* @param key sessionID+email组合拼接
* @param code 验证码
*/
@Override
public void AddSendToEmail(String key, String code) {
log.debug("开始向Redis中添加数据email:{},code:{}", key, code);
ValueOperations<String, Serializable> operations = redisTemplate.opsForValue();
operations.set(key,code,3, TimeUnit.MINUTES);
}
/**
* 查询key是否已存在与Redis之中;
* 存在返回true,不存在返回false
*
* @param key
* @return
*/
@Override
public boolean keyByKey(String key) {
log.debug("判断Key是否存在,开始查询key是否存在于redis之中");
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
/**
* 通过key查询这个key的剩余时间
*
* @param key Redis之中存储的Key
* @return key存在返回true 不存在返回false
*/
@Override
public Long timeOrdata(String key) {
log.debug("开始查询剩余时间");
return Optional.ofNullable(redisTemplate.getExpire(key, TimeUnit.SECONDS)).orElse(0L);
}
/**
* 通过key取出value的值;
*
* @param key 存储到Redis之中的key
* @return 将value返回;
*/
@Override
public String valueByKey(String key) {
log.debug("开始通过key取出value");
String code = (String) redisTemplate.opsForValue().get(key);
return code;
}
}
package cn.tedu.youbiliprojectbackend.modules.user.register.mapper;
package cn.tedu.youbiliprojectbackend.modules.user.register.dao.mapper;
import cn.tedu.youbiliprojectbackend.modules.user.account.pojo.entity.Account;
......
......@@ -15,23 +15,34 @@ import java.io.Serializable;
public class AccountRegDTO implements Serializable {
/**
* 用户名
* 长度 2 - 16
* 只能包含字母、数字、下划线或短横线,并且长度为 2 到 16
* 长度 4 - 14
* 只能包含字母、数字、下划线或短横线,并且长度为 4 到 14
*/
@Pattern(regexp = "^[a-zA-Z0-9_]{4,14}$", message = "用户名只能包含字母、数字和下划线,且长度为4-14位")
private String username;
/**
* 密码:
* 长度6-18
*/
@Length(min = 6, max=18)
private String password;
/**
* 邮箱:
* 格式为邮箱
*/
@Email(message = "您输入的邮箱格式错误,请重新输入!")
private String email;
/**
* 昵称:
* 长度1-10
*/
@Length(min = 1,max = 10)
private String nickname;
/**
* 验证码!
* 验证码
*/
@Length(min = 6,max = 6)
private String code;
......
......@@ -2,13 +2,15 @@ package cn.tedu.youbiliprojectbackend.modules.user.register.service.impl;
import cn.tedu.youbiliprojectbackend.common.ex.ServiceException;
import cn.tedu.youbiliprojectbackend.common.web.response.ServiceCode;
import cn.tedu.youbiliprojectbackend.modules.user.register.mapper.UserMapper;
import cn.tedu.youbiliprojectbackend.modules.user.register.dao.cache.RegisteCacheRepository;
import cn.tedu.youbiliprojectbackend.modules.user.register.dao.cache.impl.RegisteCacheRepositoryImpl;
import cn.tedu.youbiliprojectbackend.modules.user.register.dao.mapper.UserMapper;
import cn.tedu.youbiliprojectbackend.modules.user.register.service.AuthorizeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
......@@ -45,10 +47,8 @@ public class AuthorizeServiceImpl implements AuthorizeService {
@Autowired
MailSender mailSender;
//Redis
@Autowired
StringRedisTemplate template;
RegisteCacheRepository registeCacheRepository;
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
......@@ -66,20 +66,18 @@ public class AuthorizeServiceImpl implements AuthorizeService {
log.debug(" 开始发送验证码业务操作! ");
String key = REGISTER_EMAIL_SEND + sessionId +" : "+ email;
log.debug("sendValidateEmail : {}",key);
log.debug("生成Key : {}",key);
log.debug("判断这个Key是否存在");
if (Boolean.TRUE.equals(template.hasKey(key))) { //判断这个hasKey是否存在
log.debug("key,存在判断剩余时间");
Long expire = Optional.ofNullable(template.getExpire(key, TimeUnit.SECONDS)).orElse(0L); //获取key的过期时间,单位是秒,如果没有过期时间,返回0
if (registeCacheRepository.keyByKey(key)) { //判断这个hasKey是否存在
Long expire = registeCacheRepository.timeOrdata(key); //获取key的过期时间,单位是秒,如果没有过期时间,返回0
if (expire > 120) {
throw new ServiceException(ServiceCode.ERROR,"请求频繁,请稍后再试");
}
}
log.debug("没有存在仅需执行! 继续执行");
log.debug("没有存在继续执行! 继续执行");
if (mapper.selectByEmail(email) != null) { // 判断邮箱是否已被注册
throw new ServiceException(ServiceCode.ERROR,"此邮箱已被其他用户注册");
......@@ -98,8 +96,10 @@ public class AuthorizeServiceImpl implements AuthorizeService {
message.setText("验证码是" + code); //设置邮件内容为"验证码是"+code,即拼接验证码和字符串
try {
log.debug("开始发送邮件验证码");
mailSender.send(message);
template.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES); //存入redis数据库,持续时间3分钟
registeCacheRepository.AddSendToEmail(key,String.valueOf(code));
// template.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES); //存入redis数据库,持续时间3分钟
log.debug("验证码为:{}",code);
// return null;
} catch (MailException e) {
......@@ -123,10 +123,9 @@ public class AuthorizeServiceImpl implements AuthorizeService {
public void validateAndRegister(String username, String password, String email, String nickname, String code, String sessionId) {
log.debug("开始注册业务操作");
String key = REGISTER_EMAIL_SEND + sessionId +" : "+ email;
if (Boolean.TRUE.equals(template.hasKey(key))) {
String s = template.opsForValue().get(key);
if (registeCacheRepository.keyByKey(key)) {
String s = registeCacheRepository.valueByKey(key);
if (s == null) {
throw new ServiceException(ServiceCode.ERROR,"验证码失效,请重新请求");
}
......
......@@ -2,7 +2,7 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.youbiliprojectbackend.modules.user.account.mapper.AccountMapper">
<mapper namespace="cn.tedu.youbiliprojectbackend.modules.user.account.dao.mapper.AccountMapper">
<select id="SelectByUserName" resultType="cn.tedu.youbiliprojectbackend.modules.user.account.pojo.entity.Account">
SELECT userID, username, nickname, password, email, birthday, accountLevel, fans, follows, videoCount, totalLikes, membershipStatus, registrationDate, lastLoginDate, imgUrl, enable, gmtCreate, gmtModified
FROM user
......
......@@ -2,7 +2,7 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tedu.youbiliprojectbackend.modules.user.register.mapper.UserMapper">
<mapper namespace="cn.tedu.youbiliprojectbackend.modules.user.register.dao.mapper.UserMapper">
<insert id="insertUser">
INSERT INTO user (username, nickname, password, email) VALUES (#{username},#{nickname},#{password},#{email})
</insert>
......
package cn.tedu.youbiliprojectbackend;
import cn.tedu.youbiliprojectbackend.modules.user.register.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册