一、需求
点击表格操作列的操作按钮,弹出弹窗确认后可复制该行数据,表格随之增加一行
二、思路(自己做的有点笨)
- 点击操作列的按钮时都会获取到当前行的信息;
- 在按钮的点击函数中控制复制弹窗的显示,定义一个收集表单信息的对象,里面的字段和你表格的需要一致;
- 将点击某一行后拿到的该行的数据进行修改,因为复制的信息不能和原本的一样需要做区别,修改之后直接赋值给对象的对应字段,这样点击确认时就能得到和原来的行一样的数据;
- 最后将新复制的数据在submit的函数中保存到后端
三、实现
这里table是子组件进行引入
<div class="table">
<Table :columns="tableColumns" :data="equipmenytArray" :tabletype="tableType" :operationsButtons="buttonsData"
:total="pageTotal" @showComponents="showComponents"></Table>
</div>
父组件中的showComponents函数:
//根据操作按钮展示不同组件
const showComponents = (val,index)=>{
console.log('子btns',val,index)//val就是点击的该行的信息
if(val.label == '查看'){
router.push({
path:'/detail/index',
// name:'数据详情',
query: {
id:val.id || val.projectID,
}
})
}
if(val.label == '删除'){
ElMessageBox.confirm('确定要删除嘛?', '提示', {
confirmButtonText: '删除',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
//从表格中删除对应数据
equipmenytArray.value = equipmenytArray.value.filter(obj => obj.id !== val.id)
pageTotal.value = equipmenytArray.value.length
store.commit('Del_EquipmentID',val.id)
//调用接口删除数据库中的数据
deleteEquipment(val.id)
}).catch(() => {
});
}
if(val.label == '复制'){
copyShow.value = true
//对id和name进行修改以便区别
dialogtitle.value = '复制设备信息'
const equipID = val.id + '_1'
const equipName = val.name + '_1'
const createTime = getCurrentDate() //创建时间
//这里我不仅需要复制这一行,还有这一行代表的设备的附带所有设备属性,是一个单独的表格内容
getEquipAttrs(val.id).then((response)=>{
console.log(response.data)
response.data.data.id = equipID
saveEquipAttrs(response.data.data).then((res)=>{
// console.log(res.data)
store.commit('SET_AttrsData',res.data.attrs)
})
console.log('导入成功')
// ElMessage.success('复制成功')
})
//这是定义的收集表单的对象,当复制弹窗弹出时里面默认会有id和name,可自行修改,addTime是当前时间,其他字段都是和原来的行数据一样的
const indexgroupData = {
id:equipID,
name:equipName,
deviceSuper:val.deviceSuper,
addTime:createTime,
creator:val.creator,
manufacturers:val.manufacturers,
modelNumber:val.modelNumber,
}
//传递给子组件
formData.value = indexgroupData
}
}
父组件的submit函数,这里提交弹窗收集的表单数据并调用接口进行存储
//提交新建表单
const handleSubmit = async () => {
console.log('formData',formData.value)
attrDevice.value.push({
label:formData.value.id,
value:formData.value.name,
})
dialogVisible.value = false
importdialogVisible.value = false
copyShow.value = false
//因为每个操作按钮提交表单不一样所以做个判断
//提交的是新建表单进行保存
if(!formData.value.hasOwnProperty('attrs') ){
saveEquipmentInfo(formData.value).then(response=>{
console.log(response.data)
equipmenytArray.value.push(response.data)
store.commit('SET_EquipmentData',equipmenytArray.value)
store.commit('SET_EquipmentID',response.data.id)
pageTotal.value = equipmenytArray.value.length
}).catch((error)=>{
console.error('请求出错',error)
})
}else{ //提交的是属性表单
// store.commit('SET_AttrsData',formData.value.attrs)
let resultAttrs = await saveEquipAttrs(formData.value)
console.log('resultAttrs',resultAttrs)
store.commit('SET_AttrsData',resultAttrs.data.attrs)
ElMessage.success('导入成功')
}
}
四、所有代码
- table的
<template>
<div>
<el-table :data="tableData" :row-key="getRowKey" :default-sort="{ prop: 'id', order: 'ascending' } "
selection-type="multiple" @selection-change="handleSelectionChange" ref="table"
:row-class-name="rowStyle" id="eltable" max-height="450px" :header-cell-style="{background:'#f5f5f5'}">
<el-table-column :type="tabletype" width="55" align="center"></el-table-column>
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label"
:width="column.width" :filters="column.filters" :filter-method="filterMethod">
</el-table-column>
<el-table-column label="操作" width="180" v-if="showOperate" fixed="right">
<template #default="{ row , $index }">
<el-button-group class="btns">
<el-button v-for="button in operationsButtons" :key="button.label" size="small"
:style="button.style" @click="() => handleOperation(row, button, $index)">
<template v-if="button.type == 'text'">
{{ button.label }}
</template>
<template v-if="button.type == 'img'">
<img :src="button.icon" style="width:18px;height:18px;" />
</template>
</el-button>
</el-button-group>
</template>
</el-table-column>
</el-table>
<div>
<!-- 分页 -->
<el-pagination :locale="locale" background class="pagination" small :page-sizes="pageSizesArr"
@size-change="sizeChange" @current-change="currentChange" :current-page="current" :page-size="size"
:total="total" :layout="layout" />
</div>
</div>
</template>
<script setup>
// import { setStore} from '../../utils/store'
// import {ElMessageBox } from 'element-plus';
import { ref, computed, defineProps, onMounted } from 'vue';
const table = ref(null)
const size = ref(10)
const selectedRows = ref([]);
const dialogVisible = ref(false)
//接收父组件传递过来的数据
const props = defineProps({
columns: {
type: Array,
required: true,
},
tabletype:{
type:String,
default:'',
},
data: {
type: Array,
required: true,
},
operationsButtons: {
type: Array,
required: true,
default:''
},
total: {
type: Number,
// 类型
required: true,
default: 0,
},
// 分页的页容量数组
pageSizesArr: {
type: Array,
default() {
return [10, 20, 30, 50];
},
},
// 分页的布局
layout: {
type: String,
default: "total, sizes, prev, pager, next, jumper",
},
showOperate: {
type: Boolean,
default: true,
},
});
//通过emits 和父组件进行通信
const emits = defineEmits(["sizeChange", "currentChange", "openDrawer",'showComponents']);
function handleSelectionChange(selection) {
selectedRows.value = selection;
}
const tableData = computed(() => props.data);
onMounted(()=>{
// console.log(table.value.getSelectionRows())
})
// 处理操作按钮点击事件
function handleOperation(row, button ,index) {
// console.log(index)
dialogVisible.value = true
row.label = button.label
console.log('row',row)
emits("showComponents", row,index);
}
function getRowKey(row) {
return row.id;
}
// 页数改变的时候触发的事件
const sizeChange = (val) => {
emits("sizeChange", val);
}
// 当前页改变的时候触发的事件
const currentChange = (val) => {
emits("currentChange", val);
}
//可忽略,这是我在另一个页面引用这个子组件所需要的
const rowStyle = ({row})=>{
// console.log(row)
if(row.alarmLevel=== '一级'){
return 'alarm-one-level'
}else if(row.alarmLevel=== '二级'){
return 'alarm-two-level'
}else if(row.alarmLevel=== '三级'){
return 'alarm-three-level'
}
}
const filterMethod =(value,row,column)=>{
const property = column['property']
return row[property] === value
}
</script>
<style>
.pagination {
float: right;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
.el-table .alarm-one-level{
color: #DC143C;
/* background-color:#DC143C; */
}
.el-table .alarm-two-level{
color: #FFD700;
/* background-color: #FFD700; */
}
.el-table .alarm-three-level{
color: #F4A460;
/* background-color: #F4A460; */
}
.btns{
display: flex;
margin-right: 5px;
}
</style>
- 父组件
<template>
<div>
<div class="table">
<Table :columns="tableColumns" :data="equipmenytArray" :tabletype="tableType" :operationsButtons="buttonsData"
:total="pageTotal" @showComponents="showComponents"></Table>
</div>
</div>
<DialogForm v-model="dialogVisible" :dialogtitle="dialogtitle" v-model:form-data="formData"
@submit="handleSubmit" :formItems="formItems" :selectData="selectData" :propertyData="dataOfTree"/>
<ImportDialog v-model="importdialogVisible" :dialogtitle="importdialogtitle" v-model:form-data="formData"
@submit="handleSubmit" :formItems="attributeItems">
</ImportDialog>
//这里不需要再引入一个dialog,用上面DialogForm 这个即可,可删除这一部分多余了。然后在showComponents 的复制if中,直接用dialogVisible、dialogtitle、formItems这几个变量即可
<CopyForm v-model="copyShow" :dialogtitle="dialogtitle" v-model:form-data="formData"
@submit="handleSubmit" :formItems="copyInfoItems"></CopyForm>
</template>
<script setup>
import { useStore } from "vuex"
import { ref, onMounted } from 'vue'
import { useRouter} from 'vue-router'
import { getStore,setStore } from "utils/store";
import Table from './TableComponent.vue'
// import detailTable from "./detailTable.vue"
import ImportDialog from './importDialog.vue'
import {ElMessageBox,ElMessage} from 'element-plus'
import { generateUniqueCode } from '../../utils/uuid'
import { getCurrentDate } from '../../utils/datehandle.mjs'
import CopyForm from '../../components/dialog/addDialog.vue'
import { handleTreeData } from '../../utils/arrayTotreeData'
import DialogForm from '../../components/dialog/addDialog.vue'
import { formItemsDevice,copyInfoItems } from './staticConfigData/powerstation'
import { saveEquipmentInfo, delDeviceById, getAllProperty,saveEquipAttrs ,getEquipAttrs} from '@/api/equipmentManageApi'
//变量定义
const dialogtitle = ref('') //模态框标题
const dialogVisible = ref(false)//模态框显示与否
const equipmenytArray = ref([]) //设备
const formItems = ref([]) //模态框组件各个小组件标签
const formData = ref({}) //模态框组件表单数据
const copyShow = ref(false) //复制模态框显示与否
// const copydialogtitle = ref('')
const attrDevice = ref([])
const dataOfTree = ref([])
const pageTotal = ref(0)
const equipmentName = ref([])
const attributeItems = ref([
{ label: "选择设备", prop: "id", type: "select" ,options:equipmentName.value},
{ label: "导入属性", prop: "attrs", type: "upload" },
])
//表格表头
const tableColumns = [
{ prop: 'id', label: '标识',width:120 },
{ prop: 'name', label: '设备名称',width:200 },
{ prop: 'deviceSuper', label: '所属资产',width:250 },
{ prop: 'manufacturers', label: '厂家',width:220 },
{ prop: 'modelNumber', label: '型号',width:120 },
{ prop: 'addTime', label: '新增时间',width:200 },
{ prop: 'creator', label: '创建人',width:120 },
];
//表格操作按钮,表格的操作按钮可由父组件传入,数量,图标,大小可自定义
const buttonsData = [
{ label: '查看', type: 'img', style:'border-radius:3px;width:20px;margin:0px 5px', icon: '/img/check.png' },
{ label: '编辑', type: 'img', style:'border-radius:3px;width:20px;margin:0px 5px', icon: '/img/edit.png' },
{ label: '删除', type: 'img', style:'border-radius:3px;width:20px;margin:0px 5px', icon: '/img/del.png' },
{ label: '复制', type: 'img', style:'border-radius:3px;width:20px;margin:0px 5px', icon: '/img/copy.png' },
]
onMounted(()=>{
const handledata = store.state.project.projectData
dataOfTree.value = handleTreeData(handledata)
console.log('dataOfTree',dataOfTree.value)
const allId = getStore({ name:'equipmentID' })
getData(allId)
})
//下拉选择框事件
const changeSelectValue = (val)=>{
inputPlaceholder.value = val
}
//获取数据
const getData = async (id) =>{
console.log(id)
let result = await getAllProperty(id)
console.log('result',result)
if(Array.isArray(result.data)){
equipmenytArray.value = result.data
equipmenytArray.value.map(item=>{
equipmentName.value.push({
label:item.name,
value:item.id
})
})
}
store.commit('SET_EquipmentData',equipmenytArray.value)
}
//新增设备
const addDevice = ()=>{
dialogVisible.value = true
dialogtitle.value = '新增设备'
const uniquecode = generateUniqueCode() //设备唯一标识
const createTime = getCurrentDate() //创建时间
const creator = store.state.user.userInfo.username //获取当前用户
const indexgroupData = { pip:'2', id: uniquecode ,name:'',deviceSuper:'',manufacturers:'' ,modelNumber:'',addTime:createTime,creator:creator}
formItems.value = formItemsDevice
formData.value = indexgroupData
}
//提交新建表单
const handleSubmit = async () => {
console.log('formData',formData.value)
attrDevice.value.push({
label:formData.value.id,
value:formData.value.name,
})
dialogVisible.value = false
importdialogVisible.value = false
copyShow.value = false
//提交的是新建表单进行保存
if(!formData.value.hasOwnProperty('attrs') ){
saveEquipmentInfo(formData.value).then(response=>{
console.log(response.data)
equipmenytArray.value.push(response.data)
store.commit('SET_EquipmentData',equipmenytArray.value)
store.commit('SET_EquipmentID',response.data.id)
pageTotal.value = equipmenytArray.value.length
}).catch((error)=>{
console.error('请求出错',error)
})
}else{ //提交的是属性表单
// store.commit('SET_AttrsData',formData.value.attrs)
let resultAttrs = await saveEquipAttrs(formData.value)
console.log('resultAttrs',resultAttrs)
store.commit('SET_AttrsData',resultAttrs.data.attrs)
ElMessage.success('导入成功')
}
}
//删除数据
const deleteEquipment = async (id) => {
try {
await delDeviceById(id);
console.log('删除成功');
ElMessage.success('删除成功')
} catch (error) {
console.error('删除失败', error);
ElMessage.error('删除失败')
}
};
//根据操作按钮展示不同组件
const showComponents = (val,index)=>{
console.log('子btns',val,index)
if(val.label == '查看'){
router.push({
path:'/detail/index',
// name:'数据详情',
query: {
id:val.id || val.projectID,
}
})
}
if(val.label == '删除'){
ElMessageBox.confirm('确定要删除嘛?', '提示', {
confirmButtonText: '删除',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
//从表格中删除对应数据
equipmenytArray.value = equipmenytArray.value.filter(obj => obj.id !== val.id)
pageTotal.value = equipmenytArray.value.length
store.commit('Del_EquipmentID',val.id)
//调用接口删除数据库中的数据
deleteEquipment(val.id)
}).catch(() => {
});
}
if(val.label == '复制'){
dialogVisible.value = true
dialogtitle.value = '复制设备信息'
const equipID = val.id + '_1'
const equipName = val.name + '_1'
const createTime = getCurrentDate() //创建时间
getEquipAttrs(val.id).then((response)=>{
console.log(response.data)
response.data.data.id = equipID
saveEquipAttrs(response.data.data).then((res)=>{
// console.log(res.data)
store.commit('SET_AttrsData',res.data.attrs)
})
console.log('导入成功')
// ElMessage.success('复制成功')
})
const indexgroupData = {
id:equipID,
name:equipName,
deviceSuper:val.deviceSuper,
addTime:createTime,
creator:val.creator,
manufacturers:val.manufacturers,
modelNumber:val.modelNumber,
}
formData.value = indexgroupData
//copyInfoItems这个是单独定义在一个js中引入的
formItems.value = copyInfoItems
}
}
//导入单个设备属性
const importAttr = ()=>{
importdialogVisible.value = true
importdialogtitle.value = '导入设备属性'
}
//批量导入设备属性
const importAttrs = () =>{
importdialogVisible.value = true
importdialogtitle.value = '批量导入设备属性'
attributeItems.value[0].type = 'mulselect'
const deviceData = store.state.project.equipmentData
const handledata = store.state.project.projectData
const multiSelect = handleTreeData(deviceData)
console.log('deviceData',deviceData)
console.log('multiSelect',multiSelect)
}
</script>
<style scoped lang="scss">
.search{
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 10px;
.btns{
margin-left: 10px;
}
}
</style>
const copyInfoItems = [
{ label: "设备标识", prop: "id", type: "input" },
{ label: "设备名称", prop: "name", type: "input" },
];