Changes
This commit is contained in:
@@ -2,9 +2,9 @@ const apply = {
|
||||
template: /*language=HTML*/ `
|
||||
<div>
|
||||
<el-row :gutter="20" class="mb10">
|
||||
<el-col :span="24" style="text-align: center">
|
||||
<div style="font-size: large;color: #303133">
|
||||
您正在预约【<span style="color: #409EFF">{{ row.name }}</span>】活动场地
|
||||
<el-col :span="24" style="text-align: center;">
|
||||
<div style="font-size: large; color: #303133;">
|
||||
您正在预约【<span style="color: #409EFF;">{{ row.name }}</span>】活动场地
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -28,26 +28,33 @@ const apply = {
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="预约类型" prop="reserveType">
|
||||
<el-radio-group v-model="formData.reserveType" @change="reserveTypeChange">
|
||||
<el-radio-group v-if="availableReserveTypes.length" v-model="formData.reserveType" @change="reserveTypeChange" style="display: none;">
|
||||
<el-radio-button label="union">分工会预约</el-radio-button>
|
||||
<el-radio-button label="club">协会预约</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-radio-group v-if="availableReserveTypes.length" v-model="formData.reserveType" @change="reserveTypeChange">
|
||||
<el-radio-button
|
||||
v-for="item in availableReserveTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
<span v-else style="color: #909399;">当前无可用的预约权限</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分工会" prop="applyUnionName" v-if="formData.reserveType === 'union'">
|
||||
<el-input readonly v-model="formData.applyUnionName"
|
||||
placeholder="自动读取当前登录人的分工会"></el-input>
|
||||
<el-col :span="12" v-if="formData.reserveType === 'union'">
|
||||
<el-form-item label="分工会" prop="applyUnionName">
|
||||
<el-input readonly v-model="formData.applyUnionName" placeholder="自动读取当前登录人的分工会"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="12" v-if="formData.reserveType === 'club'">
|
||||
<el-form-item
|
||||
label="协会"
|
||||
prop="clubId"
|
||||
v-if="formData.reserveType === 'club'"
|
||||
:rules="[{ required: true, message: '请选择您管理的协会', trigger: ['change', 'blur'] }]">
|
||||
<el-select v-model="formData.clubId" placeholder="请选择您管理的协会" filterable clearable
|
||||
style="width: 100%" @change="clubChange">
|
||||
style="width: 100%;" @change="clubChange">
|
||||
<el-option
|
||||
v-for="item in clubOptions"
|
||||
:key="item.id"
|
||||
@@ -62,6 +69,81 @@ const apply = {
|
||||
<el-input maxlength="11" placeholder="请输入联系电话" v-model="formData.applyMobile"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<div class="apply-visual-panel">
|
||||
<div class="apply-visual-panel__toolbar">
|
||||
<div>
|
||||
<div class="apply-visual-panel__title">可预约时段</div>
|
||||
<div class="apply-visual-panel__subtitle">{{ scheduleRuleText }}</div>
|
||||
</div>
|
||||
<div class="apply-visual-panel__actions">
|
||||
<el-tag size="small" type="success">{{ reserveModeText }}</el-tag>
|
||||
<el-date-picker
|
||||
v-model="scheduleDate"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="请选择预约日期"
|
||||
:picker-options="{ disabledDate: isDisabledDate }"
|
||||
@change="onScheduleDateChange">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="apply-visual-panel__legend">
|
||||
<span class="apply-legend__item"><i class="apply-legend__dot apply-legend__dot--available"></i>未预约</span>
|
||||
<span class="apply-legend__item"><i class="apply-legend__dot apply-legend__dot--reserved"></i>已预约</span>
|
||||
<span class="apply-legend__item"><i class="apply-legend__dot apply-legend__dot--selected"></i>已选择</span>
|
||||
<span class="apply-legend__item"><i class="apply-legend__dot apply-legend__dot--closed"></i>不可预约</span>
|
||||
</div>
|
||||
|
||||
<el-skeleton :loading="availabilityLoading" animated>
|
||||
<template slot="template">
|
||||
<div style="padding-top: 8px;">
|
||||
<el-skeleton-item variant="p" style="width: 100%; height: 80px;"></el-skeleton-item>
|
||||
</div>
|
||||
</template>
|
||||
<template>
|
||||
<el-empty v-if="!availabilityBlocks.length" description="当前日期暂无可选时段"></el-empty>
|
||||
|
||||
<div v-else-if="isSegmentedMode">
|
||||
<div v-for="group in segmentedBlockGroups" :key="group.groupIndex" class="apply-block-group">
|
||||
<div class="apply-block-group__title">{{ group.groupLabel }}</div>
|
||||
<div class="apply-block-grid">
|
||||
<button
|
||||
v-for="block in group.blocks"
|
||||
:key="block.key"
|
||||
type="button"
|
||||
:class="getBlockClass(block)"
|
||||
@click="onAvailabilityBlockClick(block)">
|
||||
<span>{{ block.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="apply-block-group">
|
||||
<div class="apply-block-group__title">全天候时段</div>
|
||||
<div class="apply-block-grid">
|
||||
<button
|
||||
v-for="block in availabilityBlocks"
|
||||
:key="block.key"
|
||||
type="button"
|
||||
:class="getBlockClass(block)"
|
||||
@click="onAvailabilityBlockClick(block)">
|
||||
<span>{{ block.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-skeleton>
|
||||
|
||||
<div class="apply-visual-panel__summary" v-if="selectionSummary">
|
||||
当前选择:{{ selectionSummary }}
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="预约开始时间" prop="reserveStartTime">
|
||||
<el-date-picker
|
||||
@@ -71,7 +153,7 @@ const apply = {
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择预约开始时间"
|
||||
:picker-options="startPickerOptions"
|
||||
style="width: 100%"
|
||||
style="width: 100%;"
|
||||
@change="timeFieldChange('reserveStartTime')">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
@@ -85,21 +167,30 @@ const apply = {
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择预约结束时间"
|
||||
:picker-options="endPickerOptions"
|
||||
style="width: 100%"
|
||||
style="width: 100%;"
|
||||
@change="timeFieldChange('reserveEndTime')">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="批量预约">
|
||||
<div style="display:flex;align-items:flex-start;column-gap:12px;flex-wrap:wrap;line-height:1.7;">
|
||||
<div style="display: flex; align-items: flex-start; column-gap: 12px; flex-wrap: wrap; line-height: 1.7;">
|
||||
<el-checkbox v-model="yearlyReserve">预约本年后续每周同一时段</el-checkbox>
|
||||
<span style="color:#909399;">
|
||||
<span style="color: #909399;">
|
||||
例如先选某个周一 09:00-11:00,勾选后会自动预约本年剩余所有周一的这个时段。
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="yearlyReserve && yearlyReserveSummary" style="margin-top:8px;color:#E6A23C;">
|
||||
{{ yearlyReserveSummary }}
|
||||
<div v-if="yearlyReserve" style="margin-top: 10px; max-width: 320px;">
|
||||
<el-date-picker
|
||||
v-model="formData.yearlyReserveEndDate"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="请选择批量预约截止日期"
|
||||
:picker-options="yearlyReserveEndDatePickerOptions">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div v-if="yearlyReserve && batchReserveSummary" style="margin-top: 8px; color: #E6A23C;">
|
||||
{{ batchReserveSummary }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -124,20 +215,30 @@ const apply = {
|
||||
row: {},
|
||||
clubOptions: [],
|
||||
yearlyReserve: false,
|
||||
scheduleDate: '',
|
||||
availabilityLoading: false,
|
||||
selectedBlockKeys: [],
|
||||
timeLimitConfig: {
|
||||
filterHolidays: false,
|
||||
holidayList: [],
|
||||
notApplyTimeList: [],
|
||||
},
|
||||
availabilityData: {
|
||||
date: '',
|
||||
reserveTimeType: 1,
|
||||
reserveTimeTypeName: '分段预约',
|
||||
blocks: [],
|
||||
},
|
||||
pickerRefreshKey: 0,
|
||||
formData: {
|
||||
reserveType: 'union',
|
||||
reserveType: '',
|
||||
applyUnionId: '',
|
||||
applyUnionName: '',
|
||||
clubId: '',
|
||||
clubName: '',
|
||||
reserveStartTime: '',
|
||||
reserveEndTime: '',
|
||||
yearlyReserveEndDate: '',
|
||||
joinCount: 1,
|
||||
applyCause: '',
|
||||
},
|
||||
@@ -152,17 +253,77 @@ const apply = {
|
||||
reserveEndTime: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
joinCount: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
applyCause: [{required: true, message: '必填', trigger: ['blur', 'change']}],
|
||||
clubId: [{ validator: (rule, value, callback) => {
|
||||
if (this.formData.reserveType === 'club' && !value) {
|
||||
callback(new Error('请选择您管理的协会'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
}, trigger: ['blur', 'change']}],
|
||||
clubId: [{
|
||||
validator: (rule, value, callback) => {
|
||||
if (this.formData.reserveType === 'club' && !value) {
|
||||
callback(new Error('请选择您管理的协会'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: ['blur', 'change']
|
||||
}],
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canApplyUnion() {
|
||||
return this.$auth.hasPermission('siteCug.apply.union')
|
||||
},
|
||||
canApplyClub() {
|
||||
return this.$auth.hasPermission('siteCug.apply.club')
|
||||
},
|
||||
availableReserveTypes() {
|
||||
const result = []
|
||||
if (this.canApplyUnion) {
|
||||
result.push('union')
|
||||
}
|
||||
if (this.canApplyClub) {
|
||||
result.push('club')
|
||||
}
|
||||
return result
|
||||
},
|
||||
availableReserveTypeOptions() {
|
||||
const result = []
|
||||
if (this.canApplyUnion) {
|
||||
result.push({value: 'union', label: '分工会预约'})
|
||||
}
|
||||
if (this.canApplyClub) {
|
||||
result.push({value: 'club', label: '协会预约'})
|
||||
}
|
||||
return result
|
||||
},
|
||||
availabilityBlocks() {
|
||||
return Array.isArray(this.availabilityData.blocks) ? this.availabilityData.blocks : []
|
||||
},
|
||||
isSegmentedMode() {
|
||||
return Number(this.availabilityData.reserveTimeType || this.row.reserveTimeType || 1) === 1
|
||||
},
|
||||
reserveModeText() {
|
||||
return this.availabilityData.reserveTimeTypeName || (this.isSegmentedMode ? '分段预约' : '全天候预约')
|
||||
},
|
||||
scheduleRuleText() {
|
||||
if (this.isSegmentedMode) {
|
||||
return '分段预约场地需按场次时间单位选择一个或多个连续时段,不能跨间隔跳选。'
|
||||
}
|
||||
return '全天候预约场地需按预约时间单位选择一个或多个连续时段,开始和结束时间会自动回填。'
|
||||
},
|
||||
segmentedBlockGroups() {
|
||||
const groups = []
|
||||
this.availabilityBlocks.forEach(block => {
|
||||
let target = groups.find(item => item.groupIndex === block.groupIndex)
|
||||
if (!target) {
|
||||
target = {
|
||||
groupIndex: block.groupIndex,
|
||||
groupLabel: block.groupLabel,
|
||||
blocks: [],
|
||||
}
|
||||
groups.push(target)
|
||||
}
|
||||
target.blocks.push(block)
|
||||
})
|
||||
return groups
|
||||
},
|
||||
startPickerOptions() {
|
||||
return {
|
||||
disabledDate: (time) => this.isDisabledDate(time),
|
||||
@@ -175,27 +336,38 @@ const apply = {
|
||||
selectableRange: this.buildSelectableRange(this.formData.reserveEndTime),
|
||||
}
|
||||
},
|
||||
yearlyReserveEndDatePickerOptions() {
|
||||
return {
|
||||
disabledDate: (time) => {
|
||||
if (!this.formData.reserveStartTime) {
|
||||
return false
|
||||
}
|
||||
return this.$moment(time).format('YYYY-MM-DD') < this.formData.reserveStartTime.slice(0, 10)
|
||||
},
|
||||
}
|
||||
},
|
||||
yearlyReserveDates() {
|
||||
if (!this.yearlyReserve || !this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
if (!this.yearlyReserve || !this.formData.reserveStartTime || !this.formData.reserveEndTime || !this.formData.yearlyReserveEndDate) {
|
||||
return []
|
||||
}
|
||||
const start = this.$moment(this.formData.reserveStartTime)
|
||||
const end = this.$moment(this.formData.reserveEndTime)
|
||||
if (!start.isValid() || !end.isValid() || !end.isAfter(start)) {
|
||||
const reserveEndDate = this.$moment(this.formData.yearlyReserveEndDate, 'YYYY-MM-DD')
|
||||
if (!start.isValid() || !end.isValid() || !end.isAfter(start) || !reserveEndDate.isValid() || reserveEndDate.isBefore(start, 'day')) {
|
||||
return []
|
||||
}
|
||||
const result = []
|
||||
const current = start.clone().startOf('day')
|
||||
const endOfYear = start.clone().endOf('year').startOf('day')
|
||||
const reserveEndDay = reserveEndDate.clone().startOf('day')
|
||||
const targetWeekDay = start.day()
|
||||
const startClock = start.format('HH:mm:ss')
|
||||
const endClock = end.format('HH:mm:ss')
|
||||
while (current.isSameOrBefore(endOfYear, 'day')) {
|
||||
while (current.isSameOrBefore(reserveEndDay, 'day')) {
|
||||
if (current.day() === targetWeekDay) {
|
||||
const day = current.format('YYYY-MM-DD')
|
||||
const startTime = day + ' ' + startClock
|
||||
const endTime = day + ' ' + endClock
|
||||
if (this.validateTimeLimit(false, startTime, endTime)) {
|
||||
if (this.validateTimeLimit(false, startTime, endTime) && this.validateGraphSelection(false, startTime, endTime, day)) {
|
||||
result.push(day)
|
||||
}
|
||||
}
|
||||
@@ -203,6 +375,21 @@ const apply = {
|
||||
}
|
||||
return result
|
||||
},
|
||||
batchReserveSummary() {
|
||||
if (!this.yearlyReserve) {
|
||||
return ''
|
||||
}
|
||||
if (!this.formData.yearlyReserveEndDate) {
|
||||
return '请选择批量预约截止日期'
|
||||
}
|
||||
if (!this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
return '请先选择开始和结束时间,再批量预约截止日期内的同星期时段'
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
return '当前时间段在截止日期内无法生成可批量预约的日期'
|
||||
}
|
||||
return '将从 ' + this.yearlyReserveDates[0] + ' 开始,自动预约到 ' + this.formData.yearlyReserveEndDate + ',共 ' + this.yearlyReserveDates.length + ' 个时段'
|
||||
},
|
||||
yearlyReserveSummary() {
|
||||
if (!this.yearlyReserve) {
|
||||
return ''
|
||||
@@ -215,13 +402,39 @@ const apply = {
|
||||
}
|
||||
return '将从 ' + this.yearlyReserveDates[0] + ' 开始,自动预约到 ' + this.yearlyReserveDates[this.yearlyReserveDates.length - 1] + ',共 ' + this.yearlyReserveDates.length + ' 个时段'
|
||||
},
|
||||
batchReserveSummary() {
|
||||
if (!this.yearlyReserve) {
|
||||
return ''
|
||||
}
|
||||
if (!this.formData.yearlyReserveEndDate) {
|
||||
return '请选择批量预约截止日期'
|
||||
}
|
||||
if (!this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
return '请先选择开始和结束时间,再设置批量预约截止日期'
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
return '当前截止日期内没有可批量预约的同星期时段'
|
||||
}
|
||||
return '将从 ' + this.formData.reserveStartTime.slice(0, 10) + ' 开始,自动预约到 ' + this.formData.yearlyReserveEndDate
|
||||
},
|
||||
selectionSummary() {
|
||||
if (!this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
return ''
|
||||
}
|
||||
return this.formData.reserveStartTime + ' 至 ' + this.formData.reserveEndTime
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
yearlyReserve(val) {
|
||||
if (val) {
|
||||
this.syncYearlyReserveEndDate(true)
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async onOpen(row) {
|
||||
this.row = row
|
||||
this.clubOptions = []
|
||||
this.yearlyReserve = false
|
||||
this.formData = {
|
||||
createDefaultFormData(row) {
|
||||
const reserveType = this.getDefaultReserveType()
|
||||
return {
|
||||
siteId: row.id,
|
||||
applyUserId: this.$store.state.user.id,
|
||||
applyUserName: this.$store.state.user.username,
|
||||
@@ -229,18 +442,71 @@ const apply = {
|
||||
applyLoginName: this.$store.state.user.loginname,
|
||||
applyUnitId: this.$store.state.user?.unit?.id,
|
||||
applyUnitName: this.$store.state.user?.unit?.name,
|
||||
reserveType: 'union',
|
||||
applyUnionId: this.$store.state.user?.union?.id,
|
||||
applyUnionName: this.$store.state.user?.union?.name,
|
||||
reserveType,
|
||||
applyUnionId: reserveType === 'union' ? (this.$store.state.user?.union?.id || '') : '',
|
||||
applyUnionName: reserveType === 'union' ? (this.$store.state.user?.union?.name || '') : '',
|
||||
clubId: '',
|
||||
clubName: '',
|
||||
applyMobile: this.$store.state.user.mobile,
|
||||
reserveStartTime: '',
|
||||
reserveEndTime: '',
|
||||
yearlyReserveEndDate: '',
|
||||
joinCount: 1,
|
||||
applyCause: '',
|
||||
}
|
||||
},
|
||||
getDefaultReserveType() {
|
||||
return this.availableReserveTypes[0] || ''
|
||||
},
|
||||
async onOpen(row) {
|
||||
this.row = row || {}
|
||||
this.clubOptions = []
|
||||
this.yearlyReserve = false
|
||||
this.selectedBlockKeys = []
|
||||
this.scheduleDate = ''
|
||||
this.availabilityData = {
|
||||
date: '',
|
||||
reserveTimeType: Number(row.reserveTimeType || 1),
|
||||
reserveTimeTypeName: row.reserveTimeTypeName || (Number(row.reserveTimeType || 1) === 2 ? '全天候预约' : '分段预约'),
|
||||
blocks: [],
|
||||
}
|
||||
this.formData = this.createDefaultFormData(row || {})
|
||||
if (this.formData.reserveType) {
|
||||
await this.reserveTypeChange(this.formData.reserveType)
|
||||
}
|
||||
this.syncYearlyReserveEndDate(true)
|
||||
await this.queryTimeLimitConfig()
|
||||
this.scheduleDate = this.getInitialScheduleDate()
|
||||
await this.queryAvailability()
|
||||
},
|
||||
getDefaultYearlyReserveEndDate() {
|
||||
const base = this.formData.reserveStartTime
|
||||
? this.$moment(this.formData.reserveStartTime)
|
||||
: (this.scheduleDate ? this.$moment(this.scheduleDate, 'YYYY-MM-DD') : this.$moment())
|
||||
if (!base.isValid()) {
|
||||
return this.$moment().endOf('month').format('YYYY-MM-DD')
|
||||
}
|
||||
return base.clone().endOf('month').format('YYYY-MM-DD')
|
||||
},
|
||||
syncYearlyReserveEndDate(force = false) {
|
||||
const defaultDate = this.getDefaultYearlyReserveEndDate()
|
||||
if (force || !this.formData.yearlyReserveEndDate) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
return
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate < this.formData.reserveStartTime.slice(0, 10)) {
|
||||
this.$set(this.formData, 'yearlyReserveEndDate', defaultDate)
|
||||
}
|
||||
},
|
||||
getInitialScheduleDate() {
|
||||
let current = this.$moment().startOf('day')
|
||||
for (let i = 0; i < 90; i++) {
|
||||
if (!this.isDisabledDate(current.toDate())) {
|
||||
return current.format('YYYY-MM-DD')
|
||||
}
|
||||
current = current.add(1, 'day')
|
||||
}
|
||||
return this.$moment().add(1, 'day').format('YYYY-MM-DD')
|
||||
},
|
||||
async queryTimeLimitConfig() {
|
||||
const fallback = {
|
||||
@@ -266,7 +532,57 @@ const apply = {
|
||||
}
|
||||
this.pickerRefreshKey += 1
|
||||
},
|
||||
async queryAvailability(date) {
|
||||
const targetDate = date || this.scheduleDate
|
||||
if (!targetDate || !this.row.id) {
|
||||
this.availabilityData.blocks = []
|
||||
return
|
||||
}
|
||||
this.availabilityLoading = true
|
||||
try {
|
||||
const res = await this.$axios.post('/platform/siteCug/apply/availability', {
|
||||
siteId: this.row.id,
|
||||
date: targetDate,
|
||||
})
|
||||
if (res.code === 0 && res.data) {
|
||||
this.availabilityData = {
|
||||
date: res.data.date || targetDate,
|
||||
reserveTimeType: Number(res.data.reserveTimeType || this.row.reserveTimeType || 1),
|
||||
reserveTimeTypeName: res.data.reserveTimeTypeName || this.reserveModeText,
|
||||
blocks: Array.isArray(res.data.blocks) ? res.data.blocks : [],
|
||||
}
|
||||
} else {
|
||||
this.availabilityData = {
|
||||
date: targetDate,
|
||||
reserveTimeType: Number(this.row.reserveTimeType || 1),
|
||||
reserveTimeTypeName: Number(this.row.reserveTimeType || 1) === 2 ? '全天候预约' : '分段预约',
|
||||
blocks: [],
|
||||
}
|
||||
this.$message.warning((res && res.msg) || '预约时段加载失败')
|
||||
}
|
||||
} catch (e) {
|
||||
this.availabilityData = {
|
||||
date: targetDate,
|
||||
reserveTimeType: Number(this.row.reserveTimeType || 1),
|
||||
reserveTimeTypeName: Number(this.row.reserveTimeType || 1) === 2 ? '全天候预约' : '分段预约',
|
||||
blocks: [],
|
||||
}
|
||||
this.$message.warning('预约时段加载失败,请稍后重试')
|
||||
} finally {
|
||||
this.availabilityLoading = false
|
||||
this.syncSelectionFromFields()
|
||||
}
|
||||
},
|
||||
async onScheduleDateChange(value) {
|
||||
this.scheduleDate = value || ''
|
||||
this.clearSelection(true)
|
||||
await this.queryAvailability(value)
|
||||
},
|
||||
async reserveTypeChange(value) {
|
||||
if (!this.availableReserveTypes.includes(value)) {
|
||||
this.formData.reserveType = this.getDefaultReserveType()
|
||||
return
|
||||
}
|
||||
if (value === 'union') {
|
||||
this.formData.applyUnionId = this.$store.state.user?.union?.id || ''
|
||||
this.formData.applyUnionName = this.$store.state.user?.union?.name || ''
|
||||
@@ -288,19 +604,44 @@ const apply = {
|
||||
try {
|
||||
const res = await this.$axios.post('/platform/club/examine/apply/getClubsByRole')
|
||||
this.clubOptions = Array.isArray(res.data) ? res.data : []
|
||||
this.syncManagedClubSelection()
|
||||
if (!this.clubOptions.length) {
|
||||
this.$message.warning('您当前没有可预约的协会管理权限')
|
||||
}
|
||||
} catch (e) {
|
||||
this.clubOptions = []
|
||||
this.formData.clubId = ''
|
||||
this.formData.clubName = ''
|
||||
this.$message.warning('协会列表加载失败,请稍后重试')
|
||||
}
|
||||
},
|
||||
syncManagedClubSelection() {
|
||||
if (!this.clubOptions.length) {
|
||||
this.formData.clubId = ''
|
||||
this.formData.clubName = ''
|
||||
return
|
||||
}
|
||||
const currentClub = this.clubOptions.find(item => item.id === this.formData.clubId)
|
||||
if (currentClub) {
|
||||
this.formData.clubName = currentClub.clubName || ''
|
||||
return
|
||||
}
|
||||
if (this.clubOptions.length === 1) {
|
||||
this.formData.clubId = this.clubOptions[0].id
|
||||
this.formData.clubName = this.clubOptions[0].clubName || ''
|
||||
return
|
||||
}
|
||||
this.formData.clubId = ''
|
||||
this.formData.clubName = ''
|
||||
},
|
||||
clubChange(clubId) {
|
||||
const club = this.clubOptions.find(item => item.id === clubId)
|
||||
this.formData.clubName = club ? club.clubName : ''
|
||||
},
|
||||
async normalizeReserveTypeData() {
|
||||
if (!this.availableReserveTypes.includes(this.formData.reserveType)) {
|
||||
this.formData.reserveType = this.getDefaultReserveType()
|
||||
}
|
||||
if (this.formData.reserveType === 'union') {
|
||||
this.formData.applyUnionId = this.$store.state.user?.union?.id || ''
|
||||
this.formData.applyUnionName = this.$store.state.user?.union?.name || ''
|
||||
@@ -417,6 +758,15 @@ const apply = {
|
||||
}
|
||||
const start = this.$moment(startTime)
|
||||
const end = this.$moment(endTime)
|
||||
if (!start.isValid() || !end.isValid()) {
|
||||
return false
|
||||
}
|
||||
if (start.format('YYYY-MM-DD') !== end.format('YYYY-MM-DD')) {
|
||||
if (showMessage) {
|
||||
this.$message.warning('预约时间必须在同一天内')
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (this.isDateTimeBlocked(startTime) || this.isDateTimeBlocked(endTime)) {
|
||||
if (showMessage) {
|
||||
this.$message.warning('预约时间不能选择周末、节假日或禁用时间')
|
||||
@@ -437,9 +787,173 @@ const apply = {
|
||||
}
|
||||
return true
|
||||
},
|
||||
timeFieldChange(field) {
|
||||
clearSelection(clearTimeFields = false) {
|
||||
this.selectedBlockKeys = []
|
||||
if (clearTimeFields) {
|
||||
this.formData.reserveStartTime = ''
|
||||
this.formData.reserveEndTime = ''
|
||||
}
|
||||
},
|
||||
getSelectedIndices() {
|
||||
return this.availabilityBlocks
|
||||
.map((block, index) => this.selectedBlockKeys.includes(block.key) ? index : -1)
|
||||
.filter(index => index > -1)
|
||||
},
|
||||
getBlockClass(block) {
|
||||
return {
|
||||
'apply-block': true,
|
||||
'apply-block--available': block.status === 'available' && !this.selectedBlockKeys.includes(block.key),
|
||||
'apply-block--reserved': block.status === 'reserved',
|
||||
'apply-block--closed': block.status === 'closed',
|
||||
'apply-block--selected': this.selectedBlockKeys.includes(block.key),
|
||||
}
|
||||
},
|
||||
onAvailabilityBlockClick(block) {
|
||||
if (!block || !block.key) {
|
||||
return
|
||||
}
|
||||
if (block.status !== 'available' && !this.selectedBlockKeys.includes(block.key)) {
|
||||
this.$message.warning(block.status === 'reserved' ? '该时段已被预约,请选择其他时段' : '该时段当前不可预约')
|
||||
return
|
||||
}
|
||||
const index = this.availabilityBlocks.findIndex(item => item.key === block.key)
|
||||
if (index < 0) {
|
||||
return
|
||||
}
|
||||
this.toggleContinuousSelection(index)
|
||||
},
|
||||
toggleContinuousSelection(index) {
|
||||
const selectedIndices = this.getSelectedIndices()
|
||||
if (!selectedIndices.length) {
|
||||
this.applySelectionRange(index, index)
|
||||
return
|
||||
}
|
||||
const selectedStart = selectedIndices[0]
|
||||
const selectedEnd = selectedIndices[selectedIndices.length - 1]
|
||||
if (selectedIndices.includes(index)) {
|
||||
if (selectedIndices.length === 1) {
|
||||
this.clearSelection(true)
|
||||
return
|
||||
}
|
||||
if (index === selectedStart) {
|
||||
this.applySelectionRange(selectedStart + 1, selectedEnd)
|
||||
return
|
||||
}
|
||||
if (index === selectedEnd) {
|
||||
this.applySelectionRange(selectedStart, selectedEnd - 1)
|
||||
return
|
||||
}
|
||||
this.applySelectionRange(index, index)
|
||||
return
|
||||
}
|
||||
const nextStart = Math.min(index, selectedStart)
|
||||
const nextEnd = Math.max(index, selectedEnd)
|
||||
if (!this.canSelectRange(nextStart, nextEnd)) {
|
||||
this.$message.warning(this.isSegmentedMode ? '分段预约只能连续选择一个或多个时间段,不能跨间隔跳选' : '全天候预约只能连续选择一个时间段')
|
||||
return
|
||||
}
|
||||
this.applySelectionRange(nextStart, nextEnd)
|
||||
},
|
||||
canSelectRange(startIndex, endIndex) {
|
||||
if (startIndex < 0 || endIndex >= this.availabilityBlocks.length || startIndex > endIndex) {
|
||||
return false
|
||||
}
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
const block = this.availabilityBlocks[i]
|
||||
if (!block || block.status !== 'available') {
|
||||
return false
|
||||
}
|
||||
if (i > startIndex) {
|
||||
const prev = this.availabilityBlocks[i - 1]
|
||||
if (!prev || prev.endDateTime !== block.startDateTime) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
applySelectionRange(startIndex, endIndex) {
|
||||
const selected = this.availabilityBlocks.slice(startIndex, endIndex + 1)
|
||||
this.selectedBlockKeys = selected.map(item => item.key)
|
||||
if (selected.length) {
|
||||
this.formData.reserveStartTime = selected[0].startDateTime
|
||||
this.formData.reserveEndTime = selected[selected.length - 1].endDateTime
|
||||
this.scheduleDate = selected[0].startDateTime.slice(0, 10)
|
||||
}
|
||||
},
|
||||
findRangeIndicesByFields(startTime, endTime) {
|
||||
if (!startTime || !endTime) {
|
||||
return null
|
||||
}
|
||||
for (let i = 0; i < this.availabilityBlocks.length; i++) {
|
||||
const block = this.availabilityBlocks[i]
|
||||
if (block.status !== 'available' || block.startDateTime !== startTime) {
|
||||
continue
|
||||
}
|
||||
let currentEnd = block.endDateTime
|
||||
if (currentEnd === endTime) {
|
||||
return [i, i]
|
||||
}
|
||||
for (let j = i + 1; j < this.availabilityBlocks.length; j++) {
|
||||
const prev = this.availabilityBlocks[j - 1]
|
||||
const next = this.availabilityBlocks[j]
|
||||
if (next.status !== 'available' || prev.endDateTime !== next.startDateTime) {
|
||||
break
|
||||
}
|
||||
currentEnd = next.endDateTime
|
||||
if (currentEnd === endTime) {
|
||||
return [i, j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
syncSelectionFromFields() {
|
||||
const startTime = this.formData.reserveStartTime
|
||||
const endTime = this.formData.reserveEndTime
|
||||
if (!startTime || !endTime) {
|
||||
this.selectedBlockKeys = []
|
||||
return
|
||||
}
|
||||
if (startTime.slice(0, 10) !== this.scheduleDate || endTime.slice(0, 10) !== this.scheduleDate) {
|
||||
this.selectedBlockKeys = []
|
||||
return
|
||||
}
|
||||
const range = this.findRangeIndicesByFields(startTime, endTime)
|
||||
if (!range) {
|
||||
this.selectedBlockKeys = []
|
||||
return
|
||||
}
|
||||
this.selectedBlockKeys = this.availabilityBlocks.slice(range[0], range[1] + 1).map(item => item.key)
|
||||
},
|
||||
validateGraphSelection(showMessage = true, startTime = this.formData.reserveStartTime, endTime = this.formData.reserveEndTime, targetDay = this.scheduleDate) {
|
||||
if (!startTime || !endTime) {
|
||||
return true
|
||||
}
|
||||
if (!targetDay || startTime.slice(0, 10) !== targetDay || endTime.slice(0, 10) !== targetDay) {
|
||||
if (showMessage) {
|
||||
this.$message.warning('预约时间必须与当前选择的预约日期一致')
|
||||
}
|
||||
return false
|
||||
}
|
||||
const range = this.findRangeIndicesByFields(startTime, endTime)
|
||||
if (range) {
|
||||
return true
|
||||
}
|
||||
if (showMessage) {
|
||||
this.$message.warning(this.isSegmentedMode
|
||||
? '分段预约请按场次时间单位选择一个或多个连续时段'
|
||||
: '全天候预约请按预约时间单位选择一个或多个连续时段')
|
||||
}
|
||||
return false
|
||||
},
|
||||
async timeFieldChange(field) {
|
||||
const value = this.formData[field]
|
||||
if (!value) {
|
||||
if (field === 'reserveStartTime') {
|
||||
this.syncYearlyReserveEndDate(true)
|
||||
}
|
||||
this.syncSelectionFromFields()
|
||||
return
|
||||
}
|
||||
if (this.isDateTimeBlocked(value)) {
|
||||
@@ -447,16 +961,38 @@ const apply = {
|
||||
this.$set(this.formData, field, '')
|
||||
return
|
||||
}
|
||||
const day = this.$moment(value).format('YYYY-MM-DD')
|
||||
if (day !== this.scheduleDate) {
|
||||
this.scheduleDate = day
|
||||
await this.queryAvailability(day)
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.reserveEndTime && !this.validateTimeLimit()) {
|
||||
this.$set(this.formData, field, '')
|
||||
return
|
||||
}
|
||||
if (field === 'reserveStartTime') {
|
||||
this.syncYearlyReserveEndDate()
|
||||
}
|
||||
this.syncSelectionFromFields()
|
||||
},
|
||||
validateYearlyReserve() {
|
||||
if (!this.yearlyReserve) {
|
||||
return true
|
||||
}
|
||||
if (!this.formData.yearlyReserveEndDate) {
|
||||
this.$message.warning('请选择批量预约截止日期')
|
||||
return false
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate < this.formData.reserveStartTime.slice(0, 10)) {
|
||||
this.$message.warning('批量预约截止日期不能早于开始日期')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('?????????????????????')
|
||||
this.$message.warning('当前选择的时间段在截止日期内无法生成可批量预约的日期')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('当前选择的时间段无法生成本年批量预约日期')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -465,10 +1001,58 @@ const apply = {
|
||||
return this.yearlyReserve ? '/platform/siteCug/apply/submitYearly' : '/platform/siteCug/apply/submit'
|
||||
},
|
||||
buildSubmitConfirmMessage() {
|
||||
const baseText = '您已选择 ' + this.formData.reserveStartTime + ' 至 ' + this.formData.reserveEndTime
|
||||
if (!this.yearlyReserve) {
|
||||
return '您确定要提交吗?'
|
||||
return baseText + ',是否确定提交预约?'
|
||||
}
|
||||
return '将一次性预约本年后续 ' + this.yearlyReserveDates.length + ' 个同星期时段,确认提交吗?'
|
||||
return baseText + '。系统将继续预约本年后续 ' + this.yearlyReserveDates.length + ' 个同星期时段,是否确定提交?'
|
||||
},
|
||||
validateYearlyReserve() {
|
||||
if (!this.yearlyReserve) {
|
||||
return true
|
||||
}
|
||||
if (!this.formData.yearlyReserveEndDate) {
|
||||
this.$message.warning('请选择批量预约截止日期')
|
||||
return false
|
||||
}
|
||||
if (this.formData.reserveStartTime && this.formData.yearlyReserveEndDate < this.formData.reserveStartTime.slice(0, 10)) {
|
||||
this.$message.warning('批量预约截止日期不能早于开始日期')
|
||||
return false
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
this.$message.warning('当前选择的时间段在截止日期内无法生成可批量预约的日期')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
buildSubmitConfirmMessage() {
|
||||
const baseText = '您已选择 ' + this.formData.reserveStartTime + ' 至 ' + this.formData.reserveEndTime
|
||||
if (!this.yearlyReserve) {
|
||||
return baseText + ',是否确定提交预约?'
|
||||
}
|
||||
return baseText + '。系统将继续预约到 ' + this.formData.yearlyReserveEndDate + ',共 ' + this.yearlyReserveDates.length + ' 个同星期时段,是否确定提交?'
|
||||
},
|
||||
batchReserveSummary() {
|
||||
if (!this.yearlyReserve) {
|
||||
return ''
|
||||
}
|
||||
if (!this.formData.yearlyReserveEndDate) {
|
||||
return '请选择批量预约截止日期'
|
||||
}
|
||||
if (!this.formData.reserveStartTime || !this.formData.reserveEndTime) {
|
||||
return '请先选择开始和结束时间,再设置批量预约截止日期'
|
||||
}
|
||||
if (!this.yearlyReserveDates.length) {
|
||||
return '当前截止日期内没有可批量预约的同星期时段'
|
||||
}
|
||||
return '将从 ' + this.yearlyReserveDates[0] + ' 开始,自动预约到 ' + this.formData.yearlyReserveEndDate
|
||||
},
|
||||
buildSubmitConfirmMessage() {
|
||||
const baseText = '您已选择 ' + this.formData.reserveStartTime + ' 至 ' + this.formData.reserveEndTime
|
||||
if (!this.yearlyReserve) {
|
||||
return baseText + ',是否确定提交预约?'
|
||||
}
|
||||
return baseText + '。系统将继续预约到 ' + this.formData.yearlyReserveEndDate + ',是否确定提交?'
|
||||
},
|
||||
onSubmit() {
|
||||
this.$refs.formRef.validate(async (valid) => {
|
||||
@@ -503,6 +1087,9 @@ const apply = {
|
||||
if (!this.validateTimeLimit()) {
|
||||
return
|
||||
}
|
||||
if (!this.validateGraphSelection()) {
|
||||
return
|
||||
}
|
||||
if (!this.validateYearlyReserve()) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ layout("/layouts/platform.html"){
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
<!--#include('../manage/info.js'){}#-->
|
||||
<!--#include('apply_v2.js'){}#-->
|
||||
<!--#include('apply.js'){}#-->
|
||||
const vue = new Vue({
|
||||
el: "#app",
|
||||
mixins: [initTableMixins],
|
||||
|
||||
Reference in New Issue
Block a user