From e30d26cc4eae3d3ee0503cd4d3e3b78b900a6f40 Mon Sep 17 00:00:00 2001 From: iMaeGoo Date: Wed, 9 Dec 2020 15:52:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(0.3.1):=20=E5=A4=B4=E5=83=8F=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E4=BC=98=E5=8C=96=EF=BC=8C=E4=BF=AE=E5=A4=8D=20bug=20?= =?UTF-8?q?(#51)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 新增 支持自定义头像CDN #16 * 新增 支持访客使用QQ头像作为评论头像 #45 * 修复 邮件中的链接 URL #hash 不正确 #48 * 重构 引入 eslint 代码检查,并优化代码 --- .editorconfig | 2 +- .eslintignore | 2 ++ .eslintrc.js | 13 ++++---- README.md | 1 + docs/.vuepress/theme/layouts/Layout.vue | 2 +- docs/README.md | 1 + docs/quick-start.md | 2 +- package.json | 13 ++++---- src/function/twikoo/index.js | 41 ++++++++++++++++++++++--- src/function/twikoo/package.json | 4 +-- src/js/entites/comment.js | 1 + src/js/utils/avatar.js | 14 +++++++++ src/js/utils/index.js | 3 ++ src/view/App.vue | 3 -- src/view/components/TkAdminComment.vue | 10 +++++- src/view/components/TkAdminConfig.vue | 23 ++++++++++---- src/view/components/TkAvatar.vue | 27 +++++++++++----- src/view/components/TkComment.vue | 39 +++++++++++++++++------ src/view/components/TkCounter.vue | 32 ------------------- src/view/components/TkFooter.vue | 23 +++++++++++++- src/view/components/TkMetaInput.vue | 12 +++----- src/view/components/TkSubmit.vue | 10 +++--- webpack.config.js | 4 +++ 23 files changed, 188 insertions(+), 94 deletions(-) create mode 100644 .eslintignore create mode 100644 src/js/utils/avatar.js delete mode 100644 src/view/components/TkCounter.vue diff --git a/.editorconfig b/.editorconfig index 6e2af7960..682d7abda 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,7 +4,7 @@ root = true end_of_line = lf charset = utf-8 -[{*.js,*.ts,*.html,*.gql,*.graqhql}] +[{*.js,*.json,*.vue,*.html,*.css}] indent_style = space indent_size = 2 \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..557ddc73d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +*.md +*.json \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 69d33abc7..ef9d20201 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,19 +1,20 @@ module.exports = { env: { browser: true, - es6: true + es2021: true, + node: true }, extends: [ + 'plugin:vue/essential', 'standard' ], - globals: { - Atomics: 'readonly', - SharedArrayBuffer: 'readonly' - }, parserOptions: { - ecmaVersion: 11, + ecmaVersion: 12, sourceType: 'module' }, + plugins: [ + 'vue' + ], rules: { } } diff --git a/README.md b/README.md index c97d6dd8e..23c9fb5d1 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ A simple, safe, free comment system based on Tencent CloudBase (tcb). ``` sh yarn dev # 开发 (http://localhost:9820/demo.html) +yarn lint # 代码检查 yarn build # 编译 (dist/twikoo.all.min.js) ``` diff --git a/docs/.vuepress/theme/layouts/Layout.vue b/docs/.vuepress/theme/layouts/Layout.vue index 6c026b753..8e0996ebe 100644 --- a/docs/.vuepress/theme/layouts/Layout.vue +++ b/docs/.vuepress/theme/layouts/Layout.vue @@ -3,7 +3,7 @@ diff --git a/docs/README.md b/docs/README.md index adf78de0b..1740be3a2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -82,6 +82,7 @@ A simple, safe, free comment system based on Tencent CloudBase (tcb). ``` sh yarn dev # 开发 (http://localhost:9820/demo.html) +yarn lint # 代码检查 yarn build # 编译 (dist/twikoo.all.min.js) ``` diff --git a/docs/quick-start.md b/docs/quick-start.md index 20e8d0323..fa18bc43c 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -103,7 +103,7 @@ Butterfly 目前支持 Twikoo,请查看 [Butterfly 安裝文檔(四) 主題配 ``` html
- + ``` diff --git a/package.json b/package.json index 09377ecd3..800c8387e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "twikoo", - "version": "0.3.0", + "version": "0.3.1", "description": "A simple comment system based on Tencent CloudBase (tcb).", "author": "imaegoo (https://github.com/imaegoo)", "license": "MIT", @@ -16,31 +16,32 @@ "scripts": { "dev": "webpack-dev-server", "serve": "webpack-dev-server", - "build": "webpack", + "build": "webpack --mode production", "analyze": "webpack --profile --json > stats.json && webpack-bundle-analyzer stats.json", "login": "tcb login", "logout": "tcb logout", "deploy": "tcb fn deploy twikoo --force", - "lint": "eslint", + "lint": "eslint src/** --ignore-path .eslintignore", "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" }, "devDependencies": { "@cloudbase/cli": "^1.0.7", - "copy-webpack-plugin": "^6.3.2", + "copy-webpack-plugin": "^6.4.0", "css-loader": "^3.6.0", - "eslint": "^7.13.0", + "eslint": "^7.15.0", "eslint-config-standard": "^16.0.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.1.0", + "eslint-plugin-vue": "^7.2.0", "svg-inline-loader": "^0.8.2", "vue-loader": "^15.9.5", "vue-template-compiler": "^2.6.12", "vuepress": "^1.7.1", "webpack": "^4.44.1", - "webpack-bundle-analyzer": "^4.1.0", + "webpack-bundle-analyzer": "^4.2.0", "webpack-cli": "^3.3.12", "webpack-dev-server": "^3.11.0" }, diff --git a/src/function/twikoo/index.js b/src/function/twikoo/index.js index 9c810e8ff..a0047e9c0 100644 --- a/src/function/twikoo/index.js +++ b/src/function/twikoo/index.js @@ -1,5 +1,5 @@ /*! - * Twikoo cloudbase function v0.3.0 + * Twikoo cloudbase function v0.3.1 * (c) 2020-2020 iMaeGoo * Released under the MIT License. */ @@ -29,7 +29,7 @@ const window = new JSDOM('').window const DOMPurify = createDOMPurify(window) // 常量 / constants -const VERSION = '0.3.0' +const VERSION = '0.3.1' const RES_CODE = { SUCCESS: 0, FAIL: 1000, @@ -293,6 +293,7 @@ function toCommentDto (comment, uid, replies = [], comments = []) { return { id: comment._id, nick: comment.nick, + avatar: comment.avatar, mailMd5: comment.mailMd5 || md5(comment.mail), link: comment.link, comment: comment.comment, @@ -828,7 +829,7 @@ async function noticeReply (currentComment) { const NICK = currentComment.nick const COMMENT = currentComment.comment const PARENT_COMMENT = parentComment.comment - const POST_URL = (currentComment.href || config.SITE_URL + currentComment.url) + '#' + currentComment._id + const POST_URL = (currentComment.href || config.SITE_URL + currentComment.url) + '#' + currentComment.pid const SITE_URL = config.SITE_URL const emailSubject = config.MAIL_SUBJECT || `${PARENT_NICK},您在『${SITE_NAME}』上的评论收到了回复` let emailContent @@ -894,6 +895,11 @@ async function parse (comment) { updated: timestamp } commentDo.isSpam = await checkSpam(commentDo) + if (isQQ(comment.mail)) { + commentDo.mail = addQQMailSuffix(comment.mail) + commentDo.mailMd5 = md5(commentDo.mail) + commentDo.avatar = await getQQAvatar(comment.mail) + } return commentDo } @@ -1093,14 +1099,41 @@ async function getRecentComments (event) { return res } +function isQQ (mail) { + return /^[1-9][0-9]{4,10}$/.test(mail) || + /^[1-9][0-9]{4,10}@qq.com$/.test(mail) +} + +function addQQMailSuffix (mail) { + if (/^[1-9][0-9]{4,10}$/.test(mail)) return `${mail}@qq.com` + else return mail +} + +async function getQQAvatar (qq) { + try { + const qqNum = qq.replace(/@qq.com/g, '') + const result = await axios.get(`https://ptlogin2.qq.com/getface?imgtype=4&uin=${qqNum}`) + if (result && result.data) { + const start = result.data.indexOf('http') + const end = result.data.indexOf('"', start) + if (start === -1 || end === -1) return null + return result.data.substring(start, end) + } + } catch (e) { + console.error('获取 QQ 头像失败:', e) + } +} + function getConfig () { return { code: RES_CODE.SUCCESS, config: { + VERSION, SITE_NAME: config.SITE_NAME, SITE_URL: config.SITE_URL, MASTER_TAG: config.MASTER_TAG, - COMMENT_BG_IMG: config.COMMENT_BG_IMG + COMMENT_BG_IMG: config.COMMENT_BG_IMG, + GRAVATAR_CDN: config.GRAVATAR_CDN } } } diff --git a/src/function/twikoo/package.json b/src/function/twikoo/package.json index 630768340..1c4919f04 100644 --- a/src/function/twikoo/package.json +++ b/src/function/twikoo/package.json @@ -2,13 +2,13 @@ "name": "twikoo-func", "main": "index.js", "dependencies": { - "@cloudbase/node-sdk": "^2.4.0", + "@cloudbase/node-sdk": "^2.4.4", "akismet-api": "^5.1.0", "axios": "^0.21.0", "blueimp-md5": "^2.18.0", "bowser": "^2.11.0", "cheerio": "^1.0.0-rc.3", - "dompurify": "^2.2.2", + "dompurify": "^2.2.3", "jsdom": "^16.4.0", "marked": "^1.2.5", "nodemailer": "^6.4.16", diff --git a/src/js/entites/comment.js b/src/js/entites/comment.js index 8c9d78a92..89d347f37 100644 --- a/src/js/entites/comment.js +++ b/src/js/entites/comment.js @@ -9,6 +9,7 @@ class Comment { this.nick = model.nick // 昵称 this.mail = model.mail // 邮箱 this.mailMd5 = model.mailMd5 // 邮箱 MD5 + this.avatar = model.avatar // 头像 URL this.link = model.link // 网址 /* 评论数据 */ diff --git a/src/js/utils/avatar.js b/src/js/utils/avatar.js new file mode 100644 index 000000000..a19a76338 --- /dev/null +++ b/src/js/utils/avatar.js @@ -0,0 +1,14 @@ +function isQQ (mail) { + return /^[1-9][0-9]{4,10}$/.test(mail) || + /^[1-9][0-9]{4,10}@qq.com$/.test(mail) +} + +function getQQAvatar (qq) { + const qqNum = qq.replace(/@qq.com/g, '') + return `https://thirdqq.qlogo.cn/g?b=sdk&nk=${qqNum}&s=140` +} + +export { + isQQ, + getQQAvatar +} diff --git a/src/js/utils/index.js b/src/js/utils/index.js index 3350f48aa..bf7dfa1f5 100644 --- a/src/js/utils/index.js +++ b/src/js/utils/index.js @@ -1,6 +1,7 @@ import timeago from './timeago' import marked from './marked' import call from './api' +import { isQQ, getQQAvatar } from './avatar' const isNotSet = (option) => { return option === undefined || option === null || option === '' @@ -70,6 +71,8 @@ export { marked, call, getFuncVer, + isQQ, + getQQAvatar, getCommentsCountApi, getRecentCommentsApi } diff --git a/src/view/App.vue b/src/view/App.vue index a1056da44..c5326f4a7 100644 --- a/src/view/App.vue +++ b/src/view/App.vue @@ -1,7 +1,6 @@