|
|
@@ -77,9 +77,7 @@
|
|
|
@edit="editProgram"
|
|
|
@remove="removeProgram"
|
|
|
>
|
|
|
- <div
|
|
|
- class="c-day-card__count u-ellipsis u-pointer"
|
|
|
- >
|
|
|
+ <div class="c-day-card__count u-ellipsis u-pointer">
|
|
|
+{{ day.programs.length - 1 }}
|
|
|
</div>
|
|
|
</pop-list>
|
|
|
@@ -93,7 +91,6 @@
|
|
|
custom-class="c-dialog"
|
|
|
:close-on-click-modal="false"
|
|
|
:before-close="handleCloseEditDialog"
|
|
|
- append-to-body
|
|
|
>
|
|
|
<schedule-edit
|
|
|
v-if="program"
|
|
|
@@ -118,6 +115,44 @@
|
|
|
</button>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
+ <el-dialog
|
|
|
+ title="冲突提醒"
|
|
|
+ :visible.sync="conflicting"
|
|
|
+ custom-class="c-dialog"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <div class="has-bottom-padding u-bold">
|
|
|
+ <div>局部覆盖:被冲突的节目的时间段将被切割</div>
|
|
|
+ <div>覆盖:被冲突的节目将被移除</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-for="conflict in conflicts"
|
|
|
+ :key="conflict.key"
|
|
|
+ >
|
|
|
+ 与 {{ conflict.target.name }} 于 {{ conflict.start }} ~ {{ conflict.end }} 冲突
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <button
|
|
|
+ class="o-button"
|
|
|
+ @click="_coverConflicts"
|
|
|
+ >
|
|
|
+ 局部覆盖
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ class="o-button"
|
|
|
+ @click="_coverConflictsFull"
|
|
|
+ >
|
|
|
+ 覆盖
|
|
|
+ </button>
|
|
|
+ <button
|
|
|
+ class="o-button cancel"
|
|
|
+ @click="conflicting = false"
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</schedule-wrapper>
|
|
|
</template>
|
|
|
|
|
|
@@ -148,7 +183,9 @@ export default {
|
|
|
current: null,
|
|
|
editing: false,
|
|
|
program: null,
|
|
|
- dirty: false
|
|
|
+ dirty: false,
|
|
|
+ conflicting: false,
|
|
|
+ conflicts: []
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -203,16 +240,46 @@ export default {
|
|
|
this.current = current
|
|
|
this._calculate()
|
|
|
},
|
|
|
+ fix () {
|
|
|
+ let endTime = Date.now() + 60000
|
|
|
+ if (this.programs.some(({ endDateTime }) => new Date(endDateTime).getTime() <= endTime)) {
|
|
|
+ return this.$confirm(
|
|
|
+ '存在过期或将要过期(<=60s)节目,是否移除?',
|
|
|
+ '提示',
|
|
|
+ {
|
|
|
+ type: 'warning',
|
|
|
+ distinguishCancelAndClose: true,
|
|
|
+ confirmButtonText: '移除',
|
|
|
+ cancelButtonText: '保留'
|
|
|
+ }
|
|
|
+ ).then(() => {
|
|
|
+ endTime = Date.now() + 60000
|
|
|
+ this.scheduleOptions.programs = this.programs.filter(({ endDateTime }) => new Date(endDateTime).getTime() > endTime)
|
|
|
+ if (this._compare(this.current, this._transform(endTime), false) <= 0) {
|
|
|
+ this._calculate()
|
|
|
+ }
|
|
|
+ return this.programs
|
|
|
+ }, action => {
|
|
|
+ if (action === 'cancel') {
|
|
|
+ return this.programs
|
|
|
+ }
|
|
|
+ return Promise.reject()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return Promise.resolve(this.programs)
|
|
|
+ },
|
|
|
onSave () {
|
|
|
- this.save(this.programs.map(({ id, name, startDateTime, endDateTime }) => {
|
|
|
- endDateTime = this._offsetDateTime(endDateTime, 1)
|
|
|
- return {
|
|
|
- programId: id,
|
|
|
- programName: name,
|
|
|
- startDateTime, endDateTime
|
|
|
- }
|
|
|
- })).then(() => {
|
|
|
- this.dirty = false
|
|
|
+ this.fix().then(programs => {
|
|
|
+ this.save(programs.map(({ id, name, startDateTime, endDateTime }) => {
|
|
|
+ endDateTime = this._offsetDateTime(endDateTime, 1)
|
|
|
+ return {
|
|
|
+ programId: id,
|
|
|
+ programName: name,
|
|
|
+ startDateTime, endDateTime
|
|
|
+ }
|
|
|
+ })).then(() => {
|
|
|
+ this.dirty = false
|
|
|
+ })
|
|
|
})
|
|
|
},
|
|
|
_transformPrograms (programs) {
|
|
|
@@ -223,13 +290,13 @@ export default {
|
|
|
},
|
|
|
_transformProgram ({ programId, programName, startDateTime, endDateTime }) {
|
|
|
// 服务器保存的时间采用左闭右开原则
|
|
|
- endDateTime = this._offsetDateTime(endDateTime, -1)
|
|
|
+ return this._createProgram(programId, programName, startDateTime, this._offsetDateTime(endDateTime, -1))
|
|
|
+ },
|
|
|
+ _createProgram (id, name, startDateTime, endDateTime) {
|
|
|
return {
|
|
|
+ id, name, startDateTime, endDateTime,
|
|
|
key: Math.random().toString(16).slice(2),
|
|
|
- id: programId,
|
|
|
- name: programName,
|
|
|
- days: this._getDays(startDateTime, endDateTime),
|
|
|
- startDateTime, endDateTime
|
|
|
+ days: this._getDays(startDateTime, endDateTime)
|
|
|
}
|
|
|
},
|
|
|
_offsetDateTime (dateTime, val) {
|
|
|
@@ -265,6 +332,9 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
_removeProgram (key) {
|
|
|
+ if (!key) {
|
|
|
+ return
|
|
|
+ }
|
|
|
const index = this.programs.findIndex(program => program.key === key)
|
|
|
this.programs.splice(index, 1)
|
|
|
if (index === 0) {
|
|
|
@@ -309,8 +379,7 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
saveProgram () {
|
|
|
- const program = this.$refs.editor.getValue()
|
|
|
- const { id, startDateTime, endDateTime } = program
|
|
|
+ const { id, name, startDateTime, endDateTime } = this.$refs.editor.getValue()
|
|
|
if (!startDateTime || !endDateTime) {
|
|
|
this.$message({
|
|
|
type: 'warning',
|
|
|
@@ -333,41 +402,103 @@ export default {
|
|
|
this.handleCloseEditDialog()
|
|
|
return
|
|
|
}
|
|
|
- const conflict = this.checkConflict(program, this.program.key)
|
|
|
- if (conflict) {
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: `与 ${conflict.name} ${conflict.startDateTime}-${conflict.endDateTime} 冲突`
|
|
|
- })
|
|
|
- return
|
|
|
+ this._program = { id, name, startDateTime, endDateTime }
|
|
|
+ if (this._checkConflict(this._program, this.program.key)) {
|
|
|
+ this._saveProgram()
|
|
|
}
|
|
|
+ },
|
|
|
+ _saveProgram () {
|
|
|
+ this._removeProgram(this.program.key)
|
|
|
+ this._mergeOrAdd()
|
|
|
this.dirty = true
|
|
|
- program.key = Math.random().toString(16).slice(2)
|
|
|
- program.days = this._getDays(program.startDateTime, program.endDateTime)
|
|
|
- if (this.program.id) {
|
|
|
- this._removeProgram(this.program.key)
|
|
|
- }
|
|
|
- const timestamp = new Date(startDateTime).getTime()
|
|
|
+ this._calculate()
|
|
|
+ this.handleCloseEditDialog()
|
|
|
+ },
|
|
|
+ _mergeOrAdd () {
|
|
|
+ let program = this._program
|
|
|
+ const timestamp = new Date(program.startDateTime).getTime()
|
|
|
const insertIndex = this.programs.findIndex(item => new Date(item.startDateTime).getTime() > timestamp)
|
|
|
+ let pre = null
|
|
|
+ let next = null
|
|
|
+ let add = true
|
|
|
if (~insertIndex) {
|
|
|
- this.programs.splice(insertIndex, 0, program)
|
|
|
+ pre = this.programs[insertIndex - 1]
|
|
|
+ next = this.programs[insertIndex]
|
|
|
} else {
|
|
|
- this.programs.push(program)
|
|
|
+ pre = this.programs[this.programs.length - 1]
|
|
|
+ }
|
|
|
+ if (next && program.id === next.id && new Date(program.endDateTime).getTime() + 1000 === new Date(next.startDateTime).getTime()) {
|
|
|
+ next.startDateTime = program.startDateTime
|
|
|
+ program = next
|
|
|
+ add = false
|
|
|
+ }
|
|
|
+ if (pre && program.id === pre.id && new Date(pre.endDateTime).getTime() + 1000 === new Date(program.startDateTime).getTime()) {
|
|
|
+ pre.endDateTime = program.endDateTime
|
|
|
+ this._removeProgram(program.key)
|
|
|
+ program = pre
|
|
|
+ add = false
|
|
|
+ }
|
|
|
+ program.key = Math.random().toString(16).slice(2)
|
|
|
+ program.days = this._getDays(program.startDateTime, program.endDateTime)
|
|
|
+ if (add) {
|
|
|
+ if (next) {
|
|
|
+ this.programs.splice(insertIndex, 0, program)
|
|
|
+ } else {
|
|
|
+ this.programs.push(program)
|
|
|
+ }
|
|
|
}
|
|
|
- this._calculate()
|
|
|
- this.handleCloseEditDialog()
|
|
|
},
|
|
|
- checkConflict (program, key) {
|
|
|
+ _checkConflict (program, key) {
|
|
|
if (this.programs.length) {
|
|
|
const cstartDateTime = new Date(program.startDateTime)
|
|
|
const cendDateTime = new Date(program.endDateTime)
|
|
|
- return this.programs.find(item => {
|
|
|
+ this.conflicts = this.programs.filter(item => {
|
|
|
const startDateTime = new Date(item.startDateTime)
|
|
|
const endDateTime = new Date(item.endDateTime)
|
|
|
return item.key !== key && !(cstartDateTime > endDateTime || cendDateTime < startDateTime)
|
|
|
+ }).map(item => {
|
|
|
+ const startDateTime = new Date(item.startDateTime)
|
|
|
+ const endDateTime = new Date(item.endDateTime)
|
|
|
+ return {
|
|
|
+ target: item,
|
|
|
+ key: item.key,
|
|
|
+ start: cstartDateTime > startDateTime ? program.startDateTime : item.startDateTime,
|
|
|
+ end: cendDateTime > endDateTime ? item.endDateTime : program.endDateTime
|
|
|
+ }
|
|
|
})
|
|
|
+ if (this.conflicts.length) {
|
|
|
+ this.conflicting = true
|
|
|
+ return false
|
|
|
+ }
|
|
|
}
|
|
|
- return null
|
|
|
+ return true
|
|
|
+ },
|
|
|
+ _coverConflicts () {
|
|
|
+ const now = Date.now()
|
|
|
+ this.conflicts.forEach(({ target, key, start, end }) => {
|
|
|
+ const { startDateTime, endDateTime } = target
|
|
|
+ if (new Date(endDateTime).getTime() <= now || startDateTime === start && endDateTime === end) {
|
|
|
+ this._removeProgram(key)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (startDateTime === start) {
|
|
|
+ target.startDateTime = this._offsetDateTime(end, 1)
|
|
|
+ } else {
|
|
|
+ if (endDateTime !== end) {
|
|
|
+ const index = this.programs.findIndex(({ key }) => key === target.key)
|
|
|
+ this.programs.splice(index + 1, 0, this._createProgram(target.id, target.name, this._offsetDateTime(end, 1), target.endDateTime))
|
|
|
+ }
|
|
|
+ target.endDateTime = this._offsetDateTime(start, -1)
|
|
|
+ }
|
|
|
+ target.days = this._getDays(target.startDateTime, target.endDateTime)
|
|
|
+ })
|
|
|
+ this.conflicting = false
|
|
|
+ this._saveProgram()
|
|
|
+ },
|
|
|
+ _coverConflictsFull () {
|
|
|
+ this.conflicts.forEach(({ key }) => this._removeProgram(key))
|
|
|
+ this.conflicting = false
|
|
|
+ this._saveProgram()
|
|
|
},
|
|
|
handleCloseEditDialog () {
|
|
|
this.program = null
|
|
|
@@ -411,7 +542,7 @@ export default {
|
|
|
},
|
|
|
_calculate () {
|
|
|
const { year, month } = this.current
|
|
|
- const monthDays = this._getPreentMonthDays(year, month).concat(this._currentMonthDays(year, month))
|
|
|
+ const monthDays = this._getPresentMonthDays(year, month).concat(this._currentMonthDays(year, month))
|
|
|
const diff = 42 - monthDays.length
|
|
|
const dates = diff === 0 ? monthDays : monthDays.concat(this._getNextMonthDays(year, month, diff))
|
|
|
const weeks = []
|
|
|
@@ -434,7 +565,7 @@ export default {
|
|
|
}
|
|
|
return dateArr
|
|
|
},
|
|
|
- _getPreentMonthDays (year, month) {
|
|
|
+ _getPresentMonthDays (year, month) {
|
|
|
const dateArr = []
|
|
|
const week = new Date(year, month, 1).getDay()
|
|
|
const fill = week === 0 ? 7 : week
|
|
|
@@ -522,7 +653,7 @@ export default {
|
|
|
&__content {
|
|
|
min-height: 0;
|
|
|
border: 1px solid $gray--light;
|
|
|
- overflow-y: auto
|
|
|
+ overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
&__row + &__row {
|
|
|
@@ -545,11 +676,11 @@ export default {
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
- &.day.enabled{
|
|
|
+ &.day.enabled {
|
|
|
cursor: pointer;
|
|
|
|
|
|
&:hover {
|
|
|
- transition: background-color .4s;
|
|
|
+ transition: background-color 0.4s;
|
|
|
background-color: #f2f8fe;
|
|
|
}
|
|
|
}
|