disabled状态el-form下el-button的disabled的精细化控制

有一个很复杂的表单,支持编辑和查看两种模式。
在这里插入图片描述

查看时当然不希望编辑,最好是区分模式,在编辑模式下直接用div显示而不是用表单元素。这样工作量就有点大。那就考虑使用表单元素的disabled来让其不能编辑。如果每个表单元素都写这个玩意也是很费劲的,幸好el-form提供了在表单上直接指定disabled的方法。那么问题又来了,表单中的按钮又想可以点击把弹框弹出显示内容,弹框中不允许保存。但是在el-form中的表单项都会表单disabled影响,具体原因如下(来自use-form-common-props.ts):

export const useFormDisabled = (fallback?: MaybeRef<boolean | undefined>) => {
  const disabled = useProp<boolean>('disabled')
  const form = inject(formContextKey, undefined)
  return computed(
    () => disabled.value || unref(fallback) || form?.disabled || false
  )
}

可以看到如果form.disabled是true,那么即使我们给表单项指定了disabled=false也无用了。真是伤脑筋呀!!

从上面的代码可以想到,如果我把el-button的form.disabled设置为false是不是就解决了呢?form是通过inject方式注入的,那么我的想法是创建一个MyButton把el-button封装起来,在MyButton里面把form拦截然后复写,如下:

<template>
  <el-button>
    <slot></slot>
  </el-button>
</template>

<script setup lang="ts">
// 为了在disabled的form中让按钮依然可用
import { formContextKey } from 'element-plus';interface IMyButtonProps {
  alwaysEnable: boolean;
}const props = withDefaults(defineProps<IMyButtonProps>(), {
  alwaysEnable: false,
});const form = inject(formContextKey, undefined);let newForm;
if (form) {
  const tmp = {
    ...form
  };
  if (props.alwaysEnable) {
    tmp.disabled = false;
  }
  newForm = reactive({
    ...tmp,
  });
}provide(formContextKey, newForm);
watch(() => props.alwaysEnable, () => {
  if (newForm) {
    newForm.disabled = props.alwaysEnable ? false : form?.disabled;
  }
})</script>


这里会把el-button的一些功能封印,比如插槽,其实可以把插槽也拿过来,只是我这里不需要就没弄。

其实推而广之的话,也可以创建一个组件复写form.disabled,代码类似上面,

<template>
  <slot></slot>
</template>

<script setup lang="ts">
import { formContextKey } from 'element-plus';

interface IEnableFormItemProps {
  enable: boolean;
}

const props = withDefaults(defineProps<IEnableFormItemProps>(), {
  enable: true,
});

const form = inject(formContextKey, undefined);

let newForm;
if (form) {
  const tmp = {
    ...form
  };
  if (props.enable) {
    tmp.disabled = false;
  }
  newForm = reactive({
    ...tmp,
  });
}

provide(formContextKey, newForm);

watch(() => props.enable, () => {
  if (newForm) {
    newForm.disabled = props.enable ? false : form?.disabled;
  }
});
</script>

用法很简单

...
<EnableFormItem enable>
	<el-button>xxx</el-button>
</EnableFormItem>
...

此时el-button的disabled不再受el-form的影响而是被EnableFormItem的enable影响。我曾尝试过用函数式组件来写,代码如下

import { inject, provide, reactive, watch } from 'vue';
import { formContextKey } from 'element-plus';
export default function EnableFormItem(props, { slots }) {

  const form = inject(formContextKey, undefined);

  let newForm;
  if (form) {
    const tmp = {
      ...form
    };
    if (props.enable) {
      tmp.disabled = false;
    }
    newForm = reactive({
      ...tmp,
    });
  }

  provide(formContextKey, newForm);

  watch(() => props.enable, () => {
    if (newForm) {
      newForm.disabled = props.enable ? false : form?.disabled;
    }
  });

  return slots.default()
}

可惜不起作用,网上查了才知道在函数式组件中不能用provide/inject,这个真是我的知识盲区,有机会需要进一步研究一下。

如果对你有帮助请点赞,嘻嘻:)
原文

