├── pic ├── home.png ├── detail.png ├── 移动端详情页.png └── 移动端首页.png ├── weblog-vue3 ├── public │ └── favicon.ico ├── src │ ├── assets │ │ ├── no-data.png │ │ ├── developer.png │ │ ├── weblog-logo.png │ │ ├── weblog-logo-mini.png │ │ ├── logo.svg │ │ └── main.css │ ├── api │ │ ├── admin │ │ │ ├── file.js │ │ │ ├── blogsettings.js │ │ │ ├── user.js │ │ │ ├── comment.js │ │ │ ├── dashboard.js │ │ │ ├── category.js │ │ │ ├── tag.js │ │ │ ├── article.js │ │ │ └── wiki.js │ │ └── frontend │ │ │ ├── search.js │ │ │ ├── statistics.js │ │ │ ├── archive.js │ │ │ ├── blogsettings.js │ │ │ ├── tag.js │ │ │ ├── article.js │ │ │ ├── category.js │ │ │ ├── wiki.js │ │ │ └── comment.js │ ├── stores │ │ ├── index.js │ │ ├── comment.js │ │ ├── menu.js │ │ ├── blogsettings.js │ │ └── user.js │ ├── components │ │ ├── icons │ │ │ ├── IconSupport.vue │ │ │ ├── IconTooling.vue │ │ │ ├── IconCommunity.vue │ │ │ └── IconDocumentation.vue │ │ ├── CountTo.vue │ │ ├── ArticlePVLineChat.vue │ │ └── FormDialog.vue │ ├── layouts │ │ ├── admin │ │ │ └── components │ │ │ │ └── AdminFooter.vue │ │ └── frontend │ │ │ └── components │ │ │ ├── Footer.vue │ │ │ ├── WikiFooter.vue │ │ │ └── ScrollToTopButton.vue │ ├── App.vue │ ├── composables │ │ ├── util.js │ │ └── cookie.js │ ├── main.js │ ├── permission.js │ └── axios.js ├── postcss.config.js ├── tailwind.config.js ├── index.html ├── .gitignore ├── README.md ├── package.json └── vite.config.js ├── weblog-springboot ├── weblog-module-admin │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── quanxiaoha │ │ │ │ └── weblog │ │ │ │ └── admin │ │ │ │ ├── package-info.java │ │ │ │ ├── model │ │ │ │ ├── package-info.java │ │ │ │ └── vo │ │ │ │ │ ├── file │ │ │ │ │ └── UploadFileRspVO.java │ │ │ │ │ ├── wiki │ │ │ │ │ ├── DeleteWikiReqVO.java │ │ │ │ │ ├── FindWikiCatalogListReqVO.java │ │ │ │ │ ├── UpdateWikiIsTopReqVO.java │ │ │ │ │ ├── UpdateWikiIsPublishReqVO.java │ │ │ │ │ ├── UpdateWikiCatalogReqVO.java │ │ │ │ │ ├── FindWikiPageListReqVO.java │ │ │ │ │ ├── FindWikiCatalogListRspVO.java │ │ │ │ │ ├── AddWikiReqVO.java │ │ │ │ │ ├── UpdateWikiCatalogItemReqVO.java │ │ │ │ │ ├── UpdateWikiReqVO.java │ │ │ │ │ └── FindWikiPageListRspVO.java │ │ │ │ │ ├── comment │ │ │ │ │ ├── DeleteCommentReqVO.java │ │ │ │ │ ├── ExamineCommentReqVO.java │ │ │ │ │ ├── FindCommentPageListRspVO.java │ │ │ │ │ └── FindCommentPageListReqVO.java │ │ │ │ │ ├── tag │ │ │ │ │ ├── DeleteTagReqVO.java │ │ │ │ │ ├── SearchTagsReqVO.java │ │ │ │ │ ├── AddTagReqVO.java │ │ │ │ │ ├── FindTagPageListRspVO.java │ │ │ │ │ └── FindTagPageListReqVO.java │ │ │ │ │ ├── article │ │ │ │ │ ├── DeleteArticleReqVO.java │ │ │ │ │ ├── FindArticleDetailReqVO.java │ │ │ │ │ ├── UpdateArticleIsTopReqVO.java │ │ │ │ │ ├── FindArticlePageListRspVO.java │ │ │ │ │ ├── FindArticlePageListReqVO.java │ │ │ │ │ ├── FindArticleDetailRspVO.java │ │ │ │ │ ├── PublishArticleReqVO.java │ │ │ │ │ └── UpdateArticleReqVO.java │ │ │ │ │ ├── dashboard │ │ │ │ │ ├── FindDashboardPVStatisticsInfoRspVO.java │ │ │ │ │ └── FindDashboardStatisticsInfoRspVO.java │ │ │ │ │ ├── user │ │ │ │ │ ├── FindUserInfoRspVO.java │ │ │ │ │ └── UpdateAdminUserPasswordReqVO.java │ │ │ │ │ ├── category │ │ │ │ │ ├── DeleteCategoryReqVO.java │ │ │ │ │ ├── AddCategoryReqVO.java │ │ │ │ │ ├── FindCategoryPageListRspVO.java │ │ │ │ │ └── FindCategoryPageListReqVO.java │ │ │ │ │ └── blogsettings │ │ │ │ │ ├── FindBlogSettingsRspVO.java │ │ │ │ │ └── UpdateBlogSettingsReqVO.java │ │ │ │ ├── service │ │ │ │ ├── package-info.java │ │ │ │ ├── AdminStatisticsService.java │ │ │ │ ├── AdminFileService.java │ │ │ │ ├── AdminDashboardService.java │ │ │ │ ├── AdminUserService.java │ │ │ │ ├── AdminBlogSettingsService.java │ │ │ │ ├── AdminCommentService.java │ │ │ │ ├── AdminTagService.java │ │ │ │ ├── AdminCategoryService.java │ │ │ │ └── AdminArticleService.java │ │ │ │ ├── event │ │ │ │ ├── DeleteArticleEvent.java │ │ │ │ ├── UpdateArticleEvent.java │ │ │ │ ├── PublishArticleEvent.java │ │ │ │ ├── UpdateCommentEvent.java │ │ │ │ └── ReadArticleEvent.java │ │ │ │ ├── config │ │ │ │ ├── MinioProperties.java │ │ │ │ ├── MinioConfig.java │ │ │ │ └── TheadPoolConfig.java │ │ │ │ ├── convert │ │ │ │ ├── CommentConvert.java │ │ │ │ ├── ArticleDetailConvert.java │ │ │ │ ├── WikiConvert.java │ │ │ │ └── BlogSettingsConvert.java │ │ │ │ ├── runner │ │ │ │ ├── StatisticsTagArticleTotalRunner.java │ │ │ │ └── StatisticsCategoryArticleTotalRunner.java │ │ │ │ ├── controller │ │ │ │ └── AdminFileController.java │ │ │ │ └── schedule │ │ │ │ └── InitPVRecordScheduledTask.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── quanxiaoha │ │ │ └── weblog │ │ │ └── admin │ │ │ └── WeblogModuleAdminApplicationTests.java │ └── .gitignore ├── weblog-module-common │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── quanxiaoha │ │ │ │ └── weblog │ │ │ │ └── common │ │ │ │ ├── package-info.java │ │ │ │ ├── model │ │ │ │ ├── package-info.java │ │ │ │ ├── BasePageQuery.java │ │ │ │ └── vo │ │ │ │ │ └── SelectRspVO.java │ │ │ │ ├── domain │ │ │ │ ├── package-info.java │ │ │ │ ├── dos │ │ │ │ │ ├── UserRoleDO.java │ │ │ │ │ ├── ArticlePublishCountDO.java │ │ │ │ │ ├── ArticleTagRelDO.java │ │ │ │ │ ├── ArticleContentDO.java │ │ │ │ │ ├── ArticleCategoryRelDO.java │ │ │ │ │ ├── TagDO.java │ │ │ │ │ ├── UserDO.java │ │ │ │ │ ├── CategoryDO.java │ │ │ │ │ ├── StatisticsArticlePVDO.java │ │ │ │ │ ├── WikiDO.java │ │ │ │ │ ├── ArticleDO.java │ │ │ │ │ ├── WikiCatalogDO.java │ │ │ │ │ ├── BlogSettingsDO.java │ │ │ │ │ └── CommentDO.java │ │ │ │ └── mapper │ │ │ │ │ ├── BlogSettingsMapper.java │ │ │ │ │ ├── UserRoleMapper.java │ │ │ │ │ ├── UserMapper.java │ │ │ │ │ ├── StatisticsArticlePVMapper.java │ │ │ │ │ └── ArticleContentMapper.java │ │ │ │ ├── exception │ │ │ │ ├── BaseExceptionInterface.java │ │ │ │ └── BizException.java │ │ │ │ ├── aspect │ │ │ │ └── ApiOperationLog.java │ │ │ │ ├── enums │ │ │ │ ├── WikiCatalogLevelEnum.java │ │ │ │ ├── ArticleTypeEnum.java │ │ │ │ ├── CommentStatusEnum.java │ │ │ │ └── ResponseCodeEnum.java │ │ │ │ ├── config │ │ │ │ ├── InsertBatchMapper.java │ │ │ │ ├── InsertBatchSqlInjector.java │ │ │ │ └── MybatisPlusConfig.java │ │ │ │ ├── constant │ │ │ │ └── Constants.java │ │ │ │ ├── utils │ │ │ │ └── JsonUtil.java │ │ │ │ └── mail │ │ │ │ └── MailHelper.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── quanxiaoha │ │ │ └── weblog │ │ │ └── common │ │ │ └── WeblogModuleCommonApplicationTests.java │ └── .gitignore ├── weblog-web │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── quanxiaoha │ │ │ │ └── weblog │ │ │ │ └── web │ │ │ │ ├── service │ │ │ │ ├── BlogSettingsService.java │ │ │ │ ├── StatisticsService.java │ │ │ │ ├── SearchService.java │ │ │ │ ├── ArchiveService.java │ │ │ │ ├── TagService.java │ │ │ │ ├── CategoryService.java │ │ │ │ ├── ArticleService.java │ │ │ │ ├── WikiService.java │ │ │ │ ├── CommentService.java │ │ │ │ └── impl │ │ │ │ │ └── BlogSettingsServiceImpl.java │ │ │ │ ├── utils │ │ │ │ └── StringUtil.java │ │ │ │ ├── model │ │ │ │ └── vo │ │ │ │ │ ├── tag │ │ │ │ │ ├── FindTagListReqVO.java │ │ │ │ │ ├── FindTagListRspVO.java │ │ │ │ │ ├── FindTagArticlePageListRspVO.java │ │ │ │ │ └── FindTagArticlePageListReqVO.java │ │ │ │ │ ├── archive │ │ │ │ │ ├── FindArchiveArticlePageListReqVO.java │ │ │ │ │ ├── FindArchiveArticlePageListRspVO.java │ │ │ │ │ └── FindArchiveArticleRspVO.java │ │ │ │ │ ├── article │ │ │ │ │ ├── FindIndexArticlePageListReqVO.java │ │ │ │ │ ├── FindArticleDetailReqVO.java │ │ │ │ │ ├── FindPreNextArticleRspVO.java │ │ │ │ │ ├── FindIndexArticlePageListRspVO.java │ │ │ │ │ └── FindArticleDetailRspVO.java │ │ │ │ │ ├── category │ │ │ │ │ ├── FindCategoryListReqVO.java │ │ │ │ │ ├── FindCategoryListRspVO.java │ │ │ │ │ ├── FindCategoryArticlePageListRspVO.java │ │ │ │ │ └── FindCategoryArticlePageListReqVO.java │ │ │ │ │ ├── comment │ │ │ │ │ ├── FindCommentListReqVO.java │ │ │ │ │ ├── FindQQUserInfoReqVO.java │ │ │ │ │ ├── FindCommentListRspVO.java │ │ │ │ │ ├── FindQQUserInfoRspVO.java │ │ │ │ │ ├── FindCommentItemRspVO.java │ │ │ │ │ └── PublishCommentReqVO.java │ │ │ │ │ ├── wiki │ │ │ │ │ ├── FindWikiCatalogListReqVO.java │ │ │ │ │ ├── FindWikiArticlePreNextReqVO.java │ │ │ │ │ ├── FindWikiListRspVO.java │ │ │ │ │ ├── FindWikiArticlePreNextRspVO.java │ │ │ │ │ └── FindWikiCatalogListRspVO.java │ │ │ │ │ ├── search │ │ │ │ │ ├── SearchArticlePageListReqVO.java │ │ │ │ │ └── SearchArticlePageListRspVO.java │ │ │ │ │ ├── blogsettings │ │ │ │ │ └── FindBlogSettingsDetailRspVO.java │ │ │ │ │ └── statistics │ │ │ │ │ └── FindStatisticsInfoRspVO.java │ │ │ │ ├── event │ │ │ │ └── PublishCommentEvent.java │ │ │ │ ├── WeblogWebApplication.java │ │ │ │ ├── convert │ │ │ │ ├── CommentConvert.java │ │ │ │ └── BlogSettingsConvert.java │ │ │ │ ├── config │ │ │ │ ├── RestTemplateConfig.java │ │ │ │ └── ToolGoodConfig.java │ │ │ │ └── controller │ │ │ │ ├── StatisticsController.java │ │ │ │ ├── BlogSettingsController.java │ │ │ │ ├── SearchController.java │ │ │ │ └── ArchiveController.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── spy.properties │ │ │ ├── application-dev.yml │ │ │ └── application-prod.yml │ ├── .gitignore │ └── Dockerfile ├── weblog-module-jwt │ ├── src │ │ ├── test │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── quanxiaoha │ │ │ │ └── weblog │ │ │ │ └── jwt │ │ │ │ └── WeblogModuleJwtApplicationTests.java │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── quanxiaoha │ │ │ └── weblog │ │ │ └── jwt │ │ │ ├── model │ │ │ └── LoginRspVO.java │ │ │ ├── exception │ │ │ └── UsernameOrPasswordNullException.java │ │ │ ├── config │ │ │ └── PasswordEncoderConfig.java │ │ │ └── handler │ │ │ ├── RestAccessDeniedHandler.java │ │ │ └── RestAuthenticationEntryPoint.java │ └── .gitignore ├── .gitignore └── weblog-module-search │ └── src │ └── main │ └── java │ └── com │ └── quanxiaoha │ └── weblog │ └── search │ ├── config │ └── LuceneProperties.java │ └── index │ └── ArticleIndex.java ├── .gitignore ├── LICENSE └── README.md /pic/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/pic/home.png -------------------------------------------------------------------------------- /pic/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/pic/detail.png -------------------------------------------------------------------------------- /pic/移动端详情页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/pic/移动端详情页.png -------------------------------------------------------------------------------- /pic/移动端首页.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/pic/移动端首页.png -------------------------------------------------------------------------------- /weblog-vue3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/weblog-vue3/public/favicon.ico -------------------------------------------------------------------------------- /weblog-vue3/src/assets/no-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/weblog-vue3/src/assets/no-data.png -------------------------------------------------------------------------------- /weblog-vue3/src/assets/developer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/weblog-vue3/src/assets/developer.png -------------------------------------------------------------------------------- /weblog-vue3/src/assets/weblog-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/weblog-vue3/src/assets/weblog-logo.png -------------------------------------------------------------------------------- /weblog-vue3/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /weblog-vue3/src/assets/weblog-logo-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MusaTabitai/weblog/HEAD/weblog-vue3/src/assets/weblog-logo-mini.png -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/file.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 上传文件 4 | export function uploadFile(form) { 5 | return axios.post("/admin/file/upload", form) 6 | } 7 | 8 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/search.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 文章搜索 4 | export function getArticleSearchPageList(data) { 5 | return axios.post("/article/search", data) 6 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/statistics.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取统计信息(文章总数、分类总数、标签总数、总访问量) 4 | export function getStatisticsInfo() { 5 | return axios.post("/statistics/info") 6 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/archive.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取文章归档分页数据 4 | export function getArchivePageList(data) { 5 | return axios.post("/archive/list", data) 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/blogsettings.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取博客设置详情 4 | export function getBlogSettingsDetail() { 5 | return axios.post("/blog/settings/detail") 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-08-16 9:28 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.admin; -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-08-10 9:20 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.common; -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-09-15 14:07 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.admin.model; -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-09-15 14:02 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.admin.service; -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-09-19 8:53 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.common.model; -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: 木萨·塔布提 3 | * @url: blog.arnasoft.site 4 | * @date: 2023-08-22 16:57 5 | * @description: TODO 6 | **/ 7 | package com.quanxiaoha.weblog.common.domain; -------------------------------------------------------------------------------- /weblog-vue3/src/stores/index.js: -------------------------------------------------------------------------------- 1 | // 引入全局状态管理 Pinia 2 | import { createPinia } from 'pinia' 3 | import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' 4 | 5 | const pinia = createPinia() 6 | // 持久化插件 7 | pinia.use(piniaPluginPersistedstate) 8 | 9 | // 暴露出去 10 | export default pinia -------------------------------------------------------------------------------- /weblog-vue3/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/tag.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取标签列表 4 | export function getTagList(data) { 5 | return axios.post("/tag/list", data) 6 | } 7 | 8 | // 获取标签下文章列表 9 | export function getTagArticlePageList(data) { 10 | return axios.post("/tag/article/list", data) 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /weblog-vue3/src/stores/comment.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | 4 | export const useCommentStore = defineStore('comment', () => { 5 | // 评论用户信息 6 | const userInfo = ref({}) 7 | 8 | return { userInfo } 9 | }, 10 | { 11 | // 开启持久化 12 | persist: true, 13 | } 14 | ) -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/article.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取文章列表 4 | export function getArticlePageList(data) { 5 | return axios.post("/article/list", data) 6 | } 7 | 8 | // 获取文章详情 9 | export function getArticleDetail(articleId) { 10 | return axios.post("/article/detail", {articleId}) 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/blogsettings.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取博客设置详情 4 | export function getBlogSettingsDetail() { 5 | return axios.post("/admin/blog/settings/detail") 6 | } 7 | 8 | // 更新博客设置 9 | export function updateBlogSettings(data) { 10 | return axios.post("/admin/blog/settings/update", data) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/category.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取分类列表 4 | export function getCategoryList(data) { 5 | return axios.post("/category/list", data) 6 | } 7 | 8 | // 获取分类-文章列表 9 | export function getCategoryArticlePageList(data) { 10 | return axios.post("/category/article/list", data) 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /weblog-vue3/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{vue,js,ts,jsx,tsx}", 6 | "./node_modules/flowbite/**/*.js", 7 | ], 8 | theme: { 9 | extend: {}, 10 | }, 11 | plugins: [ 12 | require('flowbite/plugin') 13 | ] 14 | } -------------------------------------------------------------------------------- /weblog-vue3/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /weblog-vue3/src/layouts/admin/components/AdminFooter.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | replay_pid* 25 | -------------------------------------------------------------------------------- /weblog-vue3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/wiki.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取知识库列表 4 | export function getWikiList() { 5 | return axios.post("/wiki/list") 6 | } 7 | 8 | // 获取知识库文章上下页 9 | export function getWikiArticlePreNext(data) { 10 | return axios.post("/wiki/article/preNext", data) 11 | } 12 | 13 | // 获取知识库目录 14 | export function getWikiCatalogs(id) { 15 | return axios.post("/wiki/catalog/list", {id}) 16 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BaseExceptionInterface.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.exception; 2 | 3 | /** 4 | * @author: 木萨·塔布提 5 | * @url: blog.arnasoft.site 6 | * @date: 2023-08-15 9:54 7 | * @description: 通用异常接口 8 | **/ 9 | public interface BaseExceptionInterface { 10 | String getErrorCode(); 11 | 12 | String getErrorMessage(); 13 | } 14 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/user.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 登录接口 4 | export function login(username, password) { 5 | return axios.post("/login", {username, password}) 6 | } 7 | 8 | // 获取登录用户信息 9 | export function getUserInfo() { 10 | return axios.post("/admin/user/info") 11 | } 12 | 13 | // 修改用户密码 14 | export function updateAdminPassword(data) { 15 | return axios.post("/admin/password/update", data) 16 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/comment.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取评论分页数据 4 | export function getCommentPageList(data) { 5 | return axios.post("/admin/comment/list", data) 6 | } 7 | 8 | // 删除评论 9 | export function deleteComment(id) { 10 | return axios.post("/admin/comment/delete", {id}) 11 | } 12 | 13 | // 审核评论 14 | export function examineComment(data) { 15 | return axios.post("/admin/comment/examine", data) 16 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/frontend/comment.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取 QQ 用户信息 4 | export function getUserInfoByQQ(qq) { 5 | return axios.post("/comment/qq/userInfo", { qq }) 6 | } 7 | 8 | // 发布评论 9 | export function publishComment(data) { 10 | return axios.post("/comment/publish", data) 11 | } 12 | 13 | // 获取所有评论 14 | export function getComments(routerUrl) { 15 | return axios.post("/comment/list", { routerUrl }) 16 | } -------------------------------------------------------------------------------- /weblog-vue3/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/aspect/ApiOperationLog.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.aspect; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Retention(RetentionPolicy.RUNTIME) 6 | @Target({ElementType.METHOD}) 7 | @Documented 8 | public @interface ApiOperationLog { 9 | /** 10 | * API 功能描述 11 | * 12 | * @return 13 | */ 14 | String description() default ""; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /weblog-vue3/src/stores/menu.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | 4 | export const useMenuStore = defineStore('menu', () => { 5 | // 左边栏菜单默认宽度 6 | const menuWidth = ref("250px") 7 | 8 | // 展开或伸缩左边栏菜单 9 | function handleMenuWidth() { 10 | menuWidth.value = menuWidth.value == '250px' ? '64px' : '250px' 11 | } 12 | 13 | return { menuWidth, handleMenuWidth } 14 | }, 15 | { 16 | // 开启持久化 17 | persist: true, 18 | } 19 | ) -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/BlogSettingsService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | 5 | /** 6 | * @author: 木萨·塔布提 7 | * @url: blog.arnasoft.site 8 | * @date: 2023-09-15 14:03 9 | * @description: 博客设置 10 | **/ 11 | public interface BlogSettingsService { 12 | /** 13 | * 获取博客设置信息 14 | * @return 15 | */ 16 | Response findDetail(); 17 | } 18 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/StatisticsService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | 5 | /** 6 | * @Author: 木萨·塔布提 7 | * @Date: 2024-03-27 16:37 8 | * @Version: v1.0.0 9 | * @Description: TODO 10 | **/ 11 | public interface StatisticsService { 12 | /** 13 | * 获取文章总数、分类总数、标签总数、总访问量统计信息 14 | * @return 15 | */ 16 | Response findInfo(); 17 | } 18 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/utils/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.utils; 2 | 3 | /** 4 | * @Author: 木萨·塔布提 5 | * @Date: 2024/4/3 19:53 6 | * @Version: v1.0.0 7 | * @Description: TODO 8 | **/ 9 | public class StringUtil { 10 | 11 | /** 12 | * 判断字符串是否是纯数字 13 | * @param str 14 | * @return 15 | */ 16 | public static boolean isPureNumber(String str) { 17 | return str.matches("\\d+"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminStatisticsService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | /** 4 | * @Author: 木萨·塔布提 5 | * @Date: 2024/3/28 20:32 6 | * @Version: v1.0.0 7 | * @Description: TODO 8 | **/ 9 | public interface AdminStatisticsService { 10 | 11 | /** 12 | * 统计各分类下文章总数 13 | */ 14 | void statisticsCategoryArticleTotal(); 15 | 16 | /** 17 | * 统计各标签下文章总数 18 | */ 19 | void statisticsTagArticleTotal(); 20 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/BasePageQuery.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author: 木萨·塔布提 7 | * @url: blog.arnasoft.site 8 | * @date: 2023-09-19 8:54 9 | * @description: TODO 10 | **/ 11 | @Data 12 | public class BasePageQuery { 13 | /** 14 | * 当前页码, 默认第一页 15 | */ 16 | private Long current = 1L; 17 | /** 18 | * 每页展示的数据数量,默认每页展示 10 条数据 19 | */ 20 | private Long size = 10L; 21 | } 22 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/WikiCatalogLevelEnum.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-04-01 12:23 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | @AllArgsConstructor 14 | public enum WikiCatalogLevelEnum { 15 | 16 | // 一级目录 17 | ONE(1), 18 | // 二级目录 19 | TWO(2); 20 | 21 | private Integer value; 22 | 23 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ArticleTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-04-01 12:23 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | @AllArgsConstructor 14 | public enum ArticleTypeEnum { 15 | 16 | NORMAL(1, "普通"), 17 | WIKI(2, "收录于知识库"); 18 | 19 | private Integer value; 20 | private String description; 21 | 22 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/dashboard.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取仪表盘基础信息(文章数、分类数、标签数、总浏览量) 4 | export function getBaseStatisticsInfo(data) { 5 | return axios.post("/admin/dashboard/statistics", data) 6 | } 7 | 8 | // 获取仪表盘文章发布热点统计信息 9 | export function getPublishArticleStatisticsInfo(data) { 10 | return axios.post("/admin/dashboard/publishArticle/statistics", data) 11 | } 12 | 13 | // 获取仪表盘最近一周 PV 访问量信息 14 | export function getArticlePVStatisticsInfo(data) { 15 | return axios.post("/admin/dashboard/pv/statistics", data) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/test/java/com/quanxiaoha/weblog/jwt/WeblogModuleJwtApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = WeblogModuleJwtApplicationTests.Application.class) 7 | class WeblogModuleJwtApplicationTests { 8 | 9 | public static class Application { 10 | } 11 | 12 | @Test 13 | void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /weblog-springboot/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/category.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取分类分页数据 4 | export function getCategoryPageList(data) { 5 | return axios.post("/admin/category/list", data) 6 | } 7 | 8 | // 添加分类 9 | export function addCategory(data) { 10 | return axios.post("/admin/category/add", data) 11 | } 12 | 13 | // 删除分类 14 | export function deleteCategory(id) { 15 | return axios.post("/admin/category/delete", {id}) 16 | } 17 | 18 | // 获取分类 select 数据 19 | export function getCategorySelectList() { 20 | return axios.post("/admin/category/select/list") 21 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /weblog-vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/model/LoginRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-08-24 9:43 12 | * @description: 用户登录 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class LoginRspVO { 19 | 20 | /** 21 | * Token 值 22 | */ 23 | private String token; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.config; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-06-13 22:50 12 | * @description: 批量插入 13 | **/ 14 | public interface InsertBatchMapper extends BaseMapper { 15 | 16 | // 批量插入 17 | int insertBatchSomeColumn(@Param("list") List batchList); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/tag/FindTagListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.tag; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/3/28 23:18 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindTagListReqVO { 19 | 20 | /** 21 | * 展示数量 22 | */ 23 | private Long size; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/archive/FindArchiveArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.archive; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-09-15 14:07 12 | * @description: 文章归档 13 | **/ 14 | @Data 15 | @Builder 16 | @ApiModel(value = "文章归档分页 VO") 17 | public class FindArchiveArticlePageListReqVO extends BasePageQuery { 18 | } 19 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/article/FindIndexArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.article; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-09-15 14:07 12 | * @description: 首页-文章分页 13 | **/ 14 | @Data 15 | @Builder 16 | @ApiModel(value = "首页查询文章分页 VO") 17 | public class FindIndexArticlePageListReqVO extends BasePageQuery { 18 | } 19 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM 指定使用哪个镜像作为基准 2 | FROM openjdk:8-jdk-alpine 3 | 4 | # 创建目录, 并设置该目录为工作目录 5 | RUN mkdir -p /weblog 6 | WORKDIR /weblog 7 | 8 | # 复制文件到镜像中 9 | COPY weblog-web-0.0.1-SNAPSHOT.jar app.jar 10 | 11 | # 设置时区 12 | ENV TZ=Asia/Shanghai 13 | 14 | # 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖 15 | ENV JAVA_OPTS="-Xms300m -Xmx300m -Djava.security.egd=file:/dev/./urandom" 16 | 17 | # 应用参数,可通过 docker run -e "ARGS=" 来设置,如 -e "ARGS=--spring.profiles.active=prod" 18 | ENV ARGS="" 19 | 20 | # 暴露 8080 端口 21 | EXPOSE 8080 22 | 23 | # 启动后端服务 24 | CMD java ${JAVA_OPTS} -jar app.jar $ARGS -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/category/FindCategoryListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.category; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/3/28 23:18 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindCategoryListReqVO { 19 | 20 | /** 21 | * 展示数量 22 | */ 23 | private Long size; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/tag/FindTagListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.tag; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-04-19 16:06 12 | * @description: 标签 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindTagListRspVO { 19 | private Long id; 20 | private String name; 21 | private Integer articlesTotal; 22 | } 23 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-search/src/main/java/com/quanxiaoha/weblog/search/config/LuceneProperties.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.search.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * @Author: 木萨·塔布提 9 | * @Date: 2024-03-27 17:56 10 | * @Version: v1.0.0 11 | * @Description: TODO 12 | **/ 13 | @ConfigurationProperties(prefix = "lucene") 14 | @Component 15 | @Data 16 | public class LuceneProperties { 17 | /** 18 | * 索引存放的文件夹 19 | */ 20 | private String indexDir; 21 | } -------------------------------------------------------------------------------- /weblog-vue3/src/stores/blogsettings.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import { getBlogSettingsDetail } from '@/api/frontend/blogsettings' 4 | 5 | export const useBlogSettingsStore = defineStore('blogsettings', () => { 6 | // 博客设置信息 7 | const blogSettings = ref({}) 8 | 9 | // 获取博客设置信息 10 | function getBlogSettings() { 11 | // 调用后台获取博客设置信息接口 12 | console.log('获取博客设置信息') 13 | getBlogSettingsDetail().then(res => { 14 | if (res.success) { 15 | blogSettings.value = res.data 16 | } 17 | }) 18 | } 19 | 20 | 21 | return { blogSettings, getBlogSettings } 22 | }) -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/category/FindCategoryListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.category; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-04-19 16:06 12 | * @description: 分类 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindCategoryListRspVO { 19 | private Long id; 20 | private String name; 21 | private Integer articlesTotal; 22 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/tag.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取标签分页数据 4 | export function getTagPageList(data) { 5 | return axios.post("/admin/tag/list", data) 6 | } 7 | 8 | // 添加标签 9 | export function addTag(data) { 10 | return axios.post("/admin/tag/add", data) 11 | } 12 | 13 | // 删除标签 14 | export function deleteTag(id) { 15 | return axios.post("/admin/tag/delete", {id}) 16 | } 17 | 18 | // 根据标签名模糊查询 19 | export function searchTags(key) { 20 | return axios.post("/admin/tag/search", {key}) 21 | } 22 | 23 | // 获取标签 select 列表数据 24 | export function getTagSelectList() { 25 | return axios.post("/admin/tag/select/list") 26 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/SearchService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.search.SearchArticlePageListReqVO; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-03-27 18:12 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | public interface SearchService { 13 | 14 | /** 15 | * 关键词分页搜索 16 | * @param searchArticlePageListReqVO 17 | * @return 18 | */ 19 | Response searchArticlePageList(SearchArticlePageListReqVO searchArticlePageListReqVO); 20 | } 21 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.constant; 2 | 3 | import java.time.format.DateTimeFormatter; 4 | 5 | /** 6 | * @author: 木萨·塔布提 7 | * @url: blog.arnasoft.site 8 | * @date: 2023/11/13 11:22 9 | * @description: 全局静态变量 10 | **/ 11 | public interface Constants { 12 | /** 13 | * 月-日 格式 14 | */ 15 | DateTimeFormatter MONTH_DAY_FORMATTER = DateTimeFormatter.ofPattern("MM-dd"); 16 | 17 | /** 18 | * 年-月-日 小时-分钟-秒 19 | */ 20 | DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 21 | } 22 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserRoleDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | 9 | import java.util.Date; 10 | 11 | @Data 12 | @Builder 13 | @TableName("t_user_role") 14 | public class UserRoleDO { 15 | @TableId(type = IdType.AUTO) 16 | private Long id; 17 | private String username; 18 | private String role; 19 | private Date createTime; 20 | } 21 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/CommentStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024/4/3 20:43 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | 13 | @Getter 14 | @AllArgsConstructor 15 | public enum CommentStatusEnum { 16 | 17 | // ----------- 通用异常状态码 ----------- 18 | WAIT_EXAMINE(1, "等待审核"), 19 | NORMAL(2, "正常"), 20 | EXAMINE_FAILED(3, "审核不通过"), 21 | ; 22 | 23 | private Integer code; 24 | private String description; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/event/DeleteArticleEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-03-27 19:17 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | public class DeleteArticleEvent extends ApplicationEvent { 14 | 15 | /** 16 | * 文章 ID 17 | */ 18 | private Long articleId; 19 | 20 | public DeleteArticleEvent(Object source, Long articleId) { 21 | super(source); 22 | this.articleId = articleId; 23 | } 24 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/event/UpdateArticleEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-03-27 19:19 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | public class UpdateArticleEvent extends ApplicationEvent { 14 | 15 | /** 16 | * 文章 ID 17 | */ 18 | private Long articleId; 19 | 20 | public UpdateArticleEvent(Object source, Long articleId) { 21 | super(source); 22 | this.articleId = articleId; 23 | } 24 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/file/UploadFileRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.file; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 上传文件 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class UploadFileRspVO { 21 | 22 | /** 23 | * 文件的访问链接 24 | */ 25 | private String url; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminFileService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-09-15 14:03 11 | * @description: TODO 12 | **/ 13 | public interface AdminFileService { 14 | /** 15 | * 上传文件 16 | * @param file 17 | * @return 18 | */ 19 | Response uploadFile(MultipartFile file); 20 | } 21 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/event/PublishCommentEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024/4/3 21:41 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | 13 | @Getter 14 | public class PublishCommentEvent extends ApplicationEvent { 15 | 16 | /** 17 | * 评论 ID 18 | */ 19 | private Long commentId; 20 | 21 | public PublishCommentEvent(Object source, Long commentId) { 22 | super(source); 23 | this.commentId = commentId; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/FindCommentListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/4/3 21:20 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindCommentListReqVO { 21 | 22 | @NotBlank(message = "路由地址不能为空") 23 | private String routerUrl; 24 | 25 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/FindQQUserInfoReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/4/3 19:50 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindQQUserInfoReqVO { 21 | 22 | @NotBlank(message = "QQ 号不能为空") 23 | private String qq; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/event/PublishArticleEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024-03-27 19:10 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | public class PublishArticleEvent extends ApplicationEvent { 14 | 15 | /** 16 | * 文章 ID 17 | */ 18 | private Long articleId; 19 | 20 | public PublishArticleEvent(Object source, Long articleId) { 21 | super(source); 22 | this.articleId = articleId; 23 | } 24 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/wiki/FindWikiCatalogListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024-04-01 18:32 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiCatalogListReqVO { 21 | 22 | @NotNull(message = "知识库 ID 不能为空") 23 | private Long id; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/event/UpdateCommentEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @Author: 木萨·塔布提 8 | * @Date: 2024/4/6 23:23 9 | * @Version: v1.0.0 10 | * @Description: TODO 11 | **/ 12 | @Getter 13 | public class UpdateCommentEvent extends ApplicationEvent { 14 | 15 | /** 16 | * 评论 ID 17 | */ 18 | private Long commentId; 19 | 20 | public UpdateCommentEvent(Object source, Long commentId) { 21 | super(source); 22 | this.commentId = commentId; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/ArchiveService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.archive.FindArchiveArticlePageListReqVO; 5 | 6 | /** 7 | * @author: 木萨·塔布提 8 | * @url: blog.arnasoft.site 9 | * @date: 2023-09-15 14:03 10 | * @description: 归档文章 11 | **/ 12 | public interface ArchiveService { 13 | /** 14 | * 获取文章归档分页数据 15 | * @param findArchiveArticlePageListReqVO 16 | * @return 17 | */ 18 | Response findArchivePageList(FindArchiveArticlePageListReqVO findArchiveArticlePageListReqVO); 19 | } 20 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/event/ReadArticleEvent.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.event; 2 | 3 | import lombok.Getter; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | /** 7 | * @author: 木萨·塔布提 8 | * @url: blog.arnasoft.site 9 | * @date: 2023/11/9 10:05 10 | * @description: 文章被阅读事件 11 | **/ 12 | 13 | @Getter 14 | public class ReadArticleEvent extends ApplicationEvent { 15 | 16 | /** 17 | * 文章 ID 18 | */ 19 | private Long articleId; 20 | 21 | public ReadArticleEvent(Object source, Long articleId) { 22 | super(source); 23 | this.articleId = articleId; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/exception/UsernameOrPasswordNullException.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * @author: 木萨·塔布提 7 | * @url: blog.arnasoft.site 8 | * @date: 2023-08-24 17:11 9 | * @description: 用户名或者密码为空异常 10 | **/ 11 | public class UsernameOrPasswordNullException extends AuthenticationException { 12 | public UsernameOrPasswordNullException(String msg, Throwable cause) { 13 | super(msg, cause); 14 | } 15 | 16 | public UsernameOrPasswordNullException(String msg) { 17 | super(msg); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioProperties.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-05-11 8:49 11 | * @description: TODO 12 | **/ 13 | @ConfigurationProperties(prefix = "minio") 14 | @Component 15 | @Data 16 | public class MinioProperties { 17 | private String endpoint; 18 | private String accessKey; 19 | private String secretKey; 20 | private String bucketName; 21 | } 22 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/article/FindArticleDetailReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @author: 木萨·塔布提 11 | * @url: blog.arnasoft.site 12 | * @date: 2023-09-15 14:07 13 | * @description: 文章详情 14 | **/ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Builder 19 | @ApiModel(value = "查询文章详情 VO") 20 | public class FindArticleDetailReqVO { 21 | /** 22 | * 文章 ID 23 | */ 24 | private Long articleId; 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/model/vo/SelectRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.model.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023/9/20 16:02 12 | * @description: TODO 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class SelectRspVO { 19 | /** 20 | * Select 下拉列表的展示文字 21 | */ 22 | private String label; 23 | 24 | /** 25 | * Select 下拉列表的 value 值,如 ID 等 26 | */ 27 | private Object value; 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | # 默认激活 dev 环境 4 | active: dev 5 | mail: 6 | host: smtp.qq.com # 邮件服务器的地址,小哈这里使用的 QQ 邮件 7 | username: # 发送邮件的邮箱账号 8 | password: # 授权码,或发送邮件的邮箱账号的密码 9 | default-encoding: utf-8 # 邮件内容的字符编码 10 | protocol: smtps # 邮件传输协议:smtps 表示SMTP over SSL,是一种加密的SMTP连接方式,用于确保邮件传输的安全性。 11 | port: 465 # 邮件服务器的端口号:465 是 SMTPS(SMTP over SSL)的常用端口号,用于加密的邮件传输。 12 | 13 | jwt: 14 | # 签发人 15 | issuer: 16 | # 秘钥 17 | secret: 18 | # token 过期时间(单位:分钟) 24*60 19 | tokenExpireTime: 1440 20 | # token 请求头中的 key 值 21 | tokenHeaderKey: Authorization 22 | # token 请求头中的 value 值前缀 23 | tokenPrefix: Bearer -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/article/FindPreNextArticleRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.article; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-09-15 14:07 12 | * @description: 文章上下页 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindPreNextArticleRspVO { 19 | /** 20 | * 文章 ID 21 | */ 22 | private Long articleId; 23 | 24 | /** 25 | * 文章标题 26 | */ 27 | private String articleTitle; 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/DeleteWikiReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024-04-01 12:22 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "删除知识库 VO") 22 | public class DeleteWikiReqVO { 23 | 24 | @NotNull(message = "知识库 ID 不能为空") 25 | private Long id; 26 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-search/src/main/java/com/quanxiaoha/weblog/search/index/ArticleIndex.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.search.index; 2 | 3 | /** 4 | * @Author: 木萨·塔布提 5 | * @Date: 2024-03-27 17:57 6 | * @Version: v1.0.0 7 | * @Description: TODO 8 | **/ 9 | public interface ArticleIndex { 10 | /** 11 | * 索引名称 12 | */ 13 | String NAME = "article"; 14 | 15 | // --------------------- 文档字段 --------------------- 16 | String COLUMN_ID = "id"; 17 | 18 | String COLUMN_TITLE = "title"; 19 | 20 | String COLUMN_COVER = "cover"; 21 | 22 | String COLUMN_SUMMARY = "summary"; 23 | 24 | String COLUMN_CONTENT = "content"; 25 | 26 | String COLUMN_CREATE_TIME = "createTime"; 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/WeblogWebApplication.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | @SpringBootApplication 9 | @ComponentScan({"com.quanxiaoha.weblog.*"}) // 多模块项目中,必需手动指定扫描 com.quanxiaoha.weblog 包下面的所有类 10 | @EnableScheduling // 启用定时任务 11 | public class WeblogWebApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(WeblogWebApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/comment/DeleteCommentReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.comment; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024/4/6 23:15 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "删除评论 VO") 22 | public class DeleteCommentReqVO { 23 | 24 | @NotNull(message = "评论 ID 不能为空") 25 | private Long id; 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/DeleteTagReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.tag; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 删除标签 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "删除标签 VO") 22 | public class DeleteTagReqVO { 23 | 24 | @NotNull(message = "标签 ID 不能为空") 25 | private Long id; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticlePublishCountDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDate; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-08-22 17:01 14 | * @description: 以日为维度统计文章发布数量 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class ArticlePublishCountDO { 21 | /** 22 | * 日期 23 | */ 24 | private LocalDate date; 25 | 26 | /** 27 | * 文章发布数量 28 | */ 29 | private Long count; 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/FindCommentListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/4/3 21:20 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindCommentListRspVO { 21 | 22 | /** 23 | * 总评论数 24 | */ 25 | private Integer total; 26 | 27 | /** 28 | * 评论集合 29 | */ 30 | private List comments; 31 | 32 | } -------------------------------------------------------------------------------- /weblog-vue3/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | font-family: -apple-system-font,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif; 7 | color: #4c4e4d; 8 | font-size: 16px; 9 | background: #f4f4f4; 10 | line-height: 1.6; 11 | } 12 | 13 | [type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { 14 | box-shadow: 0 0 0 1px transparent inset!important; 15 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/DeleteArticleReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 删除文章 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "删除文章 VO") 22 | public class DeleteArticleReqVO { 23 | 24 | @NotNull(message = "文章 ID 不能为空") 25 | private Long id; 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/dashboard/FindDashboardPVStatisticsInfoRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.dashboard; 2 | 3 | 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.util.List; 11 | 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Builder 16 | @ApiModel(value = "查询仪表盘文章 PV 访问量信息入参 VO") 17 | public class FindDashboardPVStatisticsInfoRspVO { 18 | /** 19 | * 日期集合 20 | */ 21 | private List pvDates; 22 | 23 | /** 24 | * PV 浏览量集合 25 | */ 26 | private List pvCounts; 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/SearchTagsReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.tag; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 标签模糊查询 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "标签模糊查询 VO") 22 | public class SearchTagsReqVO { 23 | 24 | @NotBlank(message = "标签查询关键词不能为空") 25 | private String key; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/wiki/FindWikiArticlePreNextReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024-04-01 18:42 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiArticlePreNextReqVO { 21 | 22 | @NotNull(message = "知识库 ID 不能为空") 23 | private Long id; 24 | 25 | @NotNull(message = "文章 ID 不能为空") 26 | private Long articleId; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/tag/FindTagArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.tag; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDate; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 标签下文章列表 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindTagArticlePageListRspVO { 21 | private Long id; 22 | private String cover; 23 | private String title; 24 | /** 25 | * 发布日期 26 | */ 27 | private LocalDate createDate; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-vue3/README.md: -------------------------------------------------------------------------------- 1 | # 程序猿小萨博客 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | ```sh 16 | npm install 17 | ``` 18 | 19 | ### Compile and Hot-Reload for Development 20 | 21 | ```sh 22 | npm run dev 23 | ``` 24 | 25 | ### Compile and Minify for Production 26 | 27 | ```sh 28 | npm run build 29 | ``` 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/BlogSettingsMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; 7 | import com.quanxiaoha.weblog.common.domain.dos.UserDO; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-08-22 17:06 15 | * @description: TODO 16 | **/ 17 | public interface BlogSettingsMapper extends BaseMapper { 18 | } 19 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/exception/BizException.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.exception; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author: 木萨·塔布提 8 | * @url: blog.arnasoft.site 9 | * @date: 2023-08-15 9:52 10 | * @description: 业务异常 11 | **/ 12 | @Getter 13 | @Setter 14 | public class BizException extends RuntimeException { 15 | // 异常码 16 | private String errorCode; 17 | // 错误信息 18 | private String errorMessage; 19 | 20 | public BizException(BaseExceptionInterface baseExceptionInterface) { 21 | this.errorCode = baseExceptionInterface.getErrorCode(); 22 | this.errorMessage = baseExceptionInterface.getErrorMessage(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/FindUserInfoRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.user; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * @author: 木萨·塔布提 14 | * @url: blog.arnasoft.site 15 | * @date: 2023-09-15 14:07 16 | * @description: 查询用户信息 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | public class FindUserInfoRspVO { 23 | /** 24 | * 用户名 25 | */ 26 | private String username; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/archive/FindArchiveArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.archive; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.YearMonth; 9 | import java.util.List; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 文章归档 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindArchiveArticlePageListRspVO { 22 | /** 23 | * 归档的月份 24 | */ 25 | private YearMonth month; 26 | 27 | private List articles; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/FindQQUserInfoRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/3 19:52 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Builder 19 | public class FindQQUserInfoRspVO { 20 | 21 | /** 22 | * 头像 23 | */ 24 | private String avatar; 25 | 26 | /** 27 | * 昵称 28 | */ 29 | private String nickname; 30 | 31 | /** 32 | * 邮箱 33 | */ 34 | private String mail; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminDashboardService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | 5 | /** 6 | * @author: 木萨·塔布提 7 | * @url: blog.arnasoft.site 8 | * @date: 2023-09-15 14:03 9 | * @description: 仪表盘 10 | **/ 11 | public interface AdminDashboardService { 12 | 13 | /** 14 | * 获取仪表盘基础统计信息 15 | * @return 16 | */ 17 | Response findDashboardStatistics(); 18 | 19 | /** 20 | * 获取文章发布热点统计信息 21 | * @return 22 | */ 23 | Response findDashboardPublishArticleStatistics(); 24 | 25 | /** 26 | * 获取文章最近一周 PV 访问量统计信息 27 | * @return 28 | */ 29 | Response findDashboardPVStatistics(); 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminUserService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | 6 | /** 7 | * @author: 木萨·塔布提 8 | * @url: blog.arnasoft.site 9 | * @date: 2023-09-15 14:03 10 | * @description: TODO 11 | **/ 12 | public interface AdminUserService { 13 | /** 14 | * 修改密码 15 | * @param updateAdminUserPasswordReqVO 16 | * @return 17 | */ 18 | Response updatePassword(UpdateAdminUserPasswordReqVO updateAdminUserPasswordReqVO); 19 | 20 | /** 21 | * 获取当前登录用户信息 22 | * @return 23 | */ 24 | Response findUserInfo(); 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/category/FindCategoryArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.category; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDate; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 分类文章 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindCategoryArticlePageListRspVO { 21 | private Long id; 22 | private String cover; 23 | private String title; 24 | /** 25 | * 发布日期 26 | */ 27 | private LocalDate createDate; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-vue3/src/layouts/frontend/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /weblog-vue3/src/stores/user.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { ref } from 'vue' 3 | import { getUserInfo } from '@/api/admin/user' 4 | import { removeToken } from '@/composables/cookie' 5 | 6 | export const useUserStore = defineStore('user', () => { 7 | // 用户信息 8 | const userInfo = ref({}) 9 | 10 | // 设置用户信息 11 | function setUserInfo() { 12 | // 调用后头获取用户信息接口 13 | getUserInfo().then(res => { 14 | if (res.success == true) { 15 | userInfo.value = res.data 16 | } 17 | }) 18 | } 19 | 20 | // 退出登录 21 | function logout() { 22 | // 删除 cookie 中的 token 令牌 23 | removeToken() 24 | // 删除登录用户信息 25 | userInfo.value = {} 26 | } 27 | 28 | return { userInfo, setUserInfo, logout } 29 | }, 30 | { 31 | // 开启持久化 32 | persist: true, 33 | } 34 | ) -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/FindWikiCatalogListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024-04-01 13:37 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "查询知识库目录数据入参 VO") 22 | public class FindWikiCatalogListReqVO { 23 | 24 | /** 25 | * 知识库 ID 26 | */ 27 | @NotNull(message = "知识库 ID 不能为空") 28 | private Long id; 29 | 30 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/tag/FindTagArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.tag; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 标签下文章列表 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindTagArticlePageListReqVO extends BasePageQuery { 22 | 23 | /** 24 | * 标签 ID 25 | */ 26 | @NotNull(message = "标签 ID 不能为空") 27 | private Long id; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/FindArticleDetailReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 文章详情 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "查询文章详情入参 VO") 22 | public class FindArticleDetailReqVO { 23 | 24 | /** 25 | * 文章 ID 26 | */ 27 | @NotNull(message = "文章 ID 不能为空") 28 | private Long id; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/wiki/FindWikiListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024-04-01 18:22 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindWikiListRspVO { 19 | private Long id; 20 | private String cover; 21 | private String title; 22 | private String summary; 23 | 24 | /** 25 | * 是否置顶 26 | */ 27 | private Boolean isTop; 28 | 29 | /** 30 | * 第一篇文章 ID 31 | */ 32 | private Long firstArticleId; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/wiki/FindWikiArticlePreNextRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.wiki; 2 | 3 | import com.quanxiaoha.weblog.web.model.vo.article.FindPreNextArticleRspVO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * @Author: 木萨·塔布提 11 | * @Date: 2024-04-01 18:43 12 | * @Version: v1.0.0 13 | * @Description: TODO 14 | **/ 15 | 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiArticlePreNextRspVO { 21 | /** 22 | * 上一篇文章 23 | */ 24 | private FindPreNextArticleRspVO preArticle; 25 | /** 26 | * 下一篇文章 27 | */ 28 | private FindPreNextArticleRspVO nextArticle; 29 | 30 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/article.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取文章分页数据 4 | export function getArticlePageList(data) { 5 | return axios.post("/admin/article/list", data) 6 | } 7 | 8 | // 删除文章 9 | export function deleteArticle(id) { 10 | return axios.post("/admin/article/delete", {id}) 11 | } 12 | 13 | // 发布文章 14 | export function publishArticle(data) { 15 | return axios.post("/admin/article/publish", data) 16 | } 17 | 18 | // 获取文章详情 19 | export function getArticleDetail(id) { 20 | return axios.post("/admin/article/detail", {id}) 21 | } 22 | 23 | // 更新文章 24 | export function updateArticle(data) { 25 | return axios.post("/admin/article/update", data) 26 | } 27 | 28 | // 更新文章置顶状态 29 | export function updateArticleIsTop(data) { 30 | return axios.post("/admin/article/isTop/update", data) 31 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/UpdateWikiIsTopReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024-04-01 13:12 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "更新知识库置顶状态 VO") 22 | public class UpdateWikiIsTopReqVO { 23 | 24 | @NotNull(message = "知识库 ID 不能为空") 25 | private Long id; 26 | 27 | @NotNull(message = "知识库置顶状态不能为空") 28 | private Boolean isTop; 29 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/category/FindCategoryArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.category; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 分类文章 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindCategoryArticlePageListReqVO extends BasePageQuery { 22 | 23 | /** 24 | * 分类 ID 25 | */ 26 | @NotNull(message = "分类 ID 不能为空") 27 | private Long id; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/UpdateArticleIsTopReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024-03-31 17:09 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "更新文章置顶状态 VO") 22 | public class UpdateArticleIsTopReqVO { 23 | 24 | @NotNull(message = "文章 ID 不能为空") 25 | private Long id; 26 | 27 | @NotNull(message = "文章置顶状态不能为空") 28 | private Boolean isTop; 29 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/convert/CommentConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.convert; 2 | 3 | import com.quanxiaoha.weblog.common.domain.dos.CommentDO; 4 | import com.quanxiaoha.weblog.web.model.vo.comment.FindCommentItemRspVO; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/3 21:23 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Mapper 15 | public interface CommentConvert { 16 | /** 17 | * 初始化 convert 实例 18 | */ 19 | CommentConvert INSTANCE = Mappers.getMapper(CommentConvert.class); 20 | 21 | /** 22 | * CommentDO -> FindCommentItemRspVO 23 | * @param bean 24 | * @return 25 | */ 26 | FindCommentItemRspVO convertDO2VO(CommentDO bean); 27 | 28 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/CommentConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.convert; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.comment.FindCommentPageListRspVO; 4 | import com.quanxiaoha.weblog.common.domain.dos.CommentDO; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/6 22:35 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | 15 | @Mapper 16 | public interface CommentConvert { 17 | /** 18 | * 初始化 convert 实例 19 | */ 20 | CommentConvert INSTANCE = Mappers.getMapper(CommentConvert.class); 21 | 22 | /** 23 | * 将 DO 转化为 VO 24 | * @param bean 25 | * @return 26 | */ 27 | FindCommentPageListRspVO convertDO2VO(CommentDO bean); 28 | 29 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/UpdateWikiIsPublishReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024-04-01 13:17 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "更新知识库发布状态 VO") 22 | public class UpdateWikiIsPublishReqVO { 23 | 24 | @NotNull(message = "知识库 ID 不能为空") 25 | private Long id; 26 | 27 | @NotNull(message = "知识库发布状态不能为空") 28 | private Boolean isPublish; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/TagService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.tag.FindTagArticlePageListReqVO; 5 | import com.quanxiaoha.weblog.web.model.vo.tag.FindTagListReqVO; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-09-15 14:03 11 | * @description: 分类 12 | **/ 13 | public interface TagService { 14 | /** 15 | * 获取标签列表 16 | * @return 17 | */ 18 | Response findTagList(FindTagListReqVO findTagListReqVO); 19 | 20 | /** 21 | * 获取标签下文章分页列表 22 | * @param findTagArticlePageListReqVO 23 | * @return 24 | */ 25 | Response findTagPageList(FindTagArticlePageListReqVO findTagArticlePageListReqVO); 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/test/java/com/quanxiaoha/weblog/common/WeblogModuleCommonApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common; 2 | 3 | import com.quanxiaoha.weblog.common.domain.dos.UserDO; 4 | import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import java.util.Date; 11 | 12 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = WeblogModuleCommonApplicationTests.Application.class) 13 | @Slf4j 14 | class WeblogModuleCommonApplicationTests { 15 | 16 | public static class Application { 17 | } 18 | 19 | @Test 20 | public void test() { 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/wiki/FindWikiCatalogListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024-04-01 18:32 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiCatalogListRspVO { 21 | 22 | /** 23 | * 知识库 ID 24 | */ 25 | private Long id; 26 | 27 | private Long articleId; 28 | 29 | private String title; 30 | 31 | private Integer level; 32 | 33 | /** 34 | * 二级目录 35 | */ 36 | private List children; 37 | 38 | } -------------------------------------------------------------------------------- /weblog-vue3/src/composables/util.js: -------------------------------------------------------------------------------- 1 | import nprogress from "nprogress" 2 | 3 | nprogress.configure({ showSpinner: false }); 4 | 5 | // 消息提示 6 | export function showMessage(message = '提示内容', type = 'success', customClass = '') { 7 | return ElMessage({ 8 | type: type, 9 | message, 10 | customClass, 11 | }) 12 | } 13 | 14 | // 弹出确认框 15 | export function showModel(content = '提示内容', type = 'warning', title = '') { 16 | return ElMessageBox.confirm( 17 | content, 18 | title, 19 | { 20 | confirmButtonText: '确定', 21 | cancelButtonText: '取消', 22 | type, 23 | } 24 | ) 25 | } 26 | 27 | // 显示页面加载 Loading 28 | export function showPageLoading() { 29 | nprogress.start() 30 | } 31 | 32 | // 隐藏页面加载 Loading 33 | export function hidePageLoading() { 34 | nprogress.done() 35 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/DeleteCategoryReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.category; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | import javax.validation.constraints.NotNull; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-09-15 14:07 17 | * @description: 删除分类 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @ApiModel(value = "删除分类 VO") 24 | public class DeleteCategoryReqVO { 25 | 26 | @NotNull(message = "分类 ID 不能为空") 27 | private Long id; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminBlogSettingsService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; 4 | import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; 5 | import com.quanxiaoha.weblog.common.utils.Response; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-09-15 14:03 11 | * @description: TODO 12 | **/ 13 | public interface AdminBlogSettingsService { 14 | /** 15 | * 更新博客设置信息 16 | * @param updateBlogSettingsReqVO 17 | * @return 18 | */ 19 | Response updateBlogSettings(UpdateBlogSettingsReqVO updateBlogSettingsReqVO); 20 | 21 | /** 22 | * 获取博客设置详情 23 | * @return 24 | */ 25 | Response findDetail(); 26 | } 27 | -------------------------------------------------------------------------------- /weblog-vue3/src/layouts/frontend/components/WikiFooter.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/ArticleDetailConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.convert; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.article.FindArticleDetailRspVO; 4 | import com.quanxiaoha.weblog.common.domain.dos.ArticleDO; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023/10/8 14:57 12 | * @description: 文章详情转换 13 | **/ 14 | @Mapper 15 | public interface ArticleDetailConvert { 16 | /** 17 | * 初始化 convert 实例 18 | */ 19 | ArticleDetailConvert INSTANCE = Mappers.getMapper(ArticleDetailConvert.class); 20 | 21 | /** 22 | * 将 DO 转化为 VO 23 | * @param bean 24 | * @return 25 | */ 26 | FindArticleDetailRspVO convertDO2VO(ArticleDO bean); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-08-14 16:27 11 | * @description: JSON 工具类 12 | **/ 13 | @Slf4j 14 | public class JsonUtil { 15 | 16 | private static final ObjectMapper INSTANCE = new ObjectMapper(); 17 | 18 | public static String toJsonString(Object obj) { 19 | try { 20 | return INSTANCE.writeValueAsString(obj); 21 | } catch (JsonProcessingException e) { 22 | // todo Jackson 出参打印包含 Java 8 新日期出错问题 23 | return obj.toString(); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/search/SearchArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.search; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024-03-27 18:11 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Data 19 | @Builder 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @ApiModel(value = "文章搜索 VO") 23 | public class SearchArticlePageListReqVO extends BasePageQuery { 24 | /** 25 | * 查询关键词 26 | */ 27 | @NotBlank(message = "搜索关键词不能为空") 28 | private String word; 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleTagRelDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-08-22 17:01 15 | * @description: 文章 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @TableName("t_article_tag_rel") 22 | public class ArticleTagRelDO { 23 | 24 | @TableId(type = IdType.AUTO) 25 | private Long id; 26 | 27 | private Long articleId; 28 | 29 | private Long tagId; 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/convert/BlogSettingsConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.convert; 2 | 3 | import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; 4 | import com.quanxiaoha.weblog.web.model.vo.blogsettings.FindBlogSettingsDetailRspVO; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023/10/8 14:57 12 | * @description: 博客设置转换 13 | **/ 14 | @Mapper 15 | public interface BlogSettingsConvert { 16 | /** 17 | * 初始化 convert 实例 18 | */ 19 | BlogSettingsConvert INSTANCE = Mappers.getMapper(BlogSettingsConvert.class); 20 | 21 | /** 22 | * 将 DO 转化为 VO 23 | * @param bean 24 | * @return 25 | */ 26 | FindBlogSettingsDetailRspVO convertDO2VO(BlogSettingsDO bean); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/blogsettings/FindBlogSettingsDetailRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.blogsettings; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-09-15 14:07 12 | * @description: 博客设置详情 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindBlogSettingsDetailRspVO { 19 | private String logo; 20 | private String name; 21 | private String author; 22 | private String introduction; 23 | private String avatar; 24 | private String githubHomepage; 25 | private String csdnHomepage; 26 | private String giteeHomepage; 27 | private String zhihuHomepage; 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/AddCategoryReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.category; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * @author: 木萨·塔布提 14 | * @url: blog.arnasoft.site 15 | * @date: 2023-09-15 14:07 16 | * @description: 分类新增 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "添加分类 VO") 23 | public class AddCategoryReqVO { 24 | 25 | @NotBlank(message = "分类名称不能为空") 26 | @Length(min = 1, max = 20, message = "分类名称字数限制 1 ~ 20 之间") 27 | private String name; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/dashboard/FindDashboardStatisticsInfoRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.dashboard; 2 | 3 | 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Builder 14 | @ApiModel(value = "查询仪表盘基础统计信息入参 VO") 15 | public class FindDashboardStatisticsInfoRspVO { 16 | /** 17 | * 文章总数 18 | */ 19 | private Long articleTotalCount; 20 | 21 | /** 22 | * 分类总数 23 | */ 24 | private Long categoryTotalCount; 25 | 26 | /** 27 | * 标签总数 28 | */ 29 | private Long tagTotalCount; 30 | 31 | /** 32 | * 总浏览量 33 | */ 34 | private Long pvTotalCount; 35 | } 36 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/AddTagReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.tag; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | import javax.validation.constraints.NotEmpty; 12 | import java.util.List; 13 | 14 | /** 15 | * @author: 木萨·塔布提 16 | * @url: blog.arnasoft.site 17 | * @date: 2023-09-15 14:07 18 | * @description: 标签新增 19 | **/ 20 | @Data 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @Builder 24 | @ApiModel(value = "添加标签 VO") 25 | public class AddTagReqVO { 26 | 27 | @NotEmpty(message = "标签集合不能为空") 28 | private List tags; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/statistics/FindStatisticsInfoRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.statistics; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024-03-27 16:19 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindStatisticsInfoRspVO { 19 | /** 20 | * 文章总数 21 | */ 22 | private Long articleTotalCount; 23 | 24 | /** 25 | * 分类总数 26 | */ 27 | private Long categoryTotalCount; 28 | 29 | /** 30 | * 标签总数 31 | */ 32 | private Long tagTotalCount; 33 | 34 | /** 35 | * 总浏览量 36 | */ 37 | private Long pvTotalCount; 38 | } 39 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleContentDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-08-22 17:01 15 | * @description: 文章内容 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @TableName("t_article_content") 22 | public class ArticleContentDO { 23 | 24 | @TableId(type = IdType.AUTO) 25 | private Long id; 26 | 27 | private Long articleId; 28 | 29 | private String content; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleCategoryRelDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-08-22 17:01 15 | * @description: 文章 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @TableName("t_article_category_rel") 22 | public class ArticleCategoryRelDO { 23 | 24 | @TableId(type = IdType.AUTO) 25 | private Long id; 26 | 27 | private Long articleId; 28 | 29 | private Long categoryId; 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/archive/FindArchiveArticleRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.archive; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDate; 9 | import java.time.YearMonth; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: 归档列表中的文章 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindArchiveArticleRspVO { 22 | private Long id; 23 | private String cover; 24 | private String title; 25 | /** 26 | * 发布日期 27 | */ 28 | private LocalDate createDate; 29 | 30 | /** 31 | * 发布的月份(此字段不需要展示在前端,主要用于按月份分组使用) 32 | */ 33 | private YearMonth createMonth; 34 | } 35 | -------------------------------------------------------------------------------- /weblog-vue3/src/main.js: -------------------------------------------------------------------------------- 1 | import '@/assets/main.css' 2 | import 'animate.css'; 3 | import 'nprogress/nprogress.css' 4 | 5 | import { createApp } from 'vue' 6 | // 引入全局状态管理 Pinia 7 | import pinia from '@/stores' 8 | import App from '@/App.vue' 9 | // 导入路由 10 | import router from '@/router' 11 | // 导入全局路由守卫 12 | import '@/permission' 13 | // 导入 Element Plus 图标 14 | import * as ElementPlusIconsVue from '@element-plus/icons-vue' 15 | // 导入 element-plus 暗黑 css 16 | import 'element-plus/theme-chalk/dark/css-vars.css' 17 | // 图片点击放大 18 | import 'viewerjs/dist/viewer.css' 19 | import VueViewer from 'v-viewer' 20 | 21 | const app = createApp(App) 22 | 23 | // 应用路由 24 | app.use(router) 25 | // 应用 Pinia 26 | app.use(pinia) 27 | 28 | // 引入图标 29 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) { 30 | app.component(key, component) 31 | } 32 | 33 | app.use(VueViewer) 34 | 35 | app.mount('#app') 36 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/comment/ExamineCommentReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.comment; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024/4/6 23:19 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "评论审核 VO") 22 | public class ExamineCommentReqVO { 23 | 24 | @NotNull(message = "评论 ID 不能为空") 25 | private Long id; 26 | 27 | @NotNull(message = "评论状态不能为空") 28 | private Integer status; 29 | 30 | /** 31 | * 原因 32 | */ 33 | private String reason; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/search/SearchArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.search; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024-03-27 18:12 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | @Data 15 | @Builder 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class SearchArticlePageListRspVO { 19 | /** 20 | * 文章 ID 21 | */ 22 | private Long id; 23 | /** 24 | * 封面 25 | */ 26 | private String cover; 27 | /** 28 | * 标题 29 | */ 30 | private String title; 31 | /** 32 | * 摘要 33 | */ 34 | private String summary; 35 | /** 36 | * 发布日期 37 | */ 38 | private String createDate; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/RestTemplateConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/3 19:39 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | 15 | @Configuration 16 | public class RestTemplateConfig { 17 | 18 | @Bean 19 | public RestTemplate restTemplate() { 20 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 21 | factory.setConnectTimeout(5000); // 连接超时时间:5秒 22 | factory.setReadTimeout(5000); // 读取超时时间:5秒 23 | return new RestTemplate(factory); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.category.FindCategoryArticlePageListReqVO; 5 | import com.quanxiaoha.weblog.web.model.vo.category.FindCategoryListReqVO; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-09-15 14:03 11 | * @description: 分类 12 | **/ 13 | public interface CategoryService { 14 | /** 15 | * 获取分类列表 16 | * @return 17 | */ 18 | Response findCategoryList(FindCategoryListReqVO findCategoryListReqVO); 19 | 20 | /** 21 | * 获取分类下文章分页数据 22 | * @param findCategoryArticlePageListReqVO 23 | * @return 24 | */ 25 | Response findCategoryArticlePageList(FindCategoryArticlePageListReqVO findCategoryArticlePageListReqVO); 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.tag; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 标签分页 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindTagPageListRspVO { 21 | 22 | /** 23 | * 标签 ID 24 | */ 25 | private Long id; 26 | 27 | /** 28 | * 标签名称 29 | */ 30 | private String name; 31 | 32 | /** 33 | * 创建时间 34 | */ 35 | private LocalDateTime createTime; 36 | 37 | /** 38 | * 文章总数 39 | */ 40 | private Integer articlesTotal; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.category; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 分类分页 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindCategoryPageListRspVO { 21 | /** 22 | * 分类 ID 23 | */ 24 | private Long id; 25 | 26 | /** 27 | * 分类名称 28 | */ 29 | private String name; 30 | 31 | /** 32 | * 创建时间 33 | */ 34 | private LocalDateTime createTime; 35 | 36 | /** 37 | * 文章总数 38 | */ 39 | private Integer articlesTotal; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/ArticleService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.article.FindArticleDetailReqVO; 5 | import com.quanxiaoha.weblog.web.model.vo.article.FindIndexArticlePageListReqVO; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-09-15 14:03 11 | * @description: 文章 12 | **/ 13 | public interface ArticleService { 14 | /** 15 | * 获取首页文章分页数据 16 | * @param findIndexArticlePageListReqVO 17 | * @return 18 | */ 19 | Response findArticlePageList(FindIndexArticlePageListReqVO findIndexArticlePageListReqVO); 20 | 21 | /** 22 | * 获取文章详情 23 | * @param findArticleDetailReqVO 24 | * @return 25 | */ 26 | Response findArticleDetail(FindArticleDetailReqVO findArticleDetailReqVO); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/WikiConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.convert; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.wiki.FindWikiPageListRspVO; 4 | import com.quanxiaoha.weblog.common.domain.dos.WikiDO; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.Mapping; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | /** 10 | * @Author: 木萨·塔布提 11 | * @Date: 2024-04-01 13:06 12 | * @Version: v1.0.0 13 | * @Description: TODO 14 | **/ 15 | @Mapper 16 | public interface WikiConvert { 17 | /** 18 | * 初始化 convert 实例 19 | */ 20 | WikiConvert INSTANCE = Mappers.getMapper(WikiConvert.class); 21 | 22 | /** 23 | * WikiDO -> FindWikiPageListRspVO 24 | * @param bean 25 | * @return 26 | */ 27 | @Mapping(target = "isTop", expression = "java(bean.getWeight() > 0)") 28 | FindWikiPageListRspVO convertDO2VO(WikiDO bean); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/MinioConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.config; 2 | 3 | import io.minio.MinioClient; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-05-11 8:49 12 | * @description: TODO 13 | **/ 14 | @Configuration 15 | public class MinioConfig { 16 | @Autowired 17 | private MinioProperties minioProperties; 18 | 19 | @Bean 20 | public MinioClient minioClient() { 21 | // 构建 Minio 客户端 22 | return MinioClient.builder() 23 | .endpoint(minioProperties.getEndpoint()) 24 | .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()) 25 | .build(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/resources/spy.properties: -------------------------------------------------------------------------------- 1 | #3.2.1???? 2 | modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory 3 | #3.2.1????????? 4 | #modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory 5 | # ??????? 6 | logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger 7 | #???????? 8 | appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger 9 | # ???????? sql 10 | #appender=com.p6spy.engine.spy.appender.Slf4JLogger 11 | # ?? p6spy driver ?? 12 | deregisterdrivers=true 13 | # ??JDBC URL?? 14 | useprefix=true 15 | # ???? Log ??,????????error,info,batch,debug,statement,commit,rollback,result,resultset. 16 | excludecategories=info,debug,result,commit,resultset 17 | # ???? 18 | dateformat=yyyy-MM-dd HH:mm:ss 19 | # ??????? 20 | #driverlist=org.h2.Driver 21 | # ?????SQL?? 22 | outagedetection=true 23 | # ?SQL???? 2 ? 24 | outagedetectioninterval=2 -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.quanxiaoha.weblog.common.domain.dos.UserRoleDO; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author: 木萨·塔布提 11 | * @url: blog.arnasoft.site 12 | * @date: 2023-08-22 17:06 13 | * @description: TODO 14 | **/ 15 | public interface UserRoleMapper extends BaseMapper { 16 | /** 17 | * 根据用户名查询 18 | * @param username 19 | * @return 20 | */ 21 | default List selectByUsername(String username) { 22 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 23 | wrapper.eq(UserRoleDO::getUsername, username); 24 | 25 | return selectList(wrapper); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/CountTo.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/user/UpdateAdminUserPasswordReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.user; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import javax.validation.constraints.*; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:07 15 | * @description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @ApiModel(value = "修改用户密码 VO") 22 | public class UpdateAdminUserPasswordReqVO { 23 | 24 | @NotBlank(message = "用户名不能为空") 25 | @ApiModelProperty(value = "用户名") 26 | private String username; 27 | 28 | @NotBlank(message = "密码不能为空") 29 | @ApiModelProperty(value = "密码") 30 | private String password; 31 | } 32 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/UpdateWikiCatalogReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.Valid; 10 | import javax.validation.constraints.NotNull; 11 | import java.util.List; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-04-01 15:47 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @ApiModel(value = "更新知识库目录数据入参 VO") 24 | public class UpdateWikiCatalogReqVO { 25 | 26 | /** 27 | * 知识库 ID 28 | */ 29 | @NotNull(message = "知识库 ID 不能为空") 30 | private Long id; 31 | 32 | /** 33 | * 目录 34 | */ 35 | @Valid 36 | private List catalogs; 37 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/comment/FindCommentPageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/4/6 22:34 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindCommentPageListRspVO { 22 | 23 | private Long id; 24 | 25 | private String routerUrl; 26 | 27 | private String avatar; 28 | 29 | private String nickname; 30 | 31 | private String mail; 32 | 33 | private String website; 34 | 35 | private LocalDateTime createTime; 36 | 37 | private String content; 38 | 39 | private Integer status; 40 | 41 | private String reason; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/config/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 5 | import org.springframework.security.crypto.password.PasswordEncoder; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-08-24 9:17 12 | * @description: 密码加密 13 | **/ 14 | @Component 15 | public class PasswordEncoderConfig { 16 | 17 | @Bean 18 | public PasswordEncoder passwordEncoder() { 19 | // BCrypt 是一种安全且适合密码存储的哈希算法,它在进行哈希时会自动加入“盐”,增加密码的安全性。 20 | return new BCryptPasswordEncoder(); 21 | } 22 | 23 | public static void main(String[] args) { 24 | BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 25 | System.out.println(encoder.encode("111")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/FindWikiPageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDate; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024-04-01 13:03 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "查询知识库分页数据入参 VO") 23 | public class FindWikiPageListReqVO extends BasePageQuery { 24 | 25 | /** 26 | * 知识库标题 27 | */ 28 | private String title; 29 | 30 | /** 31 | * 发布的起始日期 32 | */ 33 | private LocalDate startDate; 34 | 35 | /** 36 | * 发布的结束日期 37 | */ 38 | private LocalDate endDate; 39 | 40 | } -------------------------------------------------------------------------------- /weblog-vue3/src/composables/cookie.js: -------------------------------------------------------------------------------- 1 | import { useCookies } from '@vueuse/integrations/useCookies' 2 | 3 | const cookie = useCookies() 4 | 5 | // ============================== Token 令牌 ============================== 6 | 7 | // 存储在 Cookie 中的 Token 的 key 8 | const TOKEN_KEY = 'Authorization' 9 | 10 | // 获取 Token 值 11 | export function getToken() { 12 | return cookie.get(TOKEN_KEY) 13 | } 14 | 15 | // 设置 Token 到 Cookie 中 16 | export function setToken(token) { 17 | return cookie.set(TOKEN_KEY, token) 18 | } 19 | 20 | // 删除 Token 21 | export function removeToken() { 22 | return cookie.remove(TOKEN_KEY) 23 | } 24 | 25 | // ============================== 标签页 ============================== 26 | 27 | // 存储在 Cookie 中的标签页数据的 key 28 | const TAB_LIST_KEY = 'tabList' 29 | 30 | // 获取 TabList 31 | export function getTabList() { 32 | return cookie.get(TAB_LIST_KEY) 33 | } 34 | 35 | // 存储 TabList 到 Cookie 中 36 | export function setTabList(tabList) { 37 | return cookie.set(TAB_LIST_KEY, tabList) 38 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/FindArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 文章分页 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindArticlePageListRspVO { 21 | 22 | /** 23 | * 文章 ID 24 | */ 25 | private Long id; 26 | 27 | /** 28 | * 文章标题 29 | */ 30 | private String title; 31 | 32 | /** 33 | * 文章封面 34 | */ 35 | private String cover; 36 | 37 | /** 38 | * 发布时间 39 | */ 40 | private LocalDateTime createTime; 41 | 42 | /** 43 | * 是否置顶 44 | */ 45 | private Boolean isTop; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/tag/FindTagPageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.tag; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDate; 11 | 12 | /** 13 | * @author: 木萨·塔布提 14 | * @url: blog.arnasoft.site 15 | * @date: 2023-09-15 14:07 16 | * @description: 标签分页 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "查询标签分页数据入参 VO") 23 | public class FindTagPageListReqVO extends BasePageQuery { 24 | 25 | /** 26 | * 标签名称 27 | */ 28 | private String name; 29 | 30 | /** 31 | * 创建的起始日期 32 | */ 33 | private LocalDate startDate; 34 | 35 | /** 36 | * 创建的结束日期 37 | */ 38 | private LocalDate endDate; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/FindWikiCatalogListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024-04-01 13:38 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiCatalogListRspVO { 21 | 22 | /** 23 | * 知识库 ID 24 | */ 25 | private Long id; 26 | 27 | private Long articleId; 28 | 29 | private String title; 30 | 31 | private Integer sort; 32 | 33 | private Integer level; 34 | 35 | /** 36 | * 是否处于编辑状态(用于前端是否显示编辑输入框) 37 | */ 38 | private Boolean editing; 39 | 40 | /** 41 | * 二级目录 42 | */ 43 | private List children; 44 | 45 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/AddWikiReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024-04-01 12:07 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "新增知识库 VO") 23 | public class AddWikiReqVO { 24 | 25 | @NotBlank(message = "知识库标题不能为空") 26 | @Length(min = 1, max = 20, message = "知识库标题字数需大于 1 小于 20") 27 | private String title; 28 | 29 | @NotBlank(message = "知识库摘要不能为空") 30 | private String summary; 31 | 32 | @NotBlank(message = "知识库封面不能为空") 33 | private String cover; 34 | 35 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/WikiService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.wiki.FindWikiArticlePreNextReqVO; 5 | import com.quanxiaoha.weblog.web.model.vo.wiki.FindWikiCatalogListReqVO; 6 | 7 | /** 8 | * @Author: 木萨·塔布提 9 | * @Date: 2024-04-01 18:25 10 | * @Version: v1.0.0 11 | * @Description: TODO 12 | **/ 13 | public interface WikiService { 14 | /** 15 | * 获取知识库 16 | * @return 17 | */ 18 | Response findWikiList(); 19 | 20 | /** 21 | * 获取知识库目录 22 | * @param findWikiCatalogListReqVO 23 | * @return 24 | */ 25 | Response findWikiCatalogList(FindWikiCatalogListReqVO findWikiCatalogListReqVO); 26 | 27 | /** 28 | * 获取上下页 29 | * @param findWikiArticlePreNextReqVO 30 | * @return 31 | */ 32 | Response findArticlePreNext(FindWikiArticlePreNextReqVO findWikiArticlePreNextReqVO); 33 | } 34 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/TagDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-08-22 17:01 17 | * @description: 标签 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_tag") 24 | public class TagDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String name; 30 | 31 | private LocalDateTime createTime; 32 | 33 | private LocalDateTime updateTime; 34 | 35 | private Boolean isDeleted; 36 | 37 | private Integer articlesTotal; 38 | } 39 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/UserDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-08-22 17:01 17 | * @description: 用户 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_user") 24 | public class UserDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String username; 30 | 31 | private String password; 32 | 33 | private LocalDateTime createTime; 34 | 35 | private LocalDateTime updateTime; 36 | 37 | private Boolean isDeleted; 38 | } 39 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CategoryDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-08-22 17:01 17 | * @description: 分类 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_category") 24 | public class CategoryDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String name; 30 | 31 | private LocalDateTime createTime; 32 | 33 | private LocalDateTime updateTime; 34 | 35 | private Boolean isDeleted; 36 | 37 | private Integer articlesTotal; 38 | } -------------------------------------------------------------------------------- /weblog-vue3/src/api/admin/wiki.js: -------------------------------------------------------------------------------- 1 | import axios from "@/axios"; 2 | 3 | // 获取文章分页数据 4 | export function getWikiPageList(data) { 5 | return axios.post("/admin/wiki/list", data) 6 | } 7 | 8 | // 新增知识库 9 | export function addWiki(data) { 10 | return axios.post("/admin/wiki/add", data) 11 | } 12 | 13 | // 更新知识库置顶状态 14 | export function updateWikiIsTop(data) { 15 | return axios.post("/admin/wiki/isTop/update", data) 16 | } 17 | 18 | // 更新知识库发布状态 19 | export function updateWikiIsPublish(data) { 20 | return axios.post("/admin/wiki/isPublish/update", data) 21 | } 22 | 23 | // 删除知识库 24 | export function deleteWiki(id) { 25 | return axios.post("/admin/wiki/delete", { id }) 26 | } 27 | 28 | // 更新知识库 29 | export function updateWiki(data) { 30 | return axios.post("/admin/wiki/update", data) 31 | } 32 | 33 | // 获取知识库目录 34 | export function getWikiCatalogs(id) { 35 | return axios.post("/admin/wiki/catalog/list", {id}) 36 | } 37 | 38 | // 更新知识库目录 39 | export function updateWikiCatalogs(data) { 40 | return axios.post("/admin/wiki/catalog/update", data) 41 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/FindBlogSettingsRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.blogsettings; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * @author: 木萨·塔布提 10 | * @url: blog.arnasoft.site 11 | * @date: 2023-09-15 14:07 12 | * @description: 博客基础信息 13 | **/ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Builder 18 | public class FindBlogSettingsRspVO { 19 | 20 | private String logo; 21 | 22 | private String name; 23 | 24 | private String author; 25 | 26 | private String introduction; 27 | 28 | private String avatar; 29 | 30 | private String githubHomepage; 31 | 32 | private String csdnHomepage; 33 | 34 | private String giteeHomepage; 35 | 36 | private String zhihuHomepage; 37 | 38 | private String mail; 39 | 40 | private Boolean isCommentSensiWordOpen; 41 | 42 | private Boolean isCommentExamineOpen; 43 | } 44 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/comment/FindCommentPageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.comment; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDate; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024/4/6 20:48 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "查询评论分页数据入参 VO") 23 | public class FindCommentPageListReqVO extends BasePageQuery { 24 | 25 | /** 26 | * 路由地址 27 | */ 28 | private String routerUrl; 29 | 30 | /** 31 | * 发布的起始日期 32 | */ 33 | private LocalDate startDate; 34 | 35 | /** 36 | * 发布的结束日期 37 | */ 38 | private LocalDate endDate; 39 | 40 | /** 41 | * 状态 42 | */ 43 | private Integer status; 44 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/StatisticsArticlePVDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDate; 12 | import java.time.LocalDateTime; 13 | 14 | /** 15 | * @author: 木萨·塔布提 16 | * @url: blog.arnasoft.site 17 | * @date: 2023-08-22 17:01 18 | * @description: 每日文章 PV 访问量统计 19 | **/ 20 | @Data 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @Builder 24 | @TableName("t_statistics_article_pv") 25 | public class StatisticsArticlePVDO { 26 | 27 | @TableId(type = IdType.AUTO) 28 | private Long id; 29 | 30 | private LocalDate pvDate; 31 | 32 | private Long pvCount; 33 | 34 | private LocalDateTime createTime; 35 | 36 | private LocalDateTime updateTime; 37 | } 38 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/FindArticlePageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDate; 11 | 12 | /** 13 | * @author: 木萨·塔布提 14 | * @url: blog.arnasoft.site 15 | * @date: 2023-09-15 14:07 16 | * @description: 文章分页 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | @ApiModel(value = "查询文章分页数据入参 VO") 23 | public class FindArticlePageListReqVO extends BasePageQuery { 24 | 25 | /** 26 | * 文章标题 27 | */ 28 | private String title; 29 | 30 | /** 31 | * 发布的起始日期 32 | */ 33 | private LocalDate startDate; 34 | 35 | /** 36 | * 发布的结束日期 37 | */ 38 | private LocalDate endDate; 39 | 40 | /** 41 | * 文章类型 42 | */ 43 | private Integer type; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/runner/StatisticsTagArticleTotalRunner.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.runner; 2 | 3 | import com.quanxiaoha.weblog.admin.service.AdminStatisticsService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.scheduling.annotation.Async; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/3/28 22:52 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Component 17 | @Slf4j 18 | public class StatisticsTagArticleTotalRunner implements CommandLineRunner { 19 | 20 | @Autowired 21 | private AdminStatisticsService statisticsService; 22 | 23 | @Override 24 | @Async("threadPoolTaskExecutor") 25 | public void run(String... args) throws Exception { 26 | log.info("==> 开始统计各标签下文章数量..."); 27 | statisticsService.statisticsTagArticleTotal(); 28 | log.info("==> 结束统计各标签下文章数量..."); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/InsertBatchSqlInjector.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.config; 2 | 3 | import com.baomidou.mybatisplus.core.injector.AbstractMethod; 4 | import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; 5 | import com.baomidou.mybatisplus.core.metadata.TableInfo; 6 | import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-06-13 22:46 14 | * @description: 批量插入 SQL 注入器 15 | **/ 16 | public class InsertBatchSqlInjector extends DefaultSqlInjector { 17 | 18 | @Override 19 | public List getMethodList(Class mapperClass, TableInfo tableInfo) { 20 | // super.getMethodList() 保留 Mybatis Plus 自带的方法 21 | List methodList = super.getMethodList(mapperClass, tableInfo); 22 | // 添加自定义方法:批量插入,方法名为 insertBatchSomeColumn 23 | methodList.add(new InsertBatchSomeColumn()); 24 | return methodList; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/runner/StatisticsCategoryArticleTotalRunner.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.runner; 2 | 3 | import com.quanxiaoha.weblog.admin.service.AdminStatisticsService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.scheduling.annotation.Async; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024/3/28 20:40 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Component 17 | @Slf4j 18 | public class StatisticsCategoryArticleTotalRunner implements CommandLineRunner { 19 | 20 | @Autowired 21 | private AdminStatisticsService statisticsService; 22 | 23 | @Override 24 | @Async("threadPoolTaskExecutor") 25 | public void run(String... args) throws Exception { 26 | log.info("==> 开始统计各分类下文章数量..."); 27 | statisticsService.statisticsCategoryArticleTotal(); 28 | log.info("==> 结束统计各分类下文章数量..."); 29 | } 30 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/convert/BlogSettingsConvert.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.convert; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.blogsettings.FindBlogSettingsRspVO; 4 | import com.quanxiaoha.weblog.admin.model.vo.blogsettings.UpdateBlogSettingsReqVO; 5 | import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | /** 10 | * @author: 木萨·塔布提 11 | * @url: blog.arnasoft.site 12 | * @date: 2023/10/8 14:57 13 | * @description: 博客设置转换 14 | **/ 15 | @Mapper 16 | public interface BlogSettingsConvert { 17 | /** 18 | * 初始化 convert 实例 19 | */ 20 | BlogSettingsConvert INSTANCE = Mappers.getMapper(BlogSettingsConvert.class); 21 | 22 | /** 23 | * 将 VO 转化为 DO 24 | * @param bean 25 | * @return 26 | */ 27 | BlogSettingsDO convertVO2DO(UpdateBlogSettingsReqVO bean); 28 | 29 | /** 30 | * 将 DO 转化为 VO 31 | * @param bean 32 | * @return 33 | */ 34 | FindBlogSettingsRspVO convertDO2VO(BlogSettingsDO bean); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 MUSA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/WikiDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-04-01 12:03 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_wiki") 24 | public class WikiDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String title; 30 | 31 | private String cover; 32 | 33 | private String summary; 34 | 35 | private LocalDateTime createTime; 36 | 37 | private LocalDateTime updateTime; 38 | 39 | private Boolean isDeleted; 40 | 41 | private Integer weight; 42 | 43 | private Boolean isPublish; 44 | } 45 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/UpdateWikiCatalogItemReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.validation.Valid; 9 | import javax.validation.constraints.NotBlank; 10 | import javax.validation.constraints.NotNull; 11 | import java.util.List; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-04-01 15:47 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | public class UpdateWikiCatalogItemReqVO { 24 | 25 | /** 26 | * 目录 ID 27 | */ 28 | @NotNull(message = "目录 ID 不能为空") 29 | private Long id; 30 | 31 | private Long articleId; 32 | 33 | @NotBlank(message = "目录标题不能为空") 34 | private String title; 35 | 36 | private Integer sort; 37 | 38 | private Integer level; 39 | 40 | /** 41 | * 子目录 42 | */ 43 | @Valid 44 | private List children; 45 | 46 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/UpdateWikiReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | import javax.validation.constraints.NotNull; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-04-01 13:27 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @ApiModel(value = "更新知识库 VO") 24 | public class UpdateWikiReqVO { 25 | 26 | @NotNull(message = "ID 不能为空") 27 | private Long id; 28 | 29 | @NotBlank(message = "知识库标题不能为空") 30 | @Length(min = 1, max = 20, message = "知识库标题字数需大于 1 小于 20") 31 | private String title; 32 | 33 | @NotBlank(message = "知识库摘要不能为空") 34 | private String summary; 35 | 36 | @NotBlank(message = "知识库封面不能为空") 37 | private String cover; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/CommentService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service; 2 | 3 | import com.quanxiaoha.weblog.common.utils.Response; 4 | import com.quanxiaoha.weblog.web.model.vo.comment.FindCommentListReqVO; 5 | import com.quanxiaoha.weblog.web.model.vo.comment.FindQQUserInfoReqVO; 6 | import com.quanxiaoha.weblog.web.model.vo.comment.PublishCommentReqVO; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/3 19:54 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | public interface CommentService { 15 | 16 | /** 17 | * 根据 QQ 号获取用户信息 18 | * @param findQQUserInfoReqVO 19 | * @return 20 | */ 21 | Response findQQUserInfo(FindQQUserInfoReqVO findQQUserInfoReqVO); 22 | 23 | /** 24 | * 发布评论 25 | * @param publishCommentReqVO 26 | * @return 27 | */ 28 | Response publishComment(PublishCommentReqVO publishCommentReqVO); 29 | 30 | /** 31 | * 查询页面所有评论 32 | * @param findCommentListReqVO 33 | * @return 34 | */ 35 | Response findCommentList(FindCommentListReqVO findCommentListReqVO); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/config/TheadPoolConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | 8 | import java.util.concurrent.Executor; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023/11/9 10:47 14 | * @description: 线程池配置 15 | **/ 16 | @Configuration 17 | @EnableAsync 18 | public class TheadPoolConfig { 19 | 20 | @Bean("threadPoolTaskExecutor") 21 | public Executor threadPoolTaskExecutor() { 22 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 23 | executor.setCorePoolSize(10); // 核心线程数 24 | executor.setMaxPoolSize(20); // 最大线程数 25 | executor.setQueueCapacity(100); // 队列容量 26 | executor.setThreadNamePrefix("WeblogThreadPool-"); // 线程名前缀 27 | executor.initialize(); 28 | return executor; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/wiki/FindWikiPageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.wiki; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @Author: 木萨·塔布提 12 | * @Date: 2024-04-01 13:04 13 | * @Version: v1.0.0 14 | * @Description: TODO 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindWikiPageListRspVO { 21 | 22 | /** 23 | * 知识库 ID 24 | */ 25 | private Long id; 26 | 27 | /** 28 | * 知识库标题 29 | */ 30 | private String title; 31 | 32 | /** 33 | * 知识库封面 34 | */ 35 | private String cover; 36 | 37 | /** 38 | * 摘要 39 | */ 40 | private String summary; 41 | 42 | /** 43 | * 发布时间 44 | */ 45 | private LocalDateTime createTime; 46 | 47 | /** 48 | * 是否置顶 49 | */ 50 | private Boolean isTop; 51 | 52 | /** 53 | * 是否发布 54 | */ 55 | private Boolean isPublish; 56 | 57 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/FindArticleDetailRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:07 14 | * @description: 文章详情 15 | **/ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Builder 20 | public class FindArticleDetailRspVO { 21 | 22 | /** 23 | * 文章 ID 24 | */ 25 | private Long id; 26 | 27 | /** 28 | * 文章标题 29 | */ 30 | private String title; 31 | 32 | /** 33 | * 文章封面 34 | */ 35 | private String cover; 36 | 37 | /** 38 | * 文章内容 39 | */ 40 | private String content; 41 | 42 | /** 43 | * 分类 ID 44 | */ 45 | private Long categoryId; 46 | 47 | /** 48 | * 标签 ID 集合 49 | */ 50 | private List tagIds; 51 | 52 | /** 53 | * 摘要 54 | */ 55 | private String summary; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/category/FindCategoryPageListReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.category; 2 | 3 | import com.quanxiaoha.weblog.common.model.BasePageQuery; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import org.hibernate.validator.constraints.Length; 10 | 11 | import javax.validation.constraints.NotBlank; 12 | import java.time.LocalDate; 13 | import java.time.LocalDateTime; 14 | 15 | /** 16 | * @author: 木萨·塔布提 17 | * @url: blog.arnasoft.site 18 | * @date: 2023-09-15 14:07 19 | * @description: 分类分页 20 | **/ 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Builder 25 | @ApiModel(value = "查询分类分页数据入参 VO") 26 | public class FindCategoryPageListReqVO extends BasePageQuery { 27 | 28 | /** 29 | * 分类名称 30 | */ 31 | private String name; 32 | 33 | /** 34 | * 创建的起始日期 35 | */ 36 | private LocalDate startDate; 37 | 38 | /** 39 | * 创建的结束日期 40 | */ 41 | private LocalDate endDate; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCommentService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.comment.DeleteCommentReqVO; 4 | import com.quanxiaoha.weblog.admin.model.vo.comment.ExamineCommentReqVO; 5 | import com.quanxiaoha.weblog.admin.model.vo.comment.FindCommentPageListReqVO; 6 | import com.quanxiaoha.weblog.common.utils.Response; 7 | 8 | /** 9 | * @Author: 木萨·塔布提 10 | * @Date: 2024/4/6 22:36 11 | * @Version: v1.0.0 12 | * @Description: TODO 13 | **/ 14 | public interface AdminCommentService { 15 | 16 | /** 17 | * 查询评论分页数据 18 | * @param findCommentPageListReqVO 19 | * @return 20 | */ 21 | Response findCommentPageList(FindCommentPageListReqVO findCommentPageListReqVO); 22 | 23 | /** 24 | * 删除评论 25 | * @param deleteCommentReqVO 26 | * @return 27 | */ 28 | Response deleteComment(DeleteCommentReqVO deleteCommentReqVO); 29 | 30 | /** 31 | * 评论审核 32 | * @param examineCommentReqVO 33 | * @return 34 | */ 35 | Response examine(ExamineCommentReqVO examineCommentReqVO); 36 | } 37 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/ArticleDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-08-22 17:01 17 | * @description: 文章 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_article") 24 | public class ArticleDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String title; 30 | 31 | private String cover; 32 | 33 | private String summary; 34 | 35 | private LocalDateTime createTime; 36 | 37 | private LocalDateTime updateTime; 38 | 39 | private Boolean isDeleted; 40 | 41 | private Long readNum; 42 | 43 | private Integer weight; 44 | 45 | private Integer type; 46 | } 47 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/WikiCatalogDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-04-01 12:03 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_wiki_catalog") 24 | public class WikiCatalogDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private Long wikiId; 30 | 31 | private Long articleId; 32 | 33 | private String title; 34 | 35 | private Integer level; 36 | 37 | private Long parentId; 38 | 39 | private Integer sort; 40 | 41 | private LocalDateTime createTime; 42 | 43 | private LocalDateTime updateTime; 44 | 45 | private Boolean isDeleted; 46 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/article/FindIndexArticlePageListRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.article; 2 | 3 | import com.quanxiaoha.weblog.web.model.vo.category.FindCategoryListRspVO; 4 | import com.quanxiaoha.weblog.web.model.vo.tag.FindTagListRspVO; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.time.LocalDate; 11 | import java.util.List; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-09-15 14:07 17 | * @description: 首页-文章分页 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | public class FindIndexArticlePageListRspVO { 24 | private Long id; 25 | private String cover; 26 | private String title; 27 | private LocalDate createDate; 28 | private String summary; 29 | /** 30 | * 文章分类 31 | */ 32 | private FindCategoryListRspVO category; 33 | 34 | /** 35 | * 文章标签 36 | */ 37 | private List tags; 38 | 39 | /** 40 | * 是否置顶 41 | */ 42 | private Boolean isTop; 43 | } 44 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/test/java/com/quanxiaoha/weblog/admin/WeblogModuleAdminApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin; 2 | 3 | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; 4 | import com.quanxiaoha.weblog.common.domain.dos.UserDO; 5 | import com.quanxiaoha.weblog.common.domain.mapper.UserMapper; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 9 | import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.context.annotation.Import; 12 | 13 | import java.time.LocalDateTime; 14 | 15 | @SpringBootTest(classes = WeblogModuleAdminApplicationTests.Application.class) 16 | class WeblogModuleAdminApplicationTests { 17 | // @Import({ 18 | // DataSourceAutoConfiguration.class, // Spring DB 自动配置类 19 | // DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 20 | // MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 21 | // }) 22 | public static class Application { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/StatisticsController.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.controller; 2 | 3 | import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.web.service.StatisticsService; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024-03-27 16:40 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @RestController 20 | @RequestMapping("/statistics") 21 | @Api(tags = "统计信息") 22 | public class StatisticsController { 23 | 24 | @Autowired 25 | private StatisticsService statisticsService; 26 | 27 | @PostMapping("/info") 28 | @ApiOperation(value = "前台获取统计信息") 29 | @ApiOperationLog(description = "前台获取统计信息") 30 | public Response findInfo() { 31 | return statisticsService.findInfo(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/BlogSettingsController.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.controller; 2 | 3 | import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.web.service.BlogSettingsService; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-09-15 14:01 17 | * @description: 博客设置 18 | **/ 19 | @RestController 20 | @RequestMapping("/blog/settings") 21 | @Api(tags = "博客设置") 22 | public class BlogSettingsController { 23 | 24 | @Autowired 25 | private BlogSettingsService blogSettingsService; 26 | 27 | @PostMapping("/detail") 28 | @ApiOperation(value = "前台获取博客详情") 29 | @ApiOperationLog(description = "前台获取博客详情") 30 | public Response findDetail() { 31 | return blogSettingsService.findDetail(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/ArticlePVLineChat.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.config; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | /** 10 | * @author: 木萨·塔布提 11 | * @url: blog.arnasoft.site 12 | * @date: 2023-08-22 16:52 13 | * @description: Mybatis Plus 配置文件 14 | **/ 15 | @Configuration 16 | @MapperScan("com.quanxiaoha.weblog.common.domain.mapper") 17 | public class MybatisPlusConfig { 18 | 19 | /** 20 | * 分页插件 21 | * @return 22 | */ 23 | @Bean 24 | public MybatisPlusInterceptor mybatisPlusInterceptor(){ 25 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 26 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 27 | return interceptor; 28 | } 29 | 30 | /** 31 | * 自定义批量插入 SQL 注入器 32 | */ 33 | @Bean 34 | public InsertBatchSqlInjector insertBatchSqlInjector() { 35 | return new InsertBatchSqlInjector(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/BlogSettingsDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-08-22 17:01 15 | * @description: 博客设置 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @TableName("t_blog_settings") 22 | public class BlogSettingsDO { 23 | 24 | @TableId(type = IdType.AUTO) 25 | private Long id; 26 | 27 | private String logo; 28 | 29 | private String name; 30 | 31 | private String author; 32 | 33 | private String introduction; 34 | 35 | private String avatar; 36 | 37 | private String githubHomepage; 38 | 39 | private String csdnHomepage; 40 | 41 | private String giteeHomepage; 42 | 43 | private String zhihuHomepage; 44 | 45 | private String mail; 46 | 47 | private Boolean isCommentSensiWordOpen; 48 | 49 | private Boolean isCommentExamineOpen; 50 | } 51 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/dos/CommentDO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.dos; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @Author: 木萨·塔布提 15 | * @Date: 2024/4/3 20:39 16 | * @Version: v1.0.0 17 | * @Description: TODO 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @TableName("t_comment") 24 | public class CommentDO { 25 | 26 | @TableId(type = IdType.AUTO) 27 | private Long id; 28 | 29 | private String content; 30 | 31 | private String avatar; 32 | 33 | private String nickname; 34 | 35 | private String mail; 36 | 37 | private String website; 38 | 39 | private String routerUrl; 40 | 41 | private LocalDateTime createTime; 42 | 43 | private LocalDateTime updateTime; 44 | 45 | private Boolean isDeleted; 46 | 47 | private Long replyCommentId; 48 | 49 | private Long parentCommentId; 50 | 51 | private Integer status; 52 | 53 | private String reason; 54 | } -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/PublishArticleReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | import org.hibernate.validator.constraints.NotEmpty; 10 | 11 | import javax.validation.constraints.NotBlank; 12 | import javax.validation.constraints.NotNull; 13 | import java.util.List; 14 | 15 | /** 16 | * @author: 木萨·塔布提 17 | * @url: blog.arnasoft.site 18 | * @date: 2023-09-15 14:07 19 | * @description: 文章发布 20 | **/ 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Builder 25 | @ApiModel(value = "发布文章 VO") 26 | public class PublishArticleReqVO { 27 | 28 | @NotBlank(message = "文章标题不能为空") 29 | @Length(min = 1, max = 40, message = "文章标题字数需大于 1 小于 40") 30 | private String title; 31 | 32 | @NotBlank(message = "文章内容不能为空") 33 | private String content; 34 | 35 | @NotBlank(message = "文章封面不能为空") 36 | private String cover; 37 | 38 | private String summary; 39 | 40 | @NotNull(message = "文章分类不能为空") 41 | private Long categoryId; 42 | 43 | @NotEmpty(message = "文章标签不能为空") 44 | private List tags; 45 | } 46 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.quanxiaoha.weblog.common.domain.dos.UserDO; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-08-22 17:06 14 | * @description: TODO 15 | **/ 16 | public interface UserMapper extends BaseMapper { 17 | default UserDO findByUsername(String username) { 18 | LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); 19 | wrapper.eq(UserDO::getUsername, username); 20 | return selectOne(wrapper); 21 | } 22 | 23 | default int updatePasswordByUsername(String username, String password) { 24 | LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); 25 | // 设置要更新的字段 26 | wrapper.set(UserDO::getPassword, password); 27 | wrapper.set(UserDO::getUpdateTime, LocalDateTime.now()); 28 | // 更新条件 29 | wrapper.eq(UserDO::getUsername, username); 30 | 31 | return update(null, wrapper); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/FindCommentItemRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.time.LocalDateTime; 9 | import java.util.List; 10 | 11 | /** 12 | * @Author: 木萨·塔布提 13 | * @Date: 2024/4/3 21:21 14 | * @Version: v1.0.0 15 | * @Description: TODO 16 | **/ 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | public class FindCommentItemRspVO { 22 | 23 | /** 24 | * 主键 25 | */ 26 | private Long id; 27 | 28 | /** 29 | * 头像 30 | */ 31 | private String avatar; 32 | 33 | /** 34 | * 昵称 35 | */ 36 | private String nickname; 37 | 38 | /** 39 | * 网址 40 | */ 41 | private String website; 42 | 43 | /** 44 | * 评论内容 45 | */ 46 | private String content; 47 | 48 | /** 49 | * 发布时间 50 | */ 51 | private LocalDateTime createTime; 52 | 53 | /** 54 | * 回复用户的昵称 55 | */ 56 | private String replyNickname; 57 | 58 | /** 59 | * 子评论集合 60 | */ 61 | private List childComments; 62 | 63 | /** 64 | * 是否展示回复表单(默认 false) 65 | */ 66 | private Boolean isShowReplyForm; 67 | 68 | } -------------------------------------------------------------------------------- /weblog-vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "msblog-vue3", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "@element-plus/icons-vue": "^2.1.0", 12 | "@vueuse/core": "^10.4.1", 13 | "@vueuse/integrations": "^10.4.1", 14 | "animate.css": "^4.1.1", 15 | "axios": "^1.5.0", 16 | "date-fns": "^2.30.0", 17 | "echarts": "^5.4.2", 18 | "element-plus": "^2.3.9", 19 | "flowbite": "^1.8.1", 20 | "gsap": "^3.12.2", 21 | "highlight.js": "^11.9.0", 22 | "md-editor-v3": "^4.8.1", 23 | "moment": "^2.29.4", 24 | "nprogress": "^0.2.0", 25 | "pinia": "^2.1.6", 26 | "pinia-plugin-persistedstate": "^3.2.0", 27 | "universal-cookie": "^6.1.0", 28 | "v-viewer": "^3.0.11", 29 | "viewerjs": "^1.11.6", 30 | "vue": "^3.3.4", 31 | "vue-draggable-plus": "^0.4.0", 32 | "vue-router": "^4.2.4" 33 | }, 34 | "devDependencies": { 35 | "@vitejs/plugin-vue": "^4.2.3", 36 | "autoprefixer": "^10.4.15", 37 | "postcss": "^8.4.28", 38 | "tailwindcss": "^3.3.3", 39 | "unplugin-auto-import": "^0.16.6", 40 | "unplugin-vue-components": "^0.25.1", 41 | "vite": "^4.4.6", 42 | "vite-plugin-cdn-import": "^0.3.5", 43 | "vite-plugin-compression": "^0.5.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt.handler; 2 | 3 | import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.jwt.utils.ResultUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | /** 17 | * @author: 木萨·塔布提 18 | * @url: blog.arnasoft.site 19 | * @date: 2023-08-27 17:32 20 | * @description: 登录成功访问收保护的资源,但是权限不够 21 | **/ 22 | @Slf4j 23 | @Component 24 | public class RestAccessDeniedHandler implements AccessDeniedHandler { 25 | 26 | @Override 27 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 28 | log.warn("登录成功访问收保护的资源,但是权限不够: ", accessDeniedException); 29 | // 预留,后面引入多角色时会用到 30 | ResultUtil.fail(response, Response.fail(ResponseCodeEnum.FORBIDDEN)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | datasource: 4 | # 指定数据库驱动类 5 | driver-class-name: com.mysql.cj.jdbc.Driver 6 | # 数据库连接信息 7 | url: jdbc:mysql://localhost:3306/weblog?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull 8 | username: root 9 | password: root 10 | hikari: # 数据库连接池使用 Hikari 11 | minimum-idle: 5 # 连接池中最小空闲连接数 12 | maximum-pool-size: 20 # 连接池中允许的最大连接数 13 | auto-commit: true # 是否自动提交事务 14 | idle-timeout: 30000 # 连接在连接池中闲置的最长时间,超过这个时间会被释放。 15 | pool-name: Weblog-HikariCP # 自定义连接池的名字 16 | max-lifetime: 1800000 # 连接在连接池中的最大存活时间,超过这个时间会被强制关闭。 17 | connection-timeout: 30000 # 连接的超时时间 18 | connection-test-query: SELECT 1 # 用于测试连接是否可用的SQL查询 19 | 20 | 21 | #================================================================= 22 | # minio (上传图片需要,需配置成自己的地址) 23 | #================================================================= 24 | minio: 25 | endpoint: #endpoint 26 | accessKey: #accessKey 27 | secretKey: #secretKey 28 | bucketName: # bucketName 29 | 30 | #================================================================= 31 | # Lucene 全文检索 32 | #================================================================= 33 | lucene: 34 | 35 | indexDir: E:\\java_workspace\\lucene-index # lucene 索引存放的位置 36 | server: 37 | port: 8080 -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/StatisticsArticlePVMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.quanxiaoha.weblog.common.domain.dos.StatisticsArticlePVDO; 6 | 7 | import java.time.LocalDate; 8 | import java.util.List; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-08-22 17:06 14 | * @description: 每日文章 PV 访问量统计 15 | **/ 16 | public interface StatisticsArticlePVMapper extends BaseMapper { 17 | 18 | /** 19 | * 对指定日期的文章 PV 访问量进行 +1 20 | * @param date 21 | * @return 22 | */ 23 | default int increasePVCount(LocalDate date) { 24 | return update(null, Wrappers.lambdaUpdate() 25 | .setSql("pv_count = pv_count + 1") 26 | .eq(StatisticsArticlePVDO::getPvDate, date)); 27 | } 28 | 29 | /** 30 | * 查询最近一周的文章 PV 访问量记录 31 | * @return 32 | */ 33 | default List selectLatestWeekRecords() { 34 | return selectList(Wrappers.lambdaQuery() 35 | .le(StatisticsArticlePVDO::getPvDate, LocalDate.now()) // 小于等于当前日期 36 | .last("limit 7")); // 仅查询七条 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /weblog-vue3/src/layouts/frontend/components/ScrollToTopButton.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 38 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/article/UpdateArticleReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.article; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import org.hibernate.validator.constraints.Length; 9 | import org.hibernate.validator.constraints.NotEmpty; 10 | 11 | import javax.validation.constraints.NotBlank; 12 | import javax.validation.constraints.NotNull; 13 | import java.util.List; 14 | 15 | /** 16 | * @author: 木萨·塔布提 17 | * @url: blog.arnasoft.site 18 | * @date: 2023-09-15 14:07 19 | * @description: 更新文章 20 | **/ 21 | @Data 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Builder 25 | @ApiModel(value = "更新文章 VO") 26 | public class UpdateArticleReqVO { 27 | 28 | @NotNull(message = "文章 ID 不能为空") 29 | private Long id; 30 | 31 | @NotBlank(message = "文章标题不能为空") 32 | @Length(min = 1, max = 40, message = "文章标题字数需大于 1 小于 40") 33 | private String title; 34 | 35 | @NotBlank(message = "文章内容不能为空") 36 | private String content; 37 | 38 | @NotBlank(message = "文章封面不能为空") 39 | private String cover; 40 | 41 | private String summary; 42 | 43 | @NotNull(message = "文章分类不能为空") 44 | private Long categoryId; 45 | 46 | @NotEmpty(message = "文章标签不能为空") 47 | private List tags; 48 | } 49 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/comment/PublishCommentReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.comment; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | import javax.validation.constraints.Email; 10 | import javax.validation.constraints.NotBlank; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024/4/3 20:40 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | public class PublishCommentReqVO { 23 | 24 | /** 25 | * 头像 26 | */ 27 | private String avatar; 28 | 29 | @NotBlank(message = "昵称不能为空") 30 | private String nickname; 31 | 32 | @NotBlank(message = "邮箱不能为空") 33 | @Email(message = "邮箱格式错误") 34 | private String mail; 35 | 36 | /** 37 | * 网址 38 | */ 39 | private String website; 40 | 41 | @NotBlank(message = "路由地址不能为空") 42 | private String routerUrl; 43 | 44 | @NotBlank(message = "评论内容不能为空") 45 | @Length(min = 1, max = 120, message = "评论内容需大于 1 小于 120 字符") 46 | private String content; 47 | 48 | /** 49 | * 回复的评论 ID 50 | */ 51 | private Long replyCommentId; 52 | 53 | /** 54 | * 父评论 ID 55 | */ 56 | private Long parentCommentId; 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/SearchController.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.controller; 2 | 3 | import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.web.model.vo.search.SearchArticlePageListReqVO; 6 | import com.quanxiaoha.weblog.web.service.SearchService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.validation.annotation.Validated; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @Author: 木萨·塔布提 17 | * @Date: 2024-03-27 18:18 18 | * @Version: v1.0.0 19 | * @Description: TODO 20 | **/ 21 | @RestController 22 | @Api(tags = "搜索") 23 | public class SearchController { 24 | 25 | @Autowired 26 | private SearchService searchService; 27 | 28 | @PostMapping("/article/search") 29 | @ApiOperation(value = "文章搜索") 30 | @ApiOperationLog(description = "文章搜索") 31 | public Response searchArticlePageList(@RequestBody @Validated SearchArticlePageListReqVO searchArticlePageListReqVO) { 32 | return searchService.searchArticlePageList(searchArticlePageListReqVO); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /weblog-vue3/src/permission.js: -------------------------------------------------------------------------------- 1 | import router from '@/router/index' 2 | import { getToken } from '@/composables/cookie' 3 | import { showMessage } from '@/composables/util' 4 | import { showPageLoading, hidePageLoading } from '@/composables/util' 5 | import { useBlogSettingsStore } from '@/stores/blogsettings' 6 | 7 | // 全局路由前置守卫 8 | router.beforeEach((to, from, next) => { 9 | console.log('==> 全局路由前置守卫') 10 | 11 | // 展示页面加载 Loading 12 | showPageLoading() 13 | 14 | let token = getToken() 15 | 16 | if (!token && to.path.startsWith('/admin')) { 17 | // 若用户想访问后台(以 /admin 为前缀的路由) 18 | // 未登录,则强制跳转登录页 19 | showMessage('请先登录', 'warning') 20 | next({ path: '/login' }) 21 | } else if (token && to.path == '/login') { 22 | // 若用户已经登录,且重复访问登录页 23 | showMessage('请勿重复登录', 'warning') 24 | // 跳转后台首页 25 | next({ path: '/admin/index' }) 26 | } else if (!to.path.startsWith('/admin')) { 27 | // 如果访问的非 /admin 前缀路由 28 | // 引入博客设置 store 29 | let blogSettingsStore = useBlogSettingsStore() 30 | // 获取博客设置信息并保存到全局状态中 31 | blogSettingsStore.getBlogSettings() 32 | next() 33 | } else { 34 | next() 35 | } 36 | }) 37 | 38 | // 全局路由后置守卫 39 | router.afterEach((to, from) => { 40 | // 动态设置页面 Titile 41 | let title = (to.meta.title ? to.meta.title : '') + ' - 程序猿小萨' 42 | document.title = title 43 | 44 | // 隐藏页面加载 Loading 45 | hidePageLoading() 46 | }) -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/service/impl/BlogSettingsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.service.impl; 2 | 3 | import com.quanxiaoha.weblog.common.domain.dos.BlogSettingsDO; 4 | import com.quanxiaoha.weblog.common.domain.mapper.BlogSettingsMapper; 5 | import com.quanxiaoha.weblog.common.utils.Response; 6 | import com.quanxiaoha.weblog.web.convert.BlogSettingsConvert; 7 | import com.quanxiaoha.weblog.web.model.vo.blogsettings.FindBlogSettingsDetailRspVO; 8 | import com.quanxiaoha.weblog.web.service.BlogSettingsService; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-09-15 14:03 17 | * @description: 博客设置 18 | **/ 19 | @Service 20 | @Slf4j 21 | public class BlogSettingsServiceImpl implements BlogSettingsService { 22 | 23 | @Autowired 24 | private BlogSettingsMapper blogSettingsMapper; 25 | 26 | /** 27 | * 获取博客设置信息 28 | * 29 | * @return 30 | */ 31 | @Override 32 | public Response findDetail() { 33 | // 查询博客设置信息(约定的 ID 为 1) 34 | BlogSettingsDO blogSettingsDO = blogSettingsMapper.selectById(1L); 35 | // DO 转 VO 36 | FindBlogSettingsDetailRspVO vo = BlogSettingsConvert.INSTANCE.convertDO2VO(blogSettingsDO); 37 | 38 | return Response.success(vo); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/controller/ArchiveController.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.controller; 2 | 3 | import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.web.model.vo.archive.FindArchiveArticlePageListReqVO; 6 | import com.quanxiaoha.weblog.web.service.ArchiveService; 7 | import io.swagger.annotations.Api; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.validation.annotation.Validated; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @author: 木萨·塔布提 17 | * @url: blog.arnasoft.site 18 | * @date: 2023-09-15 14:01 19 | * @description: 文章归档 20 | **/ 21 | @RestController 22 | @Api(tags = "文章归档") 23 | public class ArchiveController { 24 | 25 | @Autowired 26 | private ArchiveService archiveService; 27 | 28 | @PostMapping("/archive/list") 29 | @ApiOperation(value = "获取文章归档分页数据") 30 | @ApiOperationLog(description = "获取文章归档分页数据") 31 | public Response findArchivePageList(@RequestBody @Validated FindArchiveArticlePageListReqVO findArchiveArticlePageListReqVO) { 32 | return archiveService.findArchivePageList(findArchiveArticlePageListReqVO); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminTagService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO; 4 | import com.quanxiaoha.weblog.admin.model.vo.tag.DeleteTagReqVO; 5 | import com.quanxiaoha.weblog.admin.model.vo.tag.FindTagPageListReqVO; 6 | import com.quanxiaoha.weblog.admin.model.vo.tag.SearchTagsReqVO; 7 | import com.quanxiaoha.weblog.common.utils.PageResponse; 8 | import com.quanxiaoha.weblog.common.utils.Response; 9 | 10 | /** 11 | * @author: 木萨·塔布提 12 | * @url: blog.arnasoft.site 13 | * @date: 2023-09-15 14:03 14 | * @description: TODO 15 | **/ 16 | public interface AdminTagService { 17 | 18 | /** 19 | * 添加标签集合 20 | * @param addTagReqVO 21 | * @return 22 | */ 23 | Response addTags(AddTagReqVO addTagReqVO); 24 | 25 | /** 26 | * 查询标签分页 27 | * @param findTagPageListReqVO 28 | * @return 29 | */ 30 | PageResponse findTagPageList(FindTagPageListReqVO findTagPageListReqVO); 31 | 32 | /** 33 | * 删除标签 34 | * @param deleteTagReqVO 35 | * @return 36 | */ 37 | Response deleteTag(DeleteTagReqVO deleteTagReqVO); 38 | 39 | /** 40 | * 根据标签关键词模糊查询 41 | * @param searchTagsReqVO 42 | * @return 43 | */ 44 | Response searchTags(SearchTagsReqVO searchTagsReqVO); 45 | 46 | /** 47 | * 查询标签 Select 列表数据 48 | * @return 49 | */ 50 | Response findTagSelectList(); 51 | } 52 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminCategoryService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.category.AddCategoryReqVO; 4 | import com.quanxiaoha.weblog.admin.model.vo.category.DeleteCategoryReqVO; 5 | import com.quanxiaoha.weblog.admin.model.vo.category.FindCategoryPageListReqVO; 6 | import com.quanxiaoha.weblog.admin.model.vo.tag.AddTagReqVO; 7 | import com.quanxiaoha.weblog.admin.model.vo.user.UpdateAdminUserPasswordReqVO; 8 | import com.quanxiaoha.weblog.common.utils.PageResponse; 9 | import com.quanxiaoha.weblog.common.utils.Response; 10 | 11 | /** 12 | * @author: 木萨·塔布提 13 | * @url: blog.arnasoft.site 14 | * @date: 2023-09-15 14:03 15 | * @description: TODO 16 | **/ 17 | public interface AdminCategoryService { 18 | /** 19 | * 添加分类 20 | * @param addCategoryReqVO 21 | * @return 22 | */ 23 | Response addCategory(AddCategoryReqVO addCategoryReqVO); 24 | 25 | /** 26 | * 分类分页数据查询 27 | * @param findCategoryPageListReqVO 28 | * @return 29 | */ 30 | PageResponse findCategoryPageList(FindCategoryPageListReqVO findCategoryPageListReqVO); 31 | 32 | /** 33 | * 删除分类 34 | * @param deleteCategoryReqVO 35 | * @return 36 | */ 37 | Response deleteCategory(DeleteCategoryReqVO deleteCategoryReqVO); 38 | 39 | /** 40 | * 获取文章分类的 Select 列表数据 41 | * @return 42 | */ 43 | Response findCategorySelectList(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/controller/AdminFileController.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.controller; 2 | 3 | import com.quanxiaoha.weblog.admin.service.AdminFileService; 4 | import com.quanxiaoha.weblog.common.aspect.ApiOperationLog; 5 | import com.quanxiaoha.weblog.common.utils.Response; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import org.springframework.web.multipart.MultipartFile; 15 | 16 | /** 17 | * @author: 木萨·塔布提 18 | * @url: blog.arnasoft.site 19 | * @date: 2023-09-15 14:01 20 | * @description: 文件模块 21 | **/ 22 | @RestController 23 | @RequestMapping("/admin") 24 | @Api(tags = "Admin 文件模块") 25 | public class AdminFileController { 26 | 27 | @Autowired 28 | private AdminFileService fileService; 29 | 30 | @PostMapping("/file/upload") 31 | @ApiOperation(value = "文件上传") 32 | @ApiOperationLog(description = "文件上传") 33 | @PreAuthorize("hasRole('ROLE_ADMIN')") 34 | public Response uploadFile(@RequestParam MultipartFile file) { 35 | return fileService.uploadFile(file); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/service/AdminArticleService.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.service; 2 | 3 | import com.quanxiaoha.weblog.admin.model.vo.article.*; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | 6 | /** 7 | * @author: 木萨·塔布提 8 | * @url: blog.arnasoft.site 9 | * @date: 2023-09-15 14:03 10 | * @description: 文章 11 | **/ 12 | public interface AdminArticleService { 13 | /** 14 | * 更新文章是否置顶 15 | * @param updateArticleIsTopReqVO 16 | * @return 17 | */ 18 | Response updateArticleIsTop(UpdateArticleIsTopReqVO updateArticleIsTopReqVO); 19 | 20 | /** 21 | * 发布文章 22 | * @param publishArticleReqVO 23 | * @return 24 | */ 25 | Response publishArticle(PublishArticleReqVO publishArticleReqVO); 26 | 27 | /** 28 | * 删除文章 29 | * @param deleteArticleReqVO 30 | * @return 31 | */ 32 | Response deleteArticle(DeleteArticleReqVO deleteArticleReqVO); 33 | 34 | /** 35 | * 查询文章分页数据 36 | * @param findArticlePageListReqVO 37 | * @return 38 | */ 39 | Response findArticlePageList(FindArticlePageListReqVO findArticlePageListReqVO); 40 | 41 | /** 42 | * 查询文章详情 43 | * @param findArticleDetailReqVO 44 | * @return 45 | */ 46 | Response findArticleDetail(FindArticleDetailReqVO findArticleDetailReqVO); 47 | 48 | /** 49 | * 更新文章 50 | * @param updateArticleReqVO 51 | * @return 52 | */ 53 | Response updateArticle(UpdateArticleReqVO updateArticleReqVO); 54 | } 55 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/domain/mapper/ArticleContentMapper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.domain.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; 5 | import com.quanxiaoha.weblog.common.domain.dos.ArticleContentDO; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-08-22 17:06 11 | * @description: 文章 12 | **/ 13 | public interface ArticleContentMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据文章 ID 删除记录 17 | * @param articleId 18 | * @return 19 | */ 20 | default int deleteByArticleId(Long articleId) { 21 | return delete(Wrappers.lambdaQuery() 22 | .eq(ArticleContentDO::getArticleId, articleId)); 23 | } 24 | 25 | /** 26 | * 根据文章 ID 查询 27 | * @param articleId 28 | * @return 29 | */ 30 | default ArticleContentDO selectByArticleId(Long articleId) { 31 | return selectOne(Wrappers.lambdaQuery() 32 | .eq(ArticleContentDO::getArticleId, articleId)); 33 | } 34 | 35 | /** 36 | * 通过文章 ID 更新 37 | * @param articleContentDO 38 | */ 39 | default int updateByArticleId(ArticleContentDO articleContentDO) { 40 | return update(articleContentDO, 41 | Wrappers.lambdaQuery() 42 | .eq(ArticleContentDO::getArticleId, articleContentDO.getArticleId())); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | spring: 4 | datasource: 5 | # 指定数据库驱动类 6 | driver-class-name: com.mysql.cj.jdbc.Driver 7 | # 数据库连接信息 8 | url: jdbc:mysql://172.17.0.1:3306/weblog?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull 9 | username: root 10 | password: root 11 | hikari: # 数据库连接池使用 Hikari 12 | minimum-idle: 5 # 连接池中最小空闲连接数 13 | maximum-pool-size: 20 # 连接池中允许的最大连接数 14 | auto-commit: true # 是否自动提交事务 15 | idle-timeout: 30000 # 连接在连接池中闲置的最长时间,超过这个时间会被释放。 16 | pool-name: Weblog-HikariCP # 自定义连接池的名字 17 | max-lifetime: 1800000 # 连接在连接池中的最大存活时间,超过这个时间会被强制关闭。 18 | connection-timeout: 30000 # 连接的超时时间 19 | connection-test-query: SELECT 1 # 用于测试连接是否可用的SQL查询 20 | 21 | #================================================================= 22 | # log 日志 23 | #================================================================= 24 | logging: 25 | config: classpath:logback-weblog.xml 26 | 27 | #================================================================= 28 | # minio (上传图片需要,需配置成自己的地址) 29 | #================================================================= 30 | minio: 31 | endpoint: #endpoint 32 | accessKey: #accessKey 33 | secretKey: #secretKey 34 | bucketName: # bucketName 35 | 36 | #================================================================= 37 | # Lucene 全文检索 38 | #================================================================= 39 | lucene: 40 | indexDir: /app/weblog/lucene-index # lucene 索引存放的位置 -------------------------------------------------------------------------------- /weblog-vue3/src/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { getToken } from "@/composables/cookie" 3 | import { showMessage} from '@/composables/util' 4 | import { useUserStore } from '@/stores/user' 5 | 6 | // 创建 Axios 实例 7 | const instance = axios.create({ 8 | baseURL: "/api", // 你的 API 基础 URL 9 | timeout: 7000, // 请求超时时间 10 | }) 11 | 12 | 13 | // 添加请求拦截器 14 | instance.interceptors.request.use(function (config) { 15 | // 在发送请求之前做些什么 16 | const token = getToken() 17 | console.log('统一添加请求头中的 Token:' + token) 18 | 19 | // 当 token 不为空时 20 | if (token) { 21 | // 添加请求头, key 为 Authorization,value 值的前缀为 'Bearer ' 22 | config.headers['Authorization'] = 'Bearer ' + token 23 | } 24 | 25 | return config; 26 | }, function (error) { 27 | // 对请求错误做些什么 28 | return Promise.reject(error) 29 | }); 30 | 31 | // 添加响应拦截器 32 | instance.interceptors.response.use(function (response) { 33 | // 2xx 范围内的状态码都会触发该函数。 34 | // 对响应数据做点什么 35 | return response.data 36 | }, function (error) { 37 | // 超出 2xx 范围的状态码都会触发该函数。 38 | // 对响应错误做点什么 39 | let status = error.response.status 40 | 41 | // 状态码 401 42 | if (status == 401) { 43 | // 退出登录 44 | let userStore = useUserStore() 45 | userStore.logout() 46 | // 刷新页面 47 | location.reload() 48 | } 49 | 50 | // 若后台有错误提示就用提示文字,默认提示为 '请求失败' 51 | let errorMsg = error.response.data.message || '请求失败' 52 | // 弹错误提示 53 | showMessage(errorMsg, 'error') 54 | 55 | return Promise.reject(error) 56 | }) 57 | 58 | // 暴露出去 59 | export default instance; -------------------------------------------------------------------------------- /weblog-vue3/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | import AutoImport from 'unplugin-auto-import/vite' 7 | import Components from 'unplugin-vue-components/vite' 8 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 9 | import ViteCompressionPlugin from 'vite-plugin-compression' 10 | import importToCDN from 'vite-plugin-cdn-import' 11 | 12 | // https://vitejs.dev/config/ 13 | export default defineConfig({ 14 | server: { 15 | proxy: { 16 | '/api': { 17 | target: 'http://47.98.119.250:8080', 18 | changeOrigin: true, 19 | rewrite: (path) => path.replace(/^\/api/, ''), 20 | }, 21 | } 22 | }, 23 | plugins: [ 24 | vue(), 25 | AutoImport({ 26 | resolvers: [ElementPlusResolver()], 27 | }), 28 | Components({ 29 | resolvers: [ElementPlusResolver()], 30 | }), 31 | ViteCompressionPlugin({ 32 | filter: /\.(js|css)$/i, // 只压缩 js 和 css 文件 33 | threshold: 1024, // 只压缩大于 1KB 的文件 34 | algorithm: 'gzip', // 使用 gzip 算法 35 | ext: '.gz', // 压缩文件的扩展名 36 | }), 37 | importToCDN({ 38 | modules: [ 39 | { 40 | name: 'echarts', 41 | var: 'echarts', 42 | path: 'https://cdn.bootcdn.net/ajax/libs/echarts/5.4.2/echarts.min.js', 43 | }, 44 | ], 45 | }), 46 | ], 47 | resolve: { 48 | alias: { 49 | // 定义一个别名 '@',该别名对应于当前 JavaScript 模块文件所在目录下的 'src' 目录的绝对文件路径。 50 | '@': fileURLToPath(new URL('./src', import.meta.url)) 51 | } 52 | } 53 | }) 54 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/model/vo/blogsettings/UpdateBlogSettingsReqVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.model.vo.blogsettings; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.Email; 10 | import javax.validation.constraints.NotBlank; 11 | import javax.validation.constraints.NotNull; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023-09-15 14:07 17 | * @description: 博客基础信息修改 18 | **/ 19 | @Data 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Builder 23 | @ApiModel(value = " 博客基础信息修改 VO") 24 | public class UpdateBlogSettingsReqVO { 25 | 26 | @NotBlank(message = "博客 LOGO 不能为空") 27 | private String logo; 28 | 29 | @NotBlank(message = "博客名称不能为空") 30 | private String name; 31 | 32 | @NotBlank(message = "博客作者不能为空") 33 | private String author; 34 | 35 | @NotBlank(message = "博客介绍语不能为空") 36 | private String introduction; 37 | 38 | @NotBlank(message = "博客头像不能为空") 39 | private String avatar; 40 | 41 | private String githubHomepage; 42 | 43 | private String csdnHomepage; 44 | 45 | private String giteeHomepage; 46 | 47 | private String zhihuHomepage; 48 | 49 | @Email(message = "邮箱格式不正确") 50 | private String mail; 51 | 52 | @NotNull(message = "请设置评论敏感词过滤是否开启") 53 | private Boolean isCommentSensiWordOpen; 54 | 55 | @NotNull(message = "请设置评论审核是否开启") 56 | private Boolean isCommentExamineOpen; 57 | } 58 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/model/vo/article/FindArticleDetailRspVO.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.model.vo.article; 2 | 3 | import com.quanxiaoha.weblog.web.model.vo.tag.FindTagListRspVO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.time.LocalDateTime; 10 | import java.util.List; 11 | 12 | /** 13 | * @author: 木萨·塔布提 14 | * @url: blog.arnasoft.site 15 | * @date: 2023-09-15 14:07 16 | * @description: 文章详情 17 | **/ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Builder 22 | public class FindArticleDetailRspVO { 23 | /** 24 | * 文章标题 25 | */ 26 | private String title; 27 | /** 28 | * 文章正文(HTML) 29 | */ 30 | private String content; 31 | /** 32 | * 发布时间 33 | */ 34 | private LocalDateTime createTime; 35 | /** 36 | * 分类 ID 37 | */ 38 | private Long categoryId; 39 | /** 40 | * 分类名称 41 | */ 42 | private String categoryName; 43 | /** 44 | * 阅读量 45 | */ 46 | private Long readNum; 47 | /** 48 | * 标签集合 49 | */ 50 | private List tags; 51 | /** 52 | * 上一篇文章 53 | */ 54 | private FindPreNextArticleRspVO preArticle; 55 | /** 56 | * 下一篇文章 57 | */ 58 | private FindPreNextArticleRspVO nextArticle; 59 | /** 60 | * 总字数 61 | */ 62 | private Integer totalWords; 63 | /** 64 | * 阅读时长 65 | */ 66 | private String readTime; 67 | 68 | /** 69 | * 最后更新时间 70 | */ 71 | private LocalDateTime updateTime; 72 | } 73 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-admin/src/main/java/com/quanxiaoha/weblog/admin/schedule/InitPVRecordScheduledTask.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.admin.schedule; 2 | 3 | import com.quanxiaoha.weblog.common.domain.dos.StatisticsArticlePVDO; 4 | import com.quanxiaoha.weblog.common.domain.mapper.StatisticsArticlePVMapper; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.time.LocalDate; 11 | import java.time.LocalDateTime; 12 | 13 | /** 14 | * @author: 木萨·塔布提 15 | * @url: blog.arnasoft.site 16 | * @date: 2023/11/12 12:02 17 | * @description: 初始化 PV 访问量定时任务 18 | **/ 19 | @Component 20 | @Slf4j 21 | public class InitPVRecordScheduledTask { 22 | 23 | @Autowired 24 | private StatisticsArticlePVMapper articlePVMapper; 25 | 26 | @Scheduled(cron = "0 0 23 * * ?") // 每天晚间 23 点执行 27 | // @Scheduled(cron = "0 * * * * ?") // 每一分钟执行一次 28 | public void execute() { 29 | // 定时任务执行的业务逻辑 30 | log.info("==> 开始执行初始化明日 PV 访问量记录定时任务"); 31 | 32 | // 当日日期 33 | LocalDate currDate = LocalDate.now(); 34 | 35 | // 明日 36 | LocalDate tomorrowDate = currDate.plusDays(1); 37 | 38 | // 组装插入的记录 39 | StatisticsArticlePVDO articlePVDO = StatisticsArticlePVDO.builder() 40 | .pvDate(tomorrowDate) // 明日的文章 pv 访问量 41 | .pvCount(0L) // 默认阅读量为 0 42 | .createTime(LocalDateTime.now()) 43 | .updateTime(LocalDateTime.now()) 44 | .build(); 45 | 46 | articlePVMapper.insert(articlePVDO); 47 | log.info("==> 结束执行初始化明日 PV 访问量记录定时任务"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /weblog-vue3/src/components/FormDialog.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-jwt/src/main/java/com/quanxiaoha/weblog/jwt/handler/RestAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.jwt.handler; 2 | 3 | import com.quanxiaoha.weblog.common.enums.ResponseCodeEnum; 4 | import com.quanxiaoha.weblog.common.utils.Response; 5 | import com.quanxiaoha.weblog.jwt.utils.ResultUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.security.authentication.BadCredentialsException; 9 | import org.springframework.security.authentication.InsufficientAuthenticationException; 10 | import org.springframework.security.core.AuthenticationException; 11 | import org.springframework.security.web.AuthenticationEntryPoint; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.servlet.ServletException; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | import java.io.IOException; 18 | 19 | /** 20 | * @author: 木萨·塔布提 21 | * @url: blog.arnasoft.site 22 | * @date: 2023-08-27 17:27 23 | * @description: 用户未登录访问受保护的资源 24 | **/ 25 | @Slf4j 26 | @Component 27 | public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { 28 | 29 | @Override 30 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 31 | log.warn("用户未登录访问受保护的资源: ", authException); 32 | if (authException instanceof InsufficientAuthenticationException) { 33 | ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(ResponseCodeEnum.UNAUTHORIZED)); 34 | } 35 | 36 | ResultUtil.fail(response, HttpStatus.UNAUTHORIZED.value(), Response.fail(authException.getMessage())); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 一、项目介绍 4 | 5 | `Weblog` 项目就是完成一个完整的前后端分离的博客项目,包含服务端接口API,管理后台以及部署上线流程。这个项目主要介绍使用 `SpringBoot2.6 ` 开发一套完整的 RESTful 风格服务端接口 API 和使用 `Vue2` 开发管理后台。(本项目只给小伙伴学习使用的,不能做任何开源商业使用,请尊重作者-🔜[犬小哈](https://www.quanxiaoha.com/)) 6 | 7 | ### 1.1 项目展示 8 | 9 | - 前端线上展示地址:https://blog.arnasoft.site/#/ 10 | 11 | - 首页 12 | ![](./pic/home.png) 13 | 14 | - 详情页 15 | ![](./pic/detail.png) 16 | 17 | - 移动端 18 | ![](./pic/移动端首页.png) ![](./pic/移动端详情页.png) 19 | 20 | 21 | ## 二、使用项目 22 | 23 | ### 2.1 克隆项目 24 | 25 | ``` 26 | # 克隆项目代码 27 | 28 | git clone git@github.com:programmer-xiaosa/weblog.git 29 | ``` 30 | 31 | ### 2.2 项目部署 32 | 33 | 小伙伴们可以使用传统方式部署也可以使用 `docker jenkins` 自动化部署,推荐使用 `docker` 34 | 35 | - [Docker 教程](https://www.quanxiaoha.com/docker/docker-tutorial.html) 36 | - [Linux常用命令](https://www.quanxiaoha.com/linux-command/linux-shutdown.html) 37 | 38 | ## 三、FAQ 39 | 40 | 1. 没有yarn环境,npm 可以吗? 41 | 42 | > 答:可以的,建议使用 yarn,yarn 比 npm 速度快,主要是安装版本统一。 43 | 44 | 2. npm 下载依赖包失败,卡住? 45 | 46 | > 答:本项目采用的事vue3,建议使用 node版本是 v18.12.1.,小伙伴们可以使用 `n` 或者 `nvm` 来切换电脑上的node版本,这样可以使用多个版本的系统,不会冲突。 47 | 48 | 3. ... 更多问题请到 [Issues](https://github.com/programmer-xiaosa/weblog/issues)查阅,或者有问题请到 [Issues 提问](https://github.com/programmer-xiaosa/weblog/issues/new)。 49 | 4. 本项目学习[犬小哈老师](https://www.quanxiaoha.com/)的课程后开发的博客项目,代码基本跟源码一致,只做部分修改和优化,,修改和优化可以到生产环境看下,[点这里](https://blog.arnasoft.site/#/)。小伙伴们可以参考学习,希望大家多多支持犬小哈老师的课程,我个人认为犬小哈老师的图文教程是特别棒的,肯定会有收获 50 | 51 | ## License 52 | 53 | [MIT](https://github.com/programmer-xiaosa/Weblog/blob/main/LICENSE), by [programmer-xiaosa](https://github.com/programmer-xiaosa/Weblog/commits?author=programmer-xiaosa) 54 | 55 | 喜欢或对你有帮助的话,请你点一个星星 star 鼓励我,或者您有更好的建议和意见,请提出来告知我,可以留言 [Issues](https://github.com/programmer-xiaosa/weblog/issues/new)。希望能够帮助到你学习!Thanks -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/enums/ResponseCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.enums; 2 | 3 | import com.quanxiaoha.weblog.common.exception.BaseExceptionInterface; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | /** 8 | * @author: 木萨·塔布提 9 | * @url: blog.arnasoft.site 10 | * @date: 2023-08-15 10:33 11 | * @description: 响应异常码 12 | **/ 13 | @Getter 14 | @AllArgsConstructor 15 | public enum ResponseCodeEnum implements BaseExceptionInterface { 16 | 17 | // ----------- 通用异常状态码 ----------- 18 | SYSTEM_ERROR("10000", "出错啦,后台小哥正在努力修复中..."), 19 | PARAM_NOT_VALID("10001", "参数错误"), 20 | 21 | 22 | // ----------- 业务异常状态码 ----------- 23 | LOGIN_FAIL("20000", "登录失败"), 24 | USERNAME_OR_PWD_ERROR("20001", "用户名或密码错误"), 25 | UNAUTHORIZED("20002", "无访问权限,请先登录!"), 26 | USERNAME_NOT_FOUND("20003", "该用户不存在"), 27 | FORBIDDEN("20004", "演示账号仅支持查询操作!"), 28 | CATEGORY_NAME_IS_EXISTED("20005", "该分类已存在,请勿重复添加!"), 29 | TAG_CANT_DUPLICATE("20006", "请勿添加表中已存在的标签!"), 30 | TAG_NOT_EXISTED("20007", "该标签不存在!"), 31 | FILE_UPLOAD_FAILED("20008", "文件上传失败!"), 32 | CATEGORY_NOT_EXISTED("20009", "提交的分类不存在!"), 33 | ARTICLE_NOT_FOUND("20010", "该文章不存在!"), 34 | CATEGORY_CAN_NOT_DELETE("20011", "该分类下包含文章,请先删除对应文章,才能删除!"), 35 | TAG_CAN_NOT_DELETE("20012", "该标签下包含文章,请先删除对应文章,才能删除!"), 36 | WIKI_NOT_FOUND("20013", "该知识库不存在"), 37 | NOT_QQ_NUMBER("20014", "QQ 号格式不正确"), 38 | COMMENT_CONTAIN_SENSITIVE_WORD("20015", "评论内容中包含敏感词,请重新编辑后再提交"), 39 | COMMENT_WAIT_EXAMINE("20016", "评论已提交, 等待博主审核通过"), 40 | COMMENT_NOT_FOUND("20017", "该评论不存在"), 41 | COMMENT_STATUS_NOT_WAIT_EXAMINE("20018", "该评论未处于待审核状态"), 42 | ; 43 | 44 | // 异常码 45 | private String errorCode; 46 | // 错误信息 47 | private String errorMessage; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-web/src/main/java/com/quanxiaoha/weblog/web/config/ToolGoodConfig.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.web.config; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.io.ResourceLoader; 9 | import toolgood.words.IllegalWordsSearch; 10 | 11 | import java.io.BufferedReader; 12 | import java.io.IOException; 13 | import java.io.InputStreamReader; 14 | import java.util.List; 15 | 16 | /** 17 | * @Author: 木萨·塔布提 18 | * @Date: 2024/4/3 21:06 19 | * @Version: v1.0.0 20 | * @Description: TODO 21 | **/ 22 | @Configuration 23 | @Slf4j 24 | public class ToolGoodConfig { 25 | 26 | @Bean 27 | public IllegalWordsSearch illegalWordsSearch(ResourceLoader resourceLoader) throws IOException { 28 | log.info("==> 开始初初始化敏感词工具类 ..."); 29 | IllegalWordsSearch illegalWordsSearch = new IllegalWordsSearch(); 30 | 31 | log.info("==> 加载敏感词 txt 文件 ..."); 32 | // 读取 /resource 目录下的敏感词 txt 文件 33 | List sensitiveWords = Lists.newArrayList(); 34 | try (BufferedReader reader = new BufferedReader( 35 | new InputStreamReader(resourceLoader.getResource("classpath:word/sensi_words.txt").getInputStream()))) { 36 | String line; 37 | while ((line = reader.readLine()) != null) { 38 | if (StringUtils.isNotBlank(line.trim())) { 39 | sensitiveWords.add(line.trim()); 40 | } 41 | } 42 | } 43 | 44 | // 设置敏感词 45 | illegalWordsSearch.SetKeywords(sensitiveWords); 46 | log.info("==> 初始化敏感词工具类成功 ..."); 47 | return illegalWordsSearch; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /weblog-springboot/weblog-module-common/src/main/java/com/quanxiaoha/weblog/common/mail/MailHelper.java: -------------------------------------------------------------------------------- 1 | package com.quanxiaoha.weblog.common.mail; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.autoconfigure.mail.MailProperties; 6 | import org.springframework.mail.javamail.JavaMailSender; 7 | import org.springframework.mail.javamail.MimeMessageHelper; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.mail.internet.MimeMessage; 11 | 12 | /** 13 | * @Author: 木萨·塔布提 14 | * @Date: 2024/4/3 21:40 15 | * @Version: v1.0.0 16 | * @Description: TODO 17 | **/ 18 | @Component 19 | @Slf4j 20 | public class MailHelper { 21 | 22 | @Autowired 23 | private MailProperties mailProperties; 24 | @Autowired 25 | private JavaMailSender javaMailSender; 26 | 27 | public boolean sendHtml(String to, String title, String html) { 28 | log.info("==> 开始发送邮件 ..."); 29 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 30 | 31 | MimeMessageHelper mimeMessageHelper = null; 32 | try { 33 | mimeMessageHelper = new MimeMessageHelper(mimeMessage, true); 34 | // 邮件发送来源 35 | mimeMessageHelper.setFrom(mailProperties.getUsername()); 36 | // 邮件发送目标 37 | mimeMessageHelper.setTo(to); 38 | // 设置标题 39 | mimeMessageHelper.setSubject(title); 40 | // 设置内容,内容是否为 html 格式,值为 true 41 | mimeMessageHelper.setText(html, true); 42 | 43 | javaMailSender.send(mimeMessage); 44 | log.info("==> 邮件发送成功, to: {}, title: {}, content: {}", to, title, html); 45 | } catch (Exception e) { 46 | log.error("==> 发送邮件异常: ", e); 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | } 53 | --------------------------------------------------------------------------------