资源下载链路打通

This commit is contained in:
limqhz
2022-05-03 17:15:54 +08:00
parent f44f36356d
commit f271221d8b
39 changed files with 888 additions and 312 deletions

View File

@@ -102,6 +102,12 @@
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.5.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->

View File

@@ -4,7 +4,6 @@ package com.quinn.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quinn.pojo.About;
import com.quinn.pojo.Say;
import com.quinn.service.AboutService;
import com.quinn.utils.QuinnUtils;
import org.springframework.stereotype.Controller;

View File

@@ -3,11 +3,13 @@ package com.quinn.controller;
import com.quinn.mapper.DownloadMapper;
import com.quinn.pojo.Download;
import com.quinn.service.DownloadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import javax.annotation.Resource;
import java.util.List;
/**
@@ -21,12 +23,12 @@ import java.util.List;
@Controller
public class DownloadController {
@Autowired
DownloadMapper downloadMapper;
@Resource
DownloadService downloadService;
@GetMapping({"/download"})
public String download(Model model){
List<Download> downloadList = downloadMapper.selectList(null);
List<Download> downloadList = downloadService.list(null);
model.addAttribute("downloadList",downloadList);
return "page/download";
}

View File

@@ -31,11 +31,6 @@ public class LoginController {
return "index";
}
@GetMapping({"/auto"})
public String auto(){
return "index";
}
@GetMapping("/toLogin")
public String toLogin(){
return "login";

View File

@@ -1,53 +0,0 @@
package com.quinn.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quinn.pojo.Say;
import com.quinn.service.SayService;
import com.quinn.utils.QuinnUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Controller
public class SayController {
@Autowired
SayService sayService;
@GetMapping("/say")
public String userIndexBlog(Model model){
Page<Say> pageParam = new Page<>(1, 50);
sayService.page(pageParam,new QueryWrapper<Say>().orderByDesc("gmt_create"));
// 结果
List<Say> sayList = pageParam.getRecords();
model.addAttribute("sayList",sayList);
model.addAttribute("pageParam",pageParam);
return "page/say";
}
@PostMapping("/say/{role}")
public String saveSay(@PathVariable("role") int role, Say say){
// 防止请求提交
if (role!=1){
return "redirect:/say";
}
say.setId(QuinnUtils.getUuid());
say.setGmtCreate(QuinnUtils.getTime());
// 结果
sayService.save(say);
return "redirect:/say";
}
}

View File

@@ -0,0 +1,21 @@
package com.quinn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Controller
public class SourceCategoryController {
}

View File

@@ -0,0 +1,17 @@
package com.quinn.controller;
import org.springframework.stereotype.Controller;
/**
* <p>
* 前端控制器
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Controller
public class SourceCommentController {
}

View File

@@ -0,0 +1,83 @@
package com.quinn.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quinn.pojo.*;
import com.quinn.service.SourceCategoryService;
import com.quinn.service.SourceCommentService;
import com.quinn.service.SourceService;
import com.quinn.utils.UUIDGenerator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Controller
public class SourceController {
@Resource
SourceService sourceService;
@Resource
SourceCategoryService sourceCategoryService;
@Resource
SourceCommentService sourceCommentService;
// 列表展示
@GetMapping("/source")
public String blogList(@RequestParam String name,@RequestParam int category,Model model){
System.out.println(name + category);
Page<Source> pageParam = new Page<>(1, 10);
QueryWrapper<Source> sourceQuery = new QueryWrapper<>();
sourceQuery.orderByDesc("gmt_create");
sourceService.page(pageParam,sourceQuery);
// 结果
List<Source> sourceList = pageParam.getRecords();
model.addAttribute("sourceList",sourceList);
model.addAttribute("pageParam",pageParam);
// 分类信息
List<SourceCategory> categoryList = sourceCategoryService.list(null);
model.addAttribute("categoryList",categoryList);
return "source/list";
}
// 查看文件详情
@GetMapping("/source/view/{sid}")
public String read(@PathVariable("sid") String sid, Model model){
Source source = sourceService.getOne(new QueryWrapper<Source>().eq("id", sid));
source.setSourceLink("no network link");
model.addAttribute("source",source);
List<SourceComment> commentList = sourceCommentService.list(new QueryWrapper<SourceComment>().eq("topic_id", sid).orderByDesc("gmt_create"));
model.addAttribute("commentList",commentList);
return "source/view";
}
// 下载文件
@GetMapping("/source/download/{sid}")
public void read(HttpServletResponse response, @PathVariable("sid") String sid) throws IOException {
//通知浏览器以附件形式下载
response.setHeader("Content-Disposition",
"attachment;filename=" + UUIDGenerator.randomUUID());
this.sourceService.downloadSource(response.getOutputStream(),sid);
}
}

View File

@@ -22,7 +22,7 @@ public class CodeGenerator {
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("limqsh");
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setFileOverride(true); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
@@ -51,7 +51,7 @@ public class CodeGenerator {
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("qn_about");//设置要映射的表名
strategy.setInclude("qn_source_comment");//设置要映射的表名
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix("qn_");//设置表前缀不生成

View File

@@ -0,0 +1,16 @@
package com.quinn.mapper;
import com.quinn.pojo.SourceCategory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
public interface SourceCategoryMapper extends BaseMapper<SourceCategory> {
}

View File

@@ -0,0 +1,16 @@
package com.quinn.mapper;
import com.quinn.pojo.SourceComment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
public interface SourceCommentMapper extends BaseMapper<SourceComment> {
}

View File

@@ -1,6 +1,6 @@
package com.quinn.mapper;
import com.quinn.pojo.Say;
import com.quinn.pojo.Source;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
@@ -9,8 +9,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* </p>
*
* @author limqsh
* @since 2020-07-01
* @since 2022-05-03
*/
public interface SayMapper extends BaseMapper<Say> {
public interface SourceMapper extends BaseMapper<Source> {
}

View File

@@ -0,0 +1,5 @@
<?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="com.quinn.mapper.SourceCategoryMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?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="com.quinn.mapper.SourceCommentMapper">
</mapper>

View File

@@ -0,0 +1,5 @@
<?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="com.quinn.mapper.SourceMapper">
</mapper>

View File

@@ -0,0 +1,68 @@
package com.quinn.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("qn_source")
@ApiModel(value="Source对象", description="")
public class Source implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "资源名")
private String sourceName;
@ApiModelProperty(value = "资源内容")
private String sourceContent;
@ApiModelProperty(value = "关键字1")
private String keyWord1;
@ApiModelProperty(value = "关键字2")
private String keyWord2;
@ApiModelProperty(value = "关键字3")
private String keyWord3;
@ApiModelProperty(value = "资源类型")
private String sourceType;
@ApiModelProperty(value = "资源链接")
private String sourceLink;
@ApiModelProperty(value = "类别ID")
private Integer categoryId;
@ApiModelProperty(value = "类别名")
private String categoryName;
@ApiModelProperty(value = "创建时间")
private Date gmtCreate;
@ApiModelProperty(value = "修改时间")
private Date gmtUpdate;
}