<template> <div class="app-container"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form-item label="种质名称" prop="germplasmName"> <el-input v-model="queryParams.germplasmName" placeholder="请输入种质名称" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="来源地" prop="origin"> <el-input v-model="queryParams.origin" placeholder="请输入来源地" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="储存位置" prop="storageLocation"> <el-input v-model="queryParams.storageLocation" placeholder="请输入储存位置" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="库存" prop="stock"> <el-input v-model="queryParams.stock" placeholder="请输入库存" clearable @keyup.enter.native="handleQuery" /> </el-form-item> <el-form-item label="入库时间" prop="entryTime"> <el-date-picker clearable v-model="queryParams.entryTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择入库时间"> </el-date-picker> </el-form-item> <el-form-item label="保质期" prop="expirationDate"> <el-date-picker clearable v-model="queryParams.expirationDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择保质期"> </el-date-picker> </el-form-item> <el-form-item label="活性预警时间" prop="activityWarningTime"> <el-date-picker clearable v-model="queryParams.activityWarningTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择活性预警时间"> </el-date-picker> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> </el-form-item> </el-form> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['crop:Crop_germ_resources:add']" >新增</el-button> </el-col> <el-col :span="1.5"> <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['crop:Crop_germ_resources:edit']" >修改</el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['crop:Crop_germ_resources:remove']" >删除</el-button> </el-col> <el-col :span="1.5"> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['crop:Crop_germ_resources:export']" >导出</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> </el-row> <el-table v-loading="loading" :data="Crop_germ_resourcesList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column label="资源id" align="center" prop="id" /> <el-table-column label="种质名称" align="center" prop="germplasmName" /> <el-table-column label="作物种类" align="center" prop="cropType" /> <el-table-column label="品种特性" align="center" prop="varietyTraits" /> <el-table-column label="来源地" align="center" prop="origin" /> <el-table-column label="储存状态" align="center" prop="storageStatus" /> <el-table-column label="储存位置" align="center" prop="storageLocation" /> <el-table-column label="库存" align="center" prop="stock" /> <el-table-column label="入库时间" align="center" prop="entryTime" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.entryTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="保质期" align="center" prop="expirationDate" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.expirationDate, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="活性状态" align="center" prop="activityStatus" /> <el-table-column label="活性预警时间" align="center" prop="activityWarningTime" width="180"> <template slot-scope="scope"> <span>{{ parseTime(scope.row.activityWarningTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['crop:Crop_germ_resources:edit']" >修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['crop:Crop_germ_resources:remove']" >删除</el-button> <el-button size="mini" type="text" icon="el-icon-document" @click="handleExperimentApply(scope.row)" v-hasPermi="['crop:Crop_germ_resources:edit']" >实验申请</el-button> <el-button size="mini" type="text" icon="el-icon-shopping-cart-full" @click="handleCollectApply(scope.row)" v-hasPermi="['crop:Crop_germ_resources:edit']" >领取申请</el-button> </template> </el-table-column> </el-table> <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 添加或修改农作物种质资源对话框 --> <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="种质名称" prop="germplasmName"> <el-input v-model="form.germplasmName" placeholder="请输入种质名称" /> </el-form-item> <el-form-item label="品种特性" prop="varietyTraits"> <el-input v-model="form.varietyTraits" type="textarea" placeholder="请输入内容" /> </el-form-item> <el-form-item label="来源地" prop="origin"> <el-input v-model="form.origin" placeholder="请输入来源地" /> </el-form-item> <el-form-item label="储存位置" prop="storageLocation"> <el-input v-model="form.storageLocation" placeholder="请输入储存位置" /> </el-form-item> <el-form-item label="库存" prop="stock"> <el-input v-model="form.stock" placeholder="请输入库存" /> </el-form-item> <el-form-item label="入库时间" prop="entryTime"> <el-date-picker clearable v-model="form.entryTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择入库时间"> </el-date-picker> </el-form-item> <el-form-item label="保质期" prop="expirationDate"> <el-date-picker clearable v-model="form.expirationDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择保质期"> </el-date-picker> </el-form-item> <el-form-item label="活性预警时间" prop="activityWarningTime"> <el-date-picker clearable v-model="form.activityWarningTime" type="date" value-format="yyyy-MM-dd" placeholder="请选择活性预警时间"> </el-date-picker> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </el-dialog> <!-- 实验申请对话框 --> <el-dialog title="实验申请" :visible.sync="experimentOpen" width="600px" append-to-body> <el-form ref="experimentForm" :model="experimentForm" :rules="experimentRules" label-width="100px"> <el-form-item label="申请ID" prop="id"> <el-input v-model="experimentForm.id" disabled /> </el-form-item> <el-form-item label="申请时间" prop="applicationTime"> <el-date-picker v-model="experimentForm.applicationTime" type="date" value-format="yyyy-MM-dd" disabled> </el-date-picker> </el-form-item> <el-form-item label="种质名称" prop="germplasmName"> <el-input v-model="experimentForm.germplasmName" disabled /> </el-form-item> <el-form-item label="实验目的" prop="experimentPurpose"> <el-input v-model="experimentForm.experimentPurpose" type="textarea" placeholder="请输入实验目的" /> </el-form-item> <el-form-item label="申请用量" prop="applicationAmount"> <el-input v-model.number="experimentForm.applicationAmount" placeholder="请输入申请用量" /> </el-form-item> <el-form-item label="用量单位" prop="unit"> <el-radio-group v-model="experimentForm.unit"> <el-radio label="粒">粒</el-radio> <el-radio label="克">克</el-radio> <el-radio label="株">株</el-radio> <el-radio label="块">块</el-radio> <el-radio label="段">段</el-radio> <el-radio label="芽">芽</el-radio> </el-radio-group> </el-form-item> <el-form-item label="实验周期" prop="experimentCycle"> <el-input v-model="experimentForm.experimentCycle" placeholder="请输入实验周期"> <template slot="append">天</template> </el-input> </el-form-item> <el-form-item label="育种员姓名" prop="breederName"> <el-input v-model="experimentForm.breederName" placeholder="请输入育种员姓名" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitExperimentForm">确 定</el-button> <el-button @click="cancelExperiment">取 消</el-button> </div> </el-dialog> <!-- 领取申请对话框 --> <el-dialog title="领取申请" :visible.sync="collectOpen" width="600px" append-to-body> <el-form ref="collectForm" :model="collectForm" :rules="collectRules" label-width="100px"> <el-form-item label="申请ID" prop="id"> <el-input v-model="collectForm.id" disabled /> </el-form-item> <el-form-item label="申请时间" prop="applicationTime"> <el-date-picker v-model="collectForm.applicationTime" type="date" value-format="yyyy-MM-dd" disabled> </el-date-picker> </el-form-item> <el-form-item label="种质名称" prop="germplasmName"> <el-input v-model="collectForm.germplasmName" disabled /> </el-form-item> <el-form-item label="领取用途" prop="collectPurpose"> <el-input v-model="collectForm.collectPurpose" type="textarea" placeholder="请输入领取用途" /> </el-form-item> <el-form-item label="领取用量" prop="collectAmount"> <el-input v-model.number="collectForm.collectAmount" placeholder="请输入领取用量" /> </el-form-item> <el-form-item label="用量单位" prop="unit"> <el-radio-group v-model="collectForm.unit"> <el-radio label="粒">粒</el-radio> <el-radio label="克">克</el-radio> <el-radio label="株">株</el-radio> <el-radio label="块">块</el-radio> <el-radio label="段">段</el-radio> <el-radio label="芽">芽</el-radio> </el-radio-group> </el-form-item> <el-form-item label="机构名称" prop="institutionName"> <el-input v-model="collectForm.institutionName" placeholder="请输入机构名称" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitCollectForm">确 定</el-button> <el-button @click="cancelCollect">取 消</el-button> </div> </el-dialog> </div> </template> <script> import { listCrop_germ_resources, getCrop_germ_resources, delCrop_germ_resources, addCrop_germ_resources, updateCrop_germ_resources } from "@/api/crop/Crop_germ_resources" export default { name: "Crop_germ_resources", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 显示搜索条件 showSearch: true, // 总条数 total: 0, // 农作物种质资源表格数据 Crop_germ_resourcesList: [], // 弹出层标题 title: "", // 是否显示弹出层 open: false, // 查询参数 queryParams: { pageNum: 1, pageSize: 10, germplasmName: null, cropType: null, varietyTraits: null, origin: null, storageStatus: null, storageLocation: null, stock: null, entryTime: null, expirationDate: null, activityStatus: null, activityWarningTime: null }, // 表单参数 form: {}, // 表单校验 rules: { germplasmName: [ { required: true, message: "种质名称不能为空", trigger: "blur" } ], cropType: [ { required: true, message: "作物种类不能为空", trigger: "change" } ], varietyTraits: [ { required: true, message: "品种特性不能为空", trigger: "blur" } ], origin: [ { required: true, message: "来源地不能为空", trigger: "blur" } ], storageStatus: [ { required: true, message: "储存状态不能为空", trigger: "change" } ], storageLocation: [ { required: true, message: "储存位置不能为空", trigger: "blur" } ], stock: [ { required: true, message: "库存不能为空", trigger: "blur" } ], entryTime: [ { required: true, message: "入库时间不能为空", trigger: "blur" } ], expirationDate: [ { required: true, message: "保质期不能为空", trigger: "blur" } ], activityStatus: [ { required: true, message: "活性状态不能为空", trigger: "change" } ], activityWarningTime: [ { required: true, message: "活性预警时间不能为空", trigger: "blur" } ] }, // 实验申请弹窗控制 experimentOpen: false, // 实验申请表单 experimentForm: {}, // 实验申请表单校验 experimentRules: { experimentPurpose: [ { required: true, message: "实验目的不能为空", trigger: "blur" } ], applicationAmount: [ { required: true, message: "申请用量不能为空", trigger: "blur" }, { type: 'number', message: '申请用量必须为数字值', trigger: "blur" } ], unit: [ { required: true, message: "用量单位不能为空", trigger: "change" } ], experimentCycle: [ { required: true, message: "实验周期不能为空", trigger: "blur" } ], breederName: [ { required: true, message: "育种员姓名不能为空", trigger: "blur" } ] }, // 领取申请弹窗控制 collectOpen: false, // 领取申请表单 collectForm: {}, // 领取申请表单校验 collectRules: { collectPurpose: [ { required: true, message: "领取用途不能为空", trigger: "blur" } ], collectAmount: [ { required: true, message: "领取用量不能为空", trigger: "blur" }, { type: 'number', message: '领取用量必须为数字值', trigger: "blur" } ], unit: [ { required: true, message: "用量单位不能为空", trigger: "change" } ], institutionName: [ { required: true, message: "机构名称不能为空", trigger: "blur" } ] } } }, created() { this.getList() }, methods: { /** 查询农作物种质资源列表 */ getList() { this.loading = true listCrop_germ_resources(this.queryParams).then(response => { this.Crop_germ_resourcesList = response.rows this.total = response.total this.loading = false }) }, // 取消按钮 cancel() { this.open = false this.reset() }, // 表单重置 reset() { this.form = { id: null, germplasmName: null, cropType: null, varietyTraits: null, origin: null, storageStatus: null, storageLocation: null, stock: null, entryTime: null, expirationDate: null, activityStatus: null, activityWarningTime: null } this.resetForm("form") }, /** 搜索按钮操作 */ handleQuery() { this.queryParams.pageNum = 1 this.getList() }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm") this.handleQuery() }, // 多选框选中数据 handleSelectionChange(selection) { this.ids = selection.map(item => item.id) this.single = selection.length!==1 this.multiple = !selection.length }, /** 新增按钮操作 */ handleAdd() { this.reset() this.open = true this.title = "添加农作物种质资源" }, /** 修改按钮操作 */ handleUpdate(row) { this.reset() const id = row.id || this.ids getCrop_germ_resources(id).then(response => { this.form = response.data this.open = true this.title = "修改农作物种质资源" }) }, /** 提交按钮 */ submitForm() { this.$refs["form"].validate(valid => { if (valid) { if (this.form.id != null) { updateCrop_germ_resources(this.form).then(response => { this.$modal.msgSuccess("修改成功") this.open = false this.getList() }) } else { addCrop_germ_resources(this.form).then(response => { this.$modal.msgSuccess("新增成功") this.open = false this.getList() }) } } }) }, /** 删除按钮操作 */ handleDelete(row) { const ids = row.id || this.ids this.$modal.confirm('是否确认删除农作物种质资源编号为"' + ids + '"的数据项?').then(function() { return delCrop_germ_resources(ids) }).then(() => { this.getList() this.$modal.msgSuccess("删除成功") }).catch(() => {}) }, /** 导出按钮操作 */ handleExport() { this.download('crop/Crop_germ_resources/export', { ...this.queryParams }, `Crop_germ_resources_${new Date().getTime()}.xlsx`) }, /** 实验申请按钮操作 */ handleExperimentApply(row) { // 获取最新的实验申请ID import("@/api/application/Exp_applications").then(api => { api.listExp_applications({ pageNum: 1, pageSize: 1 }).then(response => { let newId = 1; if (response.rows && response.rows.length > 0) { newId = response.rows[0].id + 1; } this.experimentForm = { id: newId, applicationTime: this.parseTime(new Date(), '{y}-{m}-{d}'), germplasmName: row.germplasmName, experimentPurpose: null, applicationAmount: null, unit: null, experimentCycle: null, breederName: this.$store.state.user.name || '' // 从用户信息中获取育种员姓名 }; this.experimentOpen = true; this.selectedRow = row; // 保存当前行信息用于校验库存 }); }); }, /** 领取申请按钮操作 */ handleCollectApply(row) { // 获取最新的领取申请ID import("@/api/application/Collect_applications").then(api => { api.listCollect_applications({ pageNum: 1, pageSize: 1 }).then(response => { let newId = 1; if (response.rows && response.rows.length > 0) { newId = response.rows[0].id + 1; } this.collectForm = { id: newId, applicationTime: this.parseTime(new Date(), '{y}-{m}-{d}'), germplasmName: row.germplasmName, collectPurpose: null, collectAmount: null, unit: null, institutionName: this.$store.state.user.dept?.deptName || '' // 从用户信息中获取机构名称 }; this.collectOpen = true; this.selectedRow = row; // 保存当前行信息用于校验库存 }); }); }, /** 提交实验申请 */ submitExperimentForm() { this.$refs["experimentForm"].validate(valid => { if (valid) { // 校验申请用量不能大于库存 if (this.experimentForm.applicationAmount > this.selectedRow.stock) { this.$modal.msgError("申请用量不能大于库存"); return; } // 处理实验周期,确保带有"天"单位 let experimentCycle = this.experimentForm.experimentCycle; if (experimentCycle && !experimentCycle.toString().endsWith('天')) { experimentCycle += '天'; } // 调用API将数据保存到Exp_applications表 import("@/api/application/Exp_applications").then(api => { const formData = { ...this.experimentForm, experimentCycle: experimentCycle }; api.addExp_applications(formData).then(response => { this.$modal.msgSuccess("实验申请提交成功"); this.experimentOpen = false; this.$refs["experimentForm"].resetFields(); }).catch(error => { this.$modal.msgError("实验申请提交失败"); console.error(error); }); }); } }); }, /** 提交领取申请 */ submitCollectForm() { this.$refs["collectForm"].validate(valid => { if (valid) { // 校验领取用量不能大于库存 if (this.collectForm.collectAmount > this.selectedRow.stock) { this.$modal.msgError("领取用量不能大于库存"); return; } // 调用API将数据保存到Collect_applications表 import("@/api/application/Collect_applications").then(api => { api.addCollect_applications(this.collectForm).then(response => { this.$modal.msgSuccess("领取申请提交成功"); this.collectOpen = false; this.$refs["collectForm"].resetFields(); }).catch(error => { this.$modal.msgError("领取申请提交失败"); console.error(error); }); }); } }); }, /** 取消实验申请 */ cancelExperiment() { this.experimentOpen = false; this.$refs["experimentForm"].resetFields(); }, /** 取消领取申请 */ cancelCollect() { this.collectOpen = false; this.$refs["collectForm"].resetFields(); }, /** 生成ID(模拟) */ generateId() { // 实际应用中应该从后端获取最新ID return 'APP' + new Date().getTime(); } } } </script> 育种员身份只能看到这个页面的实验申请按钮,合作农科院机构只看到这个页面的领取申请按钮,怎么设置?
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值