Element UI Table实现可编辑表格+校验(行和行,列和列)

Table:

<template>
  <div class="as-details-section">
    <span class="title">任务分解表</span>
    <div class="as-detail-list">
      <el-table
        :data="tableData"
        :row-key="getRowKeys"
        border
        style="width: 100%">
        <el-table-column
          prop="stageName"
          label="阶段"
          width="120">
        </el-table-column>
        <el-table-column
          prop="taskName"
          label="任务"
          width="190">
        </el-table-column>
        <el-table-column
          prop="planStartTime"
          label="计划开始时间"
          className="editable"
          width="120">
          <template slot-scope="{ row, column, $index }">
            <table-date-picker
              v-if="row.isTask && !row.isDisabled"
              v-model="row.planStartTime"
              :valueValid="row.planStartTimeValid"
              :valueEmpty="row.planStartTimeEmpty"
              @change="change(row, column, $index)"
              @blur="onBlur(row, column)">
            </table-date-picker>
            <span v-else class="cell-value">{{row.planStartTime | dateFormat}}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="planEndTime"
          label="计划结束时间"
          className="editable"
          width="120">
          <template slot-scope="{ row, column, $index }">
            <table-date-picker
              v-if="row.isTask && !row.isDisabled"
              v-model="row.planEndTime"
              :valueValid="row.planEndTimeValid"
              :valueEmpty="row.planEndTimeEmpty"
              isEndDate
              @change="change(row, column, $index)"
              @blur="onBlur(row, column)">
            </table-date-picker>
            <span v-else class="cell-value">{{row.planEndTime | dateFormat}}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="actualStartTime"
          label="实际开始"
          className="editable"
          width="120">
          <template slot-scope="{ row, column, $index }">
            <table-date-picker
              v-if="row.isTask && !row.isDisabled"
              v-model="row.actualStartTime"
              :valueValid="row.actualStartTimeValid"
              :valueEmpty="row.actualStartTimeEmpty"
              :disabled="row.isActualDisabled"
              :pickerOptions="pickerOptions"
              @change="changeRealDate(row, column, $index)">
            </table-date-picker>
            <span v-else class="cell-value">{{row.actualStartTime | dateFormat}}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="actualEndTime"
          label="实际结束"
          className="editable"
          width="120">
          <template slot-scope="{ row, column, $index }">
            <table-date-picker
              v-if="row.isTask && !row.isDisabled"
              v-model="row.actualEndTime"
              :valueValid="row.actualEndTimeValid"
              :valueEmpty="row.actualEndTimeEmpty"
              :disabled="row.isActualDisabled"
              :pickerOptions="pickerOptions"
              isEndDate
              @change="changeRealDate(row, column, $index)">
            </table-date-picker>
            <span v-else class="cell-value">{{row.actualEndTime | dateFormat}}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="projectWbsTaskResourceList"
          label="资源及投入比例"
          min-width="200">
          <template slot-scope="{ row, column, $index }">
            <table-person-picker
              v-if="row.isTask && !row.isDisabled"
              v-model="row.projectWbsTaskResourceList"
              :projectWbsTrackId="row.id"
              :valueEmpty="row.projectWbsTaskResourceListEmpty"
              @change="percentChange(row, column, $index)"
              @blur="onBlur(row, column)"
            ></table-person-picker>
            <span v-else class="cell-value">{{ resourceFormat(row.projectWbsTaskResourceList) }}</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="planWorkHour"
          label="预计工时(天)"
          width="120">
        </el-table-column>
        <el-table-column
          prop="actualWorkHour"
          label="实际工时(天)"
          width="120">
        </el-table-column>
        <el-table-column
          prop="planWorkDay"
          label="预计工期(天)"
          width="120">
        </el-table-column>
        <el-table-column
          prop="actualWorkDay"
          label="实际工期(天)"
          width="120">
        </el-table-column>
      </el-table>
    </div>
    <el-dialog
      title="流转确认"
      :visible.sync="dialogVisible"
      :close-on-click-modal="false"
      width="400px">
      <el-row v-if="!isShowRollback">确认要流转至下一阶段吗?</el-row>
      <el-row v-else>确认要流转至下一阶段吗?</el-row>
      <span slot="footer" class="dialog-footer">
        <el-button v-if="!isShowRollback" @click="dialogVisible = false">取 消</el-button>
        <el-button v-if="isShowRollback" @click="promoteProject(true)">回滚至2分</el-button>
        <el-button type="primary" @click="promoteProject()">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

TablePersonPicker:

<template>
  <div class="table-date-picker">
    <div class="cell-content-wrap">
      <span class="cell-content">{{displayValue}}</span>
      <i
        class="el-icon-edit-outline"
        style="float: right"
      ></i>
    </div>
  </div>
</template>

<script>
import TablePersonPickerDialog from '@/components/projectManagement/TablePersonPickerDialog'