View File

@@ -2,7 +2,6 @@ package com.quinn.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
@@ -17,29 +16,23 @@ import lombok.experimental.Accessors;
* </p>
*
* @author limqsh
* @since 2020-07-01
* @since 2022-05-03
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("qn_say")
@ApiModel(value="Say对象", description="")
public class Say implements Serializable {
@TableName("qn_source_category")
@ApiModel(value="SourceCategory对象", description="")
public class SourceCategory implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "唯一id")
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
@ApiModelProperty(value = "自增id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "标题")
private String title;
@ApiModelProperty(value = "内容")
private String content;
@ApiModelProperty(value = "时间")
private Date gmtCreate;
@ApiModelProperty(value = "博客分类")
private String category;
}

View File

@@ -0,0 +1,60 @@
package com.quinn.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
*
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("qn_source_comment")
@ApiModel(value="SourceComment对象", description="")
public class SourceComment implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "自增id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "评论唯一id")
private String commentId;
@ApiModelProperty(value = "1博客 2问答")
private Integer topicCategory;
@ApiModelProperty(value = "评论主题id")
private String topicId;
@ApiModelProperty(value = "评论者id")
private String userId;
@ApiModelProperty(value = "评论者昵称")
private String userName;
@ApiModelProperty(value = "评论者头像")
private String userAvatar;
@ApiModelProperty(value = "评论内容")
private String content;
@ApiModelProperty(value = "评论创建时间")
private Date gmtCreate;
}

View File

@@ -0,0 +1,16 @@
package com.quinn.service;
import com.quinn.pojo.SourceCategory;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
public interface SourceCategoryService extends IService<SourceCategory> {
}

