update
1. add login action 2. add user info getter 3. add top menu ui
This commit is contained in:
parent
b8a9e43033
commit
e2de8f5d85
9
jsconfig.json
Normal file
9
jsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "classic",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
@ -2,15 +2,18 @@
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
<Loading />
|
||||
<Dialog />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Loading from '@/components/Loading'
|
||||
import Dialog from '@/components/Dialog'
|
||||
export default {
|
||||
name: 'root-view',
|
||||
components: {
|
||||
Loading
|
||||
Loading,
|
||||
Dialog
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
14
src/components/ControlPanel/channelList/index.vue
Normal file
14
src/components/ControlPanel/channelList/index.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<sui-container>
|
||||
|
||||
</sui-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ChannelList',
|
||||
data () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
36
src/components/ControlPanel/index.vue
Normal file
36
src/components/ControlPanel/index.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class='cp-div'>
|
||||
<TopMenu />
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.cp-div {
|
||||
padding-top: 60px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import TopMenu from './topMenu'
|
||||
import {mapActions} from 'vuex'
|
||||
export default {
|
||||
name: 'ControlPanel',
|
||||
components: {
|
||||
TopMenu
|
||||
},
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
created () {
|
||||
this.checkSession((flag) => {
|
||||
if (flag === false) {
|
||||
this.$router.replace('/')
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['checkSession'])
|
||||
}
|
||||
}
|
||||
</script>
|
22
src/components/ControlPanel/topMenu.vue
Normal file
22
src/components/ControlPanel/topMenu.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<sui-menu fluid borderless fixed='top'>
|
||||
<sui-container>
|
||||
<sui-menu-menu position='right'>
|
||||
<sui-menu-item>User: {{userInfo.name}}</sui-menu-item>
|
||||
</sui-menu-menu>
|
||||
</sui-container>
|
||||
</sui-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex'
|
||||
export default {
|
||||
name: 'TopMenu',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['userInfo'])
|
||||
}
|
||||
}
|
||||
</script>
|
38
src/components/Dialog/index.vue
Normal file
38
src/components/Dialog/index.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<sui-modal v-model="openModal">
|
||||
<sui-modal-content>
|
||||
{{msg}}
|
||||
</sui-modal-content>
|
||||
<sui-modal-actions>
|
||||
<sui-button @click.native="closeDialog">OK</sui-button>
|
||||
</sui-modal-actions>
|
||||
</sui-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters, mapMutations} from 'vuex'
|
||||
export default {
|
||||
name: 'Dialog',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['removeDialog']),
|
||||
closeDialog: function () {
|
||||
if (typeof this.dialogMsg.act === 'function') this.dialogMsg.act()
|
||||
this.removeDialog()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['dialogMsg']),
|
||||
msg: function () {
|
||||
if (this.dialogMsg === null) return ''
|
||||
return this.dialogMsg.msg
|
||||
},
|
||||
openModal: function () {
|
||||
if (this.dialogMsg === null) return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -8,7 +8,7 @@
|
||||
<input placeholder="Account" v-model="account">
|
||||
</sui-form-field>
|
||||
<sui-form-field>
|
||||
<input placeholder="Password" v-model="password">
|
||||
<input placeholder="Password" type="password" v-model="password">
|
||||
</sui-form-field>
|
||||
<sui-button type="submit" fluid color='teal'>Login</sui-button>
|
||||
<sui-button type="button" @click="go_oauth" class="twitch-button" fluid color='violet'>Login with Twitch</sui-button>
|
||||
@ -49,18 +49,22 @@ export default {
|
||||
this.checkSession((flag) => {
|
||||
// check login session
|
||||
// true === isLogin
|
||||
console.log(flag)
|
||||
if (flag === true) {
|
||||
this.$router.push('/cp')
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['toggleLoading']),
|
||||
...mapActions(['checkSession']),
|
||||
...mapActions(['checkSession', 'sendLogin']),
|
||||
login: function () {
|
||||
console.log('login submit')
|
||||
this.toggleLoading(1)
|
||||
setTimeout(() => {
|
||||
this.toggleLoading(0)
|
||||
}, 1000)
|
||||
this.sendLogin({
|
||||
account: this.account,
|
||||
password: this.password
|
||||
}, () => {
|
||||
this.$router.push('/cp')
|
||||
})
|
||||
},
|
||||
go_oauth: function () {
|
||||
window.location.href = apiUrl.replace(/\/$/, '') + '/twitch/login?tourl=' + encodeURIComponent(window.location.href)
|
||||
|
@ -2,6 +2,8 @@ import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
// import HelloWorld from '@/components/HelloWorld'
|
||||
import Login from '@/components/Login'
|
||||
import ControlPanel from '@/components/ControlPanel'
|
||||
import ChannelList from '@/components/ControlPanel/channelList'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
@ -13,6 +15,23 @@ export default new Router({
|
||||
path: '/',
|
||||
name: 'Login',
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
path: '/cp',
|
||||
name: 'ControlPanel',
|
||||
component: ControlPanel,
|
||||
children: [
|
||||
{
|
||||
path: 'channels',
|
||||
alias: '',
|
||||
name: 'ChannelList',
|
||||
component: ChannelList
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: 'channels'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import {apiUrl} from '@/tools'
|
||||
import {apiUrl, chkObject} from '@/tools'
|
||||
|
||||
const client = axios.create({
|
||||
baseURL: apiUrl,
|
||||
@ -11,15 +11,52 @@ export default {
|
||||
commit('toggleLoading', true)
|
||||
let flag = false
|
||||
try {
|
||||
await client({
|
||||
let result = await client({
|
||||
method: 'get',
|
||||
url: '/api/session'
|
||||
})
|
||||
if ('data' in result) {
|
||||
commit('setUserInfo', {
|
||||
name: result.data.user.name || '',
|
||||
type: result.data.user.type || ''
|
||||
})
|
||||
}
|
||||
flag = true
|
||||
} catch (err) {
|
||||
flag = false
|
||||
}
|
||||
if (typeof cb === 'function') cb(flag)
|
||||
commit('toggleLoading', false)
|
||||
},
|
||||
async sendLogin ({commit}, {account, password}, cb = null) {
|
||||
let chk = chkObject.bind({body: {account, password}})
|
||||
if (!chk('account', 'string') || !chk('password', 'string')) {
|
||||
commit('addDialog', {
|
||||
msg: '帳號密碼不能留空'
|
||||
})
|
||||
return
|
||||
}
|
||||
let data = {
|
||||
account,
|
||||
password
|
||||
}
|
||||
commit('toggleLoading', true)
|
||||
try {
|
||||
await client({
|
||||
method: 'post',
|
||||
url: '/api/login',
|
||||
data
|
||||
})
|
||||
if (typeof cb === 'function') cb()
|
||||
} catch (err) {
|
||||
let msg = ''
|
||||
if ('response' in err && 'data' in err.response && 'message' in err.response.data) {
|
||||
msg = err.response.data.message
|
||||
} else {
|
||||
msg = 'unknown error'
|
||||
}
|
||||
commit('addDialog', {msg})
|
||||
}
|
||||
commit('toggleLoading', false)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,3 @@
|
||||
export const getLoading = state => !!state.loading
|
||||
export const dialogMsg = state => state.dialog[0] || null
|
||||
export const userInfo = state => state.user
|
||||
|
@ -6,10 +6,17 @@ import * as getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const state = {
|
||||
loading: false,
|
||||
dialog: [],
|
||||
user: {
|
||||
name: '',
|
||||
type: ''
|
||||
}
|
||||
}
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
loading: false
|
||||
},
|
||||
state,
|
||||
mutations,
|
||||
getters,
|
||||
actions
|
||||
|
@ -1,5 +1,23 @@
|
||||
export default {
|
||||
toggleLoading (state, loading = null) {
|
||||
state.loading = !!loading
|
||||
},
|
||||
setUserInfo (state, {name, type}) {
|
||||
if (typeof name !== 'string' || name.trim().length === 0) return
|
||||
if (typeof type !== 'string' || type.trim().length === 0) return
|
||||
name = name.trim()
|
||||
type = type.trim()
|
||||
state.user = {
|
||||
...state.user,
|
||||
name,
|
||||
type
|
||||
}
|
||||
},
|
||||
addDialog (state, {msg, act = null}) {
|
||||
if (typeof msg !== 'string' || msg.trim().length === 0) return
|
||||
state.dialog = [...state.dialog, {msg, act}]
|
||||
},
|
||||
removeDialog (state) {
|
||||
state.dialog = state.dialog.slice(1)
|
||||
}
|
||||
}
|
||||
|
40
src/tools.js
40
src/tools.js
@ -1 +1,39 @@
|
||||
export const apiUrl = 'https://bot.trj.tw'
|
||||
export const apiUrl = 'https://bot.trj.tw'
|
||||
|
||||
export const chkObject = function (key = '', type = '', empty = false) {
|
||||
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
|
||||
|
||||
switch (type) {
|
||||
case 'string':
|
||||
if (typeof this.body[key] !== 'string' || (!empty && !this.body[key].trim())) return false
|
||||
break
|
||||
case 'number':
|
||||
if (!isFinite(this.body[key])) return false
|
||||
break
|
||||
case 'boolean':
|
||||
if (typeof this.body[key] !== 'boolean') return false
|
||||
break
|
||||
case 'array':
|
||||
if (!Array.isArray(this.body[key]) || (!empty && this.body[key].length === 0)) return false
|
||||
break
|
||||
case 'uuid':
|
||||
if (typeof this.body[key] !== 'string') return false
|
||||
if (!empty && this.body[key] === '') return false
|
||||
if (!empty && !uuidChk.test(this.body[key])) return false
|
||||
break
|
||||
case 'object':
|
||||
if (typeof this.body[key] !== 'object') return false
|
||||
try {
|
||||
let str = JSON.stringify(this.body[key])
|
||||
JSON.parse(str)
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
break
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user