Compare commits

..

5 Commits

Author SHA1 Message Date
Jay
d507cbff55 update 2018-12-05 21:04:40 +08:00
Jay
0f479b1f9b add msg item 2018-12-04 23:25:41 +08:00
Jay
f6a1b5a6c0 add line log list 2018-12-04 00:16:07 +08:00
Jay
88733e23bc add linelog page , not fin 2018-10-14 22:27:11 +08:00
Jay
de76666bc4 add menu item 2018-10-12 18:01:47 +08:00
12 changed files with 261 additions and 29 deletions

13
package-lock.json generated
View File

@ -5417,7 +5417,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -5832,7 +5833,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -5888,6 +5890,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "2.1.1" "ansi-regex": "2.1.1"
} }
@ -5931,12 +5934,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },

View File

@ -0,0 +1,17 @@
<template>
<div>
<sui-image :src="'https://bot.trj.tw/image/line_log_image/' + image" class="img-item"/>
</div>
</template>
<style lang="less" scope>
.img-item {
width: 250px;
}
</style>
<script>
export default {
props: ['image']
}
</script>

View File

@ -0,0 +1,38 @@
<template>
<div class="msg-content">
<sui-label class="time-field">{{ parseTime }}</sui-label>
<TextItem v-if="type === 'text'" :message="msg" />
<ImageItem v-if="type === 'image'" :image="msg" />
</div>
</template>
<style lang="less" scope>
.msg-content{
padding: 0.4em
}
.time-field{
margin-bottom: 5px !important;
}
</style>
<script>
import TextItem from './text-item.vue'
import ImageItem from './image-item.vue'
import {padleft} from '@/tools'
export default {
props: ['type', 'msg', 'time'],
components: {
TextItem,
ImageItem
},
data () {
return {}
},
computed: {
parseTime () {
let date = new Date(this.time)
return `${date.getFullYear()}-${date.getMonth() + 1}-${padleft(date.getDate().toString(), 2)} ${padleft(date.getHours(), 2)}:${padleft(date.getMinutes(), 2)}:${padleft(date.getSeconds(), 2)}`
}
}
}
</script>

View File

@ -0,0 +1,9 @@
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
props: ['message']
}
</script>

View File

@ -0,0 +1,82 @@
<template>
<sui-container>
<sui-grid>
<sui-grid-row>
<sui-grid-column :width="4">
<sui-segment>
<sui-list divided>
<sui-list-item @click="changeGroup('')">All</sui-list-item>
<sui-list-item v-for="it in lineGroups" :key="it.id" @click="changeGroup(it.id)">
{{ it.name }}
</sui-list-item>
</sui-list>
</sui-segment>
</sui-grid-column>
<sui-grid-column :width="12">
<sui-segment>
<sui-list>
<sui-list-item v-for="it in list" :key="it.id">
<sui-segment>
<sui-list-header><sui-label :basic="true">{{ it.group_name }}</sui-label>&nbsp;{{ it.user_name }}</sui-list-header>
<MessageItem :type="it.type" :msg="it.message" :time="it.ctime" />
</sui-segment>
</sui-list-item>
</sui-list>
</sui-segment>
</sui-grid-column>
</sui-grid-row>
</sui-grid>
</sui-container>
</template>
<script>
import MessageItem from './components/message-item.vue'
import {mapActions, mapGetters} from 'vuex'
export default {
name: 'LineLog',
components: {
MessageItem
},
data () {
return {
list: [],
nowGroup: '',
page: {
cur: 1,
total: 1
}
}
},
updated () {
console.log(this.lineGroups)
},
methods: {
...mapActions(['getLineGroups', 'getLogList']),
changeGroup (id = '') {
console.log('change grp ::::: ', id)
if (typeof id !== 'string') return
this.nowGroup = id
this.page = { cur: 1, total: 1 }
this.getLog()
},
getLog (page = -1) {
this.getLogList({
group: this.nowGroup,
page: page,
max: 20,
cb: data => {
this.list = data.list
this.page = data.page
}})
}
},
mounted () {
this.getLineGroups()
this.getLog()
},
computed: {
...mapGetters(['lineGroups'])
}
}
</script>

