VUE3 element-plus el-date-picker 日期选择范围

vue3 已经取消了 picker-options 参数,不过我们可以用 calendar-change 和 disabled-date 代替

 <el-date-picker
         v-model="dateRange"
         type="daterange"
         range-separator="-"
         @calendar-change="calendarChange"
        :disabled-date="disabledDate"
 />
const chooseDate = ref(null);
const calendarChange = (val: Date[]) => {
    chooseDate.value = val[0];
};

const disabledDate = (time: number) => {
	// 时间范围不能超过当前日期的前两个月
	let end = dayjs(chooseDate.value).add(2, "month").valueOf()
	let start = dayjs(chooseDate.value).subtract(2, "month").valueOf()
	if (chooseDate.value) {
		return time.getTime() > end || time.getTime() < start
	}
};
<think>根据提供的代码片段,我们需要修改之前的解决方案,因为归属机构字段使用了树形选择(el-tree)而不是简单的输入或选择。同时,设备编号(设备编号)等字段也需要整合进去。 修改点: 1. 归属机构(orgselect)是一个树形选择组件,它的值通过树形结构的选中节点获取。因此,在验证时,我们需要检查orgselect是否有选中的值(注意:树形选择可能支持多选,但根据代码中`check-strictly`和`show-checkbox`,这里可能是单选还是多选?从`handleCheckChangeOrg`方法名看,可能是通过勾选改变,但具体需要看实现。不过,验证逻辑上,我们只需要判断它是否有选中的值即可)。 2. 其他字段(设备编号、设备类型、卡号)保持不变。 由于原问题要求:除了时间范围,至少选择归属机构、设备编号、设备类型、卡号中的一个。 因此,我们需要在自定义验证函数中检查: - 归属机构(orgselect)是否有值(可能是数组,也可能是单个值,取决于树形选择的配置) - 设备编号(jjh)是否有值 - 设备类型(deviceType)是否有值 - 卡号(cardNum)是否有值 注意:原代码片段中,设备编号的prop是"jjh",所以表单数据中设备编号字段应该是jjh。 修改后的表单数据对象: form: { time: [], // 时间范围 brchno: &#39;&#39;, // 归属机构的值(注意:原代码中归属机构的prop是brchno,但v-model绑定的是orgselect?这里需要统一) jjh: &#39;&#39;, // 设备编号 deviceType: &#39;&#39;, // 设备类型 cardNum: &#39;&#39; // 卡号 } 但是,观察代码片段,归属机构的el-select绑定的是orgselect,而el-form-item的prop是brchno。这可能导致不一致。我们需要调整: 方案1:将el-form-item的prop改为orgselect,并在rules中定义orgselect的验证规则。 方案2:将v-model改为form.brchno,保持表单数据统一。 为了保持表单数据的统一性,建议使用方案2,即: <el-select v-model="form.brchno" ...> 但是,原代码片段中使用了树形选择,并且有自定义的过滤和选中处理,所以我们需要将树形选择的选中值同步到form.brchno中。 由于原代码片段不完整,我们假设已经通过事件(如check-change)将选中的节点值赋给了form.brchno(可能是选中的节点id数组,或者单个id,根据业务)。 因此,修改后的验证函数需要检查: - form.time 必须存在(时间范围- 并且 form.brchno, form.jjh, form.deviceType, form.cardNum 至少有一个非空。 注意:空数组(如多选但没有选)视为空,空字符串视为空。 修改后的验证函数: const validateAtLeastOne = (rule, value, callback) => { // 注意:form.brchno可能是数组(多选)或字符串(单选),我们通过判断长度来确定是否为空 const brchnoFilled = Array.isArray(form.brchno) ? form.brchno.length > 0 : !!form.brchno; const jjhFilled = !!form.jjh; const deviceTypeFilled = !!form.deviceType; const cardNumFilled = !!form.cardNum; if (!brchnoFilled && !jjhFilled && !deviceTypeFilled && !cardNumFilled) { callback(new Error(&#39;请至少填写归属机构、设备编号、设备类型或卡号中的一个&#39;)); } else { callback(); } }; 另外,时间范围是必填的,所以保留原来的规则。 由于归属机构使用了树形选择,其值可能是一个数组(多选)或字符串(单选)。这里根据实际业务,如果是多选,则form.brchno应该是数组;单选可能是字符串或数组。但为了统一,建议在单选时也使用数组(但这样可能不合适,因为单选通常是一个值)。所以,我们需要根据实际配置来处理。 根据代码片段,树形选择使用了`show-checkbox`,所以可能是多选。但原代码中`check-strictly`属性(注意:原代码中写的是`:check-strictly`,没有绑定值,可能默认true)表示父子节点没有关联,并且单选还是多选取决于是否配置了`multiple`。但原代码中没有multiple属性,所以可能是单选?实际上,树形选择在el-option内,所以它不会显示多选样式,而是以下拉树的形式出现,一般单选比较常见。 因此,我们假设这里归属机构是单选,那么form.brchno应该是一个值(节点id)。那么验证时只需要判断form.brchno不为空字符串即可。 但是,由于代码片段不完整,我们无法确定。所以,为了通用性,我们按照上面的验证函数,同时处理数组和字符串。 现在,我们修改模板代码,将归属机构和其他字段整合到之前的模板中,并调整验证规则。 注意:原代码片段中,归属机构的el-select内部有一个el-input用于过滤,还有一个el-tree用于展示树形结构。这种结构在Element Plus中不是标准用法,可能会导致一些问题。通常,树形选择可以使用`<el-tree-select>`(但Element Plus没有原生的树形选择组件,所以常用这种组合方式)。 我们保持原代码片段的结构,但将v-model绑定到form.brchno,并处理树形选择的事件。 由于原代码片段不完整,我们只关注验证部分。因此,我们假设已经通过事件将选中的节点id赋值给form.brchno。 修改后的完整代码示例: 注意:以下代码中,我们只关注表单结构和验证逻辑,树形选择的具体实现(如数据加载、过滤、选中事件)需要根据实际情况补充。</think>根据您提供的代码片段,我将修改前面的解决方案,整合树形机构选择组件并确保验证逻辑正常工作。以下是完整实现: ```vue <template> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px" > <!-- 时间范围选择 --> <el-form-item label="时间范围" prop="dateRange"> <el-date-picker v-model="form.dateRange" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" range-separator="_" unlink-panels start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[ new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59) ]" /> </el-form-item> <!-- 树形机构选择 --> <el-form-item label="归属机构" prop="brchno"> <el-select v-model="form.brchno" filterable placeholder="请输入归属机构" style="width: 200px" clearable @clear="handleClearOrg" > <el-option style="height: auto; background-color: #fff; padding: 0"> <div style="padding: 10px"> <el-input v-model="filterTextOrg" placeholder="输入关键字进行过滤" clearable @input="handleFilterOrgsTreeSelect" style="margin-bottom: 10px; width: 100%" /> <el-tree ref="orgTree" :data="orgOptions" :props="{ value: &#39;id&#39;, label: &#39;label&#39;, children: &#39;children&#39; }" node-key="id" :filter-node-method="filterNode" :check-strictly="true" show-checkbox @check="handleCheckChangeOrg" highlight-current style="max-height: 300px; overflow: auto" /> </div> </el-option> </el-select> </el-form-item> <!-- 其他字段 --> <el-form-item label="设备编号" prop="jjh"> <el-input v-model="form.jjh" placeholder="请输入设备编号" /> </el-form-item> <el-form-item label="设备类型" prop="deviceType"> <el-select v-model="form.deviceType" placeholder="请选择"> <el-option label="类型A" value="A" /> <el-option label="类型B" value="B" /> </el-select> </el-form-item> <el-form-item label="卡号" prop="cardNum"> <el-input v-model="form.cardNum" placeholder="请输入卡号" /> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm">提交</el-button> <el-button @click="resetForm">重置</el-button> </el-form-item> </el-form> </template> <script setup> import { ref, reactive, watch } from &#39;vue&#39;; const formRef = ref(null); const orgTree = ref(null); const filterTextOrg = ref(&#39;&#39;); // 表单数据 const form = reactive({ dateRange: [], brchno: null, // 机构ID(单选) jjh: &#39;&#39;, deviceType: &#39;&#39;, cardNum: &#39;&#39; }); // 模拟机构数据 const orgOptions = ref([ { id: 1, label: &#39;总公司&#39;, children: [ { id: 11, label: &#39;分公司A&#39; }, { id: 12, label: &#39;分公司B&#39; } ] }, { id: 2, label: &#39;区域中心&#39;, children: [ { id: 21, label: &#39;分中心X&#39; }, { id: 22, label: &#39;分中心Y&#39; } ] } ]); // 树形组件过滤方法 const filterNode = (value, data) => { if (!value) return true; return data.label.includes(value); }; // 监听过滤文本变化 watch(filterTextOrg, (val) => { orgTree.value?.filter(val); }); // 处理机构选择变化 const handleCheckChangeOrg = (checkedNode, { checkedKeys }) => { if (checkedKeys.length > 0) { form.brchno = checkedKeys[0]; // 单选模式取第一个 // 获取选中的节点对象 const node = orgTree.value.getNode(checkedKeys[0]); if (node && node.data) { console.log(&#39;选中的机构:&#39;, node.data.label); } } else { form.brchno = null; } }; // 清除机构选择 const handleClearOrg = () => { form.brchno = null; orgTree.value?.setCheckedKeys([]); }; // 自定义验证规则:至少填写时间外的其他一个字段 const validateAtLeastOne = (rule, value, callback) => { const { brchno, jjh, deviceType, cardNum } = form; if (!brchno && !jjh && !deviceType && !cardNum) { callback(new Error(&#39;请至少填写归属机构、设备编号、设备类型或卡号中的一个&#39;)); } else { callback(); } }; // 表单验证规则 const rules = { dateRange: [ { type: &#39;array&#39;, required: true, message: &#39;请选择时间范围&#39;, trigger: &#39;change&#39; } ], // 虚拟字段用于联合验证 atLeastOne: [ { validator: validateAtLeastOne, trigger: &#39;change&#39; } ] }; // 提交表单 const submitForm = () => { formRef.value.validate((valid) => { if (valid) { // 准备提交数据 const submitData = { startTime: form.dateRange[0], endTime: form.dateRange[1], orgId: form.brchno, deviceCode: form.jjh, deviceType: form.deviceType, cardNumber: form.cardNum }; console.log(&#39;提交数据:&#39;, submitData); alert(&#39;表单验证通过,准备提交&#39;); } else { console.log(&#39;表单验证失败&#39;); return false; } }); }; // 重置表单 const resetForm = () => { formRef.value.resetFields(); form.brchno = null; orgTree.value?.setCheckedKeys([]); }; </script> ``` ### 关键修改说明 1. **树形机构选择集成**: - 使用 `el-tree` 嵌套在 `el-select` 中实现树形选择 - 添加搜索过滤功能,通过 `filter-node-method` 实现 - 使用 `check-strictly` 实现父子节点不关联 - 通过 `@check` 事件处理选择变化 2. **机构选择数据处理**: ```javascript const handleCheckChangeOrg = (checkedNode, { checkedKeys }) => { if (checkedKeys.length > 0) { form.brchno = checkedKeys[0]; // 单选模式 const node = orgTree.value.getNode(checkedKeys[0]); // 可以获取选中节点的完整数据 } else { form.brchno = null; } }; ``` 3. **验证规则调整**: ```javascript const validateAtLeastOne = (rule, value, callback) => { const { brchno, jjh, deviceType, cardNum } = form; if (!brchno && !jjh && !deviceType && !cardNum) { callback(new Error(&#39;请至少填写一个字段&#39;)); } else { callback(); } }; ``` 4. **重置逻辑增强**: ```javascript const resetForm = () => { formRef.value.resetFields(); form.brchno = null; // 额外重置机构选择 orgTree.value?.setCheckedKeys([]); // 清空树形选择 }; ``` 5. **时间选择器配置**: - 使用 `value-format="YYYY-MM-DD HH:mm:ss"` 确保时间格式 - 设置 `:default-time` 提供默认时间值 - `unlink-panels` 允许左右面板独立选择 ### 注意事项 1. **树形选择实现细节**: - 单选模式通过只取第一个选中键实现 - 使用 `getNode` 方法可以获取选中节点的完整数据 - `check-strictly` 确保父子节点选择不联动 2. **性能优化**: - 使用 `max-height` 限制树形组件高度 - 添加滚动条防止数据过多时页面溢出 - 通过 `watch` 监听过滤文本变化,避免频繁重渲染 3. **表单验证**: - 虚拟字段 `atLeastOne` 触发联合验证 - `trigger: &#39;change&#39;` 确保实时验证 - 机构选择值使用 `null` 表示未选择 4. **数据提交**: - 时间范围拆分为 startTime 和 endTime - 机构提交 ID 值,可根据需要提交完整对象 - 保持字段命名与后端接口一致
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值