├── miniprogram ├── pages │ ├── about │ │ ├── archives │ │ │ ├── index.wxss │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.js │ │ ├── about │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ └── index.js │ │ ├── disclaimer │ │ │ ├── index.wxss │ │ │ ├── index.json │ │ │ ├── index.js │ │ │ └── index.wxml │ │ ├── links │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.js │ │ ├── notice │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ └── index.js │ │ ├── home │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ ├── index.js │ │ │ └── index.wxml │ │ └── journal │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ └── index.wxml │ ├── admin │ │ ├── login │ │ │ ├── index.wxss │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.js │ │ ├── user │ │ │ ├── index.wxss │ │ │ └── index.json │ │ ├── attachment │ │ │ ├── details │ │ │ │ ├── index.wxss │ │ │ │ └── index.json │ │ │ ├── home │ │ │ │ ├── index.json │ │ │ │ └── index.wxss │ │ │ └── select │ │ │ │ ├── index.json │ │ │ │ ├── index.wxss │ │ │ │ └── index.wxml │ │ ├── photos │ │ │ ├── details │ │ │ │ ├── index.wxss │ │ │ │ └── index.json │ │ │ └── home │ │ │ │ ├── index.json │ │ │ │ ├── index.wxss │ │ │ │ └── index.wxml │ │ ├── tag │ │ │ ├── index.json │ │ │ └── index.wxss │ │ ├── category │ │ │ ├── index.json │ │ │ └── index.wxss │ │ ├── setting │ │ │ ├── index.json │ │ │ └── index.wxss │ │ ├── environments │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ ├── index.wxml │ │ │ └── index.js │ │ ├── links │ │ │ └── home │ │ │ │ └── index.json │ │ ├── menu │ │ │ └── list │ │ │ │ ├── index.json │ │ │ │ └── index.wxss │ │ ├── theme │ │ │ └── list │ │ │ │ ├── index.json │ │ │ │ └── index.wxss │ │ ├── article │ │ │ ├── index.json │ │ │ └── index.wxss │ │ ├── comment │ │ │ ├── index.json │ │ │ └── index.wxss │ │ ├── journal │ │ │ └── home │ │ │ │ ├── index.json │ │ │ │ └── index.wxss │ │ └── home │ │ │ ├── index.json │ │ │ └── index.wxss │ ├── share │ │ ├── index.json │ │ ├── index.wxss │ │ ├── index.wxml │ │ └── index.js │ ├── tag │ │ ├── index.json │ │ └── index.wxss │ ├── photos │ │ └── home │ │ │ ├── index.json │ │ │ └── index.wxss │ ├── search │ │ ├── index.json │ │ └── index.wxss │ ├── comment │ │ ├── publish │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ └── index.wxml │ │ └── home │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ └── index.wxml │ ├── type │ │ ├── details │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ └── home │ │ │ ├── index.json │ │ │ ├── index.wxss │ │ │ └── index.wxml │ ├── index │ │ ├── index.json │ │ └── index.wxss │ └── details │ │ └── index.json ├── custom-tab-bar │ ├── index.wxss │ ├── index.json │ └── index.wxml ├── components │ ├── mp-weixin │ │ ├── audio │ │ │ ├── audio.json │ │ │ ├── context.js │ │ │ ├── index.js │ │ │ ├── audio.wxml │ │ │ ├── audio.wxss │ │ │ └── audio.js │ │ ├── index.json │ │ ├── node │ │ │ ├── node.json │ │ │ ├── node.js │ │ │ └── node.wxss │ │ ├── highlight │ │ │ ├── config.js │ │ │ └── index.js │ │ ├── index.wxss │ │ ├── index.wxml │ │ ├── markdown │ │ │ └── index.js │ │ └── style │ │ │ ├── index.js │ │ │ └── parser.js │ ├── painter │ │ ├── painter.json │ │ ├── painter.wxml │ │ └── lib │ │ │ └── util.js │ ├── authorize │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.js │ │ └── index.wxss │ ├── admin-login │ │ ├── index.json │ │ └── index.wxss │ ├── image-loader │ │ ├── index.json │ │ ├── index.wxss │ │ ├── index.wxml │ │ └── index.js │ ├── comment │ │ └── index.json │ └── article-list │ │ ├── index.json │ │ ├── index.wxss │ │ ├── index.js │ │ └── index.wxml ├── styles │ └── colorui │ │ └── components │ │ ├── cu-custom.wxss │ │ ├── cu-custom.json │ │ ├── cu-custom.wxml │ │ └── cu-custom.js ├── images │ ├── bg │ │ ├── halo.png │ │ └── background-share.png │ ├── prompt │ │ ├── warn.svg │ │ └── success.svg │ └── icon │ │ ├── home.svg │ │ ├── photo-hover.svg │ │ ├── about-hover.svg │ │ ├── love.svg │ │ ├── share.svg │ │ ├── home-hover.svg │ │ ├── poster.svg │ │ ├── type-hover.svg │ │ ├── admin-hover.svg │ │ ├── about.svg │ │ ├── gitee.svg │ │ ├── photo.svg │ │ ├── service.svg │ │ ├── comment.svg │ │ ├── article.svg │ │ ├── type.svg │ │ ├── github.svg │ │ ├── link.svg │ │ ├── know.svg │ │ ├── mail.svg │ │ ├── disclaimer.svg │ │ ├── weixin.svg │ │ ├── qq.svg │ │ ├── write.svg │ │ ├── admin.svg │ │ ├── read.svg │ │ ├── message.svg │ │ ├── friendfavor.svg │ │ ├── tag.svg │ │ └── calendar.svg ├── sitemap.json ├── services │ ├── api │ │ ├── cloud │ │ │ ├── cloud.js │ │ │ └── user.js │ │ ├── content │ │ │ ├── link.js │ │ │ ├── journal.js │ │ │ ├── archive.js │ │ │ ├── statistic.js │ │ │ ├── option.js │ │ │ ├── photo.js │ │ │ ├── tag.js │ │ │ ├── theme.js │ │ │ ├── category.js │ │ │ └── sheet.js │ │ └── admin │ │ │ ├── environment.js │ │ │ ├── option.js │ │ │ ├── statistic.js │ │ │ ├── login.js │ │ │ ├── user.js │ │ │ ├── tag.js │ │ │ ├── menu.js │ │ │ ├── link.js │ │ │ ├── journal.js │ │ │ ├── category.js │ │ │ ├── photo.js │ │ │ └── theme.js │ └── const-data │ │ ├── const-data.js │ │ └── theme-setting-key.js ├── utils │ ├── api-result.js │ └── utils.js ├── app.wxss ├── config │ └── api-tmp.js └── app.json ├── cloudfunctions ├── check_message │ ├── config.json │ ├── package.json │ └── index.js └── get_qrcode │ ├── config.json │ ├── package.json │ └── index.js ├── .eslintignore ├── .prettierignore ├── .eslintrc.js ├── .editorconfig ├── .gitignore ├── package.json ├── LICENSE ├── .prettierrc.js └── project.config.json /miniprogram/pages/about/archives/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/login/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/user/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/share/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/about/about/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/about/disclaimer/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/about/links/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/about/notice/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/about/archives/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/about/disclaimer/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/details/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/photos/details/index.wxss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/photos/home/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/home/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/photos/details/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/custom-tab-bar/index.wxss: -------------------------------------------------------------------------------- 1 | @import '/app.wxss'; 2 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/details/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/select/index.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/audio.json: -------------------------------------------------------------------------------- 1 | {"component":true} -------------------------------------------------------------------------------- /miniprogram/pages/tag/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/tag/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/category/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/setting/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/user/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/environments/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/links/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/menu/list/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/theme/list/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/styles/colorui/components/cu-custom.wxss: -------------------------------------------------------------------------------- 1 | /* styles/colorui/components/cu-custom.wxss */ -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/index.json: -------------------------------------------------------------------------------- 1 | {"component":true,"usingComponents":{"node":"./node/node"}} -------------------------------------------------------------------------------- /miniprogram/components/painter/painter.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/custom-tab-bar/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } 5 | -------------------------------------------------------------------------------- /miniprogram/pages/about/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "GeekEra | 关于我" 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/components/authorize/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } 5 | -------------------------------------------------------------------------------- /miniprogram/components/admin-login/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } 5 | -------------------------------------------------------------------------------- /miniprogram/components/image-loader/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } 5 | -------------------------------------------------------------------------------- /miniprogram/images/bg/halo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzui/GBlog-wx/HEAD/miniprogram/images/bg/halo.png -------------------------------------------------------------------------------- /miniprogram/styles/colorui/components/cu-custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/pages/admin/menu/list/index.wxss: -------------------------------------------------------------------------------- 1 | /* 表单名宽度 */ 2 | .cu-form-group > .title { 3 | width: 220rpx; 4 | } 5 | -------------------------------------------------------------------------------- /cloudfunctions/check_message/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": ["security.msgSecCheck"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /cloudfunctions/get_qrcode/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": ["wxacode.getUnlimited"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/node/node.json: -------------------------------------------------------------------------------- 1 | {"component":true,"usingComponents":{"my-audio":"../audio/audio","node":"./node"}} -------------------------------------------------------------------------------- /miniprogram/images/bg/background-share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzui/GBlog-wx/HEAD/miniprogram/images/bg/background-share.png -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/highlight/config.js: -------------------------------------------------------------------------------- 1 | "use strict";module.exports={copyByLongPress:!0,showLanguageName:!1,showLineNumber:!1}; -------------------------------------------------------------------------------- /miniprogram/pages/about/journal/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-html": "../../../components/mp-weixin/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/article/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-html": "../../../components/mp-weixin/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/comment/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-html": "../../../components/mp-weixin/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/photos/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-html": "../../../components/mp-weixin/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/search/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "article-list": "./../../components/article-list/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/components/comment/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "mp-html": "../mp-weixin/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/login/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "admin-login": "../../../components/admin-login/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/journal/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "mp-html": "../../../../components/mp-weixin/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/comment/publish/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "article-list": "./../../../components/article-list/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/type/details/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "article-list": "./../../../components/article-list/index" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/login/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /miniprogram/components/article-list/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "image-loader": "../image-loader/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /miniprogram/components/image-loader/index.wxss: -------------------------------------------------------------------------------- 1 | @import '/app.wxss'; 2 | 3 | .before-load { 4 | width: 0; 5 | height: 0; 6 | opacity: 0; 7 | display: none; 8 | } 9 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/context.js: -------------------------------------------------------------------------------- 1 | "use strict";var t={};module.exports={get:function(e){return t[e]},set:function(e,n){t[e]=n},remove:function(e){t[e]=void 0}}; -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # .eslintignore 2 | 3 | node_modules 4 | miniprogram/components/mp-weixin 5 | miniprogram/components/painter 6 | miniprogram/styles/colorui 7 | miniprogram/utils/qs.js -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/index.wxss: -------------------------------------------------------------------------------- 1 | ._root{padding:1px 0;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch}._select{-webkit-user-select:text;user-select:text} -------------------------------------------------------------------------------- /miniprogram/pages/admin/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "GeekEra | 关于我", 3 | "usingComponents": { 4 | "admin-login": "../../../components/admin-login/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/theme/list/index.wxss: -------------------------------------------------------------------------------- 1 | .add-theme { 2 | position: fixed; 3 | z-index: 1024; 4 | height: 50rpx; 5 | width: 50rpx; 6 | bottom: 30rpx; 7 | right: 30rpx; 8 | } 9 | -------------------------------------------------------------------------------- /miniprogram/components/admin-login/index.wxss: -------------------------------------------------------------------------------- 1 | @import '/app.wxss'; 2 | 3 | .cu-bar.btn-group button { 4 | padding: 20rpx 32rpx; 5 | flex: 1; 6 | margin: 0 20rpx; 7 | max-width: 80%; 8 | } 9 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "article-list": "./../../components/article-list/index", 4 | "image-loader": "./../../components/image-loader/index" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /miniprogram/pages/comment/publish/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-form-group textarea { 2 | margin: 32rpx 0 30rpx; 3 | height: 12em; 4 | width: 100%; 5 | line-height: 1.2em; 6 | flex: 1; 7 | font-size: 28rpx; 8 | padding: 0; 9 | } 10 | -------------------------------------------------------------------------------- /miniprogram/sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [ 4 | { 5 | "action": "allow", 6 | "page": "*" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/setting/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-form-group .title { 2 | min-width: calc(4em + 30rpx); 3 | } 4 | .selectSetting { 5 | position: fixed; 6 | z-index: 1024; 7 | height: 50rpx; 8 | width: 50rpx; 9 | bottom: 30rpx; 10 | right: 30rpx; 11 | } 12 | -------------------------------------------------------------------------------- /miniprogram/pages/details/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "painter": "../../components/painter/painter", 4 | "mp-html": "../../components/mp-weixin/index", 5 | "authorize": "../../components/authorize/index", 6 | "comment": "../../components/comment/index" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /miniprogram/pages/comment/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "painter": "../../../components/painter/painter", 4 | "article-list": "./../../../components/article-list/index", 5 | "authorize": "../../../components/authorize/index", 6 | "comment": "../../../components/comment/index" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /miniprogram/pages/type/home/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "painter": "../../../components/painter/painter", 4 | "article-list": "./../../../components/article-list/index", 5 | "authorize": "../../../components/authorize/index", 6 | "image-loader": "../../../components/image-loader/index" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /cloudfunctions/get_qrcode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get_qrcode", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "^2.0.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cloudfunctions/check_message/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "check_message", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "wx-server-sdk": "~2.5.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /miniprogram/pages/share/index.wxss: -------------------------------------------------------------------------------- 1 | page { 2 | background-color: #7566b4 !important; 3 | text-align: center; 4 | } 5 | .share-image { 6 | margin-top: 40rpx; 7 | width: 650rpx; 8 | } 9 | .button { 10 | margin: 1rpx 0rpx 0rpx 50rpx; 11 | padding: 50rpx 70rpx; 12 | border-radius: 20rpx; 13 | width: 650rpx; 14 | height: 164rpx; 15 | background-color: #ffffff; 16 | } 17 | -------------------------------------------------------------------------------- /cloudfunctions/get_qrcode/index.js: -------------------------------------------------------------------------------- 1 | const cloud = require('wx-server-sdk') 2 | cloud.init() 3 | exports.main = async (event, context) => { 4 | try { 5 | const result = await cloud.openapi.wxacode.getUnlimited({ 6 | scene: event.scene, 7 | page: event.path 8 | }) 9 | result.event = event 10 | return result 11 | } catch (err) { 12 | return err 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # .prettierignore 2 | 3 | *.min.js 4 | /node_modules 5 | /dist 6 | # OS 7 | .DS_Store 8 | .idea 9 | .editorconfig 10 | .npmrc 11 | package-lock.json 12 | # Ignored suffix 13 | *.log 14 | *.md 15 | *.svg 16 | *.png 17 | *ignore 18 | ## Built-files 19 | .cache 20 | dist 21 | miniprogram/components/mp-weixin 22 | miniprogram/components/painter 23 | miniprogram/styles/colorui 24 | miniprogram/utils/qs.js -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/home/index.wxss: -------------------------------------------------------------------------------- 1 | .solids-blue { 2 | position: relative; 3 | } 4 | .solids-blue::after { 5 | content: ' '; 6 | width: 200%; 7 | height: 200%; 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | border-radius: inherit; 12 | transform: scale(0.5); 13 | transform-origin: 0 0; 14 | pointer-events: none; 15 | box-sizing: border-box; 16 | border: 10rpx solid blue; 17 | } 18 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/photos/home/index.wxss: -------------------------------------------------------------------------------- 1 | .solids-blue { 2 | position: relative; 3 | } 4 | .solids-blue::after { 5 | content: ' '; 6 | width: 200%; 7 | height: 200%; 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | border-radius: inherit; 12 | transform: scale(0.5); 13 | transform-origin: 0 0; 14 | pointer-events: none; 15 | box-sizing: border-box; 16 | border: 10rpx solid blue; 17 | } 18 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/select/index.wxss: -------------------------------------------------------------------------------- 1 | .solids-blue { 2 | position: relative; 3 | } 4 | .solids-blue::after { 5 | content: ' '; 6 | width: 200%; 7 | height: 200%; 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | border-radius: inherit; 12 | transform: scale(0.5); 13 | transform-origin: 0 0; 14 | pointer-events: none; 15 | box-sizing: border-box; 16 | border: 10rpx solid blue; 17 | } 18 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/index.js: -------------------------------------------------------------------------------- 1 | "use strict";function t(t){this.vm=t}var o=require("./context"),i=0;t.prototype.onUpdate=function(){this.audios=[]},t.prototype.onParse=function(t){"audio"===t.name&&(t.attrs.id||(t.attrs.id="a"+i++),this.audios.push(t.attrs.id))},t.prototype.onLoad=function(){var t=this;setTimeout(function(){for(var i=0;i 2 | 分享海报 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /miniprogram/services/api/cloud/cloud.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 检查敏感词 3 | */ 4 | function checkMessage(content) { 5 | return new Promise((resolve, reject) => { 6 | wx.cloud.callFunction({ 7 | name: 'check_message', 8 | data: { 9 | content: content 10 | }, 11 | success(res) { 12 | resolve(res.result) 13 | }, 14 | fail(e) { 15 | reject(e) 16 | } 17 | }) 18 | }) 19 | } 20 | 21 | module.exports = { 22 | checkMessage 23 | } 24 | -------------------------------------------------------------------------------- /miniprogram/pages/about/notice/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 公告 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{blogTitle}} 10 | {{notice}} 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /miniprogram/pages/about/notice/index.wxss: -------------------------------------------------------------------------------- 1 | page { 2 | background: #fff; 3 | } 4 | .UCenter-bg { 5 | background-image: url(https://fuzui.oss-cn-shenzhen.aliyuncs.com/img/notice11.png); 6 | background-size: cover; 7 | height: 400rpx; 8 | display: flex; 9 | justify-content: center; 10 | padding-top: 40rpx; 11 | overflow: hidden; 12 | position: relative; 13 | flex-direction: column; 14 | align-items: center; 15 | color: #fff; 16 | font-weight: 300; 17 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 18 | } 19 | -------------------------------------------------------------------------------- /miniprogram/pages/about/notice/index.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 2 | 3 | const app = getApp() 4 | Page({ 5 | data: { 6 | notice: '', 7 | blogTitle: '' 8 | }, 9 | onLoad: function () {}, 10 | async onShow() { 11 | const that = this 12 | if (!app.globalData.hasInit) { 13 | await app.init() 14 | } 15 | that.setData({ 16 | notice: '', 17 | blogTitle: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] 18 | }) 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/audio.wxml: -------------------------------------------------------------------------------- 1 | {{name||'未知音频'}}{{author||'未知作者'}}{{time}} -------------------------------------------------------------------------------- /miniprogram/services/api/content/link.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/links' 4 | 5 | /** 6 | * 获取友链 7 | * @param {*} params 8 | */ 9 | function getLinks(params) { 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(moduleName, params).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | module.exports = { 23 | getLinks 24 | } 25 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/markdown/index.js: -------------------------------------------------------------------------------- 1 | "use strict";function t(t){this.vm=t,t._ids={}}var e=require("./marked.min"),a=0;t.prototype.onUpdate=function(t){if(this.vm.data.markdown)return e(t)},t.prototype.onParse=function(t,e){if(e.options.markdown){if(e.options.useAnchor&&t.attrs&&/[\u4e00-\u9fa5]/.test(t.attrs.id)){var n="t"+a++;this.vm._ids[t.attrs.id]=n,t.attrs.id=n}"p"!==t.name&&"table"!==t.name&&"tr"!==t.name&&"th"!==t.name&&"td"!==t.name&&"blockquote"!==t.name&&"pre"!==t.name&&"code"!==t.name||(t.attrs.class="md-".concat(t.name," ").concat(t.attrs.class||""))}},module.exports=t; -------------------------------------------------------------------------------- /miniprogram/services/api/content/journal.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/journals' 4 | 5 | /** 6 | * 获取日记 7 | * @param {*} params 8 | */ 9 | function getJournals(params) { 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(moduleName, params).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | module.exports = { 22 | getJournals 23 | } 24 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/archive.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/archives' 4 | 5 | /** 6 | * 获取归档 7 | */ 8 | function getArchives() { 9 | const url = moduleName + '/months' 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(url, {}).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | module.exports = { 23 | getArchives 24 | } 25 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/statistic.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/statistics' 4 | 5 | /** 6 | * 获取统计信息 7 | */ 8 | function getStatistics() { 9 | const url = moduleName + '/user' 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(url, {}).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | module.exports = { 23 | moduleName, 24 | getStatistics 25 | } 26 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | commonjs: true, 6 | es2021: true, 7 | node: true 8 | }, 9 | extends: ['standard', 'plugin:prettier/recommended'], 10 | plugins: ['prettier'], 11 | parserOptions: { 12 | requireConfigFile: false, 13 | ecmaVersion: 2021, 14 | sourceType: 'module' 15 | }, 16 | rules: {}, 17 | globals: { 18 | App: true, 19 | Page: true, 20 | Component: true, 21 | Behavior: true, 22 | wx: true, 23 | my: true, 24 | swan: true, 25 | getApp: true, 26 | getCurrentPages: true, 27 | getDate: true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/login/index.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 2 | 3 | // 获取应用实例 4 | const app = getApp() 5 | Page({ 6 | data: { 7 | logo: '' 8 | }, 9 | async onLoad() { 10 | const that = this 11 | that.setData({ 12 | logo: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 13 | }) 14 | }, 15 | async onShow() {}, 16 | /** 17 | * 登录后置处理 18 | */ 19 | async loginSuf() { 20 | const pages = getCurrentPages() 21 | const beforePage = pages[pages.length - 2] 22 | beforePage.onLoad() 23 | wx.navigateBack({ 24 | delta: 1 25 | }) 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # .editorconfig 2 | # http://editorconfig.org 3 | # https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties 4 | 5 | 6 | # 根目录的配置文件,编辑器会由当前目录向上查找,如果找到 `roor = true` 的文件,则不再查找 7 | root = true 8 | 9 | # 匹配所有的文件 10 | [*] 11 | # 缩进风格:space 12 | indent_style = space 13 | # 缩进大小 2 14 | indent_size = 2 15 | # 换行符 lf 16 | end_of_line = lf 17 | # 字符集 utf-8 18 | charset = utf-8 19 | # 不保留行末的空格 20 | trim_trailing_whitespace = true 21 | # 文件末尾添加一个空行 22 | insert_final_newline = true 23 | # 运算符两遍都有空格 24 | spaces_around_operators = true 25 | 26 | # 对所有的 js 文件生效 27 | [*.js] 28 | # 字符串使用单引号 29 | quote_type = single 30 | 31 | [*.md] 32 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /miniprogram/pages/about/about/index.wxss: -------------------------------------------------------------------------------- 1 | page { 2 | background: #fff; 3 | } 4 | .UCenter-bg { 5 | background-image: url(https://fuzui.oss-cn-shenzhen.aliyuncs.com/img/notice11.png); 6 | background-size: cover; 7 | height: 400rpx; 8 | display: flex; 9 | justify-content: center; 10 | padding-top: 40rpx; 11 | overflow: hidden; 12 | position: relative; 13 | flex-direction: column; 14 | align-items: center; 15 | color: #fff; 16 | font-weight: 300; 17 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 18 | } 19 | .cu-list.menu > .cu-item .content > image { 20 | display: inline-block; 21 | width: 1.3em; 22 | height: 1.3em; 23 | vertical-align: middle; 24 | margin-right: 15rpx; 25 | } 26 | -------------------------------------------------------------------------------- /miniprogram/pages/type/details/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | {{name}} 3 | 4 | 5 | 6 | 7 | 8 | 暂无文章 9 | 10 | 11 | 12 | 13 | 14 | 15 | 加载中... 16 | 17 | -------------------------------------------------------------------------------- /miniprogram/pages/search/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-custom { 2 | display: block; 3 | position: relative; 4 | } 5 | 6 | .cu-custom .cu-bar .content { 7 | width: calc(100% - 240rpx); 8 | left: 0rpx; 9 | /* width: 100%; */ 10 | } 11 | 12 | .cu-custom .cu-bar .content image { 13 | height: 60rpx; 14 | width: 540rpx; 15 | } 16 | 17 | .cu-custom .cu-bar { 18 | min-height: 0px; 19 | padding-right: 220rpx; 20 | box-shadow: 0rpx 0rpx 0rpx; 21 | z-index: 9999; 22 | } 23 | .cu-bar .search-form { 24 | background-color: #f5f5f5; 25 | line-height: 64rpx; 26 | height: 64rpx; 27 | font-size: 24rpx; 28 | color: var(--black); 29 | flex: 1; 30 | display: flex; 31 | align-items: center; 32 | margin: 0 30rpx; 33 | } 34 | -------------------------------------------------------------------------------- /miniprogram/components/image-loader/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /miniprogram/pages/type/details/index.wxss: -------------------------------------------------------------------------------- 1 | /* 顶图样式 */ 2 | .UCenter-bg { 3 | background-size: cover; 4 | height: 336rpx; 5 | display: flex; 6 | justify-content: center; 7 | padding-top: 40rpx; 8 | overflow: hidden; 9 | position: relative; 10 | flex-direction: column; 11 | align-items: center; 12 | color: #fff; 13 | font-weight: 300; 14 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 15 | } 16 | .fixed-bg { 17 | position: fixed; 18 | width: 100%; 19 | top: 0; 20 | z-index: 1024; 21 | box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); 22 | } 23 | /* 分类框 */ 24 | .fixed-nav { 25 | position: fixed; 26 | width: 100%; 27 | top: 321rpx; 28 | z-index: 1024; 29 | box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); 30 | } 31 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/environment.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/environments' 5 | 6 | /** 7 | * 获取服务器配置 8 | */ 9 | function adminGetEnvironments() { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, adminToken).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | module.exports = { 26 | adminGetEnvironments 27 | } 28 | -------------------------------------------------------------------------------- /miniprogram/images/prompt/warn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/option.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../../services/const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/options' 5 | 6 | /** 7 | * 获取设置信息 8 | */ 9 | function adminGetOption() { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | const url = moduleName + '/map_view' 14 | return new Promise((resolve, reject) => { 15 | apiRequest.Get(url, adminToken).then( 16 | r => { 17 | resolve(r) 18 | }, 19 | e => { 20 | reject(e) 21 | } 22 | ) 23 | }) 24 | } 25 | 26 | module.exports = { 27 | adminGetOption 28 | } 29 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/statistic.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/statistics' 5 | 6 | /** 7 | * 获取站点及博主信息 8 | */ 9 | function adminGetStatistics() { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | const url = moduleName + '/user' 14 | return new Promise((resolve, reject) => { 15 | apiRequest.Get(url, adminToken).then( 16 | r => { 17 | resolve(r) 18 | }, 19 | e => { 20 | reject(e) 21 | } 22 | ) 23 | }) 24 | } 25 | 26 | module.exports = { 27 | adminGetStatistics 28 | } 29 | -------------------------------------------------------------------------------- /miniprogram/custom-tab-bar/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 17 | 18 | {{item.text}} 19 | 20 | 21 | -------------------------------------------------------------------------------- /miniprogram/pages/comment/home/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-bar.tabbar .action { 2 | font-size: 22rpx; 3 | position: relative; 4 | flex: 1; 5 | text-align: left; 6 | padding: 0; 7 | display: block; 8 | height: auto; 9 | line-height: 1; 10 | margin: 0; 11 | overflow: initial; 12 | } 13 | .cu-bar.tabbar .comment { 14 | align-items: center; 15 | display: flex; 16 | justify-content: center; 17 | text-align: center; 18 | position: relative; 19 | flex: 3; 20 | } 21 | 22 | .cu-tag.badge { 23 | border-radius: 200rpx; 24 | position: absolute; 25 | top: -10rpx; 26 | right: -10rpx; 27 | font-size: 20rpx; 28 | padding: 0rpx 10rpx; 29 | height: 28rpx; 30 | color: var(--grey); 31 | } 32 | 33 | .cu-tag.badge:not([class*='bg-']) { 34 | background-color: #dd514c; 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | **/node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | # !.vscode/settings.json 23 | # !.vscode/tasks.json 24 | # !.vscode/launch.json 25 | # !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | package-lock.json 42 | yarn.lock 43 | 44 | # prod config 45 | **/api.js 46 | project.private.config.json 47 | -------------------------------------------------------------------------------- /miniprogram/components/authorize/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 19 | -------------------------------------------------------------------------------- /miniprogram/images/icon/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/environments/index.wxss: -------------------------------------------------------------------------------- 1 | .cardTitle { 2 | color: #fff; 3 | padding: 90rpx 60rpx; 4 | font-size: 40rpx; 5 | font-weight: 300; 6 | transform: skew(-10deg, 0deg); 7 | position: relative; 8 | text-shadow: 0px 0px 6rpx rgba(0, 0, 0, 0.3); 9 | } 10 | 11 | .cardTitle::before { 12 | content: ''; 13 | position: absolute; 14 | width: 60rpx; 15 | height: 6rpx; 16 | border-radius: 20rpx; 17 | background-color: #fff; 18 | display: block; 19 | top: 60rpx; 20 | left: 50rpx; 21 | transform: skew(10deg, 0deg); 22 | } 23 | .cardTitle::after { 24 | content: ''; 25 | position: absolute; 26 | width: 140rpx; 27 | border-radius: 6rpx; 28 | height: 24rpx; 29 | background-color: #fff; 30 | display: block; 31 | bottom: 76rpx; 32 | left: 90rpx; 33 | transform: skew(10deg, 0deg); 34 | opacity: 0.1; 35 | } 36 | -------------------------------------------------------------------------------- /miniprogram/components/article-list/index.wxss: -------------------------------------------------------------------------------- 1 | @import '/app.wxss'; 2 | /* 文章样式 */ 3 | .cu-card { 4 | display: block; 5 | overflow: hidden; 6 | } 7 | .cu-card > .cu-item { 8 | display: block; 9 | background-color: var(--white); 10 | overflow: hidden; 11 | border-radius: 10rpx; 12 | margin: 30rpx; 13 | } 14 | .cu-card.no-card > .cu-item { 15 | margin: 0rpx; 16 | border-radius: 0rpx; 17 | } 18 | .image-loader { 19 | width: 240rpx; 20 | height: 6.4em; 21 | margin-right: 20rpx; 22 | border-radius: 6rpx; 23 | } 24 | .cu-card.article > .cu-item .content .text-content { 25 | width: 350rpx; 26 | font-size: 22rpx; 27 | color: #888; 28 | height: 3.3em; 29 | overflow: hidden; 30 | } 31 | .cu-card.article > .cu-item .title { 32 | font-size: 30rpx; 33 | font-weight: 900; 34 | color: var(--black); 35 | line-height: 100rpx; 36 | padding: 0 30rpx; 37 | } 38 | -------------------------------------------------------------------------------- /cloudfunctions/check_message/index.js: -------------------------------------------------------------------------------- 1 | // 云函数入口文件 2 | const cloud = require('wx-server-sdk') 3 | 4 | cloud.init() 5 | 6 | // 云函数入口函数 7 | exports.main = async (event, context) => { 8 | try { 9 | const result = await cloud.openapi.security.msgSecCheck({ 10 | content: event.content 11 | }) 12 | if (result && result.errCode.toString() === '87014') { 13 | return { 14 | code: 300, 15 | msg: '内容违规', 16 | data: result 17 | } // 18 | } else { 19 | return { 20 | code: 200, 21 | msg: 'ok', 22 | data: result 23 | } 24 | } 25 | } catch (err) { 26 | if (err.errCode.toString() === '87014') { 27 | return { 28 | code: 300, 29 | msg: '内容违规', 30 | data: err 31 | } // 32 | } 33 | return { 34 | code: 400, 35 | msg: '安全检查异常', 36 | data: err 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/article/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-card.article { 2 | display: block; 3 | } 4 | 5 | .cu-card.article > .cu-item { 6 | padding-bottom: 30rpx; 7 | } 8 | 9 | .cu-card.article > .cu-item .title { 10 | font-size: 26rpx; 11 | font-weight: 500; 12 | color: var(--black); 13 | line-height: 80rpx; 14 | padding: 0 10rpx; 15 | } 16 | 17 | .cu-card.article > .cu-item .content { 18 | display: flex; 19 | padding: 0 30rpx; 20 | } 21 | 22 | .cu-card.article > .cu-item .content > image { 23 | width: 240rpx; 24 | height: 6.4em; 25 | margin-right: 20rpx; 26 | border-radius: 6rpx; 27 | } 28 | 29 | .cu-card.article > .cu-item .content .desc { 30 | flex: 1; 31 | display: flex; 32 | flex-direction: column; 33 | justify-content: space-between; 34 | } 35 | 36 | .cu-card.article > .cu-item .content .text-content { 37 | font-size: 26rpx; 38 | color: #888; 39 | height: auto; 40 | } 41 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/comment/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-card.article { 2 | display: block; 3 | } 4 | 5 | .cu-card.article > .cu-item { 6 | padding-bottom: 30rpx; 7 | } 8 | 9 | .cu-card.article > .cu-item .title { 10 | font-size: 28rpx; 11 | font-weight: 500; 12 | color: var(--black); 13 | line-height: 80rpx; 14 | padding: 0 30rpx; 15 | } 16 | 17 | .cu-card.article > .cu-item .content { 18 | display: flex; 19 | padding: 0 30rpx; 20 | } 21 | 22 | .cu-card.article > .cu-item .content > image { 23 | width: 240rpx; 24 | height: 6.4em; 25 | margin-right: 20rpx; 26 | border-radius: 6rpx; 27 | } 28 | 29 | .cu-card.article > .cu-item .content .desc { 30 | flex: 1; 31 | display: flex; 32 | flex-direction: column; 33 | justify-content: space-between; 34 | } 35 | 36 | .cu-card.article > .cu-item .content .text-content { 37 | font-size: 26rpx; 38 | color: #888; 39 | height: auto; 40 | } 41 | -------------------------------------------------------------------------------- /miniprogram/pages/about/home/index.wxss: -------------------------------------------------------------------------------- 1 | .UCenter-bg { 2 | background-size: cover; 3 | height: 397rpx; 4 | display: flex; 5 | justify-content: center; 6 | padding-top: 40rpx; 7 | overflow: hidden; 8 | position: relative; 9 | flex-direction: column; 10 | align-items: center; 11 | color: #fff; 12 | font-weight: 300; 13 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 14 | } 15 | .UCenter-bg text { 16 | opacity: 0.8; 17 | } 18 | 19 | .UCenter-bg image { 20 | width: 200rpx; 21 | height: 200rpx; 22 | } 23 | 24 | .UCenter-bg .gif-wave { 25 | position: absolute; 26 | width: 100%; 27 | bottom: 0; 28 | left: 0; 29 | z-index: 99; 30 | mix-blend-mode: screen; 31 | height: 100rpx; 32 | } 33 | /* 图标 */ 34 | .cu-list.menu > .cu-item .content > image { 35 | display: inline-block; 36 | width: 1.3em; 37 | height: 1.3em; 38 | vertical-align: middle; 39 | margin-right: 30rpx; 40 | } 41 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/option.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from './../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/options' 4 | /** 5 | * option 6 | * @param {*} key 7 | */ 8 | function getOptionByKey(key) { 9 | const url = moduleName + '/keys/' + key 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(url, {}).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | function getOptions() { 23 | const url = moduleName + '/list_view' 24 | return new Promise((resolve, reject) => { 25 | apiRequest.Get(url, {}).then( 26 | r => { 27 | resolve(r) 28 | }, 29 | e => { 30 | reject(e) 31 | } 32 | ) 33 | }) 34 | } 35 | 36 | module.exports = { 37 | getOptionByKey, 38 | getOptions 39 | } 40 | -------------------------------------------------------------------------------- /miniprogram/images/icon/photo-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/const-data/const-data.js: -------------------------------------------------------------------------------- 1 | export const STORAGE_KEY = { 2 | user: 'userInfo', 3 | adminToken: 'adminToken', 4 | searchHistory: 'searchHistory', 5 | searchRecommend: 'searchRecommend', 6 | gravatarSource: 'gravatarSource', 7 | gravatarDefault: 'gravatarDefault', 8 | options: 'options', 9 | themeSettings: 'themeSettings', 10 | userEmail: 'userEmail', 11 | notifiStatus: 'notifiStatus' 12 | } 13 | 14 | export const DEFAULT_VALUE = { 15 | gravatarSource: 'https://sdn.geekzu.org/avatar/', 16 | gravatarDefault: 'monsterid' 17 | } 18 | 19 | export const HALO_OPTION_KEY = { 20 | blogTitle: 'blog_title', 21 | blogFavicon: 'blog_favicon', 22 | gravatarSource: 'gravatar_source', 23 | gravatarDefault: 'comment_gravatar_default', 24 | commentNewNeedCheck: 'comment_new_need_check' 25 | } 26 | 27 | export const COMMENT_TYPE = { 28 | post: 'post', 29 | guestbook: 'guestbook', 30 | sheet: 'sheet' 31 | } 32 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/photo.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/photos' 4 | 5 | /** 6 | * 光影相册 7 | * @param {*} params 8 | */ 9 | function getPhotos(params) { 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(moduleName, params).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | /** 23 | * 光影分组 24 | * @param {*} params 25 | */ 26 | function getPhotoTeams() { 27 | return new Promise((resolve, reject) => { 28 | const url = moduleName + '/teams' 29 | apiRequest.Get(url, {}).then( 30 | r => { 31 | resolve(r) 32 | }, 33 | e => { 34 | reject(e) 35 | } 36 | ) 37 | }) 38 | } 39 | 40 | module.exports = { 41 | getPhotos, 42 | getPhotoTeams 43 | } 44 | -------------------------------------------------------------------------------- /miniprogram/styles/colorui/components/cu-custom.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/home/index.wxss: -------------------------------------------------------------------------------- 1 | .UCenter-bg { 2 | background-size: cover; 3 | height: 397rpx; 4 | display: flex; 5 | justify-content: center; 6 | padding-top: 40rpx; 7 | overflow: hidden; 8 | position: relative; 9 | flex-direction: column; 10 | align-items: center; 11 | color: #fff; 12 | font-weight: 300; 13 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 14 | } 15 | .UCenter-bg text { 16 | opacity: 0.8; 17 | } 18 | 19 | .UCenter-bg .avatar { 20 | width: 150rpx; 21 | height: 150rpx; 22 | border-radius: 50%; 23 | } 24 | 25 | .UCenter-bg .gif-wave { 26 | position: absolute; 27 | width: 100%; 28 | bottom: 0; 29 | left: 0; 30 | z-index: 99; 31 | mix-blend-mode: screen; 32 | height: 100rpx; 33 | } 34 | /* 图标 */ 35 | .cu-list.menu > .cu-item .content > image { 36 | display: inline-block; 37 | margin-left: 8rpx; 38 | margin-right: 12rpx; 39 | width: 1.3em; 40 | height: 1.3em; 41 | vertical-align: middle; 42 | } 43 | -------------------------------------------------------------------------------- /miniprogram/components/authorize/index.js: -------------------------------------------------------------------------------- 1 | import apiResult from '../../utils/api-result' 2 | import { STORAGE_KEY } from '../../services/const-data/const-data' 3 | Component({ 4 | data: {}, 5 | properties: { 6 | modalName: { 7 | type: String, 8 | value: null 9 | } 10 | }, 11 | options: { 12 | addGlobalClass: true 13 | }, 14 | methods: { 15 | hideModal(e) { 16 | this.setData({ 17 | modalName: null 18 | }) 19 | }, 20 | /** 21 | * 获取用户信息 22 | * @param {*} e 23 | */ 24 | getUserProfile(e) { 25 | wx.getUserProfile({ 26 | desc: '用于昵称、头像展示', 27 | lang: 'cn', 28 | success: res => { 29 | wx.setStorageSync(STORAGE_KEY.user, res.userInfo) 30 | this.setData({ 31 | modalName: null 32 | }) 33 | return apiResult.success('登录成功') 34 | } 35 | }) 36 | }, 37 | // 阻止滑动 38 | preventTouchMove() {} 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /miniprogram/components/article-list/index.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../../services/const-data/theme-setting-key' 2 | 3 | // 获取应用实例 4 | const app = getApp() 5 | Component({ 6 | data: { 7 | randomGraphs: [] 8 | }, 9 | properties: { 10 | content: { 11 | type: Array, 12 | value: [] 13 | }, 14 | isMore: { 15 | type: Boolean, 16 | value: true 17 | }, 18 | layout: { 19 | type: String, 20 | value: 'card' 21 | } 22 | }, 23 | options: { 24 | addGlobalClass: true 25 | }, 26 | pageLifetimes: { 27 | async show() { 28 | if (!app.globalData.hasInit) { 29 | await app.init() 30 | } 31 | this.setData({ 32 | randomGraphs: app.themeSettings[THEME_SETTING_KEY.RANDOM_IMAGE] 33 | }) 34 | } 35 | }, 36 | methods: { 37 | details(e) { 38 | // 详情页跳转 39 | wx.navigateTo({ 40 | url: '/pages/details/index?id=' + e.currentTarget.id 41 | }) 42 | } 43 | } 44 | }) 45 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/tag.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/tags' 4 | 5 | /** 6 | * 获取标签 7 | * @param {*} params 8 | */ 9 | function getTags(params) { 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(moduleName, params).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | /** 23 | * 获取标签下的文章 24 | * @param {标签别名} slug 25 | * @param {*} params 26 | */ 27 | function getTagsArticle(slug, params) { 28 | const url = moduleName + '/' + slug + '/posts' 29 | return new Promise((resolve, reject) => { 30 | apiRequest.Get(url, params).then( 31 | r => { 32 | resolve(r) 33 | }, 34 | e => { 35 | reject(e) 36 | } 37 | ) 38 | }) 39 | } 40 | 41 | module.exports = { 42 | getTags, 43 | getTagsArticle 44 | } 45 | -------------------------------------------------------------------------------- /miniprogram/images/icon/about-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/theme.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/themes' 4 | /** 5 | * 获取主题设置 6 | * @param {*} key 7 | */ 8 | function getThemeSettings() { 9 | const url = moduleName + '/activation/settings' 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(url, {}).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | /** 23 | * 根据主题id获取主题设置 24 | * @param {*} key 25 | */ 26 | function getThemeSettingsById(id) { 27 | const url = moduleName + '/' + id + '/settings' 28 | return new Promise((resolve, reject) => { 29 | apiRequest.Get(url, {}).then( 30 | r => { 31 | resolve(r) 32 | }, 33 | e => { 34 | reject(e) 35 | } 36 | ) 37 | }) 38 | } 39 | module.exports = { 40 | getThemeSettings, 41 | getThemeSettingsById 42 | } 43 | -------------------------------------------------------------------------------- /miniprogram/images/icon/love.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/category.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/categories' 4 | 5 | /** 6 | * 获取分类 7 | * @param {*} params 8 | */ 9 | function getCategories(params) { 10 | return new Promise((resolve, reject) => { 11 | apiRequest.Get(moduleName, params).then( 12 | r => { 13 | resolve(r) 14 | }, 15 | e => { 16 | reject(e) 17 | } 18 | ) 19 | }) 20 | } 21 | 22 | /** 23 | * 获取分类下的文章 24 | * @param {分类名} slug 25 | * @param {*} params 26 | */ 27 | function getCategoriesArticle(slug, params) { 28 | const url = moduleName + '/' + slug + '/posts' 29 | return new Promise((resolve, reject) => { 30 | apiRequest.Get(url, params).then( 31 | r => { 32 | resolve(r) 33 | }, 34 | e => { 35 | reject(e) 36 | } 37 | ) 38 | }) 39 | } 40 | 41 | module.exports = { 42 | getCategories, 43 | getCategoriesArticle 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gblog-wx", 3 | "version": "1.1.0", 4 | "main": "index.js", 5 | "type": "commonjs", 6 | "repository": "git@github.com:fuzui/GBlog-wx.git", 7 | "author": "fuzui <73400@163.com>", 8 | "license": "MIT", 9 | "scripts": { 10 | "test": "echo 'Error: no test specified' && exit 1", 11 | "eslint": "eslint ./ --ext .js,.wxs,.sjs", 12 | "eslint:fix": "eslint --fix . --ext .js,.wxs,.sjs", 13 | "prettier:fix": "prettier --config .prettierrc.js --write './**/*.{js,sjs,wxs,css,wxss,acss,wxml,axml,less,scss,json}'" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "^7.16.0", 17 | "@babel/eslint-parser": "^7.16.0", 18 | "eslint": "^8.1.0", 19 | "eslint-config-prettier": "^8.3.0", 20 | "eslint-config-standard": "^16.0.3", 21 | "eslint-plugin-import": "^2.25.2", 22 | "eslint-plugin-node": "^11.1.0", 23 | "eslint-plugin-prettier": "^4.0.0", 24 | "eslint-plugin-promise": "^5.1.1", 25 | "prettier": "^2.4.1", 26 | "prettier-eslint-cli": "^5.0.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /miniprogram/pages/photos/home/index.wxss: -------------------------------------------------------------------------------- 1 | /* 顶部样式 */ 2 | .fixed-nav { 3 | position: fixed; 4 | width: 100%; 5 | z-index: 1024; 6 | background-color: #bdd2ef !important; 7 | box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); 8 | } 9 | 10 | .search-form { 11 | /* background-color: rgb(175, 215, 237) !important; */ 12 | opacity: 0.4; 13 | width: 100rpx; 14 | } 15 | 16 | .search { 17 | background-color: white; 18 | opacity: 0.4; 19 | } 20 | 21 | /* picker .picker { 22 | line-height: 100rpx; 23 | font-size: 28rpx; 24 | text-overflow: ellipsis; 25 | white-space: nowrap; 26 | overflow: hidden; 27 | width: 100%; 28 | text-align: right; 29 | } */ 30 | 31 | /* picker::after { 32 | font-family: "cuIcon"; 33 | display: block; 34 | content: "\e6a3"; 35 | position: absolute; 36 | font-size: 34rpx; 37 | color: var(--grey); 38 | line-height: 100rpx; 39 | width: 60rpx; 40 | text-align: center; 41 | top: 0; 42 | bottom: 0; 43 | right: 120rpx; 44 | margin: auto; 45 | } */ 46 | 47 | .close { 48 | display: inline-flex; 49 | vertical-align: middle; 50 | } 51 | -------------------------------------------------------------------------------- /miniprogram/styles/colorui/components/cu-custom.js: -------------------------------------------------------------------------------- 1 | const app = getApp(); 2 | Component({ 3 | /** 4 | * 组件的一些选项 5 | */ 6 | options: { 7 | addGlobalClass: true, 8 | multipleSlots: true 9 | }, 10 | /** 11 | * 组件的对外属性 12 | */ 13 | properties: { 14 | bgColor: { 15 | type: String, 16 | default: '' 17 | }, 18 | isCustom: { 19 | type: [Boolean, String], 20 | default: false 21 | }, 22 | isBack: { 23 | type: [Boolean, String], 24 | default: false 25 | }, 26 | bgImage: { 27 | type: String, 28 | default: '' 29 | }, 30 | }, 31 | /** 32 | * 组件的初始数据 33 | */ 34 | data: { 35 | StatusBar: app.globalData.StatusBar, 36 | CustomBar: app.globalData.CustomBar, 37 | Custom: app.globalData.Custom 38 | }, 39 | /** 40 | * 组件的方法列表 41 | */ 42 | methods: { 43 | BackPage() { 44 | wx.navigateBack({ 45 | delta: 1 46 | }); 47 | }, 48 | toHome(){ 49 | wx.reLaunch({ 50 | url: '/pages/index/index', 51 | }) 52 | } 53 | } 54 | }) -------------------------------------------------------------------------------- /miniprogram/pages/about/links/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 友链 3 | 4 | 5 | 6 | 12 | 13 | 14 | {{item.name}} 15 | {{item.description}} 16 | 17 | 18 | {{item.url}} 19 | 20 | 21 | 22 | 23 | 24 | 加载中... 25 | 26 | -------------------------------------------------------------------------------- /miniprogram/pages/about/journal/index.wxss: -------------------------------------------------------------------------------- 1 | /* 日期 */ 2 | .cu-timeline .cu-time { 3 | width: 300rpx; 4 | text-align: left; 5 | padding: 20rpx 30rpx; 6 | font-size: 26rpx; 7 | color: #888; 8 | display: block; 9 | } 10 | /* 分割线 */ 11 | .title { 12 | font-size: 30rpx; 13 | font-weight: 900; 14 | color: var(--black); 15 | line-height: 100rpx; 16 | padding: 0 30rpx; 17 | } 18 | /* 分隔线--底部 */ 19 | .line { 20 | position: relative; 21 | top: 90rpx; 22 | width: 90%; /* 分隔线的长度 */ 23 | margin: auto; 24 | height: 1px; /* 分隔线粗细 */ 25 | text-align: center; 26 | font-size: 24rpx; 27 | color: #aaa; 28 | background: #ccc; 29 | margin-top: 5px; 30 | margin-bottom: 22px; 31 | } 32 | .line span { 33 | position: relative; 34 | top: -8px; 35 | background: #fff; 36 | padding: 0px 10px; 37 | } 38 | 39 | .cu-bar .action.sub-title text[class*='text-']:last-child { 40 | position: absolute; 41 | display: inline-block; 42 | bottom: -0.7rem; 43 | left: 0.5rem; 44 | opacity: 0.2; 45 | z-index: 0; 46 | text-align: center; 47 | font-weight: 900; 48 | font-size: 20rpx; 49 | } 50 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/environments/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 环境信息 4 | 5 | 6 | 7 | 8 | {{environments.version}} 9 | 10 | 11 | {{environments.database}} 12 | 13 | 14 | {{environments.mode}} 15 | 16 | 17 | {{tools.formatTime(environments.startTime)}} 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 扶醉 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 | -------------------------------------------------------------------------------- /miniprogram/images/icon/share.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/about/disclaimer/index.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 2 | 3 | // 获取应用实例 4 | const app = getApp() 5 | 6 | Page({ 7 | data: { 8 | mail: '' 9 | }, 10 | async onLoad() { 11 | const that = this 12 | if (!app.globalData.hasInit) { 13 | await app.init() 14 | } 15 | that.setData({ 16 | mail: app.themeSettings[THEME_SETTING_KEY.MAIL] 17 | }) 18 | }, 19 | CopyLink(e) { 20 | wx.setClipboardData({ 21 | data: e.currentTarget.dataset.link, 22 | success: res => { 23 | wx.showToast({ 24 | title: '已复制', 25 | duration: 1000 26 | }) 27 | } 28 | }) 29 | }, 30 | onShareAppMessage: function (res) { 31 | return { 32 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '免责声明', 33 | path: '/pages/about/disclaimer/index' 34 | } 35 | }, 36 | onShareTimeline: function (res) { 37 | return { 38 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '免责声明', 39 | imageUrl: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 40 | } 41 | } 42 | }) 43 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/environments/index.js: -------------------------------------------------------------------------------- 1 | import { adminGetEnvironments } from '../../../services/api/admin/environment' 2 | const app = getApp() 3 | Page({ 4 | data: { 5 | CustomBar: app.globalData.CustomBar, 6 | environments: {} 7 | }, 8 | onLoad: function () {}, 9 | async onShow() { 10 | const that = this 11 | that.setData({ 12 | loadModal: true 13 | }) 14 | const environments = await this.adminGetEnvironments() 15 | that.setData({ 16 | environments: environments, 17 | loadModal: false 18 | }) 19 | }, 20 | 21 | /** 22 | * 复制 23 | * @param {*} e 24 | */ 25 | CopyLink(e) { 26 | wx.setClipboardData({ 27 | data: e.currentTarget.dataset.link, 28 | success: res => { 29 | wx.showToast({ 30 | title: '已复制', 31 | duration: 1000 32 | }) 33 | } 34 | }) 35 | }, 36 | /** 37 | * 获取服务器配置信息 38 | */ 39 | async adminGetEnvironments() { 40 | try { 41 | const result = await adminGetEnvironments() 42 | return result 43 | } catch (error) { 44 | return error.message 45 | } 46 | } 47 | }) 48 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/login.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/login' 5 | 6 | /** 7 | * 登录 8 | * @param {*} params 9 | */ 10 | function adminLogin(params) { 11 | const adminToken = { 12 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 13 | } 14 | return new Promise((resolve, reject) => { 15 | apiRequest.Post(moduleName, params, adminToken).then( 16 | r => { 17 | resolve(r) 18 | }, 19 | e => { 20 | reject(e) 21 | } 22 | ) 23 | }) 24 | } 25 | 26 | /** 27 | * 登录前置检查 28 | * @param {*} params 29 | */ 30 | function adminLoginPreCheck(params) { 31 | const url = moduleName + '/precheck' 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Post(url, params, {}).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | module.exports = { 45 | adminLogin, 46 | adminLoginPreCheck 47 | } 48 | -------------------------------------------------------------------------------- /miniprogram/images/icon/home-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/components/authorize/index.wxss: -------------------------------------------------------------------------------- 1 | @import '/app.wxss'; 2 | /* 登录提示 */ 3 | .login-modal { 4 | position: fixed; 5 | top: 0; 6 | right: 0; 7 | bottom: 0; 8 | left: 0; 9 | z-index: 1110; 10 | opacity: 0; 11 | outline: 0; 12 | text-align: center; 13 | -ms-transform: scale(1.185); 14 | transform: scale(1.185); 15 | backface-visibility: hidden; 16 | perspective: 2000rpx; 17 | background: rgba(0, 0, 0, 0.6); 18 | transition: all 0.3s ease-in-out 0s; 19 | pointer-events: none; 20 | } 21 | 22 | .login-modal::before { 23 | content: '\200B'; 24 | display: inline-block; 25 | height: 100%; 26 | vertical-align: middle; 27 | } 28 | 29 | .login-modal.show { 30 | opacity: 1; 31 | transition-duration: 0.3s; 32 | -ms-transform: scale(1); 33 | transform: scale(1); 34 | overflow-x: hidden; 35 | overflow-y: auto; 36 | pointer-events: auto; 37 | } 38 | 39 | .login-dialog { 40 | position: relative; 41 | display: inline-block; 42 | vertical-align: middle; 43 | margin-left: auto; 44 | margin-right: auto; 45 | width: 500rpx; 46 | max-width: 100%; 47 | background-color: #f8f8f8; 48 | border-radius: 10rpx; 49 | overflow: hidden; 50 | } 51 | -------------------------------------------------------------------------------- /miniprogram/pages/comment/publish/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 发布 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 |
10 | 11 | 18 | 19 | 20 | 邮箱地址 21 | 22 | 23 | 24 | 回复是否接受推送 25 | 26 | 27 | 28 |
29 |
30 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/audio.wxss: -------------------------------------------------------------------------------- 1 | ._contain{position:relative;display:inline-flex;width:290px;background-color:#fcfcfc;border:1px solid #e0e0e0;border-radius:2px}._button{display:flex;align-items:center;justify-content:center;width:20px;height:20px;overflow:hidden;background-color:rgb(0,0,0,.2);border:1px solid #fff;border-radius:50%;opacity:.9}._play{margin-left:2px;border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:8px solid #fff}._pause{width:8px;height:8px;background-color:#fff}._poster{display:flex;align-items:center;justify-content:center;width:70px;height:70px;background-color:#e6e6e6;background-size:contain}._title{flex:1;margin:4px 0 0 14px;text-align:left}._author{width:45px;font-size:12px;color:#888}._name{width:140px;font-size:15px;line-height:39px}._author,._name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._slider{position:absolute;right:16px;bottom:8px;width:140px;margin:0}._time{margin:7px 14px 0 0;font-size:12px;color:#888}@media (min-width:400px){._contain{width:380px}._button{width:26px;height:26px}._poster{width:90px;height:90px}._author{width:60px;font-size:15px}._name{width:180px;font-size:19px;line-height:55px}._slider{right:20px;bottom:10px;width:180px}._time{font-size:15px}} -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/highlight/index.js: -------------------------------------------------------------------------------- 1 | "use strict";function e(e){this.vm=e}var r=require("./prism.min"),s=require("./config"),t=require("../parser");e.prototype.onParse=function(e,a){if("pre"===e.name){var n;for(n=e.children.length;n--&&"code"!==e.children[n].name;);if(-1===n)return;var l=e.children[n],i=l.attrs.class||"";n=i.indexOf("language-"),-1===n&&(i=e.attrs.class||"",n=i.indexOf("language-")),-1===n&&(i="language-text",n=i.indexOf("language-")),n+=9;var c;for(c=n;c"+r.highlight(g,r.languages[h],h).replace(/token /g,"hl-")+"")[0].children),e.attrs.class="hl-pre",l.attrs.class="hl-code",s.showLanguageName&&e.children.push({name:"div",attrs:{class:"hl-language",style:"user-select:none"},children:[{type:"text",text:h}]}),s.copyByLongPress&&(e.attrs.style+=(e.attrs.style||"")+";user-select:none",e.attrs["data-content"]=g,a.expose()),s.showLineNumber){for(var p=g.split("\n").length,u=[],o=p;o--;)u.push({name:"span",attrs:{class:"span"}});e.children.push({name:"span",attrs:{class:"line-numbers-rows"},children:u})}}}},module.exports=e; -------------------------------------------------------------------------------- /miniprogram/images/icon/poster.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 16 | 17 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: false, 6 | singleQuote: true, 7 | 8 | // 对象的 key 仅在必要时用引号 9 | quoteProps: 'as-needed', 10 | 11 | // jsx 不使用单引号,而使用双引号 12 | jsxSingleQuote: false, 13 | 14 | // 末尾不需要逗号 15 | trailingComma: 'none', 16 | 17 | // 大括号内的首尾需要空格 18 | bracketSpacing: true, 19 | 20 | // 标签的反尖括号需要换行 21 | bracketSameLine: false, 22 | 23 | // 箭头函数,只有一个参数的时候,无需括号 24 | arrowParens: 'avoid', 25 | 26 | // 每个文件格式化的范围是文件的全部内容 27 | rangeStart: 0, 28 | 29 | rangeEnd: Infinity, 30 | 31 | // 不需要写文件开头的 @prettier 32 | requirePragma: false, 33 | 34 | // 不需要自动在文件开头插入 @prettier 35 | insertPragma: false, 36 | 37 | // 使用默认的折行标准 38 | proseWrap: 'preserve', 39 | 40 | // 根据显示样式决定 html 要不要折行 41 | htmlWhitespaceSensitivity: 'css', 42 | 43 | // 换行符使用 lf 44 | endOfLine: 'lf', 45 | overrides: [ 46 | { 47 | files: ['*.wxss', '*.acss'], 48 | options: { 49 | parser: 'css' 50 | } 51 | }, 52 | { 53 | files: ['*.wxml', '*.axml'], 54 | options: { 55 | parser: 'html' 56 | } 57 | }, 58 | { 59 | files: ['*.wxs', '*.sjs'], 60 | options: { 61 | parser: 'babel' 62 | } 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/journal/home/index.wxss: -------------------------------------------------------------------------------- 1 | .cu-bar.btn-group button { 2 | padding: 20rpx 32rpx; 3 | flex: 1; 4 | margin: 0 20rpx; 5 | max-width: 80%; 6 | } 7 | textarea { 8 | border: medium double blue; 9 | } 10 | /* 日期 */ 11 | .cu-timeline .cu-time { 12 | width: 300rpx; 13 | text-align: left; 14 | padding: 20rpx 30rpx; 15 | font-size: 26rpx; 16 | color: #888; 17 | display: block; 18 | } 19 | /* 分割线 */ 20 | .title { 21 | font-size: 30rpx; 22 | font-weight: 900; 23 | color: var(--black); 24 | line-height: 100rpx; 25 | padding: 0 30rpx; 26 | } 27 | /* 分隔线--底部 */ 28 | .line { 29 | position: relative; 30 | top: 90rpx; 31 | width: 90%; /* 分隔线的长度 */ 32 | margin: auto; 33 | height: 1px; /* 分隔线粗细 */ 34 | text-align: center; 35 | font-size: 24rpx; 36 | color: #aaa; 37 | background: #ccc; 38 | margin-top: 5px; 39 | margin-bottom: 22px; 40 | } 41 | .line span { 42 | position: relative; 43 | top: -8px; 44 | background: #fff; 45 | padding: 0px 10px; 46 | } 47 | 48 | .cu-bar .action.sub-title text[class*='text-']:last-child { 49 | position: absolute; 50 | display: inline-block; 51 | bottom: -0.7rem; 52 | left: 0.5rem; 53 | opacity: 0.2; 54 | z-index: 0; 55 | text-align: center; 56 | font-weight: 900; 57 | font-size: 20rpx; 58 | } 59 | -------------------------------------------------------------------------------- /miniprogram/images/icon/type-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/utils/api-result.js: -------------------------------------------------------------------------------- 1 | import { STORAGE_KEY } from '../services/const-data/const-data' 2 | function requestError(data) { 3 | wx.showToast({ 4 | title: data.message, 5 | duration: 1200, 6 | mask: true, 7 | image: '/images/prompt/fail.svg' 8 | }) 9 | if (data.status === 401) { 10 | wx.setStorageSync(STORAGE_KEY.adminToken, '') 11 | const pages = getCurrentPages() 12 | const currentPage = pages[pages.length - 1].route 13 | if (currentPage !== 'pages/admin/login/index') { 14 | wx.navigateTo({ 15 | url: '/pages/admin/login/index' 16 | }) 17 | } 18 | } 19 | } 20 | 21 | function error(msg) { 22 | wx.showToast({ 23 | title: msg, 24 | duration: 1500, 25 | mask: true, 26 | image: '/images/prompt/fail.svg' 27 | }) 28 | } 29 | function warn(msg) { 30 | wx.showToast({ 31 | title: msg, 32 | duration: 1500, 33 | mask: true, 34 | image: '/images/prompt/warn.svg' 35 | }) 36 | } 37 | function success(msg) { 38 | wx.showToast({ 39 | title: msg, 40 | duration: 2000, 41 | mask: true, 42 | image: '/images/prompt/success.svg' 43 | }) 44 | } 45 | 46 | const StateCode = { 47 | success: 200, 48 | error: 500 49 | } 50 | 51 | module.exports = { 52 | requestError, 53 | error, 54 | warn, 55 | success, 56 | StateCode 57 | } 58 | -------------------------------------------------------------------------------- /miniprogram/images/icon/admin-hover.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/about.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/gitee.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/about/links/index.js: -------------------------------------------------------------------------------- 1 | import { getLinks } from '../../../services/api/content/link' 2 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 3 | 4 | const app = getApp() 5 | 6 | Page({ 7 | data: { 8 | logo: '', 9 | bottomFlag: false, 10 | links: [], 11 | bgColor: ['green', 'red', 'grey', 'blue', 'cyan', 'purple'] 12 | }, 13 | onLoad: function () { 14 | const that = this 15 | that.setData({ 16 | logo: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 17 | }) 18 | }, 19 | async onShow() { 20 | const that = this 21 | that.setData({ 22 | loadModal: true 23 | }) 24 | const links = await this.getLinks() 25 | that.setData({ 26 | links: links, 27 | loadModal: false 28 | }) 29 | }, 30 | /** 31 | * 获取友链 32 | */ 33 | async getLinks() { 34 | try { 35 | const param = {} 36 | const result = await getLinks(param) 37 | return result 38 | } catch (error) { 39 | return await Promise.reject(error) 40 | } 41 | }, 42 | /** 43 | * 复制 44 | * @param {*} e 45 | */ 46 | copyLink(e) { 47 | wx.setClipboardData({ 48 | data: e.currentTarget.dataset.link, 49 | success: res => { 50 | wx.showToast({ 51 | title: '已复制', 52 | duration: 1000 53 | }) 54 | } 55 | }) 56 | } 57 | }) 58 | -------------------------------------------------------------------------------- /miniprogram/pages/type/home/index.wxss: -------------------------------------------------------------------------------- 1 | /* 图标 */ 2 | .cu-list > .cu-item > button > .share image { 3 | display: inline-block; 4 | width: 1.5em; 5 | height: 1.5em; 6 | vertical-align: middle; 7 | } 8 | 9 | .cu-list > .cu-item > button { 10 | line-height: 1; 11 | margin: 0; 12 | background-color: #fff; 13 | } 14 | .cu-list > .cu-item > button::after { 15 | border: none; 16 | } 17 | 18 | /* 分类卡片 */ 19 | 20 | .type-card { 21 | display: block; 22 | overflow: hidden; 23 | } 24 | 25 | .type-card > .cu-item { 26 | display: block; 27 | background-color: var(--white); 28 | overflow: hidden; 29 | border-radius: 10rpx; 30 | margin: 30rpx; 31 | } 32 | 33 | .type-card > .cu-item.shadow-blur { 34 | overflow: initial; 35 | } 36 | 37 | .type-card.no-card > .cu-item { 38 | margin: 0rpx; 39 | border-radius: 0rpx; 40 | } 41 | 42 | .type-card .grid.grid-square { 43 | margin-bottom: -20rpx; 44 | } 45 | 46 | .type-card.case .image { 47 | position: relative; 48 | } 49 | 50 | .type-card.case .image .cu-capsule { 51 | position: absolute; 52 | right: 0; 53 | top: 0; 54 | } 55 | 56 | .type-card.case .image .cu-bar { 57 | position: absolute; 58 | bottom: 0; 59 | width: 100%; 60 | background-color: transparent; 61 | padding: 0rpx 30rpx; 62 | } 63 | 64 | .type-card.case.no-card .image { 65 | margin: 30rpx 30rpx 0; 66 | overflow: hidden; 67 | border-radius: 10rpx; 68 | } 69 | -------------------------------------------------------------------------------- /miniprogram/pages/about/disclaimer/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 免责声明 3 | 4 | 5 | 免责声明 6 | 7 | 1、本网站属于个人非赢利性质的网站,所有转载的文章都以遵循原作者的版权声明注明了文章来源。 8 | 2、如果原文没有版权声明,按照目前互联网开放的原则,本网站将在不通知作者的情况下转载文章。 11 | 3、如果原文明确注明“禁止转载”,本网站将不会转载。 12 | 4、如果本网站转载的文章不符合作者的版权声明或者作者不想让本网站转载您的文章,请邮件告知{{mail}},本站将会在第一时间删除相关信息! 20 | 5、本网站转载文章仅为留作备份和知识点分享的目的。 21 | 6、本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担相关责任。 24 | 7、本网站所发布、转载的文章,其版权均归原作者所有。如其他自媒体、网站或个人从本网站下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网站注明的“原文来源”或者自行去原文处复制版权声明,并自负版权等法律责任。 27 | 8、本网站的所有原创文章皆可以任意转载,但转载时务必请注明出处。 28 | 9、尊重原创,知识共享! 29 | 30 | 31 | -------------------------------------------------------------------------------- /miniprogram/images/icon/photo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/service.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/comment.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/attachment/select/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 附件选择 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 加载中... 33 | 34 | -------------------------------------------------------------------------------- /miniprogram/components/painter/painter.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 18 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /miniprogram/services/api/content/sheet.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | const moduleName = ApiBaseUrl + '/api/content/sheets' 4 | 5 | /** 6 | * 获取sheet详情 7 | * @param {*} id 8 | * @param {*} params 9 | */ 10 | function getSheetDetails(id, params) { 11 | const url = moduleName + '/' + id 12 | return new Promise((resolve, reject) => { 13 | apiRequest.Get(url, params).then( 14 | r => { 15 | resolve(r) 16 | }, 17 | e => { 18 | reject(e) 19 | } 20 | ) 21 | }) 22 | } 23 | 24 | /** 25 | * 获取sheet评论 26 | * @param {sheet id} id 27 | * @param {*} params 28 | */ 29 | function getCommentsBySheetId(id, params) { 30 | const url = moduleName + '/' + id + '/comments/tree_view' 31 | return new Promise((resolve, reject) => { 32 | apiRequest.Get(url, params).then( 33 | r => { 34 | resolve(r) 35 | }, 36 | e => { 37 | reject(e) 38 | } 39 | ) 40 | }) 41 | } 42 | /** 43 | * 撰写sheet评论 44 | * @param {*} params 45 | */ 46 | function writeSheetComment(params) { 47 | const url = moduleName + '/comments' 48 | return new Promise((resolve, reject) => { 49 | apiRequest.Post(url, params, {}).then( 50 | r => { 51 | resolve(r) 52 | }, 53 | e => { 54 | reject(e) 55 | } 56 | ) 57 | }) 58 | } 59 | 60 | module.exports = { 61 | getSheetDetails, 62 | getCommentsBySheetId, 63 | writeSheetComment 64 | } 65 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/style/index.js: -------------------------------------------------------------------------------- 1 | "use strict";function t(){this.styles=[]}function e(t,e){function r(e){if("#"===e[0]){if(t.attrs.id&&t.attrs.id.trim()===e.substr(1))return 3}else if("."===e[0]){e=e.substr(1);for(var r=(t.attrs.class||"").split(" "),s=0;ss&&(s=i)}return s}return r(e)}var r=require("./parser");t.prototype.onParse=function(t,s){if("style"===t.name&&t.children.length&&"text"===t.children[0].type)this.styles=this.styles.concat((new r).parse(t.children[0].text));else if(t.name){for(var n=["","","",""],i=0,l=this.styles.length;i=0&&o--;)if(">"===a.list[c]){if(c<1||c>a.list.length-2)break;e(s.stack[o],a.list[c-1])?c-=2:c++}else e(s.stack[o],a.list[c])&&c--;f=4}if(a.key||c<0)if(a.pseudo&&t.children){var u=void 0;a.style=a.style.replace(/content:([^;]+)/,function(e,r){return u=r.replace(/['"]/g,"").replace(/attr\((.+?)\)/,function(e,r){return t.attrs[r.trim()]||""}).replace(/\\(\w{4})/,function(t,e){return String.fromCharCode(parseInt(e,16))}),""});var h={name:"span",attrs:{style:a.style},children:[{type:"text",text:u}]};"before"===a.pseudo?t.children.unshift(h):t.children.push(h)}else n[f-1]+=a.style+(";"===a.style[a.style.length-1]?"":";")}}n=n.join(""),n.length>2&&(t.attrs.style=n+(t.attrs.style||""))}},module.exports=t; -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | /* 2 | 微信小程序不支持CSS3的CSS变量,但是这里定义样式变量,主要是为了规范诸如颜色、边线、字体大小等 3 | */ 4 | @import 'styles/colorui/main.wxss'; 5 | @import 'styles/colorui/icon.wxss'; 6 | @import 'styles/colorui/animation.wxss'; 7 | page { 8 | font-family: JetBrainsMono, -apple-system-font, Helvetica Neue, sans-serif; 9 | } 10 | 11 | /* 显示两行,溢出文字用‘...’替换 */ 12 | .ellipsis-1row { 13 | text-overflow: ellipsis; 14 | display: -webkit-box; 15 | -webkit-line-clamp: 1; 16 | -webkit-box-orient: vertical; 17 | overflow: hidden; 18 | } 19 | .ellipsis-2row { 20 | text-overflow: ellipsis; 21 | display: -webkit-box; 22 | -webkit-line-clamp: 2; 23 | -webkit-box-orient: vertical; 24 | overflow: hidden; 25 | } 26 | .ellipsis-3row { 27 | text-overflow: ellipsis; 28 | display: -webkit-box; 29 | -webkit-line-clamp: 3; 30 | -webkit-box-orient: vertical; 31 | overflow: hidden; 32 | } 33 | .ellipsis-4row { 34 | text-overflow: ellipsis; 35 | display: -webkit-box; 36 | -webkit-line-clamp: 4; 37 | -webkit-box-orient: vertical; 38 | overflow: hidden; 39 | } 40 | 41 | .text-muted { 42 | color: #888888; 43 | font-size: 28rpx; 44 | line-height: 170%; 45 | text-align: left; 46 | } 47 | 48 | /* 无结果图 */ 49 | .no-content { 50 | display: flex; 51 | justify-content: center; 52 | display: block; 53 | text-align: center; 54 | align-items: center; 55 | } 56 | .no-content image { 57 | margin-top: 70rpx; 58 | width: 400rpx; 59 | height: 400rpx; 60 | } 61 | 62 | .bg-theme { 63 | background-color: #bdd2ef !important; 64 | } 65 | -------------------------------------------------------------------------------- /miniprogram/images/icon/article.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /miniprogram/components/image-loader/index.js: -------------------------------------------------------------------------------- 1 | import { ApiBaseUrl } from '../../config/api' 2 | import { THEME_SETTING_KEY } from '../../services/const-data/theme-setting-key' 3 | 4 | const app = getApp() 5 | Component({ 6 | externalClasses: ['custom-class'], 7 | properties: { 8 | defaultImage: { 9 | type: String, 10 | value: '' 11 | }, 12 | loadErrorImage: { 13 | type: String, 14 | value: '' 15 | }, 16 | originalImage: { 17 | type: String, 18 | value: '' 19 | }, 20 | width: { 21 | type: String, 22 | value: '' 23 | }, 24 | height: { 25 | type: String, 26 | value: '' 27 | }, 28 | mode: { 29 | type: String, 30 | value: 'widthFix' 31 | }, 32 | randomGraphs: { 33 | type: Array, 34 | value: [] 35 | } 36 | }, 37 | data: { 38 | ApiBaseUrl, 39 | finishLoadFlag: false, 40 | loadErrorFlag: false 41 | }, 42 | lifetimes: { 43 | async attached() { 44 | if (!app.globalData.hasInit) { 45 | await app.init() 46 | } 47 | this.setData({ 48 | defaultImage: app.themeSettings[THEME_SETTING_KEY.PLACEHOLDER_IMAGE], 49 | loadErrorImage: app.themeSettings[THEME_SETTING_KEY.LOAD_ERROR_IMAGE] 50 | }) 51 | } 52 | }, 53 | methods: { 54 | finishLoad: function (e) { 55 | this.setData({ 56 | finishLoadFlag: true 57 | }) 58 | }, 59 | loadError: function (e) { 60 | this.setData({ 61 | loadErrorFlag: true 62 | }) 63 | } 64 | } 65 | }) 66 | -------------------------------------------------------------------------------- /miniprogram/services/const-data/theme-setting-key.js: -------------------------------------------------------------------------------- 1 | export const THEME_SETTING_KEY = { 2 | BLOG_TITLE: 'blog_title', 3 | BLOG_LOGO: 'blog_logo', 4 | GUESTBOOK_SHEET_ID: 'guestbook_sheet_id', 5 | CLOUD_IS_OPEN: 'cloud_is_open', 6 | CLOUD_ENV: 'cloud_env', 7 | CLOUD_SHARE_OPEN: 'cloud_share_open', 8 | CLOUD_CHECK_MESSAGE: 'cloud_check_message', 9 | CLOUD_ADMIN_USER: 'cloud_admin_user', 10 | BLOG: 'blog', 11 | QQ: 'qq', 12 | WX: 'wx', 13 | MAIL: 'mail', 14 | GITHUB: 'github', 15 | GITEE: 'gitee', 16 | WX_MP: 'wx_mp', 17 | NO_CONTENT_IMAGE: 'no_content_image', 18 | PLACEHOLDER_IMAGE: 'placeholder_image', 19 | LOAD_ERROR_IMAGE: 'load_error_image', 20 | RANDOM_IMAGE: 'random_image', 21 | POST_TAG_STYLE: 'post_tag_style', 22 | POST_CONTAINER_STYLE: 'post_container_style', 23 | COMMENT_TAG_STYLE: 'comment_tag_style', 24 | COMMENT_CONTAINER_STYLE: 'comment_container_style', 25 | JOURNAL_TAG_STYLE: 'journal_tag_style', 26 | JOURNAL_CONTAINER_STYLE: 'journal_container_style', 27 | TAB_BAR_HOME: 'tab_bar_home', 28 | TAB_BAR_CATEGORY: 'tab_bar_category', 29 | TAB_BAR_PHOTO: 'tab_bar_photo', 30 | TAB_BAR_ABOUT: 'tab_bar_about', 31 | TAB_BAR_ADMIN: 'tab_bar_admin', 32 | SWIPER_START: 'swiper_start', 33 | PAGE_SIZE_SWIPER: 'page_size_swiper', 34 | PAGE_SIZE_INDEX: 'page_size_index', 35 | PAGE_SIZE_SEARCH: 'page_size_search', 36 | PAGE_SIZE_CATEGORY: 'page_size_category', 37 | PAGE_SIZE_TAG: 'page_size_tag', 38 | PAGE_SIZE_PHOTO: 'page_size_photo', 39 | PAGE_SIZE_JOURNAL: 'page_size_journal', 40 | PAGE_SIZE_ATTACHMENT: 'page_size_attachment' 41 | } 42 | -------------------------------------------------------------------------------- /miniprogram/pages/about/journal/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 日记 4 | 5 | 6 | 7 | 记我所见所闻所思 8 | Remember what I saw, heard and thought 9 | 10 | 11 | 12 | 13 | 14 | {{tools.getDateDiff(item.createTime)}} 15 | 16 | 17 | 28 | 29 | 30 | 31 | 32 | 33 | 这天开始写日记的~ 34 | 35 | 36 | 37 | 38 | 39 | 加载中... 40 | 41 | -------------------------------------------------------------------------------- /miniprogram/pages/about/archives/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 文章归档 3 | 4 | 5 | 6 | {{articleNum}} 7 | 文章总数 8 | 9 | 10 | {{categoryNum}} 11 | 分类总数 12 | 13 | 14 | {{tagNum}} 15 | 标签总数 16 | 17 | 18 | 19 | 20 | {{year.year}}-{{year.month}} 21 | 22 | 23 | 24 | {{article.title}} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 加载中... 34 | 35 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/audio/audio.js: -------------------------------------------------------------------------------- 1 | "use strict";var t=require("./context");Component({data:{time:"00:00"},properties:{name:String,author:String,poster:String,autoplay:Boolean,controls:Boolean,loop:Boolean,src:{type:String,observer:function(t){this.setSrc(t)}}},created:function(){var t=this;this._ctx=wx.createInnerAudioContext(),this._ctx.onError(function(i){t.setData({error:!0}),t.triggerEvent("error",i)}),this._ctx.onTimeUpdate(function(){var i=t._ctx.currentTime,e=parseInt(i/60),s=Math.ceil(i%60),a={};a.time=(e>9?e:"0"+e)+":"+(s>9?s:"0"+s),t.lastTime||(a.value=i/t._ctx.duration*100),t.setData(a)}),this._ctx.onEnded(function(){t.data.loop||t.setData({playing:!1})})},attached:function(){t.set(this.id,this)},detached:function(){this._ctx.destroy(),t.remove(this.data.audioId)},pageLifetimes:{show:function(){this.data.playing&&this._ctx.paused&&this._ctx.play()}},methods:{setSrc:function(t){this._ctx.autoplay=this.data.autoplay,this._ctx.loop=this.data.loop,this._ctx.src=t,this.data.autoplay&&!this.data.playing&&this.setData({playing:!0})},play:function(){this._ctx.play(),this.setData({playing:!0}),this.triggerEvent("play")},pause:function(){this._ctx.pause(),this.setData({playing:!1}),this.triggerEvent("pause")},stop:function(){this._ctx.stop(),this.setData({playing:!1,time:"00:00"}),this.triggerEvent("stop")},seek:function(t){this._ctx.seek(t)},_seeking:function(t){if(!(t.timeStamp-this.lastTime<200)){var i=Math.round(t.detail.value/100*this._ctx.duration),e=parseInt(i/60),s=i%60;this.setData({time:(e>9?e:"0"+e)+":"+(s>9?s:"0"+s)}),this.lastTime=t.timeStamp}},_seeked:function(t){this._ctx.seek(t.detail.value/100*this._ctx.duration),this.lastTime=void 0}}}); -------------------------------------------------------------------------------- /miniprogram/pages/comment/home/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 全部{{title}} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 加载中... 18 | 19 | 20 | 21 | 22 | 23 | 31 | 32 | 33 | 34 | 35 | {{commentCount}} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 加载中... 43 | 44 | -------------------------------------------------------------------------------- /miniprogram/pages/share/index.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../../services/const-data/theme-setting-key' 2 | 3 | const app = getApp() 4 | Page({ 5 | data: { 6 | shareImage: null, 7 | path: null 8 | }, 9 | onLoad: function () { 10 | const eventChannel = this.getOpenerEventChannel() 11 | eventChannel.on('shareImage', data => { 12 | this.setData({ 13 | shareImage: data.shareImage, 14 | path: '/pages/details/index?id=' + data.id 15 | }) 16 | }) 17 | }, 18 | onShareAppMessage: function (res) { 19 | return { 20 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '分享海报', 21 | imageUrl: this.data.shareImage, 22 | path: this.data.path 23 | } 24 | }, 25 | onShareTimeline: function (res) { 26 | return { 27 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '分享海报', 28 | imageUrl: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 29 | } 30 | }, 31 | saveImage() { 32 | const { shareImage } = this.data 33 | if (shareImage) { 34 | this.saveImageToPhotosAlbum({ 35 | filePath: shareImage 36 | }).then(() => { 37 | wx.showToast({ 38 | icon: 'none', 39 | title: '海报已保存至相册', 40 | duration: 2000 41 | }) 42 | }) 43 | } 44 | }, 45 | // 保存图片 46 | saveImageToPhotosAlbum(option) { 47 | return new Promise((resolve, reject) => { 48 | wx.saveImageToPhotosAlbum({ 49 | ...option, 50 | success: resolve, 51 | fail: reject 52 | }) 53 | }) 54 | }, 55 | backPage() { 56 | wx.navigateBack({ 57 | delta: 1 58 | }) 59 | } 60 | }) 61 | -------------------------------------------------------------------------------- /miniprogram/components/article-list/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 置顶 7 | {{item.title}} 8 | 9 | 10 | 11 | 17 | 18 | {{item.summary}} 19 | 20 | 21 | {{item.categories[0].name}} 22 | 23 | {{tools.tsFormatTime(item.createTime)}} 26 | 27 | 28 | {{item.visits}} 29 | {{item.likes}} 30 | 31 | {{item.commentCount}} 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /miniprogram/images/icon/type.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/user.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/users' 5 | 6 | /** 7 | * 获取用户信息 8 | */ 9 | function adminGetUserProfile() { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | const url = moduleName + '/profiles' 14 | return new Promise((resolve, reject) => { 15 | apiRequest.Get(url, adminToken).then( 16 | r => { 17 | resolve(r) 18 | }, 19 | e => { 20 | reject(e) 21 | } 22 | ) 23 | }) 24 | } 25 | 26 | /** 27 | * 修改用户信息 28 | */ 29 | function adminEditUser(param) { 30 | const adminToken = { 31 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 32 | } 33 | const url = moduleName + '/profiles' 34 | return new Promise((resolve, reject) => { 35 | apiRequest.Put(url, param, adminToken).then( 36 | r => { 37 | resolve(r) 38 | }, 39 | e => { 40 | reject(e) 41 | } 42 | ) 43 | }) 44 | } 45 | 46 | /** 47 | * 修改用户信息 48 | */ 49 | function adminEditPassword(param) { 50 | const adminToken = { 51 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 52 | } 53 | const url = moduleName + '/profiles/password' 54 | return new Promise((resolve, reject) => { 55 | apiRequest.Put(url, param, adminToken).then( 56 | r => { 57 | resolve(r) 58 | }, 59 | e => { 60 | reject(e) 61 | } 62 | ) 63 | }) 64 | } 65 | 66 | module.exports = { 67 | adminGetUserProfile, 68 | adminEditUser, 69 | adminEditPassword 70 | } 71 | -------------------------------------------------------------------------------- /miniprogram/images/icon/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/cloud/user.js: -------------------------------------------------------------------------------- 1 | import { Config } from '../../../config/api' 2 | /** 3 | * 检查用户 4 | */ 5 | function checkUser(openid) { 6 | return new Promise((resolve, reject) => { 7 | const db = wx.cloud.database({ 8 | env: Config.cloudEnv 9 | }) 10 | db.collection('admin_user').get({ 11 | success: function (res) { 12 | if (res.data.length === 0) { 13 | resolve({}) 14 | } else { 15 | resolve(res.data[0]) 16 | } 17 | }, 18 | fail(e) { 19 | reject(e) 20 | } 21 | }) 22 | }) 23 | } 24 | 25 | /** 26 | * 创建用户 27 | */ 28 | function createUser(param) { 29 | return new Promise((resolve, reject) => { 30 | const db = wx.cloud.database({ 31 | env: Config.cloudEnv 32 | }) 33 | db.collection('admin_user').add({ 34 | data: { 35 | username: param.username, 36 | password: param.password 37 | }, 38 | success: function (res) { 39 | resolve(res.data) 40 | }, 41 | fail(e) { 42 | reject(e) 43 | } 44 | }) 45 | }) 46 | } 47 | 48 | /** 49 | * 更新用户 50 | */ 51 | function updateUser(param) { 52 | return new Promise((resolve, reject) => { 53 | const db = wx.cloud.database({ 54 | env: Config.cloudEnv 55 | }) 56 | db.collection('admin_user') 57 | .doc(param.id) 58 | .update({ 59 | data: { 60 | username: param.username, 61 | password: param.password 62 | }, 63 | success: function (res) { 64 | resolve(res.data) 65 | }, 66 | fail(e) { 67 | reject(e) 68 | } 69 | }) 70 | }) 71 | } 72 | 73 | module.exports = { 74 | checkUser, 75 | createUser, 76 | updateUser 77 | } 78 | -------------------------------------------------------------------------------- /miniprogram/components/painter/lib/util.js: -------------------------------------------------------------------------------- 1 | 2 | function isValidUrl(url) { 3 | return /(ht|f)tp(s?):\/\/([^ \\/]*\.)+[^ \\/]*(:[0-9]+)?\/?/.test(url); 4 | } 5 | 6 | /** 7 | * 深度对比两个对象是否一致 8 | * from: https://github.com/epoberezkin/fast-deep-equal 9 | * @param {Object} a 对象a 10 | * @param {Object} b 对象b 11 | * @return {Boolean} 是否相同 12 | */ 13 | /* eslint-disable */ 14 | function equal(a, b) { 15 | if (a === b) return true; 16 | 17 | if (a && b && typeof a == 'object' && typeof b == 'object') { 18 | var arrA = Array.isArray(a) 19 | , arrB = Array.isArray(b) 20 | , i 21 | , length 22 | , key; 23 | 24 | if (arrA && arrB) { 25 | length = a.length; 26 | if (length != b.length) return false; 27 | for (i = length; i-- !== 0;) 28 | if (!equal(a[i], b[i])) return false; 29 | return true; 30 | } 31 | 32 | if (arrA != arrB) return false; 33 | 34 | var dateA = a instanceof Date 35 | , dateB = b instanceof Date; 36 | if (dateA != dateB) return false; 37 | if (dateA && dateB) return a.getTime() == b.getTime(); 38 | 39 | var regexpA = a instanceof RegExp 40 | , regexpB = b instanceof RegExp; 41 | if (regexpA != regexpB) return false; 42 | if (regexpA && regexpB) return a.toString() == b.toString(); 43 | 44 | var keys = Object.keys(a); 45 | length = keys.length; 46 | 47 | if (length !== Object.keys(b).length) 48 | return false; 49 | 50 | for (i = length; i-- !== 0;) 51 | if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; 52 | 53 | for (i = length; i-- !== 0;) { 54 | key = keys[i]; 55 | if (!equal(a[key], b[key])) return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | return a!==a && b!==b; 62 | } 63 | 64 | module.exports = { 65 | isValidUrl, 66 | equal 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /miniprogram/pages/about/home/index.js: -------------------------------------------------------------------------------- 1 | import { COMMENT_TYPE } from '../../../services/const-data/const-data' 2 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 3 | 4 | const app = getApp() 5 | 6 | Page({ 7 | data: { 8 | starCount: 0, 9 | forksCount: 0, 10 | visitTotal: 0, 11 | blogTitle: '' 12 | }, 13 | onLoad: function () {}, 14 | async onShow() { 15 | const that = this 16 | if (!app.globalData.hasInit) { 17 | await app.init() 18 | } 19 | if (typeof that.getTabBar === 'function' && that.getTabBar()) { 20 | that.getTabBar().setData({ 21 | selected: 3 22 | }) 23 | } 24 | that.setData({ 25 | blogTitle: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] 26 | }) 27 | }, 28 | 29 | /** 30 | * 复制 31 | * @param {*} e 32 | */ 33 | CopyLink(e) { 34 | wx.setClipboardData({ 35 | data: e.currentTarget.dataset.link, 36 | success: res => { 37 | wx.showToast({ 38 | title: '已复制', 39 | duration: 1000 40 | }) 41 | } 42 | }) 43 | }, 44 | /** 45 | * 跳转到标签页面 46 | */ 47 | toTagPage() { 48 | wx.navigateTo({ 49 | url: '/pages/tag/index' 50 | }) 51 | }, 52 | /** 53 | * 跳转到归档页面 54 | */ 55 | toArchivesPage() { 56 | wx.navigateTo({ 57 | url: '/pages/about/archives/index' 58 | }) 59 | }, 60 | /** 61 | * 跳转到留言页面 62 | */ 63 | toGuestbookPage() { 64 | wx.navigateTo({ 65 | url: 66 | '/pages/comment/home/index?id=' + 67 | app.themeSettings[THEME_SETTING_KEY.GUESTBOOK_SHEET_ID] + 68 | '&type=' + 69 | COMMENT_TYPE.guestbook 70 | }) 71 | }, 72 | /** 73 | * 跳转到日记页面 74 | */ 75 | toJournalPage() { 76 | wx.navigateTo({ 77 | url: '/pages/about/journal/index' 78 | }) 79 | } 80 | }) 81 | -------------------------------------------------------------------------------- /miniprogram/images/prompt/success.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /* 轮播图 */ 2 | .card-swiper { 3 | height: 520rpx !important; 4 | } 5 | 6 | .card-swiper swiper-item { 7 | width: 670rpx !important; 8 | left: 40rpx; 9 | box-sizing: border-box; 10 | padding: 150rpx 20rpx 10rpx; 11 | overflow: initial; 12 | } 13 | 14 | .card-swiper swiper-item .swiper-item { 15 | width: 100%; 16 | display: block; 17 | height: 100%; 18 | border-radius: 10rpx; 19 | transform: scale(0.9); 20 | transition: all 0.2s ease-in 0s; 21 | overflow: hidden; 22 | } 23 | 24 | .card-swiper swiper-item.cur .swiper-item { 25 | transform: none; 26 | transition: all 0.2s ease-in 0s; 27 | } 28 | /* 顶图样式 */ 29 | .recommend { 30 | background-size: cover; 31 | height: 630rpx; 32 | justify-content: center; 33 | padding-top: 90rpx; 34 | overflow: hidden; 35 | position: relative; 36 | flex-direction: column; 37 | align-items: center; 38 | color: #fff; 39 | font-weight: 300; 40 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 41 | } 42 | .recommend-swiper-before { 43 | position: absolute; 44 | top: 0rpx; 45 | left: -20%; 46 | height: 550rpx; 47 | width: 140%; 48 | border-radius: 0 0 50% 50%; 49 | background-color: #bdd2ef !important; 50 | } 51 | .fixed-bg { 52 | position: fixed; 53 | width: 100%; 54 | top: 0; 55 | z-index: 1024; 56 | box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); 57 | } 58 | 59 | /* 分类框 */ 60 | .fixed-nav { 61 | position: fixed; 62 | width: 100%; 63 | z-index: 1024; 64 | background-color: #bdd2ef !important; 65 | box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.1); 66 | } 67 | 68 | .search-form { 69 | /* background-color: rgb(175, 215, 237) !important; */ 70 | opacity: 0.4; 71 | width: 100rpx; 72 | } 73 | 74 | .ali-font { 75 | font-family: Ali, Helvetica Neue, Helvetica, sans-serif; 76 | font-weight: bold; 77 | font-size: 40rpx; 78 | text-align: center; 79 | } 80 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/photos/home/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 图库管理 4 | 5 | 6 | 7 | 8 | 手机传 9 | 10 | 11 | 12 | 即时拍 13 | 14 | 15 | 16 | 附件选 17 | 18 | 19 | 20 | 21 | 22 | 23 | 30 | {{item.name}} 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 加载中... 39 | 40 | 41 | 42 | 43 | 上传中... 44 | 45 | -------------------------------------------------------------------------------- /miniprogram/images/icon/know.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/style/parser.js: -------------------------------------------------------------------------------- 1 | "use strict";function t(){this.styles=[],this.selectors=[]}function s(t){this.selector="",this.style="",this.handler=t}var i={" ":!0,"\n":!0,"\t":!0,"\r":!0,"\f":!0};t.prototype.parse=function(t){return new s(this).parse(t),this.styles},t.prototype.onSelector=function(t){function s(t){var s,i,e=[];for(s=1,i=0;s"),l=0;l")}else i.key=s(t);this.selectors.push(i)}},t.prototype.onContent=function(t){for(var s=0;s -------------------------------------------------------------------------------- /miniprogram/images/icon/disclaimer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/tag.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/tags' 5 | 6 | /** 7 | * 获取标签列表 8 | */ 9 | function adminGetTag(param) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 添加标签 27 | */ 28 | function adminAddTag(data) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Post(moduleName, data, adminToken).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | /** 45 | * 根据id编辑标签 46 | */ 47 | function adminEditTag(tagId, param) { 48 | const adminToken = { 49 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 50 | } 51 | const url = moduleName + '/' + tagId 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Put(url, param, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据id删除标签 66 | */ 67 | function adminDeleteTag(tagId) { 68 | const adminToken = { 69 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 70 | } 71 | const url = moduleName + '/' + tagId 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Delete(url, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | module.exports = { 85 | adminGetTag, 86 | adminAddTag, 87 | adminEditTag, 88 | adminDeleteTag 89 | } 90 | -------------------------------------------------------------------------------- /miniprogram/pages/tag/index.wxss: -------------------------------------------------------------------------------- 1 | .tag-nav.nav { 2 | width: 200rpx; 3 | white-space: initial; 4 | } 5 | .tag-nav > .cu-item .flex .text-cut { 6 | max-width: 100rpx; 7 | align-items: center; 8 | justify-content: center; 9 | } 10 | .tag-nav.nav .cu-item { 11 | width: 100%; 12 | text-align: center; 13 | background-color: #fff; 14 | margin: 0; 15 | border: none; 16 | height: 50px; 17 | position: relative; 18 | } 19 | 20 | .tag-nav.nav .cu-item.cur { 21 | background-color: #f1f1f1; 22 | } 23 | .tag-nav.nav .cu-item.cur::after { 24 | content: ''; 25 | width: 8rpx; 26 | height: 30rpx; 27 | border-radius: 10rpx 0 0 10rpx; 28 | position: absolute; 29 | background-color: currentColor; 30 | top: 0; 31 | right: 0rpx; 32 | bottom: 0; 33 | margin: auto; 34 | } 35 | .tag-box { 36 | display: flex; 37 | } 38 | .article-main { 39 | background-color: #f1f1f1; 40 | } 41 | /* 自定义标签卡片 */ 42 | .cu-list.tag-page { 43 | overflow: hidden; 44 | } 45 | 46 | .cu-list.tag-page > .cu-item { 47 | position: relative; 48 | display: flex; 49 | padding-right: 10rpx; 50 | height: 140rpx; 51 | background-color: var(--white); 52 | justify-content: flex-end; 53 | align-items: center; 54 | } 55 | 56 | .cu-list.tag-page > .cu-item .flex .text-cut { 57 | max-width: 510rpx; 58 | } 59 | 60 | .cu-list.tag-page > .cu-item .content { 61 | position: absolute; 62 | left: 30rpx; 63 | width: calc(100% - 96rpx - 60rpx - 20rpx); 64 | line-height: 1.6em; 65 | } 66 | 67 | .cu-list.tag-page > .cu-item .content.flex-sub { 68 | width: calc(100% - 96rpx - 60rpx - 20rpx); 69 | } 70 | 71 | .cu-list.tag-page > .cu-item .content > view:first-child { 72 | font-size: 30rpx; 73 | display: flex; 74 | align-items: center; 75 | } 76 | 77 | .cu-list.tag-page > .cu-item .action .likes { 78 | display: inline-block; 79 | text-align: center; 80 | height: 28rpx; 81 | font-size: 18rpx; 82 | line-height: 32rpx; 83 | } 84 | 85 | .cu-list.tag-page > .cu-item .action { 86 | width: 120rpx; 87 | text-align: center; 88 | } 89 | 90 | .cu-list.tag-page > .cu-item .action view + view { 91 | margin-top: 10rpx; 92 | } 93 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/menu.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/menus' 5 | 6 | /** 7 | * 获取菜单列表 8 | */ 9 | function adminGetMenu(param) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 添加菜单 27 | */ 28 | function adminAddMenu(data) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Post(moduleName, data, adminToken).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | /** 45 | * 根据id编辑菜单 46 | */ 47 | function adminEditMenu(menuId, param) { 48 | const adminToken = { 49 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 50 | } 51 | const url = moduleName + '/' + menuId 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Put(url, param, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据id删除菜单 66 | */ 67 | function adminDeleteMenu(menuId) { 68 | const adminToken = { 69 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 70 | } 71 | const url = moduleName + '/' + menuId 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Delete(url, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | module.exports = { 85 | adminGetMenu, 86 | adminAddMenu, 87 | adminEditMenu, 88 | adminDeleteMenu 89 | } 90 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/link.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/links' 5 | 6 | /** 7 | * 新建友链 8 | */ 9 | function adminAddLink(data) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Post(moduleName, data, adminToken).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 获取友链列表 27 | */ 28 | function adminGetLink(param) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | /** 45 | * 根据id删除友链 46 | */ 47 | function adminDeleteLink(linkId) { 48 | const adminToken = { 49 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 50 | } 51 | const url = moduleName + '/' + linkId 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Delete(url, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据友链id修改友链 66 | */ 67 | function adminEditLink(linkId, param) { 68 | const adminToken = { 69 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 70 | } 71 | const url = moduleName + '/' + linkId 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Put(url, param, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | module.exports = { 85 | adminAddLink, 86 | adminGetLink, 87 | adminDeleteLink, 88 | adminEditLink 89 | } 90 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/node/node.js: -------------------------------------------------------------------------------- 1 | "use strict";function t(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}Component({data:{ctrl:{}},properties:{childs:Array,opts:Array},attached:function(){this.triggerEvent("add",this,{bubbles:!0,composed:!0})},methods:{copyCode:function(t){wx.showActionSheet({itemList:["复制代码"],success:function(){return wx.setClipboardData({data:t.currentTarget.dataset.content})}})},noop:function(){},getNode:function(t){for(var e=t.split("_"),i=this.data.childs[e[0]],r=1;rr.src.length&&(s=0),s { 14 | apiRequest.Post(moduleName, data, adminToken).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 获取日记列表 27 | */ 28 | function adminGetJournal(param) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | /** 45 | * 根据id删除日记 46 | */ 47 | function adminDeleteJournal(journalId) { 48 | const adminToken = { 49 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 50 | } 51 | const url = moduleName + '/' + journalId 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Delete(url, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据日记id修改日记 66 | */ 67 | function adminEditJournal(journalId, param) { 68 | const adminToken = { 69 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 70 | } 71 | const url = moduleName + '/' + journalId 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Put(url, param, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | module.exports = { 85 | adminAddJournal, 86 | adminGetJournal, 87 | adminDeleteJournal, 88 | adminEditJournal 89 | } 90 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/category.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/categories' 5 | 6 | /** 7 | * 获取分类列表 8 | */ 9 | function adminGetCategory(param) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 添加分类 27 | */ 28 | function adminAddCategory(data) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | return new Promise((resolve, reject) => { 33 | apiRequest.Post(moduleName, data, adminToken).then( 34 | r => { 35 | resolve(r) 36 | }, 37 | e => { 38 | reject(e) 39 | } 40 | ) 41 | }) 42 | } 43 | 44 | /** 45 | * 根据id编辑分类 46 | */ 47 | function adminEditCategory(categoryId, param) { 48 | const url = moduleName + '/' + categoryId 49 | const adminToken = { 50 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 51 | } 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Put(url, param, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据id删除分类 66 | */ 67 | function adminDeleteCategory(categoryId) { 68 | const url = moduleName + '/' + categoryId 69 | const adminToken = { 70 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 71 | } 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Delete(url, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | module.exports = { 85 | adminGetCategory, 86 | adminAddCategory, 87 | adminEditCategory, 88 | adminDeleteCategory 89 | } 90 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", 3 | "miniprogramRoot": "miniprogram/", 4 | "cloudfunctionRoot": "cloudfunctions/", 5 | "packOptions": { 6 | "ignore": [] 7 | }, 8 | "setting": { 9 | "urlCheck": false, 10 | "es6": true, 11 | "enhance": true, 12 | "postcss": true, 13 | "preloadBackgroundData": false, 14 | "minified": true, 15 | "newFeature": true, 16 | "coverView": true, 17 | "nodeModules": false, 18 | "autoAudits": false, 19 | "showShadowRootInWxmlPanel": true, 20 | "scopeDataCheck": false, 21 | "uglifyFileName": false, 22 | "checkInvalidKey": true, 23 | "checkSiteMap": true, 24 | "uploadWithSourceMap": true, 25 | "compileHotReLoad": false, 26 | "lazyloadPlaceholderEnable": false, 27 | "useMultiFrameRuntime": true, 28 | "useApiHook": true, 29 | "useApiHostProcess": true, 30 | "babelSetting": { 31 | "ignore": [], 32 | "disablePlugins": [], 33 | "outputPath": "" 34 | }, 35 | "enableEngineNative": false, 36 | "useIsolateContext": false, 37 | "userConfirmedBundleSwitch": false, 38 | "packNpmManually": false, 39 | "packNpmRelationList": [], 40 | "minifyWXSS": true, 41 | "disableUseStrict": false, 42 | "showES6CompileOption": false, 43 | "useCompilerPlugins": false, 44 | "minifyWXML": true, 45 | "ignoreUploadUnusedFiles": true, 46 | "useStaticServer": true 47 | }, 48 | "compileType": "miniprogram", 49 | "libVersion": "2.10.4", 50 | "appid": "", 51 | "projectname": "GBlog-wx", 52 | "simulatorType": "wechat", 53 | "simulatorPluginLibVersion": {}, 54 | "cloudfunctionTemplateRoot": "cloudfunctionTemplate/", 55 | "condition": { 56 | "search": { 57 | "list": [] 58 | }, 59 | "conversation": { 60 | "list": [] 61 | }, 62 | "game": { 63 | "currentL": -1, 64 | "list": [] 65 | }, 66 | "miniprogram": { 67 | "list": [] 68 | } 69 | }, 70 | "srcMiniprogramRoot": "miniprogram/", 71 | "editorSetting": { 72 | "tabIndent": "insertSpaces", 73 | "tabSize": 2 74 | } 75 | } -------------------------------------------------------------------------------- /miniprogram/pages/about/archives/index.js: -------------------------------------------------------------------------------- 1 | import { getArchives } from '../../../services/api/content/archive' 2 | import { getStatistics } from '../../../services/api/content/statistic' 3 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 4 | 5 | const app = getApp() 6 | 7 | Page({ 8 | data: { 9 | archives: [], 10 | categoryNum: 0, 11 | tagNum: 0, 12 | articleNum: 0 13 | }, 14 | onLoad: function () { 15 | const that = this 16 | that.setData({ 17 | logo: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 18 | }) 19 | }, 20 | async onShow() { 21 | const that = this 22 | that.setData({ 23 | loadModal: true 24 | }) 25 | const archives = await this.getArchives() 26 | const statistics = await this.getStatistics() 27 | that.setData({ 28 | archives: archives, 29 | loadModal: false 30 | }) 31 | that.setData({ 32 | categoryNum: statistics.categoryCount, 33 | tagNum: statistics.tagCount, 34 | articleNum: statistics.postCount 35 | }) 36 | }, 37 | /** 38 | * 获取归档 39 | */ 40 | async getArchives() { 41 | try { 42 | const result = await getArchives() 43 | return result 44 | } catch (error) { 45 | return await Promise.reject(error) 46 | } 47 | }, 48 | /** 49 | * 获取统计信息 50 | */ 51 | async getStatistics() { 52 | try { 53 | const result = await getStatistics() 54 | return result 55 | } catch (error) { 56 | return await Promise.reject(error) 57 | } 58 | }, 59 | toCategoryPage() { 60 | wx.switchTab({ 61 | url: '/pages/type/home/index' 62 | }) 63 | }, 64 | toTagPage() { 65 | wx.navigateTo({ 66 | url: '/pages/tag/index' 67 | }) 68 | }, 69 | onShareAppMessage: function (res) { 70 | return { 71 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '的归档文章', 72 | path: '/pages/about/archives/index' 73 | } 74 | }, 75 | onShareTimeline: function (res) { 76 | return { 77 | title: app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE] + '的归档文章', 78 | imageUrl: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 79 | } 80 | } 81 | }) 82 | -------------------------------------------------------------------------------- /miniprogram/images/icon/weixin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/qq.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/write.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/admin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/read.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/message.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/friendfavor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/images/icon/tag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/config/api-tmp.js: -------------------------------------------------------------------------------- 1 | import { THEME_SETTING_KEY } from '../services/const-data/theme-setting-key' 2 | 3 | const ApiBaseUrl = 'http://127.0.0.1:8091' 4 | 5 | const Config = { 6 | AccessKey: '', // 接口key,必填 7 | cloudEnv: '', // 云环境ID 8 | themeSettingsCache: true 9 | } 10 | 11 | const themeSettings = { 12 | [THEME_SETTING_KEY.BLOG_TITLE]: '', 13 | [THEME_SETTING_KEY.BLOG_LOGO]: '', 14 | [THEME_SETTING_KEY.GUESTBOOK_SHEET_ID]: 2, 15 | [THEME_SETTING_KEY.CLOUD_IS_OPEN]: false, 16 | [THEME_SETTING_KEY.CLOUD_ENV]: 'cloud_env', 17 | [THEME_SETTING_KEY.CLOUD_SHARE_OPEN]: false, 18 | [THEME_SETTING_KEY.CLOUD_CHECK_MESSAGE]: false, 19 | [THEME_SETTING_KEY.CLOUD_ADMIN_USER]: false, 20 | // 关于页面中个人信息,置空不显示 21 | [THEME_SETTING_KEY.BLOG]: 'https://www.geekera.cn', 22 | [THEME_SETTING_KEY.QQ]: '59210983', 23 | [THEME_SETTING_KEY.WX]: '59210983', 24 | [THEME_SETTING_KEY.MAIL]: 'zes@qq.com', 25 | [THEME_SETTING_KEY.GITHUB]: 'https://github.com/fuzui', 26 | [THEME_SETTING_KEY.GITEE]: 'https://gitee.com/fuzui', 27 | [THEME_SETTING_KEY.WX_MP]: '', 28 | // 无内容占位图 29 | [THEME_SETTING_KEY.NO_CONTENT_IMAGE]: 'no_content_image', 30 | // 占位图 31 | [THEME_SETTING_KEY.PLACEHOLDER_IMAGE]: '', 32 | // 加载失败占位图 33 | [THEME_SETTING_KEY.LOAD_ERROR_IMAGE]: 'load_error_image', 34 | // 随机图,分号隔开 35 | [THEME_SETTING_KEY.RANDOM_IMAGE]: '', 36 | // 样式 37 | [THEME_SETTING_KEY.POST_TAG_STYLE]: '', 38 | [THEME_SETTING_KEY.POST_CONTAINER_STYLE]: '', 39 | [THEME_SETTING_KEY.COMMENT_TAG_STYLE]: '', 40 | [THEME_SETTING_KEY.COMMENT_CONTAINER_STYLE]: '', 41 | [THEME_SETTING_KEY.JOURNAL_TAG_STYLE]: '', 42 | [THEME_SETTING_KEY.JOURNAL_CONTAINER_STYLE]: '', 43 | // 页面布局 44 | [THEME_SETTING_KEY.TAB_BAR_HOME]: '首页', 45 | [THEME_SETTING_KEY.TAB_BAR_CATEGORY]: '分类', 46 | [THEME_SETTING_KEY.TAB_BAR_PHOTO]: '光影', 47 | [THEME_SETTING_KEY.TAB_BAR_ABOUT]: '关于', 48 | [THEME_SETTING_KEY.TAB_BAR_ADMIN]: '管理', 49 | // 分页信息 50 | [THEME_SETTING_KEY.SWIPER_START]: 0, 51 | [THEME_SETTING_KEY.PAGE_SIZE_SWIPER]: 10, 52 | [THEME_SETTING_KEY.PAGE_SIZE_INDEX]: 10, 53 | [THEME_SETTING_KEY.PAGE_SIZE_SEARCH]: 10, 54 | [THEME_SETTING_KEY.PAGE_SIZE_CATEGORY]: 10, 55 | [THEME_SETTING_KEY.PAGE_SIZE_TAG]: 10, 56 | [THEME_SETTING_KEY.PAGE_SIZE_PHOTO]: 12, 57 | [THEME_SETTING_KEY.PAGE_SIZE_JOURNAL]: 10, 58 | [THEME_SETTING_KEY.PAGE_SIZE_ATTACHMENT]: 12 59 | } 60 | 61 | module.exports = { 62 | ApiBaseUrl, 63 | Config, 64 | themeSettings 65 | } 66 | -------------------------------------------------------------------------------- /miniprogram/pages/about/about/index.js: -------------------------------------------------------------------------------- 1 | import { getStatistics } from '../../../services/api/content/statistic' 2 | import { THEME_SETTING_KEY } from '../../../services/const-data/theme-setting-key' 3 | 4 | // 获取应用实例 5 | const app = getApp() 6 | 7 | Page({ 8 | data: { 9 | title: '关于', 10 | statistics: {}, 11 | contact: { 12 | blog: '', 13 | qq: '', 14 | wx: '', 15 | mail: '', 16 | github: '', 17 | gitee: '' 18 | } 19 | }, 20 | onLoad: function () {}, 21 | async onShow() { 22 | const that = this 23 | if (!app.globalData.hasInit) { 24 | await app.init() 25 | } 26 | const statistics = await this.getStatistics() 27 | that.setData({ 28 | statistics: statistics, 29 | contact: { 30 | blog: app.themeSettings[THEME_SETTING_KEY.BLOG], 31 | qq: app.themeSettings[THEME_SETTING_KEY.QQ], 32 | wx: app.themeSettings[THEME_SETTING_KEY.WX], 33 | mail: app.themeSettings[THEME_SETTING_KEY.MAIL], 34 | github: app.themeSettings[THEME_SETTING_KEY.GITHUB], 35 | gitee: app.themeSettings[THEME_SETTING_KEY.GITEE] 36 | } 37 | }) 38 | }, 39 | /** 40 | * 获取统计信息 41 | */ 42 | async getStatistics() { 43 | try { 44 | const result = await getStatistics() 45 | return result 46 | } catch (error) { 47 | return await Promise.reject(error) 48 | } 49 | }, 50 | /** 51 | * 复制 52 | * @param {*} e 53 | */ 54 | copyLink(e) { 55 | wx.setClipboardData({ 56 | data: e.currentTarget.dataset.link, 57 | success: res => { 58 | wx.showToast({ 59 | title: '已复制', 60 | duration: 1000 61 | }) 62 | } 63 | }) 64 | }, 65 | toArchivesPage() { 66 | wx.navigateTo({ 67 | url: '/pages/about/archives/index' 68 | }) 69 | }, 70 | toCategoryPage() { 71 | wx.switchTab({ 72 | url: '/pages/type/home/index' 73 | }) 74 | }, 75 | toTagPage() { 76 | wx.navigateTo({ 77 | url: '/pages/tag/index' 78 | }) 79 | }, 80 | onShareAppMessage: function (res) { 81 | return { 82 | title: '关于' + app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE], 83 | path: '/pages/about/about/index' 84 | } 85 | }, 86 | onShareTimeline: function (res) { 87 | return { 88 | title: '关于' + app.themeSettings[THEME_SETTING_KEY.BLOG_TITLE], 89 | imageUrl: app.themeSettings[THEME_SETTING_KEY.BLOG_LOGO] 90 | } 91 | } 92 | }) 93 | -------------------------------------------------------------------------------- /miniprogram/utils/utils.js: -------------------------------------------------------------------------------- 1 | import { ApiBaseUrl } from './../config/api' 2 | // 构建url 3 | const buildURL = (url, query = {}, isSequence = true) => { 4 | if (!query) return url 5 | const joiner = url.match(/\?/) ? '&' : '?' 6 | const queryStr = Object.keys(query) 7 | .map(key => `${key}=${encodeURIComponent(isSequence ? JSON.stringify(query[key]) : query[key])}`) 8 | .join('&') 9 | return url + joiner + queryStr 10 | } 11 | 12 | // 解析query对象 13 | const decodeQuery = (originQuery = {}, isSequence = true) => { 14 | const result = {} 15 | if (!originQuery) return {} 16 | return Object.keys(originQuery).reduce((prev, curr) => { 17 | result[curr] = decodeURIComponent(originQuery[curr]) 18 | if (isSequence) { 19 | result[curr] = JSON.parse(result[curr]) 20 | } 21 | return result 22 | }, result) 23 | } 24 | 25 | const mergeJsonObject = (jsonObject1 = {}, jsonObject2 = {}) => { 26 | const resultJsonObject = {} 27 | for (const attr in jsonObject1) { 28 | resultJsonObject[attr] = jsonObject1[attr] 29 | } 30 | for (const attr in jsonObject2) { 31 | resultJsonObject[attr] = jsonObject2[attr] 32 | } 33 | return resultJsonObject 34 | } 35 | 36 | const compareVersion = (v1, v2) => { 37 | v1 = v1.split('.') 38 | v2 = v2.split('.') 39 | const len = Math.max(v1.length, v2.length) 40 | 41 | while (v1.length < len) { 42 | v1.push('0') 43 | } 44 | while (v2.length < len) { 45 | v2.push('0') 46 | } 47 | 48 | for (let i = 0; i < len; i++) { 49 | const num1 = parseInt(v1[i]) 50 | const num2 = parseInt(v2[i]) 51 | 52 | if (num1 > num2) { 53 | return 1 54 | } else if (num1 < num2) { 55 | return -1 56 | } 57 | } 58 | return 0 59 | } 60 | const getRandomImage = (arr = []) => { 61 | return arr[Math.floor(Math.random() * arr.length)] 62 | } 63 | 64 | /** 65 | * 图片路径处理 66 | * @param url 67 | * @param randomImages 随机图,为空不使用 68 | */ 69 | const convertImageUrl = (url, randomImages) => { 70 | if (!url) { 71 | if (randomImages && randomImages.length > 0) { 72 | url = getRandomImage(randomImages) 73 | } else { 74 | return null 75 | } 76 | } 77 | // 是否为相对路径 78 | if (url.substring(0, 1) === '/' && url.substring(1, 2) !== '/' && url.substring(0, 7) !== '/iamges') { 79 | return ApiBaseUrl + url 80 | } 81 | return url 82 | } 83 | 84 | module.exports = { 85 | buildURL, 86 | decodeQuery, 87 | mergeJsonObject, 88 | compareVersion, 89 | getRandomImage, 90 | convertImageUrl 91 | } 92 | -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/about/home/index", 5 | "pages/about/about/index", 6 | "pages/about/archives/index", 7 | "pages/about/disclaimer/index", 8 | "pages/about/journal/index", 9 | "pages/about/links/index", 10 | "pages/about/notice/index", 11 | "pages/admin/article/index", 12 | "pages/admin/attachment/home/index", 13 | "pages/admin/attachment/details/index", 14 | "pages/admin/attachment/select/index", 15 | "pages/admin/category/index", 16 | "pages/admin/comment/index", 17 | "pages/admin/environments/index", 18 | "pages/admin/home/index", 19 | "pages/admin/journal/home/index", 20 | "pages/admin/links/home/index", 21 | "pages/admin/login/index", 22 | "pages/admin/menu/list/index", 23 | "pages/admin/photos/details/index", 24 | "pages/admin/photos/home/index", 25 | "pages/admin/setting/index", 26 | "pages/admin/tag/index", 27 | "pages/admin/theme/list/index", 28 | "pages/admin/user/index", 29 | "pages/comment/home/index", 30 | "pages/comment/publish/index", 31 | "pages/details/index", 32 | "pages/photos/home/index", 33 | "pages/search/index", 34 | "pages/share/index", 35 | "pages/tag/index", 36 | "pages/type/details/index", 37 | "pages/type/home/index" 38 | ], 39 | "window": { 40 | "navigationBarBackgroundColor": "#39b54a", 41 | "navigationBarTitleText": "Geek Era", 42 | "navigationStyle": "custom", 43 | "navigationBarTextStyle": "white" 44 | }, 45 | "usingComponents": { 46 | "cu-custom": "styles/colorui/components/cu-custom" 47 | }, 48 | "tabBar": { 49 | "custom": true, 50 | "color": "#7A7E83", 51 | "selectedColor": "#000000", 52 | "borderStyle": "black", 53 | "backgroundColor": "#fdfefa", 54 | "list": [ 55 | { 56 | "pagePath": "pages/index/index", 57 | "text": "首页" 58 | }, 59 | { 60 | "pagePath": "pages/type/home/index", 61 | "text": "分类" 62 | }, 63 | { 64 | "pagePath": "pages/photos/home/index", 65 | "text": "光影" 66 | }, 67 | { 68 | "pagePath": "pages/about/home/index", 69 | "text": "关于" 70 | }, 71 | { 72 | "pagePath": "pages/admin/home/index", 73 | "text": "管理" 74 | } 75 | ] 76 | }, 77 | "networkTimeout": { 78 | "request": 60000, 79 | "downloadFile": 60000 80 | }, 81 | "debug": true, 82 | "sitemapLocation": "sitemap.json" 83 | } 84 | -------------------------------------------------------------------------------- /miniprogram/pages/type/home/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 专题 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | {{item.name}} 17 | 18 | {{item.postCount}} 19 | 20 | 21 | {{item.description}} 22 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 40 | 41 | 42 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 加载中... 60 | 61 | -------------------------------------------------------------------------------- /miniprogram/images/icon/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/services/api/admin/photo.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/photos' 5 | 6 | /** 7 | * 获取图库列表 8 | */ 9 | function adminGetPhoto(param) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 获取图库详情 27 | */ 28 | function adminGetPhotoDetails(photoId) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | const url = moduleName + '/' + photoId 33 | return new Promise((resolve, reject) => { 34 | apiRequest.Get(url, adminToken).then( 35 | r => { 36 | resolve(r) 37 | }, 38 | e => { 39 | reject(e) 40 | } 41 | ) 42 | }) 43 | } 44 | 45 | /** 46 | * 添加图库 47 | */ 48 | function adminAddPhoto(data) { 49 | const adminToken = { 50 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 51 | } 52 | return new Promise((resolve, reject) => { 53 | apiRequest.Post(moduleName, data, adminToken).then( 54 | r => { 55 | resolve(r) 56 | }, 57 | e => { 58 | reject(e) 59 | } 60 | ) 61 | }) 62 | } 63 | 64 | /** 65 | * 根据id编辑图库 66 | */ 67 | function adminEditPhotoDetails(photoId, param) { 68 | const adminToken = { 69 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 70 | } 71 | const url = moduleName + '/' + photoId 72 | return new Promise((resolve, reject) => { 73 | apiRequest.Put(url, param, adminToken).then( 74 | r => { 75 | resolve(r) 76 | }, 77 | e => { 78 | reject(e) 79 | } 80 | ) 81 | }) 82 | } 83 | 84 | /** 85 | * 根据id删除图库 86 | */ 87 | function adminDeletePhoto(photoId) { 88 | const adminToken = { 89 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 90 | } 91 | const url = moduleName + '/' + photoId 92 | return new Promise((resolve, reject) => { 93 | apiRequest.Delete(url, adminToken).then( 94 | r => { 95 | resolve(r) 96 | }, 97 | e => { 98 | reject(e) 99 | } 100 | ) 101 | }) 102 | } 103 | 104 | module.exports = { 105 | adminGetPhoto, 106 | adminAddPhoto, 107 | adminGetPhotoDetails, 108 | adminEditPhotoDetails, 109 | adminDeletePhoto 110 | } 111 | -------------------------------------------------------------------------------- /miniprogram/pages/about/home/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{blogTitle}} 5 | 6 | 心之所向,即所向披靡 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 标签 15 | 16 | 17 | 18 | 归档 19 | 20 | 21 | 22 | 日记 23 | 24 | 25 | 26 | 留言 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 友情链接 35 | 36 | 37 | 38 | 39 | 40 | 免责声明 41 | 42 | 43 | 44 | 45 | 46 | 关于我 47 | 48 | 49 | 50 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /miniprogram/components/mp-weixin/node/node.wxss: -------------------------------------------------------------------------------- 1 | .hl-code,.hl-pre{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.hl-pre{padding:1em;margin:.5em 0;overflow:auto}.hl-pre{background:#2d2d2d}.hl-block-comment,.hl-cdata,.hl-comment,.hl-doctype,.hl-prolog{color:#999}.hl-punctuation{color:#ccc}.hl-attr-name,.hl-deleted,.hl-namespace,.hl-tag{color:#e2777a}.hl-function-name{color:#6196cc}.hl-boolean,.hl-function,.hl-number{color:#f08d49}.hl-class-name,.hl-constant,.hl-property,.hl-symbol{color:#f8c555}.hl-atrule,.hl-builtin,.hl-important,.hl-keyword,.hl-selector{color:#cc99cd}.hl-attr-value,.hl-char,.hl-regex,.hl-string,.hl-variable{color:#7ec699}.hl-entity,.hl-operator,.hl-url{color:#67cdcc}.hl-bold,.hl-important{font-weight:700}.hl-italic{font-style:italic}.hl-entity{cursor:help}.hl-inserted{color:green}.md-p{margin-block-start:1em;margin-block-end:1em}.md-blockquote,.md-table{margin-bottom:16px}.md-table{box-sizing:border-box;width:100%;overflow:auto;border-spacing:0;border-collapse:collapse}.md-tr{background-color:#fff;border-top:1px solid #c6cbd1}.md-table .md-tr:nth-child(2n){background-color:#f6f8fa}.md-td,.md-th{padding:6px 13px!important;border:1px solid #dfe2e5}.md-th{font-weight:600}.md-blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.md-code{padding:.2em .4em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.md-pre .md-code{padding:0;font-size:100%;background:0 0;border:0}._a{padding:1.5px 0 1.5px 0;color:#366092;word-break:break-all}._hover{text-decoration:underline;opacity:.7}._img{max-width:100%;-webkit-touch-callout:none}._b,._strong{font-weight:700}._code{font-family:monospace}._del{text-decoration:line-through}._em,._i{font-style:italic}._h1{font-size:2em}._h2{font-size:1.5em}._h3{font-size:1.17em}._h5{font-size:.83em}._h6{font-size:.67em}._h1,._h2,._h3,._h4,._h5,._h6{display:block;font-weight:700}._ins{text-decoration:underline}._li{display:list-item}._ol{list-style-type:decimal}._ol,._ul{display:block;padding-left:40px;margin:1em 0}._q::before{content:'"'}._q::after{content:'"'}._sub{font-size:smaller;vertical-align:sub}._sup{font-size:smaller;vertical-align:super}._tbody,._tfoot,._thead{display:table-row-group}._tr{display:table-row}._td,._th{display:table-cell;vertical-align:middle}._th{font-weight:700;text-align:center}._ul{list-style-type:disc}._ul ._ul{margin:0;list-style-type:circle}._ul ._ul ._ul{list-style-type:square}._abbr,._b,._code,._del,._em,._i,._ins,._label,._q,._span,._strong,._sub,._sup{display:inline}._blockquote,._div,._p{display:block} -------------------------------------------------------------------------------- /miniprogram/services/api/admin/theme.js: -------------------------------------------------------------------------------- 1 | import apiRequest from './../../../utils/api-request' 2 | import { ApiBaseUrl } from '../../../config/api' 3 | import { STORAGE_KEY } from '../../const-data/const-data' 4 | const moduleName = ApiBaseUrl + '/api/admin/themes' 5 | 6 | /** 7 | * 获取主题列表 8 | */ 9 | function adminGetTheme(param) { 10 | const adminToken = { 11 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 12 | } 13 | return new Promise((resolve, reject) => { 14 | apiRequest.Get(moduleName, Object.assign(adminToken, param)).then( 15 | r => { 16 | resolve(r) 17 | }, 18 | e => { 19 | reject(e) 20 | } 21 | ) 22 | }) 23 | } 24 | 25 | /** 26 | * 启用主题 27 | */ 28 | function adminActivatesTheme(thmemId) { 29 | const adminToken = { 30 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 31 | } 32 | const url = moduleName + '/' + thmemId + '/activation' 33 | return new Promise((resolve, reject) => { 34 | apiRequest.Post(url, {}, adminToken).then( 35 | r => { 36 | resolve(r) 37 | }, 38 | e => { 39 | reject(e) 40 | } 41 | ) 42 | }) 43 | } 44 | 45 | /** 46 | * 拉取新主题 47 | */ 48 | function adminFetchingNewTheme(data) { 49 | const adminToken = { 50 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 51 | } 52 | const url = moduleName + '/fetching' 53 | return new Promise((resolve, reject) => { 54 | apiRequest.Post(url, data, adminToken).then( 55 | r => { 56 | resolve(r) 57 | }, 58 | e => { 59 | reject(e) 60 | } 61 | ) 62 | }) 63 | } 64 | 65 | /** 66 | * 根据id删除主题 67 | */ 68 | function adminDeleteTheme(thmemId) { 69 | const adminToken = { 70 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 71 | } 72 | const url = moduleName + '/' + thmemId 73 | return new Promise((resolve, reject) => { 74 | apiRequest.Delete(url, adminToken).then( 75 | r => { 76 | resolve(r) 77 | }, 78 | e => { 79 | reject(e) 80 | } 81 | ) 82 | }) 83 | } 84 | 85 | /** 86 | * 根据id在线更新主题 87 | */ 88 | function adminFetchingTheme(thmemId) { 89 | const adminToken = { 90 | admin_token: wx.getStorageSync(STORAGE_KEY.adminToken) 91 | } 92 | const url = moduleName + '/fetching/' + thmemId 93 | return new Promise((resolve, reject) => { 94 | apiRequest.Put(url, {}, adminToken).then( 95 | r => { 96 | resolve(r) 97 | }, 98 | e => { 99 | reject(e) 100 | } 101 | ) 102 | }) 103 | } 104 | 105 | module.exports = { 106 | adminGetTheme, 107 | adminActivatesTheme, 108 | adminDeleteTheme, 109 | adminFetchingTheme, 110 | adminFetchingNewTheme 111 | } 112 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/tag/index.wxss: -------------------------------------------------------------------------------- 1 | .UCenter-bg { 2 | background-size: cover; 3 | height: 270rpx; 4 | display: flex; 5 | justify-content: center; 6 | overflow: hidden; 7 | position: relative; 8 | flex-direction: column; 9 | align-items: center; 10 | color: #fff; 11 | font-weight: 300; 12 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 13 | } 14 | 15 | .tag-nav.nav { 16 | width: 200rpx; 17 | white-space: initial; 18 | } 19 | .tag-nav > .cu-item .flex .text-cut { 20 | max-width: 100rpx; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | .tag-nav.nav .cu-item { 25 | width: 100%; 26 | text-align: center; 27 | background-color: #fff; 28 | margin: 0; 29 | border: none; 30 | height: 50px; 31 | position: relative; 32 | } 33 | 34 | .tag-nav.nav .cu-item.cur { 35 | background-color: #f1f1f1; 36 | } 37 | .tag-nav.nav .cu-item.cur::after { 38 | content: ''; 39 | width: 8rpx; 40 | height: 30rpx; 41 | border-radius: 10rpx 0 0 10rpx; 42 | position: absolute; 43 | background-color: currentColor; 44 | top: 0; 45 | right: 0rpx; 46 | bottom: 0; 47 | margin: auto; 48 | } 49 | .tag-box { 50 | display: flex; 51 | } 52 | .article-main { 53 | background-color: #f1f1f1; 54 | } 55 | /* 自定义标签卡片 */ 56 | .cu-list.tag-page { 57 | overflow: hidden; 58 | } 59 | 60 | .cu-list.tag-page > .cu-item { 61 | position: relative; 62 | display: flex; 63 | padding-right: 10rpx; 64 | height: 140rpx; 65 | background-color: var(--white); 66 | justify-content: flex-end; 67 | align-items: center; 68 | } 69 | 70 | .cu-list.tag-page > .cu-item .flex .text-cut { 71 | max-width: 510rpx; 72 | } 73 | 74 | .cu-list.tag-page > .cu-item .content { 75 | position: absolute; 76 | left: 30rpx; 77 | width: calc(100% - 96rpx - 60rpx - 20rpx); 78 | line-height: 1.6em; 79 | } 80 | 81 | .cu-list.tag-page > .cu-item .content.flex-sub { 82 | width: calc(100% - 96rpx - 60rpx - 20rpx); 83 | } 84 | 85 | .cu-list.tag-page > .cu-item .content > view:first-child { 86 | font-size: 30rpx; 87 | display: flex; 88 | align-items: center; 89 | } 90 | 91 | .cu-list.tag-page > .cu-item .action .likes { 92 | display: inline-block; 93 | text-align: center; 94 | height: 28rpx; 95 | font-size: 18rpx; 96 | line-height: 32rpx; 97 | } 98 | 99 | .cu-list.tag-page > .cu-item .action { 100 | width: 120rpx; 101 | text-align: center; 102 | } 103 | 104 | .cu-list.tag-page > .cu-item .action view + view { 105 | margin-top: 10rpx; 106 | } 107 | 108 | .cu-form-group .title { 109 | min-width: calc(4em + 30rpx); 110 | } 111 | .selectSetting { 112 | position: fixed; 113 | z-index: 1024; 114 | height: 50rpx; 115 | width: 50rpx; 116 | bottom: 30rpx; 117 | right: 30rpx; 118 | } 119 | -------------------------------------------------------------------------------- /miniprogram/pages/admin/category/index.wxss: -------------------------------------------------------------------------------- 1 | .UCenter-bg { 2 | background-size: cover; 3 | height: 270rpx; 4 | display: flex; 5 | justify-content: center; 6 | overflow: hidden; 7 | position: relative; 8 | flex-direction: column; 9 | align-items: center; 10 | color: #fff; 11 | font-weight: 300; 12 | text-shadow: 0 0 3px rgba(0, 0, 0, 0.3); 13 | } 14 | 15 | .tag-nav.nav { 16 | width: 200rpx; 17 | white-space: initial; 18 | } 19 | .tag-nav > .cu-item .flex .text-cut { 20 | max-width: 100rpx; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | .tag-nav.nav .cu-item { 25 | width: 100%; 26 | text-align: center; 27 | background-color: #fff; 28 | margin: 0; 29 | border: none; 30 | height: 50px; 31 | position: relative; 32 | } 33 | 34 | .tag-nav.nav .cu-item.cur { 35 | background-color: #f1f1f1; 36 | } 37 | .tag-nav.nav .cu-item.cur::after { 38 | content: ''; 39 | width: 8rpx; 40 | height: 30rpx; 41 | border-radius: 10rpx 0 0 10rpx; 42 | position: absolute; 43 | background-color: currentColor; 44 | top: 0; 45 | right: 0rpx; 46 | bottom: 0; 47 | margin: auto; 48 | } 49 | .tag-box { 50 | display: flex; 51 | } 52 | .article-main { 53 | background-color: #f1f1f1; 54 | } 55 | /* 自定义标签卡片 */ 56 | .cu-list.tag-page { 57 | overflow: hidden; 58 | } 59 | 60 | .cu-list.tag-page > .cu-item { 61 | position: relative; 62 | display: flex; 63 | padding-right: 10rpx; 64 | height: 140rpx; 65 | background-color: var(--white); 66 | justify-content: flex-end; 67 | align-items: center; 68 | } 69 | 70 | .cu-list.tag-page > .cu-item .flex .text-cut { 71 | max-width: 510rpx; 72 | } 73 | 74 | .cu-list.tag-page > .cu-item .content { 75 | position: absolute; 76 | left: 30rpx; 77 | width: calc(100% - 96rpx - 60rpx - 20rpx); 78 | line-height: 1.6em; 79 | } 80 | 81 | .cu-list.tag-page > .cu-item .content.flex-sub { 82 | width: calc(100% - 96rpx - 60rpx - 20rpx); 83 | } 84 | 85 | .cu-list.tag-page > .cu-item .content > view:first-child { 86 | font-size: 30rpx; 87 | display: flex; 88 | align-items: center; 89 | } 90 | 91 | .cu-list.tag-page > .cu-item .action .likes { 92 | display: inline-block; 93 | text-align: center; 94 | height: 28rpx; 95 | font-size: 18rpx; 96 | line-height: 32rpx; 97 | } 98 | 99 | .cu-list.tag-page > .cu-item .action { 100 | width: 120rpx; 101 | text-align: center; 102 | } 103 | 104 | .cu-list.tag-page > .cu-item .action view + view { 105 | margin-top: 10rpx; 106 | } 107 | 108 | .cu-form-group .title { 109 | min-width: calc(4em + 30rpx); 110 | } 111 | .selectSetting { 112 | position: fixed; 113 | z-index: 1024; 114 | height: 50rpx; 115 | width: 50rpx; 116 | bottom: 30rpx; 117 | right: 30rpx; 118 | } 119 | --------------------------------------------------------------------------------