上传、下载、复制粘贴功能的梳理

开发了一个设置日预算的需求,其中涉及到的技术点比较多,也很常用。现在对此次需求进行一下梳理,以便日后学习。


背景:对选择的计划批量设置/修改预算。修改方式有在线编辑excel批量导入两种。

1、在线编辑

样式如下:

html代码如下:

<el-table :data="tableData" ref="budgetTable" :max-height="heightNumber">
    <el-table-column prop="campaignName" label="计划名称" key="campaignName" fixed
width="200px" ></el-table-column>
    <el-table-column prop="dayBudgetCustom" label="统一日预算" key="dayBudgetCustom" fixed min-width="140px" >
        <template v-slot="scope">
            <el-input v-model.trim="scope.row.dayBudgetCustom" style="width: 100px"
                @paste.native.capture.prevent="onPaste"
                @focus="onFocus(scope, 0)"
                @keyup.native="handleNumberType"
                @blur="handleNumberRange"
                placeholder="不限"></el-input>
        </template>
    </el-table-column>
    <!-- 今日预算 -->
    <el-table-column prop="dayBudget" :label="startDate" key="dayBudget" fixed min-width="140px" >
        <template v-slot="scope">
            <el-input v-model.trim="scope.row.dayBudget" style="width: 100px"
                @paste.native.capture.prevent="onPaste"
                @focus="onFocus(scope, 1)"
                @keyup.native="handleNumberType"
                @blur="handleNumberRange"
                placeholder="不限"></el-input>
        </template>
    </el-table-column>
    <template v-for="(col, index) in colListBudget">
        <el-table-column :label="col" :prop="col" :key="col+index" min-width="110px">
            <template v-slot="scope">
                <el-input v-model.trim="scope.row[col]"
                    @paste.native.capture.prevent="onPaste"
                    @focus="onFocus(scope, index+2)"
                    @keyup.native="handleNumberType"
                    @blur="handleNumberRange"
                    placeholder="不限"></el-input>
             </template>
         </el-table-column>
    </template>
</el-table>

1、选择要操作的日期,开始日期始终是今天,结束日期是未来30天。

startDate: dayjs().format('YYYY-MM-DD'),
endDate: dayjs().add(30,'day').format('YYYY-MM-DD'),
<el-date-picker v-model="startDate"
                type="date"
                :readonly="true"
                style="width:130px"
                placeholder="选择日期"></el-date-picker>
至
<el-date-picker v-model="endDate"
                type="date"
                :clearable="false"
                :editable="false"
                :picker-options="pickerOptions"
                style="width:130px"
                @change="handleChangeData"></el-date-picker>

同时对结束日期做限制:只能选择今天及未来30天。

pickerOptions: {
    disabledDate: (time) => {
        let startDate, endDate
        endDate = dayjs().add(30,'day')
        startDate = dayjs().add(-1,'day')
        return (
            time.getTime() < startDate || time.getTime() > endDate
        );
    },
},

2、对所选计划,配合要设置预算的日期,制造出相应的表格

当弹框值drawerShow为真(即弹窗打开)时,将外面传过来的值campaignArray深拷贝一份赋值给campaignData,遍历campaignData返回一个我们需要哪些值的新数组tableData(即表格数组)。

watch: {
    drawerShow: {
        handler: function (val, oldval) {
            if(val) {
                this.heightNumber = window.innerHeight - 220;
                this.campaignData = JSON.parse(JSON.stringify(this.campaignArray))
                this.tableData = this.campaignData.map(item => {
                    item.dateRange = JSON.parse(item.dateRange)
                    return {
                        id: item.campaignId,
                        campaignName: item.campaignName,
                        dayBudgetCustom: item.dayBudgetCustom, //统一日预算
                        dayBudget: item.dayBudget, //今日预算
                        ...item.dateRange,
                    }
                 })
                 this.handleChangeData() //日期填充表格
                 this.checkDayBudgetTask()//检查是否有日预算任务进行
             }
        },
    },
    immediate: true,
},

遍历日期填充表格:自定义日期是用dayjs的diff方法计算开始日期(加一天,即明天)和结束日期的时间差(比如开始日期21号,结束日期24号,计算的是22号到24号的时间差,为2天),for循环将每一天添加到一个新数组temp,赋值给colListBudget,即自定义列的表头数据源。

