add bookingNew

This commit is contained in:
David 2019-05-26 14:15:42 +08:00
parent b91010cfbc
commit a8ecbd02e4
6 changed files with 396 additions and 41 deletions

View File

@ -1,8 +1,8 @@
import fetchAPI from '../utils/fetch'
export default {
getRoomList (params) {
return fetchAPI('booking/room/', 'get', null, params)
getRoomList () {
return fetchAPI('booking/room/', 'get', null)
},
createRoom (room) {
return fetchAPI('/booking/room/', 'post', room)

View File

@ -27,6 +27,13 @@ export const routerMap = [
component: () => import(/* webpackChunkName: "booking" */ '../views/booking/Booking'),
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'] },
},
{
path: '/booking/create',
name: 'bookingCreate',

View File

@ -58,8 +58,6 @@ export default function fetchAPI (url, method, data = null, params = null) {
return res.text()
} else if (res.status === 400) {
return res.json()
} else if (res.status === 404) {
return res.json()
} else if (res.ok) {
return res.json()
} else {

View File

@ -125,7 +125,7 @@
type="primary"
icon="plus"
style="width: 100%;"
@click="$router.push({name: 'dashboard'})">
@click="$router.push({name: 'bookingNew'})">
新建
</a-button>
</a-col>
@ -257,7 +257,7 @@
}
},
mounted () {
roomAPI.getRoomList(null)
roomAPI.getRoomList()
.then(data => {
this.roomList = data
})
@ -286,9 +286,6 @@
this.count = data.count
this.state.loading = false
})
.catch(() => {
this.state.loading = false
})
},
handleClearParams () {
this.params = {

View File

@ -0,0 +1,346 @@
<template>
<page-layout title="新建预约">
<a-card>
<a-col
:xs="{span: 24}"
:sm="{span: 20}"
:xl="{span: 16}">
<a-form>
<a-form-item
label="房间"
v-bind="layout">
<a-select
v-model="form.room">
<a-select-option v-for="item in roomList" :key="item.id">{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item
label="日期"
v-bind="layout">
<a-date-picker
style="width: 100%"
format="YYYY 年 MM 月 DD 日"
@change="handleDateChange"
:disabledDate="getDisabledDate"
:allowClear="false"
v-model="form.date">
</a-date-picker>
</a-form-item>
<a-form-item
label="开始时间"
v-bind="layout">
<a-time-picker
style="width: 100%"
placeholder="选择开始时间"
:minuteStep="30"
:secondStep="60"
:disabledHours="getStartTimeDisabledHours"
:disabledMinutes="getStartTimeDisabledMinutes"
:hideDisabledOptions="true"
:inputReadOnly="true"
:allowEmpty="false"
v-model="form.startTime"
@change="handleStartTimeChange">
</a-time-picker>
</a-form-item>
<a-form-item
label="结束时间"
v-bind="layout">
<a-time-picker
style="width: 100%"
placeholder="选择结束时间"
:minuteStep="30"
:secondStep="60"
:disabledHours="getEndTimeDisabledHours"
:disabledMinutes="getEndTimeDisabledMinutes"
:hideDisabledOptions="true"
:inputReadOnly="true"
:allowEmpty="false"
v-model="form.endTime"
@change="handleEndTimeChange">
</a-time-picker>
</a-form-item>
<a-form-item
label="座位"
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>
<div>
<span style="vertical-align: -6px;">提示:
<span class="box white"></span>可选座位
<span class="box green"></span>不可选座位
<span class="box blue"></span>已选座位
</span>
</div>
</div>
</a-spin>
</a-form-item>
<a-form-item
label="预约人"
v-bind="layout">
<a-select
v-if="!isTeacher"
showSearch
placeholder="搜索用户名邮箱"
:showArrow="false"
:filterOption="false"
: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>
</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>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSubmit" style="float: right">
新建预约
</a-button>
<a-button @click="$router.go(-1)" style="float: right; margin-right: 4px">
返回
</a-button>
</a-form-item>
</a-form>
</a-col>
</a-card>
</page-layout>
</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'
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 => {
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' })
}
},
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()
if (this.form.endTime.minute() === 0) {
end_hour -= 1
}
for (let i = 0; i < 24; i++) {
if (i < start_hour || i > end_hour) {
ret.push(i)
}
}
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()
if (this.form.startTime.minute() === 30) {
start_hour += 1
}
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
},
getEndTimeDisabledMinutes (selectedHour) {
let ret = []
if (selectedHour === this.form.startTime.hour()) {
ret.push(0)
}
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
})
}
},
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;
line-height: 30px;
display: inline-block;
height: 36px;
width: 36px;
margin: 4px;
padding: 1px;
border: solid 1px rgba(128, 128, 128, 0.3);
box-shadow: 0 0 1px @primary-color;
border-radius: 2px;
cursor: pointer;
}
.unselectable {
cursor: not-allowed;
background-color: @success-color;
}
.selected {
background-color: @primary-color;
}
.box {
display: inline-block;
margin: 0 2px 0 8px;
vertical-align: -2px;
height: 14px;
width: 14px;
border: solid 1px rgba(128, 128, 128, 0.3);
}
.green {
background-color: @success-color;
}
.blue {
background-color: @primary-color;
}
.white {
background-color: #fff;
}
}
</style>

View File

@ -59,7 +59,7 @@
<a-button
style="float: right"
type="primary"
:disabled="Object.keys(selected).length === 0"
:disabled="Object.keys(this.selected).length === 0"
@click="handleCreate">
新建预约
</a-button>
@ -147,43 +147,45 @@
}
},
handleSelect (x, y) {
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
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
}
}
}
} 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
}
}
this.selected = {}
}
} else {
this.selected = {}
this.firstSelected = null
}
this.firstSelected = null
this.selected = newData
}
this.selected = newData
},
handleCreate () {
let key_list = Object.keys(this.selected)
@ -213,6 +215,11 @@
}
this.$router.push({ name: 'bookingCreate', params: { bookingCreate } })
}
},
computed: {
isSelectable () {
return new moment().format('YYYY-MM-DD') <= this.params.date
}
}
}
</script>