增删改批量操作

双击可触发input框模式,可修改当前单元格内容,点击其他地方失去焦点input状态隐藏

修改过的行背景色变红,点击保存则取消背景色

 

 单页面所有代码假数据测试看效果版:

<template>
  <div class="custom-tree-table">
    <el-button style="margin: 2px 0;" size="mini" type="primary" @click="onAdd">+ 新增</el-button>
    <el-button style="margin: 2px 0 0 10px;" size="mini" type="success" @click="onBatchSave">保存</el-button>
    <el-button style="margin: 2px 0 0 10px;" size="mini" type="danger" @click="onBatchDelete" class="el-icon-delete"> 批量删除</el-button>
      <el-table
        :data="currentPageData"
        row-key="id"
        border
        default-expand-all
        height="508"
        :row-style="rowStyle"
        @selection-change="onSelectionChange">
        <!-- 复选框 -->
        <el-table-column width="62" align="center" type="selection" label="选择" />
        <!-- 参数ID -->
        <el-table-column label="参数ID" prop="key" min-width="250">
          <template #default="{ row }">
            <el-input 
              :value="row.key" 
              @click="onEdit(row, 'key')"
              @blur="onBlur(row, 'key')"
              v-if="row.isEditKey || row.key === ''"
              v-model="row.key" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'key')">{{ row.key }}</span>
          </template>
        </el-table-column>
        <!-- 参数名称 -->
        <el-table-column label="参数名称" prop="type" min-width="200">
          <template #default="{ row }">
            <el-input 
              :value="row.type" 
              @click="onEdit(row, 'type')"
              @blur="onBlur(row, 'type')"
              v-if="row.isEditType || row.type === ''"
              v-model="row.type" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'type')">{{ row.type }}</span>
          </template>
        </el-table-column>
        <!-- 参数描述 -->
        <el-table-column label="参数描述" prop="description" min-width="220">
          <template #default="{ row }">
            <el-input 
              :value="row.description" 
              @click="onEdit(row, 'description')"
              @blur="onBlur(row, 'description')"
              v-if="row.isEditDescription || row.description === ''"
              v-model="row.description" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'description')">{{ row.description }}</span>
          </template>
        </el-table-column>
      </el-table>
    <!-- 分页 -->
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page.sync="currentPage"
      :page-sizes="[10, 20, 30, 40]"
      :page-size="pageSize"
      :total="totalDataCount"
      layout="total, sizes, prev, pager, next, jumper"/>
  </div>
</template>

