<template>
    <div class="app-data-upload-view" v-loading.fullscreen="isUploading" element-loading-background="rgba(57, 57, 57, 0.2)">
        <el-row style="margin-top:24px" :gutter="20">
            <el-col :span="4">
                <el-button type="primary" @click="handleUpLoad">{{$t('components.appDataUploadView.selectfile')}}</el-button>
                <input ref="inputUpLoad" type="file" style="display: none" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" @change="importFile"/>
            </el-col>
            <el-col :span="4">
                <el-button type="primary" @click="uploadServer">{{$t('components.appDataUploadView.uploadserver')}}</el-button>
            </el-col>
            <el-col :span="16">
                <div class="import-temp"><span style="cursor: pointer;" @click="downloadTemp">{{$t('components.appDataUploadView.datatemplate')}}</span></div>
            </el-col>
        </el-row>
        <el-divider></el-divider>
        <el-progress class="progress" v-show="isUploading" :text-inside="true" :stroke-width="14" :percentage="uploadProgress"></el-progress>
        <el-row style="height:480px;padding: 0px 12px;">
            <div class="data-info-content" >
                <template v-if="importDataArray.length >0 && isUploading === false">
                    <ul>
                        <li v-for="(item,index) in importDataArray" :key="index" class="font-class">
                            {{item[importUniqueItem]?$t('components.appDataUploadView.dataid')+item[importUniqueItem]+$t('components.appDataUploadView.read')+'......':$t('components.appDataUploadView.read')+'......'}}
                        </li>
                    </ul>
                </template>
                <template v-if="hasImported === true && importDataArray.length === 0">
                    <span class="font-class">{{isUploading === true?$t('components.appDataUploadView.importing')+"......":promptInfo}}</span>
                </template>
            </div>
        </el-row>
        <el-row>
            <!-- <el-col :span="4">
            <div class="import-temp">
                <div style="cursor: pointer;display: inline-block;" @click="downloadSuccessData">{{importSuccessData.length >0?"下载导入成功数据":""}}</div>
            </div>
            </el-col>
            <el-col :span="4">
                <div class="import-temp">
                    <span style="cursor: pointer;display: inline-block;" @click="downloadErrorData">{{importErrorData.length >0?"下载导入失败数据":""}}</span>
                </div>
            </el-col> -->
            <el-col :span="2" :offset="22">
                <el-button type="primary" @click="handleOK">{{$t('components.appDataUploadView.confirm')}}</el-button>
            </el-col>
        </el-row>
    </div>
</template>

<script lang="ts">
import XLSX from 'xlsx';
import CodeListService from "@/codelist/codelist-service";
import EntityService from '@/service/entity-service';
import { Vue, Component, Prop, Provide, Emit, Watch } from 'vue-property-decorator';
import { Environment } from '@/environments/environment';
import moment from "moment"; 

@Component({
})
export default class AppDataUploadView extends Vue {

     /**
     * 传入视图上下文
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    @Prop() protected viewdata!: string;

    /**
     * 传入视图参数
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    @Prop() protected viewparam!: string;

    /**
     * 代码表服务对象
     *
     * @type {CodeListService}
     * @memberof AppDataUploadView
     */  
    public codeListService:CodeListService = new CodeListService();

    /**
     * 实体服务对象
     *
     * @protected
     * @type {EntityService}
     * @memberof AppDataUploadView
     */
    protected entityService: EntityService = new EntityService();

    /**
     * 视图参数
     *
     * @type {*}
     * @memberof AppDataUploadView
     */
    protected viewparams:any = {};

    /**
     * 导入数据模型
     *
     * @type {Array<*>}
     * @memberof AppDataUploadView
     */
    protected importDataModel:Array<any> = [];

    /**
     * 导入数据集合
     *
     * @type {Array<*>}
     * @memberof AppDataUploadView
     */
    protected importDataArray:Array<any> = [];

    /**
     * 导入标识
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    protected importId:string = "";

    /**
     * 是否已有导入数据
     *
     * @type {boolean}
     * @memberof AppDataUploadView
     */
    protected hasImported:boolean = false;

