1
0
mirror of https://gitee.com/bookshelfplus/bookshelfplus synced 2025-09-03 23:52:51 +08:00
Code Issues Projects Releases Wiki Activity GitHub Gitee

添加链接失效反馈后端及数据库;登陆改为登录

This commit is contained in:
2022-04-18 18:33:33 +08:00
parent 928bfa40ff
commit 883a245058
20 changed files with 1382 additions and 403 deletions

View File

@@ -368,7 +368,7 @@
toggleDisplayButton();
} else {
if (data.errCode == "20004") {
// 登过期,小问题,这里不弹窗显示
// 登过期,小问题,这里不弹窗显示
localStorageUtils.userLogout();
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
@@ -501,11 +501,11 @@
<div class="file-object-item-content">${content}</div>
<div class="file-object-item-link">${downloadLink}</div>
<div class="outdated-feedback">
<img src="/assets/image/svg/feedback.svg"/>
<img src="/assets/image/svg/feedback.svg" onclick="linkFeedback(${fileObjectInfo.fileId},${fileObjectInfo.id});"/>
<span class="outdated-feedback-tip">链接失效?点击反馈!</span>
</div>
</div>`.replace(/\ [ ]+?/g,"").replace(/[\n]/g,"") //去掉多余空格、换行
console.log(dom);
// console.log(dom);
return dom;
}
getRequest("/file/getFile", { bookId: bookId })
@@ -550,7 +550,7 @@
</div>`
);
}
fileContainer.innerHTML += innerHTML.join("");
fileContainer.innerHTML = innerHTML.join("");
if (innerHTML.length == 0) {
var fileItem = document.createElement("div");
@@ -623,5 +623,39 @@
});
}
</script>
<script>
// 链接失效反馈
function linkFeedback(fileId, fileObjectId) {
if (!confirm("确定这个下载链接失效了吗?(没失效的链接不可以乱点着玩儿哦)"))
return;
if (!localStorageUtils.getLoginStatus()) {
if (confirm("您尚未登录,登录后反馈处理更快,是否前往登录?")) {
location.href = "/login?redirect=" + encodeURIComponent(location.pathname + location.search);
return;
}
}
postRequest("/file/object/FailureFeedback", { bookId: bookId, fileId: fileId, fileObjectId: fileObjectId, token: localStorageUtils.getToken() })
.then(function (response) {
var axiosData = response.data;
var status = axiosData.status;
var data = axiosData.data;
if (status === "success") {
// console.log(data);
if (data) {
alert("真棒!反馈成功!");
} else {
alert("反馈失败,请稍后再试!");
}
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
}
}).catch(function (error) {
console.log(error);
alert("无法连接到服务器,请检查网络连接!");
});
}
</script>
</body>
</html>

View File

