'use strict';
/**
*
*
* @author Zhong
* @date 2019/5/15
* @version
*/
//操作接口为eventListen
const importView = (() => {
let importXML = null;
let xmlObj = null; //导入xml转化后的对象
let tbcObj = null; //待确认对象
//显示、隐藏提示上传文件窗口相关提示信息
function showUploadAlert(success, msg) {
if (!success) {
$('#uploadAlert').removeClass('alert-success');
$('#uploadAlert').addClass('alert-danger');
} else {
$('#uploadAlert').removeClass('alert-danger');
$('#uploadAlert').addClass('alert-success');
}
$('#uploadAlert').text(msg);
$('#uploadAlert').show();
}
/*
* 获取单位工程数据(将所有单项工程里的单位工程放到一起,含有单项工程的一些信息)
* @param {Object} xmlObj @return {Array}
* */
function getTenderDatas(xmlObj) {
if (!xmlObj || !xmlObj.engs) {
return [];
}
let rst = [];
for (let eng of xmlObj.engs) {
if (Array.isArray(eng.tenders)) {
for (let tender of eng.tenders) {
tender.temp = {}; //暂时存放的信息(不是从导入文件中获取的,记录当前工程已阅、选择的费用标准、计算程序)
tender.engName = eng.name;
}
rst.push(...eng.tenders);
}
}
return rst;
}
//确认界面提示信息隐藏
function hideTBCInfo() {
$('#tbc-engName-info').hide();
$('#tbc-tenderName-info').hide();
$('#tbc-engineering-info').hide();
$('#tbc-calcProgram-info').hide();
}
//待确认界面相关
class TBC {
constructor(xmlObj, fileKind, valuation, taxType) {
this.datas = getTenderDatas(xmlObj);
this.fileKind = fileKind; //文件类型
this.valuationType = 'bill'; //计价方式 暂时默认为清单计价
this.valuation = valuation; //计价规则数据
this.taxType = taxType; //计税方法
this.engineeringList = valuation ? valuation.engineering_list : []; //工程专业库数据
this.curIdx = 0; //当前单位工程数据索引
this.init();
}
//初始化
init() {
this.next(this.curIdx);
$('#importInterface .modal-content:eq(1) p:eq(0)').text(`该文件共有${this.datas.length}个单位工程待导入`); //信息统计信息
}
checkConfirmed() {
//检查数据是否都确认过了
let allConfirmed = this.datas.every(data => data.temp.confirmed);
if (allConfirmed) {
$('#import-confirm').prop('disabled', false);
}
}
//检测当前待确认工程是否有效,有效才可确认
checkValid() {
let engName = $('#tbc-engName').val();
if (!engName) {
return $('#tbc-engName-info').show();
} else {
$('#tbc-engName-info').hide();
}
let tenderName = $('#tbc-tenderName').val();
if (!tenderName) {
return $('#tbc-tenderName-info').show();
} else {
$('#tbc-tenderName-info').hide();
}
let engineering = $('#tbc-engineering').val();
if (!engineering) {
return $('#tbc-engineering-info').show();
} else {
$('#tbc-engineering-info').hide();
}
let feeStandard = $('#tbc-feeStandard').val();
if (!feeStandard) {
return $('#tbc-feeStandard-info').show();
} else {
$('#tbc-feeStandard-info').hide();
}
let calcProgram = $('#tbc-calcProgram').val();
if (!calcProgram) {
return $('#tbc-calcProgram-info').show();
} else {
$('#tbc-calcProgram-info').hide();
}
return null;
}
//下一工程
next(idx = null) {
this.curIdx = idx !== null ? idx : this.curIdx + 1;
if (this.curIdx && this.checkValid()) {
this.curIdx--;
return;
}
let curData = this.datas[this.curIdx];
//显示这个工程的相关信息
$('#tbc-engName').val(curData.engName || '');
$('#tbc-tenderName').val(curData.name || '');
$('#tbc-engineering').val(curData.engineering || '');
curData.temp.confirmed = true; //增加确认信息(已读)
if (this.curIdx === this.datas.length - 1) { //到最后一个数据了,无法点击下一工程
$('#tbc-next').prop('disabled', true);
} else {
$('#tbc-next').prop('disabled', false);
}
if (this.curIdx !== 0) { //不为第一个数据,可以点击上一工程
$('#tbc-prev').prop('disabled', false);
} else {
$('#tbc-prev').prop('disabled', true);
}
//更新x/x信息
$('#tbc-info').text(`${this.curIdx + 1}/${this.datas.length} 已确认`);
//更新选项信息
this.initFeeOpts(curData);
this.checkConfirmed();
}
//上一工程
prev(idx = null) {
this.curIdx = idx !== null ? idx : this.curIdx - 1;
let curData = this.datas[this.curIdx];
$('#tbc-engName').val(curData.engName || '');
$('#tbc-tenderName').val(curData.name || '');
$('#tbc-engineering').val(curData.engineering || '');
if (this.curIdx === 0) { //到第一个数据了,无法点击上一工程
$('#tbc-prev').prop('disabled', true);
} else {
$('#tbc-prev').prop('disabled', false);
}
if (this.curIdx !== this.datas.length - 1) { //不为最后一个数据了,可以点击下一工程
$('#tbc-next').prop('disabled', false);
} else {
$('#tbc-next').prop('disabled', true);
}
//更新x/x信息
$('#tbc-info').text(`${this.curIdx + 1}/${this.datas.length} 已确认`);
//更新选项信息
this.initFeeOpts(curData);
this.checkConfirmed();
}
/*
* 初始化工程的费用选项等相关信息(专业工程、费用标准、计算程序等)
* 根据导入文件提取的专业工程等数据确定,需要我们软件有对应的工程专业数据,否则下拉选择为空
* @param {Object}tenderData(当前确认单位工程数据) {Array}engineeringList(当前计价规则下的工程专业数据)
* @return {void}
* */
initFeeOpts(tenderData) {
$('#tbc-engineering').empty(); //清空工程专业选项
$('#tbc-feeStandard').empty(); //清空费用标准选项
$('#tbc-calcProgram').empty(); //清空计算程序选项
let engineerings = [];
if (tenderData.temp.engineering) {
engineerings = this.engineeringList.filter(data => data.lib.name === tenderData.temp.engineering);
} else {
engineerings = this.engineeringList.filter(data => data.lib.name === tenderData.engineering);
tenderData.temp.engineering = tenderData.engineering;
}
//文件里的工程专业跟软件里的对应不上,取第一个
if (!engineerings.length) {
let firstEngineering = this.engineeringList[0];
engineerings = this.engineeringList.filter(data => data.lib.name === firstEngineering.lib.name);
tenderData.temp.engineering = engineerings[0] ? engineerings[0].lib.name : tenderData.engineering;
}
if (!engineerings.length) {
return;
}
//工程专业名称去重
let engineeringNames = [...new Set(this.engineeringList.map(data => data.lib.name))];
let engineeringHtml = engineeringNames.map(name =>
``);
$('#tbc-engineering').html(engineeringHtml);
//$('#tbc-engineering').html(``);
//费用标准,若当前工程有费用标准数据(该数据本身没有费用标准数据,选择过了,就会记录),则选中该费用标准
let feeOptsHtml = engineerings.map(data =>
``).join('');
$('#tbc-feeStandard').html(feeOptsHtml);
//记录选中的费用标准
tenderData.temp.feeStandard = $('#tbc-feeStandard').val();
//根据工程专业及费用标准确定的当前选中的工程专业库
let curEngineering = engineerings.find(data => data.lib.feeName === tenderData.temp.feeStandard) || engineerings[0];
//根据计税方法过滤出来的计税组合
let taxDatas = curEngineering.lib.tax_group.filter(data => data.taxType == this.taxType);
//计算程序,若当前工程有计算程序(该数据本身没有计算程序数据,选择过了,就会记录),则选中该计算程序
let calcOptsHtml = taxDatas.map(data =>
``);
$('#tbc-calcProgram').html(calcOptsHtml);
tenderData.temp.calcProgram = $('#tbc-calcProgram').val();
}
}
/*
* 根据条件获取计税组合数据
* @param {Object}query ({engineeringName, feeName, taxType, calcProgram}) {Array}engineeringList(当前计价规则下的所有工程专业数据)
* @return {Object}
* */
function getTaxData(query, engineeringList) {
//工程专业名称 + 费用标准名称 确定一个工程专业数据
let engineering = engineeringList.find(data => query.engineeringName === data.lib.name &&
query.feeStandard === data.lib.feeName);
if (!engineering || !Array.isArray(engineering.lib.tax_group)) {
return null;
}
return engineering.lib.tax_group.find(data => query.taxType == data.taxType &&
query.calcProgram === data.program_lib.name);
}
//获取单位工程项目属性的一些数据(新建单位工程需要,前端能获取到的一些数据,还有一些数据需要后端获取: rootProjectID, projectFeature..)
/*
* @param {Object}tbcObj(TBC实例) {Object}curData(单位工程数据)
* @return {Object}
* */
function getProperty(tbcObj, curData) {
if (!tbcObj) {
throw '存在无效数据,无法生成项目。';
}
//计税数据
let query = {
engineeringName: curData.temp.engineering || curData.engineering,
feeStandard: curData.temp.feeStandard,
taxType: tbcObj.taxType, //取导入时选择的计税方法,不读取文件中的计税方法
calcProgram: curData.temp.calcProgram
};
let taxData = getTaxData(query, tbcObj.engineeringList);
if (!taxData) {
throw '无效计税数据,无法生成项目。';
}
//当前工程专业数据
let curEngineering = tbcObj.engineeringList.find(data => query.engineeringName === data.lib.name &&
query.feeStandard === data.lib.feeName);
return {
region: '全省', //地区
valuationType: tbcObj.valuationType, //计价方式
valuation: tbcObj.valuation.id, //计价规则
valuationName: tbcObj.valuation.name,
engineering_id: curEngineering.engineering_id, //工程专业
engineeringName: curEngineering.lib.name,
taxType: parseInt(tbcObj.taxType), //计税方法
isInstall: !!curEngineering.lib.isInstall, //是安装工程?
isItemIncrease: !!curEngineering.lib.isItemIncrease, //是否子目增加费?
isAreaIncrease: !!curEngineering.lib.isAreaIncrease, //是否子目增加费?
feeStandardName: curEngineering.lib.feeName, //费用标准
engineering: curEngineering.lib.engineering, //定额取费专业
projectEngineering: curEngineering.lib.projectEngineering, //单位工程取费专业
featureLibID: curEngineering.lib.feature_lib[0] ? curEngineering.lib.feature_lib[0].id : '', //工程特征
indexName: curEngineering.lib.indexName, // 指标名称
engineerInfoLibID: curEngineering.lib.engineer_info_lib[0] ? curEngineering.lib.engineer_info_lib[0].id : '', // 工程信息指标
engineerFeatureLibID: curEngineering.lib.engineer_feature_lib[0] ? curEngineering.lib.engineer_feature_lib[0].id : '', //工程特征指标
economicLibID: curEngineering.lib.economic_lib[0] ? curEngineering.lib.economic_lib[0].id : '', // 主要经济指标
mainQuantityLibID: curEngineering.lib.main_quantity_lib[0] ? curEngineering.lib.main_quantity_lib[0].id : '', // 主要工程量指标
materialLibID: curEngineering.lib.material_lib[0] ? curEngineering.lib.material_lib[0].id : '', // 主要工料指标
calcProgram: { name: taxData.program_lib.name, id: taxData.program_lib.id }, //计算程序
colLibID: taxData.col_lib.id, //列设置
templateLibID: taxData.template_lib.id, //清单模板
unitPriceFile: { name: curData.name, id: '' }, //新建单价文件
feeFile: { name: curData.name, id: `newFeeRate@@${taxData.fee_lib.id}` } //新建费率文件
};
}
function eventListen() {
//选择文件
$('#customFile').change(async function () {
let file = $(this)[0].files[0];
$('#import-confirm').prop('disabled', true); //确认导入无效
$('.custom-file-label').text(`${file ? file.name : ''}`); //设置选择框文本
$('#uploadAlert').hide();
$('.selFile').hide();
hideTBCInfo();
if (file) {
let reg = /(xml|XML|qtf|QTF)$/;
if (file.name && !reg.test(file.name)) {
$('.selFile').hide();
showUploadAlert(false, '请选择xml或qtf文件。');
return;
}
$.bootstrapLoading.start();
$('#loadingPage').css('z-index', '2000');
//转换数据
importXML = new ImportXML();
try {
xmlObj = await importXML.extractData(file, false);
$('.selFile input:eq(0)').val(xmlObj && xmlObj.name ? xmlObj.name : '');
$('.selFile input[name="fileKind-import"]:eq(0)').prop('checked', true); //文件类型恢复成投标
$('#import-taxType').val('1'); //计税方法显示回默认的一般计税法
$('.selFile').show(); //显示建设项目、计价规则
} catch (err) {
console.log(err);
showUploadAlert(false, err);
$(this).val('');
}
$.bootstrapLoading.end();
}
});
//下一步
$('#import-next').click(function () {
let file = $('#customFile')[0].files[0];
if (!file) {
showUploadAlert(false, '请选择导入文件。');
return;
}
if (!xmlObj) {
showUploadAlert(false, '不存在有效数据。');
return;
}
let projectName = $('.selFile input:eq(0)').val();
if (!projectName) {
showUploadAlert(false, '不存在有效建设项目。');
return;
}
//文件类型
let fileKind = $('.selFile input[name="fileKind-import"]:checked').val();
if (!fileKind) {
showUploadAlert(false, '不存在有效文件类型。');
}
//计价规则
let valuation = $('#import-valuation').val();
if (!valuation) {
showUploadAlert(false, '不存在有效计价规则。');
return;
}
//计税方法
let taxType = $('#import-taxType').val();
if (!taxType) {
showUploadAlert(false, '不存在有效计税方法。');
return;
}
if (!xmlObj.engs.length) {
showUploadAlert(false, '不存在单项工程数据。');
return;
}
if (!getTenderDatas(xmlObj).length) {
showUploadAlert(false, '不存在单位工程数据。');
return;
}
$('#importInterface .modal-content:eq(0)').hide(); //隐藏第一步内容
$('#importInterface .modal-content:eq(1)').show(); //显示第二步内容
//console.log(getTenderDatas(xmlObj));
//console.log(xmlObj);
let selValuation = billValuation.find(data => data.id === valuation);
tbcObj = new TBC(xmlObj, fileKind, selValuation, taxType);
});
//上一步
$('#import-prev').click(function () {
$('#importInterface .modal-content:eq(0)').show(); //显示第一步内容
$('#importInterface .modal-content:eq(1)').hide(); //隐藏第二步内容
hideTBCInfo();
$('#import-confirm').prop('disabled', true); //确认导入无效
//清空确认字段
if (tbcObj) {
for (let data of tbcObj.datas) {
delete data.temp.confirmed;
}
}
});
//变换专业工程
$('#tbc-engineering').change(function () {
let curData = tbcObj ? tbcObj.datas[tbcObj.curIdx] : null;
if (!curData) {
return;
}
curData.temp.engineering = $(this).val();
tbcObj.initFeeOpts(curData);
});
//变换费用标准
$('#tbc-feeStandard').change(function () {
let curData = tbcObj ? tbcObj.datas[tbcObj.curIdx] : null;
if (!curData) {
return;
}
curData.temp.feeStandard = $(this).val();
tbcObj.initFeeOpts(curData);
});
//变换计算程序
$('#tbc-calcProgram').change(function () {
let curData = tbcObj ? tbcObj.datas[tbcObj.curIdx] : null;
if (!curData) {
return;
}
curData.temp.calcProgram = $(this).val();
tbcObj.initFeeOpts(curData);
});
//待确认-下一工程
$('#tbc-next').click(function () {
tbcObj.next();
});
//待确认-上一工程
$('#tbc-prev').click(function () {
tbcObj.prev();
hideTBCInfo();
});
//确认导入
$('#import-confirm').click(async function () {
if (STATE.importing) {
return;
}
STATE.importing = true;
if (tbcObj && tbcObj.checkValid()) {
return;
}
let pr = new SCComponent.InitProgressBar();
try {
//建设项目设置选择的文件类型和选择的计税方法
xmlObj.property.fileKind = tbcObj.fileKind;
xmlObj.property.taxType = tbcObj.taxType;
//确定使用的计税组合
tbcObj.datas.map(data => {
data.property = getProperty(tbcObj, data);
//默认定额库
let curEngineering = tbcObj.engineeringList.find(enData => data.temp.engineering === enData.lib.name &&
data.temp.feeStandard === enData.lib.feeName);
let defaultLib = curEngineering.lib.ration_lib.find(data => data.isDefault) || curEngineering.lib.ration_lib[0];
data.defaultRationLib = parseInt(defaultLib.id);
//此费用定额下可用的定额库id,人材机库id
data.rationLibIDs = curEngineering.lib.ration_lib.map(data => parseInt(data.id));
data.gljLibIDs = curEngineering.lib.glj_lib.map(data => parseInt(data.id));
});
//确定生成建设项目的父、前、后节点ID
let { parentProjectID, preProjectID, nextProjectID } = projTreeObj.getRelProjectID(projTreeObj.tree.selected);
xmlObj.ParentID = parentProjectID;
xmlObj.preID = preProjectID;
xmlObj.NextSiblingID = nextProjectID;
//确定建设项目的名称(不允许重复)
let sameDepthProjs = getProjs(projTreeObj.tree.selected);
if (sameDepthProjs.find(node => node.data.name === xmlObj.name)) {
xmlObj.name += `(${moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')})`;
}
$('#importInterface').modal('hide');
pr.start('导入文件', '正在生成文件,请稍候……');
let importData = await importXML.transformData(xmlObj);
let blob = new Blob([JSON.stringify(importData)], { type: 'text/plain;charset=utf-8' });
// 转换成File实例
const key = `${uuid.v1()}.json`;
const file = new File([blob], key);
// 上传文件
console.time();
await projTreeObj.getUploadToken();
await UPLOAD_CDN.uploadSync(file, key, projTreeObj.uptoken);
// 下载并处理文件
const rstData = await ajaxPost('/pm/import/importInterface', { key });
console.timeEnd();
if (Array.isArray(rstData)) {
doAfterImport(rstData);
}
} catch (err) {
console.log(err);
alert(err);
} finally {
projTreeObj.uptoken = null;
setTimeout(function () {
STATE.importing = false;
}, 500);
pr.end();
}
});
// 导入窗口激活
$('#importInterface').on('show.bs.modal', function () {
// 恢复计价规则下拉
setValuationSels($('#import-valuation'), billValuation);
});
//导入窗口消失后
$('#importInterface').on('hidden.bs.modal', function () {
importXML = null;
xmlObj = null; //重置数据
tbcObj = null;
$('#importInterface .modal-content:eq(0)').show(); //显示第一步内容
$('#importInterface .modal-content:eq(1)').hide(); //隐藏第二步内容
$('#customFile').val(''); //清除选择
$('.custom-file-label').text(''); //设置选择框文本
$('#uploadAlert').hide(); //隐藏提示
$('.selFile').hide(); //隐藏建设项目及计价规则
$('#import-confirm').prop('disabled', true); //确认导入无效
$('.selFile input[name="fileKind-import"]:eq(0)').prop('checked', true); //文件类型恢复成投标
$('#import-taxType').val('1'); //显示回一般计税
hideTBCInfo();
});
}
//projectDatas在后端已经按照顺序排过了: project eng1 tender1-1 tender1-2 eng2 tender2-1 tender2-2
function doAfterImport(projectDatas) {
//插入节点
let lastNode;
for (let data of projectDatas) {
data.feeStandardName = data.property && data.property.feeStandardName || ''; //工程专业列显示用
let parent = projTreeObj.tree.items.find(node => node.data.ID === data.ParentID),
next = projTreeObj.tree.items.find(node => node.data.ID === data.NextSiblingID);
lastNode = projTreeObj.insert(data, parent, next);
}
if (lastNode) {
projTreeObj.workBook.getSheet(0).showRow(lastNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
}
}
return { eventListen };
})();