eslint
This commit is contained in:
parent
107afc89bc
commit
a6773358f5
|
@ -94,7 +94,11 @@
|
|||
{
|
||||
"ignoreReadBeforeAssign": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"camelcase": 0,
|
||||
"new-cap": 0,
|
||||
"vue/no-unused-vars": 0,
|
||||
"vue/require-default-prop": 0
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
|
|
|
@ -22,4 +22,4 @@ export default {
|
|||
checkUsername (username) {
|
||||
return fetchAPI('user/checkUsername/', 'get', null, { username })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,4 +16,4 @@ export default {
|
|||
getStatusList () {
|
||||
return fetchAPI('booking/statusList/', 'get')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ export default {
|
|||
getRoomBookingStatusDetail (id, params) {
|
||||
return fetchAPI(`booking/room/${id}/bookingStatus/`, 'get', null, params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,4 @@ export default {
|
|||
deleteSeat (id) {
|
||||
return fetchAPI(`booking/seat/${id}`, 'delete')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ export default {
|
|||
updateSettingDetail (setting) {
|
||||
return fetchAPI('booking/setting/1/', 'put', setting)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,25 +26,25 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import RouteView from '@/components/layouts/RouteView'
|
||||
import { mixinDevice } from '@/utils/mixin.js'
|
||||
import RouteView from '@/components/layouts/RouteView'
|
||||
import { mixinDevice } from '@/utils/mixin.js'
|
||||
|
||||
export default {
|
||||
name: 'UserLayout',
|
||||
components: { RouteView },
|
||||
mixins: [mixinDevice],
|
||||
data () {
|
||||
return {
|
||||
year: (new Date()).getFullYear()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
document.body.classList.add('userLayout')
|
||||
},
|
||||
beforeDestroy () {
|
||||
document.body.classList.remove('userLayout')
|
||||
export default {
|
||||
name: 'UserLayout',
|
||||
components: { RouteView },
|
||||
mixins: [mixinDevice],
|
||||
data () {
|
||||
return {
|
||||
year: (new Date()).getFullYear()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
document.body.classList.add('userLayout')
|
||||
},
|
||||
beforeDestroy () {
|
||||
document.body.classList.remove('userLayout')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -18,45 +18,45 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ALayoutSider from 'ant-design-vue/es/layout/Sider'
|
||||
import Logo from '../tools/Logo'
|
||||
import SMenu from './index'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import ALayoutSider from 'ant-design-vue/es/layout/Sider'
|
||||
import Logo from '../tools/Logo'
|
||||
import SMenu from './index'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
|
||||
export default {
|
||||
name: 'SideMenu',
|
||||
components: { ALayoutSider, Logo, SMenu },
|
||||
mixins: [mixin, mixinDevice],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'inline'
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'dark'
|
||||
},
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
menus: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
export default {
|
||||
name: 'SideMenu',
|
||||
components: { ALayoutSider, Logo, SMenu },
|
||||
mixins: [mixin, mixinDevice],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'inline'
|
||||
},
|
||||
methods: {
|
||||
onSelect (obj) {
|
||||
this.$emit('menuSelect', obj)
|
||||
}
|
||||
theme: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'dark'
|
||||
},
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
menus: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelect (obj) {
|
||||
this.$emit('menuSelect', obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<template>
|
||||
<!-- , width: fixedHeader ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%' -->
|
||||
<a-layout-header v-if="!headerBarFixed"
|
||||
:class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
|
||||
:style="{ padding: '0' }">
|
||||
<a-layout-header
|
||||
v-if="!headerBarFixed"
|
||||
:class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
|
||||
:style="{ padding: '0' }">
|
||||
<div v-if="mode === 'sidemenu'" class="header">
|
||||
<a-icon
|
||||
v-if="device==='mobile'"
|
||||
|
@ -41,72 +42,72 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import UserMenu from '../tools/UserMenu'
|
||||
import SMenu from '../menu/'
|
||||
import Logo from '../tools/Logo'
|
||||
import UserMenu from '../tools/UserMenu'
|
||||
import SMenu from '../menu/'
|
||||
import Logo from '../tools/Logo'
|
||||
|
||||
import { mixin } from '@/utils/mixin.js'
|
||||
import { mixin } from '@/utils/mixin.js'
|
||||
|
||||
export default {
|
||||
name: 'GlobalHeader',
|
||||
components: {
|
||||
UserMenu,
|
||||
SMenu,
|
||||
Logo
|
||||
export default {
|
||||
name: 'GlobalHeader',
|
||||
components: {
|
||||
UserMenu,
|
||||
SMenu,
|
||||
Logo
|
||||
},
|
||||
mixins: [mixin],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
// sidemenu, topmenu
|
||||
default: 'sidemenu'
|
||||
},
|
||||
mixins: [mixin],
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
// sidemenu, topmenu
|
||||
default: 'sidemenu'
|
||||
},
|
||||
menus: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'dark'
|
||||
},
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
device: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'desktop'
|
||||
}
|
||||
menus: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
headerBarFixed: false
|
||||
}
|
||||
theme: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'dark'
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
methods: {
|
||||
handleScroll () {
|
||||
if (this.autoHideHeader) {
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
|
||||
if (scrollTop > 100) {
|
||||
this.headerBarFixed = true
|
||||
} else {
|
||||
this.headerBarFixed = false
|
||||
}
|
||||
device: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'desktop'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
headerBarFixed: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
methods: {
|
||||
handleScroll () {
|
||||
if (this.autoHideHeader) {
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
|
||||
if (scrollTop > 100) {
|
||||
this.headerBarFixed = true
|
||||
} else {
|
||||
this.headerBarFixed = false
|
||||
}
|
||||
},
|
||||
toggle () {
|
||||
this.$emit('toggle')
|
||||
} else {
|
||||
this.headerBarFixed = false
|
||||
}
|
||||
},
|
||||
toggle () {
|
||||
this.$emit('toggle')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -46,8 +46,9 @@
|
|||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<a-layout :class="[layoutMode, `content-width-${contentWidth}`]"
|
||||
:style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
|
||||
<a-layout
|
||||
:class="[layoutMode, `content-width-${contentWidth}`]"
|
||||
:style="{ paddingLeft: contentPaddingLeft, minHeight: '100vh' }">
|
||||
<!-- layout header -->
|
||||
<global-header
|
||||
:mode="layoutMode"
|
||||
|
@ -72,75 +73,75 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import SideMenu from '@/components/menu/SideMenu'
|
||||
import GlobalHeader from '@/components/page/GlobalHeader'
|
||||
import GlobalFooter from '@/components/page/GlobalFooter'
|
||||
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||
import { mapActions, mapState } from 'vuex'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import SideMenu from '@/components/menu/SideMenu'
|
||||
import GlobalHeader from '@/components/page/GlobalHeader'
|
||||
import GlobalFooter from '@/components/page/GlobalFooter'
|
||||
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||
import { mapActions, mapState } from 'vuex'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
|
||||
export default {
|
||||
name: 'GlobalLayout',
|
||||
components: {
|
||||
SideMenu,
|
||||
GlobalHeader,
|
||||
GlobalFooter
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
data () {
|
||||
return {
|
||||
collapsed: false,
|
||||
menus: []
|
||||
export default {
|
||||
name: 'GlobalLayout',
|
||||
components: {
|
||||
SideMenu,
|
||||
GlobalHeader,
|
||||
GlobalFooter
|
||||
},
|
||||
mixins: [mixin, mixinDevice],
|
||||
data () {
|
||||
return {
|
||||
collapsed: false,
|
||||
menus: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
// 主路由
|
||||
mainMenu: state => state.permission.addRouters
|
||||
}),
|
||||
contentPaddingLeft () {
|
||||
if (!this.fixSidebar || this.isMobile()) {
|
||||
return '0'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
// 主路由
|
||||
mainMenu: state => state.permission.addRouters
|
||||
}),
|
||||
contentPaddingLeft () {
|
||||
if (!this.fixSidebar || this.isMobile()) {
|
||||
return '0'
|
||||
}
|
||||
if (this.sidebarOpened) {
|
||||
return '256px'
|
||||
}
|
||||
return '80px'
|
||||
if (this.sidebarOpened) {
|
||||
return '256px'
|
||||
}
|
||||
return '80px'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sidebarOpened (val) {
|
||||
this.collapsed = !val
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.menus = this.mainMenu.find((item) => item.path === '/').children
|
||||
this.collapsed = !this.sidebarOpened
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setSidebar']),
|
||||
toggle () {
|
||||
this.collapsed = !this.collapsed
|
||||
this.setSidebar(!this.collapsed)
|
||||
triggerWindowResizeEvent()
|
||||
},
|
||||
watch: {
|
||||
sidebarOpened (val) {
|
||||
this.collapsed = !val
|
||||
paddingCalc () {
|
||||
let left = ''
|
||||
if (this.sidebarOpened) {
|
||||
left = this.isDesktop() ? '256px' : '80px'
|
||||
} else {
|
||||
left = this.isMobile() && '0' || (this.fixSidebar && '80px' || '0')
|
||||
}
|
||||
console.log('left', left)
|
||||
return left
|
||||
},
|
||||
created () {
|
||||
this.menus = this.mainMenu.find((item) => item.path === '/').children
|
||||
this.collapsed = !this.sidebarOpened
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setSidebar']),
|
||||
toggle () {
|
||||
this.collapsed = !this.collapsed
|
||||
this.setSidebar(!this.collapsed)
|
||||
triggerWindowResizeEvent()
|
||||
},
|
||||
paddingCalc () {
|
||||
let left = ''
|
||||
if (this.sidebarOpened) {
|
||||
left = this.isDesktop() ? '256px' : '80px'
|
||||
} else {
|
||||
left = this.isMobile() && '0' || (this.fixSidebar && '80px' || '0')
|
||||
}
|
||||
console.log('left', left)
|
||||
return left
|
||||
},
|
||||
menuSelect () {
|
||||
if (!this.isDesktop()) {
|
||||
this.collapsed = false
|
||||
}
|
||||
menuSelect () {
|
||||
if (!this.isDesktop()) {
|
||||
this.collapsed = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="page-header">
|
||||
<div class="page-header-index-wide">
|
||||
<!-- <a-breadcrumb class="breadcrumb">-->
|
||||
<!-- <a-breadcrumb-item v-for="(item, index) in breadList" :key="index">-->
|
||||
<!-- <router-link v-if="item.name !== name" :to="{ path: item.path }">-->
|
||||
<!-- {{ item.meta.title }}-->
|
||||
<!-- </router-link>-->
|
||||
<!-- <span v-else>{{ item.meta.title }}</span>-->
|
||||
<!-- </a-breadcrumb-item>-->
|
||||
<!-- </a-breadcrumb>-->
|
||||
<!-- <a-breadcrumb class="breadcrumb">-->
|
||||
<!-- <a-breadcrumb-item v-for="(item, index) in breadList" :key="index">-->
|
||||
<!-- <router-link v-if="item.name !== name" :to="{ path: item.path }">-->
|
||||
<!-- {{ item.meta.title }}-->
|
||||
<!-- </router-link>-->
|
||||
<!-- <span v-else>{{ item.meta.title }}</span>-->
|
||||
<!-- </a-breadcrumb-item>-->
|
||||
<!-- </a-breadcrumb>-->
|
||||
|
||||
<div class="detail">
|
||||
<div class="main" v-if="!$route.meta.hiddenHeaderContent">
|
||||
|
@ -41,62 +41,62 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
// import Breadcrumb from '@/components/tools/Breadcrumb'
|
||||
// import Breadcrumb from '@/components/tools/Breadcrumb'
|
||||
|
||||
export default {
|
||||
name: 'PageHeader',
|
||||
components: {
|
||||
// 's-breadcrumb': Breadcrumb
|
||||
export default {
|
||||
name: 'PageHeader',
|
||||
components: {
|
||||
// 's-breadcrumb': Breadcrumb
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
// breadcrumb: {
|
||||
// type: Array,
|
||||
// default: null,
|
||||
// required: false
|
||||
// },
|
||||
logo: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
}
|
||||
// breadcrumb: {
|
||||
// type: Array,
|
||||
// default: null,
|
||||
// required: false
|
||||
// },
|
||||
logo: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
name: '',
|
||||
// breadList: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
// getBreadcrumb () {
|
||||
// this.breadList = []
|
||||
// // this.breadList.push({name: 'index', path: '/dashboard/', meta: {title: '首页'}})
|
||||
//
|
||||
// this.name = this.$route.name
|
||||
// this.$route.matched.forEach((item) => {
|
||||
// // item.name !== 'index' && this.breadList.push(item)
|
||||
// this.breadList.push(item)
|
||||
// })
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
// $route () {
|
||||
// this.getBreadcrumb()
|
||||
// }
|
||||
avatar: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
name: ''
|
||||
// breadList: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
// this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
// getBreadcrumb () {
|
||||
// this.breadList = []
|
||||
// // this.breadList.push({name: 'index', path: '/dashboard/', meta: {title: '首页'}})
|
||||
//
|
||||
// this.name = this.$route.name
|
||||
// this.$route.matched.forEach((item) => {
|
||||
// // item.name !== 'index' && this.breadList.push(item)
|
||||
// this.breadList.push(item)
|
||||
// })
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
// $route () {
|
||||
// this.getBreadcrumb()
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -18,33 +18,33 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HeaderNotice',
|
||||
props: {
|
||||
tabs: {
|
||||
type: Array,
|
||||
default: null,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loadding: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchNotice () {
|
||||
if (this.loadding) {
|
||||
this.loadding = false
|
||||
return
|
||||
}
|
||||
this.loadding = true
|
||||
setTimeout(() => {
|
||||
this.loadding = false
|
||||
}, 2000)
|
||||
export default {
|
||||
name: 'HeaderNotice',
|
||||
props: {
|
||||
tabs: {
|
||||
type: Array,
|
||||
default: null,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loadding: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchNotice () {
|
||||
if (this.loadding) {
|
||||
this.loadding = false
|
||||
return
|
||||
}
|
||||
this.loadding = true
|
||||
setTimeout(() => {
|
||||
this.loadding = false
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -8,19 +8,19 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Logo',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Booking Admin',
|
||||
required: false
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
required: false
|
||||
}
|
||||
export default {
|
||||
name: 'Logo',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Booking Admin',
|
||||
required: false
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
required: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="user-wrapper">
|
||||
<router-link :to="{ name: 'help' }">
|
||||
<span class="action">
|
||||
<span class="action">
|
||||
<a-icon type="question-circle-o"></a-icon>
|
||||
</span>
|
||||
</span>
|
||||
</router-link>
|
||||
<a-dropdown>
|
||||
<span class="action ant-dropdown-link user-dropdown-menu">
|
||||
|
@ -29,28 +29,28 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'UserMenu',
|
||||
methods: {
|
||||
...mapActions(['Logout']),
|
||||
...mapGetters(['username']),
|
||||
handleLogout () {
|
||||
const that = this
|
||||
this.$confirm({
|
||||
title: '提示',
|
||||
content: '确定要注销登录吗?',
|
||||
onOk () {
|
||||
return that.Logout({})
|
||||
.then(() => {
|
||||
that.$router.push({ name: 'login' })
|
||||
})
|
||||
},
|
||||
onCancel () {
|
||||
}
|
||||
})
|
||||
}
|
||||
export default {
|
||||
name: 'UserMenu',
|
||||
methods: {
|
||||
...mapActions(['Logout']),
|
||||
...mapGetters(['username']),
|
||||
handleLogout () {
|
||||
const that = this
|
||||
this.$confirm({
|
||||
title: '提示',
|
||||
content: '确定要注销登录吗?',
|
||||
onOk () {
|
||||
return that.Logout({})
|
||||
.then(() => {
|
||||
that.$router.push({ name: 'login' })
|
||||
})
|
||||
},
|
||||
onCancel () {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -25,14 +25,14 @@ export const routerMap = [
|
|||
path: '/booking',
|
||||
name: 'booking',
|
||||
component: () => import(/* webpackChunkName: "booking" */ '../views/booking/Booking'),
|
||||
meta: { title: '预约', icon: 'book', permission: ['ADMIN', 'TEACHER'] },
|
||||
meta: { title: '预约', icon: 'book', permission: ['ADMIN', 'TEACHER'] }
|
||||
},
|
||||
{
|
||||
path: '/booking/new',
|
||||
name: 'bookingNew',
|
||||
hidden: true,
|
||||
component: () => import(/* webpackChunkName: "booking" */ '../views/booking/BookingNew'),
|
||||
meta: { title: '新建预约', icon: 'book', permission: ['ADMIN', 'TEACHER'] },
|
||||
meta: { title: '新建预约', icon: 'book', permission: ['ADMIN', 'TEACHER'] }
|
||||
},
|
||||
{
|
||||
path: '/booking/create',
|
||||
|
@ -40,7 +40,7 @@ export const routerMap = [
|
|||
props: true,
|
||||
hidden: true,
|
||||
component: () => import(/* webpackChunkName: "booking" */ '../views/booking/BookingDetail'),
|
||||
meta: { title: '新建预约', permission: ['ADMIN', 'TEACHER'] },
|
||||
meta: { title: '新建预约', permission: ['ADMIN', 'TEACHER'] }
|
||||
},
|
||||
{
|
||||
path: '/booking/:id/edit',
|
||||
|
@ -48,7 +48,7 @@ export const routerMap = [
|
|||
props: true,
|
||||
hidden: true,
|
||||
component: () => import(/* webpackChunkName: "booking" */ '../views/booking/BookingDetail'),
|
||||
meta: { title: '编辑预约', permission: ['ADMIN', 'TEACHER'] },
|
||||
meta: { title: '编辑预约', permission: ['ADMIN', 'TEACHER'] }
|
||||
},
|
||||
{
|
||||
path: '/room',
|
||||
|
@ -122,7 +122,7 @@ export const routerMap = [
|
|||
name: 'settingBooking',
|
||||
component: () => import(/* webpackChunkName: "setting" */ '../views/setting/BookingSetting'),
|
||||
meta: { title: '预约设置', permission: ['ADMIN'] }
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ export const routerMap = [
|
|||
name: 'help',
|
||||
component: () => import(/* webpackChunkName: "help" */ '../views/help/Help'),
|
||||
meta: { title: '帮助', icon: 'question-circle', permission: ['ADMIN', 'TEACHER'] }
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -163,4 +163,4 @@ export const basicRouterMap = [
|
|||
component:
|
||||
() => import(/* webpackChunkName: "exception" */ '@/views/exception/404')
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
@ -11,7 +11,7 @@ const whiteList = ['login'] // no redirect whitelist
|
|||
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start() // start progress bar
|
||||
let isLogin = cookie.get('sessionid')
|
||||
const isLogin = cookie.get('sessionid')
|
||||
if (isLogin) {
|
||||
if (to.path === '/user/login') {
|
||||
next({ name: 'dashboard' })
|
||||
|
@ -52,4 +52,4 @@ router.beforeEach((to, from, next) => {
|
|||
|
||||
router.afterEach(() => {
|
||||
NProgress.done()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@ const getters = {
|
|||
username: state => state.user.username,
|
||||
userid: state => state.user.id,
|
||||
role: state => state.user.role,
|
||||
addRouters: state => state.permission.addRouters,
|
||||
addRouters: state => state.permission.addRouters
|
||||
}
|
||||
|
||||
export default getters
|
||||
|
|
|
@ -12,7 +12,7 @@ export default new Vuex.Store({
|
|||
modules: {
|
||||
app,
|
||||
user,
|
||||
permission,
|
||||
permission
|
||||
},
|
||||
state: {
|
||||
|
||||
|
|
|
@ -52,4 +52,4 @@ const permission = {
|
|||
}
|
||||
}
|
||||
|
||||
export default permission
|
||||
export default permission
|
||||
|
|
|
@ -31,7 +31,7 @@ const user = {
|
|||
key: 'ERROR'
|
||||
})
|
||||
dispatch('Logout').then(() => {})
|
||||
reject('Not a admin or teacher account')
|
||||
reject(new Error('Not a admin or teacher account'))
|
||||
} else {
|
||||
resolve(data)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ const user = {
|
|||
key: 'ERROR'
|
||||
})
|
||||
dispatch('Logout').then(() => {})
|
||||
reject('Not a admin or teacher account')
|
||||
reject(new Error('Not a admin or teacher account'))
|
||||
} else {
|
||||
commit('SET_ID', data.id)
|
||||
commit('SET_USERNAME', data.username)
|
||||
|
|
|
@ -42,7 +42,7 @@ export default function fetchAPI (url, method, data = null, params = null) {
|
|||
} else if (res.ok) {
|
||||
return res.json()
|
||||
} else {
|
||||
throw `${res.status}, ${res.statusText}`
|
||||
throw new Error(`${res.status}, ${res.statusText}`)
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
|
@ -61,7 +61,7 @@ export default function fetchAPI (url, method, data = null, params = null) {
|
|||
export function fetchAPIBase (url, method, data = null, params = null) {
|
||||
let body = null
|
||||
// csrf
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
if (!/^(GET|HEAD|OPTIONS|TRACE)$/.test(method.toUpperCase())) {
|
||||
|
@ -79,4 +79,4 @@ export function fetchAPIBase (url, method, data = null, params = null) {
|
|||
method: method,
|
||||
body: body
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,10 @@ export function removeLoadingAnimate (id = '', timeout = 1500) {
|
|||
* @param fileName
|
||||
*/
|
||||
export function downloadFile (blob, fileName) {
|
||||
let aLink = document.createElement('a')
|
||||
let evt = document.createEvent('HTMLEvents')
|
||||
evt.initEvent('click', true, true) //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
|
||||
const aLink = document.createElement('a')
|
||||
const evt = document.createEvent('HTMLEvents')
|
||||
evt.initEvent('click', true, true) // initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
|
||||
aLink.download = fileName
|
||||
aLink.href = URL.createObjectURL(blob)
|
||||
aLink.click()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
style="width: 100%;"
|
||||
@change="getData()">
|
||||
<a-select-option value="">角色筛选</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in roleList">{{item.name}}</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in roleList" :key="item.id">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col
|
||||
|
@ -84,10 +84,10 @@
|
|||
:dataSource="userList"
|
||||
:pagination="false">
|
||||
<template slot="role" slot-scope="text, record, index">
|
||||
{{roleList.find(item=> item.id === text).name}}
|
||||
{{ roleList.find(item=> item.id === text).name }}
|
||||
</template>
|
||||
<template slot="is_active" slot-scope="text, record, index">
|
||||
{{text ? '有效': '无效'}}
|
||||
{{ text ? '有效': '无效' }}
|
||||
</template>
|
||||
<template slot="operation" slot-scope="text, record, index">
|
||||
<a-button @click="$router.push({name: 'accountEdit', params: {id: record.id.toString()}})">编辑</a-button>
|
||||
|
@ -97,7 +97,7 @@
|
|||
</a-row>
|
||||
<a-row>
|
||||
<a-col class="item">
|
||||
<span style="vertical-align: -5px">共 {{count}} 条</span>
|
||||
<span style="vertical-align: -5px">共 {{ count }} 条</span>
|
||||
<a-pagination
|
||||
v-model="params.page"
|
||||
@change="handelePage"
|
||||
|
@ -111,127 +111,127 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '8%'
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'username',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'role',
|
||||
width: '12%',
|
||||
scopedSlots: { customRender: 'role' }
|
||||
},
|
||||
{
|
||||
title: '积分',
|
||||
dataIndex: 'point',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '上次登陆时间',
|
||||
dataIndex: 'last_login',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'is_active',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'is_active' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' }
|
||||
}
|
||||
]
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/account'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/account'
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '8%'
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'username',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'role',
|
||||
width: '12%',
|
||||
scopedSlots: { customRender: 'role' }
|
||||
},
|
||||
{
|
||||
title: '积分',
|
||||
dataIndex: 'point',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '上次登陆时间',
|
||||
dataIndex: 'last_login',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'is_active',
|
||||
width: '10%',
|
||||
scopedSlots: { customRender: 'is_active' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' }
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Account',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
layout1: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 8 },
|
||||
},
|
||||
layout2: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 4 },
|
||||
},
|
||||
params: {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: '-last_login',
|
||||
role: '',
|
||||
},
|
||||
state: {
|
||||
loading: false,
|
||||
},
|
||||
roleList: [],
|
||||
count: 0,
|
||||
userList: [],
|
||||
setting: {}
|
||||
export default {
|
||||
name: 'Account',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
layout1: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 8 }
|
||||
},
|
||||
layout2: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 4 }
|
||||
},
|
||||
params: {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: '-last_login',
|
||||
role: ''
|
||||
},
|
||||
state: {
|
||||
loading: false
|
||||
},
|
||||
roleList: [],
|
||||
count: 0,
|
||||
userList: [],
|
||||
setting: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
api.getRoleList()
|
||||
.then(data => {
|
||||
this.roleList = data
|
||||
this.getData()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
if (this.$store.getters.role === 'TEACHER') {
|
||||
this.params.teacher = this.$store.getters.userid
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
api.getRoleList()
|
||||
api.getUserList(this.params)
|
||||
.then(data => {
|
||||
this.roleList = data
|
||||
this.getData()
|
||||
this.userList = data.results
|
||||
this.count = data.count
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
if (this.$store.getters.role === 'TEACHER') {
|
||||
this.params.teacher = this.$store.getters.userid
|
||||
}
|
||||
api.getUserList(this.params)
|
||||
.then(data => {
|
||||
this.userList = data.results
|
||||
this.count = data.count
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
handleClearParams () {
|
||||
this.params = {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: '-last_login',
|
||||
role: '',
|
||||
}
|
||||
this.state = {
|
||||
loading: false
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
handelePage (page) {
|
||||
this.params.page = page
|
||||
this.getData()
|
||||
},
|
||||
handleClearParams () {
|
||||
this.params = {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: '-last_login',
|
||||
role: ''
|
||||
}
|
||||
this.state = {
|
||||
loading: false
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
handelePage (page) {
|
||||
this.params.page = page
|
||||
this.getData()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
|
|
@ -13,19 +13,19 @@
|
|||
v-if="isEdit"
|
||||
label="ID"
|
||||
v-bind="layout">
|
||||
{{id}}
|
||||
{{ id }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="isEdit"
|
||||
label="加入日期"
|
||||
v-bind="layout">
|
||||
{{account.date_joined}}
|
||||
{{ account.date_joined }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
v-if="isEdit"
|
||||
label="上次登录时间"
|
||||
v-bind="layout">
|
||||
{{account.last_login || '无'}}
|
||||
{{ account.last_login || '无' }}
|
||||
</a-form-item>
|
||||
<a-divider v-if="isEdit">修改信息</a-divider>
|
||||
<a-form-item
|
||||
|
@ -42,7 +42,7 @@
|
|||
],
|
||||
validateTrigger: 'blur',
|
||||
initialValue: isEdit ? account.username : ''
|
||||
}
|
||||
}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
@ -53,16 +53,16 @@
|
|||
<a-input
|
||||
type="password"
|
||||
v-decorator="[
|
||||
'password',
|
||||
{
|
||||
rules: [
|
||||
{required: !isEdit, message: '请输入密码'},
|
||||
{min: 8, message: '密码长度在8个字符以上'},
|
||||
{validator: notAllNumberValidator, message: '密码不能全为数字'},
|
||||
],
|
||||
validateTrigger: 'blur'
|
||||
}
|
||||
]">
|
||||
'password',
|
||||
{
|
||||
rules: [
|
||||
{required: !isEdit, message: '请输入密码'},
|
||||
{min: 8, message: '密码长度在8个字符以上'},
|
||||
{validator: notAllNumberValidator, message: '密码不能全为数字'},
|
||||
],
|
||||
validateTrigger: 'blur'
|
||||
}
|
||||
]">
|
||||
</a-input>
|
||||
</a-tooltip>
|
||||
<a-input
|
||||
|
@ -77,7 +77,7 @@
|
|||
{validator: notAllNumberValidator, message: '密码不能全为数字'},
|
||||
],
|
||||
validateTrigger: 'blur'
|
||||
}
|
||||
}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
@ -95,7 +95,7 @@
|
|||
{validator: samePasswordValidator, message: '密码不能全为数字'},
|
||||
],
|
||||
validateTrigger: 'blur'
|
||||
}
|
||||
}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
@ -115,7 +115,7 @@
|
|||
initialValue: isEdit ? account.role : (isTeacher ? 'STUDENT' : '')
|
||||
}
|
||||
]">
|
||||
<a-select-option v-for="item in roleList" :value="item.id">{{item.name}}</a-select-option>
|
||||
<a-select-option v-for="item in roleList" :value="item.id" :key="item.id">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
|
@ -132,12 +132,12 @@
|
|||
:disabled="form.getFieldValue('role') !== 'STUDENT'"
|
||||
@search="handleSearch"
|
||||
v-decorator="[
|
||||
'teacher',
|
||||
{
|
||||
initialValue: isEdit ? account.teacher : []
|
||||
}
|
||||
]">
|
||||
<a-select-option v-for="item in teacherList" :value="item.id">{{item.username}} {{item.email}}
|
||||
'teacher',
|
||||
{
|
||||
initialValue: isEdit ? account.teacher : []
|
||||
}
|
||||
]">
|
||||
<a-select-option v-for="item in teacherList" :value="item.id" :key="item.id">{{ item.username }} {{ item.email }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
@ -219,141 +219,137 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/account'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/account'
|
||||
|
||||
export default {
|
||||
name: 'AccountDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
form: this.$form.createForm(this),
|
||||
roleList: [],
|
||||
teacherList: [],
|
||||
params: {
|
||||
search: '',
|
||||
role: 'TEACHER'
|
||||
},
|
||||
account: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
api.getRoleList()
|
||||
export default {
|
||||
name: 'AccountDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
form: this.$form.createForm(this),
|
||||
roleList: [],
|
||||
teacherList: [],
|
||||
params: {
|
||||
search: '',
|
||||
role: 'TEACHER'
|
||||
},
|
||||
account: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
api.getRoleList()
|
||||
.then(data => {
|
||||
this.roleList = data
|
||||
this.getData()
|
||||
if (this.isEdit) {
|
||||
api.getUser(this.id)
|
||||
.then(data => {
|
||||
this.account = data
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getUserList(this.params)
|
||||
.then(data => {
|
||||
this.roleList = data
|
||||
this.getData()
|
||||
this.teacherList = data.results
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
if (this.isEdit) {
|
||||
api.getUser(this.id)
|
||||
api.updateUser(this.account.id, data)
|
||||
.then(data => {
|
||||
this.account = data
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `更新用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
} else {
|
||||
api.createUser(data)
|
||||
.then(data => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `新建用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete () {
|
||||
api.deleteUser(this.id)
|
||||
.then(data => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `删除用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getUserList(this.params)
|
||||
usernameValidator (rule, value, callback) {
|
||||
if ((value && !this.isEdit) || (value && this.isEdit && (value !== this.account.username))) {
|
||||
api.checkUsername(value)
|
||||
.then(data => {
|
||||
this.teacherList = data.results
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
if (this.isEdit) {
|
||||
api.updateUser(this.account.id, data)
|
||||
.then(data => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `更新用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
if (data) {
|
||||
const msg = 'username is duplicated'
|
||||
callback(msg)
|
||||
} else {
|
||||
api.createUser(data)
|
||||
.then(data => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `新建用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
callback()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleDelete () {
|
||||
api.deleteUser(this.id)
|
||||
.then(data => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: `删除用户成功`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
this.$router.push({ name: 'account' })
|
||||
})
|
||||
},
|
||||
usernameValidator (rule, value, callback) {
|
||||
if ((value && !this.isEdit) || (value && this.isEdit && (value !== this.account.username))) {
|
||||
api.checkUsername(value)
|
||||
.then(data => {
|
||||
if (data) {
|
||||
callback('username is duplicated')
|
||||
return false
|
||||
} else {
|
||||
callback()
|
||||
return true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
callback()
|
||||
return true
|
||||
}
|
||||
},
|
||||
notAllNumberValidator (rule, value, callback) {
|
||||
if (/^[0-9]+.?[0-9]*$/.test(value)) {
|
||||
callback('password cant be all numbers')
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
samePasswordValidator (rule, value, callback) {
|
||||
if (value && (value !== this.form.getFieldValue('password'))) {
|
||||
callback('two passwords are different')
|
||||
return false
|
||||
}
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
handleSearch (value) {
|
||||
this.params.search = value
|
||||
this.getData()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
},
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
notAllNumberValidator (rule, value, callback) {
|
||||
if (/^[0-9]+.?[0-9]*$/.test(value)) {
|
||||
const msg = 'password cant be all numbers'
|
||||
callback(msg)
|
||||
}
|
||||
callback()
|
||||
},
|
||||
samePasswordValidator (rule, value, callback) {
|
||||
if (value && (value !== this.form.getFieldValue('password'))) {
|
||||
const msg = 'two passwords are different'
|
||||
callback(msg)
|
||||
}
|
||||
callback()
|
||||
},
|
||||
handleSearch (value) {
|
||||
this.params.search = value
|
||||
this.getData()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
},
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
style="width: 100%;"
|
||||
@change="getData">
|
||||
<a-select-option value="">房间筛选</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in roomList">{{item.name}}</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in roomList" :key="item.id">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col
|
||||
|
@ -67,7 +67,7 @@
|
|||
style="width: 100%;"
|
||||
@change="getData">
|
||||
<a-select-option value="">状态筛选</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in statusList">{{item.name}}</a-select-option>
|
||||
<a-select-option :value="item.id" v-for="item in statusList" :key="item.id">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col
|
||||
|
@ -141,7 +141,7 @@
|
|||
:dataSource="bookingList"
|
||||
:pagination="false">
|
||||
<template slot="status" slot-scope="text, record, index">
|
||||
{{statusList.find(item=>item.id === text).name}}
|
||||
{{ statusList.find(item=>item.id === text).name }}
|
||||
</template>
|
||||
<template slot="operation" slot-scope="text, record, index">
|
||||
<a-button @click="$router.push({name: 'bookingEdit', params: {id: record.id}})">编辑</a-button>
|
||||
|
@ -151,7 +151,7 @@
|
|||
</a-row>
|
||||
<a-row>
|
||||
<a-col class="item">
|
||||
<span style="vertical-align: -5px">共 {{count}} 条</span>
|
||||
<span style="vertical-align: -5px">共 {{ count }} 条</span>
|
||||
<a-pagination
|
||||
v-model="params.page"
|
||||
@change="handelePage"
|
||||
|
@ -165,194 +165,194 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '8%'
|
||||
},
|
||||
{
|
||||
title: '房间',
|
||||
dataIndex: 'room.name',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'start_time',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'end_time',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'user.username',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
width: '14%',
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' }
|
||||
}
|
||||
]
|
||||
import moment from 'moment'
|
||||
import bookingAPI from '../../api/booking'
|
||||
import roomAPI from '../../api/room'
|
||||
import settingAPI from '../../api/setting'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import moment from 'moment'
|
||||
import bookingAPI from '../../api/booking'
|
||||
import roomAPI from '../../api/room'
|
||||
import settingAPI from '../../api/setting'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '8%'
|
||||
},
|
||||
{
|
||||
title: '房间',
|
||||
dataIndex: 'room.name',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'start_time',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'end_time',
|
||||
width: '12%'
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'user.username',
|
||||
width: '14%'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
width: '14%',
|
||||
scopedSlots: { customRender: 'status' }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' }
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Booking',
|
||||
components: {
|
||||
PageLayout
|
||||
export default {
|
||||
name: 'Booking',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
layout1: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 8 }
|
||||
},
|
||||
layout2: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 6 }
|
||||
},
|
||||
params: {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: 'date',
|
||||
room: '',
|
||||
status: '',
|
||||
min_date: this.getDateRangeDefaultValue()[0].format('YYYY-MM-DD'),
|
||||
max_date: this.getDateRangeDefaultValue()[1].format('YYYY-MM-DD'),
|
||||
min_time: '',
|
||||
max_time: ''
|
||||
},
|
||||
state: {
|
||||
loading: false,
|
||||
dateRange: this.getDateRangeDefaultValue(),
|
||||
startTime: new moment(),
|
||||
endTime: new moment()
|
||||
},
|
||||
roomList: [],
|
||||
count: 0,
|
||||
bookingList: [],
|
||||
statusList: [],
|
||||
setting: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
roomAPI.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
})
|
||||
settingAPI.getSettingDetail()
|
||||
.then(data => {
|
||||
this.params.min_time = data.start_time
|
||||
this.params.max_time = data.end_time
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
this.state.startTime = data.start_time
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.state.endTime = data.end_time
|
||||
this.setting = data
|
||||
})
|
||||
bookingAPI.getStatusList()
|
||||
.then(data => {
|
||||
this.statusList = data
|
||||
})
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
bookingAPI.getBookingList(this.params)
|
||||
.then(data => {
|
||||
this.bookingList = data.results
|
||||
this.count = data.count
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
layout1: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 8 },
|
||||
},
|
||||
layout2: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 8 },
|
||||
xl: { span: 6 },
|
||||
},
|
||||
params: {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: 'date',
|
||||
room: '',
|
||||
status: '',
|
||||
min_date: this.getDateRangeDefaultValue()[0].format('YYYY-MM-DD'),
|
||||
max_date: this.getDateRangeDefaultValue()[1].format('YYYY-MM-DD'),
|
||||
min_time: '',
|
||||
max_time: ''
|
||||
},
|
||||
state: {
|
||||
loading: false,
|
||||
dateRange: this.getDateRangeDefaultValue(),
|
||||
startTime: new moment(),
|
||||
endTime: new moment()
|
||||
},
|
||||
roomList: [],
|
||||
count: 0,
|
||||
bookingList: [],
|
||||
statusList: [],
|
||||
setting: {}
|
||||
handleClearParams () {
|
||||
this.params = {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: 'date',
|
||||
room: '',
|
||||
status: '',
|
||||
min_date: this.getDateRangeDefaultValue()[0].format('YYYY-MM-DD'),
|
||||
max_date: this.getDateRangeDefaultValue()[1].format('YYYY-MM-DD'),
|
||||
min_time: this.setting.start_time.format('HH:mm:ss'),
|
||||
max_time: this.setting.end_time.format('HH:mm:ss')
|
||||
}
|
||||
this.state = {
|
||||
loading: false,
|
||||
dateRange: this.getDateRangeDefaultValue(),
|
||||
startTime: this.setting.start_time,
|
||||
endTime: this.setting.end_time
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
roomAPI.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
})
|
||||
settingAPI.getSettingDetail()
|
||||
.then(data => {
|
||||
this.params.min_time = data.start_time
|
||||
this.params.max_time = data.end_time
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
this.state.startTime = data.start_time
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.state.endTime = data.end_time
|
||||
this.setting = data
|
||||
})
|
||||
bookingAPI.getStatusList()
|
||||
.then(data=>{
|
||||
this.statusList = data
|
||||
})
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
bookingAPI.getBookingList(this.params)
|
||||
.then(data => {
|
||||
this.bookingList = data.results
|
||||
this.count = data.count
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
handleClearParams () {
|
||||
this.params = {
|
||||
search: '',
|
||||
page: 1,
|
||||
ordering: 'date',
|
||||
room: '',
|
||||
status: '',
|
||||
min_date: this.getDateRangeDefaultValue()[0].format('YYYY-MM-DD'),
|
||||
max_date: this.getDateRangeDefaultValue()[1].format('YYYY-MM-DD'),
|
||||
min_time: this.setting.start_time.format('HH:mm:ss'),
|
||||
max_time: this.setting.end_time.format('HH:mm:ss')
|
||||
handelePage (page) {
|
||||
this.params.page = page
|
||||
this.getData()
|
||||
},
|
||||
hangdleDateRangeChange (dates, dateStrings) {
|
||||
this.params.min_date = dateStrings[0]
|
||||
this.params.max_date = dateStrings[1]
|
||||
this.getData()
|
||||
},
|
||||
handleStartTimeChange (time, timeString) {
|
||||
this.params.min_time = timeString
|
||||
this.getData()
|
||||
},
|
||||
handleEndTimeChange (time, timeString) {
|
||||
this.params.max_time = timeString
|
||||
this.getData()
|
||||
},
|
||||
getDateRangeDefaultValue () {
|
||||
const now = new moment()
|
||||
const aWeekLater = (new moment()).add(7, 'days')
|
||||
return [now, aWeekLater]
|
||||
},
|
||||
getDisabledHours () {
|
||||
const ret = []
|
||||
const start_hour = this.setting.start_time.hour()
|
||||
const end_hour = this.setting.end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
this.state = {
|
||||
loading: false,
|
||||
dateRange: this.getDateRangeDefaultValue(),
|
||||
startTime: this.setting.start_time,
|
||||
endTime: this.setting.end_time
|
||||
}
|
||||
this.getData()
|
||||
},
|
||||
handelePage (page) {
|
||||
this.params.page = page
|
||||
this.getData()
|
||||
},
|
||||
hangdleDateRangeChange (dates, dateStrings) {
|
||||
this.params.min_date = dateStrings[0]
|
||||
this.params.max_date = dateStrings[1]
|
||||
this.getData()
|
||||
},
|
||||
handleStartTimeChange (time, timeString) {
|
||||
this.params.min_time = timeString
|
||||
this.getData()
|
||||
},
|
||||
handleEndTimeChange (time, timeString) {
|
||||
this.params.max_time = timeString
|
||||
this.getData()
|
||||
},
|
||||
getDateRangeDefaultValue () {
|
||||
let now = new moment()
|
||||
let aWeekLater = (new moment()).add(7, 'days')
|
||||
return [now, aWeekLater]
|
||||
},
|
||||
getDisabledHours () {
|
||||
let ret = []
|
||||
let start_hour = this.setting.start_time.hour()
|
||||
let end_hour = this.setting.end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getDisabledMinutes (selectedHour) {
|
||||
let ret = []
|
||||
if (selectedHour === this.setting.end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getDisabledMinutes (selectedHour) {
|
||||
const ret = []
|
||||
if (selectedHour === this.setting.end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.item {
|
||||
margin: 8px 0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -11,47 +11,49 @@
|
|||
label="ID"
|
||||
v-if="isEdit"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.id}}
|
||||
{{ bookingEdit.id }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="房间"
|
||||
v-bind="layout">
|
||||
<div v-if="isTeacher">{{isEdit ? bookingEdit.room.name : bookingCreate.room.name}}</div>
|
||||
<div v-if="isTeacher">{{ isEdit ? bookingEdit.room.name : bookingCreate.room.name }}</div>
|
||||
<router-link
|
||||
v-else
|
||||
:to="{ name: 'roomEdit', params: { id: bookingEdit.room.id} }">
|
||||
{{isEdit ? bookingEdit.room.name : bookingCreate.room.name}}
|
||||
{{ isEdit ? bookingEdit.room.name : bookingCreate.room.name }}
|
||||
</router-link>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="日期"
|
||||
v-bind="layout">
|
||||
{{isEdit ? bookingEdit.date : bookingCreate.date}}
|
||||
{{ isEdit ? bookingEdit.date : bookingCreate.date }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="开始时间"
|
||||
v-bind="layout">
|
||||
{{isEdit ? bookingEdit.start_time : bookingCreate.start_time}}
|
||||
{{ isEdit ? bookingEdit.start_time : bookingCreate.start_time }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="结束时间"
|
||||
v-bind="layout">
|
||||
{{isEdit ? bookingEdit.end_time : bookingCreate.end_time}}
|
||||
{{ isEdit ? bookingEdit.end_time : bookingCreate.end_time }}
|
||||
</a-form-item>
|
||||
<div v-if="bookingEdit">
|
||||
<a-form-item
|
||||
v-for="(item, index) in bookingEdit.seats" :key="index"
|
||||
v-for="(item, index) in bookingEdit.seats"
|
||||
:key="index"
|
||||
:label="'座位' + (index + 1).toString()"
|
||||
v-bind="layout">
|
||||
<div>{{item.name}}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<div v-if="bookingCreate">
|
||||
<a-form-item
|
||||
v-for="(item, index) in bookingCreate.seats" :key="index"
|
||||
v-for="(item, index) in bookingCreate.seats"
|
||||
:key="index"
|
||||
:label="'座位' + (index + 1).toString()"
|
||||
v-bind="layout">
|
||||
<div>{{item.name}}</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<a-form-item
|
||||
|
@ -66,38 +68,38 @@
|
|||
@search="handleSearch"
|
||||
v-if="!isEdit"
|
||||
v-model="createBookingForm.user">
|
||||
<a-select-option v-for="item in userList" :value="item.id">{{item.username}} {{item.email}}
|
||||
<a-select-option v-for="item in userList" :value="item.id" :key="item.id">{{ item.username }} {{ item.email }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<router-link
|
||||
:to="{ name: 'accountEdit', params: { id: bookingEdit.user.id} }"
|
||||
v-else>
|
||||
{{bookingEdit.user.username}} {{bookingEdit.user.email}}
|
||||
{{ bookingEdit.user.username }} {{ bookingEdit.user.email }}
|
||||
</router-link>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="申请时间"
|
||||
v-if="isEdit"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.created_datetime}}
|
||||
{{ bookingEdit.created_datetime }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="到达时间"
|
||||
v-if="isEdit"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.arrive_time || '未签到'}}
|
||||
{{ bookingEdit.arrive_time || '未签到' }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="离开时间"
|
||||
v-if="isEdit"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.leave_time || '未签离'}}
|
||||
{{ bookingEdit.leave_time || '未签离' }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="状态"
|
||||
v-if="isEdit"
|
||||
v-bind="layout">
|
||||
{{statusName}}
|
||||
{{ statusName }}
|
||||
</a-form-item>
|
||||
<a-form-item v-if="!isEdit">
|
||||
<a-button type="primary" @click="handleCreateSubmit" style="float: right">
|
||||
|
@ -115,12 +117,12 @@
|
|||
<a-form-item
|
||||
label="取消人"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.cancel_by ? bookingEdit.cancel_by.username : ''}}
|
||||
{{ bookingEdit.cancel_by ? bookingEdit.cancel_by.username : '' }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="取消时间"
|
||||
v-bind="layout">
|
||||
{{bookingEdit.cancel_datetime}}
|
||||
{{ bookingEdit.cancel_datetime }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="取消原因"
|
||||
|
@ -130,9 +132,9 @@
|
|||
v-decorator="[
|
||||
'cancel_reason',
|
||||
{rules: [
|
||||
{max: 512, message: '最多512个字符'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: bookingEdit.cancel_reason}
|
||||
{max: 512, message: '最多512个字符'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: bookingEdit.cancel_reason}
|
||||
]">
|
||||
</a-textarea>
|
||||
</a-form-item>
|
||||
|
@ -169,140 +171,140 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import accountAPI from '../../api/account'
|
||||
import bookingAPI from '../../api/booking'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import accountAPI from '../../api/account'
|
||||
import bookingAPI from '../../api/booking'
|
||||
|
||||
export default {
|
||||
name: 'BookingDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: Number,
|
||||
bookingCreate: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
export default {
|
||||
name: 'BookingDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: Number,
|
||||
bookingCreate: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
userList: [],
|
||||
bookingEdit: {
|
||||
room: {
|
||||
id: '0',
|
||||
name: ''
|
||||
},
|
||||
userList: [],
|
||||
bookingEdit: {
|
||||
room: {
|
||||
id: '0',
|
||||
name: ''
|
||||
},
|
||||
user: {
|
||||
id: 0,
|
||||
name: '',
|
||||
email: ''
|
||||
}
|
||||
},
|
||||
createBookingForm: {
|
||||
user: this.$store.getters.userid,
|
||||
},
|
||||
cancelBookingForm: this.$form.createForm(this),
|
||||
params: {
|
||||
search: ''
|
||||
},
|
||||
statusList: []
|
||||
}
|
||||
},
|
||||
beforeRouteEnter (to, from, next) {
|
||||
if (from.path !== '/') {
|
||||
next()
|
||||
user: {
|
||||
id: 0,
|
||||
name: '',
|
||||
email: ''
|
||||
}
|
||||
},
|
||||
createBookingForm: {
|
||||
user: this.$store.getters.userid
|
||||
},
|
||||
cancelBookingForm: this.$form.createForm(this),
|
||||
params: {
|
||||
search: ''
|
||||
},
|
||||
statusList: []
|
||||
}
|
||||
},
|
||||
beforeRouteEnter (to, from, next) {
|
||||
if (from.path !== '/') {
|
||||
next()
|
||||
} else {
|
||||
next({ name: 'dashboard' })
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
if (this.isEdit) {
|
||||
bookingAPI.getBooking(this.id)
|
||||
.then(data => {
|
||||
this.bookingEdit = data
|
||||
})
|
||||
bookingAPI.getStatusList()
|
||||
.then(data => {
|
||||
this.statusList = data
|
||||
})
|
||||
} else {
|
||||
next({ name: 'dashboard' })
|
||||
accountAPI.getUserList(this.getParams())
|
||||
.then(data => {
|
||||
this.userList = data.results
|
||||
if (this.isTeacher) {
|
||||
this.userList.push({
|
||||
id: this.$store.getters.userid,
|
||||
username: this.$store.getters.username,
|
||||
email: ''
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
handleCreateSubmit () {
|
||||
const form = {
|
||||
user: this.createBookingForm.user,
|
||||
room: this.bookingCreate.room.id,
|
||||
seats: this.bookingCreate.seats.map((item) => {
|
||||
return item.id
|
||||
}),
|
||||
date: this.bookingCreate.date,
|
||||
start_time: this.bookingCreate.start_time,
|
||||
end_time: this.bookingCreate.end_time
|
||||
}
|
||||
bookingAPI.createBooking(form)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '提交申请成功', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'dashboard' })
|
||||
})
|
||||
},
|
||||
handleCancelSubmit () {
|
||||
this.cancelBookingForm.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
bookingAPI.cancelBooking(this.bookingEdit.id, data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '取消预约成功', key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSearch (value) {
|
||||
this.params.search = value
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
if (this.isEdit) {
|
||||
bookingAPI.getBooking(this.id)
|
||||
.then(data => {
|
||||
this.bookingEdit = data
|
||||
})
|
||||
bookingAPI.getStatusList()
|
||||
.then(data => {
|
||||
this.statusList = data
|
||||
})
|
||||
} else {
|
||||
accountAPI.getUserList(this.getParams)
|
||||
.then(data => {
|
||||
this.userList = data.results
|
||||
if (this.isTeacher) {
|
||||
this.userList.push({
|
||||
id: this.$store.getters.userid,
|
||||
username: this.$store.getters.username,
|
||||
email: ''
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
handleCreateSubmit () {
|
||||
let form = {
|
||||
user: this.createBookingForm.user,
|
||||
room: this.bookingCreate.room.id,
|
||||
seats: this.bookingCreate.seats.map((item) => {
|
||||
return item.id
|
||||
}),
|
||||
date: this.bookingCreate.date,
|
||||
start_time: this.bookingCreate.start_time,
|
||||
end_time: this.bookingCreate.end_time
|
||||
}
|
||||
bookingAPI.createBooking(form)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '提交申请成功', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'dashboard' })
|
||||
})
|
||||
},
|
||||
handleCancelSubmit () {
|
||||
this.cancelBookingForm.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
bookingAPI.cancelBooking(this.bookingEdit.id, data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '取消预约成功', key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSearch (value) {
|
||||
this.params.search = value
|
||||
this.getData()
|
||||
getParams () {
|
||||
if (this.isTeacher) {
|
||||
this.params.teacher = this.$store.getters.userid
|
||||
}
|
||||
return this.params
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
},
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
},
|
||||
statusName () {
|
||||
let ret = ''
|
||||
let result = this.statusList.find(item => item.id === this.bookingEdit.status)
|
||||
if (result) {
|
||||
ret = result.name
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getParams () {
|
||||
if (this.isTeacher) {
|
||||
this.params.teacher = this.$store.getters.userid
|
||||
}
|
||||
return this.params
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
},
|
||||
statusName () {
|
||||
let ret = ''
|
||||
const result = this.statusList.find(item => item.id === this.bookingEdit.status)
|
||||
if (result) {
|
||||
ret = result.name
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<a-select
|
||||
v-model="form.room"
|
||||
@change="handleRoomChange">
|
||||
<a-select-option v-for="item in roomList" :key="item.id">{{item.name}}</a-select-option>
|
||||
<a-select-option v-for="item in roomList" :key="item.id">{{ item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -66,11 +66,13 @@
|
|||
v-bind="layout">
|
||||
<a-spin :spinning="this.state.loading">
|
||||
<div class="seat" v-if="bookingStatusList">
|
||||
<div class="seat-card"
|
||||
v-for="item in bookingStatusList.seat_list"
|
||||
@click="handleClick(item)"
|
||||
:class="[{unselectable: item.is_booked}, {selected: seatSelected.indexOf(item.id) !== -1}]">
|
||||
{{item.name}}
|
||||
<div
|
||||
class="seat-card"
|
||||
v-for="item in bookingStatusList.seat_list"
|
||||
:key="item.id"
|
||||
@click="handleClick(item)"
|
||||
:class="[{unselectable: item.is_booked}, {selected: seatSelected.indexOf(item.id) !== -1}]">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div>
|
||||
<span style="vertical-align: -6px;">提示:
|
||||
|
@ -94,14 +96,14 @@
|
|||
:notFoundContent="null"
|
||||
@search="handleSearch"
|
||||
v-model="form.user">
|
||||
<a-select-option v-for="item in userList" :value="item.id">{{item.username}} {{item.email}}
|
||||
<a-select-option v-for="item in userList" :value="item.id" :key="item.id">{{ item.username }} {{ item.email }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-select
|
||||
v-else
|
||||
:disabled="true"
|
||||
v-model="form.user">
|
||||
<a-select-option :value="form.user">{{$store.getters.username}}</a-select-option>
|
||||
<a-select-option :value="form.user">{{ $store.getters.username }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
|
@ -119,192 +121,191 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import DatePickerBar from '../dashboard/components/DatePickerBar'
|
||||
import moment from 'moment'
|
||||
import settingAPI from '../../api/setting'
|
||||
import roomAPI from '../../api/room'
|
||||
import dashboardAPI from '../../api/dashboard'
|
||||
import accountAPI from '../../api/account'
|
||||
import bookingAPI from '../../api/booking'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import DatePickerBar from '../dashboard/components/DatePickerBar'
|
||||
import moment from 'moment'
|
||||
import settingAPI from '../../api/setting'
|
||||
import roomAPI from '../../api/room'
|
||||
import dashboardAPI from '../../api/dashboard'
|
||||
import accountAPI from '../../api/account'
|
||||
import bookingAPI from '../../api/booking'
|
||||
|
||||
export default {
|
||||
name: 'BookingNew',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
state: {
|
||||
loading: false,
|
||||
},
|
||||
form: {
|
||||
date: new moment(),
|
||||
startTime: new moment(),
|
||||
endTime: new moment(),
|
||||
room: null,
|
||||
user: this.isTeacher ? this.$store.getters.userid : null
|
||||
},
|
||||
setting: {},
|
||||
roomList: [],
|
||||
bookingStatusList: [],
|
||||
seatSelected: [],
|
||||
userList: []
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
settingAPI.getSettingDetail()
|
||||
export default {
|
||||
name: 'BookingNew',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
state: {
|
||||
loading: false
|
||||
},
|
||||
form: {
|
||||
date: new moment(),
|
||||
startTime: new moment(),
|
||||
endTime: new moment(),
|
||||
room: null,
|
||||
user: this.isTeacher ? this.$store.getters.userid : null
|
||||
},
|
||||
setting: {},
|
||||
roomList: [],
|
||||
bookingStatusList: [],
|
||||
seatSelected: [],
|
||||
userList: []
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
settingAPI.getSettingDetail()
|
||||
.then(data => {
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.form.startTime = data.start_time
|
||||
this.form.endTime = data.end_time
|
||||
this.setting = data
|
||||
roomAPI.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
this.form.room = data[0].id
|
||||
this.getData()
|
||||
})
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
dashboardAPI.getRoomBookingStatusDetail(this.form.room, {
|
||||
date: this.form.date.format('YYYY-MM-DD'),
|
||||
start_time: this.form.startTime.format('HH:mm:ss'),
|
||||
end_time: this.form.endTime.format('HH:mm:ss')
|
||||
})
|
||||
.then(data => {
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.form.startTime = data.start_time
|
||||
this.form.endTime = data.end_time
|
||||
this.setting = data
|
||||
roomAPI.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
this.form.room = data[0].id
|
||||
this.getData()
|
||||
})
|
||||
this.seatSelected = []
|
||||
this.bookingStatusList = data
|
||||
if (!this.isTeacher) {
|
||||
this.handleSearch('')
|
||||
}
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
dashboardAPI.getRoomBookingStatusDetail(this.form.room, {
|
||||
handleSubmit () {
|
||||
if (this.form.user) {
|
||||
const form = {
|
||||
user: this.form.user,
|
||||
room: this.form.room,
|
||||
seats: this.seatSelected,
|
||||
date: this.form.date.format('YYYY-MM-DD'),
|
||||
start_time: this.form.startTime.format('HH:mm:ss'),
|
||||
end_time: this.form.endTime.format('HH:mm:ss')
|
||||
})
|
||||
}
|
||||
bookingAPI.createBooking(form)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '提交申请成功', key: 'SUCCESS' })
|
||||
this.seatSelected = []
|
||||
this.bookingStatusList = data
|
||||
if (!this.isTeacher) {
|
||||
this.handleSearch('')
|
||||
}
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
handleSubmit () {
|
||||
if (this.form.user) {
|
||||
let form = {
|
||||
user: this.form.user,
|
||||
room: this.form.room,
|
||||
seats: this.seatSelected,
|
||||
date: this.form.date.format('YYYY-MM-DD'),
|
||||
start_time: this.form.startTime.format('HH:mm:ss'),
|
||||
end_time: this.form.endTime.format('HH:mm:ss')
|
||||
}
|
||||
bookingAPI.createBooking(form)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '提交申请成功', key: 'SUCCESS' })
|
||||
this.seatSelected = []
|
||||
this.getData()
|
||||
})
|
||||
} else {
|
||||
this.$notification.error({ message: '错误', description: '请选择预约人', key: 'ERROR' })
|
||||
}
|
||||
},
|
||||
handleRoomChange (room) {
|
||||
this.getData()
|
||||
},
|
||||
handleDateChange (date) {
|
||||
this.getData()
|
||||
},
|
||||
handleStartTimeChange (time, timeString) {
|
||||
this.getData()
|
||||
},
|
||||
handleEndTimeChange (time, timeString) {
|
||||
this.getData()
|
||||
},
|
||||
getDisabledDate (currentDate) {
|
||||
return currentDate > this.maxDate || currentDate <= new moment().subtract(1, 'days')
|
||||
},
|
||||
getStartTimeDisabledHours () {
|
||||
let ret = []
|
||||
let start_hour = this.setting.start_time.hour()
|
||||
let end_hour = this.form.endTime.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (this.form.endTime.minute() === 0) {
|
||||
ret.push(end_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getStartTimeDisabledMinutes (selectedHour) {
|
||||
let ret = []
|
||||
if (selectedHour === this.form.endTime.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledHours () {
|
||||
let ret = []
|
||||
let start_hour = this.form.startTime.hour()
|
||||
let end_hour = this.setting.end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (this.form.startTime.minute() === 30 || this.setting.booking_interval === 60) {
|
||||
ret.push(start_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledMinutes (selectedHour) {
|
||||
let ret = []
|
||||
if (selectedHour === this.form.startTime.hour()) {
|
||||
ret.push(0)
|
||||
}
|
||||
if (selectedHour === this.setting.end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
handleClick (item) {
|
||||
if (!item.is_booked) {
|
||||
let index = this.seatSelected.indexOf(item.id)
|
||||
if (index === -1) {
|
||||
this.seatSelected.push(item.id)
|
||||
} else {
|
||||
this.seatSelected.splice(index, 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
handleSearch (value) {
|
||||
accountAPI.getUserList({
|
||||
search: value,
|
||||
role: 'TEACHER'
|
||||
})
|
||||
.then(data => {
|
||||
this.userList = data.results
|
||||
this.getData()
|
||||
})
|
||||
} else {
|
||||
this.$notification.error({ message: '错误', description: '请选择预约人', key: 'ERROR' })
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
maxDate () {
|
||||
return new moment().add(this.setting.pre_booking_interval_day, 'days')
|
||||
},
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
handleRoomChange (room) {
|
||||
this.getData()
|
||||
},
|
||||
handleDateChange (date) {
|
||||
this.getData()
|
||||
},
|
||||
handleStartTimeChange (time, timeString) {
|
||||
this.getData()
|
||||
},
|
||||
handleEndTimeChange (time, timeString) {
|
||||
this.getData()
|
||||
},
|
||||
getDisabledDate (currentDate) {
|
||||
return currentDate > this.maxDate || currentDate <= new moment().subtract(1, 'days')
|
||||
},
|
||||
getStartTimeDisabledHours () {
|
||||
const ret = []
|
||||
const start_hour = this.setting.start_time.hour()
|
||||
const end_hour = this.form.endTime.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (this.form.endTime.minute() === 0) {
|
||||
ret.push(end_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getStartTimeDisabledMinutes (selectedHour) {
|
||||
const ret = []
|
||||
if (selectedHour === this.form.endTime.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledHours () {
|
||||
const ret = []
|
||||
const start_hour = this.form.startTime.hour()
|
||||
const end_hour = this.setting.end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour || i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (this.form.startTime.minute() === 30 || this.setting.booking_interval === 60) {
|
||||
ret.push(start_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledMinutes (selectedHour) {
|
||||
const ret = []
|
||||
if (selectedHour === this.form.startTime.hour()) {
|
||||
ret.push(0)
|
||||
}
|
||||
if (selectedHour === this.setting.end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
handleClick (item) {
|
||||
if (!item.is_booked) {
|
||||
const index = this.seatSelected.indexOf(item.id)
|
||||
if (index === -1) {
|
||||
this.seatSelected.push(item.id)
|
||||
} else {
|
||||
this.seatSelected.splice(index, 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
handleSearch (value) {
|
||||
accountAPI.getUserList({
|
||||
search: value,
|
||||
role: 'TEACHER'
|
||||
})
|
||||
.then(data => {
|
||||
this.userList = data.results
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
maxDate () {
|
||||
return new moment().add(this.setting.pre_booking_interval_day, 'days')
|
||||
},
|
||||
isTeacher () {
|
||||
return this.$store.getters.role === 'TEACHER'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "../../../public/color";
|
||||
|
||||
|
||||
.seat {
|
||||
.seat-card {
|
||||
text-align: center;
|
||||
|
@ -354,4 +355,4 @@
|
|||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
:key="item.id"
|
||||
@click="handleJump(item)">
|
||||
<a-card class="room-status-card">
|
||||
<span class="name">{{item.name}}</span>
|
||||
<span class="name">{{ item.name }}</span>
|
||||
<div v-if="item.count">
|
||||
<span class="big">{{item.booking_count}}</span>
|
||||
<span class="big">{{ item.booking_count }}</span>
|
||||
<span> 条,</span>
|
||||
<span> {{((1 - item.booked_count/item.count)*100).toFixed(2)}} % 剩余</span>
|
||||
<span> {{ ((1 - item.booked_count/item.count)*100).toFixed(2) }} % 剩余</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span class="big">无座位</span>
|
||||
|
@ -27,10 +27,10 @@
|
|||
</a-row>
|
||||
</a-spin>
|
||||
<a-row>
|
||||
<span>共 {{bookingCountTotal}} 条, {{((1 - bookedCountTotal/countTotal)*100).toFixed(2)}} % 剩余</span>
|
||||
<span>共 {{ bookingCountTotal }} 条, {{ ((1 - bookedCountTotal/countTotal)*100).toFixed(2) }} % 剩余</span>
|
||||
<a-tooltip placement="top" title="每分钟自动">
|
||||
<div style="float: right;">
|
||||
<span style="vertical-align: -2px;">更新时间: {{updateTime}} 自动更新 </span>
|
||||
<span style="vertical-align: -2px;">更新时间: {{ updateTime }} 自动更新 </span>
|
||||
<a-switch checkedChildren="开" unCheckedChildren="关" defaultChecked @change="handleAutoChange"></a-switch>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
|
@ -40,76 +40,76 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import moment from 'moment'
|
||||
import api from '../../api/dashboard'
|
||||
import DatePickerBar from './components/DatePickerBar'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import moment from 'moment'
|
||||
import api from '../../api/dashboard'
|
||||
import DatePickerBar from './components/DatePickerBar'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
params: {
|
||||
date: new moment().format('YYYY-MM-DD')
|
||||
},
|
||||
status: {
|
||||
loading: false
|
||||
},
|
||||
updateTime: '',
|
||||
roomBookingStatusList: [],
|
||||
countTotal: 0,
|
||||
bookedCountTotal: 0,
|
||||
bookingCountTotal: 0,
|
||||
intervalID: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
this.handleAutoChange(true)
|
||||
},
|
||||
destroyed () {
|
||||
this.handleAutoChange(false)
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.status.loading = true
|
||||
api.getRoomBookingStatus(this.params)
|
||||
.then(data => {
|
||||
this.roomBookingStatusList = data.results
|
||||
this.countTotal = data.count_total
|
||||
this.bookedCountTotal = data.booked_count_total
|
||||
this.bookingCountTotal = data.booking_count_total
|
||||
this.updateTime = new moment().format('YYYY-MM-DD hh:mm:ss')
|
||||
this.status.loading = false
|
||||
})
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
params: {
|
||||
date: new moment().format('YYYY-MM-DD')
|
||||
},
|
||||
status: {
|
||||
loading: false
|
||||
},
|
||||
updateTime: '',
|
||||
roomBookingStatusList: [],
|
||||
countTotal: 0,
|
||||
bookedCountTotal: 0,
|
||||
bookingCountTotal: 0,
|
||||
intervalID: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
handleDateChange (date) {
|
||||
this.params.date = date.format('YYYY-MM-DD')
|
||||
this.getData()
|
||||
this.handleAutoChange(true)
|
||||
},
|
||||
destroyed () {
|
||||
this.handleAutoChange(false)
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.status.loading = true
|
||||
api.getRoomBookingStatus(this.params)
|
||||
.then(data => {
|
||||
this.roomBookingStatusList = data.results
|
||||
this.countTotal = data.count_total
|
||||
this.bookedCountTotal = data.booked_count_total
|
||||
this.bookingCountTotal = data.booking_count_total
|
||||
this.updateTime = new moment().format('YYYY-MM-DD hh:mm:ss')
|
||||
this.status.loading = false
|
||||
})
|
||||
},
|
||||
handleDateChange (date) {
|
||||
this.params.date = date.format('YYYY-MM-DD')
|
||||
this.getData()
|
||||
},
|
||||
handleAutoChange (checked) {
|
||||
if (checked) {
|
||||
this.intervalID = setInterval(this.getData, 1000 * 60)
|
||||
} else {
|
||||
clearInterval(this.intervalID)
|
||||
}
|
||||
},
|
||||
getDefaultDate () {
|
||||
return new moment()
|
||||
},
|
||||
handleJump (item) {
|
||||
if (item.count) {
|
||||
this.$router.push({ name: 'dashboardDetail', params: { id: item.id, date: this.params.date } })
|
||||
} else {
|
||||
this.$router.push({ name: 'seat', params: { id: item.id } })
|
||||
}
|
||||
handleAutoChange (checked) {
|
||||
if (checked) {
|
||||
this.intervalID = setInterval(this.getData, 1000 * 60)
|
||||
} else {
|
||||
clearInterval(this.intervalID)
|
||||
}
|
||||
},
|
||||
getDefaultDate () {
|
||||
return new moment()
|
||||
},
|
||||
handleJump (item) {
|
||||
if (item.count) {
|
||||
this.$router.push({ name: 'dashboardDetail', params: { id: item.id, date: this.params.date } })
|
||||
} else {
|
||||
this.$router.push({ name: 'seat', params: { id: item.id } })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
|
|
@ -11,33 +11,33 @@
|
|||
<th
|
||||
v-for="(item, index) in room.seat_list[0].booking_status_list"
|
||||
:key="index">
|
||||
{{item.start_time.slice(0, 5)}} {{item.end_time.slice(0, 5)}}
|
||||
{{ item.start_time.slice(0, 5) }} {{ item.end_time.slice(0, 5) }}
|
||||
</th>
|
||||
</tr>
|
||||
<tr
|
||||
v-for="(seat, seatIndex) in room.seat_list"
|
||||
:key="seat.id">
|
||||
<td>
|
||||
{{seat.name}}
|
||||
{{ seat.name }}
|
||||
</td>
|
||||
<td
|
||||
v-for="(item, itemIndex) in seat.booking_status_list"
|
||||
:key="itemIndex"
|
||||
:class="[
|
||||
{
|
||||
'booked-cell': item.booking,
|
||||
'selected-cell': selected[seatIndex.toString() + ' ' + itemIndex.toString()],
|
||||
},
|
||||
'cell'
|
||||
]">
|
||||
{
|
||||
'booked-cell': item.booking,
|
||||
'selected-cell': selected[seatIndex.toString() + ' ' + itemIndex.toString()],
|
||||
},
|
||||
'cell'
|
||||
]">
|
||||
<a-popover placement="top" v-if="item.booking">
|
||||
<div style="width: 100%; height: 20px;"></div>
|
||||
<template slot="title">预约 {{item.booking.id}}</template>
|
||||
<template slot="title">预约 {{ item.booking.id }}</template>
|
||||
<template slot="content">
|
||||
<div>用户: {{item.booking.user.username}}</div>
|
||||
<div>预约时间: {{item.booking.start_time}}-{{item.booking.end_time}}</div>
|
||||
<div>到达时间: {{item.booking.arrive_time}}</div>
|
||||
<div>离开时间: {{item.booking.leave_time}}</div>
|
||||
<div>用户: {{ item.booking.user.username }}</div>
|
||||
<div>预约时间: {{ item.booking.start_time }}-{{ item.booking.end_time }}</div>
|
||||
<div>到达时间: {{ item.booking.arrive_time }}</div>
|
||||
<div>离开时间: {{ item.booking.leave_time }}</div>
|
||||
<router-link :to="{name: 'bookingEdit', params:{id: item.booking.id}}">查看</router-link>
|
||||
</template>
|
||||
</a-popover>
|
||||
|
@ -68,10 +68,10 @@
|
|||
</a-button>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<span>总计: {{room.booked_count_total}} / {{room.count_total}}</span>
|
||||
<span>总计: {{ room.booked_count_total }} / {{ room.count_total }}</span>
|
||||
<a-tooltip placement="top" title="每分钟自动">
|
||||
<div style="float: right;">
|
||||
<span style="vertical-align: -2px;">更新时间: {{updateTime}} 自动更新 </span>
|
||||
<span style="vertical-align: -2px;">更新时间: {{ updateTime }} 自动更新 </span>
|
||||
<a-switch
|
||||
checkedChildren="开"
|
||||
unCheckedChildren="关"
|
||||
|
@ -86,142 +86,142 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/dashboard'
|
||||
import DatePickerBar from './components/DatePickerBar'
|
||||
import moment from 'moment'
|
||||
import _ from 'lodash'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/dashboard'
|
||||
import DatePickerBar from './components/DatePickerBar'
|
||||
import moment from 'moment'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'DashboardDetail',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
export default {
|
||||
name: 'DashboardDetail',
|
||||
components: {
|
||||
PageLayout,
|
||||
DatePickerBar
|
||||
},
|
||||
props: {
|
||||
id: String,
|
||||
date: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
params: {
|
||||
date: this.date ? new moment(this.date).format('YYYY-MM-DD') : new moment().format('YYYY-MM-DD')
|
||||
},
|
||||
status: {
|
||||
loading: false
|
||||
},
|
||||
room: {},
|
||||
updateTime: '',
|
||||
intervalID: null,
|
||||
selected: {},
|
||||
firstSelected: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.status.loading = true
|
||||
api.getRoomBookingStatusDetail(this.id, this.params)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
this.updateTime = new moment().format('YYYY-MM-DD hh:mm:ss')
|
||||
this.selected = {}
|
||||
this.firstSelected = null
|
||||
this.status.loading = false
|
||||
})
|
||||
},
|
||||
props: {
|
||||
id: String,
|
||||
date: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
params: {
|
||||
date: this.date ? new moment(this.date).format('YYYY-MM-DD') : new moment().format('YYYY-MM-DD')
|
||||
},
|
||||
status: {
|
||||
loading: false
|
||||
},
|
||||
room: {},
|
||||
updateTime: '',
|
||||
intervalID: null,
|
||||
selected: {},
|
||||
firstSelected: null
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
handleDateChange (date) {
|
||||
this.params.date = date.format('YYYY-MM-DD')
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.status.loading = true
|
||||
api.getRoomBookingStatusDetail(this.id, this.params)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
this.updateTime = new moment().format('YYYY-MM-DD hh:mm:ss')
|
||||
this.selected = {}
|
||||
this.firstSelected = null
|
||||
this.status.loading = false
|
||||
})
|
||||
},
|
||||
handleDateChange (date) {
|
||||
this.params.date = date.format('YYYY-MM-DD')
|
||||
this.getData()
|
||||
},
|
||||
getDefaultDate () {
|
||||
return new moment(this.date)
|
||||
},
|
||||
handleAutoChange (checked) {
|
||||
if (checked) {
|
||||
this.intervalID = setInterval(this.getData, 1000 * 60)
|
||||
getDefaultDate () {
|
||||
return new moment(this.date)
|
||||
},
|
||||
handleAutoChange (checked) {
|
||||
if (checked) {
|
||||
this.intervalID = setInterval(this.getData, 1000 * 60)
|
||||
} else {
|
||||
clearInterval(this.intervalID)
|
||||
}
|
||||
},
|
||||
handleSelect (x, y) {
|
||||
if (this.isSelectable) {
|
||||
let newData = {}
|
||||
if (!this.firstSelected) {
|
||||
this.firstSelected = { x, y }
|
||||
newData[x.toString() + ' ' + y.toString()] = true
|
||||
} else {
|
||||
clearInterval(this.intervalID)
|
||||
}
|
||||
},
|
||||
handleSelect (x, y) {
|
||||
if (this.isSelectable) {
|
||||
let newData = {}
|
||||
if (!this.firstSelected) {
|
||||
this.firstSelected = { x, y }
|
||||
newData[x.toString() + ' ' + y.toString()] = true
|
||||
} else {
|
||||
if (this.firstSelected.x === x) {
|
||||
newData = _.cloneDeep(this.selected)
|
||||
if (this.firstSelected.y === y) {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
} else if (this.firstSelected.y < y) {
|
||||
for (let i = this.firstSelected.y; i <= y; i++) {
|
||||
if (!this.room.seat_list[x].booking_status_list[i].booking) {
|
||||
newData[x.toString() + ' ' + i.toString()] = true
|
||||
} else {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = y; i <= this.firstSelected.y; i++) {
|
||||
if (!this.room.seat_list[x].booking_status_list[i].booking) {
|
||||
newData[x.toString() + ' ' + i.toString()] = true
|
||||
} else {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
break
|
||||
}
|
||||
if (this.firstSelected.x === x) {
|
||||
newData = _.cloneDeep(this.selected)
|
||||
if (this.firstSelected.y === y) {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
} else if (this.firstSelected.y < y) {
|
||||
for (let i = this.firstSelected.y; i <= y; i++) {
|
||||
if (!this.room.seat_list[x].booking_status_list[i].booking) {
|
||||
newData[x.toString() + ' ' + i.toString()] = true
|
||||
} else {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.selected = {}
|
||||
for (let i = y; i <= this.firstSelected.y; i++) {
|
||||
if (!this.room.seat_list[x].booking_status_list[i].booking) {
|
||||
newData[x.toString() + ' ' + i.toString()] = true
|
||||
} else {
|
||||
this.selected = {}
|
||||
newData = {}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this.firstSelected = null
|
||||
} else {
|
||||
this.selected = {}
|
||||
}
|
||||
this.selected = newData
|
||||
this.firstSelected = null
|
||||
}
|
||||
},
|
||||
handleCreate () {
|
||||
let key_list = Object.keys(this.selected)
|
||||
let x = key_list[0].split(' ')[0]
|
||||
let key_y_list = key_list.map((item) => {
|
||||
return item.split(' ')[1]
|
||||
})
|
||||
let y1 = Math.min.apply(null, key_y_list)
|
||||
let y2 = Math.max.apply(null, key_y_list)
|
||||
let seats = []
|
||||
let seat = this.room.seat_list[x]
|
||||
let start_time = this.room.seat_list[x].booking_status_list[y1].start_time
|
||||
let end_time = this.room.seat_list[x].booking_status_list[y2].end_time
|
||||
seats.push({
|
||||
id: seat.id,
|
||||
name: seat.name
|
||||
})
|
||||
let bookingCreate = {
|
||||
date: this.params.date,
|
||||
room: {
|
||||
id: this.room.id,
|
||||
name: this.room.name
|
||||
},
|
||||
seats,
|
||||
start_time,
|
||||
end_time
|
||||
}
|
||||
this.$router.push({ name: 'bookingCreate', params: { bookingCreate } })
|
||||
this.selected = newData
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isSelectable () {
|
||||
return new moment().format('YYYY-MM-DD') <= this.params.date
|
||||
handleCreate () {
|
||||
const key_list = Object.keys(this.selected)
|
||||
const x = key_list[0].split(' ')[0]
|
||||
const key_y_list = key_list.map((item) => {
|
||||
return item.split(' ')[1]
|
||||
})
|
||||
const y1 = Math.min.apply(null, key_y_list)
|
||||
const y2 = Math.max.apply(null, key_y_list)
|
||||
const seats = []
|
||||
const seat = this.room.seat_list[x]
|
||||
const start_time = this.room.seat_list[x].booking_status_list[y1].start_time
|
||||
const end_time = this.room.seat_list[x].booking_status_list[y2].end_time
|
||||
seats.push({
|
||||
id: seat.id,
|
||||
name: seat.name
|
||||
})
|
||||
const bookingCreate = {
|
||||
date: this.params.date,
|
||||
room: {
|
||||
id: this.room.id,
|
||||
name: this.room.name
|
||||
},
|
||||
seats,
|
||||
start_time,
|
||||
end_time
|
||||
}
|
||||
this.$router.push({ name: 'bookingCreate', params: { bookingCreate } })
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isSelectable () {
|
||||
return new moment().format('YYYY-MM-DD') <= this.params.date
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@ -233,7 +233,6 @@
|
|||
|
||||
.booking-status-timetable {
|
||||
|
||||
|
||||
th, td {
|
||||
border: solid 1px rgba(128, 128, 128, 0.3);
|
||||
padding: 5px 2px;
|
||||
|
@ -282,4 +281,4 @@
|
|||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
class="date"
|
||||
v-if="!status.showDatePicker"
|
||||
@click="status.showDatePicker = true">
|
||||
{{dateString}}
|
||||
</span>
|
||||
{{ dateString }}
|
||||
</span>
|
||||
<a-date-picker
|
||||
v-if="status.showDatePicker"
|
||||
class="date-picker"
|
||||
|
@ -28,63 +28,63 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import settingAPI from '../../../api/setting'
|
||||
import moment from 'moment'
|
||||
import settingAPI from '../../../api/setting'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'DatePickerBar',
|
||||
props: {
|
||||
defaultDate: Object
|
||||
export default {
|
||||
name: 'DatePickerBar',
|
||||
props: {
|
||||
defaultDate: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
status: {
|
||||
showDatePicker: false
|
||||
},
|
||||
date: this.defaultDate,
|
||||
dateString: '',
|
||||
setting: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
settingAPI.getSettingDetail()
|
||||
.then(data => {
|
||||
this.setting = data
|
||||
})
|
||||
this.getDateString()
|
||||
},
|
||||
methods: {
|
||||
getDateString () {
|
||||
this.dateString = this.date.format('YYYY 年 MM 月 DD 日')
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
status: {
|
||||
showDatePicker: false
|
||||
},
|
||||
date: this.defaultDate,
|
||||
dateString: '',
|
||||
setting: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
settingAPI.getSettingDetail()
|
||||
.then(data => {
|
||||
this.setting = data
|
||||
})
|
||||
handleDateChange (date) {
|
||||
this.date = date
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
methods: {
|
||||
getDateString () {
|
||||
this.dateString = this.date.format('YYYY 年 MM 月 DD 日')
|
||||
},
|
||||
handleDateChange (date) {
|
||||
this.date = date
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
handleDatePickerClose (status) {
|
||||
if (!status) this.status.showDatePicker = false
|
||||
},
|
||||
handlePrevious () {
|
||||
this.date.subtract(1, 'days')
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
handleNext () {
|
||||
this.date.add(1, 'days')
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
disabledDate (currentDate) {
|
||||
return currentDate > this.maxDate
|
||||
}
|
||||
handleDatePickerClose (status) {
|
||||
if (!status) this.status.showDatePicker = false
|
||||
},
|
||||
computed: {
|
||||
maxDate () {
|
||||
return new moment().add(this.setting.pre_booking_interval_day, 'days')
|
||||
}
|
||||
handlePrevious () {
|
||||
this.date.subtract(1, 'days')
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
handleNext () {
|
||||
this.date.add(1, 'days')
|
||||
this.getDateString()
|
||||
this.$emit('change', this.date)
|
||||
},
|
||||
disabledDate (currentDate) {
|
||||
return currentDate > this.maxDate
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
maxDate () {
|
||||
return new moment().add(this.setting.pre_booking_interval_day, 'days')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@ -108,4 +108,4 @@
|
|||
float: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
|||
return {
|
||||
config: types
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
|
||||
export default {
|
||||
name: 'Help',
|
||||
components: {
|
||||
PageLayout
|
||||
}
|
||||
export default {
|
||||
name: 'Help',
|
||||
components: {
|
||||
PageLayout
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
|
|
@ -41,92 +41,92 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '30%'
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: '10%'
|
||||
},
|
||||
{
|
||||
title: '座位数量',
|
||||
dataIndex: 'seat_count',
|
||||
width: '10%'
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' },
|
||||
width: '30%'
|
||||
}
|
||||
]
|
||||
import api from '../../api/room'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import { fetchAPIBase } from '../../utils/fetch'
|
||||
import { downloadFile } from '../../utils/util'
|
||||
|
||||
import api from '../../api/room'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import { fetchAPIBase } from '../../utils/fetch'
|
||||
import { downloadFile } from '../../utils/util'
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '30%'
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: '10%'
|
||||
},
|
||||
{
|
||||
title: '座位数量',
|
||||
dataIndex: 'seat_count',
|
||||
width: '10%'
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' },
|
||||
width: '30%'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Room',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
state: {
|
||||
loading: false,
|
||||
},
|
||||
roomList: [],
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
api.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
export default {
|
||||
name: 'Room',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
state: {
|
||||
loading: false
|
||||
},
|
||||
handleDownload (record) {
|
||||
const qrcode = {
|
||||
type: 'room',
|
||||
name: record.name,
|
||||
id: record.id
|
||||
}
|
||||
fetchAPIBase('qrcode/', 'get', null, qrcode)
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `房间-${record.name}.png`)
|
||||
})
|
||||
.catch(error => {
|
||||
this.$notification({ message: '下载失败', description: error, key: 'ERROR' })
|
||||
})
|
||||
roomList: []
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
api.getRoomList()
|
||||
.then(data => {
|
||||
this.roomList = data
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
handleDownload (record) {
|
||||
const qrcode = {
|
||||
type: 'room',
|
||||
name: record.name,
|
||||
id: record.id
|
||||
}
|
||||
fetchAPIBase('qrcode/', 'get', null, qrcode)
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `房间-${record.name}.png`)
|
||||
})
|
||||
.catch(error => {
|
||||
this.$notification({ message: '下载失败', description: error, key: 'ERROR' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
v-if="isEdit"
|
||||
label="ID"
|
||||
v-bind="layout">
|
||||
{{room.id}}
|
||||
{{ room.id }}
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="名称"
|
||||
|
@ -28,7 +28,7 @@
|
|||
validateTrigger: 'blur',
|
||||
initialValue: isEdit ? room.name : null
|
||||
}
|
||||
]">
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -46,7 +46,7 @@
|
|||
],
|
||||
validateTrigger: 'blur'
|
||||
}
|
||||
]">
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -58,7 +58,7 @@
|
|||
v-decorator="[
|
||||
'description',
|
||||
{initialValue: isEdit ? room.description: ''}
|
||||
]">
|
||||
]">
|
||||
</a-textarea>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
|
@ -85,76 +85,76 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../../api/room'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/room'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
|
||||
export default {
|
||||
name: 'RoomDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
form: this.$form.createForm(this),
|
||||
room: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.isEdit) {
|
||||
this.getData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getRoom(this.id)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
})
|
||||
export default {
|
||||
name: 'RoomDetail',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
if (this.isEdit) {
|
||||
api.updateRoom(this.id, data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功修改房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
} else {
|
||||
api.createRoom(data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功新建房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
}
|
||||
}
|
||||
form: this.$form.createForm(this),
|
||||
room: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.isEdit) {
|
||||
this.getData()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getRoom(this.id)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
if (this.isEdit) {
|
||||
api.updateRoom(this.id, data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功修改房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
} else {
|
||||
api.createRoom(data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功新建房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
}
|
||||
)
|
||||
},
|
||||
handleDelete () {
|
||||
api.deleteRoom(this.id)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功删除房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
handleDelete () {
|
||||
api.deleteRoom(this.id)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '成功删除房间', key: 'SUCCESS' })
|
||||
this.$router.push({ name: 'room' })
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEdit () {
|
||||
return this.$route.path.split('/').pop() === 'edit'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:xs="{span: 12}"
|
||||
:sm="{span: 6}"
|
||||
:xl="{span: 4}">
|
||||
<span style="vertical-align: -5px">共 {{count||0}} 个</span>
|
||||
<span style="vertical-align: -5px">共 {{ count||0 }} 个</span>
|
||||
</a-col>
|
||||
<a-col
|
||||
class="item"
|
||||
|
@ -70,130 +70,130 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '40%'
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'created_datetime',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' },
|
||||
width: '20%'
|
||||
}
|
||||
]
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/room'
|
||||
import { fetchAPIBase } from '../../utils/fetch'
|
||||
import { downloadFile } from '../../utils/util'
|
||||
import PageLayout from '../../components/page/PageLayout'
|
||||
import api from '../../api/room'
|
||||
import { fetchAPIBase } from '../../utils/fetch'
|
||||
import { downloadFile } from '../../utils/util'
|
||||
const columns = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'id',
|
||||
width: '40%'
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'created_datetime',
|
||||
width: '20%'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
scopedSlots: { customRender: 'operation' },
|
||||
width: '20%'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Seat',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
params: {
|
||||
room__id: this.id
|
||||
},
|
||||
state: {
|
||||
loading: false,
|
||||
},
|
||||
room: {},
|
||||
seatList: [],
|
||||
count: 0,
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
api.getRoom(this.id)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
api.getSeatList(this.params)
|
||||
.then(data => {
|
||||
this.seatList = data
|
||||
this.count = data.length
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
export default {
|
||||
name: 'Seat',
|
||||
components: {
|
||||
PageLayout
|
||||
},
|
||||
props: {
|
||||
id: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columns,
|
||||
params: {
|
||||
room__id: this.id
|
||||
},
|
||||
handleCreate () {
|
||||
let new_seat = {
|
||||
name: (this.count + 1).toString(),
|
||||
room: this.id
|
||||
}
|
||||
api.createSeat(new_seat)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: `成功新建座位`, key: 'SUCCESS' })
|
||||
state: {
|
||||
loading: false
|
||||
},
|
||||
room: {},
|
||||
seatList: [],
|
||||
count: 0
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.state.loading = true
|
||||
api.getRoom(this.id)
|
||||
.then(data => {
|
||||
this.room = data
|
||||
api.getSeatList(this.params)
|
||||
.then(data => {
|
||||
this.seatList = data
|
||||
this.count = data.length
|
||||
this.state.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loading = false
|
||||
})
|
||||
},
|
||||
handleCreate () {
|
||||
const new_seat = {
|
||||
name: (this.count + 1).toString(),
|
||||
room: this.id
|
||||
}
|
||||
api.createSeat(new_seat)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: `成功新建座位`, key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
},
|
||||
handleDelete () {
|
||||
if (this.count) {
|
||||
const last = this.seatList[0]
|
||||
api.deleteSeat(last.id)
|
||||
.then(() => {
|
||||
this.$notification.success({ message: '成功', description: `成功删除座位`, key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
},
|
||||
handleDelete () {
|
||||
if (this.count) {
|
||||
let last = this.seatList[0]
|
||||
api.deleteSeat(last.id)
|
||||
.then(() => {
|
||||
this.$notification.success({ message: '成功', description: `成功删除座位`, key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
} else {
|
||||
this.$notification.error({ message: '错误', description: '暂无座位', key: 'ERROR' })
|
||||
}
|
||||
},
|
||||
handleDownload (record) {
|
||||
const qrcode = {
|
||||
type: 'seat',
|
||||
name: record.name,
|
||||
id: record.id
|
||||
}
|
||||
fetchAPIBase('qrcode/', 'get', null, qrcode)
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `座位-${record.name}.png`)
|
||||
})
|
||||
},
|
||||
handleDownloadAll () {
|
||||
fetchAPIBase('qrcode/all/', 'get', null, { room: this.room.id })
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `房间-${this.room.name}.zip`)
|
||||
})
|
||||
.catch(error => {
|
||||
this.$notification({ message: '下载失败', description: error, key: 'ERROR' })
|
||||
})
|
||||
} else {
|
||||
this.$notification.error({ message: '错误', description: '暂无座位', key: 'ERROR' })
|
||||
}
|
||||
},
|
||||
handleDownload (record) {
|
||||
const qrcode = {
|
||||
type: 'seat',
|
||||
name: record.name,
|
||||
id: record.id
|
||||
}
|
||||
fetchAPIBase('qrcode/', 'get', null, qrcode)
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `座位-${record.name}.png`)
|
||||
})
|
||||
},
|
||||
handleDownloadAll () {
|
||||
fetchAPIBase('qrcode/all/', 'get', null, { room: this.room.id })
|
||||
.then(res => {
|
||||
return res.blob()
|
||||
})
|
||||
.then(data => {
|
||||
downloadFile(data, `房间-${this.room.name}.zip`)
|
||||
})
|
||||
.catch(error => {
|
||||
this.$notification({ message: '下载失败', description: error, key: 'ERROR' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
@ -201,4 +201,4 @@
|
|||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
type="number"
|
||||
addonAfter="天"
|
||||
v-decorator="[
|
||||
'pre_booking_interval_day',
|
||||
{rules: [
|
||||
{required: true, message: '请输入提前预约间隔'},
|
||||
{pattern: /^[1-9]\d*$/, message: '请输入大于1的正整数'},
|
||||
],
|
||||
validateTrigger: 'blur',
|
||||
initialValue: setting.pre_booking_interval_day}
|
||||
]">
|
||||
'pre_booking_interval_day',
|
||||
{rules: [
|
||||
{required: true, message: '请输入提前预约间隔'},
|
||||
{pattern: /^[1-9]\d*$/, message: '请输入大于1的正整数'},
|
||||
],
|
||||
validateTrigger: 'blur',
|
||||
initialValue: setting.pre_booking_interval_day}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -29,13 +29,13 @@
|
|||
v-bind="layout">
|
||||
<a-radio-group
|
||||
v-decorator="[
|
||||
'booking_interval',
|
||||
{rules: [
|
||||
{required: true, message: '请选择预约间隔'},
|
||||
{validator: validateInterval, message: '请确保预约间隔和开始结束时间匹配'}
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.booking_interval}
|
||||
]">
|
||||
'booking_interval',
|
||||
{rules: [
|
||||
{required: true, message: '请选择预约间隔'},
|
||||
{validator: validateInterval, message: '请确保预约间隔和开始结束时间匹配'}
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.booking_interval}
|
||||
]">
|
||||
<a-radio :value="30">30分钟</a-radio>
|
||||
<a-radio :value="60">60分钟</a-radio>
|
||||
</a-radio-group>
|
||||
|
@ -53,10 +53,10 @@
|
|||
:allowEmpty="false"
|
||||
style="width: 100%;"
|
||||
v-decorator="[
|
||||
'start_time',{
|
||||
rules: [{ type: 'object', required: true, message: '请输入开始时间' }],
|
||||
initialValue: setting.start_time
|
||||
}]"></a-time-picker>
|
||||
'start_time',{
|
||||
rules: [{ type: 'object', required: true, message: '请输入开始时间' }],
|
||||
initialValue: setting.start_time
|
||||
}]"></a-time-picker>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="结束时间"
|
||||
|
@ -71,10 +71,10 @@
|
|||
:allowEmpty="false"
|
||||
style="width: 100%;"
|
||||
v-decorator="[
|
||||
'end_time',{
|
||||
rules: [{ type: 'object', required: true, message: '请选择结束时间' }],
|
||||
initialValue: setting.end_time
|
||||
}]"></a-time-picker>
|
||||
'end_time',{
|
||||
rules: [{ type: 'object', required: true, message: '请选择结束时间' }],
|
||||
initialValue: setting.end_time
|
||||
}]"></a-time-picker>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="惩罚积分数"
|
||||
|
@ -83,13 +83,13 @@
|
|||
type="number"
|
||||
addonAfter="分"
|
||||
v-decorator="[
|
||||
'punish_point',
|
||||
{rules: [
|
||||
{required: true, message: '请输入惩罚积分数'},
|
||||
{pattern: /(^[1-9]\d*$)/, message: '请输入大于1的正整数'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.punish_point}
|
||||
]">
|
||||
'punish_point',
|
||||
{rules: [
|
||||
{required: true, message: '请输入惩罚积分数'},
|
||||
{pattern: /(^[1-9]\d*$)/, message: '请输入大于1的正整数'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.punish_point}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
|
@ -99,13 +99,13 @@
|
|||
type="number"
|
||||
addonAfter="分"
|
||||
v-decorator="[
|
||||
'reward_point',
|
||||
{rules: [
|
||||
{required: true, message: '请输入奖励积分数'},
|
||||
{pattern: /(^[1-9]\d*$)/, message: '请输入大于1的正整数'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.reward_point}
|
||||
]">
|
||||
'reward_point',
|
||||
{rules: [
|
||||
{required: true, message: '请输入奖励积分数'},
|
||||
{pattern: /(^[1-9]\d*$)/, message: '请输入大于1的正整数'},
|
||||
], validateTrigger: 'blur',
|
||||
initialValue: setting.reward_point}
|
||||
]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
|
@ -119,105 +119,106 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../../api/setting'
|
||||
import moment from 'moment'
|
||||
import api from '../../api/setting'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'BookingSetting',
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
setting: {},
|
||||
form: this.$form.createForm(this),
|
||||
export default {
|
||||
name: 'BookingSetting',
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
setting: {},
|
||||
form: this.$form.createForm(this)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getSettingDetail()
|
||||
.then(data => {
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.setting = data
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
data.start_time = data.start_time.format('HH:mm:ss')
|
||||
data.end_time = data.end_time.format('HH:mm:ss')
|
||||
api.updateSettingDetail(data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '保存成功', key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
mounted () {
|
||||
this.getData()
|
||||
getStartTimeDisabledHours () {
|
||||
const ret = []
|
||||
const end_time = this.form.getFieldValue('end_time')
|
||||
const end_hour = end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (end_time.minute() === 0 || this.setting.booking_interval === 60) {
|
||||
ret.push(end_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
api.getSettingDetail()
|
||||
.then(data => {
|
||||
data.start_time = new moment(data.start_time, 'HH:mm:ss')
|
||||
data.end_time = new moment(data.end_time, 'HH:mm:ss')
|
||||
this.setting = data
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
data.start_time = data.start_time.format('HH:mm:ss')
|
||||
data.end_time = data.end_time.format('HH:mm:ss')
|
||||
api.updateSettingDetail(data)
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '保存成功', key: 'SUCCESS' })
|
||||
this.getData()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
getStartTimeDisabledHours () {
|
||||
let ret = []
|
||||
let end_time = this.form.getFieldValue('end_time')
|
||||
let end_hour = end_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i > end_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (end_time.minute() === 0 || this.setting.booking_interval === 60) {
|
||||
ret.push(end_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getStartTimeDisabledMinutes (selectedHour) {
|
||||
let ret = []
|
||||
let end_time = this.form.getFieldValue('end_time')
|
||||
if (selectedHour === end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledHours () {
|
||||
let ret = []
|
||||
let start_time = this.form.getFieldValue('start_time')
|
||||
let start_hour = start_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (start_time.minute() === 30 || this.setting.booking_interval === 60) {
|
||||
ret.push(start_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledMinutes (selectedHour) {
|
||||
let ret = []
|
||||
let start_time = this.form.getFieldValue('start_time')
|
||||
if (selectedHour === start_time.hour()) {
|
||||
ret.push(0)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
validateInterval (rule, value, callback) {
|
||||
let start_time = this.form.getFieldValue('start_time')
|
||||
let end_time = this.form.getFieldValue('end_time')
|
||||
if (end_time.diff(start_time) / 1000 / 60 % value === 0) {
|
||||
callback()
|
||||
} else {
|
||||
callback('can by divided by interval')
|
||||
getStartTimeDisabledMinutes (selectedHour) {
|
||||
const ret = []
|
||||
const end_time = this.form.getFieldValue('end_time')
|
||||
if (selectedHour === end_time.hour()) {
|
||||
ret.push(30)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledHours () {
|
||||
const ret = []
|
||||
const start_time = this.form.getFieldValue('start_time')
|
||||
const start_hour = start_time.hour()
|
||||
for (let i = 0; i < 24; i++) {
|
||||
if (i < start_hour) {
|
||||
ret.push(i)
|
||||
}
|
||||
}
|
||||
if (start_time.minute() === 30 || this.setting.booking_interval === 60) {
|
||||
ret.push(start_hour)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
getEndTimeDisabledMinutes (selectedHour) {
|
||||
const ret = []
|
||||
const start_time = this.form.getFieldValue('start_time')
|
||||
if (selectedHour === start_time.hour()) {
|
||||
ret.push(0)
|
||||
}
|
||||
return ret
|
||||
},
|
||||
validateInterval (rule, value, callback) {
|
||||
const start_time = this.form.getFieldValue('start_time')
|
||||
const end_time = this.form.getFieldValue('end_time')
|
||||
if (end_time.diff(start_time) / 1000 / 60 % value === 0) {
|
||||
callback()
|
||||
} else {
|
||||
const msg = 'can by divided by interval'
|
||||
callback(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -23,23 +23,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Setting',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['ToggleTheme']),
|
||||
handleThemeChange (e) {
|
||||
this.ToggleTheme(e.target.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['theme'])
|
||||
export default {
|
||||
name: 'Setting',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['ToggleTheme']),
|
||||
handleThemeChange (e) {
|
||||
this.ToggleTheme(e.target.value)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['theme'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -73,109 +73,111 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../../api/user'
|
||||
import { getCookie } from '../../utils/fetch'
|
||||
import api from '../../api/user'
|
||||
import { getCookie } from '../../utils/fetch'
|
||||
|
||||
export default {
|
||||
name: 'UserSetting',
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
reset: {
|
||||
form: this.$form.createForm(this),
|
||||
},
|
||||
status: {
|
||||
image: {
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
export default {
|
||||
name: 'UserSetting',
|
||||
data () {
|
||||
return {
|
||||
layout: {
|
||||
'label-col': { span: 6 },
|
||||
'wrapper-col': { span: 18 }
|
||||
},
|
||||
reset: {
|
||||
form: this.$form.createForm(this)
|
||||
},
|
||||
status: {
|
||||
image: {
|
||||
url: '',
|
||||
id: ''
|
||||
},
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
image: {
|
||||
url: '',
|
||||
id: ''
|
||||
},
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
api.getUserAvatar()
|
||||
.then(data => {
|
||||
this.image = data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.reset.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
api.resetPassword(data.password)
|
||||
.then(() => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: '修改密码成功,请重新登陆'
|
||||
})
|
||||
this.$router.push({ name: 'login' })
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
mounted () {
|
||||
api.getUserAvatar()
|
||||
.then(data => {
|
||||
this.image = data
|
||||
})
|
||||
notAllNumberValidator (rule, value, callback) {
|
||||
if (/^[0-9]+.?[0-9]*$/.test(value)) {
|
||||
const msg = 'password cant be all numbers'
|
||||
callback(msg)
|
||||
return false
|
||||
}
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
methods: {
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.reset.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
api.resetPassword(data.password)
|
||||
.then(() => {
|
||||
this.$notification.success({
|
||||
message: '成功',
|
||||
description: '修改密码成功,请重新登陆',
|
||||
})
|
||||
this.$router.push({ name: 'login' })
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
notAllNumberValidator (rule, value, callback) {
|
||||
if (/^[0-9]+.?[0-9]*$/.test(value)) {
|
||||
callback('password cant be all numbers')
|
||||
return false
|
||||
}
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
samePasswordValidator (rule, value, callback) {
|
||||
if (value !== this.reset.form.getFieldValue('password')) {
|
||||
callback('two passwords are different')
|
||||
return false
|
||||
}
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
handleImageChange (info) {
|
||||
if (info.file.status === 'uploading') {
|
||||
this.loading = true
|
||||
} else if (info.file.status === 'done') {
|
||||
this.image.id = info.file.response.id
|
||||
this.image.url = info.file.response.url.toString()
|
||||
this.loading = false
|
||||
api.updateUserAvatar({ id: this.image.id })
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '上传头像成功', key: 'SUCCESS' })
|
||||
})
|
||||
} else if (info.file.status === 'error') {
|
||||
this.$message.error(`${info.file.name} 上传失败.`)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
beforeUpload (file) {
|
||||
const isImage = /image\/*/.test(file.type)
|
||||
if (!isImage) {
|
||||
this.$message.error('图片格式不正确')
|
||||
}
|
||||
const isLt10M = file.size / 1024 / 1024 <= 10
|
||||
if (!isLt10M) {
|
||||
this.$message.error('图片大小请小于10MB')
|
||||
}
|
||||
const isNameLt256 = file.name.length < 256
|
||||
if (!isNameLt256) {
|
||||
this.$message.error('图片名称请小于256个字符')
|
||||
}
|
||||
return isImage && isLt10M && isNameLt256
|
||||
},
|
||||
samePasswordValidator (rule, value, callback) {
|
||||
if (value !== this.reset.form.getFieldValue('password')) {
|
||||
const msg = 'two passwords are different'
|
||||
callback(msg)
|
||||
return false
|
||||
}
|
||||
callback()
|
||||
return true
|
||||
},
|
||||
handleImageChange (info) {
|
||||
if (info.file.status === 'uploading') {
|
||||
this.loading = true
|
||||
} else if (info.file.status === 'done') {
|
||||
this.image.id = info.file.response.id
|
||||
this.image.url = info.file.response.url.toString()
|
||||
this.loading = false
|
||||
api.updateUserAvatar({ id: this.image.id })
|
||||
.then(data => {
|
||||
this.$notification.success({ message: '成功', description: '上传头像成功', key: 'SUCCESS' })
|
||||
})
|
||||
} else if (info.file.status === 'error') {
|
||||
this.$message.error(`${info.file.name} 上传失败.`)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
beforeUpload (file) {
|
||||
const isImage = /image\/*/.test(file.type)
|
||||
if (!isImage) {
|
||||
this.$message.error('图片格式不正确')
|
||||
}
|
||||
const isLt10M = file.size / 1024 / 1024 <= 10
|
||||
if (!isLt10M) {
|
||||
this.$message.error('图片大小请小于10MB')
|
||||
}
|
||||
const isNameLt256 = file.name.length < 256
|
||||
if (!isNameLt256) {
|
||||
this.$message.error('图片名称请小于256个字符')
|
||||
}
|
||||
return isImage && isLt10M && isNameLt256
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
autocomplete="true"
|
||||
placeholder="用户名"
|
||||
v-decorator="[
|
||||
'username',
|
||||
{rules: [{ required: true, message: '请输入用户名' }], validateTrigger: 'blur'}
|
||||
]">
|
||||
'username',
|
||||
{rules: [{ required: true, message: '请输入用户名' }], validateTrigger: 'blur'}
|
||||
]">
|
||||
<a-icon slot="prefix" type="user" style="color: rgba(0, 0, 0, .25)"></a-icon>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
@ -29,9 +29,9 @@
|
|||
autocomplete="true"
|
||||
placeholder="密码"
|
||||
v-decorator="[
|
||||
'password',
|
||||
{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}
|
||||
]">
|
||||
'password',
|
||||
{rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}
|
||||
]">
|
||||
<a-icon slot="prefix" type="lock" style="color: rgba(0, 0, 0, .25)"></a-icon>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
|
@ -51,53 +51,53 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { timeFix } from '@/utils/util'
|
||||
import { mapActions } from 'vuex'
|
||||
import { timeFix } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
data () {
|
||||
return {
|
||||
form: this.$form.createForm(this),
|
||||
state: {
|
||||
loginBtn: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['Login', 'Logout']),
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
this.Login(data)
|
||||
.then((data) => {
|
||||
this.state.loginBtn = true
|
||||
this.loginSuccess(data)
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loginBtn = false
|
||||
})
|
||||
} else {
|
||||
this.state.loginBtn = true
|
||||
setTimeout(() => {
|
||||
this.state.loginBtn = false
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
},
|
||||
loginSuccess (data) {
|
||||
this.$router.push({ path: '/' })
|
||||
setTimeout(() => {
|
||||
this.$notification.success({
|
||||
message: `欢迎`,
|
||||
description: `${timeFix()} ${this.$store.getters.username},欢迎回来`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
}, 1000)
|
||||
export default {
|
||||
name: 'Login',
|
||||
data () {
|
||||
return {
|
||||
form: this.$form.createForm(this),
|
||||
state: {
|
||||
loginBtn: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['Login', 'Logout']),
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((error, data) => {
|
||||
if (!error) {
|
||||
this.Login(data)
|
||||
.then((data) => {
|
||||
this.state.loginBtn = true
|
||||
this.loginSuccess(data)
|
||||
})
|
||||
.catch(() => {
|
||||
this.state.loginBtn = false
|
||||
})
|
||||
} else {
|
||||
this.state.loginBtn = true
|
||||
setTimeout(() => {
|
||||
this.state.loginBtn = false
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
},
|
||||
loginSuccess (data) {
|
||||
this.$router.push({ path: '/' })
|
||||
setTimeout(() => {
|
||||
this.$notification.success({
|
||||
message: `欢迎`,
|
||||
description: `${timeFix()} ${this.$store.getters.username},欢迎回来`,
|
||||
key: 'SUCCESS'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
Loading…
Reference in New Issue