vue+antd 可编辑表格以及单元格失焦事件

文章展示了一个Vue.js组件,该组件包含一个可折叠的表格,具有搜索功能和资源选择下拉菜单。表格支持单元格编辑,双击激活编辑,点击外部区域取消编辑。同时,文章还涉及数据检索和日期范围选择。组件还包括了事件监听,如点击事件和文档级事件处理,用于控制表格的显示和编辑状态。
摘要由CSDN通过智能技术生成

重点:1、<div ref=“wrapper” @click=“handleClickOutside”>
2、@click.stop="handleDblclick
3、mounted() {
document.addEventListener(‘click’, this.handleClickOutside);
},
beforeDestroy() {
document.removeEventListener(‘click’, this.handleClickOutside);
},

<template>
  <div >
    <a-card>
      <a-collapse v-model="activeKey">
        <a-collapse-panel key="1" header="资源产能">
          <template #extra>
            <div slot="toolBar" @click.stop>
              <FactoryImport />
              <FactoryExport />
            </div>
          </template>
          <div>
            <a-form-model :model="form" :layout="'horizontal'">
              <a-col :span="7">
                <a-form-model-item label="资源组代码" :labelCol="{ span: 6 }" :wrapperCol="{ span: 16 }">
                  <!-- <a-input v-model="form.resourceGroupCode" allowClear placeholder="请输入" size="small" /> -->
                  <a-select v-model="form.resourceGroupCode" placeholder="请选择" allowClear size="small">
                    <a-select-option v-for="item in resourceGroupList" :key="item">
                      {{ item }}
                    </a-select-option>
                  </a-select>
                </a-form-model-item>
              </a-col>
              <a-col :span="7">
                <a-form-model-item label="资源代码" :labelCol="{ span: 6 }" :wrapperCol="{ span: 16 }">
                  <a-input v-model="form.standardResourceCode" allowClear placeholder="请输入" size="small" />
                </a-form-model-item>
              </a-col>

              <a-col :span="7">
                <a-form-model-item label="下单日期" :labelCol="{ span: 6 }" :wrapperCol="{ span: 16 }">
                  <a-range-picker
                    :placeholder="['开始日期', '结束日期']"
                    size="small"
                    format="YYYY-MM"
                    :value="dataValue"
                    :mode="mode2"
                    @panelChange="handlePanelChange2"
                    @change="handleDataChange"
                  />
                </a-form-model-item>
              </a-col>

              <a-col :span="3">
                <a-form-model-item>
                  <a-button type="primary" style="float: right;margin-top:8px" @click="onSubmit" size="small"
                    >搜索</a-button
                  >
                </a-form-model-item>
              </a-col>
            </a-form-model>
          </div>
        </a-collapse-panel>
      </a-collapse>
    </a-card>
    <div ref="wrapper" @click="handleClickOutside">
    <a-card>
      <a-table
        bordered
        :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, onSelect: onSelect }"
        :columns="columns"
        :row-key="record => record.stockPointId"
        :data-source="data"
        :pagination="goodsRoutingPagination"
        :loading="loading"
        :scroll="{ x: tableWidth }"
        size="small"
      >
        <template v-for="(col, i) in editDynamicColumnArr" :slot="col" slot-scope="text, record">
          <a-input
            :key="i"
            v-if="record[`${col}_editable`]"
            :value="text"
            size="small"
            style="width: 65px;height:18px;"
            @change="e => handleEditChange(e, col, record)"
            @blur="e => handleEdit(e, col, record)"
          />
          <span v-else :key="i" @click.stop="handleDblclick(col, text, record)">{{ text }}</span>
        </template>
      </a-table>
    </a-card>
    </div>
  </div>
</template>

<script>
import Auth from '@/components/Auth';
import exportExcle from '@/api/factory/exportExcle';
import FactoryExport from './factoryExport.vue';
import FactoryImport from './factoryImport.vue';
import { queryByPage, updateSalesForecastDemand, getResourceList } from '@/api/resourceCapacity/resourceCapacity';
import baseUrl from '@/utils/baseUrl';
import moment from 'moment';

