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 @@
-
@@ -9,14 +8,12 @@
diff --git a/src/view/components/TkCounter.vue b/src/view/components/TkCounter.vue
deleted file mode 100644
index 5342df7d7..000000000
--- a/src/view/components/TkCounter.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
diff --git a/src/view/components/TkFooter.vue b/src/view/components/TkFooter.vue
index 087f20ce0..1fabb5a1e 100644
--- a/src/view/components/TkFooter.vue
+++ b/src/view/components/TkFooter.vue
@@ -7,12 +7,33 @@
diff --git a/src/view/components/TkMetaInput.vue b/src/view/components/TkMetaInput.vue
index 85d5313db..d96540c52 100644
--- a/src/view/components/TkMetaInput.vue
+++ b/src/view/components/TkMetaInput.vue
@@ -3,9 +3,9 @@
{{ metaInput.locale }}
@@ -15,9 +15,9 @@