├── .github └── ISSUE_TEMPLATE │ ├── ✨-新功能建议.md │ ├── 系统问题解答.md │ └── 🐞-bug反馈.md ├── .gitignore ├── LICENSE ├── README.md ├── blog.sql ├── client ├── env │ ├── .env │ ├── .env.development │ └── index.js ├── next-env.d.ts ├── next.config.ts ├── package.json ├── postcss.config.js ├── prettier.config.js ├── public │ ├── favicon.ico │ ├── favicon.svg │ ├── icon │ │ ├── admin │ │ │ ├── QQ.svg │ │ │ ├── fork.svg │ │ │ ├── github.svg │ │ │ ├── homepage.svg │ │ │ ├── issues.svg │ │ │ ├── star.svg │ │ │ ├── watch.svg │ │ │ ├── 数据看板.svg │ │ │ └── 邮箱.svg │ │ └── client │ │ │ ├── briefcase.png │ │ │ ├── collection-blue.png │ │ │ ├── collection-fill.png │ │ │ ├── collection.png │ │ │ ├── comment.png │ │ │ ├── comments.png │ │ │ ├── delete-fill.png │ │ │ ├── delete.png │ │ │ ├── drafts.svg │ │ │ ├── email-fill.png │ │ │ ├── email.png │ │ │ ├── emoji.png │ │ │ ├── github-fill.png │ │ │ ├── github.png │ │ │ ├── likes-fill.png │ │ │ ├── likes.png │ │ │ ├── picture.png │ │ │ ├── police.png │ │ │ ├── postcard.png │ │ │ ├── problem-collection-black.png │ │ │ ├── problem-collection-white.png │ │ │ ├── problem-follow-black.png │ │ │ ├── problem-follow-white.png │ │ │ ├── problem-like-black.png │ │ │ ├── problem-like-white.png │ │ │ ├── problem.svg │ │ │ ├── qq.png │ │ │ ├── share.png │ │ │ ├── small-bell.png │ │ │ ├── unit.png │ │ │ ├── view-blue.png │ │ │ ├── view-white.png │ │ │ ├── view.png │ │ │ ├── website.png │ │ │ ├── wechat.png │ │ │ └── write-article.svg │ ├── image │ │ ├── admin │ │ │ ├── bg.svg │ │ │ └── statistics │ │ │ │ ├── bg.jpg │ │ │ │ ├── border_bg.jpg │ │ │ │ ├── title_left_bg.png │ │ │ │ └── title_right_bg.png │ │ └── client │ │ │ ├── collection-bg.jpg │ │ │ ├── github.jpg │ │ │ ├── load-error.png │ │ │ ├── qq-qrcode.jpg │ │ │ └── wechat-qrcode.jpg │ ├── robots-template.txt │ └── vditor │ │ ├── ant.js │ │ ├── github.min.css │ │ ├── highlight.min.js │ │ ├── light.css │ │ ├── lute.min.js │ │ ├── third-languages.js │ │ └── zh_CN.js ├── scripts │ └── build-output │ │ ├── index.js │ │ └── nodemon.json ├── src │ ├── app │ │ ├── (main) │ │ │ └── page.tsx │ │ ├── (route) │ │ │ ├── ads.txt │ │ │ │ └── route.ts │ │ │ ├── sitemap │ │ │ │ └── [type] │ │ │ │ │ ├── index.xml │ │ │ │ │ └── route.tsx │ │ │ │ │ └── index[index].xml │ │ │ │ │ └── route.tsx │ │ │ └── static │ │ │ │ ├── antd │ │ │ │ └── [name] │ │ │ │ │ └── route.tsx │ │ │ │ ├── editor │ │ │ │ └── [...path] │ │ │ │ │ └── route.tsx │ │ │ │ ├── high-light │ │ │ │ └── [type] │ │ │ │ │ └── route.tsx │ │ │ │ └── theme │ │ │ │ └── [id] │ │ │ │ └── route.tsx │ │ ├── admin │ │ │ ├── [...all] │ │ │ │ └── page.tsx │ │ │ ├── advertisement │ │ │ │ ├── [id] │ │ │ │ │ └── page.tsx │ │ │ │ ├── list │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── article │ │ │ │ ├── [id] │ │ │ │ │ └── page.tsx │ │ │ │ ├── list │ │ │ │ │ └── page.tsx │ │ │ │ └── write │ │ │ │ │ └── page.tsx │ │ │ ├── comment │ │ │ │ └── page.tsx │ │ │ ├── external-link │ │ │ │ └── page.tsx │ │ │ ├── friendly-link │ │ │ │ ├── create │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── login │ │ │ │ └── page.tsx │ │ │ ├── oss │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ ├── statistics │ │ │ │ └── page.tsx │ │ │ ├── theme │ │ │ │ ├── create │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── type │ │ │ │ ├── page.tsx │ │ │ │ ├── tag │ │ │ │ │ └── [id] │ │ │ │ │ │ └── page.tsx │ │ │ │ └── type │ │ │ │ │ └── [id] │ │ │ │ │ └── page.tsx │ │ │ └── user │ │ │ │ ├── [id] │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ ├── article │ │ │ ├── [id] │ │ │ │ ├── (main) │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── not-found.tsx │ │ │ └── editor │ │ │ │ ├── [id] │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ ├── collection │ │ │ └── [id] │ │ │ │ ├── not-found.tsx │ │ │ │ └── page.tsx │ │ ├── creator │ │ │ ├── content │ │ │ │ ├── article │ │ │ │ │ └── page.tsx │ │ │ │ └── problem │ │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ ├── error.tsx │ │ ├── forget-password │ │ │ └── page.tsx │ │ ├── friendly-link │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── link │ │ │ └── page.tsx │ │ ├── not-found.tsx │ │ ├── notification │ │ │ ├── [type] │ │ │ │ └── page.tsx │ │ │ └── page.tsx │ │ ├── oauth │ │ │ └── github │ │ │ │ └── page.tsx │ │ ├── problem │ │ │ ├── (main) │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ ├── [id] │ │ │ │ ├── (main) │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── not-found.tsx │ │ │ └── editor │ │ │ │ ├── [id] │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ ├── result │ │ │ └── page.tsx │ │ ├── robots.ts │ │ ├── search │ │ │ └── page.tsx │ │ ├── sitemap │ │ │ └── [type] │ │ │ │ └── page.tsx │ │ ├── tag │ │ │ └── article │ │ │ │ └── [id] │ │ │ │ └── page.tsx │ │ ├── theme │ │ │ └── page.tsx │ │ └── user │ │ │ ├── [id] │ │ │ └── page.tsx │ │ │ └── settings │ │ │ ├── account │ │ │ └── page.tsx │ │ │ ├── destroy │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ └── profile │ │ │ └── page.tsx │ ├── common │ │ ├── hooks │ │ │ ├── useComputed.ts │ │ │ ├── useFetch.tsx │ │ │ ├── useGetRawPath.tsx │ │ │ └── useWatchEffect.tsx │ │ ├── modules │ │ │ ├── cookie │ │ │ │ └── index.ts │ │ │ ├── readingRecords │ │ │ │ ├── index.ts │ │ │ │ ├── redis.ts │ │ │ │ ├── setReferer.ts │ │ │ │ └── setSpider.ts │ │ │ └── sitemap │ │ │ │ ├── sitemap-index.ts │ │ │ │ └── sitemap.ts │ │ └── utils │ │ │ ├── HtmlToMarkDown.ts │ │ │ └── vw.ts │ ├── components │ │ ├── admin │ │ │ ├── common │ │ │ │ ├── Footer │ │ │ │ │ └── index.tsx │ │ │ │ └── Header │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── items.tsx │ │ │ └── page │ │ │ │ ├── advertisement │ │ │ │ └── AdvertisementForm.tsx │ │ │ │ ├── article │ │ │ │ └── list │ │ │ │ │ ├── Header.tsx │ │ │ │ │ └── Table.tsx │ │ │ │ ├── index │ │ │ │ └── notice.tsx │ │ │ │ ├── statistics │ │ │ │ ├── Bottom │ │ │ │ │ ├── Occupation.tsx │ │ │ │ │ ├── Referer.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Container │ │ │ │ │ └── index.tsx │ │ │ │ ├── Statistics.tsx │ │ │ │ └── Top │ │ │ │ │ ├── Article.tsx │ │ │ │ │ ├── ArticleRanking.tsx │ │ │ │ │ ├── Header │ │ │ │ │ ├── HeaderItem.tsx │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Visits.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── theme │ │ │ │ └── CodeEdite.tsx │ │ │ │ └── type │ │ │ │ ├── AddTagModal.tsx │ │ │ │ ├── AddTypeModal.tsx │ │ │ │ ├── TagForm.tsx │ │ │ │ └── TypeForm.tsx │ │ ├── common │ │ │ ├── AdSense │ │ │ │ ├── ADS.tsx │ │ │ │ └── index.tsx │ │ │ ├── Advertisement │ │ │ │ └── index.tsx │ │ │ ├── ArticleEditor │ │ │ │ ├── DraftsButton.tsx │ │ │ │ ├── Modal │ │ │ │ │ ├── Cover.tsx │ │ │ │ │ ├── Reprint.tsx │ │ │ │ │ ├── Type.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── ArticleList │ │ │ │ ├── ArticleItem.tsx │ │ │ │ ├── Cover.tsx │ │ │ │ ├── index.module.scss │ │ │ │ └── index.tsx │ │ │ ├── Avatar │ │ │ │ ├── Menu.tsx │ │ │ │ └── index.tsx │ │ │ ├── BackTop │ │ │ │ └── index.tsx │ │ │ ├── CollectionModal │ │ │ │ ├── CreateFrom.tsx │ │ │ │ ├── List.tsx │ │ │ │ └── index.tsx │ │ │ ├── CreateTheme │ │ │ │ └── index.tsx │ │ │ ├── Editor │ │ │ │ ├── LanguageListPlugin.tsx │ │ │ │ ├── Skeleton.tsx │ │ │ │ ├── StyleLink.tsx │ │ │ │ ├── VditorEditor.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ └── upload.ts │ │ │ ├── Header │ │ │ │ ├── Navigation.tsx │ │ │ │ ├── News.tsx │ │ │ │ ├── Search.tsx │ │ │ │ ├── Sign │ │ │ │ │ ├── ForgetPassword │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── LogIn │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── LogOn │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── User │ │ │ │ │ ├── NotLogin │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── UserData │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── UpLoad │ │ │ │ ├── Image.tsx │ │ │ │ ├── Modal.tsx │ │ │ │ ├── getCroppedImg.ts │ │ │ │ ├── index.tsx │ │ │ │ └── upload.ts │ │ │ └── _Editor │ │ │ │ ├── Editor.tsx │ │ │ │ ├── MarkDownEditor │ │ │ │ ├── LanguageListPlugin.tsx │ │ │ │ ├── ThemeSelect.tsx │ │ │ │ ├── UseRichTextPlugin.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── RichTextEditor │ │ │ │ ├── CodeEditor.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── StyleLink.tsx │ │ │ │ ├── index.scss │ │ │ │ ├── index.tsx │ │ │ │ └── upload.ts │ │ ├── next │ │ │ ├── ActiveLink.tsx │ │ │ ├── Head.tsx │ │ │ ├── Image.tsx │ │ │ └── NoFollowLink.tsx │ │ └── page │ │ │ ├── article │ │ │ ├── Aside │ │ │ │ ├── Catalogue │ │ │ │ │ ├── Catalogue.tsx │ │ │ │ │ ├── index.module.scss │ │ │ │ │ └── index.tsx │ │ │ │ ├── Repository │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ ├── Comments │ │ │ │ ├── Comment │ │ │ │ │ ├── Item.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── Editor.tsx │ │ │ │ └── index.tsx │ │ │ ├── ImagePreview │ │ │ │ ├── index.module.scss │ │ │ │ └── index.tsx │ │ │ ├── Layout.tsx │ │ │ ├── NoFound.tsx │ │ │ ├── Recommend.tsx │ │ │ ├── Reprint.tsx │ │ │ ├── Store.tsx │ │ │ ├── ToolBar │ │ │ │ ├── Collection │ │ │ │ │ └── index.tsx │ │ │ │ ├── Comment.tsx │ │ │ │ ├── Like.tsx │ │ │ │ ├── Share.tsx │ │ │ │ ├── class.ts │ │ │ │ └── index.tsx │ │ │ ├── UserData │ │ │ │ ├── FollowButton.tsx │ │ │ │ └── index.tsx │ │ │ ├── View │ │ │ │ └── index.tsx │ │ │ └── editor │ │ │ │ └── ArticleRemoveWarn.tsx │ │ │ ├── collection │ │ │ ├── Brow.tsx │ │ │ ├── Collection.tsx │ │ │ ├── FavoritesModal.tsx │ │ │ └── ToolsBar.tsx │ │ │ ├── creator │ │ │ ├── ArticleList │ │ │ │ ├── ArticleListItem.tsx │ │ │ │ └── index.tsx │ │ │ └── Layout │ │ │ │ ├── Aside.tsx │ │ │ │ ├── Header.tsx │ │ │ │ └── index.tsx │ │ │ ├── friendly-link │ │ │ └── FriendlyLink.tsx │ │ │ ├── index │ │ │ ├── Footer.tsx │ │ │ ├── Layout.tsx │ │ │ ├── Ranking │ │ │ │ ├── AuthorRanking.tsx │ │ │ │ ├── FunsRanking.tsx │ │ │ │ ├── RankingList.tsx │ │ │ │ └── index.tsx │ │ │ ├── SortSelect │ │ │ │ └── index.tsx │ │ │ ├── TypeHeader │ │ │ │ └── index.tsx │ │ │ ├── index.module.scss │ │ │ └── index.tsx │ │ │ ├── notification │ │ │ ├── Layout.tsx │ │ │ └── Notice │ │ │ │ ├── Answer.tsx │ │ │ │ ├── Comment.tsx │ │ │ │ ├── Follow.tsx │ │ │ │ └── index.tsx │ │ │ ├── problem │ │ │ ├── Answer │ │ │ │ └── index.tsx │ │ │ ├── Aside.tsx │ │ │ ├── Comments │ │ │ │ ├── Editor.tsx │ │ │ │ ├── Item.tsx │ │ │ │ └── index.tsx │ │ │ ├── Editor │ │ │ │ ├── Message.tsx │ │ │ │ └── index.tsx │ │ │ ├── Layout.tsx │ │ │ ├── List │ │ │ │ ├── Item.tsx │ │ │ │ └── index.tsx │ │ │ ├── NoFound.tsx │ │ │ ├── ProblemDetail.tsx │ │ │ ├── ProblemList.tsx │ │ │ ├── ToolBar │ │ │ │ └── index.tsx │ │ │ └── write │ │ │ │ └── Tag.tsx │ │ │ ├── tag │ │ │ ├── Layout.tsx │ │ │ └── List.tsx │ │ │ └── user │ │ │ ├── index │ │ │ ├── NotFind.tsx │ │ │ └── UserData │ │ │ │ ├── Aside │ │ │ │ └── index.tsx │ │ │ │ ├── Header │ │ │ │ ├── FollowButton.tsx │ │ │ │ └── index.tsx │ │ │ │ ├── Main │ │ │ │ ├── Favorites │ │ │ │ │ ├── Modal.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── FollowList │ │ │ │ │ ├── FollowButton.tsx │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ └── setting │ │ │ ├── UpdateEmailModal.tsx │ │ │ ├── UpdatePasswordModal.tsx │ │ │ └── UploadAvatar │ │ │ └── index.tsx │ ├── layout │ │ ├── Admin │ │ │ └── Base.tsx │ │ ├── Base │ │ │ └── index.tsx │ │ ├── Content │ │ │ ├── HightLight │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── Main │ │ │ └── index.tsx │ │ └── Sidebar │ │ │ └── index.tsx │ ├── plugin │ │ ├── antd.tsx │ │ ├── axios.ts │ │ └── dayjs.ts │ ├── request │ │ ├── advertisement.ts │ │ ├── article │ │ │ └── article-list.ts │ │ ├── collection │ │ │ ├── collection.ts │ │ │ ├── index.ts │ │ │ └── uncollection.ts │ │ ├── follow │ │ │ ├── follow.ts │ │ │ ├── index.ts │ │ │ └── unfollow.ts │ │ ├── like │ │ │ ├── index.ts │ │ │ ├── like.ts │ │ │ └── unlike.ts │ │ ├── load-static.ts │ │ └── type │ │ │ ├── getTag.ts │ │ │ ├── getTagArticleLData.ts │ │ │ └── type-tree-index.ts │ ├── store │ │ ├── admin │ │ │ ├── admin-article-list │ │ │ │ └── index.ts │ │ │ ├── admin-search-option │ │ │ │ └── index.ts │ │ │ ├── admin-statistics-data │ │ │ │ ├── index.tsx │ │ │ │ └── store.ts │ │ │ └── admin-table-option │ │ │ │ └── index.ts │ │ ├── common │ │ │ └── editor-mode │ │ │ │ └── index.ts │ │ └── user │ │ │ ├── user-article-comment │ │ │ └── index.ts │ │ │ ├── user-current-article-data │ │ │ └── index.ts │ │ │ ├── user-data │ │ │ ├── index.tsx │ │ │ └── store.ts │ │ │ ├── user-sign-model-state │ │ │ └── index.ts │ │ │ └── user-write-article │ │ │ └── index.ts │ └── styles │ │ ├── content.module.scss │ │ ├── genAntdCss.tsx │ │ ├── globals.scss │ │ └── reset.css ├── tailwind.config.js ├── tsconfig.json ├── types │ ├── common │ │ ├── response.ts │ │ └── user-data.ts │ ├── folder.ts │ ├── index.d.ts │ ├── model-attribute.ts │ ├── model │ │ ├── advertisement.ts │ │ ├── article-comment.ts │ │ ├── article-list-item.ts │ │ ├── favorites-collection-list.ts │ │ └── problem.ts │ ├── response.ts │ ├── statistics-type.ts │ └── type.ts └── yarn.lock ├── dev.bat ├── intall.bat ├── lint.bat └── server ├── ecosystem.config.js ├── env └── .env.template ├── package.json ├── prettier.config.js ├── public ├── prism.zip └── robots.txt ├── scripts ├── build.ts ├── dev │ └── index.ts ├── modules │ ├── compile.ts │ ├── copyDir.ts │ ├── countFile.ts │ └── deleteDir.ts └── start.ts ├── src ├── app.ts ├── common │ ├── middleware │ │ ├── auth │ │ │ ├── getUserId.ts │ │ │ └── index.ts │ │ ├── cache │ │ │ └── index.ts │ │ └── verify │ │ │ ├── validator.ts │ │ │ └── validatorAsync.ts │ ├── modules │ │ ├── article │ │ │ ├── get │ │ │ │ ├── external-link.ts │ │ │ │ ├── html-to-markdown.ts │ │ │ │ ├── img-add-prefix.ts │ │ │ │ ├── set-code-block-language.ts │ │ │ │ ├── set-description.ts │ │ │ │ ├── set-tag-data.ts │ │ │ │ └── set-title-id.ts │ │ │ └── select │ │ │ │ ├── getBloggerList.ts │ │ │ │ ├── getTypeChildrenTag.ts │ │ │ │ ├── option.ts │ │ │ │ └── search.ts │ │ ├── cache │ │ │ ├── advertisement │ │ │ │ └── index.ts │ │ │ ├── email │ │ │ │ └── index.ts │ │ │ ├── external-link │ │ │ │ └── index.ts │ │ │ └── type │ │ │ │ └── index.ts │ │ ├── comment │ │ │ └── get-comment-childrnen-list.ts │ │ ├── getAllRouter.ts │ │ ├── getFilePath.ts │ │ ├── github │ │ │ ├── getGithubName.ts │ │ │ └── updata.ts │ │ ├── notice │ │ │ ├── answer.ts │ │ │ ├── comment │ │ │ │ ├── comment-answer.ts │ │ │ │ ├── comment-article.ts │ │ │ │ └── comment-problem.ts │ │ │ ├── follow │ │ │ │ ├── follow-article.ts │ │ │ │ └── follow-problem.ts │ │ │ └── index.ts │ │ ├── tasks │ │ │ ├── set-recommend-data.ts │ │ │ └── sortArticleList.ts │ │ └── user │ │ │ ├── destroy.ts │ │ │ └── isEmailDestroy.ts │ ├── tasks │ │ ├── advertisement.ts │ │ ├── auto-delete-recommend.ts │ │ ├── friendly-link-response-time.ts │ │ ├── index.ts │ │ ├── oss │ │ │ └── delete-redis-cache.ts │ │ ├── ranking │ │ │ └── index.ts │ │ ├── recommend │ │ │ ├── cache-recommend-data.ts │ │ │ └── index.ts │ │ ├── set-article-view-count.ts │ │ └── visualization │ │ │ ├── github.ts │ │ │ ├── history.ts │ │ │ └── load.ts │ ├── transaction │ │ ├── answer │ │ │ ├── create.ts │ │ │ └── delete.ts │ │ ├── article │ │ │ ├── create-article.ts │ │ │ └── delete-article.ts │ │ ├── comment │ │ │ ├── create-comment.ts │ │ │ └── delete-comment.ts │ │ ├── follow │ │ │ └── unfollow │ │ │ │ ├── index.ts │ │ │ │ ├── problem.ts │ │ │ │ └── user.ts │ │ └── problem │ │ │ ├── adopt.ts │ │ │ ├── cancel.ts │ │ │ └── delete.ts │ ├── utils │ │ ├── auth │ │ │ ├── destroy-session.ts │ │ │ ├── sign-jwt.ts │ │ │ ├── sign-session.ts │ │ │ ├── sign.ts │ │ │ ├── verify-jwt.ts │ │ │ ├── verify-session.ts │ │ │ └── verify.ts │ │ ├── email │ │ │ └── index.ts │ │ ├── id.ts │ │ ├── map.ts │ │ ├── random.ts │ │ ├── redis.ts │ │ ├── sha256.ts │ │ ├── sleep.ts │ │ ├── static │ │ │ ├── ali │ │ │ │ ├── deleteFile.ts │ │ │ │ ├── exist.ts │ │ │ │ ├── imageInfo.ts │ │ │ │ ├── listPrefix.ts │ │ │ │ ├── refreshUrls.ts │ │ │ │ ├── upload.ts │ │ │ │ └── utils │ │ │ │ │ └── oss.ts │ │ │ ├── folderList.ts │ │ │ ├── index.ts │ │ │ └── qiniu │ │ │ │ ├── deleteFile.ts │ │ │ │ ├── exist.ts │ │ │ │ ├── imageInfo.ts │ │ │ │ ├── listPrefix.ts │ │ │ │ ├── refreshUrls.ts │ │ │ │ ├── upload.ts │ │ │ │ └── utils │ │ │ │ ├── Mac.ts │ │ │ │ ├── bucketManager.ts │ │ │ │ └── zone.ts │ │ └── xss │ │ │ ├── article.ts │ │ │ └── comment.ts │ └── verify │ │ ├── api-verify │ │ ├── advertisement │ │ │ └── create-update.ts │ │ ├── answer │ │ │ ├── create.ts │ │ │ ├── delete.ts │ │ │ ├── problem-md.ts │ │ │ └── update.ts │ │ ├── article │ │ │ ├── common.module.ts │ │ │ ├── create-article.ts │ │ │ ├── list.ts │ │ │ ├── search.ts │ │ │ └── update-article.ts │ │ ├── collection │ │ │ ├── create.ts │ │ │ └── update.ts │ │ ├── comment │ │ │ └── create.ts │ │ ├── external-link │ │ │ └── create.ts │ │ ├── favorites │ │ │ └── create.ts │ │ ├── follow │ │ │ └── create │ │ │ │ ├── index.ts │ │ │ │ └── map.ts │ │ ├── friendly-link │ │ │ └── create.ts │ │ ├── like │ │ │ └── create.ts │ │ ├── problem │ │ │ ├── adopt.ts │ │ │ ├── cancel.ts │ │ │ ├── create.ts │ │ │ ├── list.ts │ │ │ ├── questions.ts │ │ │ └── update.ts │ │ ├── theme │ │ │ ├── create.ts │ │ │ ├── remove.ts │ │ │ └── update.ts │ │ └── user │ │ │ └── update.ts │ │ ├── integer.ts │ │ └── modules │ │ ├── file-name.ts │ │ ├── tag.ts │ │ ├── type.ts │ │ └── url.ts ├── db │ ├── config │ │ └── index.ts │ ├── hooks │ │ ├── advertisement.ts │ │ ├── external-link.ts │ │ ├── type.ts │ │ └── utils │ │ │ └── init.ts │ ├── index.ts │ ├── models │ │ ├── advertisement.ts │ │ ├── answer.ts │ │ ├── article.ts │ │ ├── article_tag.ts │ │ ├── collection.ts │ │ ├── comment.ts │ │ ├── external_link.ts │ │ ├── favorites.ts │ │ ├── follow.ts │ │ ├── friendly_link.ts │ │ ├── init-models.ts │ │ ├── likes.ts │ │ ├── notice.ts │ │ ├── problem.ts │ │ ├── recommend.ts │ │ ├── tag.ts │ │ ├── theme.ts │ │ └── user.ts │ └── utils │ │ └── stringArrayReplace.ts ├── index.ts ├── routes │ ├── advertisement │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── get-all.ts │ │ ├── id.ts │ │ └── update.ts │ ├── answer │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── problem-md.ts │ │ └── update.ts │ ├── article │ │ ├── create.ts │ │ ├── delete-article.ts │ │ ├── get-data │ │ │ ├── article-list-search.ts │ │ │ ├── article-list-tag.ts │ │ │ ├── article-list.ts │ │ │ ├── get-id.ts │ │ │ └── get-list-page.ts │ │ ├── recommend.ts │ │ └── update.ts │ ├── auth │ │ └── github.ts │ ├── collection │ │ ├── collection-state.ts │ │ ├── collection-user-list.ts │ │ ├── create.ts │ │ ├── delete-favorites.ts │ │ ├── delete.ts │ │ ├── favorites-list.ts │ │ └── update.ts │ ├── comment │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── list-article.ts │ │ ├── list.ts │ │ └── review.ts │ ├── external-link │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── find.ts │ │ └── list.ts │ ├── favorites │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── id.ts │ │ ├── list.ts │ │ └── update.ts │ ├── follow │ │ ├── follow.ts │ │ ├── followers-list.ts │ │ ├── following-list.ts │ │ ├── unfollow.ts │ │ └── user-follow-state.ts │ ├── friendly-link │ │ ├── adopt.ts │ │ ├── apply.ts │ │ ├── create.ts │ │ ├── delete.ts │ │ └── list.ts │ ├── high-light │ │ ├── high-light.ts │ │ └── language-list.ts │ ├── like │ │ ├── create.ts │ │ ├── delete.ts │ │ └── state.ts │ ├── notice │ │ ├── list-notice.ts │ │ ├── notice-count.ts │ │ └── update-notice.ts │ ├── problem │ │ ├── adopt.ts │ │ ├── cancel.ts │ │ ├── create.ts │ │ ├── delete.ts │ │ ├── list-user.ts │ │ ├── list.ts │ │ ├── questions.ts │ │ ├── read-update.ts │ │ └── update.ts │ ├── ranking │ │ ├── author.ts │ │ └── funs.ts │ ├── sitemap │ │ ├── index.ts │ │ ├── list-xml.ts │ │ └── list.ts │ ├── static │ │ └── upload-image.ts │ ├── statistics │ │ ├── index.ts │ │ └── visualization.ts │ ├── tag │ │ ├── create-tag.ts │ │ ├── delete-tag.ts │ │ ├── get-data-id.ts │ │ ├── list.ts │ │ ├── reception-tag-tree.ts │ │ └── update.ts │ ├── theme │ │ ├── create.ts │ │ ├── item.ts │ │ ├── list.ts │ │ ├── remove.ts │ │ └── update.ts │ └── user │ │ ├── destroy │ │ ├── destroy-id.ts │ │ ├── destroy.ts │ │ └── recovery.ts │ │ ├── forget-password │ │ ├── email-update.ts │ │ └── email.ts │ │ ├── get-data │ │ ├── achievement.ts │ │ ├── user-data.ts │ │ ├── user-info.ts │ │ └── user-list.ts │ │ ├── login │ │ └── email-password.ts │ │ ├── logon │ │ ├── email-link.ts │ │ └── logn-email-link.ts │ │ ├── tools │ │ └── location.ts │ │ └── update │ │ ├── email │ │ ├── email-link.ts │ │ └── email.ts │ │ ├── password.ts │ │ └── update.ts ├── socket │ ├── index.ts │ └── oss.ts └── views │ ├── forget-password.ejs │ ├── friendly-apply.ejs │ ├── friendly-fail.ejs │ ├── logn-up.ejs │ └── update-email.ejs ├── tsconfig.json ├── types ├── NodeJS │ └── index.d.ts ├── identicon.js │ └── index.d.ts ├── koa │ └── index.d.ts └── turndown-plugin-gfm │ └── index.d.ts └── yarn.lock /.github/ISSUE_TEMPLATE/✨-新功能建议.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "✨ 新功能建议" 3 | about: 建议出一个XX新功能 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/系统问题解答.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 系统问题解答 3 | about: 对于系统内的功能实现,你有什么不懂的可以再这里提问 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 1.管理系统、用户端、服务器哪里的哪个问题不懂 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/🐞-bug反馈.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41E BUG反馈" 3 | about: 反馈系统漏洞 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ** 环境 ** 11 | 1. 浏览器以及版本: 12 | 2. Node.js版本: 13 | 3. MySQL版本: 14 | 4. Redis版本: 15 | 16 | ** 报错情况 ** 17 | 18 | 19 | ** 我该如何复现 ** 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .next 4 | .idea 5 | .vscode 6 | .DS_Store 7 | *.local 8 | 9 | server/**/.env.development 10 | server/**/.env.production 11 | server/log 12 | server/blog_server 13 | 14 | client/env/.env.production -------------------------------------------------------------------------------- /client/env/.env: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_SITE_NAME=网络日志 2 | # 站长信息配置 3 | QQ=1974109227 4 | EMAIL=1974109227@qq.com 5 | GITHUB=https://github.com/Lrunlin 6 | ICP=辽ICP备2020014377号 7 | # Google ADS 8 | NEXT_PUBLIC_GOOGLE_ADS_CLIENT_ID=1577114276814290 9 | NEXT_PUBLIC_GOOGLE_ADS_SLOT=3214779798 10 | 11 | # 上传图片最大多MB 12 | UPLOAD_MAX_SIZE=5 13 | 14 | # 鉴权方式 15 | AUTH_MODE=session -------------------------------------------------------------------------------- /client/env/.env.development: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_HOST=http://localhost:5678 2 | NEXT_PUBLIC_API_HOST=http://localhost:3000 3 | NEXT_PUBLIC_GITHUB_CLIENT_ID=b1099c9c62ebb6ff2d87 4 | 5 | CDN=http://localhost:5678 6 | 7 | # Redis配置 8 | REDIS_HOST=localhost 9 | REDIS_USER= 10 | REDIS_POST=6379 11 | REDIS_PASSWORD="" 12 | 13 | -------------------------------------------------------------------------------- /client/env/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const dotenv = require("dotenv"); 4 | const md5 = require("md5"); 5 | const { globSync } = require("glob"); 6 | 7 | let envObject = dotenv.parse( 8 | `${fs.readFileSync(path.join(__dirname, "./.env"))} 9 | \n 10 | ${fs.readFileSync( 11 | path.join( 12 | __dirname, 13 | `./.env.${process.env.NEXT_PUBLIC_ISPRO ? "production" : "development"}`, 14 | ), 15 | )} 16 | `, 17 | ); 18 | 19 | module.exports = { 20 | buildid: () => { 21 | return md5( 22 | globSync(["src/**/*.*", "./**.js", "./**.json", "./**.ts", "./**.lock"]) 23 | .filter((item) => { 24 | const filePath = path.resolve(process.cwd(), item); 25 | return fs.existsSync(filePath) && fs.statSync(filePath).isFile(); 26 | }) 27 | .map((item) => { 28 | let str = fs.readFileSync(item).toString(); 29 | return md5(item + str); 30 | }) 31 | .join(""), 32 | ); 33 | }, 34 | env: envObject, 35 | }; 36 | -------------------------------------------------------------------------------- /client/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | // autoprefixer: {},//自动前缀 5 | ...(process.env.NEXT_PUBLIC_ISPRO 6 | ? { 7 | cssnano: {}, 8 | } 9 | : {}), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/icon/admin/QQ.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/icon/admin/fork.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/icon/admin/数据看板.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/public/icon/client/briefcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/briefcase.png -------------------------------------------------------------------------------- /client/public/icon/client/collection-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/collection-blue.png -------------------------------------------------------------------------------- /client/public/icon/client/collection-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/collection-fill.png -------------------------------------------------------------------------------- /client/public/icon/client/collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/collection.png -------------------------------------------------------------------------------- /client/public/icon/client/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/comment.png -------------------------------------------------------------------------------- /client/public/icon/client/comments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/comments.png -------------------------------------------------------------------------------- /client/public/icon/client/delete-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/delete-fill.png -------------------------------------------------------------------------------- /client/public/icon/client/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/delete.png -------------------------------------------------------------------------------- /client/public/icon/client/email-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/email-fill.png -------------------------------------------------------------------------------- /client/public/icon/client/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/email.png -------------------------------------------------------------------------------- /client/public/icon/client/emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/emoji.png -------------------------------------------------------------------------------- /client/public/icon/client/github-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/github-fill.png -------------------------------------------------------------------------------- /client/public/icon/client/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/github.png -------------------------------------------------------------------------------- /client/public/icon/client/likes-fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/likes-fill.png -------------------------------------------------------------------------------- /client/public/icon/client/likes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/likes.png -------------------------------------------------------------------------------- /client/public/icon/client/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/picture.png -------------------------------------------------------------------------------- /client/public/icon/client/police.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/police.png -------------------------------------------------------------------------------- /client/public/icon/client/postcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/postcard.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-collection-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-collection-black.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-collection-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-collection-white.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-follow-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-follow-black.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-follow-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-follow-white.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-like-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-like-black.png -------------------------------------------------------------------------------- /client/public/icon/client/problem-like-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/problem-like-white.png -------------------------------------------------------------------------------- /client/public/icon/client/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/qq.png -------------------------------------------------------------------------------- /client/public/icon/client/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/share.png -------------------------------------------------------------------------------- /client/public/icon/client/small-bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/small-bell.png -------------------------------------------------------------------------------- /client/public/icon/client/unit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/unit.png -------------------------------------------------------------------------------- /client/public/icon/client/view-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/view-blue.png -------------------------------------------------------------------------------- /client/public/icon/client/view-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/view-white.png -------------------------------------------------------------------------------- /client/public/icon/client/view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/view.png -------------------------------------------------------------------------------- /client/public/icon/client/website.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/website.png -------------------------------------------------------------------------------- /client/public/icon/client/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/icon/client/wechat.png -------------------------------------------------------------------------------- /client/public/image/admin/statistics/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/admin/statistics/bg.jpg -------------------------------------------------------------------------------- /client/public/image/admin/statistics/border_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/admin/statistics/border_bg.jpg -------------------------------------------------------------------------------- /client/public/image/admin/statistics/title_left_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/admin/statistics/title_left_bg.png -------------------------------------------------------------------------------- /client/public/image/admin/statistics/title_right_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/admin/statistics/title_right_bg.png -------------------------------------------------------------------------------- /client/public/image/client/collection-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/client/collection-bg.jpg -------------------------------------------------------------------------------- /client/public/image/client/github.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/client/github.jpg -------------------------------------------------------------------------------- /client/public/image/client/load-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/client/load-error.png -------------------------------------------------------------------------------- /client/public/image/client/qq-qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/client/qq-qrcode.jpg -------------------------------------------------------------------------------- /client/public/image/client/wechat-qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lrunlin/blog/342bb962c6f7b94b798311ee934315fc1b924157/client/public/image/client/wechat-qrcode.jpg -------------------------------------------------------------------------------- /client/public/robots-template.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow:* 3 | # 文章修改和发布 4 | Disallow:/article/editor 5 | # 开发者中心 6 | Disallow:/creator 7 | # 文章搜索 8 | Disallow:/search 9 | # 用户信息 10 | Disallow:/user 11 | # 消息提示 12 | Disallow:/notification 13 | # oauth登录重定向 14 | Disallow:/oauth 15 | # 部分链接的结果展示 16 | Disallow:/result 17 | # 友链页面 18 | Disallow:/friendly-link 19 | #中转页面 20 | Disallow:/link 21 | # 提问 22 | Disallow:/problem/editor 23 | # 收藏页面 24 | Disallow:/collection 25 | # 管理员 26 | Disallow:/admin 27 | # 找回密码 28 | Disallow:/forget-password 29 | 30 | Sitemap:https://blogweb.cn/sitemap/index.xml -------------------------------------------------------------------------------- /client/scripts/build-output/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [], 3 | "ext": "js", 4 | "ignore": ["*"], 5 | "restartable": "rs", 6 | "exec": "node ./server.js", 7 | "env": { 8 | "PORT": "5678", 9 | "NEXT_PUBLIC_ISPRO": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /client/src/app/(route)/ads.txt/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET() { 2 | if (process.env.NEXT_PUBLIC_GOOGLE_ADS_CLIENT_ID) { 3 | return new Response( 4 | `google.com, pub-${process.env.NEXT_PUBLIC_GOOGLE_ADS_CLIENT_ID}, DIRECT, f08c47fec0942fa0`, 5 | { 6 | status: 200, 7 | headers: { 8 | "content-type": "text/txt; charset=utf-8", 9 | }, 10 | }, 11 | ); 12 | } else { 13 | return new Response(undefined, { 14 | status: 404, 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client/src/app/(route)/sitemap/[type]/index.xml/route.tsx: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | import axios from "@axios"; 3 | import setSiteMap from "@/common/modules/sitemap/sitemap-index"; 4 | 5 | export async function GET( 6 | res: NextRequest, 7 | props: { params: Promise<{ type: string }> }, 8 | ) { 9 | const params = await props.params; 10 | let xml = await axios 11 | .get("/sitemap/" + params.type) 12 | .then((res) => setSiteMap(res.data.data)); 13 | return new Response(xml, { 14 | status: 200, 15 | headers: { 16 | "content-type": "text/xml; charset=utf-8", 17 | }, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /client/src/app/(route)/sitemap/[type]/index[index].xml/route.tsx: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | import axios from "@axios"; 3 | import setSiteMap from "@/common/modules/sitemap/sitemap"; 4 | 5 | export async function GET( 6 | res: NextRequest, 7 | props: { params: Promise<{ type: string }> }, 8 | ) { 9 | const params = await props.params; 10 | let match = res.nextUrl.pathname.match(/index(\d+)\.xml/); 11 | 12 | if (!match || !["article", "problem"].includes(params.type)) { 13 | return new Response(undefined, { 14 | status: 400, 15 | }); 16 | } 17 | 18 | let sitemap = await axios 19 | .get(`/sitemap/${params.type}/${match[1]}`) 20 | .then((res) => setSiteMap(res.data.data)) 21 | .catch((err) => { 22 | console.log(err); 23 | return ``; 24 | }); 25 | 26 | return new Response(sitemap, { 27 | status: 200, 28 | headers: { 29 | "content-type": "text/xml; charset=utf-8", 30 | }, 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /client/src/app/(route)/static/antd/[name]/route.tsx: -------------------------------------------------------------------------------- 1 | import { NextRequest } from "next/server"; 2 | import fs from "fs"; 3 | 4 | type Params = { 5 | name: string; 6 | }; 7 | 8 | export async function GET( 9 | res: NextRequest, 10 | context: { params: Promise }, 11 | ) { 12 | let name = (await context.params)!.name as string | undefined; 13 | if (typeof name == "string" && name?.endsWith(".css")) { 14 | try { 15 | let content = fs.readFileSync(`.next/css/${name}`).toString(); 16 | 17 | return new Response(content, { 18 | status: 200, 19 | headers: { 20 | "content-type": "text/css; charset=utf-8", 21 | }, 22 | }); 23 | } catch (error) { 24 | console.log(error); 25 | return new Response(undefined, { 26 | status: 404, 27 | }); 28 | } 29 | } else { 30 | return new Response(undefined, { 31 | status: 404, 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /client/src/app/(route)/static/high-light/[type]/route.tsx: -------------------------------------------------------------------------------- 1 | import type { NextRequest } from "next/server"; 2 | import axios from "@axios"; 3 | 4 | export async function GET( 5 | res: NextRequest, 6 | props: { params: Promise<{ type: string }> }, 7 | ) { 8 | const params = await props.params; 9 | 10 | const { type } = params; 11 | 12 | const searchParams = res.nextUrl.searchParams; 13 | const languages = searchParams.get("languages"); 14 | if (["js", "css"].includes(String(type))) { 15 | let content = await axios 16 | .get(`/high-light/${type}`, { 17 | params: { languages: languages }, 18 | }) 19 | .then((res) => res.data); 20 | return new Response(content, { 21 | status: 200, 22 | headers: { 23 | "content-type": `text/${type}; charset=utf-8`, 24 | "Cache-Control": `public, max-age=9999999999, must-revalidate`, 25 | }, 26 | }); 27 | } else { 28 | return new Response(undefined, { 29 | status: 404, 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /client/src/app/(route)/static/theme/[id]/route.tsx: -------------------------------------------------------------------------------- 1 | import type { NextRequest } from "next/server"; 2 | import axios from "@axios"; 3 | 4 | export async function GET( 5 | res: NextRequest, 6 | props: { params: Promise<{ id: string }> }, 7 | ) { 8 | const params = await props.params; 9 | 10 | const { id } = params; 11 | 12 | if (!(id as string).endsWith(".css")) { 13 | return new Response(undefined, { 14 | status: 404, 15 | }); 16 | } 17 | 18 | let content = await axios 19 | .get(`/theme/${(id as string).replace(/.css/, "")}`) 20 | .then((res) => res.data?.data?.content) 21 | .catch(() => false); 22 | 23 | if (!content) { 24 | return new Response(undefined, { 25 | status: 404, 26 | }); 27 | } 28 | 29 | return new Response(content, { 30 | status: 200, 31 | headers: { 32 | "content-type": `text/css; charset=utf-8`, 33 | "Cache-Control": `public, max-age=9999999999, must-revalidate`, 34 | }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /client/src/app/admin/[...all]/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useRouter } from "next/navigation"; 4 | import { Button, Result } from "antd"; 5 | import AdminLayout from "@/layout/Admin/Base"; 6 | import Head from "@/components/next/Head"; 7 | 8 | const NoFound = () => { 9 | let router = useRouter(); 10 | return ( 11 | 12 | 13 | router.replace("/admin")}> 19 | 首页 20 | 21 | } 22 | /> 23 | 24 | ); 25 | }; 26 | export default NoFound; 27 | -------------------------------------------------------------------------------- /client/src/app/admin/advertisement/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | import { message } from "antd"; 5 | import axios from "@axios"; 6 | import AdminLayout from "@/layout/Admin/Base"; 7 | import AdvertisementForm from "@/components/admin/page/advertisement/AdvertisementForm"; 8 | 9 | const APP = () => { 10 | const [key, setKey] = useState(`key-AdvertisementForm-1`); 11 | 12 | function onFinish(values: any) { 13 | axios.post("/advertisement", values).then((res) => { 14 | if (res.data.success) { 15 | message.success(res.data.message); 16 | setKey(`key-AdvertisementForm-${Math.random()}`); 17 | } else { 18 | message.error(res.data.message); 19 | } 20 | }); 21 | } 22 | return ( 23 | 24 |
25 | 26 |
27 |
28 | ); 29 | }; 30 | export default APP; 31 | -------------------------------------------------------------------------------- /client/src/app/admin/layout.tsx: -------------------------------------------------------------------------------- 1 | export default async function RootLayout({ 2 | children, 3 | }: Readonly<{ 4 | children: React.ReactNode; 5 | }>) { 6 | return <>{children}; 7 | } 8 | -------------------------------------------------------------------------------- /client/src/app/admin/theme/create/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import AdminLayout from "@/layout/Admin/Base"; 4 | import CreateTheme from "@/components/common/CreateTheme"; 5 | 6 | export default () => ( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /client/src/app/article/[id]/(main)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { FC, ReactNode } from "react"; 2 | import Read from "@/layout/Content"; 3 | import Aside from "@/components/page/article/Aside"; 4 | import ToolBar from "@/components/page/article/ToolBar"; 5 | 6 | const Layout: FC<{ children: ReactNode }> = ({ children }) => { 7 | return ( 8 | <> 9 | } Aside={