    /**
     * 导入数据识别项属性
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    protected importUniqueItem:string ="";

    /**
     * 提示信息
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    protected promptInfo:string ="";

    /**
     * 导入状态
     *
     * @type {boolean}
     * @memberof AppDataUploadView
     */
    protected isUploading:boolean = false;

    /**
     * 导入成功数据
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    protected importSuccessData:Array<any> = [];

    /**
     * 导入失败数据
     *
     * @type {string}
     * @memberof AppDataUploadView
     */
    protected importErrorData:Array<any> = [];

    /**
     * 读取完成的数据
     *
     * @type {*}
     * @memberof AppDataUploadView
     */
    public workBookData:any;

    /**
     * 所有的代码表
     *
     * @type {*}
     * @memberof AppDataUploadView
     */
    public allCodeList:any;

    /**
     * 属性Map(用作属性转化)
     *
     * @type {*}
     * @memberof AppDataUploadView
     */
    public allFieldMap:Map<string,any> = new Map();
    
    /**
     * 上传服务器数据切片数
     *
     * @type {number}
     * @memberof AppDataUploadView
     */
    public sliceUploadCnt: number = Environment.sliceUploadCnt;

    /**
     * 上传服务器进度条百分比
     *
     * @type {number}
     * @memberof AppDataUploadView
     */
    public uploadProgress: number = 0;

    /**
     * 视图参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppDataUploadView
     */
    @Watch('viewparam',{immediate: true, deep: true})
    onParamData(newVal: any, oldVal: any) {
        if(newVal){
            Object.assign(this.viewparams, JSON.parse(this.viewparam));
            this.initBasic();
        } 
    }

    /**
     * 初始化基础数据
     *
     * @memberof AppDataUploadView
     */
    public async initBasic(){
        if(this.viewparams.importId){
            this.importId = this.viewparams.importId;
        }
        if(this.viewparams.importData){
            this.importDataModel = Object.values(this.viewparams.importData);
            this.BubbleSort(this.importDataModel,this.importDataModel.length);
        }
        this.importDataModel.forEach((item:any) =>{
            if(item.isuniqueitem){
                this.importUniqueItem = item.headername;
            }
            this.allFieldMap.set(item.headername,item);
        });
        //获取代码表值
        this.allCodeList = await this.getChartAllCodeList();
    }

