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));
}
},
效果图:
文章来源地址https://www.toymoban.com/news/detail-613068.html
文章来源:https://www.toymoban.com/news/detail-613068.html
到了这里,关于Element UI Table实现可编辑表格+校验(行和行,列和列)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!