需求:为了支持运维的高效率工作,需要新增,编辑,归档事项,事项中又包括了task1,task2,task3......在任务项中又包括了要做的各种编辑项,新增项,先几个图来介绍下:
1.新增事项:通过弹窗填写新增的事项,其中包括了提交时做的各种校验
2.事项列表,包括编辑事项和新增的任务的操作项,(不要问我为什么没有删除项,这里的设计是在我们点击编辑时。有一列“事项状态”,可以更改里面的事项状态来达到删除的作用)
其中还,每个展开行中都会有一个表格,通过点击事项名称或者 “新增任务”按钮 可展开行
3.新增任务:这里给出的需求是在原来有的事项中去新增子事项,我们这里称新任务,那么就是需要新增一行表格,并且表格内要有对应的填写项,而且是可以指定是在任务的前面还是末尾添加一行表格;
4.编辑事项/任务:这两个项时比较相似的,也就是点击编辑可改当前事项的内容
分析: 用到vxe-table,里面比较相像的是tree结构和展开行,但是对于这两种,我们还是选择展开行内嵌入表格。找个主要是考虑展开行的数据是一个有自己表头的单独表格。然后后端返回的数据中也不好定义parentId和自己的id。同时我们这边来看一下后端的数据输出格式:
那就是集展开行、编辑、树形表格于一体,下面我们来直接上代码
结构这块我们可以这样实现: `
<vxe-table ref="xTable" border show-overflow show-header-overflow :column-config="{resizable: true}"
:loading="editData.loading" :data="editData.tableData" class="event-style" keep-source
:row-class-name="eventRowClass" :expand-config="{labelField: 'qe_event_name'}"
:edit-config="{trigger: 'manual', mode: 'row'}" :tooltip-config="editData.tableTooltipConfig">
<!-- @edit-closed="cancelRowEvent" -->
<vxe-column field="qe_event_name" title="事项" type="expand">
<!-- 展开行 -->
<template #content="{row:eventRow,rowIndex:eventRowIndex}">
<vxe-table border :ref="(el)=>setItemRef(el, 'tree'+eventRow.qe_event_index)" show-overflow
keep-source show-header-overflow :data="eventRow.qe_task_list"
:column-config="{resizable: true}" :edit-config="{trigger: 'manual', mode: 'row'}"
style="padding: 20px;" :tooltip-config="editData.taskTooltipConfig">
<!-- @edit-closed="cancelRowTask(eventRow.qe_event_index)" -->
<vxe-column field="qt_task_name" title="任务" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qt_task_name" type="text" placeholder="请输入"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qt_task_oper" title="跟进人" :edit-render="{}" width="100">
<template #edit="{ row }">
<vxe-input v-model="row.qt_task_oper" type="text" placeholder="请输入"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qt_task_progress" title="进度描述" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qt_task_progress" type="text"
placeholder="请输入"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qt_task_status" title="任务状态" :edit-render="{}" width="100">
<template #default="{ row }">
<el-tag v-if="row.qt_task_status" :type="tagType(row.qt_task_status)">
{{row.qt_task_status}}
</el-tag>
</template>
<template #edit="{ row }">
<vxe-select v-model="row.qt_task_status " transfer>
<vxe-option v-for="(item,idx) in editData.taskOption" :key="idx+100000"
:value="item" :label="item"></vxe-option>
</vxe-select>
</template>
</vxe-column>
<vxe-column field="qt_task_estimate" title="预计完成日期" :edit-render="{}" width="125">
<template #edit="{ row }">
<vxe-input v-model="row.qt_task_estimate " type="date" placeholder="请选择日期"
transfer></vxe-input>
</template>
</vxe-column>
<vxe-column field="qt_task_link" title="相关链接" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qt_task_link" type="text"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qt_task_create" title="任务创建日期" width="125">
</vxe-column>
<vxe-column title="操作" align="center" width="160" fixed="right">
<template #default="{ row }">
<template v-if="isEditTask(eventRow.qe_event_index,row)">
<el-button size="small" type="primary"
@click="saveRowTask(eventRow,row,eventRowIndex)">保存</el-button>
<el-button size="small"
@click="cancelRowTask(eventRow.qe_event_index)">取消</el-button>
</template>
<template v-else>
<el-button @click="editRowTask(eventRow,row)">编辑任务</el-button>
</template>
</template>
</vxe-column>
</vxe-table>
<!-- 展开行终止 -->
</template>
<template #edit="{ row}">
<vxe-input v-model="row.qe_event_name " type="text"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_creator" title="创建人" :edit-render="{}" width="100">
<template #edit="{ row }">
<vxe-input v-model="row.qe_event_creator " type="text" placeholder="创建人"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_detail" title="事项描述" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qe_event_detail " type="text" placeholder="事项描述"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_progress" title="进度描述" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qe_event_progress" type="text" placeholder="进度描述"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_status" title="事项状态" :edit-render="{}" width="100">
<template #default="{ row }">
<!-- <span>{{row.qe_event_status}}</span> -->
<el-tag v-if="row.qe_event_status" :type="tagType(row.qe_event_status)">
{{row.qe_event_status}}
</el-tag>
</template>
<template #edit="{ row }">
<vxe-select v-model="row.qe_event_status" transfer placeholder="事项状态">
<vxe-option v-for="(item,idx) in editData.eventOption" :key="idx+1000" :value="item"
:label="item"></vxe-option>
</vxe-select>
</template>
</vxe-column>
<vxe-column field="qe_event_estimate" title="预计完成日期" :edit-render="{}" width="125">
<template #edit="{ row }">
<vxe-input v-model="row.qe_event_estimate " type="date" placeholder="日期"
transfer></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_link" title="相关链接" :edit-render="{}">
<template #edit="{ row }">
<vxe-input v-model="row.qe_event_link " type="text" placeholder="多个链接用分号分隔"></vxe-input>
</template>
</vxe-column>
<vxe-column field="qe_event_create" title="任务创建日期" width="120">
</vxe-column>
<vxe-column title="操作" align="center" width="200" fixed="right">
<template #default="{ row }">
<template v-if="$refs.xTable.isEditByRow(row)">
<el-button size="small" type="primary" @click="saveRowEvent(row)">保存</el-button>
<el-button size="small" @click="cancelRowEvent()">取消</el-button>
</template>
<template v-else>
<el-button type="info" size="small" plain @click="editRowEvent(row)">编辑事项</el-button>
<el-button type="success" size="small" plain @click="addTaskEvent(row)">新增任务</el-button>
</template>
</template>
</vxe-column>
</vxe-table>`
初始化定义:
const editData = reactive({
loading: false,
tableData: [
],
taskOption: ["未开始", "进行中", "已完成", "暂停"],
eventOption: ["未开始", "进行中", "已完成", "暂停", "归档"],
tableTooltipConfig: {
howAll: true,
enterable: true,
theme: 'light',
// contentMethod: ({ type, column, row, items, _columnIndex }) => {
// const { field } = column
// if (!field) {
// return
// }
// if (field == 'qe_event_link') {
// let arrLink = row[field].split(';')
// return arrLink.join('\n')
// }
// //return row[field]
// }
},
taskTooltipConfig: {
howAll: true,
enterable: true,
theme: 'light',
}
})
const xTable = ref()
在结构中我们可以观察到有动态树的存在,我们是这么解决的:
if (el) {
iframeRefs[key] = el
}
};
const iframeRefs = {}`
对于事件的操作:
//编辑事项
const editRowEvent = (row) => {
const $table = xTable.value
$table.setEditRow(row)
}
//保存事项
const saveRowEvent = (row) => {
const $table = xTable.value
$table.clearEdit().then(() => {
editData.loading = true
setTimeout(() => {
editData.loading = false
let obj = {
qe_event_index: row.qe_event_index,
qe_event_name: row.qe_event_name,
qe_event_creator: row.qe_event_creator,
qe_event_detail: row.qe_event_detail,
qe_event_estimate: row.qe_event_estimate,
qe_event_link: row.qe_event_link,
qe_event_status: row.qe_event_status,
qe_event_progress: row.qe_event_progress
//task_list: row.task_list
}
create_event(obj).then(res => {
if (res.code == 200) {
ElMessage.success(res.message)
getTable();
} else {
ElMessage.error(res.message)
}
})
}, 300)
})
}
//取消保存事项
const cancelRowEvent = () => {
const $table = xTable.value
$table.clearEdit().then(() => {
// 还原行数据
$table.revertData()
})
}
//新增任务
const addTaskEvent = async (row) => {
const $fatable = xTable.value
if (!$fatable.isExpandByRow(row)) {
await $fatable.toggleRowExpand(row)
}
const $table = iframeRefs['tree' + row.qe_event_index]
const record = {
qt_task_name: '',
qt_task_oper: '',
qt_task_progress: '',
qt_task_status: '',
qt_task_create: '',
qt_task_estimate: '',
qt_task_link: ''
}
const { row: newRow } = await $table.insertAt(record, row.qe_task_list[0])
await $table.setEditCell(newRow,)
await $table.setEditRow(newRow);
}
//编辑任务
const editRowTask = (frow, row) => {
const $table = iframeRefs['tree' + frow.qe_event_index]
currentTaskRowKey.value = row.qt_task_index;
$table.setEditRow(row)
}
//保存任务
const saveRowTask = (frow, row, eventRowIndex) => {
fatherRow.value = frow;
let task_list_name = frow.qe_task_list.map(item => {
return item.qt_task_name
})
if (row.qt_task_name == '') {
ElMessage.error('任务名称不能为空')
return;
}
//新增下的任务
if (!row.qt_task_index) {
if (task_list_name.indexOf(row.qt_task_name) != -1) {
ElMessage.warning('新增的任务有重新啦!')
return;
}
}
//编辑任务
// if (row.qt_task_index == currentTaskRowKey.value) {
// let flagFtype = task_list_others.value.every((item) => !!item.qt_task_name);
// if (flagFtype) {
// ElMessage.warning('修改后的任务名已经存在啦!')
// return;
// }
// }
const $table = iframeRefs['tree' + frow.qe_event_index]
$table.clearEdit().then(() => {
setTimeout(() => {
let obj = {
findex: row.qt_task_index ? row.qt_task_index : '',
ops_event: frow.qe_event_name,
ops_task: row.qt_task_name,
ops_person: row.qt_task_oper,
fprogress: row.qt_task_progress,
ftask_status: row.qt_task_status,
festimate_time: row.qt_task_estimate,
flink: row.qt_task_link,
}
edit_save(obj).then(res => {
if (res.code == 200) {
ElMessage.success(res.message)
getTable();
setTimeout(() => {
// xTable.value.setAllRowExpand(true)
//console.log(fatherRow.value, 'fatherRow.valuefatherRow.valuefatherRow.value');
xTable.value.setRowExpand(editData.tableData[eventRowIndex], true)
}, 300)
} else {
ElMessage.error(res.message)
}
})
}, 100)
})
}
//取消保存任务
const cancelRowTask = async (key) => {
const $table = iframeRefs['tree' + key]
await $table.clearEdit().then(() => {
// 还原行数据
$table.revertData()
})
}