    /**
     * 冒泡排序
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppDataUploadView
     */
    public BubbleSort(array:Array<any>,length:number){
        for (let i = 0; i < length; i++){
		for (let j = 0; j < length -  i - 1; j++){
                if (array[j].order > array[j + 1].order){
                    let temp:any;
                    temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
            }
        }
    }

    /**
     * 下载导入数据模板
     *
     * @memberof AppDataUploadView
     */
    public downloadTemp(){
        this.importExcel(this.viewparams.appDeLogicName+this.$t('components.appDataUploadView.datatemp'),[]);
    }

    /**
     * 选择文件
     *
     * @memberof AppDataUploadView
     */
    public handleUpLoad(){
        this.importSuccessData = [];
        (this.$refs.inputUpLoad as any).click();
    }

    /**
     * 上传服务器
     *
     * @memberof AppDataUploadView
     */
    public uploadServer(){
        if(this.importDataArray.length == 0){
            return;
        }
        let tempDataArray:Array<any> = [];
        this.transformData(this.importDataArray,tempDataArray);
        this.hasImported = true;
        this.isUploading = true;
        this.uploadProgress = 0;
        this.importDataArray = [];
        this.sliceUploadService(tempDataArray, 0);
    }

    /**
     * 数据切片上传
     *
     * @memberof AppDataUploadView
     */
    public sliceUploadService(dataArray: Array<any>, cnt: number) {
        if(cnt > dataArray.length) {
            this.isUploading = false;
            this.uploadProgress = 100;
            return;
        }
        let sliceArray: Array<any> = [];
        if(dataArray) {
            sliceArray = dataArray.slice(cnt, cnt+this.sliceUploadCnt);
        }
        try{
            this.entityService.getService(this.viewparams.serviceName).then((service:any) =>{
            service.ImportData(this.viewdata,{name:this.importId,importData:sliceArray}).then((res:any) =>{
                const result:any = res.data;
                if(result && result.rst !== 0){
                    this.promptInfo = (this.$t('components.appDataUploadView.importfailed') as string);
                    this.isUploading = false;
                    return;
                }
                this.importSuccessData = result.data;
                this.promptInfo = (this.$t('components.appDataUploadView.completed') as string);
                this.uploadProgress = Number((cnt / dataArray.length * 100).toFixed(2));
                this.sliceUploadService(dataArray, cnt + this.sliceUploadCnt);
            }).catch((error:any) =>{
                this.isUploading = false;
                this.promptInfo = (this.$t('components.appDataUploadView.importfailed') as string);
                console.error(error);
            })
            }).catch((error:any) =>{
                this.isUploading = false;
                this.promptInfo = (this.$t('components.appDataUploadView.importfailed') as string);
                console.error(error);
            })
        }catch(error){
            this.isUploading = false;
            this.promptInfo = (this.$t('components.appDataUploadView.importfailed') as string);
            console.error(error);
        };
    }
    /**
     * 导出excel
     *
     * @memberof AppDataUploadView
     */
    public async importExcel (filename:string,_data:any){
        const tHeader: Array<any> = [];
        this.importDataModel.forEach((item: any) => {
            tHeader.push(item.headername);
        });
        //const data = await this.formatExcelData(filterVal, _data);
        const data = _data?_data:[];
        this.$export.exportExcel().then((excel:any)=>{
            excel.export_json_to_excel({
                header: tHeader, //表头 必填
                data:data, //具体数据 必填
                filename: filename, //非必填
                autoWidth: true, //非必填
                bookType: "xlsx" //非必填
            });
        }); 
    };

    /**
     * 确认
     *
     * @memberof AppDataUploadView
     */
    public handleOK(){
        this.$emit('close',this.importSuccessData);
    }

    /**
     * 导入Excel
     *
     * @memberof AppDataUploadView
     */
    public importFile($event:any) {
        let obj = $event.target || $event.srcElement;
       if (!obj.files) {
           return;
       }
       let f = obj.files[0];
       let reader = new FileReader();
       reader.onload = (e:any) => {
           let data = e.target.result;
           this.workBookData = XLSX.read(data, {type: 'binary',cellDates: true});
           let xlsxData = XLSX.utils.sheet_to_json(this.workBookData.Sheets[this.workBookData.SheetNames[0]]);
           let list1 = this.getFirstRow(this.workBookData);
           xlsxData = this.AddXlsxData(xlsxData, list1);
           this.importDataArray = this.$util.deepCopy(xlsxData);
           (this.$refs.inputUpLoad as any).value = '';
       };
       reader.readAsBinaryString(f);
   }

    /**
     * 获取excel第一行的内容
     *
     * @memberof AppDataUploadView
     */
   public getFirstRow(wb:any) {
       //// 读取的excel单元格内容
       let wbData = wb.Sheets[wb.SheetNames[0]];
       // 匹配excel第一行的内容
       let re = /^[A-Z]1$/; 
       let temparr = [];
       // excel第一行内容赋值给数组
       for (let key in wbData) {
           if (wbData.hasOwnProperty(key)) {
               if (re.test(key)) {
                   temparr.push(wbData[key].h);
               }
           }
       }
       return temparr;
   }

    /**
     * 增加对应字段空白内容
     *
     * @memberof AppDataUploadView
     */
   public AddXlsxData(xlsxData:any, list1:any) {
       // 空白字段替换值
       let addData = null;
       for (let i = 0; i < xlsxData.length; i++) {
           // 要被JSON的数组
           for (let j = 0; j < list1.length; j++) {
               // excel第一行内容
               if (!xlsxData[i][list1[j]]) {
                   xlsxData[i][list1[j]] = addData;
               }
           }
       }
       return xlsxData;
   }

    /**
     * 获取图表所需代码表
     * 
     * @memberof AppDataUploadView
     */
    public async getChartAllCodeList(){
        let codeListMap:Map<string,any> = new Map();
        if(Object.values(this.importDataModel).length >0){
            await Object.values(this.importDataModel).forEach(async (singleDataModel:any) =>{
                if(singleDataModel.codelist){
                    let tempCodeListMap:Map<any,any> = new Map();
                    let res:any = await this.getCodeList(singleDataModel.codelist);
                    if(res && res.length >0){
                        res.forEach((codeListItem:any) =>{
                            tempCodeListMap.set(codeListItem.value,codeListItem.text);
                        })
                    }
                    codeListMap.set(singleDataModel.codelist.tag,tempCodeListMap);
                }
            })
        }
        return codeListMap;
    }

    /**
     * 获取代码表
     * 
     * @returns {Promise<any>} 
     * @memberof AppDataUploadView
     */
    public getCodeList(codeListObject:any):Promise<any>{
        return new Promise((resolve:any,reject:any) =>{
            if(codeListObject.tag && Object.is(codeListObject.type,"STATIC")){
                const codelist = this.$store.getters.getCodeList(codeListObject.tag);
                if (codelist) {
                    resolve([...JSON.parse(JSON.stringify(codelist.items))]);
                } else {
                    console.log(`----${codeListObject.tag}----${(this.$t('app.commonWords.codeNotExist') as string)}`);
                }
            }else if(codeListObject.tag && Object.is(codeListObject.type,"DYNAMIC")){
                this.codeListService.getItems(codeListObject.tag).then((res:any) => {
                    resolve(res);
                }).catch((error:any) => {
                    console.log(`----${codeListObject.tag}----${(this.$t('app.commonWords.codeNotExist') as string)}`);
                });
            }
        })
    }

    /**
     * 转化数据
     * 
     * @memberof AppDataUploadView
     */
    public transformData(data:Array<any>,result:Array<any>){
        data.forEach((item:any) =>{
            let curObject:any = {};
            Object.keys(item).forEach((ele:any) => {
                // todo XLSX读取时间为国际时间(东8区)+8H转为标准时间
                if (item[ele] instanceof Date){
                    const tempDate:Date = item[ele];
                    item[ele] = moment(tempDate).add(8, 'h').format("YYYY-MM-DD HH:mm:ss");
                }
                if(this.allFieldMap.get(ele).codelist){
                    let codelistTag:string = this.allFieldMap.get(ele).codelist.tag;
                     let codelistIsNumber:boolean = this.allFieldMap.get(ele).codelist.isnumber;
                    let curCodeList:any = this.transCodeList(codelistTag,codelistIsNumber,true);
                   Object.defineProperty(curObject, this.allFieldMap.get(ele).name, {
                        value: curCodeList.get(item[ele]),
                        writable : true,
                        enumerable : true,
                        configurable : true
                    }); 
                }else{
                    Object.defineProperty(curObject, this.allFieldMap.get(ele).name, {
                        value: item[ele],
                        writable : true,
                        enumerable : true,
                        configurable : true
                    }); 
                }
            });
            result.push(curObject);
        })
    }

    /**
     * 翻译代码表
     * 
     * @memberof AppDataUploadView
     */
    public transCodeList(codeListTag:string,codelistIsNumber:boolean,isTransform:boolean){
        let curCodeList:any = this.allCodeList.get(codeListTag);
        if(isTransform){
            let tempCodelist:Map<string,string> = new Map();
            curCodeList.forEach((item:string,key:string) =>{
                let value:any = codelistIsNumber?Number(key):key;
                tempCodelist.set(item,value);
            })
            curCodeList = tempCodelist;
        }
        return curCodeList;
    }

}
</script>

<style lang='less'>
@import './app-data-upload.less';
</style>