处理表格数据:遍历tableData的每一项,再for of遍历temp数组,通过对象的hasOwnProperty方法判断表格的当前项item是否有自定义日期属性,如果有,就给item添加此属性并赋值;若没有这个属性,则添加属性并赋统一日预算dayBudgetCustom的值。

methods: {
    //改变日期
    handleChangeData() {
        //计算结束日期与开始日期的时间差
        let dys = dayjs(this.endDate).diff(dayjs(this.startDate).add(1,'day'), 'day');
        let temp = []
        // Math.abs() 返回一个数的绝对值
        // add(1,'day')是为了表格渲染自定义列的时候从“明天”开始,
        // 因为“今天”在表格中要被处理成“今日预算”,虽然看起来是“202x-xx-xx”格式,但赋值的字段是dayBudget
        // 为何要这样处理? 原因之一是:“今日预算”要固定
        for (let i = 0; i <= Math.abs(dys); ++i) {
            temp.push(dayjs(this.startDate).add(1,'day').add(i, 'day').format('YYYY-MM-DD'));
        }
        this.colListBudget = temp;
        //处理成一个完整的table
        this.tableData = this.tableData.map(item => {
            var obj = {}
            for (let p of temp) {
                item[p] = item.hasOwnProperty(p) ? item[p] : (item.dayBudgetCustom||null)
                obj[p] = item[p]
            }
            return {
                id: item.id,
                dayBudgetCustom: item.dayBudgetCustom,
                dayBudget: item.dayBudget,
                campaignName: item.campaignName,
                ...obj,
            }
         })
    },
}

 3、粘贴复制功能

功能描述:支持从 EXCEL 中复制多行多列数据,选中开始输入框,自动向右向下填充复制内容

首先给input框绑定focus事件,获取当前框的横、纵坐标 

onFocus()两个参数,第一个是当前行对象(可获取x坐标),第二个是当前纵坐标

<el-input v-model.trim="scope.row.dayBudgetCustom" style="width: 100px"
    @paste.native.capture.prevent="onPaste"
    @focus="onFocus(scope, 0)"
    @keyup.native="handleNumberType"
    @blur="handleNumberRange"
    placeholder="不限"></el-input>
onFocus(scope, index) {
    this.xIndex = scope.$index;
    this.yIndex = index;
}

代码解析:replace(new RegExp(',','gm'),'')用于将粘贴内容中的“,”去掉。 将处理好的内容全部整理到strArr数组中。parseInt方法将小数取整。

onPaste(e) {
    if (e.clipboardData) { 
        var item = e.clipboardData.items[0];
        if (item && item.kind === 'string') {
            item.getAsString(str =>{
                let nb = str.replace(/[\t]/g, '|').replace(/[\r\n]/g, ';').replace(new RegExp(',','gm'),'');
                let strArr = [];
                let nbs = nb.split(';');
                for (let i = 0; i < nbs.length; i++) {
                    if (nbs[i] !== '') {
                        strArr.push(nbs[i]);
                    }
                 }
                 for (let i = 0, x = this.xIndex, y = this.yIndex;i < strArr.length && x < this.tableData.length && y < this.colListBudget.length + 2; i++, x++) {
                     if(y === 0) {
                         this.tableData[x]['dayBudgetCustom'] = parseInt(strArr[i].split('|')[0]);
                         this.tableData[x]['dayBudget'] = parseInt(strArr[i].split('|')[1]);
                      } else if(y === 1) {
                          this.tableData[x]['dayBudget'] = parseInt(strArr[i].split('|')[0]);
                      }
                      for (let m = 0; m < strArr[i].split('|').length && y + m < this.colListBudget.length; m++) {
                          if(strArr[i].split('|')[m] && y>1) { //从自定义列区域 复制
                              this.tableData[x][this.colListBudget[m+y-2]] = parseInt(strArr[i].split('|')[m]);//从明天开始的自定义列
                           }
                           if(strArr[i].split('|')[m+2-y] && y<2) {
                               this.tableData[x][this.colListBudget[m]] = parseInt(strArr[i].split('|')[m+2-y]);//从明天开始的自定义列
                           }
                           this.$set(this.tableData, x, this.tableData[x]);
                       }  
                  }
            });
        }
    }
},