export default {
  name: 'TablePersonPicker',
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: Array,
      default() {
        return [];
      }
    },
    valueValid: {
      type: Boolean,
      default() {
        return true;
      }
    },
    valueEmpty: {
      type: Boolean,
      default() {
        return false;
      }
    },
    disabled: {
      type: Boolean,
      default() {
        return false;
      }
    },
    projectWbsTrackId: {
      type: String,
      default() {
        return null;
      }
    }
  },
  data() {
    return {
      newValue: [],
      displayValue: '',
      pencentArr: []
    };
  },
  mounted() {
    // 点击表格td,编辑状态,输入框获取焦点
    this.$el.parentNode.parentNode.onclick = () => {
      if (!this.disabled) {
        this.showDialog();
      }
    }
  },
  methods: {
    showDialog() {
      this.$utils.create(TablePersonPickerDialog, {
        context: this,
        keyName: this.id,
        deliveryDept: this.options,
        value: this.value
      });
    },
    confirm(data) {
      this.pencentArr = data;
      this.displayValue = this.formatDisaplyValue();
      this.$emit('change', this.pencentArr);
    },
    getItemById(personId) {
      let item = null;
      // 新增人员
      for (const obj of this.data) {
        if (obj.personId === personId) {
          item = obj;
          break;
        }
      }
      return item;
    },
    formatDisaplyValue() {
      const displayArr = [];
      for (const item of this.pencentArr) {
        displayArr.push(`${item.personLabel}(${item.inputPercentage}%)`)
      }
      return displayArr.join(',');
    },
    formatOptions() {
      const optons = [];
      let option = null;
      for (const item of this.$store.state.DICT_DATA.delivery_dept) {
        option = {
          id: item.dictValue,
          personLabel: item.dictName,
          disabled: true
        };
        optons.push(option);
      }
      return optons;
    }
  },
  created() {
    this.options = this.formatOptions();
    let template = null;
    for (const item of this.value) {
      this.newValue.push(item.personId);
      template = {
        personId: item.personId,
        projectWbsTrackId: this.projectWbsTrackId,
        inputPercentage: item.inputPercentage,
        personLabel: item.personLabel
      };
      this.pencentArr.push(template);
    }
    this.displayValue = this.formatDisaplyValue();
  },
  watch: {
    valueEmpty() {
      if (this.valueEmpty) {
        this.$el.parentNode.parentNode.style.background = '#FEF0F0';
      } else {
        this.$el.parentNode.parentNode.style.background = 'none';
      }
    },
    valueValid() {
      if (!this.valueValid) {
        this.$el.parentNode.parentNode.style.background = '#FEF0F0';
      } else {
        this.$el.parentNode.parentNode.style.background = 'none';
      }
    }
  }
};
</script>
<style scoped lang="scss">
.table-date-picker {
  display: flex;
  flex-flow: row;
  align-items: center;
  .cell-content-wrap {
      display: flex;
      flex-flow: row;
      align-items: center;
      i {
        color: #20a0ff;
        margin-left: 8px;
        cursor: pointer;
      }
  }
  .cell-content {
    padding: 0 8px;
    flex: 1;
  }
}
</style>

输入校验:


    /**
     * 表格预计开始时间和预计结束时间注册事件
     */
    change(row, column, $index) {
      const { property } = column;
      const value = row[property];
      if ((!value || value === '') && value !== 0) {
        row[`${property}Empty`] = true;
      } else {
        row[`${property}Empty`] = false;
        // 时间发生变化,往下开始计算时间
        this.calculatePlanDate(row, column, $index);
        // 计算预计工时和预计工期
        this.caculatePlanData();
        // 任务预计开始时间小于任务结束时间
        const isValid = this.validateDate(row.planStartTime, row.planEndTime);
        if (!isValid) {
          this.$message.error('预计结束时间必须大于等于预计开始时间!');
        }
        // 任务的预计开始时间大于上一个阶段的结束时间
        const isStartDateValid = this.validateTaskStartDate(row, property, $index);
        if (!isStartDateValid) {
          this.$message.error('任务的预计开始时间和预计结束时间必须大于上一个阶段的预计结束时间');
        }
        if (isValid && isStartDateValid) {
          row[`${property}Valid`] = true;
        } else {
          row[`${property}Valid`] = false;
        }
        this.$set(this.tableData, $index, Object.assign({}, row));
      }
    },

效果图:

 

 

Element UI是一个流行的开源UI组件库,由饿了么开发,专为Vue.js应用提供丰富的前端界面解决方案。Element UI中的"可编辑表格"(Editable Table)是一个功能强大的组件,它允许用户在页面上直接修改表格中的数据,支持单元格级别的操作,比如文本输入、选择、删除等。 具体特点包括: 1. **实时更新**:对表格中的每一项数据进行编辑后,改动会被即时反映到数据模型中,无需额外提交或刷新操作。 2. **列宽自适应**:表格可以根据内容自动调整列宽,使得显示更加直观和舒适。 3. **事件处理**:提供了诸如点击、输入等事件的处理机制,方便开发者定制各种交互行为。 4. **内置验证**:对于输入的数据,可以设置校验规则,确保数据的合理性。 5. **API友好**:表格提供了丰富的API接口,用于获取数据、添加行、删除行等操作。 要使用Element UI的可编辑表格,首先需要安装Element UI库,然后在模板中引用相应的组件,并配置列定义、数据源以及是否开启编辑模式。例如: ```html <template> <el-table :data="tableData" :editable="isEditable"> <!-- 列定义 --> <el-table-column prop="name" label="姓名" width="180" /> <el-table-column prop="age" label="年龄" width="180" /> <!-- 更多列... --> </el-table> </template> <script> import { ElTable, ElTableColumn } from "element-plus"; export default { components: { ElTable, ElTableColumn, }, data() { return { tableData: [ // 数据列表... ], isEditable: true, // 是否启用编辑模式,默认为false }; }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值