diff --git a/README.md b/README.md index 0e02931..84fcc87 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,9 @@ npm run lint - [x] F 修复 login 200 重定向动态域名 v0.0.8 - [x] F 修复 MacOS 不能复制粘贴 添加菜单映射 v0.0.9 - [x] N 新增 导出好友列表完成后通知消息 v0.0.9 +- [x] F 修复 侧边栏分组人数在切换用户后不对 - 分组对应用户 v0.1.0 +- [x] N 新增 自定义 图灵key v0.1.0 +- [x] N 新增 心跳图标 v0.1.0 ## 依赖 This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[de85f81](https://github.com/SimulatedGREG/electron-vue/tree/de85f81890c01500113738bfe57bef136f9fbf52) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html). diff --git a/build/github/latest-mac.json b/build/github/latest-mac.json index a9c7726..072c2a1 100644 --- a/build/github/latest-mac.json +++ b/build/github/latest-mac.json @@ -1,5 +1,5 @@ { - "version": "0.0.9", - "releaseDate": "2017-11-08T10:36:06.201Z", - "url": "https://github.com/joehecn/j/releases/download/v0.0.9/j-0.0.9-mac.zip" + "version": "0.1.0", + "releaseDate": "2017-11-09T03:47:40.668Z", + "url": "https://github.com/joehecn/j/releases/download/v0.1.0/j-0.1.0-mac.zip" } diff --git a/package.json b/package.json index 1422551..9f2c444 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "j", - "version": "v0.0.9", + "version": "v0.1.0", "author": "joehe ", "description": "An electron-vue project", "main": "./dist/electron/main.js", diff --git a/src/renderer/jbot/daemon.js b/src/renderer/jbot/daemon.js index f56daf0..9224c90 100644 --- a/src/renderer/jbot/daemon.js +++ b/src/renderer/jbot/daemon.js @@ -46,7 +46,7 @@ export default new class Daemon extends Emitter { this.emit('on_memberlist', res.MemberList) while (true) { - console.log('心跳') + // console.log('心跳') res = await synccheck(ctx.BaseRequest, ctx.SyncKey.List) // 新消息 diff --git a/src/renderer/jbot/index.js b/src/renderer/jbot/index.js index f42d9cc..60a0854 100644 --- a/src/renderer/jbot/index.js +++ b/src/renderer/jbot/index.js @@ -134,7 +134,7 @@ export default new class JBot extends Emitter { } async robotsendmsg (msg) { - const res = await tuling.sendmsg(msg.Content, msg.FromUserName.replace(/@/g, '')) + const res = await tuling.sendmsg(store.state.tulingkey, msg.Content, msg.FromUserName.replace(/@/g, '')) CTX.method = 'sendmsg' diff --git a/src/renderer/jbot/tuling.js b/src/renderer/jbot/tuling.js index 4b90dc3..f95d490 100644 --- a/src/renderer/jbot/tuling.js +++ b/src/renderer/jbot/tuling.js @@ -1,13 +1,13 @@ import rpn from 'request-promise-native' -export const sendmsg = async (info, userid) => { +export const sendmsg = async (key, info, userid) => { const res = await rpn({ url: 'http://www.tuling123.com/openapi/api', method: 'POST', json: true, body: { - key: '778d4422ba5f4bbbbf87e968f43a9102', + key, // '778d4422ba5f4bbbbf87e968f43a9102' info, userid } diff --git a/src/renderer/main.js b/src/renderer/main.js index 92ec3e5..464568c 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -1,4 +1,7 @@ import Vue from 'vue' + +import './style/iconfont.css' + import { Button, Input, @@ -29,6 +32,7 @@ Vue.use(TabPane) // Vue.use(Upload) Vue.prototype.$confirm = MessageBox.confirm +Vue.prototype.$prompt = MessageBox.prompt Vue.prototype.$notify = Notification // title diff --git a/src/renderer/store/actions.js b/src/renderer/store/actions.js index 608006e..083218e 100644 --- a/src/renderer/store/actions.js +++ b/src/renderer/store/actions.js @@ -2,10 +2,14 @@ 'use strict' // import * as api from '@/api' -import { SET_USER } from './mutation-types.js' +import { SET_USER, SET_KEY } from './mutation-types.js' export default { setUser ({ commit }, user) { commit(SET_USER, user) + }, + + setKey ({ commit }, key) { + commit(SET_KEY, key) } } diff --git a/src/renderer/store/index.js b/src/renderer/store/index.js index 0baa1ee..13ad7fe 100644 --- a/src/renderer/store/index.js +++ b/src/renderer/store/index.js @@ -5,6 +5,7 @@ import Vue from 'vue' import Vuex from 'vuex' import mutations from './mutations.js' import actions from './actions.js' +import plugins from './plugins.js' import { DEFAULT_USER } from '@/util' Vue.use(Vuex) @@ -14,10 +15,12 @@ export const USER_KEY = 'user' // Local Storage Key const store = new Vuex.Store({ strict: process.env.NODE_ENV !== 'production', state: { + tulingkey: window.localStorage.tulingkey || '', user: DEFAULT_USER }, mutations, - actions + actions, + plugins }) export default store diff --git a/src/renderer/store/mutation-types.js b/src/renderer/store/mutation-types.js index 823496f..2bc0be0 100644 --- a/src/renderer/store/mutation-types.js +++ b/src/renderer/store/mutation-types.js @@ -2,3 +2,4 @@ 'use strict' export const SET_USER = 'SET_USER' +export const SET_KEY = 'SET_KEY' diff --git a/src/renderer/store/mutations.js b/src/renderer/store/mutations.js index 99a5ddb..93f6e26 100644 --- a/src/renderer/store/mutations.js +++ b/src/renderer/store/mutations.js @@ -1,10 +1,14 @@ 'use strict' -import { SET_USER } from './mutation-types.js' +import { SET_USER, SET_KEY } from './mutation-types.js' export default { [SET_USER] (state, user) { state.user = user + }, + + [SET_KEY] (state, key) { + state.tulingkey = key } } diff --git a/src/renderer/store/plugins.js b/src/renderer/store/plugins.js new file mode 100644 index 0000000..cd021a9 --- /dev/null +++ b/src/renderer/store/plugins.js @@ -0,0 +1,15 @@ + +'use strict' + +import { SET_KEY } from './mutation-types.js' + +const localStoragePlugin = store => { + store.subscribe((mutation, state) => { + if (mutation.type === SET_KEY) { + console.log(state) + window.localStorage.tulingkey = state.tulingkey + } + }) +} + +export default [localStoragePlugin] diff --git a/src/renderer/style/iconfont.css b/src/renderer/style/iconfont.css new file mode 100644 index 0000000..78a6326 --- /dev/null +++ b/src/renderer/style/iconfont.css @@ -0,0 +1,19 @@ + +@font-face {font-family: "iconfont"; + src: url('iconfont.eot?t=1510195890723'); /* IE9*/ + src: url('iconfont.eot?t=1510195890723#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAT4AAsAAAAAB0QAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kgtY21hcAAAAYAAAABeAAABhppEBr5nbHlmAAAB4AAAASgAAAEsuU72Z2hlYWQAAAMIAAAALwAAADYPcwsoaGhlYQAAAzgAAAAcAAAAJAfeA4RobXR4AAADVAAAAAwAAAAMC+kAAGxvY2EAAANgAAAACAAAAAgAdgCWbWF4cAAAA2gAAAAfAAAAIAESAF1uYW1lAAADiAAAAUUAAAJtPlT+fXBvc3QAAATQAAAAJQAAADbP6ljueJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/sE4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDxzZm7438AQw9zA0AAUZgTJAQAoVQyveJzFkMENgDAMAy9t6QMxCA+26BK8mKMTd41iQnkwQS05VhxLiQIsQBQPMYFdGA9OueZ+ZHU/eSZLjUBtpXf1nyqiWXYNKplpsHmr/9i87qPTV6iDOrGVl4Qb+ocMmwAAeJwVj71Kw1AYhr/vHJMmtU3syX/aNE1je5RqwBjroLY0WKEiVHBy9AJ0cegiUgXBQcFrEMHRoaNdvBTR64imDy8P7/qAAPD3TefUBg3WYAsO4RQAxQ42FeJhwJOIdNAIBMPSFcpDHhTCZkQP0GqKuhl3k7YlFkQVFazjdhB3eUQ47iQ9soex6SE6VfeMtWqMvmDR5vWH7Ji8ouGHNbW3mY02+nrc0KRJiTGHsSdJFASJkCVVwUvLlAW5KGZvguoac3+d+FhyuHtyXm5U2cVjcuW1LBlxOkWt2lDe+xW3ku/GNTXmFFbKku2Ww1UdJ7/Ltlby2j+Qg3nrB/0in6ACyKSd7HZjH3NZpk5vs/vsbjAYzo4WGqa4n13j8+Kl43GaDmfwD9JCNUF4nGNgZGBgAGJHx8yOeH6brwzcLAwgcE3z8SYE/X89CwOzBJDLwcAEEgUAHV4KIwB4nGNgZGBgbvjfwBDDwgACQJKRARUwAwBHCQJsBAAAAAPpAAAEAAAAAAAAAAB2AJZ4nGNgZGBgYGYIZGBlAAEmIOYCQgaG/2A+AwAQ9wFwAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nGNgYoAALgbsgJmRiZGZkYWBsYIjI7GoJK00J4eBAQAfRwP/AAAA') format('woff'), + url('iconfont.ttf?t=1510195890723') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('iconfont.svg?t=1510195890723#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family:"iconfont" !important; + font-size:16px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-hartfull:before { content: "\e643"; } + diff --git a/src/renderer/style/iconfont.eot b/src/renderer/style/iconfont.eot new file mode 100644 index 0000000..21d98bd Binary files /dev/null and b/src/renderer/style/iconfont.eot differ diff --git a/src/renderer/style/iconfont.svg b/src/renderer/style/iconfont.svg new file mode 100644 index 0000000..72ed31b --- /dev/null +++ b/src/renderer/style/iconfont.svg @@ -0,0 +1,36 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + diff --git a/src/renderer/style/iconfont.ttf b/src/renderer/style/iconfont.ttf new file mode 100644 index 0000000..63a99f5 Binary files /dev/null and b/src/renderer/style/iconfont.ttf differ diff --git a/src/renderer/style/iconfont.woff b/src/renderer/style/iconfont.woff new file mode 100644 index 0000000..de8e580 Binary files /dev/null and b/src/renderer/style/iconfont.woff differ diff --git a/src/renderer/views/Home.vue b/src/renderer/views/Home.vue index f0edb9d..f9c9401 100644 --- a/src/renderer/views/Home.vue +++ b/src/renderer/views/Home.vue @@ -2,7 +2,12 @@
自动回复 + 删除图灵key 导出好友列表 +
+ +
@@ -118,7 +123,8 @@ export default { data () { return { - robot: false, + jumping: true, + robot: false, // 自动回复 memberlist: [], batchlist: [], // [ @@ -196,6 +202,16 @@ export default { } }, + watch: { + robot (val) { + // 如果为 true, 检测 tuling key + // 如果没有 key, 打开 输入key对话框 + if (val && !this.$store.state.tulingkey) { + this.openInputKey() + } + } + }, + filters: { filterNum (md5) { let num = 0 @@ -209,32 +225,21 @@ export default { }, mounted () { - this.groups = JSON.parse(window.localStorage.groups || '[]') - - // this.memberlist = JSON.parse(window.localStorage.memberlist || '[]').map(item => { - // item.md5 = MD5(`${item.AttrStatus}${item.NickName}`) - // return item - // }) - // this.showPage = true - jbot.on('on_error', err => { console.log(err) }).on('on_reluser', user => { this.$store.dispatch('setUser', user) + this.groups = JSON.parse(window.localStorage[user.Uin] || '[]') }).on('on_memberlist', memberlist => { this.memberlist = memberlist.filter(item => { return item.AttrStatus > 0 && item.UserName[0] === '@' }).map(item => { - // item.md5 = MD5(`${item.AttrStatus}${item.NickName}`) - // console.log(item.md5) item.md5 = SparkMD5.hash(`${item.AttrStatus}${item.NickName}`) return item }) this.showPage = true }).on('on_msg', msg => { - // console.log(msg) - // console.log(this.robot) // 自动回复 && 群聊不回复 if (this.robot && msg.FromUserName.substring(1, 2) !== '@') { jbot.robotsendmsg(msg) @@ -257,21 +262,51 @@ export default { if (state === 'completed') { this.$notify.success({ title: '成功', - message: '下载成功' + message: '导出好友成功' }) } else { this.$notify.error({ title: '失败', - message: '下载失败' + message: '导出好友失败' }) } }) + // this.showPage = true // 守护进程 - jbot.daemon() + jbot.daemon().then(() => { + this.jumping = false + this.$notify.error({ + title: '失败', + message: '守护进程已死', + duration: 0 + }) + }) }, methods: { + openInputKey () { + this.$prompt('提示: 如果没有key, 请到 www.tuling123.com 注册一个', '请输入图灵 key', { + confirmButtonText: '确定', + cancelButtonText: '取消', + inputPattern: /^[a-z0-9]{32}$/, + inputErrorMessage: 'key 格式不正确' + }).then(({ value }) => { + this.$store.dispatch('setKey', value) + }).catch(() => { + this.robot = false + }) + }, + + removeKey () { + this.$store.dispatch('setKey', '') + this.robot = false + this.$notify.success({ + title: '成功', + message: '删除图灵key成功' + }) + }, + downloadMemberlist () { if (this.memberlist.length > 0) { this.downloading = true @@ -304,7 +339,7 @@ export default { md5: {} }) - window.localStorage.groups = JSON.stringify(this.groups) + window.localStorage[this.$store.state.user.Uin] = JSON.stringify(this.groups) } this.newgroupname = '' @@ -321,7 +356,7 @@ export default { this.selected = -1 this.groups.splice(index, 1) - window.localStorage.groups = JSON.stringify(this.groups) + window.localStorage[this.$store.state.user.Uin] = JSON.stringify(this.groups) }).catch(() => {}) }, @@ -330,7 +365,7 @@ export default { let _item = this.groups[this.selected] _item.md5[item.md5] = !item.checked this.$set(this.groups, this.selected, _item) - window.localStorage.groups = JSON.stringify(this.groups) + window.localStorage[this.$store.state.user.Uin] = JSON.stringify(this.groups) this.searchText = '' }, @@ -465,6 +500,32 @@ export default { border-bottom: 1px solid #ddd; } +.hm-icon { + position: absolute; + margin-top: -14px; + font-size: 22px; + color: #ddd; +} + +.hm-icon-life { + color: red; + animation:jump 1.5s infinite linear; +} + +@keyframes jump { + 0% { + font-size: 20px; + } + + 50% { + font-size: 24px; + } + + 100% { + font-size: 20px; + } +} + .left { background: #eaeaea; border-right: 1px solid #ddd;