<script>
import axios from 'axios';
export default {
  data() {
    return {
      tableData: [
        { id: '1', key: 'ufnak', type: '按钮', description: 'Name of the person', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '2', key: 'fbunkjn', type: '按钮2', description: 'Age of the person', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '3', key: 'fain', type: '安牛3', description: 'Active status', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '4', key: 'key4', type: 'Type 4', description: 'Description 4', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '5', key: 'key5', type: 'Type 5', description: 'Description 5', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '6', key: 'key6', type: 'Type 6', description: 'Description 6', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '7', key: 'key7', type: 'Type 7', description: 'Description 7', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '8', key: 'key8', type: 'Type 8', description: 'Description 8', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '9', key: 'key9', type: 'Type 9', description: 'Description 9', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '10', key: 'key10', type: 'Type 10', description: 'Description 10', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '11', key: 'key11', type: 'Type 11', description: 'Description 11', isEditKey: false, isEditType: false, isEditDescription: false },
        { id: '12', key: 'key12', type: 'Type 12', description: 'Description 12', isEditKey: false, isEditType: false, isEditDescription: false },
      ],
      selectedRows: [], // 复选框
      modifiedRows: [], // 已经被修改的行的id/背景色
      // 分页
      currentPage: 1, // 前往当前页
      pageSize: 10, // 每页显示多少条
      originalValue: '', //一个变量用于记录编辑前的值
    }
  },
  computed: {
    totalDataCount() { // 计算总数据量
      return this.tableData.length;
    },
    currentPageData() { // 基于分页计算当前页面数据
      const startIndex = (this.currentPage - 1) * this.pageSize;
      const endIndex = startIndex + this.pageSize;
      return this.tableData.slice(startIndex, endIndex);
    },
  },
  methods: {
    // +新增
    onAdd() {
      const id = String(Date.now());
      const newRecord = { id, key: '', type: '', description: '', isEditKey: true, isEditType: true, isEditDescription: true };
      this.tableData.unshift(newRecord);
    },
    // 批量删除
    onBatchDelete() {
      if (this.selectedRows.length > 0) {
        this.tableData = this.tableData.filter(item => !this.selectedRows.some(row => row.id === item.id));
        this.selectedRows = []; // 清空选中的行
      }
    },
    onSelectionChange(selection) { // 复选框选择变更时触发,批量删除
      this.selectedRows = selection;
    },
    // 保存
    onBatchSave() {
      // 收集表格中所有数据
      const allData = this.tableData;
      // 发送数据给后端
      axios.post('/your-backend-endpoint', allData)
        .then(response => {
          // 处理后端返回的响应
          console.log(response.data);
        })
        .catch(error => {
          // 处理错误
          console.error('Error:', error);
        });
      // 清空已修改的行数组
      this.modifiedRows = [];
    },
   // 点击单元格进入编辑状态
   onEdit(row, field) {
      // 在进入编辑状态时记录编辑前的值
      this.originalValue = row[field];
      if (field === 'key') {
        row.isEditKey = true; // 参数ID
        row.isEditType = false; // 参数名称
        row.isEditDescription = false; // 参数描述
      } else if (field === 'type') {
        row.isEditKey = false;
        row.isEditType = true;
        row.isEditDescription = false;
      } else if (field === 'description') {
        row.isEditKey = false;
        row.isEditType = false;
        row.isEditDescription = true;
      }
    },
    // 根据编辑状态设置行样式
    rowStyle({ row }) {
      return { backgroundColor: this.modifiedRows.includes(row.id) ? '#ffcccc' : '' };
    },
    // 失去焦点时触发,隐藏输入框
    onBlur(row, field) {
      if (this.originalValue !== row[field]) {
        // 只有在值发生变化时才将当前行的 ID 添加到 modifiedRows 数组中
        if (!this.modifiedRows.includes(row.id)) {
          this.modifiedRows.push(row.id);
        }
      }
      //
      if (field === 'key') {
        row.isEditKey = false;
      } else if (field === 'type') {
        row.isEditType = false;
      } else if (field === 'description') {
        row.isEditDescription = false;
      }
      // 如果有已修改的行,并且当前行不在已修改的行中,则隐藏已修改的行的编辑状态
      this.tableData.forEach(item => {
        if (this.modifiedRows.includes(item.id) && item.id !== row.id) {
          item.isEditKey = false;
          item.isEditType = false;
          item.isEditDescription = false;
        }
      });
    },
    // 分页每页多少条
    handleSizeChange(val) {
      this.pageSize = val;
    },
    // 前往当前页
    handleCurrentChange(val) {
      this.currentPage = val;
    },
  }
}
</script>

<style scoped>
.custom-tree-table {
  height: 100%;
  background-color: #fff;
  padding: 15px;
}
/*新增按钮宽高*/
.el-button--mini{
  padding: 7px 12px;
}
/*表格每行高度*/
.custom-tree-table /deep/ .el-table__cell {
  padding: 8px;
}
/* input高度 */
::v-deep .el-input__inner{
  height: 26px
}
/* 分页器位置 */
::v-deep .el-pagination{
  display: flex;
  justify-content: flex-end;
}