2、Excel 批量导入

样式如下:

html代码如下:

<div v-else>
    <el-tag class="upload-tag" :disable-transitions="true">
        <i class="el-alert__icon el-icon-warning" style="color: #E6A23C;"></i>
        <span class="ml10">请先下载需要设置次日预算的导入模板</span>
        <el-button type="plain" size="mini" class="ml15" @click="handleDownload">下载导入模板</el-button>
    </el-tag>
    <div class="upload-box select-item">
        <span class="select-lable">上传文件</span>
        <div class="up-body">
            <el-upload action=""
                :file-list="fileList"
                :on-remove="handleRemove"
                :before-upload="beforeUpload"
                :on-change="handleUploadChange"
                accept=".xls,.xlsx"
                :auto-upload="false">
                <el-button type="primary">点击上传</el-button>
                <div slot="tip" class="el-upload__tip">
                    <p>· 支持格式:xls,xlsx</p>
                    <p>· 单个文件大小不超过10M</p>
                </div>
                <span v-show="isShowIcon" class="load-icon"><i class="el-icon-loading"></i></span>
            </el-upload>
         </div>
    </div>
</div>

1、下载模板

handleDownload() {
    let ids = this.campaignData.map(item => item.campaignId)
    this.$axios.post('/jdkc-biz-ad/jdkc/campaign/dayBudgetTemplate', 
        ids,
        {responseType: "blob",}
    ).then(response => {
         if(response.data) {
             let blob = new Blob([response.data]);
             let fileName = '京东快车_计划日预算_上传模板.xlsx';
             if(navigator.userAgent.indexOf("Edge") > -1) {
                 window.navigator.msSaveOrOpenBlob(blob, fileName);
             }
             let url = window.URL.createObjectURL(blob);
             // 生成一个a标签
             let link = document.createElement("a");
             link.style.display = "none";
             link.href = url;
             // 生成时间戳
             link.download = decodeURI(fileName);
             document.body.appendChild(link);
             link.click();
             document.body.removeChild(link); // 下载完成移除元素
             window.URL.revokeObjectURL(url); // 释放掉blob对象
        }
    })
},

2、导入上传

confirmUpload() {
    this.isUpload = false; //不禁用按钮
    let formData = new FormData();
    let file = this.fileList[0].raw;
    formData.append("file", file);
    let config = {
        headers: {
           "Content-Type": "multipart/form-data",
        },
    };
    this.$axios.post('/jdkc-biz-ad/jdkc/campaign/dayBudgetImport',
        formData,
        config
    ).then((response) => {
        if (response.data.status===0) {
            this.$message.success("上传成功");
            this.handleCloseDrawer('refresh')
        } else {
            this.isUpload = true; //失败则禁用按钮
        }
    })
},

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在WPF项目开发中,复制粘贴功能可以实现工程的完整拷贝。具体的实现过程如下: 1. 复制操作很简单,需要获取到完整的工程对象信息。可以通过一个私有的ICloneable类型的变量copyItem来保存要复制的工程对象信息。在复制操作中,将要复制的工程对象赋值给copyItem变量。 2. 粘贴操作需要生成一个与被拷贝工程没有任何关联的新工程。可以通过反射获取Project中的对象信息,并使用Clone()函数实现工程的复制。在Clone()函数中,使用反射创建与被拷贝工程相同类型的新对象,然后遍历属性列表,将被拷贝工程的属性值赋给新对象的对应属性。最后返回新的工程对象作为粘贴的结果。 实现复制粘贴功能的步骤如下: 1. 在复制操作中,获取要复制的工程对象信息,并保存到一个私有变量中。 2. 在粘贴操作中,通过反射获取被拷贝工程的属性信息。 3. 使用反射创建一个与被拷贝工程类型相同的新对象。 4. 遍历属性列表,将被拷贝工程的属性值赋给新对象的对应属性。 5. 返回新的工程对象作为粘贴的结果。 通过以上步骤,就可以实现WPF项目中的复制粘贴功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [WPF中通过反射实现对象的复制粘贴](https://blog.csdn.net/SQWH_SSGS/article/details/109204771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值