@@ -52,7 +52,7 @@
window.location.href = "/login";
}
} else {
if(data.errCode == "20004") { // 登过期
if(data.errCode == "20004") { // 登过期
localStorageUtils.userLogout();
window.location.href = "/login";
}

View File

@@ -135,7 +135,7 @@
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
if (data.errCode == "20004") {
// 登过期
// 登过期
localStorageUtils.userLogout();
location.href = "/login";
}

View File

@@ -3,11 +3,6 @@
<head>
<%- include("./component/header.html"); %>
<style>
* {
margin: 0;
padding: 0;
}
.wrap {
margin: 20px auto;
position: relative;
@@ -53,7 +48,7 @@
user-select: all;
}
p {
.main p {
font-size: 14px !important;
font-family: initial !important;
}
@@ -65,7 +60,7 @@
<h1><%= headText %></h1>
<div id="container">
<p>
<br>反馈前请选择正确的分类,否则反馈经过二次转接,响应时间将会变长。
反馈前请选择正确的分类,否则反馈经过二次转接,响应时间将会变长。
</p>
<div class="wrap">
<label>
@@ -95,7 +90,7 @@
<br>
</p>
<p>
请点击链接旁的 <img src="/assets/image/svg/feedback.svg" style="width: 1em; height: 1em;"/> 按钮进行反馈。
前往下载页面,点击链接旁的 <img src="/assets/image/svg/feedback.svg" style="width: 1em; height: 1em;"/> 按钮进行反馈。
</p>
</div>
</label>
@@ -141,16 +136,8 @@
</main>
<%- include("./component/footer.html"); %>
<!-- 获取参数 -->
<script src="/assets/javascripts/getParams.js"></script>
<!-- 点击复制及反馈样式 -->
<script src="/assets/javascripts/cssUtils.js"></script>
<script>
var requestParams = getParams();
// var searchbox = document.getElementById("searchInput");
// var categoryId = requestParams["id"] ?? "";
// console.log("categoryId", categoryId);
</script>
<script>
// 点击复制
$(".click2copy").click(function (e) {

View File

@@ -78,6 +78,8 @@
<!-- <script src="/assets/lib/cryptography/2.2/md5-min.js"></script> -->
<!-- <script src="/assets/lib/cryptography/2.2/sha1-min.js"></script> -->
<!-- 获取参数 -->
<script src="/assets/javascripts/getParams.js"></script>
<script>
// 避免重复点击
var isOnLogin = false;
@@ -137,6 +139,17 @@
token: data.token,
is_admin: data.group === "ADMIN",
});
// 用户登录成功
// 如果指定了 Redirect 链接,则跳到指定链接
var requestParams = getParams();
var redirectUrl = requestParams["redirect"] ?? "";
if (redirectUrl) {
location.href = location.origin + redirectUrl;
return;
}
// 如果没有指定 Redirect 链接,则跳到后台
if (localStorageUtils.getIsAdmin()) {
window.location.href = "/dashboard/admin/index";
} else {

View File

@@ -11,7 +11,7 @@
Target Server Version : 50726
File Encoding : 65001
Date: 16/04/2022 23:29:53
Date: 18/04/2022 17:54:01
*/
SET NAMES utf8mb4;
@@ -131,6 +131,22 @@ CREATE TABLE `cos_presigned_url_generate_log` (
-- Records of cos_presigned_url_generate_log
-- ----------------------------
-- ----------------------------
-- Table structure for failure_feedback
-- ----------------------------
DROP TABLE IF EXISTS `failure_feedback`;
CREATE TABLE `failure_feedback` (
`book_id` int(11) NOT NULL DEFAULT 0,
`file_id` int(11) NOT NULL DEFAULT 0,
`file_object_id` int(11) NOT NULL DEFAULT 0,
`user_id` int(11) NOT NULL DEFAULT 0,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '失效反馈' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of failure_feedback
-- ----------------------------
-- ----------------------------
-- Table structure for file_info
-- ----------------------------

View File

@@ -872,6 +872,83 @@ __可选__|string
----
[[_failurefeedbackusingpost]]
==== 链接失效反馈
....
POST /api/file/object/FailureFeedback
....
===== 说明
查询文件列表
===== 参数
[options="header", cols=".^2a,.^3a,.^4a"]
|===
|类型|名称|类型
|**FormData**|**bookId** +
__可选__|integer (int32)
|**FormData**|**fileId** +
__可选__|integer (int32)
|**FormData**|**fileObjectId** +
__可选__|integer (int32)
|**FormData**|**token** +
__可选__|string
|===
===== 响应
[options="header", cols=".^2a,.^14a,.^4a"]
|===
|HTTP代码|说明|类型
|**200**|OK|<<_commonreturntype,CommonReturnType>>
|**201**|Created|无内容
|**401**|Unauthorized|无内容
|**403**|Forbidden|无内容
|**404**|Not Found|无内容
|===
===== 消耗
* `application/x-www-form-urlencoded`
===== 生成
* `\*/*`
===== HTTP请求示例
====== 请求 path
----
/api/file/object/FailureFeedback
----
====== 请求 formData
[source,json]
----
"string"
----
===== HTTP响应示例
====== 响应 200
[source,json]
----
{
"data" : "object",
"status" : "string"
}
----
[[_objectlistusingpost]]
==== 【管理员】查询文件对象列表
....
@@ -943,6 +1020,79 @@ __可选__|string
----
[[_refreshfileobjectstatususingpost]]
==== 【管理员】更新文件对象上传状态
....
POST /api/file/object/refreshFileObjectStatus
....
===== 说明
重新从 COS 对象存储中获取文件对象上传状态
===== 参数
[options="header", cols=".^2a,.^3a,.^4a"]
|===
|类型|名称|类型
|**FormData**|**fileObjectId** +
__可选__|integer (int32)
|**FormData**|**token** +
__可选__|string
|===
===== 响应
[options="header", cols=".^2a,.^14a,.^4a"]
|===
|HTTP代码|说明|类型
|**200**|OK|<<_commonreturntype,CommonReturnType>>
|**201**|Created|无内容
|**401**|Unauthorized|无内容
|**403**|Forbidden|无内容
|**404**|Not Found|无内容
|===
===== 消耗
* `application/x-www-form-urlencoded`
===== 生成
* `\*/*`
===== HTTP请求示例
====== 请求 path
----
/api/file/object/refreshFileObjectStatus
----
====== 请求 formData
[source,json]
----
"string"
----
===== HTTP响应示例
====== 响应 200
[source,json]
----
{
"data" : "object",
"status" : "string"
}
----
[[_coscheckfilestatususingpost]]
==== 【COS】腾讯云 COS 文件上传成功回调
....

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,7 @@ public class BaseController {
public static final Integer COMMON_PAGE_SIZE = 10;
/**
* 获取用户登状态
* 获取用户登状态
*/
public Boolean isLogin() {
SessionManager sessionManager = RedisSessionManager.getInstance(redisTemplate);

View File

@@ -19,9 +19,11 @@ import plus.bookshelf.Common.Response.CommonReturnType;
import plus.bookshelf.Config.QCloudCosConfig;
import plus.bookshelf.Controller.VO.FileObjectVO;
import plus.bookshelf.Controller.VO.FileVO;
import plus.bookshelf.Service.Impl.FailureFeedbackServiceImpl;
import plus.bookshelf.Service.Impl.FileObjectServiceImpl;
import plus.bookshelf.Service.Impl.FileServiceImpl;
import plus.bookshelf.Service.Impl.UserServiceImpl;
import plus.bookshelf.Service.Model.FailureFeedbackModel;
import plus.bookshelf.Service.Model.FileModel;
import plus.bookshelf.Service.Model.FileObjectModel;
import plus.bookshelf.Service.Model.UserModel;
@@ -50,6 +52,9 @@ public class FileController extends BaseController {
@Autowired
FileObjectServiceImpl fileObjectService;
@Autowired
FailureFeedbackServiceImpl failureFeedbackService;
@ApiOperation(value = "书籍下载页面获取文件提供的下载方式", notes = "")
@RequestMapping(value = "getFile", method = {RequestMethod.GET})
@ResponseBody
@@ -95,6 +100,37 @@ public class FileController extends BaseController {
return CommonReturnType.create(fileVOS);
}
@ApiOperation(value = "链接失效反馈", notes = "查询文件列表")
@RequestMapping(value = "object/FailureFeedback", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType failureFeedback(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "bookId", required = false) Integer bookId,
@RequestParam(value = "fileId", required = false) Integer fileId,
@RequestParam(value = "fileObjectId", required = false) Integer fileObjectId) throws BusinessException {
Integer userId = null;
if (token != null) {
try {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
userId = userModel.getId();
} catch (BusinessException e) {
// 用户未登录,不返回错误信息
}
}
FailureFeedbackModel failureFeedbackModel = new FailureFeedbackModel();
failureFeedbackModel.setBookId(bookId);
failureFeedbackModel.setFileId(fileId);
failureFeedbackModel.setFileObjectId(fileObjectId);
failureFeedbackModel.setUserId(userId);
failureFeedbackModel.setCreateTime(Calendar.getInstance().getTime());
Boolean isSuccess = failureFeedbackService.addFailureFeedback(failureFeedbackModel);
if (!isSuccess) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "反馈失败");
}
return CommonReturnType.create(isSuccess);
}
@ApiOperation(value = "【管理员】查询文件对象列表", notes = "查询文件列表")
@RequestMapping(value = "object/list", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody

View File

@@ -0,0 +1,19 @@
package plus.bookshelf.Controller.VO;
import lombok.Data;
import java.util.Date;
@Data
public class FailureFeedbackVO {
private Integer bookId;
private Integer fileId;
private Integer fileObjectId;
private Integer userId;
private Date createTime;
}

View File

@@ -0,0 +1,170 @@
package plus.bookshelf.Dao.DO;
import java.util.Date;
public class FailureFeedbackDO {
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column failure_feedback.book_id
*
* @mbg.generated
*/
private Integer bookId;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column failure_feedback.file_id
*
* @mbg.generated
*/
private Integer fileId;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column failure_feedback.file_object_id
*
* @mbg.generated
*/
private Integer fileObjectId;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column failure_feedback.user_id
*
* @mbg.generated
*/
private Integer userId;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column failure_feedback.create_time
*
* @mbg.generated
*/
private Date createTime;
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column failure_feedback.book_id
*
* @return the value of failure_feedback.book_id
*
* @mbg.generated
*/
public Integer getBookId() {
return bookId;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column failure_feedback.book_id
*
* @param bookId the value for failure_feedback.book_id
*
* @mbg.generated
*/
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column failure_feedback.file_id
*
* @return the value of failure_feedback.file_id
*
* @mbg.generated
*/
public Integer getFileId() {
return fileId;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column failure_feedback.file_id
*
* @param fileId the value for failure_feedback.file_id
*
* @mbg.generated
*/
public void setFileId(Integer fileId) {
this.fileId = fileId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column failure_feedback.file_object_id
*
* @return the value of failure_feedback.file_object_id
*
* @mbg.generated
*/
public Integer getFileObjectId() {
return fileObjectId;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column failure_feedback.file_object_id
*
* @param fileObjectId the value for failure_feedback.file_object_id
*
* @mbg.generated
*/
public void setFileObjectId(Integer fileObjectId) {
this.fileObjectId = fileObjectId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column failure_feedback.user_id
*
* @return the value of failure_feedback.user_id
*
* @mbg.generated
*/
public Integer getUserId() {
return userId;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column failure_feedback.user_id
*
* @param userId the value for failure_feedback.user_id
*
* @mbg.generated
*/
public void setUserId(Integer userId) {
this.userId = userId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column failure_feedback.create_time
*
* @return the value of failure_feedback.create_time
*
* @mbg.generated
*/
public Date getCreateTime() {
return createTime;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column failure_feedback.create_time
*
* @param createTime the value for failure_feedback.create_time
*
* @mbg.generated
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@@ -0,0 +1,23 @@
package plus.bookshelf.Dao.Mapper;
import org.springframework.stereotype.Repository;
import plus.bookshelf.Dao.DO.FailureFeedbackDO;
@Repository // 添加这个注解Autowired的时候idea就不会报错了
public interface FailureFeedbackDOMapper {
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table failure_feedback
*
* @mbg.generated
*/
int insert(FailureFeedbackDO row);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table failure_feedback
*
* @mbg.generated
*/
int insertSelective(FailureFeedbackDO row);
}

View File

@@ -0,0 +1,37 @@
package plus.bookshelf.Service.Impl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import plus.bookshelf.Dao.DO.FailureFeedbackDO;
import plus.bookshelf.Dao.Mapper.FailureFeedbackDOMapper;
import plus.bookshelf.Service.Model.FailureFeedbackModel;
import plus.bookshelf.Service.Service.FailureFeedbackService;
@Service
public class FailureFeedbackServiceImpl implements FailureFeedbackService {
@Autowired
FailureFeedbackDOMapper failureFeedbackDOMapper;
/**
* 添加反馈
*
* @return
*/
@Override
public Boolean addFailureFeedback(FailureFeedbackModel failureFeedbackModel) {
FailureFeedbackDO failureFeedbackDO = convertToDataObject(failureFeedbackModel);
int affectRows = failureFeedbackDOMapper.insertSelective(failureFeedbackDO);
return affectRows > 0;
}
private FailureFeedbackDO convertToDataObject(FailureFeedbackModel failureFeedbackModel) {
if (failureFeedbackModel == null) {
return null;
}
FailureFeedbackDO failureFeedbackDO = new FailureFeedbackDO();
BeanUtils.copyProperties(failureFeedbackModel, failureFeedbackDO);
return failureFeedbackDO;
}
}

View File

@@ -56,7 +56,7 @@ public class UserServiceImpl implements UserService {
// token 已过期
Object userIdObject = RedisSessionManager.getInstance(redisTemplate).getValue(token);
if (userIdObject == null) {
throw new BusinessException(BusinessErrorCode.USER_TOKEN_EXPIRED, "过期啦,请重新登录");
throw new BusinessException(BusinessErrorCode.USER_TOKEN_EXPIRED, "过期啦,请重新登录");
}
Integer userId = (Integer) userIdObject;

View File

@@ -0,0 +1,19 @@
package plus.bookshelf.Service.Model;
import lombok.Data;
import java.util.Date;
@Data
public class FailureFeedbackModel {
private Integer bookId;
private Integer fileId;
private Integer fileObjectId;
private Integer userId;
private Date createTime;
}

View File

@@ -0,0 +1,14 @@
package plus.bookshelf.Service.Service;
import plus.bookshelf.Service.Model.FailureFeedbackModel;
public interface FailureFeedbackService {
/**
* 添加反馈
*
* @param failureFeedbackModel
* @return
*/
Boolean addFailureFeedback(FailureFeedbackModel failureFeedbackModel);
}

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="plus.bookshelf.Dao.Mapper.FailureFeedbackDOMapper">
<resultMap id="BaseResultMap" type="plus.bookshelf.Dao.DO.FailureFeedbackDO">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<result column="book_id" jdbcType="INTEGER" property="bookId" />
<result column="file_id" jdbcType="INTEGER" property="fileId" />
<result column="file_object_id" jdbcType="INTEGER" property="fileObjectId" />
<result column="user_id" jdbcType="INTEGER" property="userId" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>
<insert id="insert" parameterType="plus.bookshelf.Dao.DO.FailureFeedbackDO">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into failure_feedback (book_id, file_id, file_object_id,
user_id, create_time)
values (#{bookId,jdbcType=INTEGER}, #{fileId,jdbcType=INTEGER}, #{fileObjectId,jdbcType=INTEGER},
#{userId,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective" parameterType="plus.bookshelf.Dao.DO.FailureFeedbackDO">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into failure_feedback
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bookId != null">
book_id,
</if>
<if test="fileId != null">
file_id,
</if>
<if test="fileObjectId != null">
file_object_id,
</if>
<if test="userId != null">
user_id,
</if>
<if test="createTime != null">
create_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bookId != null">
#{bookId,jdbcType=INTEGER},
</if>
<if test="fileId != null">
#{fileId,jdbcType=INTEGER},
</if>
<if test="fileObjectId != null">
#{fileObjectId,jdbcType=INTEGER},
</if>
<if test="userId != null">
#{userId,jdbcType=INTEGER},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
</mapper>

View File

@@ -103,5 +103,8 @@
<!--<table tableName="schedule_task" domainObjectName="ScheduleTaskDO" enableCountByExample="false"-->
<!-- enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"-->
<!-- selectByExampleQueryId="false"></table>-->
<!--<table tableName="failure_feedback" domainObjectName="FailureFeedbackDO" enableCountByExample="false"-->
<!-- enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"-->
<!-- selectByExampleQueryId="false"></table>-->
</context>
</generatorConfiguration>

View File

@@ -4,7 +4,7 @@
## 第1种创建子用户
腾讯云后台进入访问管理下的用户列表页https://console.cloud.tencent.com/cam
腾讯云后台进入访问管理下的用户列表页https://console.cloud.tencent.com/cam
点击新建用户