View File

@@ -1,6 +1,6 @@
package com.quinn.service;
import com.quinn.pojo.Say;
import com.quinn.pojo.SourceComment;
import com.baomidou.mybatisplus.extension.service.IService;
/**
@@ -9,8 +9,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
* </p>
*
* @author limqsh
* @since 2020-07-01
* @since 2022-05-03
*/
public interface SayService extends IService<Say> {
public interface SourceCommentService extends IService<SourceComment> {
}

View File

@@ -0,0 +1,22 @@
package com.quinn.service;
import com.quinn.pojo.Source;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* <p>
* 服务类
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
public interface SourceService extends IService<Source> {
void downloadSource(ServletOutputStream outputStream, String sid) throws IOException;
}

View File

@@ -1,20 +0,0 @@
package com.quinn.service.impl;
import com.quinn.pojo.Say;
import com.quinn.mapper.SayMapper;
import com.quinn.service.SayService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author limqsh
* @since 2020-07-01
*/
@Service
public class SayServiceImpl extends ServiceImpl<SayMapper, Say> implements SayService {
}

View File

@@ -0,0 +1,20 @@
package com.quinn.service.impl;
import com.quinn.pojo.SourceCategory;
import com.quinn.mapper.SourceCategoryMapper;
import com.quinn.service.SourceCategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Service
public class SourceCategoryServiceImpl extends ServiceImpl<SourceCategoryMapper, SourceCategory> implements SourceCategoryService {
}

View File

@@ -0,0 +1,20 @@
package com.quinn.service.impl;
import com.quinn.pojo.SourceComment;
import com.quinn.mapper.SourceCommentMapper;
import com.quinn.service.SourceCommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Service
public class SourceCommentServiceImpl extends ServiceImpl<SourceCommentMapper, SourceComment> implements SourceCommentService {
}

View File

@@ -0,0 +1,52 @@
package com.quinn.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.quinn.pojo.Source;
import com.quinn.mapper.SourceMapper;
import com.quinn.service.SourceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quinn.utils.OSSClientUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* <p>
* 服务实现类
* </p>
*
* @author limqsh
* @since 2022-05-03
*/
@Service
public class SourceServiceImpl extends ServiceImpl<SourceMapper, Source> implements SourceService {
@Resource
OSSClientUtil ossClientUtil;
@Override
public void downloadSource(ServletOutputStream outputStream, String sid) throws IOException {
Source source = getOne(new QueryWrapper<Source>().eq("id", sid));
String sourceLink = source.getSourceLink();
// 读取文件内容。
BufferedInputStream in = new BufferedInputStream(ossClientUtil.downloadFile(sourceLink));
BufferedOutputStream out = new BufferedOutputStream(outputStream);
byte[] buffer = new byte[1024];
int lenght = 0;
while ((lenght = in.read(buffer)) != -1) {
out.write(buffer, 0, lenght);
}
if (out != null) {
out.flush();
out.close();
}
if (in != null) {
in.close();
}
}
}

View File

@@ -0,0 +1,115 @@
package com.quinn.utils;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.OSSObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
/**
* 阿里云 OSS文件类
*
* @author zuojie.liang
*/
@Component
public class OSSClientUtil {
Log log = LogFactory.getLog(OSSClientUtil.class);
/**
* 协议
*/
@Value("${oss.protocol}")
private String protocol;
/**
* 仓库名称
*/
@Value("${oss.name}")
private String bucketName;
/**
* 公网节点
*/
@Value("${oss.endPoint}")
private String endpoint;
@Value("${oss.accessKeyId}")
private String accessKeyId;
/**
* API访问值
*/
@Value("${oss.accessKeySecret}")
private String accessKeySecret;
@Value("${oss.url}")
private String url;
private OSSClient ossClient;
public String upload(String filename, InputStream file) {
return uploadImg(file, filename);
}
/**
* 上传图片
*
* @param file
* @return
*/
public String uploadImg(MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename();
return uploadImg(file.getInputStream(), originalFilename);
}
public String uploadImg(InputStream inputStream, String originalFilename) {
String backUrl = "";
try {
ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
Random random = new Random();
String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
backUrl = "imageDir/" + name;
// 上传文件
ossClient.putObject(bucketName, backUrl, inputStream);
ossClient.setObjectAcl(bucketName, backUrl, CannedAccessControlList.PublicRead);
// 判断是否上传成功
boolean uploadResult = ossClient.doesObjectExist(bucketName, backUrl);
if (uploadResult) {
backUrl = getImgUrl(name);
} else {
backUrl = "";
}
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
return backUrl;
}
/**
* 获得图片路径
*
* @param fileUrl
* @return
*/
public String getImgUrl(String fileUrl) {
if (!StringUtils.isEmpty(fileUrl)) {
String[] split = fileUrl.split("/");
return url + "imageDir/" + split[split.length - 1];
}
return null;
}
public InputStream downloadFile(String objName){
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
OSSObject ossObject = ossClient.getObject(bucketName, objName);
return ossObject.getObjectContent();
}
}

View File

@@ -0,0 +1,28 @@
package com.quinn.utils;
import java.util.StringTokenizer;
import java.util.UUID;
/**
* @title UUIDGenerator
* @description 随机生成32位UUID格式如a11686c39a154cf2a5238fb14cf3d097
* <br>
* <br>
*/
public class UUIDGenerator {
/**
* 主键生成机制
* @return
*/
public static String randomUUID(){
String result="";
UUID uuid = UUID.randomUUID();
String temp=uuid.toString();
StringTokenizer token=new StringTokenizer(temp,"-");
while(token.hasMoreTokens()){
result+=token.nextToken();
}
return result;
}
}

View File

@@ -1 +1,8 @@
spring.profiles.active=dev
oss.accessKeyId=LTAIlbtS4W2Xe4OV
oss.accessKeySecret=qWMYkSfmXFtRoIv9q9OCbszcF9U7dX
oss.protocol=http
oss.name=smartvenue
oss.endPoint=http://oss-cn-beijing.aliyuncs.com
oss.url=https://smartvenue.oss-cn-beijing.aliyuncs.com/

View File

@@ -299,19 +299,19 @@ div {
@-webkit-keyframes zeroFour {
0% {
content: "4";
content: "";
}
100% {
content: "0";
content: "";
}
}
@keyframes zeroFour {
0% {
content: "4";
content: "";
}
100% {
content: "0";
content: "";
}
}

View File

@@ -62,8 +62,8 @@ try {
"mouseover": [
{ "selector": ".container a[href^='http']", "text": ["要看看 <span style=\"color:#0099cc;\">{text}</span> 么?"] },
{ "selector": ".fui-home", "text": ["点击前往首页,想回到上一页可以使用浏览器的后退功能哦"] },
{ "selector": ".fui-chat", "text": ["一言一语,一颦一笑。一字一句,一颗赛艇。"] },
{ "selector": ".fui-eye", "text": ["嗯··· 要切换 看板娘 吗?"] },
{ "selector": ".fui-chat", "text": ["我们来干点 鸡汤 吧?"] },
{ "selector": ".fui-eye", "text": ["嗯··· 要切换 角色 吗?"] },
{ "selector": ".fui-user", "text": ["喜欢换装 Play 吗?"] },
{ "selector": ".fui-photo", "text": ["要拍张纪念照片吗?"] },
{ "selector": ".fui-info-circle", "text": ["这里有关于我的信息呢"] },
@@ -124,10 +124,15 @@ try {
;
live2d_settings['hitokotoAPI'] = 'hitokoto.cn';
live2d_settings['modelId'] = 5;
live2d_settings['modelTexturesId'] = 1;
live2d_settings['homePageUrl'] = 'index';
live2d_settings['modelId'] = 2;
live2d_settings['modelTexturesId'] = 22;
live2d_settings['modelStorage'] = false;
live2d_settings['canTurnToAboutPage'] = false;
live2d_settings['screenshotCaptureName']= 'quinn.png';
live2d_settings['waifuEdgeSide'] = 'left:0'; // 看板娘贴边方向,例如 'left:0'(靠左 0px), 'right:30'(靠右 30px)
live2d_settings['waifuDraggable'] = 'unlimited'; // 拖拽样式,例如 'disable'(禁用), 'axis-x'(只能水平拖拽), 'unlimited'(自由拖拽)
live2d_settings['waifuDraggableRevert'] = true; // 松开鼠标还原拖拽位置,可选 true(真), false(假)
initModel(modelJson);
}
});

View File

@@ -32,9 +32,9 @@
<a href="#" th:text="${blog.getAuthorName()}"></a>
<span>
<svg class="bi bi-eye-fill" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path fill-rule="evenodd" d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
</svg>
<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path fill-rule="evenodd" d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
</svg>
[[${blog.getViews()}]]
</span>
<!-- 自己写的文章可以编辑和删除 -->

View File

@@ -27,10 +27,10 @@
<a class="nav-link" th:href="@{/blog}">博客 </a>
</li>
<li th:class="${activeUrl=='download'?'nav-item active':'nav-item'}">
<a class="nav-link" th:href="@{/download}">资源 </a>
<a class="nav-link" th:href="@{/download}">热门资源 </a>
</li>
<li th:class="${activeUrl=='say'?'nav-item active':'nav-item'}">
<a class="nav-link" th:href="@{/say}">公告 </a>
<li th:class="${activeUrl=='source'?'nav-item active':'nav-item'}">
<a class="nav-link" th:href="@{/source?name=&category=0}">资源库 </a>
</li>
<li th:class="${activeUrl=='about'?'nav-item active':'nav-item'}">
<a class="nav-link" th:href="@{/about}">关于 </a>

View File

@@ -1,51 +0,0 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>404-Quinn</title>
<link rel="stylesheet" th:href="@{/css/error.css}">
</head>
<body>
<div class="NotPage">
<div class="message"><a th:href="@{/index}" style="color: white">没有此页面,点击回主页</a></div>
<div class="message2" style="text-align: center"><a style="color: white">Quinn</a></div>
<div class="rail">
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
</div>
<div class="world">
<div class="forward">
<div class="box">
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>ERROR-Quinn</title>
<link rel="stylesheet" th:href="@{/css/error.css}">
</head>
<body>
<div class="NotPage">
<div class="message"><a th:href="@{/index}" style="color: white">没有此页面,点击回主页</a></div>
<div class="message2" style="text-align: center"><a style="color: white">Quinn-资源丢失</a></div>
<img th:src="@{/images/logo/logo.png}">
</div>
</body>
</html>

View File

@@ -3,48 +3,15 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>5xx-Quinn</title>
<title>ERROR-Quinn</title>
<link rel="stylesheet" th:href="@{/css/error.css}">
</head>
<body>
<div class="NotPage">
<div class="message"><a th:href="@{/index}" style="color: white">没有此页面,点击回主页</a></div>
<div class="message2" style="text-align: center"><a style="color: white">Quinn</a></div>
<div class="rail">
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
<div class="stamp four">4</div>
<div class="stamp zero">0</div>
</div>
<div class="world">
<div class="forward">
<div class="box">
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
<div class="wall"></div>
</div>
</div>
</div>
<div class="message2" style="text-align: center"><a style="color: white">Quinn-资源丢失</a></div>
<img th:src="@{/images/logo/logo.png}">
</div>
</body>

View File

@@ -13,43 +13,45 @@
<div th:replace="~{common/header::header(activeUrl='about')}"></div>
<main role="main">
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselExampleCaptions" data-slide-to="0" class="active"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="1"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
</ol>
<div class="carousel-inner">
<div class="carousel-item active">
<img th:src="@{/images/menu/t1.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>First slide label</h5>
<p>Some representative placeholder content for the first slide.</p>
</div>
</div>
<div class="carousel-item">
<img th:src="@{/images/menu/t2.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>Second slide label</h5>
<p>Some representative placeholder content for the second slide.</p>
</div>
</div>
<div class="carousel-item">
<img th:src="@{/images/menu/t3.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>Third slide label</h5>
<p>Some representative placeholder content for the third slide.</p>
<div class="container">
<div id="carouselExampleCaptions" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carouselExampleCaptions" data-slide-to="0" class="active"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="1"></li>
<li data-target="#carouselExampleCaptions" data-slide-to="2"></li>
</ol>
<div class="carousel-inner">
<div class="carousel-item active">
<img th:src="@{/images/menu/t1.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>First slide label</h5>
<p>Some representative placeholder content for the first slide.</p>
</div>
</div>
<div class="carousel-item">
<img th:src="@{/images/menu/t2.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>Second slide label</h5>
<p>Some representative placeholder content for the second slide.</p>
</div>
</div>
<div class="carousel-item">
<img th:src="@{/images/menu/t3.jpg}" class="d-block w-100" alt="...">
<div class="carousel-caption d-none d-md-block">
<h5>Third slide label</h5>
<p>Some representative placeholder content for the third slide.</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-target="#carouselExampleCaptions" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-target="#carouselExampleCaptions" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</button>
</div>
<button class="carousel-control-prev" type="button" data-target="#carouselExampleCaptions" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-target="#carouselExampleCaptions" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</button>
</div>
</main>

View File

@@ -1,70 +0,0 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>公告-Quinn</title>
<link rel="stylesheet" th:href="@{/bootstrap/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/css/timeline.css}">
</head>
<body>
<div th:replace="~{common/header::header(activeUrl='say')}"></div>
<main role="main">
<div class="container">
<div th:if="${session.loginUser.getRoleId()==1}"
class="col-md-12 blog-main" style="margin-top: 20px">
<form th:action="@{'/say/'+${session.loginUser.getRoleId()}}" method="post">
<div class="col-md-12 mb-3">
<label>标题</label>
<input type="text" name="title" class="form-control" value="" required>
</div>
<div class="col-md-12 mb-3">
<label>内容</label>
<div id="blog-content">
<textarea required name="content" rows="3" class="form-control"> </textarea>
</div>
</div>
<div class="col-md-12 mb-3">
<button type="submit" class="btn btn-primary btn-sm btn-block">发布闲记</button>
</div>
</form>
</div>
<!-- 主要内容部分 -->
<div class="timeline-small">
<div class="timeline-small-body">
<ul>
<li th:each="say:${sayList}">
<div class="bullet green"></div>
<div class="desc">
<h3>
[[${say.getTitle()}]]
<small class="float-right" th:text="${#dates.format(say.getGmtCreate(),'yyyy-MM-dd')}"></small>
</h3>
<h4 th:utext="${say.getContent()}"></h4>
</div>
</li>
</ul>
<p class="text-center" style="color: #1F4661"> ...... </p>
</div>
</div>
</div>
</main>
<div th:replace="~{common/footer::footer}"></div>
<a class="to-top">返回顶部</a>
<script th:src="@{/js/jquery-3.5.1.min.js}"></script>
<script th:src="@{/bootstrap/js/bootstrap.bundle.min.js}"></script>
<script th:src="@{/js/toTop.js}"></script>
<script th:src="@{/js/jquery-ui.min.js}"></script>
<script th:src="@{/live/js/addlive2d.js}"></script>
</body>
</html>

View File

@@ -0,0 +1,82 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>资源库-Quinn</title>
<link rel="stylesheet" th:href="@{/bootstrap/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/css/download.css}">
</head>
<body>
<div th:replace="~{common/header::header(activeUrl='source')}"></div>
<main role="main" class="mt-3">
<div class="container">
<form action="/source">
<div class="form-row align-items-center">
<div class="col-auto">
<label class="sr-only" for="name">KEYWORD</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">关键字</div>
</div>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入关键字"/>
</div>
</div>
<div class="col-auto">
<label class="sr-only" for="category">SOURCE-TYPE</label>
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">类别</div>
</div>
<select id="category" name="category" class="form-control">
<option th:each="category:${categoryList}" th:value="${category.getId()}" th:text="${category.getCategory()}"></option>
</select>
</div>
</div>
<div class="col-auto ml-auto">
<button type="submit" class="btn btn-primary mb-2">查询</button>
</div>
</div>
</form>
</div>
<div class="container">
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">#</th>
<th scope="col">资源名</th>
<th scope="col">资源内容</th>
<th scope="col">资源类型</th>
<th scope="col">去下载</th>
</tr>
</thead>
<tbody>
<tr th:each="source:${sourceList}">
<td th:text="${source.getId()}"></td>
<td th:text="${source.getSourceName()}"></td>
<td th:text="${source.getSourceContent()}"></td>
<td th:text="${source.getCategoryName()}"></td>
<td th:name="${source.getId()}">
<a style="color: white" th:href="@{'/source/view/'+${source.getId()}}" class="btn btn-sm btn-primary">详情</a>
</td>
</tr>
</tbody>
</table>
</div>
</main>
<div th:replace="~{common/footer::footer}"></div>
<a class="to-top">返回顶部</a>
<script th:src="@{/js/jquery-3.5.1.min.js}"></script>
<script th:src="@{/bootstrap/js/bootstrap.bundle.min.js}"></script>
<script th:src="@{/js/toTop.js}"></script>
<script th:src="@{/js/jquery-ui.min.js}"></script>
<script th:src="@{/live/js/addlive2d.js}"></script>
</body>
</html>

View File

@@ -0,0 +1,125 @@
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>资源下载-Quinn</title>
<link rel="stylesheet" th:href="@{/bootstrap/css/bootstrap.min.css}">
<style>
.nav-underline .nav-link {
padding-top: .75rem;
padding-bottom: .75rem;
font-size: .875rem;
color: #6c757d;
}
</style>
</head>
<body style="background: #f2f2f2;">
<!-- 导航栏 -->
<div th:replace="~{common/header::header(activeUrl='source')}"></div>
<main role="main" class="container mt-3 p-3 bg-white rounded">
<div class="row">
<div class="col-md-12 source-main">
<div class="source-post">
<h2 class="source-post-title" th:text="${source.getSourceName()}"></h2>
<p class="source-post-meta">
上传时间:
<span th:text="${#dates.format(source.getGmtUpdate(),'yyyy-MM-dd')}"></span>
类别-
<span th:text="${source.getCategoryName()}"></span>
<a th:href="@{'/source/download/' + ${source.getId()}}" class="btn btn-outline-success col-md-2 float-right">下载</a>
</p>
</div>
<hr style="margin-top: 18px">
<!--文章主体内容-->
<div id="doc-content">
<textarea th:text="${source.getSourceContent()}" style="display:none;" placeholder="markdown"></textarea>
</div>
</div>
<div class="col-md-12 source-main" style="margin-top: 20px">
<hr>
</div>
<div class="col-md-12 source-main" style="margin-top: 20px">
<form th:action="@{'/source/comment/'+${source.getId()}}" method="post">
<input type="hidden" name="userId" th:value="${session.loginUser.getUid()}">
<input type="hidden" name="userName" th:value="${session.loginUser.getUsername()}">
<input type="hidden" name="userAvatar" th:value="${session.loginUser.getAvatar()}">
<input type="hidden" name="topicId" th:value="${source.getId()}">
<div class="form-group">
<textarea name="content" class="form-control" rows="3" required></textarea>
</div>
<button type="submit" class="btn btn-primary float-right">提交评论</button>
</form>
</div>
<div th:if="${commentList.size()!=0}" class="col-md-12 source-main" style="margin-top: 20px">
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2 mb-0">评论列表</h6>
<div th:each="comment:${commentList}" class="media text-muted pt-3">
<img th:src="${comment.getUserAvatar()}" style="border-radius: 5px;margin-right: 5px " width="32" height="32">
<p class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
<strong class="d-block text-gray-dark" th:text="${comment.getUserName()}"></strong>
<span th:text="${comment.getContent()}"></span>
<span th:text="${#dates.format(comment.getGmtCreate(),'yyyy-MM-dd')}" class="badge badge-light float-right"></span>
</p>
</div>
</div>
</div>
<div th:if="${commentList.size()==0}" class="col-md-12 source-main" style="margin-top: 20px">
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="pb-2 mb-0 text-center">emmm... 这里暂时还没有评论....</h6>
</div>
</div>
</div>
</main>
<div th:replace="~{common/footer::footer}"></div>
<a class="to-top">返回顶部</a>
<script th:src="@{/js/jquery-3.5.1.min.js}"></script>
<script th:src="@{/bootstrap/js/bootstrap.bundle.min.js}"></script>
<script th:src="@{/js/toTop.js}"></script>
<script th:src="@{/js/jquery-ui.min.js}"></script>
<script th:src="@{/live/js/addlive2d.js}"></script>
<link rel="stylesheet" th:href="@{/editormd/css/editormd.preview.css}" />
<script th:src="@{/editormd/lib/marked.min.js}"></script>
<script th:src="@{/editormd/lib/prettify.min.js}"></script>
<script th:src="@{/editormd/lib/raphael.min.js}"></script>
<script th:src="@{/editormd/lib/underscore.min.js}"></script>
<script th:src="@{/editormd/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/editormd/lib/flowchart.min.js}"></script>
<script th:src="@{/editormd/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editormd/editormd.js}"></script>
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd.markdownToHTML("doc-content", {//注意这里是上面DIV的id
htmlDecode: "style,script,iframe",
emoji: true,
taskList: true,
tocm: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
codeFold: true
});});
</script>
</body>
</html>