View File

@ -1,10 +1,13 @@
<template> <template>
<sui-menu fluid borderless fixed='top'> <sui-menu fluid borderless fixed='top'>
<sui-container> <sui-container>
<sui-menu-menu> <sui-menu-menu position="left">
<sui-menu-item :active="activeItem === '' || activeItem === 'channel'"> <sui-menu-item :active="activeItem === '' || activeItem === 'channel'">
<router-link :to="{name: 'ChannelList'}">Channels</router-link> <router-link :to="{name: 'ChannelList'}">Channels</router-link>
</sui-menu-item> </sui-menu-item>
<sui-menu-item :active="activeItem !== '' && activeItem === 'linelog'" v-if="userInfo.type === 'system'">
<router-link :to="{name: 'LineLog'}">Line Log</router-link>
</sui-menu-item>
</sui-menu-menu> </sui-menu-menu>
<sui-menu-menu position='right'> <sui-menu-menu position='right'>
<sui-menu-item>User: {{userInfo.name}}</sui-menu-item> <sui-menu-item>User: {{userInfo.name}}</sui-menu-item>

View File

@ -6,6 +6,7 @@ import ControlPanel from '@/components/ControlPanel'
import ChannelList from '@/components/ControlPanel/channelList' import ChannelList from '@/components/ControlPanel/channelList'
import Channel from '@/components/ControlPanel/channel' import Channel from '@/components/ControlPanel/channel'
import ChannelOpay from '@/components/ControlPanel/channel/opay' import ChannelOpay from '@/components/ControlPanel/channel/opay'
import LineLog from '@/components/ControlPanel/lineLog'
import PublicOpayBar from '@/components/showDonateBar' import PublicOpayBar from '@/components/showDonateBar'
@ -34,6 +35,15 @@ export default new Router({
topMenu: 'channel' topMenu: 'channel'
} }
}, },
{
path: 'linelog',
alias: '',
name: 'LineLog',
component: LineLog,
meta: {
topMenu: 'linelog'
}
},
{ {
path: 'channel/:chid', path: 'channel/:chid',
alias: '', alias: '',

View File

@ -235,5 +235,37 @@ export default {
errorCatch.apply(commit, [err]) errorCatch.apply(commit, [err])
} }
commit('toggleLoading', false) commit('toggleLoading', false)
},
async getLineGroups ({commit, dispatch}) {
try {
let res = await client({
method: 'get',
url: `/api/line/groups`
})
commit('setLineGroups', res.data.list)
} catch (err) {
errorCatch.call(commit, err)
}
},
async getLogList ({commit, dispatch}, {group, page, max = 20, cb = null}) {
console.log('get log list :::::: ', group, page, max)
let chk = chkObject.bind({ body: { group, page, max } })
if (!chk('group', 'string', true) || !chk('page', 'number') || !chk('max', 'number')) return
try {
let opts = {
method: 'get',
url: '/api/line/logs',
params: {
order: 'asc'
}
}
if (group.length > 0) opts.params.group = group
if (page > 1 || page < 0) opts.params.p = page
if (max > 0) opts.params.max = max
let res = await client(opts)
if (cb !== null && typeof cb === 'function') cb(res.data)
} catch (err) {
errorCatch.call(commit, err)
}
} }
} }

View File

@ -6,3 +6,4 @@ export const getChannel = state => id => {
let arr = state.twitch.channels.filter(t => t.id === id) let arr = state.twitch.channels.filter(t => t.id === id)
return arr.length > 0 ? arr[0] : null return arr.length > 0 ? arr[0] : null
} }
export const lineGroups = state => state.line.groups || []

View File

@ -15,6 +15,9 @@ const state = {
}, },
twitch: { twitch: {
channels: [] channels: []
},
line: {
groups: []
} }
} }

View File

@ -39,5 +39,8 @@ export default {
return t return t
}) })
state.twitch.channels = [...list] state.twitch.channels = [...list]
},
setLineGroups (state, list) {
state.line.groups = [...list]
} }
} }

