npm install devextreme@22.2.6 devextreme-vue@22.2.6
效果图:
<template>
<div style="padding: 20px">
<!-- 日期选择框 -->
<DxDateBox
v-model="selectedDate"
displayFormat="yyyy/M/d"
placeholder="请选择大于最近版本且不早于今天的有效日期"
:min="minSelectableDate"
:show-clear-button="true"
:use-calendar="true"
:width="200"
:disabled="loading"
@value-changed="handleDateChange"
/>
<!-- 提交按钮 -->
<DxButton
text="提交"
type="default"
styling-mode="contained"
style="margin-left: 10px"
:width="100"
:disabled="!selectedDateStr || loading"
@click="submit"
/>
</div>
</template>
<script>
import { DxDateBox } from 'devextreme-vue/date-box';
import { DxButton } from 'devextreme-vue/button';
import 'devextreme/dist/css/dx.light.css';
import moment from 'moment';
// 中文支持
import { locale, loadMessages } from 'devextreme/localization';
import dxMessagesZh from 'devextreme/localization/messages/zh';
loadMessages(dxMessagesZh);
locale('zh-CN');
export default {
components: { DxDateBox, DxButton },
data() {
return {
list: [], // 初始为空,等待后端加载
selectedDate: null,
selectedDateStr: '',
loading: true // 控制加载状态
};
},
created() {
// 模拟异步从后端加载数据
setTimeout(() => {
this.list = [
{ id: 1, date: '2025-08-09', isValid: true },
{ id: 2, date: '2025-08-10', isValid: true },
{ id: 3, date: '2025-08-05', isValid: false },
{ id: 4, date: '2025-08-08', isValid: true },
{ id: 5, date: '2025-08-15', isValid: true }
];
this.loading = false; // 关闭加载状态
}, 800); // 模拟网络延迟
},
computed: {
/**
* 功能:计算最小可选日期
*
* 原理:初始化改变了依赖的list 又因为list是响应数据vue监听到会触发minSelectableDate方法
*
* 业务:用户可选的日期必须同时满足两个条件
* 1.大于 list 中所有 isValid: true 记录的 最大日期
* 2.大于等于今天(当前系统日期)
*/
minSelectableDate() {
const latestValidDate = this.findLatestValidDate(this.list, 'date');
// 当前日期(今天)00:00:00
const today = moment().startOf('day');
// 历史版本最大有效日期加上 1 天(得到“最大有效日期的下一天”)
const nextDayAfterLatest = latestValidDate ? latestValidDate.clone().add(1, 'day').startOf('day') : null;
// 最小可选日期 == 两者中较大的(即更晚的日期)
const minDate = nextDayAfterLatest ? moment.max(nextDayAfterLatest, today) : today;
return minDate.toDate();
}
},
methods: {
// 找出 list 中 isValid === true 的记录,并返回指定字段(生效日期)的最大日期
findLatestValidDate(list, fieldName) {
let max = null;
for (const item of list) {
if (!item.isValid) continue;
const date = moment(item[fieldName], 'YYYY-MM-DD');
if (!date.isValid()) continue;
if (max === null || date.isAfter(max, 'day')) {
max = date;
}
}
return max;
},
/**
* 功能:更新要提交的表单数据
*
* e 是 DevExtreme 的事件对象,用户选择下来日期自动带过来
* 结构: e = {
* value: Date | null, // 用户选中的日期(JavaScript Date 对象),或 null(清空时)
* previousValue: ... // 上一次的值(这里没用到)
* }
*/
handleDateChange(e) {
this.selectedDateStr = e.value ? moment(e.value).format('YYYY/M/D') : '';
},
/**
* 功能:模拟保存并提交表单
*/
submit() {
if (!this.selectedDateStr) return;
alert(`已提交:${this.selectedDateStr}(模拟成功)`);
}
}
};
</script>
<style scoped>
.dx-datebox {
margin-right: 10px;
}
</style>