/* 设置按钮颜色 */
.el-button--primary {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
.el-button--success {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
.el-button--danger {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
</style>

 单页面代码数据改成接口渲染联动版:

<template>
  <div class="custom-tree-table">
    <el-button style="margin: 2px 0;" size="mini" type="primary" @click="onAdd">+ 新增</el-button>
    <el-button style="margin: 2px 0 0 10px;" size="mini" type="success" @click="onBatchSave">保存</el-button>
    <el-button style="margin: 2px 0 0 10px;" size="mini" type="danger" @click="onBatchDelete" class="el-icon-delete"> 批量删除</el-button>
      <el-table
        :data="currentPageData"
        row-key="id"
        border
        default-expand-all
        height="508"
        :row-style="rowStyle"
        @selection-change="onSelectionChange">
        <!-- 复选框 -->
        <el-table-column width="62" align="center" type="selection" label="选择" />
        <!-- 参数ID -->
        <el-table-column label="参数ID" prop="key" min-width="250">
          <template #default="{ row }">
            <el-input 
              :value="row.key" 
              @click="onEdit(row, 'key')"
              @blur="onBlur(row, 'key')"
              v-if="row.isEditKey || row.key === ''"
              v-model="row.key" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'key')">{{ row.key }}</span>
          </template>
        </el-table-column>
        <!-- 参数名称 -->
        <el-table-column label="参数名称" prop="type" min-width="200">
          <template #default="{ row }">
            <el-input 
              :value="row.type" 
              @click="onEdit(row, 'type')"
              @blur="onBlur(row, 'type')"
              v-if="row.isEditType || row.type === ''"
              v-model="row.type" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'type')">{{ row.type }}</span>
          </template>
        </el-table-column>
        <!-- 参数描述 -->
        <el-table-column label="参数描述" prop="description" min-width="220">
          <template #default="{ row }">
            <el-input 
              :value="row.description" 
              @click="onEdit(row, 'description')"
              @blur="onBlur(row, 'description')"
              v-if="row.isEditDescription || row.description === ''"
              v-model="row.description" 
              placeholder="请输入"/>
            <span v-else @click="onEdit(row, 'description')">{{ row.description }}</span>
          </template>
        </el-table-column>
      </el-table>
    <!-- 分页 -->
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page.sync="currentPage"
      :page-sizes="[10, 20, 30, 40]"
      :page-size="pageSize"
      :total="totalDataCount"
      layout="total, sizes, prev, pager, next, jumper"/>
  </div>
</template>

<script>
import axios from 'axios';
export default {
  data() {
    return {
      tableData: [],
      selectedRows: [], // 复选框
      modifiedRows: [], // 已经被修改的行的id/背景色
      // 分页
      currentPage: 1, // 前往当前页
      pageSize: 10, // 每页显示多少条
      originalValue: '', //一个变量用于记录编辑前的值
    }
  },
  computed: {
    totalDataCount() { // 计算总数据量
      return this.tableData.length;
    },
    currentPageData() { // 基于分页计算当前页面数据
      const startIndex = (this.currentPage - 1) * this.pageSize;
      const endIndex = startIndex + this.pageSize;
      return this.tableData.slice(startIndex, endIndex);
    },
  },
  created() {
    this.fetchData();
  },
  methods: {
    // 获取数据后端数据表格
    async fetchData() {
      try {
        // 调用后端获取数据的接口
        const response = await axios.get('/api/getData');
        // 将返回的数据赋值给tableData
        this.tableData = response.data;
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    },
    // +新增
    async onAdd() {
        try {
          // 调用后端新增数据的接口
          const response = await axios.post('/api/addData', { key: '', type: '', description: '', isEditKey: true, isEditType: true, isEditDescription: true});
          // 将返回的新数据插入到表格的最前面
          const newRecord = response.data;
          this.tableData.unshift(newRecord);
        } catch (error) {
          console.error('新增数据时发生错误:', error);
        }
    },
    // 批量删除
    async onBatchDelete() {
      if (this.selectedRows.length > 0) {
        try {
          // 获取选中行的id数组
          const selectedIds = this.selectedRows.map(row => row.id);
          // 调用后端删除数据的接口
          await axios.delete('/api/deleteData', { data: { ids: selectedIds } });
          // 从tableData中移除选中的行
          this.tableData = this.tableData.filter(item => !selectedIds.includes(item.id));
          // 清空选中的行
          this.selectedRows = [];
        } catch (error) {
          console.error('批量删除时发生错误:', error);
        }
      }
    },
    onSelectionChange(selection) { // 复选框选择变更时触发,批量删除
      this.selectedRows = selection;
    },
    // 保存
    async onBatchSave() {
      try {
        // 收集表格中所有数据
        const allData = this.tableData;
        // 发送数据给后端
        const response = await axios.post('/your-backend-endpoint', allData);
        // 处理后端返回的响应
        console.log(response.data);
        // 清空已修改的行数组
        this.modifiedRows = [];
      } catch (error) {
        // 处理错误
        console.error('保存时发生错误:', error);
      }
    },
   // 点击单元格进入编辑状态
   onEdit(row, field) {
      // 在进入编辑状态时记录编辑前的值
      this.originalValue = row[field];
      if (field === 'key') {
        row.isEditKey = true; // 参数ID
        row.isEditType = false; // 参数名称
        row.isEditDescription = false; // 参数描述
      } else if (field === 'type') {
        row.isEditKey = false;
        row.isEditType = true;
        row.isEditDescription = false;
      } else if (field === 'description') {
        row.isEditKey = false;
        row.isEditType = false;
        row.isEditDescription = true;
      }
    },
    // 根据编辑状态设置行样式
    rowStyle({ row }) {
      return { backgroundColor: this.modifiedRows.includes(row.id) ? '#ffcccc' : '' };
    },
    // 失去焦点时触发,隐藏输入框
    onBlur(row, field) {
      if (this.originalValue !== row[field]) {
        // 只有在值发生变化时才将当前行的 ID 添加到 modifiedRows 数组中
        if (!this.modifiedRows.includes(row.id)) {
          this.modifiedRows.push(row.id);
        }
      }
      //
      if (field === 'key') {
        row.isEditKey = false;
      } else if (field === 'type') {
        row.isEditType = false;
      } else if (field === 'description') {
        row.isEditDescription = false;
      }
      // 如果有已修改的行,并且当前行不在已修改的行中,则隐藏已修改的行的编辑状态
      this.tableData.forEach(item => {
        if (this.modifiedRows.includes(item.id) && item.id !== row.id) {
          item.isEditKey = false;
          item.isEditType = false;
          item.isEditDescription = false;
        }
      });
    },
    // 分页每页多少条
    handleSizeChange(val) {
      this.pageSize = val;
    },
    // 前往当前页
    handleCurrentChange(val) {
      this.currentPage = val;
    },
  }
}
</script>

<style scoped>
.custom-tree-table {
  height: 100%;
  background-color: #fff;
  padding: 15px;
}
/*新增按钮宽高*/
.el-button--mini{
  padding: 7px 12px;
}
/*表格每行高度*/
.custom-tree-table /deep/ .el-table__cell {
  padding: 8px;
}
/* input高度 */
::v-deep .el-input__inner{
  height: 26px
}
/* 分页器位置 */
::v-deep .el-pagination{
  display: flex;
  justify-content: flex-end;
}

/* 设置按钮颜色 */
.el-button--primary {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
.el-button--success {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
.el-button--danger {
  background-color: #7184FF;
  border-color: #7184FF;
  color: #fff;
}
</style>

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 gin 批量增删操作可以通过 HTTP POST 请求来实现,请求的 body 包含操作类型和数据,服务器端根据操作类型执行对应的增删操作。以下是一个示例代码,实现批量增删用户的功能: ```go type User struct { ID int `json:"id"` Name string `json:"name"` Age int `json:"age"` } var users = []User{ {ID: 1, Name: "Alice", Age: 20}, {ID: 2, Name: "Bob", Age: 25}, {ID: 3, Name: "Charlie", Age: 30}, } type BatchRequest struct { Op string `json:"op"` // 操作类型,可以是 add, update 或 delete Users []User `json:"users"` // 待操作的用户列表 } func main() { r := gin.Default() r.POST("/batch", func(c *gin.Context) { var batchReq BatchRequest if err := c.BindJSON(&batchReq); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } switch batchReq.Op { case "add": for _, user := range batchReq.Users { users = append(users, user) } case "update": for _, user := range batchReq.Users { for i := range users { if users[i].ID == user.ID { users[i] = user break } } } case "delete": ids := make(map[int]bool) for _, user := range batchReq.Users { ids[user.ID] = true } newUsers := make([]User, 0, len(users)) for _, user := range users { if !ids[user.ID] { newUsers = append(newUsers, user) } } users = newUsers default: c.JSON(http.StatusBadRequest, gin.H{"error": "invalid operation type"}) return } c.JSON(http.StatusOK, gin.H{"message": "success"}) }) r.Run(":8080") } ``` 在上述代码,我们定义了一个 `User` 结构体,包含用户的 ID、姓名和年龄。我们使用一个全局变量 `users` 来保存所有用户的信息。在路由处理函数,我们首先解析 HTTP 请求的 JSON 数据,然后根据 `BatchRequest.Op` 的值执行对应的增删操作。具体来说: - 如果 `Op` 是 `"add"`,就将请求的所有用户添加到 `users` ; - 如果 `Op` 是 `"update"`,就将请求的所有用户的信息更新到 `users` ; - 如果 `Op` 是 `"delete"`,就将请求的所有用户从 `users` 删除。 最后,我们返回一个 JSON 响应,表示操作成功。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值