View File

@ -1,21 +1,70 @@
export const apiUrl = 'https://bot.trj.tw' export const apiUrl = 'https://bot.trj.tw'
export const chkObject = function (key = '', type = '', empty = false) { export const padleft = (str, len, pad = '0') => {
if (typeof str !== 'string') str = str.toString()
if (str.length < len) return padleft(`${pad}${str}`, len, pad)
return str
}
/**
* check is number
* @param {any} v input value
* @return {boolean}
*/
export const isNumber = (v) => {
if (!isFinite(v) || v === true || v === false) return false
return true
}
/**
* src value to int
* @param {object} v src value
* @param {number} defVal default value
* @param {number} min range min
* @param {number} max range max
*/
export const toInt = (v, defVal = 0, min = null, max = null) => {
if (!isNumber(defVal)) defVal = 0
if (typeof defVal === 'string') defVal = parseInt(defVal)
min = !isNumber(min) ? null : (typeof min === 'string' ? parseInt(min) : min)
max = !isNumber(max) ? null : (typeof max === 'string' ? parseInt(max) : max)
if (!isNumber(v)) return defVal
if (typeof v === 'string') v = parseInt(v)
if (min !== null && v < min) v = min
if (max !== null && v > max) v = max
return v
}
/**
* check Object
* @param {string} key key name
* @param {string} type type name
* @param {boolean} empty can empty
* @param {number} max max value
*/
export const chkObject = function (key = '', type = '', empty = false, max = null) {
const uuidChk = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i const uuidChk = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
if (!(key in this.body)) return false if (!(key in this.body)) return false
if (isFinite(empty) && (empty !== false && empty !== true)) {
max = toInt(empty, 0)
empty = false
}
switch (type) { switch (type) {
case 'string': case 'string':
if (typeof this.body[key] !== 'string' || (!empty && !this.body[key].trim())) return false if (typeof this.body[key] !== 'string' || (!empty && !this.body[key])) return false
if (max !== null && this.body[key].length > max) return false
break break
case 'number': case 'number':
if (!isFinite(this.body[key])) return false if (!isNumber(this.body[key])) return false
if (max !== null && this.body[key] > max) return false
break break
case 'boolean': case 'boolean':
if (typeof this.body[key] !== 'boolean') return false if (typeof this.body[key] !== 'boolean') return false
break break
case 'array': case 'array':
if (!Array.isArray(this.body[key]) || (!empty && this.body[key].length === 0)) return false if (!Array.isArray(this.body[key]) || (!empty && this.body[key].length === 0)) return false
if (max !== null && this.body[key].length > max) return false
break break
case 'uuid': case 'uuid':
if (typeof this.body[key] !== 'string') return false if (typeof this.body[key] !== 'string') return false
@ -23,7 +72,7 @@ export const chkObject = function (key = '', type = '', empty = false) {
if (!empty && !uuidChk.test(this.body[key])) return false if (!empty && !uuidChk.test(this.body[key])) return false
break break
case 'object': case 'object':
if (typeof this.body[key] !== 'object') return false if (typeof this.body[key] !== 'object' || this.body[key] === null || this.body[key] === undefined) return false
try { try {
let str = JSON.stringify(this.body[key]) let str = JSON.stringify(this.body[key])
JSON.parse(str) JSON.parse(str)
@ -37,23 +86,3 @@ export const chkObject = function (key = '', type = '', empty = false) {
return true return true
} }
/**
* parse number
* @param {any} v input number
* @param {number} def default number
* @param {number} min min number
* @param {number} max max number
* @return {number}
*/
export const toInt = (v, def = 0, min = null, max = null) => {
if (!isFinite(def)) def = 0
if (typeof def === 'string') def = parseInt(def)
min = isFinite(min) ? (typeof min === 'string' ? parseInt(min) : min) : null
max = isFinite(max) ? (typeof max === 'string' ? parseInt(max) : max) : null
if (!isFinite(v)) return def
if (typeof v === 'string') v = parseInt(v)
if (min !== null && v < min) v = min
if (max !== null && v > max) v = max
return v
}