export default {
  name: 'factory',
  components: {
    FactoryExport,
    FactoryImport,
    Auth
  },
  data() {
    return {
      editDynamicColumnArr: [],
      dataValue: [],
      resourceGroupList: [],
      tableWidth: 1200,
      rules: {
        beginTime: [{ required: true, message: '请选择开始日期', trigger: 'change' }],
        endTime: [{ required: true, message: '请选择结束日期', trigger: 'change' }],
        yearAndMonth: [{ required: true, message: '请选择所属年月', trigger: 'change' }],
        lineNum: [{ required: true, message: '请输入月数  ', trigger: 'change' }]
      },
      mode2: ['month', 'month'],
      mHeight: window.innerHeight - 320 + 'px',
      params: {},
      action: baseUrl.schedule + '/resourceCapacity/importData',
      data1: { deptId: '' },
      headers: {
        authorization: 'authorization-text',
        dataBaseName: sessionStorage.getItem('switchName') || ''
      },
      monthVisible: false,
      activeKey: ['1'],
      timeVisible: false,
      importVisible: false,
      labelCol: { span: 6 },
      wrapperCol: { span: 30 },
      form: {},
      timeSettForm: {},
      forecastMonths: {},
      data: [],
      beginData: '',
      endData: '',
      loading: false,
      columns: [],
      selectedRowKeys: [],
      selectedColumns: [],
      editFactory: {},
      goodsRoutingPagination: {
        pageSizeOptions: ['10', '20', '30', '50'],
        showSizeChanger: true,
        showQuickJumper: true,
        pageNum: 1,
        pageSize: 10,
        current: 1,
        total: 0,
        showTotal: total => {
          return `共 ${total} 条`;
        }
      }
    };
  },
  computed: {},
  created() {
    this.onSubmit();
    this.getResourceListFn();
    const deptId = JSON.parse(localStorage.getItem('LOGIN_INFO')).deptId;
    this.data1.deptId = deptId;
  },
  mounted() {
    document.addEventListener('click', this.handleClickOutside);
  },
  beforeDestroy() {
    document.removeEventListener('click', this.handleClickOutside);
  },

  methods: {
    getResourceListFn() {
      getResourceList().then(res => {
        console.log(res);
        const { data } = res || {};
        if (data.success) {
          this.resourceGroupList = data.data.resourceGroupName;
        } else {
          this.resourceGroupList = [];
        }
      });
    },

    handleClickOutside(event) {
      const wrapper = this.$refs.wrapper;
      if (wrapper && !wrapper.contains(event.target)) {
        // 在此处执行取消行编辑的逻辑;
        this.data.forEach(item => {
          for (const key in item) {
            if (Object.hasOwnProperty.call(item, key)) {
              if (key.includes('_editable')) {
                this.$nextTick(() => {
                  item[`${key}`] = false;
                });
              }
            }
          }
        });
      }
    },

    confirm() {
      if (this.selectedRowKeys.length == 0) {
        this.$message.warning('请选择要删除的数据');
      } else {
        deleteByPlantIds(this.selectedRowKeys.join(','))
          .then(res => {
            if (res.data.success) {
              this.$message.success('删除成功');
              this.selectedRowKeys = [];
              this.onSubmit();
            } else {
              this.$message.error('删除失败');
            }
          })
          .catch(() => {
            this.$message.error('删除失败');
          });
      }
    },
    handleChange(info) {
      if (info.file.response !== undefined) {
        if (info.file.response.success) {
          this.$message.success(info.file.response.msg || '导入成功');
          this.onSubmit();
          // this.$emit('getQueryByPage');
        } else {
          this.$message.error(info.file.response.msg || '导入失败');
        }
      }
    },

    // 双击修改
    handleDblclick(col, text, record) {
      for (const key in record) {
        if (Object.hasOwnProperty.call(record, key)) {
          if (key.includes('_editable') && key != `${col}_editable`) {
            record[`${key}`] = false;
          }
        }
      }

      this.data.forEach(item => {
        if (item.id != record.id) {
          for (const key in item) {
            if (Object.hasOwnProperty.call(item, key)) {
              if (key.includes('_editable')) {
                item[`${key}`] = false;
              }
            }
          }
        }
      });
      record[`${col}_editable`] = true;
    },

    handleEditChange(e, col, record) {
      record[col] = e.target.value;
    },

    // 编辑
    handleEdit(e, col, record) {
      console.log(record, col);
      const value = e.target.value;
      record[col] = value;
      const { id, ruleVersion, resourceGroupCode, standardResourceCode } = record || {};
      let obj = {
        id,
        standardResourceCode,
        resourceGroupCode,
        ruleVersion,
        values: {}
      };
      obj.values[col] = record[col];
      this.editParams = obj;
      console.log(this.editParams);
      this.toupdate(obj);
    },

    toupdate(data) {
      this.loading = true;
      updateSalesForecastDemand(data)
        .then(res => {
          const { data } = res;
          console.log(data);
          if (data.success) {
            this.$message.success(data.msg);
            this.loading = false;
            this.onSubmit();
          } else {
            this.loading = false;
            this.$message.error(data.msg);
          }
        })
        .catch(err => {
          console.log(err);
          this.loading = false;
          this.$message.error('服务器错误');
        });
    },

    handlePanelChange2(value, mode) {
      this.dataValue = value;
      this.mode2 = [mode[0] === 'date' ? 'month' : mode[0], mode[1] === 'date' ? 'month' : mode[1]];
    },

    handleDataChange(value) {
      this.dataValue = value;
    },

    exportTemplate() {
      const params = this.params;
      exportExcle.exportExcleModel(`${baseUrl.schedule}/salesForecast/exportTemplate`);
    },

    timeSet() {
      this.timeVisible = true;
    },

    handleCancel() {
      this.timeVisible = false;
      this.importVisible = false;
      this.monthVisible = false;
    },

    handleStartTime(date, dateString) {
      this.beginData = dateString;
    },

    handleInputStartTime(date, dateString) {
      this.data1.yearAndMonth = dateString;
    },
    handleEndTime(date, dateString) {
      this.endData = dateString;
    },

    messageHandle(e) {
      console.log('page2页面共享线程counter值:', e.data);
    },
    prevent() {},

    getUpload(data) {
      let { response } = data || {};
      if (response) {
        if (response.success) {
          this.loading = true;
          this.onSubmit();
        }
      }
    },

    onSelect(record) {
      console.log(record);
    },
    onSelectChange(selectedRowKeys) {
      console.log(selectedRowKeys);
      this.selectedRowKeys = selectedRowKeys;
      if (selectedRowKeys.length == 1) {
        this.editFactory = this.data.filter(item => {
          if (item.stockPointId == selectedRowKeys[0]) {
            return item;
          }
        })[0];
      }
      console.log(this.editFactory);
    },
    getQueryByPage(params) {
      queryByPage(params)
        .then(data => {
          this.loading = false;
          if (data.data.success) {
            let mycolumns = [];
            let editDynamicColumnArr = [];
            let dataSource = [];
            if (data.data.data.list.length > 0) {
              data.data.data.list[0].headerList.map((item, i) => {
                if (item == '资源组名称' || item == '资源名称') {
                  mycolumns.push({
                    dataIndex: item,
                    title: item,
                    fixed: true,
                    width: 100
                  });
                } else {
                  editDynamicColumnArr.push(item);
                  mycolumns.push({
                    dataIndex: item,
                    title: item,
                    scopedSlots: { customRender: item }
                  });
                }
              });

              for (let index = 0; index < data.data.data.list.length; index++) {
                const element = data.data.data.list[index];
                element.resultMap.modifyTime = element.modifyTime;
                element.resultMap.modifierName = element.modifierName;
                element.resultMap.id = element.id;
                element.resultMap.ruleVersion = element.ruleVersion;
                element.resultMap.standardResourceCode = element.standardResourceCode;
                element.resultMap.resourceGroupCode = element.resourceGroupCode;

                for (const key in element.resultMap) {
                  if (Object.hasOwnProperty.call(element.resultMap, key)) {
                    if (key != '资源组名称' || key != '资源名称') {
                      element.resultMap[`${key}_editable`] = false;
                    }
                  }
                }
                dataSource.push(element.resultMap);
              }

              console.log(dataSource);

              this.data = dataSource;
              this.editDynamicColumnArr = editDynamicColumnArr;
              this.columns = mycolumns;
              this.tableWidth = (this.columns.length - 1) * 80 > 1200 ? (this.columns.length - 1) * 80 : 1200;
              console.log(this.tableWidth);
            } else {
              this.tableWidth = 0;
              this.data = [];
              this.columns = [];
            }
          } else {
            this.tableWidth = 0;
            this.data = [];
            this.$message.error(data.data.msg || '数据查询失败');
          }
        })
        .catch(() => {
          this.loading = false;
        });
    },
    onSubmit() {
      let params = {
        // pageNum,
        // pageSize,
        ...this.form
      };
      if (this.dataValue && this.dataValue.length > 0) {
        params.beginTime = moment(this.dataValue[0]).format('YYYY-MM');
        params.endTime = moment(this.dataValue[1]).format('YYYY-MM');
      }
      this.getQueryByPage(params);
    },

    submitAdd() {
      this.onSubmit();
    }
  },
  destroyed() {}
};
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值