243 行
9.4 KiB
HTML
243 行
9.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>跨天时间选择器测试</title>
|
|
<!-- 引入Vue.js -->
|
|
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
|
|
<!-- 引入Element UI -->
|
|
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
|
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
|
<style>
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 50px auto;
|
|
padding: 20px;
|
|
}
|
|
.time-block {
|
|
margin-top: 15px;
|
|
padding: 15px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 5px;
|
|
}
|
|
.time-block:first-child {
|
|
margin-top: 0;
|
|
}
|
|
.result {
|
|
margin-top: 20px;
|
|
padding: 15px;
|
|
background-color: #f5f5f5;
|
|
border-radius: 5px;
|
|
}
|
|
.cross-day-indicator {
|
|
color: #e6a23c;
|
|
font-weight: bold;
|
|
}
|
|
.conflict-indicator {
|
|
color: #f56c6c;
|
|
font-weight: bold;
|
|
}
|
|
.valid-indicator {
|
|
color: #67c23a;
|
|
font-weight: bold;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app" class="container">
|
|
<h1>跨天时间选择器测试</h1>
|
|
|
|
<el-card>
|
|
<div slot="header">
|
|
<span>营业时间设置</span>
|
|
</div>
|
|
|
|
<div v-for="(item, index) in businessTime" :key="index" class="time-block">
|
|
<h4>时间段 {{ index + 1 }}</h4>
|
|
<el-time-select
|
|
placeholder="开始时间"
|
|
v-model="item[0]"
|
|
value-format="HH:mm"
|
|
:picker-options="getTimeOptions()">
|
|
</el-time-select>
|
|
<span style="margin: 0 10px;">至</span>
|
|
<el-time-select
|
|
placeholder="结束时间"
|
|
v-model="item[1]"
|
|
value-format="HH:mm"
|
|
:picker-options="getTimeOptions()">
|
|
</el-time-select>
|
|
|
|
<el-button v-if="index === 0" @click="addTimeSlot" type="primary" size="mini" style="margin-left: 10px;">
|
|
添加时间段
|
|
</el-button>
|
|
<el-button v-else @click="removeTimeSlot(index)" type="danger" size="mini" style="margin-left: 10px;">
|
|
删除
|
|
</el-button>
|
|
|
|
<!-- 显示当前时间段状态 -->
|
|
<div style="margin-top: 10px;">
|
|
<span v-if="item[0] && item[1]">
|
|
<span v-if="isCrossDay(item[0], item[1])" class="cross-day-indicator">
|
|
⚠️ 跨天时间段: {{ item[0] }} - {{ item[1] }} (次日)
|
|
</span>
|
|
<span v-else class="valid-indicator">
|
|
✅ 正常时间段: {{ item[0] }} - {{ item[1] }}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="result">
|
|
<h3>验证结果</h3>
|
|
<div v-for="(result, index) in validationResults" :key="index">
|
|
<p :class="result.isValid ? 'valid-indicator' : 'conflict-indicator'">
|
|
{{ result.message }}
|
|
</p>
|
|
</div>
|
|
|
|
<h4>测试用例</h4>
|
|
<el-button @click="testNormalTime" size="small">测试正常时间 (09:00-17:00)</el-button>
|
|
<el-button @click="testCrossDayTime" size="small">测试跨天时间 (22:00-06:00)</el-button>
|
|
<el-button @click="testMultipleCrossDay" size="small">测试多个跨天时间段</el-button>
|
|
<el-button @click="testConflictTime" size="small">测试冲突时间</el-button>
|
|
<el-button @click="clearAll" size="small">清空所有</el-button>
|
|
</div>
|
|
</el-card>
|
|
</div>
|
|
|
|
<script>
|
|
new Vue({
|
|
el: '#app',
|
|
data() {
|
|
return {
|
|
businessTime: [['', '']]
|
|
}
|
|
},
|
|
computed: {
|
|
validationResults() {
|
|
const results = [];
|
|
|
|
// 检查每个时间段
|
|
for (let i = 0; i < this.businessTime.length; i++) {
|
|
const timeSlot = this.businessTime[i];
|
|
if (!timeSlot[0] || !timeSlot[1]) continue;
|
|
|
|
// 检查开始时间是否等于结束时间
|
|
if (timeSlot[0] === timeSlot[1]) {
|
|
results.push({
|
|
isValid: false,
|
|
message: `时间段 ${i + 1}: 开始时间不能等于结束时间`
|
|
});
|
|
continue;
|
|
}
|
|
|
|
// 检查与其他时间段的冲突
|
|
for (let j = 0; j < this.businessTime.length; j++) {
|
|
if (i !== j && this.businessTime[j][0] && this.businessTime[j][1]) {
|
|
if (this.isTimeConflict(timeSlot[0], timeSlot[1], this.businessTime[j][0], this.businessTime[j][1])) {
|
|
results.push({
|
|
isValid: false,
|
|
message: `时间段 ${i + 1} 与时间段 ${j + 1} 存在冲突`
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (results.length === 0) {
|
|
results.push({
|
|
isValid: true,
|
|
message: '✅ 所有时间段设置正确,无冲突'
|
|
});
|
|
}
|
|
|
|
return results;
|
|
}
|
|
},
|
|
methods: {
|
|
getTimeOptions() {
|
|
return {
|
|
start: '00:00',
|
|
step: '00:05',
|
|
end: '23:59'
|
|
};
|
|
},
|
|
|
|
addTimeSlot() {
|
|
if (this.businessTime.length < 3) {
|
|
this.businessTime.push(['', '']);
|
|
}
|
|
},
|
|
|
|
removeTimeSlot(index) {
|
|
this.businessTime.splice(index, 1);
|
|
},
|
|
|
|
getTimestamp(time) {
|
|
return Date.parse(new Date('1970-01-01 ' + time + ':00'));
|
|
},
|
|
|
|
isCrossDay(startTime, endTime) {
|
|
return this.getTimestamp(startTime) > this.getTimestamp(endTime);
|
|
},
|
|
|
|
isTimeConflict(time1Start, time1End, time2Start, time2End) {
|
|
const t1s = this.getTimestamp(time1Start);
|
|
const t1e = this.getTimestamp(time1End);
|
|
const t2s = this.getTimestamp(time2Start);
|
|
const t2e = this.getTimestamp(time2End);
|
|
|
|
// 如果时间段1跨天,时间段2不跨天
|
|
if (this.isCrossDay(time1Start, time1End) && !this.isCrossDay(time2Start, time2End)) {
|
|
return (t2s >= t1s || t2e <= t1e || t2s <= t1e);
|
|
}
|
|
|
|
// 如果时间段1不跨天,时间段2跨天
|
|
if (!this.isCrossDay(time1Start, time1End) && this.isCrossDay(time2Start, time2End)) {
|
|
return (t1s >= t2s || t1e <= t2e || t1s <= t2e);
|
|
}
|
|
|
|
// 如果两个时间段都跨天
|
|
if (this.isCrossDay(time1Start, time1End) && this.isCrossDay(time2Start, time2End)) {
|
|
return true; // 两个跨天时间段必然冲突
|
|
}
|
|
|
|
// 两个时间段都不跨天,使用常规比较
|
|
return !(t1e <= t2s || t1s >= t2e);
|
|
},
|
|
|
|
// 测试用例
|
|
testNormalTime() {
|
|
this.businessTime = [['09:00', '17:00']];
|
|
},
|
|
|
|
testCrossDayTime() {
|
|
this.businessTime = [['22:00', '06:00']];
|
|
},
|
|
|
|
testMultipleCrossDay() {
|
|
this.businessTime = [
|
|
['08:00', '12:00'],
|
|
['14:00', '18:00'],
|
|
['20:00', '02:00']
|
|
];
|
|
},
|
|
|
|
testConflictTime() {
|
|
this.businessTime = [
|
|
['09:00', '17:00'],
|
|
['16:00', '20:00'] // 与第一个时间段冲突
|
|
];
|
|
},
|
|
|
|
clearAll() {
|
|
this.businessTime = [['', '']];
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |